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:
Marco Trevisan (Treviño) 2019-11-19 20:18:13 +01:00 committed by Benjamin Berg
parent 7d6b0c1376
commit b46d336d2b
6 changed files with 434 additions and 245 deletions

View file

@ -6,6 +6,10 @@
int main (int argc, char **argv) int main (int argc, char **argv)
{ {
fp_init (); FpContext *ctx;
ctx = fp_context_new ();
g_object_unref (ctx);
return 0; return 0;
} }

View file

@ -2,6 +2,7 @@
* Example fingerprint enrollment program * Example fingerprint enrollment program
* Enrolls your right index finger and saves the print to disk * Enrolls your right index finger and saves the print to disk
* Copyright (C) 2007 Daniel Drake <dsd@gentoo.org> * 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -19,91 +20,128 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <libfprint/fprint.h> #include <libfprint/fprint.h>
#include "storage.h" #include "storage.h"
struct fp_dscv_dev *discover_device(struct fp_dscv_dev **discovered_devs) typedef struct _EnrollData {
GMainLoop *loop;
int ret_value;
} EnrollData;
static void
enroll_data_free (EnrollData *enroll_data)
{ {
struct fp_dscv_dev *ddev = discovered_devs[0]; g_main_loop_unref (enroll_data->loop);
struct fp_driver *drv; g_free (enroll_data);
if (!ddev) }
G_DEFINE_AUTOPTR_CLEANUP_FUNC (EnrollData, enroll_data_free)
FpDevice *discover_device (GPtrArray *devices)
{
FpDevice *dev;
if (!devices->len)
return NULL; return NULL;
drv = fp_dscv_dev_get_driver(ddev); dev = g_ptr_array_index (devices, 0);
printf("Found device claimed by %s driver\n", fp_driver_get_full_name(drv)); printf("Found device claimed by %s driver\n", fp_device_get_driver (dev));
return ddev; return dev;
} }
struct fp_print_data *enroll(struct fp_dev *dev) { static void
struct fp_print_data *enrolled_print = NULL; on_device_closed (FpDevice *dev, GAsyncResult *res, void *user_data) {
int r; EnrollData *enroll_data = user_data;
g_autoptr(GError) error = NULL;
printf("You will need to successfully scan your finger %d times to " fp_device_close_finish (dev, res, &error);
"complete the process.\n", fp_dev_get_nr_enroll_stages(dev));
do { if (error)
struct fp_img *img = NULL; g_warning ("Failed closing device %s\n", error->message);
printf("\nScan your finger now.\n"); g_main_loop_quit (enroll_data->loop);
}
r = fp_enroll_finger_img(dev, &enrolled_print, &img); static void
if (img) { on_enroll_completed (FpDevice *dev, GAsyncResult *res, void *user_data) {
fp_img_save_to_file(img, "enrolled.pgm"); EnrollData *enroll_data = user_data;
printf("Wrote scanned image to enrolled.pgm\n"); g_autoptr(FpPrint) print = NULL;
fp_img_free(img); g_autoptr(GError) error = NULL;
print = fp_device_enroll_finish (dev, res, &error);
if (!error) {
enroll_data->ret_value = EXIT_SUCCESS;
if (!fp_device_has_storage (dev)) {
g_debug("Device has not storage, saving locally");
int r = print_data_save(print, FP_FINGER_RIGHT_INDEX);
if (r < 0) {
g_warning("Data save failed, code %d", r);
enroll_data->ret_value = EXIT_FAILURE;
}
} }
if (r < 0) { } else {
printf("Enroll failed with error %d\n", r); g_warning("Enroll failed with error %s\n", error->message);
return NULL;
}
switch (r) {
case FP_ENROLL_COMPLETE:
printf("Enroll complete!\n");
break;
case FP_ENROLL_FAIL:
printf("Enroll failed, something wen't wrong :(\n");
return NULL;
case FP_ENROLL_PASS:
printf("Enroll stage passed. Yay!\n");
break;
case FP_ENROLL_RETRY:
printf("Didn't quite catch that. Please try again.\n");
break;
case FP_ENROLL_RETRY_TOO_SHORT:
printf("Your swipe was too short, please try again.\n");
break;
case FP_ENROLL_RETRY_CENTER_FINGER:
printf("Didn't catch that, please center your finger on the "
"sensor and try again.\n");
break;
case FP_ENROLL_RETRY_REMOVE_FINGER:
printf("Scan failed, please remove your finger and then try "
"again.\n");
break;
}
} while (r != FP_ENROLL_COMPLETE);
if (!enrolled_print) {
fprintf(stderr, "Enroll complete but no print?\n");
return NULL;
} }
printf("Enrollment completed!\n\n"); fp_device_close (dev, NULL, (GAsyncReadyCallback) on_device_closed,
return enrolled_print; enroll_data);
}
static void
on_enroll_progress (FpDevice *device,
gint completed_stages,
FpPrint *print,
gpointer user_data,
GError *error)
{
if (error) {
g_warning ("Enroll stage %d of %d failed with error %s",
completed_stages,
fp_device_get_nr_enroll_stages (device),
error->message);
return;
}
if (fp_device_supports_capture (device) &&
print_image_save (print, "enrolled.pgm")) {
printf ("Wrote scanned image to enrolled.pgm\n");
}
printf ("Enroll stage %d of %d passed. Yay!\n", completed_stages,
fp_device_get_nr_enroll_stages (device));
}
static void
on_device_opened (FpDevice *dev, GAsyncResult *res, void *user_data)
{
EnrollData *enroll_data = user_data;
FpPrint *print_template;
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 (enroll_data->loop);
return;
}
printf ("Opened device. It's now time to enroll your finger.\n\n");
printf ("You will need to successfully scan your finger %d times to "
"complete the process.\n\n", fp_device_get_nr_enroll_stages (dev));
printf ("Scan your finger now.\n");
print_template = print_create_template (dev, FP_FINGER_RIGHT_INDEX);
fp_device_enroll (dev, print_template, NULL, on_enroll_progress, NULL,
NULL, (GAsyncReadyCallback) on_enroll_completed,
enroll_data);
} }
int main(void) int main(void)
{ {
int r = 1; g_autoptr (FpContext) ctx = NULL;
struct fp_dscv_dev *ddev; g_autoptr (EnrollData) enroll_data = NULL;
struct fp_dscv_dev **discovered_devs; GPtrArray *devices;
struct fp_dev *dev; FpDevice *dev;
struct fp_print_data *data;
printf("This program will enroll your right index finger, " printf("This program will enroll your right index finger, "
"unconditionally overwriting any right-index print that was enrolled " "unconditionally overwriting any right-index print that was enrolled "
@ -112,48 +150,29 @@ int main(void)
getchar(); getchar();
setenv ("G_MESSAGES_DEBUG", "all", 0); setenv ("G_MESSAGES_DEBUG", "all", 0);
setenv ("LIBUSB_DEBUG", "3", 0);
r = fp_init(); ctx = fp_context_new ();
if (r < 0) {
fprintf(stderr, "Failed to initialize libfprint\n"); devices = fp_context_get_devices (ctx);
exit(1); if (!devices) {
g_warning("Impossible to get devices");
return EXIT_FAILURE;
} }
discovered_devs = fp_discover_devs(); dev = discover_device (devices);
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);
if (!dev) { if (!dev) {
fprintf(stderr, "Could not open device.\n"); g_warning("No devices detected.");
goto out; return EXIT_FAILURE;
} }
printf("Opened device. It's now time to enroll your finger.\n\n"); enroll_data = g_new0 (EnrollData, 1);
data = enroll(dev); enroll_data->ret_value = EXIT_FAILURE;
if (!data) enroll_data->loop = g_main_loop_new (NULL, FALSE);
goto out_close;
r = print_data_save(data, RIGHT_INDEX); fp_device_open (dev, NULL, (GAsyncReadyCallback) on_device_opened,
if (r < 0) enroll_data);
fprintf(stderr, "Data save failed, code %d\n", r);
fp_print_data_free(data); g_main_loop_run (enroll_data->loop);
out_close:
fp_dev_close(dev); return enroll_data->ret_value;
out:
fp_exit();
return r;
} }

View file

@ -1,22 +1,22 @@
examples = [ 'verify_live', 'enroll', 'verify', 'img_capture' ] examples = [ 'enroll', 'verify', 'manage-prints' ]
foreach example: examples foreach example: examples
executable(example, executable(example,
[example + '.c', 'storage.c'], [example + '.c', 'storage.c'],
dependencies: [libfprint_dep], dependencies: [libfprint_dep, glib_dep],
include_directories: [ include_directories: [
root_inc, root_inc,
], ],
c_args: common_cflags) c_args: common_cflags)
endforeach endforeach
# executable('cpp-test', executable('cpp-test',
# 'cpp-test.cpp', 'cpp-test.cpp',
# dependencies: libfprint_dep, dependencies: libfprint_dep,
# include_directories: [ include_directories: [
# root_inc, root_inc,
# ], ],
# c_args: common_cflags) c_args: common_cflags)
# if get_option('x11-examples') # if get_option('x11-examples')
# executable('img_capture_continuous', # executable('img_capture_continuous',

View file

@ -2,6 +2,7 @@
* Trivial storage driver for example programs * Trivial storage driver for example programs
* *
* Copyright (C) 2019 Benjamin Berg <bberg@redhat.com> * Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
* Copyright (C) 2019 Marco Trevisan <marco.trevisan@canonical.com>
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -18,41 +19,41 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include <glib.h> #include <libfprint/fprint.h>
#include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <libfprint/fprint.h>
#define STORAGE_FILE "test-storage.variant" #define STORAGE_FILE "test-storage.variant"
static char * static char *
get_print_data_descriptor (struct fp_print_data *data, struct fp_dev *dev, enum fp_finger finger) get_print_data_descriptor (FpPrint *print, FpDevice *dev, FpFinger finger)
{ {
gint drv_id; const char *driver;
gint devtype; const char *dev_id;
if (data) { if (print) {
drv_id = fp_print_data_get_driver_id (data); driver = fp_print_get_driver (print);
devtype = fp_print_data_get_devtype (data); dev_id = fp_print_get_device_id (print);
} else { } else {
drv_id = fp_driver_get_driver_id(fp_dev_get_driver (dev)); driver = fp_device_get_driver (dev);
devtype = fp_dev_get_devtype (dev); dev_id = fp_device_get_device_id (dev);
} }
return g_strdup_printf("%x/%08x/%x", return g_strdup_printf("%s/%s/%x",
drv_id, driver,
devtype, dev_id,
finger); finger);
} }
static GVariantDict* static GVariantDict *
load_data(void) load_data(void)
{ {
GVariantDict *res; GVariantDict *res;
GVariant *var; GVariant *var;
gchar *contents = NULL; g_autofree gchar *contents = NULL;
gssize length = 0; gssize length = 0;
if (!g_file_get_contents (STORAGE_FILE, &contents, &length, NULL)) { if (!g_file_get_contents (STORAGE_FILE, &contents, &length, NULL)) {
@ -88,49 +89,125 @@ save_data(GVariant *data)
} }
int int
print_data_save(struct fp_print_data *fp_data, enum fp_finger finger) print_data_save(FpPrint *print, FpFinger finger)
{ {
gchar *descr = get_print_data_descriptor (fp_data, NULL, finger); g_autofree gchar *descr = get_print_data_descriptor (print, NULL, finger);
GVariantDict *dict; g_autoptr (GError) error = NULL;
g_autoptr (GVariantDict) dict = NULL;
g_autofree guchar *data = NULL;
GVariant *val; GVariant *val;
guchar *data;
gsize size; gsize size;
int res; int res;
dict = load_data(); dict = load_data();
size = fp_print_data_get_data(fp_data, &data); fp_print_serialize (print, &data, &size, &error);
if (error) {
g_warning ("Error serializing data: %s", error->message);
return -1;
}
val = g_variant_new_fixed_array (G_VARIANT_TYPE("y"), data, size, 1); val = g_variant_new_fixed_array (G_VARIANT_TYPE("y"), data, size, 1);
g_variant_dict_insert_value (dict, descr, val); g_variant_dict_insert_value (dict, descr, val);
res = save_data(g_variant_dict_end(dict)); res = save_data(g_variant_dict_end(dict));
g_variant_dict_unref(dict);
return res; return res;
} }
struct fp_print_data* FpPrint *
print_data_load(struct fp_dev *dev, enum fp_finger finger) print_data_load(FpDevice *dev, FpFinger finger)
{ {
gchar *descr = get_print_data_descriptor (NULL, dev, finger); g_autofree gchar *descr = get_print_data_descriptor (NULL, dev, finger);
GVariantDict *dict; g_autoptr (GVariant) val = NULL;
guchar *stored_data; g_autoptr (GVariantDict) dict = NULL;
g_autofree guchar *stored_data = NULL;
gsize stored_len; gsize stored_len;
GVariant *val;
struct fp_print_data *res = NULL;
dict = load_data(); dict = load_data();
val = g_variant_dict_lookup_value (dict, descr, G_VARIANT_TYPE ("ay")); val = g_variant_dict_lookup_value (dict, descr, G_VARIANT_TYPE ("ay"));
if (val) { if (val) {
stored_data = (guchar*) g_variant_get_fixed_array (val, &stored_len, 1); FpPrint *print;
res = fp_print_data_from_data(stored_data, stored_len); g_autoptr (GError) error = NULL;
g_variant_unref(val); stored_data = (guchar*) g_variant_get_fixed_array (val, &stored_len, 1);
print = fp_print_deserialize (stored_data, stored_len, &error);
if (error)
g_warning ("Error deserializing data: %s", error->message);
return print;
} }
g_variant_dict_unref(dict); return NULL;
g_free(descr); }
return res; FpPrint *
print_create_template (FpDevice *dev, FpFinger finger)
{
g_autoptr(GDateTime) datetime = NULL;
FpPrint *template = NULL;
GDate *date = NULL;
gint year, month, day;
template = fp_print_new (dev);
fp_print_set_finger (template, finger);
fp_print_set_username (template, g_get_user_name ());
datetime = g_date_time_new_now_local ();
g_date_time_get_ymd (datetime, &year, &month, &day);
date = g_date_new_dmy (day, month, year);
fp_print_set_enroll_date (template, date);
g_date_free (date);
return template;
}
static gboolean
save_image_to_pgm (FpImage *img, const char *path)
{
FILE *fd = fopen (path, "w");
size_t write_size;
const guchar *data = fp_image_get_data (img, &write_size);
int r;
if (!fd) {
g_warning("could not open '%s' for writing: %d", path, errno);
return FALSE;
}
r = fprintf (fd, "P5 %d %d 255\n",
fp_image_get_width (img), fp_image_get_height (img));
if (r < 0) {
fclose(fd);
g_critical("pgm header write failed, error %d", r);
return FALSE;
}
r = fwrite (data, 1, write_size, fd);
if (r < write_size) {
fclose(fd);
g_critical("short write (%d)", r);
return FALSE;
}
fclose (fd);
g_debug ("written to '%s'", path);
return TRUE;
}
gboolean print_image_save (FpPrint *print, const char *path)
{
g_autoptr(FpImage) img = NULL;
g_return_val_if_fail (FP_IS_PRINT (print), FALSE);
g_return_val_if_fail (path != NULL, FALSE);
img = fp_print_get_image (print);
if (img)
return save_image_to_pgm (img, path);
return FALSE;
} }

View file

@ -21,7 +21,10 @@
#ifndef __STORAGE_H #ifndef __STORAGE_H
#define __STORAGE_H #define __STORAGE_H
int print_data_save(struct fp_print_data *fp_data, enum fp_finger finger);
struct fp_print_data* print_data_load(struct fp_dev *dev, enum fp_finger finger); int print_data_save(FpPrint *print, FpFinger finger);
FpPrint * print_data_load(FpDevice *dev, FpFinger finger);
FpPrint * print_create_template(FpDevice *dev, FpFinger finger);
gboolean print_image_save(FpPrint *print, const char *path);
#endif /* __STORAGE_H */ #endif /* __STORAGE_H */

View file

@ -2,6 +2,7 @@
* Example fingerprint verification program, which verifies the right index * Example fingerprint verification program, which verifies the right index
* finger which has been previously enrolled to disk. * finger which has been previously enrolled to disk.
* Copyright (C) 2007 Daniel Drake <dsd@gentoo.org> * 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -19,131 +20,216 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <libfprint/fprint.h> #include <libfprint/fprint.h>
#include "storage.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]; g_main_loop_unref (verify_data->loop);
struct fp_driver *drv; g_free (verify_data);
if (!ddev) }
G_DEFINE_AUTOPTR_CLEANUP_FUNC (VerifyData, verify_data_free)
FpDevice *discover_device (GPtrArray *devices)
{
FpDevice *dev;
if (!devices->len)
return NULL; return NULL;
drv = fp_dscv_dev_get_driver(ddev); dev = g_ptr_array_index (devices, 0);
printf("Found device claimed by %s driver\n", fp_driver_get_full_name(drv)); printf("Found device claimed by %s driver\n", fp_device_get_driver (dev));
return ddev; 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 { if (!fp_device_verify_finish (dev, res, &match, &print, &error)) {
struct fp_img *img = NULL; g_warning ("Failed to verify print: %s", error->message);
g_main_loop_quit (verify_data->loop);
return;
}
sleep(1); if (match) {
printf("\nScan your finger now.\n"); g_print ("MATCH!\n");
r = fp_verify_finger_img(dev, data, &img); if (fp_device_supports_capture (dev) &&
if (img) { print_image_save (print, "verify.pgm")) {
fp_img_save_to_file(img, "verify.pgm"); g_print("Print image saved as verify.pgm");
printf("Wrote scanned image to verify.pgm\n");
fp_img_free(img);
} }
if (r < 0) {
printf("verification failed with error %d :(\n", r); verify_data->ret_value = EXIT_SUCCESS;
return r; } 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: if (!verify_print) {
printf("NO MATCH!\n"); g_warning ("Did you remember to enroll your right index "
return 0; "finger first?");
case FP_VERIFY_MATCH: g_main_loop_quit (verify_data->loop);
printf("MATCH!\n"); return;
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;
} }
} 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 main(void)
{ {
int r = 1; g_autoptr (FpContext) ctx = NULL;
struct fp_dscv_dev *ddev; g_autoptr (VerifyData) verify_data = NULL;
struct fp_dscv_dev **discovered_devs; GPtrArray *devices;
struct fp_dev *dev; FpDevice *dev;
struct fp_print_data *data;
setenv ("G_MESSAGES_DEBUG", "all", 0); setenv ("G_MESSAGES_DEBUG", "all", 0);
setenv ("LIBUSB_DEBUG", "3", 0); setenv ("LIBUSB_DEBUG", "3", 0);
r = fp_init(); ctx = fp_context_new ();
if (r < 0) {
fprintf(stderr, "Failed to initialize libfprint\n"); devices = fp_context_get_devices (ctx);
exit(1); if (!devices) {
g_warning("Impossible to get devices");
return EXIT_FAILURE;
} }
discovered_devs = fp_discover_devs(); dev = discover_device (devices);
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);
if (!dev) { if (!dev) {
fprintf(stderr, "Could not open device.\n"); g_warning("No devices detected.");
goto out; return EXIT_FAILURE;
} }
printf("Opened device. Loading previously enrolled right index finger " verify_data = g_new0 (VerifyData, 1);
"data...\n"); verify_data->ret_value = EXIT_FAILURE;
verify_data->loop = g_main_loop_new (NULL, FALSE);
data = print_data_load(dev, RIGHT_INDEX); fp_device_open (dev, NULL, (GAsyncReadyCallback) on_device_opened,
if (!data) { verify_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;
}
printf("Print loaded. Time to verify!\n"); g_main_loop_run (verify_data->loop);
do {
char buffer[20];
verify(dev, data); return verify_data->ret_value;
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;
} }