diff --git a/examples/Makefile.am b/examples/Makefile.am index fa58c783..708a378d 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -1,6 +1,12 @@ INCLUDES = -I$(top_srcdir) -noinst_PROGRAMS = verify_live +noinst_PROGRAMS = verify_live enroll verify verify_live_SOURCES = verify_live.c verify_live_LDADD = ../libfprint/libfprint.la -lfprint +enroll_SOURCES = enroll.c +enroll_LDADD = ../libfprint/libfprint.la -lfprint + +verify_SOURCES = verify.c +verify_LDADD = ../libfprint/libfprint.la -lfprint + diff --git a/examples/enroll.c b/examples/enroll.c new file mode 100644 index 00000000..3ed5c8a0 --- /dev/null +++ b/examples/enroll.c @@ -0,0 +1,147 @@ +/* + * Example fingerprint enrollment program + * Enrolls your right index finger and saves the print to disk + * Copyright (C) 2007 Daniel Drake + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include + +struct fp_dscv_dev *discover_device(struct fp_dscv_dev **discovered_devs) +{ + struct fp_dscv_dev *ddev = NULL; + int i; + + for (i = 0; ddev = discovered_devs[i]; i++) { + const struct fp_driver *drv = fp_dscv_dev_get_driver(ddev); + printf("Found device claimed by %s driver\n", + fp_driver_get_full_name(drv)); + return ddev; + } + + return ddev; +} + +struct fp_print_data *enroll(struct fp_dev *dev) { + struct fp_print_data *enrolled_print = NULL; + int r; + + printf("You will need to successfully scan your finger %d times to " + "complete the process.\n", fp_dev_get_nr_enroll_stages(dev)); + + do { + sleep(1); + printf("\nScan your finger now.\n"); + r = fp_enroll_finger(dev, &enrolled_print); + if (r < 0) { + printf("Enroll failed with error %d\n", r); + 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"); + return enrolled_print; +} + +int main(void) +{ + int r; + struct fp_dscv_dev *ddev; + struct fp_dscv_dev **discovered_devs; + struct fp_dev *dev; + struct fp_print_data *data; + + printf("This program will enroll your right index finger, " + "unconditionally overwriting any right-index print that was enrolled " + "previously. If you want to continue, press enter, otherwise hit " + "Ctrl+C\n"); + getchar(); + + r = fp_init(); + if (r < 0) { + fprintf(stderr, "Failed to initialize libfprint\n"); + exit(1); + } + + discovered_devs = fp_discover_devs(); + if (!discovered_devs) { + fprintf(stderr, "Could not discover devices\n"); + exit(1); + } + + ddev = discover_device(discovered_devs); + if (!ddev) { + fprintf(stderr, "No devices detected.\n"); + exit(1); + } + + dev = fp_dev_open(ddev); + fp_dscv_devs_free(discovered_devs); + if (!dev) { + fprintf(stderr, "Could not open device.\n"); + exit(1); + } + + printf("Opened device. It's now time to enroll your finger.\n\n"); + data = enroll(dev); + if (!data) + goto out_close; + + r = fp_print_data_save(data, RIGHT_INDEX); + if (r < 0) + fprintf(stderr, "Data save failed, code %d\n", r); + + fp_print_data_free(data); +out_close: + fp_dev_close(dev); + return r; +} + + diff --git a/examples/verify.c b/examples/verify.c new file mode 100644 index 00000000..3837c6a5 --- /dev/null +++ b/examples/verify.c @@ -0,0 +1,138 @@ +/* + * Example fingerprint verification program, which verifies the right index + * finger which has been previously enrolled to disk. + * Copyright (C) 2007 Daniel Drake + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include + +struct fp_dscv_dev *discover_device(struct fp_dscv_dev **discovered_devs) +{ + struct fp_dscv_dev *ddev = NULL; + int i; + + for (i = 0; ddev = discovered_devs[i]; i++) { + const struct fp_driver *drv = fp_dscv_dev_get_driver(ddev); + printf("Found device claimed by %s driver\n", + fp_driver_get_full_name(drv)); + return ddev; + } + + return ddev; +} + +int verify(struct fp_dev *dev, struct fp_print_data *data) +{ + int r; + + do { + sleep(1); + printf("\nScan your finger now.\n"); + r = fp_verify_finger(dev, data); + if (r < 0) { + printf("verification failed with error %d :(\n", r); + return r; + } + 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; + } + } while (1); +} + +int main(void) +{ + int r; + struct fp_dscv_dev *ddev; + struct fp_dscv_dev **discovered_devs; + struct fp_dev *dev; + struct fp_print_data *data; + + r = fp_init(); + if (r < 0) { + fprintf(stderr, "Failed to initialize libfprint\n"); + exit(1); + } + + discovered_devs = fp_discover_devs(); + if (!discovered_devs) { + fprintf(stderr, "Could not discover devices\n"); + exit(1); + } + + ddev = discover_device(discovered_devs); + if (!ddev) { + fprintf(stderr, "No devices detected.\n"); + exit(1); + } + + dev = fp_dev_open(ddev); + fp_dscv_devs_free(discovered_devs); + if (!dev) { + fprintf(stderr, "Could not open device.\n"); + exit(1); + } + + printf("Opened device. Loading previously enrolled right index finger " + "data...\n"); + + r = fp_print_data_load(dev, RIGHT_INDEX, &data); + if (r != 0) { + 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"); + do { + char buffer[20]; + + 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); + return r; +} + + diff --git a/examples/verify_live.c b/examples/verify_live.c index 825b6090..50dbe962 100644 --- a/examples/verify_live.c +++ b/examples/verify_live.c @@ -127,7 +127,6 @@ int verify(struct fp_dev *dev, struct fp_print_data *data) int main(void) { int r; - int ret = 1; struct fp_dscv_dev *ddev; struct fp_dscv_dev **discovered_devs; struct fp_dev *dev; @@ -175,7 +174,6 @@ int main(void) verify(dev, data); printf("Verify again? [Y/n]? "); fgets(buffer, sizeof(buffer), stdin); - buffer[sizeof(buffer) - 1] = 0; /* null-terminate */ if (buffer[0] != '\n' && buffer[0] != 'y' && buffer[0] != 'Y') break; } while (1); @@ -183,7 +181,7 @@ int main(void) fp_print_data_free(data); out_close: fp_dev_close(dev); - return ret; + return r; } diff --git a/libfprint/data.c b/libfprint/data.c index 4201665c..ebfde409 100644 --- a/libfprint/data.c +++ b/libfprint/data.c @@ -18,12 +18,55 @@ */ #include +#include #include +#include +#include +#include #include #include "fp_internal.h" +#define DIR_PERMS 0700 + +/* FIXME: should free this during library shutdown */ +static char *base_store = NULL; + +static void storage_setup(void) +{ + const char *homedir; + + homedir = g_getenv("HOME"); + if (!homedir) + homedir = g_get_home_dir(); + if (!homedir) + return; + + base_store = g_build_filename(homedir, ".fprint/prints", NULL); + g_mkdir_with_parents(base_store, DIR_PERMS); + /* FIXME handle failure */ +} + +static const char *finger_code_to_str(enum fp_finger finger) +{ + const char *names[] = { + [LEFT_THUMB] = "lthu", + [LEFT_INDEX] = "lind", + [LEFT_MIDDLE] = "lmid", + [LEFT_RING] = "lrin", + [LEFT_LITTLE] = "llit", + [RIGHT_THUMB] = "rthu", + [RIGHT_INDEX] = "rind", + [RIGHT_MIDDLE] = "rmid", + [RIGHT_RING] = "rrin", + [RIGHT_LITTLE] = "rlit", + }; + if (finger < LEFT_THUMB || finger > RIGHT_LITTLE) + return NULL; + return names[finger]; +} + struct fp_print_data *fpi_print_data_new(struct fp_dev *dev, size_t length) { struct fp_print_data *data = g_malloc(sizeof(*data) + length); @@ -33,6 +76,82 @@ struct fp_print_data *fpi_print_data_new(struct fp_dev *dev, size_t length) return data; } +API_EXPORTED int fp_print_data_save(struct fp_print_data *data, + enum fp_finger finger) +{ + GError *err = NULL; + char *path; + char *dirpath; + const char *fingerstr = finger_code_to_str(finger); + int r; + + if (!fingerstr) + return -EINVAL; + + if (!base_store) + storage_setup(); + + fp_dbg("save %s print from %s", fingerstr, data->driver_name); + dirpath = g_build_filename(base_store, data->driver_name, NULL); + r = g_mkdir_with_parents(dirpath, DIR_PERMS); + if (r < 0) { + fp_err("couldn't create storage directory"); + g_free(dirpath); + return r; + } + + path = g_build_filename(dirpath, fingerstr, NULL); + fp_dbg("saving to %s", path); + g_file_set_contents(path, data->buffer, data->length, &err); + g_free(dirpath); + g_free(path); + if (err) { + r = err->code; + fp_err("%s save failed: %s", fingerstr, err->message); + g_error_free(err); + return r; + } + + return 0; +} + +API_EXPORTED int fp_print_data_load(struct fp_dev *dev, + enum fp_finger finger, struct fp_print_data **data) +{ + const char *fingerstr = finger_code_to_str(finger); + gchar *path; + gsize length; + gchar *contents; + GError *err = NULL; + struct fp_print_data *fdata; + + if (!fingerstr) + return -EINVAL; + + if (!base_store) + storage_setup(); + + path = g_build_filename(base_store, dev->drv->name, fingerstr, NULL); + fp_dbg("from %s", path); + g_file_get_contents(path, &contents, &length, &err); + g_free(path); + if (err) { + int r = err->code; + fp_err("%s load failed: %s", fingerstr, err->message); + g_error_free(err); + if (r == G_FILE_ERROR_NOENT) + return -ENOENT; + else + return r; + } + + fdata = fpi_print_data_new(dev, length); + memcpy(fdata->buffer, contents, length); + g_free(contents); + *data = fdata; + return 0; +} + API_EXPORTED void fp_print_data_free(struct fp_print_data *data) { g_free(data); diff --git a/libfprint/fprint.h b/libfprint/fprint.h index fce42838..8f7984fd 100644 --- a/libfprint/fprint.h +++ b/libfprint/fprint.h @@ -26,6 +26,20 @@ struct fp_dev; struct fp_driver; struct fp_print_data; +/* misc/general stuff */ +enum fp_finger { + LEFT_THUMB = 1, + LEFT_INDEX, + LEFT_MIDDLE, + LEFT_RING, + LEFT_LITTLE, + RIGHT_THUMB, + RIGHT_INDEX, + RIGHT_MIDDLE, + RIGHT_RING, + RIGHT_LITTLE, +}; + /* Device discovery */ struct fp_dscv_dev **fp_discover_devs(void); void fp_dscv_devs_free(struct fp_dscv_dev **devs); @@ -67,6 +81,9 @@ enum fp_verify_result { int fp_verify_finger(struct fp_dev *dev, struct fp_print_data *enrolled_print); /* Data handling */ +int fp_print_data_load(struct fp_dev *dev, enum fp_finger finger, + struct fp_print_data **data); +int fp_print_data_save(struct fp_print_data *data, enum fp_finger finger); void fp_print_data_free(struct fp_print_data *data); /* Library */