mirror of
https://gitlab.freedesktop.org/libfprint/libfprint.git
synced 2025-11-15 07:38:12 +00:00
examples: Add back examples using the async APIs
Add the examples back by using the new async API, support verification and enroll for devices with own storage.
This commit is contained in:
committed by
Benjamin Berg
parent
7d6b0c1376
commit
b46d336d2b
@@ -2,6 +2,7 @@
|
||||
* Example fingerprint verification program, which verifies the right index
|
||||
* finger which has been previously enrolled to disk.
|
||||
* Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
|
||||
* Copyright (C) 2019 Marco Trevisan <marco.trevisan@canonical.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -19,131 +20,216 @@
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <libfprint/fprint.h>
|
||||
|
||||
#include "storage.h"
|
||||
|
||||
struct fp_dscv_dev *discover_device(struct fp_dscv_dev **discovered_devs)
|
||||
typedef struct _VerifyData {
|
||||
GMainLoop *loop;
|
||||
int ret_value;
|
||||
} VerifyData;
|
||||
|
||||
static void
|
||||
verify_data_free (VerifyData *verify_data)
|
||||
{
|
||||
struct fp_dscv_dev *ddev = discovered_devs[0];
|
||||
struct fp_driver *drv;
|
||||
if (!ddev)
|
||||
g_main_loop_unref (verify_data->loop);
|
||||
g_free (verify_data);
|
||||
}
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (VerifyData, verify_data_free)
|
||||
|
||||
FpDevice *discover_device (GPtrArray *devices)
|
||||
{
|
||||
FpDevice *dev;
|
||||
if (!devices->len)
|
||||
return NULL;
|
||||
|
||||
drv = fp_dscv_dev_get_driver(ddev);
|
||||
printf("Found device claimed by %s driver\n", fp_driver_get_full_name(drv));
|
||||
return ddev;
|
||||
|
||||
dev = g_ptr_array_index (devices, 0);
|
||||
printf("Found device claimed by %s driver\n", fp_device_get_driver (dev));
|
||||
return dev;
|
||||
}
|
||||
|
||||
int verify(struct fp_dev *dev, struct fp_print_data *data)
|
||||
static void
|
||||
on_device_closed (FpDevice *dev, GAsyncResult *res, void *user_data) {
|
||||
VerifyData *verify_data = user_data;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
fp_device_close_finish (dev, res, &error);
|
||||
|
||||
if (error)
|
||||
g_warning ("Failed closing device %s\n", error->message);
|
||||
|
||||
g_main_loop_quit (verify_data->loop);
|
||||
}
|
||||
|
||||
static void start_verification (FpDevice *dev, VerifyData *verify_data);
|
||||
|
||||
static void
|
||||
on_verify_completed (FpDevice *dev, GAsyncResult *res, void *user_data)
|
||||
{
|
||||
int r;
|
||||
VerifyData *verify_data = user_data;
|
||||
g_autoptr(FpPrint) print = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
char buffer[20];
|
||||
gboolean match;
|
||||
|
||||
do {
|
||||
struct fp_img *img = NULL;
|
||||
if (!fp_device_verify_finish (dev, res, &match, &print, &error)) {
|
||||
g_warning ("Failed to verify print: %s", error->message);
|
||||
g_main_loop_quit (verify_data->loop);
|
||||
return;
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
printf("\nScan your finger now.\n");
|
||||
r = fp_verify_finger_img(dev, data, &img);
|
||||
if (img) {
|
||||
fp_img_save_to_file(img, "verify.pgm");
|
||||
printf("Wrote scanned image to verify.pgm\n");
|
||||
fp_img_free(img);
|
||||
if (match) {
|
||||
g_print ("MATCH!\n");
|
||||
if (fp_device_supports_capture (dev) &&
|
||||
print_image_save (print, "verify.pgm")) {
|
||||
g_print("Print image saved as verify.pgm");
|
||||
}
|
||||
if (r < 0) {
|
||||
printf("verification failed with error %d :(\n", r);
|
||||
return r;
|
||||
|
||||
verify_data->ret_value = EXIT_SUCCESS;
|
||||
} else {
|
||||
g_print ("NO MATCH!\n");
|
||||
verify_data->ret_value = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
g_print ("Verify again? [Y/n]? ");
|
||||
if (fgets (buffer, sizeof (buffer), stdin) &&
|
||||
(buffer[0] == 'Y' || buffer[0] == 'y')) {
|
||||
start_verification (dev, verify_data);
|
||||
return;
|
||||
}
|
||||
|
||||
fp_device_close (dev, NULL, (GAsyncReadyCallback) on_device_closed,
|
||||
verify_data);
|
||||
}
|
||||
|
||||
static void
|
||||
on_list_completed (FpDevice *dev, GAsyncResult *res, gpointer user_data)
|
||||
{
|
||||
VerifyData *verify_data = user_data;
|
||||
g_autoptr(GPtrArray) prints = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
prints = fp_device_list_prints_finish (dev, res, &error);
|
||||
|
||||
if (!error) {
|
||||
FpPrint *verify_print = NULL;
|
||||
guint i;
|
||||
|
||||
if (!prints->len)
|
||||
g_warning ("No prints saved on device");
|
||||
|
||||
for (i = 0; i < prints->len; ++i) {
|
||||
FpPrint *print = prints->pdata[i];
|
||||
|
||||
if (fp_print_get_finger (print) == FP_FINGER_RIGHT_INDEX &&
|
||||
g_strcmp0 (fp_print_get_username (print), g_get_user_name ()) == 0) {
|
||||
if (!verify_print ||
|
||||
(g_date_compare (fp_print_get_enroll_date (print),
|
||||
fp_print_get_enroll_date (verify_print)) >= 0))
|
||||
verify_print = print;
|
||||
}
|
||||
}
|
||||
switch (r) {
|
||||
case FP_VERIFY_NO_MATCH:
|
||||
printf("NO MATCH!\n");
|
||||
return 0;
|
||||
case FP_VERIFY_MATCH:
|
||||
printf("MATCH!\n");
|
||||
return 0;
|
||||
case FP_VERIFY_RETRY:
|
||||
printf("Scan didn't quite work. Please try again.\n");
|
||||
break;
|
||||
case FP_VERIFY_RETRY_TOO_SHORT:
|
||||
printf("Swipe was too short, please try again.\n");
|
||||
break;
|
||||
case FP_VERIFY_RETRY_CENTER_FINGER:
|
||||
printf("Please center your finger on the sensor and try again.\n");
|
||||
break;
|
||||
case FP_VERIFY_RETRY_REMOVE_FINGER:
|
||||
printf("Please remove finger from the sensor and try again.\n");
|
||||
break;
|
||||
|
||||
if (!verify_print) {
|
||||
g_warning ("Did you remember to enroll your right index "
|
||||
"finger first?");
|
||||
g_main_loop_quit (verify_data->loop);
|
||||
return;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
g_debug ("Comparing print with %s",
|
||||
fp_print_get_description (verify_print));
|
||||
|
||||
g_print ("Print loaded. Time to verify!\n");
|
||||
fp_device_verify (dev, verify_print, NULL,
|
||||
(GAsyncReadyCallback) on_verify_completed,
|
||||
verify_data);
|
||||
} else {
|
||||
g_warning ("Loading prints failed with error %s", error->message);
|
||||
g_main_loop_quit (verify_data->loop);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
start_verification (FpDevice *dev, VerifyData *verify_data)
|
||||
{
|
||||
if (fp_device_has_storage (dev)) {
|
||||
g_print ("Creating finger template, using device storage...\n");
|
||||
fp_device_list_prints (dev, NULL,
|
||||
(GAsyncReadyCallback) on_list_completed,
|
||||
verify_data);
|
||||
} else {
|
||||
g_print ("Loading previously enrolled right index finger data...\n");
|
||||
g_autoptr(FpPrint) verify_print;
|
||||
|
||||
verify_print = print_data_load (dev, FP_FINGER_RIGHT_INDEX);
|
||||
|
||||
if (!verify_print) {
|
||||
g_warning ("Failed to load fingerprint data");
|
||||
g_warning ("Did you remember to enroll your right index "
|
||||
"finger first?");
|
||||
g_main_loop_quit (verify_data->loop);
|
||||
return;
|
||||
}
|
||||
|
||||
g_print ("Print loaded. Time to verify!\n");
|
||||
fp_device_verify (dev, verify_print, NULL,
|
||||
(GAsyncReadyCallback) on_verify_completed,
|
||||
verify_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_device_opened (FpDevice *dev, GAsyncResult *res, void *user_data)
|
||||
{
|
||||
VerifyData *verify_data = user_data;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
if (!fp_device_open_finish (dev, res, &error)) {
|
||||
g_warning ("Failed to open device: %s", error->message);
|
||||
g_main_loop_quit (verify_data->loop);
|
||||
return;
|
||||
}
|
||||
|
||||
g_print ("Opened device. ");
|
||||
|
||||
start_verification (dev, verify_data);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int r = 1;
|
||||
struct fp_dscv_dev *ddev;
|
||||
struct fp_dscv_dev **discovered_devs;
|
||||
struct fp_dev *dev;
|
||||
struct fp_print_data *data;
|
||||
g_autoptr (FpContext) ctx = NULL;
|
||||
g_autoptr (VerifyData) verify_data = NULL;
|
||||
GPtrArray *devices;
|
||||
FpDevice *dev;
|
||||
|
||||
setenv ("G_MESSAGES_DEBUG", "all", 0);
|
||||
setenv ("LIBUSB_DEBUG", "3", 0);
|
||||
|
||||
r = fp_init();
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "Failed to initialize libfprint\n");
|
||||
exit(1);
|
||||
ctx = fp_context_new ();
|
||||
|
||||
devices = fp_context_get_devices (ctx);
|
||||
if (!devices) {
|
||||
g_warning("Impossible to get devices");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
discovered_devs = fp_discover_devs();
|
||||
if (!discovered_devs) {
|
||||
fprintf(stderr, "Could not discover devices\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ddev = discover_device(discovered_devs);
|
||||
if (!ddev) {
|
||||
fprintf(stderr, "No devices detected.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev = fp_dev_open(ddev);
|
||||
fp_dscv_devs_free(discovered_devs);
|
||||
dev = discover_device (devices);
|
||||
if (!dev) {
|
||||
fprintf(stderr, "Could not open device.\n");
|
||||
goto out;
|
||||
g_warning("No devices detected.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
printf("Opened device. Loading previously enrolled right index finger "
|
||||
"data...\n");
|
||||
verify_data = g_new0 (VerifyData, 1);
|
||||
verify_data->ret_value = EXIT_FAILURE;
|
||||
verify_data->loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
data = print_data_load(dev, RIGHT_INDEX);
|
||||
if (!data) {
|
||||
fprintf(stderr, "Failed to load fingerprint, error %d\n", r);
|
||||
fprintf(stderr, "Did you remember to enroll your right index finger "
|
||||
"first?\n");
|
||||
goto out_close;
|
||||
}
|
||||
fp_device_open (dev, NULL, (GAsyncReadyCallback) on_device_opened,
|
||||
verify_data);
|
||||
|
||||
printf("Print loaded. Time to verify!\n");
|
||||
do {
|
||||
char buffer[20];
|
||||
g_main_loop_run (verify_data->loop);
|
||||
|
||||
verify(dev, data);
|
||||
printf("Verify again? [Y/n]? ");
|
||||
fgets(buffer, sizeof(buffer), stdin);
|
||||
if (buffer[0] != '\n' && buffer[0] != 'y' && buffer[0] != 'Y')
|
||||
break;
|
||||
} while (1);
|
||||
|
||||
fp_print_data_free(data);
|
||||
out_close:
|
||||
fp_dev_close(dev);
|
||||
out:
|
||||
fp_exit();
|
||||
return r;
|
||||
return verify_data->ret_value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user