162 lines
5.6 KiB
C
162 lines
5.6 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
#include "gxfp/session.h"
|
|
|
|
#include <errno.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
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;
|
|
}
|