diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/core/driver.c | 15 | ||||
-rw-r--r-- | drivers/usb/core/generic.c | 29 |
2 files changed, 42 insertions, 2 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 697898327b44..9d1502a9571d 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -818,13 +818,24 @@ static int usb_device_match(struct device *dev, struct device_driver *drv) { /* devices and interfaces are handled separately */ if (is_usb_device(dev)) { + struct usb_device *udev; + struct usb_device_driver *udrv; /* interface drivers never match devices */ if (!is_usb_device_driver(drv)) return 0; - /* TODO: Add real matching code */ - return 1; + udev = to_usb_device(dev); + udrv = to_usb_device_driver(drv); + + if (udrv->id_table && + usb_device_match_id(udev, udrv->id_table) != NULL) { + return 1; + } + + if (udrv->match) + return udrv->match(udev); + return 0; } else if (is_usb_interface(dev)) { struct usb_interface *intf; diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c index 28ece4d77749..84da85c13825 100644 --- a/drivers/usb/core/generic.c +++ b/drivers/usb/core/generic.c @@ -195,6 +195,34 @@ int usb_choose_configuration(struct usb_device *udev) } EXPORT_SYMBOL_GPL(usb_choose_configuration); +static int __check_usb_generic(struct device_driver *drv, void *data) +{ + struct usb_device *udev = data; + struct usb_device_driver *udrv; + + if (!is_usb_device_driver(drv)) + return 0; + udrv = to_usb_device_driver(drv); + if (udrv == &usb_generic_driver) + return 0; + if (!udrv->id_table) + return 0; + + return usb_device_match_id(udev, udrv->id_table) != NULL; +} + +static bool usb_generic_driver_match(struct usb_device *udev) +{ + /* + * If any other driver wants the device, leave the device to this other + * driver. + */ + if (bus_for_each_drv(&usb_bus_type, NULL, udev, __check_usb_generic)) + return false; + + return true; +} + int usb_generic_driver_probe(struct usb_device *udev) { int err, c; @@ -285,6 +313,7 @@ int usb_generic_driver_resume(struct usb_device *udev, pm_message_t msg) struct usb_device_driver usb_generic_driver = { .name = "usb", + .match = usb_generic_driver_match, .probe = usb_generic_driver_probe, .disconnect = usb_generic_driver_disconnect, #ifdef CONFIG_PM |