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
|
@ -410,51 +410,80 @@ API_EXPORTED struct fp_driver **fprint_get_drivers (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct fp_driver *find_supporting_driver(libusb_device *udev,
|
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;
|
int ret;
|
||||||
GSList *elem = registered_drivers;
|
GSList *elem = registered_drivers;
|
||||||
struct libusb_device_descriptor dsc;
|
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);
|
ret = libusb_get_device_descriptor(udev, &dsc);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fp_err("Failed to get device descriptor");
|
fp_err("Failed to get device descriptor");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
best_drv = NULL;
|
||||||
|
best_devtype = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
struct fp_driver *drv = elem->data;
|
struct fp_driver *drv = elem->data;
|
||||||
|
uint32_t type = 0;
|
||||||
const struct usb_id *id;
|
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 (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",
|
fp_dbg("driver %s supports USB device %04x:%04x",
|
||||||
drv->name, id->vendor, id->product);
|
drv->name, id->vendor, id->product);
|
||||||
*usb_id = id;
|
best_usb_id = id;
|
||||||
return drv;
|
best_drv = drv;
|
||||||
|
best_devtype = type;
|
||||||
|
|
||||||
|
/* We found the best possible driver */
|
||||||
|
if (drv_score == 100)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} while ((elem = g_slist_next(elem)));
|
} 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)
|
static struct fp_dscv_dev *discover_dev(libusb_device *udev)
|
||||||
{
|
{
|
||||||
const struct usb_id *usb_id;
|
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;
|
struct fp_dscv_dev *ddev;
|
||||||
uint32_t devtype = 0;
|
uint32_t devtype;
|
||||||
|
|
||||||
|
drv = find_supporting_driver(udev, &usb_id, &devtype);
|
||||||
|
|
||||||
if (!drv)
|
if (!drv)
|
||||||
return NULL;
|
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 = g_malloc0(sizeof(*ddev));
|
||||||
ddev->drv = drv;
|
ddev->drv = drv;
|
||||||
ddev->udev = udev;
|
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);
|
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)
|
static int dev_init(struct fp_dev *dev, unsigned long driver_data)
|
||||||
{
|
{
|
||||||
struct upeke2_dev *upekdev = NULL;
|
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[] = {
|
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 */
|
{ 0, 0, 0, }, /* terminating entry */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1453,6 +1458,7 @@ struct fp_driver upeke2_driver = {
|
||||||
.full_name = "UPEK Eikon 2",
|
.full_name = "UPEK Eikon 2",
|
||||||
.id_table = id_table,
|
.id_table = id_table,
|
||||||
.scan_type = FP_SCAN_TYPE_SWIPE,
|
.scan_type = FP_SCAN_TYPE_SWIPE,
|
||||||
|
.discover = discover,
|
||||||
.open = dev_init,
|
.open = dev_init,
|
||||||
.close = dev_exit,
|
.close = dev_exit,
|
||||||
.enroll_start = enroll_start,
|
.enroll_start = enroll_start,
|
||||||
|
|
|
@ -204,7 +204,7 @@ struct fp_driver {
|
||||||
void *priv;
|
void *priv;
|
||||||
|
|
||||||
/* Device operations */
|
/* 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);
|
int (*open)(struct fp_dev *dev, unsigned long driver_data);
|
||||||
void (*close)(struct fp_dev *dev);
|
void (*close)(struct fp_dev *dev);
|
||||||
int (*enroll_start)(struct fp_dev *dev);
|
int (*enroll_start)(struct fp_dev *dev);
|
||||||
|
|
Loading…
Reference in a new issue