aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/driver.c
diff options
context:
space:
mode:
authorBastien Nocera <hadess@hadess.net>2019-10-16 11:39:31 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-02-12 11:01:55 -0800
commit88b7381a939de0fa1f1b1629c56b03dca7077309 (patch)
tree74bb40156ebfcf5b169cb703c6b79821d26913ca /drivers/usb/core/driver.c
parentUSB: Implement usb_device_match_id() (diff)
downloadlinux-dev-88b7381a939de0fa1f1b1629c56b03dca7077309.tar.xz
linux-dev-88b7381a939de0fa1f1b1629c56b03dca7077309.zip
USB: Select better matching USB drivers when available
Now that USB device drivers can reuse code from the generic USB device driver, we need to make sure that they get selected rather than the generic driver. Add an id_table and match vfunc to the usb_device_driver struct, which will get used to select a better matching driver at ->probe time. This is a similar mechanism to that used in the HID drivers, with the generic driver being selected unless there's a better matching one found in the registered drivers (see hid_generic_match() in drivers/hid/hid-generic.c). Signed-off-by: Bastien Nocera <hadess@hadess.net> Acked-by: Alan Stern <stern@rowland.harvard.edu> Link: https://lore.kernel.org/r/20191016093933.693-5-hadess@hadess.net Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/core/driver.c')
-rw-r--r--drivers/usb/core/driver.c15
1 files changed, 13 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;