From df4a6f53d2b74f43d453940cebd43d0cd802584d Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Tue, 17 Aug 2010 23:14:18 +0100 Subject: [PATCH] Rework "discover" code for drivers Check all the drivers for one that'll drive our device in question, and prefer ones that have a discover() method that runs successfully to a driver without such a method. This allow drivers to both reject devices (if 2 drivers handle the same USB IDs), or a single driver to handle variants of the same device (through the devtype out value of the discover method). --- libfprint/core.c | 63 ++++++++++++++++++++++++++++---------- libfprint/drivers/upeke2.c | 10 ++++-- libfprint/fp_internal.h | 2 +- 3 files changed, 55 insertions(+), 20 deletions(-) diff --git a/libfprint/core.c b/libfprint/core.c index af97bdf..1ce3d0b 100644 --- a/libfprint/core.c +++ b/libfprint/core.c @@ -364,7 +364,7 @@ static struct fp_img_driver * const img_drivers[] = { #ifdef ENABLE_UPEKSONLY &upeksonly_driver, #endif - + #ifdef ENABLE_AES1610 &aes1610_driver, #endif @@ -410,51 +410,80 @@ API_EXPORTED struct fp_driver **fprint_get_drivers (void) } static struct fp_driver *find_supporting_driver(libusb_device *udev, - const struct usb_id **usb_id) + const struct usb_id **usb_id, uint32_t *devtype) { int ret; GSList *elem = registered_drivers; struct libusb_device_descriptor dsc; + const struct usb_id *best_usb_id; + struct fp_driver *best_drv; + uint32_t best_devtype; + int drv_score = 0; + ret = libusb_get_device_descriptor(udev, &dsc); if (ret < 0) { fp_err("Failed to get device descriptor"); return NULL; } - + + best_drv = NULL; + best_devtype = 0; + do { struct fp_driver *drv = elem->data; + uint32_t type = 0; const struct usb_id *id; - for (id = drv->id_table; id->vendor; id++) + for (id = drv->id_table; id->vendor; id++) { if (dsc.idVendor == id->vendor && dsc.idProduct == id->product) { + if (drv->discover) { + int r = drv->discover(&dsc, &type); + if (r < 0) + fp_err("%s discover failed, code %d", drv->name, r); + if (r <= 0) + continue; + /* Has a discover function, and matched our device */ + drv_score = 100; + } else { + /* Already got a driver as good */ + if (drv_score >= 50) + continue; + drv_score = 50; + } fp_dbg("driver %s supports USB device %04x:%04x", drv->name, id->vendor, id->product); - *usb_id = id; - return drv; + best_usb_id = id; + best_drv = drv; + best_devtype = type; + + /* We found the best possible driver */ + if (drv_score == 100) + break; } + } } while ((elem = g_slist_next(elem))); - return NULL; + + fp_dbg("selected driver %s supports USB device %04x:%04x", + best_drv->name, dsc.idVendor, dsc.idProduct); + *devtype = best_devtype; + *usb_id = best_usb_id; + + return best_drv; } static struct fp_dscv_dev *discover_dev(libusb_device *udev) { const struct usb_id *usb_id; - struct fp_driver *drv = find_supporting_driver(udev, &usb_id); + struct fp_driver *drv; struct fp_dscv_dev *ddev; - uint32_t devtype = 0; + uint32_t devtype; + + drv = find_supporting_driver(udev, &usb_id, &devtype); if (!drv) return NULL; - if (drv->discover) { - int r = drv->discover(usb_id, &devtype); - if (r < 0) - fp_err("%s discover failed, code %d", drv->name, r); - if (r <= 0) - return NULL; - } - ddev = g_malloc0(sizeof(*ddev)); ddev->drv = drv; ddev->udev = udev; diff --git a/libfprint/drivers/upeke2.c b/libfprint/drivers/upeke2.c index f4a812d..5c7129a 100644 --- a/libfprint/drivers/upeke2.c +++ b/libfprint/drivers/upeke2.c @@ -844,6 +844,12 @@ static struct fpi_ssm *deinitsm_new(struct fp_dev *dev) return fpi_ssm_new(dev, deinitsm_state_handler, DEINITSM_NUM_STATES); } +static int discover(struct libusb_device_descriptor *dsc, uint32_t *devtype) +{ + /* FIXME: Detect whether dsc represents a device that we can handle */ + return 0; +} + static int dev_init(struct fp_dev *dev, unsigned long driver_data) { struct upeke2_dev *upekdev = NULL; @@ -1442,8 +1448,7 @@ static int verify_stop(struct fp_dev *dev, gboolean iterating) } static const struct usb_id id_table[] = { -/* FIXME: Disabled for now, as this clashes with the upeksonly driver */ -/* { .vendor = 0x147e, .product = 0x2016 }, */ + { .vendor = 0x147e, .product = 0x2016 }, { 0, 0, 0, }, /* terminating entry */ }; @@ -1453,6 +1458,7 @@ struct fp_driver upeke2_driver = { .full_name = "UPEK Eikon 2", .id_table = id_table, .scan_type = FP_SCAN_TYPE_SWIPE, + .discover = discover, .open = dev_init, .close = dev_exit, .enroll_start = enroll_start, diff --git a/libfprint/fp_internal.h b/libfprint/fp_internal.h index 5196ca2..4a0441d 100644 --- a/libfprint/fp_internal.h +++ b/libfprint/fp_internal.h @@ -204,7 +204,7 @@ struct fp_driver { void *priv; /* Device operations */ - int (*discover)(const struct usb_id *usb_id, uint32_t *devtype); + int (*discover)(struct libusb_device_descriptor *dsc, uint32_t *devtype); int (*open)(struct fp_dev *dev, unsigned long driver_data); void (*close)(struct fp_dev *dev); int (*enroll_start)(struct fp_dev *dev);