diff --git a/examples/verify.c b/examples/verify.c index 1a424fd..5f66860 100644 --- a/examples/verify.c +++ b/examples/verify.c @@ -60,6 +60,13 @@ struct fp_print_data *enroll(struct fp_dev *dev) { 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; } } while (status != FP_ENROLL_COMPLETE); @@ -103,6 +110,7 @@ int main(void) 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"); diff --git a/libfprint/core.c b/libfprint/core.c index 19a78b8..b6d90f0 100644 --- a/libfprint/core.c +++ b/libfprint/core.c @@ -178,6 +178,7 @@ API_EXPORTED struct fp_dev *fp_dev_open(struct fp_dscv_dev *ddev) dev = g_malloc0(sizeof(*dev)); dev->drv = drv; dev->udev = udevh; + dev->__enroll_stage = -1; if (drv->init) { r = drv->init(dev); @@ -226,13 +227,58 @@ API_EXPORTED enum fp_enroll_status fp_enroll_finger(struct fp_dev *dev, struct fp_print_data **print_data) { const struct fp_driver *drv = dev->drv; + enum fp_enroll_status ret; + int stage = dev->__enroll_stage; + gboolean initial = FALSE; + if (!dev->nr_enroll_stages || !drv->enroll) { fp_err("driver %s has 0 enroll stages or no enroll func", dev->drv->name); return FP_ENROLL_FAIL; } - return drv->enroll(dev, print_data); + if (stage == -1) { + initial = TRUE; + dev->__enroll_stage = ++stage; + } + + if (stage >= dev->nr_enroll_stages) { + fp_err("exceeding number of enroll stages for device claimed by " + "driver %s (%d stages)", dev->drv->name, dev->nr_enroll_stages); + return FP_ENROLL_FAIL; + } + fp_dbg("%s will handle enroll stage %d/%d%s", drv->name, stage, + dev->nr_enroll_stages - 1, initial ? " (initial)" : ""); + + ret = drv->enroll(dev, initial, stage, print_data); + switch (ret) { + case FP_ENROLL_PASS: + fp_dbg("enroll stage passed"); + dev->__enroll_stage = stage + 1; + break; + case FP_ENROLL_COMPLETE: + fp_dbg("enroll complete"); + dev->__enroll_stage = -1; + break; + case FP_ENROLL_RETRY: + fp_dbg("enroll should retry"); + break; + case FP_ENROLL_RETRY_TOO_SHORT: + fp_dbg("swipe was too short, enroll should retry"); + break; + case FP_ENROLL_RETRY_CENTER_FINGER: + fp_dbg("finger was not centered, enroll should retry"); + break; + case FP_ENROLL_FAIL: + fp_err("enroll failed"); + dev->__enroll_stage = -1; + break; + default: + fp_err("unrecognised return code %d", ret); + dev->__enroll_stage = -1; + return FP_ENROLL_FAIL; + } + return ret; } API_EXPORTED int fp_init(void) diff --git a/libfprint/data.c b/libfprint/data.c index d3b416c..9f940b8 100644 --- a/libfprint/data.c +++ b/libfprint/data.c @@ -24,12 +24,13 @@ #include "fp_internal.h" -struct fp_print_data *fpi_print_data_new(struct fp_driver *drv, size_t length) +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); - fp_dbg("length=%z", length); - data->driver_name = drv->name; + fp_dbg("length=%zd", length); + data->driver_name = dev->drv->name; data->length = length; + return data; } unsigned char *fpi_print_data_get_buffer(struct fp_print_data *data) diff --git a/libfprint/fp_internal.h b/libfprint/fp_internal.h index 23213b6..5073866 100644 --- a/libfprint/fp_internal.h +++ b/libfprint/fp_internal.h @@ -22,6 +22,7 @@ #include +#include #include #ifdef __DARWIN_NULL @@ -65,6 +66,9 @@ struct fp_dev { void *priv; int nr_enroll_stages; + + /* drivers should not mess with these */ + int __enroll_stage; }; struct usb_id { @@ -81,8 +85,8 @@ struct fp_driver { /* Device operations */ int (*init)(struct fp_dev *dev); void (*exit)(struct fp_dev *dev); - enum fp_enroll_status (*enroll)(struct fp_dev *dev, - struct fp_print_data **print_data); + enum fp_enroll_status (*enroll)(struct fp_dev *dev, gboolean initial, + int stage, struct fp_print_data **print_data); }; extern const struct fp_driver upekts_driver; @@ -98,7 +102,7 @@ struct fp_print_data { unsigned char buffer[0]; }; -struct fp_print_data *fpi_print_data_new(struct fp_driver *drv, size_t length); +struct fp_print_data *fpi_print_data_new(struct fp_dev *dev, size_t length); unsigned char *fpi_print_data_get_buffer(struct fp_print_data *data); int fpi_print_data_compatible(struct fp_dev *dev, struct fp_print_data *data); diff --git a/libfprint/fprint.h b/libfprint/fprint.h index 6a2ac9a..721cf02 100644 --- a/libfprint/fprint.h +++ b/libfprint/fprint.h @@ -43,10 +43,12 @@ const char *fp_driver_get_full_name(const struct fp_driver *drv); /* Enrolment */ enum fp_enroll_status { - FP_ENROLL_COMPLETE, + FP_ENROLL_COMPLETE = 1, FP_ENROLL_FAIL, FP_ENROLL_PASS, FP_ENROLL_RETRY, + FP_ENROLL_RETRY_TOO_SHORT, + FP_ENROLL_RETRY_CENTER_FINGER, }; enum fp_enroll_status fp_enroll_finger(struct fp_dev *dev,