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).
This commit is contained in:
parent
48af46a2c5
commit
df4a6f53d2
3 changed files with 55 additions and 20 deletions
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue