From fc6b0c194ce37cdf6c95a73d82dfd33fa99dce3f Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Thu, 6 Mar 2008 16:37:19 +0000 Subject: [PATCH] Add enrollment functionality --- .gitignore | 1 + TODO | 1 - examples/Makefile.am | 6 +- examples/demo.c | 6 +- examples/enroll.c | 177 +++++++++++++++++++++++++++++++++++++++++++ src/device.c | 76 ++++++++++++++++++- src/device.xml | 14 +++- src/fprintd.h | 3 +- 8 files changed, 274 insertions(+), 10 deletions(-) create mode 100644 examples/enroll.c diff --git a/.gitignore b/.gitignore index faf3f9f..980b6fa 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ config.status client-bindings.h *-dbus-glue.h demo +enroll *.o fprintd *.swp diff --git a/TODO b/TODO index 5575d6e..33872f5 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,3 @@ -Enrollment Identification Image transfer Imaging diff --git a/examples/Makefile.am b/examples/Makefile.am index 061a9cd..87ba388 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -2,12 +2,16 @@ BUILT_SOURCES = manager-dbus-glue.h device-dbus-glue.h noinst_HEADERS = $(BUILT_SOURCES) CLEANFILES = $(BUILT_SOURCES) -bin_PROGRAMS = demo +bin_PROGRAMS = demo enroll demo_SOURCES = demo.c demo_CFLAGS = $(AM_CFLAGS) $(DBUS_GLIB_CFLAGS) demo_LDADD = $(DBUS_GLIB_LIBS) +enroll_SOURCES = enroll.c +enroll_CFLAGS = $(AM_CFLAGS) $(DBUS_GLIB_CFLAGS) +enroll_LDADD = $(DBUS_GLIB_LIBS) + manager-dbus-glue.h: ../src/manager.xml dbus-binding-tool --prefix=fprint_manager --mode=glib-client $< --output=$@ diff --git a/examples/demo.c b/examples/demo.c index 8c4152f..265aa22 100644 --- a/examples/demo.c +++ b/examples/demo.c @@ -192,8 +192,8 @@ static void do_verify(DBusGProxy *dev, guint32 print_id) GError *error; gboolean verify_completed = FALSE; - dbus_g_proxy_add_signal(dev, "VerifyResult", G_TYPE_INT, NULL); - dbus_g_proxy_connect_signal(dev, "VerifyResult", G_CALLBACK(verify_result), + dbus_g_proxy_add_signal(dev, "VerifyStatus", G_TYPE_INT, NULL); + dbus_g_proxy_connect_signal(dev, "VerifyStatus", G_CALLBACK(verify_result), &verify_completed, NULL); if (!net_reactivated_Fprint_Device_verify_start(dev, print_id, &error)) @@ -202,7 +202,7 @@ static void do_verify(DBusGProxy *dev, guint32 print_id) while (!verify_completed) g_main_context_iteration(NULL, TRUE); - dbus_g_proxy_disconnect_signal(dev, "VerifyResult", G_CALLBACK(verify_result), &verify_completed); + dbus_g_proxy_disconnect_signal(dev, "VerifyStatus", G_CALLBACK(verify_result), &verify_completed); if (!net_reactivated_Fprint_Device_verify_stop(dev, &error)) g_error("VerifyStop failed: %s", error->message); diff --git a/examples/enroll.c b/examples/enroll.c new file mode 100644 index 0000000..694968e --- /dev/null +++ b/examples/enroll.c @@ -0,0 +1,177 @@ +/* + * fprintd example to enroll right index finger + * Copyright (C) 2008 Daniel Drake + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include "manager-dbus-glue.h" +#include "device-dbus-glue.h" + +static DBusGProxy *manager = NULL; +static DBusGConnection *connection = NULL; + +enum enroll_result { + ENROLL_COMPLETE = 1, + ENROLL_FAIL, + ENROLL_PASS, + ENROLL_RETRY = 100, + ENROLL_RETRY_TOO_SHORT = 101, + ENROLL_RETRY_CENTER_FINGER = 102, + ENROLL_RETRY_REMOVE_FINGER = 103, +}; + +static const char *enroll_result_str(int result) +{ + switch (result) { + case ENROLL_COMPLETE: + return "Enroll completed."; + case ENROLL_FAIL: + return "Enroll failed :("; + case ENROLL_PASS: + return "Enroll stage passed. Please scan again for next stage."; + case ENROLL_RETRY: + return "Retry scan"; + case ENROLL_RETRY_TOO_SHORT: + return "Swipe too short, please retry"; + case ENROLL_RETRY_CENTER_FINGER: + return "Finger not centered, please retry"; + case ENROLL_RETRY_REMOVE_FINGER: + return "Please remove finger and retry"; + default: + return "Unknown"; + } +} + +enum fp_finger { + LEFT_THUMB = 1, /** thumb (left hand) */ + LEFT_INDEX, /** index finger (left hand) */ + LEFT_MIDDLE, /** middle finger (left hand) */ + LEFT_RING, /** ring finger (left hand) */ + LEFT_LITTLE, /** little finger (left hand) */ + RIGHT_THUMB, /** thumb (right hand) */ + RIGHT_INDEX, /** index finger (right hand) */ + RIGHT_MIDDLE, /** middle finger (right hand) */ + RIGHT_RING, /** ring finger (right hand) */ + RIGHT_LITTLE, /** little finger (right hand) */ +}; + +static void create_manager(void) +{ + GError *error = NULL; + + connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error); + if (connection == NULL) + g_error("Failed to connect to session bus: %s", error->message); + + manager = dbus_g_proxy_new_for_name_owner(connection, + "net.reactivated.Fprint", "/net/reactivated/Fprint/Manager", + "net.reactivated.Fprint.Manager", &error); + if (manager == NULL) + g_error("Failed to create proxy: %s", error->message); +} + +static DBusGProxy *open_device(void) +{ + GError *error = NULL; + GPtrArray *devices; + gchar *path; + DBusGProxy *dev; + guint i; + + if (!net_reactivated_Fprint_Manager_get_devices(manager, &devices, &error)) + g_error("list_devices failed: %s", error->message); + + if (devices->len == 0) { + g_print("No devices found\n"); + exit(1); + } + + g_print("found %d devices\n", devices->len); + for (i = 0; i < devices->len; i++) { + path = g_ptr_array_index(devices, i); + g_print("Device at %s\n", path); + } + + path = g_ptr_array_index(devices, 0); + g_print("Using device %s\n", path); + + /* FIXME use for_name_owner?? */ + dev = dbus_g_proxy_new_for_name(connection, "net.reactivated.Fprint", + path, "net.reactivated.Fprint.Device"); + + g_ptr_array_foreach(devices, (GFunc) g_free, NULL); + g_ptr_array_free(devices, TRUE); + + if (!net_reactivated_Fprint_Device_claim(dev, &error)) + g_error("failed to claim device: %s", error->message); + return dev; +} + +static void enroll_result(GObject *object, int result, void *user_data) +{ + gboolean *enroll_completed = user_data; + g_print("Enroll result: %s (%d)\n", enroll_result_str(result), result); + if (result == ENROLL_COMPLETE || result == ENROLL_FAIL) + *enroll_completed = TRUE; +} + +static void do_enroll(DBusGProxy *dev) +{ + GError *error; + gboolean enroll_completed = FALSE; + + dbus_g_proxy_add_signal(dev, "EnrollStatus", G_TYPE_INT, NULL); + dbus_g_proxy_connect_signal(dev, "EnrollStatus", G_CALLBACK(enroll_result), + &enroll_completed, NULL); + + g_print("Enrolling right index finger.\n"); + if (!net_reactivated_Fprint_Device_enroll_start(dev, RIGHT_INDEX, &error)) + g_error("EnrollStart failed: %s", error->message); + + while (!enroll_completed) + g_main_context_iteration(NULL, TRUE); + + dbus_g_proxy_disconnect_signal(dev, "EnrollStatus", + G_CALLBACK(enroll_result), &enroll_completed); + + if (!net_reactivated_Fprint_Device_enroll_stop(dev, &error)) + g_error("VerifyStop failed: %s", error->message); +} + +static void release_device(DBusGProxy *dev) +{ + GError *error = NULL; + if (!net_reactivated_Fprint_Device_release(dev, &error)) + g_error("ReleaseDevice failed: %s", error->message); +} + +int main(int argc, char **argv) +{ + GMainLoop *loop; + DBusGProxy *dev; + + g_type_init(); + loop = g_main_loop_new(NULL, FALSE); + create_manager(); + + dev = open_device(); + do_enroll(dev); + release_device(dev); + return 0; +} + diff --git a/src/device.c b/src/device.c index 3faaf44..b44bc9a 100644 --- a/src/device.c +++ b/src/device.c @@ -38,10 +38,17 @@ static gboolean fprint_device_verify_start(FprintDevice *rdev, guint32 print_id, GError **error); static gboolean fprint_device_verify_stop(FprintDevice *rdev, DBusGMethodInvocation *context); +static gboolean fprint_device_enroll_start(FprintDevice *rdev, + guint32 finger_num, GError **error); +static gboolean fprint_device_enroll_stop(FprintDevice *rdev, + DBusGMethodInvocation *context); #include "device-dbus-glue.h" struct session_data { + /* finger being enrolled */ + int enroll_finger; + /* method invocation for async ClaimDevice() */ DBusGMethodInvocation *context_claim_device; @@ -73,7 +80,8 @@ enum fprint_device_properties { }; enum fprint_device_signals { - SIGNAL_VERIFY_RESULT, + SIGNAL_VERIFY_STATUS, + SIGNAL_ENROLL_STATUS, NUM_SIGNALS, }; @@ -121,7 +129,10 @@ static void device_class_init(FprintDeviceClass *klass) g_object_class_install_property(gobject_class, FPRINT_DEVICE_CONSTRUCT_DDEV, pspec); - signals[SIGNAL_VERIFY_RESULT] = g_signal_new("verify-result", + signals[SIGNAL_VERIFY_STATUS] = g_signal_new("verify-status", + G_TYPE_FROM_CLASS(gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, + g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); + signals[SIGNAL_ENROLL_STATUS] = g_signal_new("enroll-status", G_TYPE_FROM_CLASS(gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); } @@ -357,7 +368,7 @@ static void verify_cb(struct fp_dev *dev, int r, struct fp_img *img, struct FprintDevice *rdev = user_data; g_message("verify_cb: result %d", r); - g_signal_emit(rdev, signals[SIGNAL_VERIFY_RESULT], 0, r); + g_signal_emit(rdev, signals[SIGNAL_VERIFY_STATUS], 0, r); fp_img_free(img); } @@ -425,3 +436,62 @@ static gboolean fprint_device_verify_stop(FprintDevice *rdev, return TRUE; } +static void enroll_stage_cb(struct fp_dev *dev, int result, + struct fp_print_data *print, struct fp_img *img, void *user_data) +{ + struct FprintDevice *rdev = user_data; + FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev); + struct session_data *session = priv->session; + + g_message("enroll_stage_cb: result %d", result); + if (result == FP_ENROLL_COMPLETE) + fp_print_data_save(print, session->enroll_finger); + + g_signal_emit(rdev, signals[SIGNAL_ENROLL_STATUS], 0, result); + fp_img_free(img); + fp_print_data_free(print); +} + +static gboolean fprint_device_enroll_start(FprintDevice *rdev, + guint32 finger_num, GError **error) +{ + FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev); + struct session_data *session = priv->session; + int r; + + g_message("start enrollment device %d finger %d", priv->id, finger_num); + session->enroll_finger = finger_num; + + r = fp_async_enroll_start(priv->dev, enroll_stage_cb, rdev); + if (r < 0) { + g_set_error(error, FPRINT_ERROR, FPRINT_ERROR_ENROLL_START, + "Enroll start failed with error %d", r); + return FALSE; + } + + return TRUE; +} + +static void enroll_stop_cb(struct fp_dev *dev, void *user_data) +{ + dbus_g_method_return((DBusGMethodInvocation *) user_data); +} + +static gboolean fprint_device_enroll_stop(FprintDevice *rdev, + DBusGMethodInvocation *context) +{ + FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev); + int r; + + r = fp_async_enroll_stop(priv->dev, enroll_stop_cb, context); + if (r < 0) { + GError *error; + g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_ENROLL_STOP, + "Enroll stop failed with error %d", r); + dbus_g_method_return_error(context, error); + return FALSE; + } + + return TRUE; +} + diff --git a/src/device.xml b/src/device.xml index 2a684b4..0c86987 100644 --- a/src/device.xml +++ b/src/device.xml @@ -34,7 +34,19 @@ - + + + + + + + + + + + + + diff --git a/src/fprintd.h b/src/fprintd.h index e632a3d..6d484ca 100644 --- a/src/fprintd.h +++ b/src/fprintd.h @@ -31,7 +31,6 @@ GQuark fprint_error_quark(void); /* Errors */ #define FPRINT_ERROR fprint_error_quark() typedef enum { - FPRINT_ERROR_NO_SUCH_DEVICE, FPRINT_ERROR_DISCOVER_PRINTS, FPRINT_ERROR_PRINT_NOT_FOUND, FPRINT_ERROR_PRINT_LOAD, @@ -39,6 +38,8 @@ typedef enum { FPRINT_ERROR_CLAIM_DEVICE, FPRINT_ERROR_VERIFY_START, FPRINT_ERROR_VERIFY_STOP, + FPRINT_ERROR_ENROLL_START, + FPRINT_ERROR_ENROLL_STOP, FPRINT_ERROR_FAILED, } FprintError;