// SPDX-License-Identifier: GPL-2.0-only #include "gxfp/session.h" #include #include #include #include #include static const char *error_string(int error) { if (error >= 0) return "non-negative API error"; return strerror(-error); } static int print_image_stats(unsigned int index, const struct gxfp_image12 *image) { size_t count; uint16_t minimum = UINT16_MAX; uint16_t maximum = 0; uint64_t sum = 0; size_t i; if (!image || !image->pixels || !image->width || !image->height) { fprintf(stderr, "invalid image returned by capture\n"); return -EINVAL; } if (image->width > SIZE_MAX / image->height) { fprintf(stderr, "image dimensions overflow\n"); return -EOVERFLOW; } count = image->width * image->height; for (i = 0; i < count; i++) { uint16_t value = image->pixels[i]; if (value < minimum) minimum = value; if (value > maximum) maximum = value; sum += value; } printf("capture_index: %u\n", index); printf("image: %zux%zu, samples=%zu\n", image->width, image->height, count); printf("CRC: stored=0x%08x calculated=0x%08x valid=yes\n", image->crc_stored, image->crc_calculated); printf("header: %02x %02x %02x %02x %02x\n", image->header[0], image->header[1], image->header[2], image->header[3], image->header[4]); printf("frame_trailer: 0x%02x\n", image->trailer); printf("pixel_min=%u pixel_max=%u pixel_mean=%.2f\n", minimum, maximum, (double)sum / count); return 0; } int main(int argc, char **argv) { const char *path = argc > 1 ? argv[1] : "/dev/gxfp"; unsigned int capture_count = 1u; struct gxfp_session *session = NULL; const char *stage = "open"; unsigned int completed = 0; unsigned int index; int active = 0; int ret; if (argc > 3) { fprintf(stderr, "usage: %s [device] [capture-count]\n", argv[0]); return EXIT_FAILURE; } if (argc > 2) { char *end = NULL; unsigned long value; errno = 0; value = strtoul(argv[2], &end, 10); if (errno == ERANGE || end == argv[2] || *end != '\0' || value == 0 || value > 100) { fprintf(stderr, "capture count must be in range 1..100\n"); return EXIT_FAILURE; } capture_count = (unsigned int)value; } ret = gxfp_session_open(&session, path); if (ret) { fprintf(stderr, "session open failed: %s (%d)\n", error_string(ret), ret); return EXIT_FAILURE; } stage = "activate"; ret = gxfp_session_activate(session, 10000); if (ret) { fprintf(stderr, "session activate failed: %s (%d)\n", error_string(ret), ret); goto out; } active = 1; printf("Session active; TLS established.\n"); for (index = 1; index <= capture_count; index++) { struct gxfp_image12 image = { 0 }; printf("\n=== Capture %u/%u ===\n", index, capture_count); stage = "arm-finger-down"; ret = gxfp_session_arm_finger_down(session); if (ret) goto capture_error; printf("FDT down armed. Put finger on sensor...\n"); stage = "wait-finger-down"; ret = gxfp_session_wait_finger_down(session, 10000); if (ret) goto capture_error; stage = "capture"; ret = gxfp_session_capture(session, &image, 20000); if (ret) goto capture_error; stage = "print-image-stats"; ret = print_image_stats(index, &image); if (ret) goto capture_error; gxfp_image12_clear(&image); stage = "arm-finger-up"; ret = gxfp_session_arm_finger_up(session); if (ret) goto capture_error; printf("Remove your finger...\n"); stage = "wait-finger-up"; ret = gxfp_session_wait_finger_up(session, 10000); if (ret) goto capture_error; completed++; continue; capture_error: gxfp_image12_clear(&image); fprintf(stderr, "capture %u failed during %s, state=%d: %s (%d)\n", index, stage, (int)gxfp_session_get_state(session), error_string(ret), ret); break; } out: printf("\ncompleted captures: %u/%u\n", completed, capture_count); if (session) { if (active) { int deactivate_ret = gxfp_session_deactivate(session); if (!ret && deactivate_ret) ret = deactivate_ret; } gxfp_session_close(session); } return ret ? EXIT_FAILURE : EXIT_SUCCESS; }