diff options
author | Wolfram Sang | 2014-01-10 19:36:42 +0100 |
---|---|---|
committer | Greg Kroah-Hartman | 2014-01-11 01:54:35 +0100 |
commit | 2fc82c2de604deabb86b0558be0a301bb2209a19 (patch) | |
tree | 968d174a545222b71a3e43d44ab10b21fb0c5ac4 /drivers/usb/core | |
parent | usb: core: add sanity checks when using bInterfaceClass with new_id (diff) | |
download | kernel-qcow2-linux-2fc82c2de604deabb86b0558be0a301bb2209a19.tar.gz kernel-qcow2-linux-2fc82c2de604deabb86b0558be0a301bb2209a19.tar.xz kernel-qcow2-linux-2fc82c2de604deabb86b0558be0a301bb2209a19.zip |
usb: core: allow a reference device for new_id
Often, usb drivers need some driver_info to get a device to work. To
have access to driver_info when using new_id, allow to pass a reference
vendor:product tuple from which new_id will inherit driver_info.
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/core')
-rw-r--r-- | drivers/usb/core/driver.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 574f5a04c92d..9b29e5c94be7 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -37,6 +37,7 @@ * and cause the driver to probe for all devices again. */ ssize_t usb_store_new_id(struct usb_dynids *dynids, + const struct usb_device_id *id_table, struct device_driver *driver, const char *buf, size_t count) { @@ -44,11 +45,12 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids, u32 idVendor = 0; u32 idProduct = 0; unsigned int bInterfaceClass = 0; + u32 refVendor, refProduct; int fields = 0; int retval = 0; - fields = sscanf(buf, "%x %x %x", &idVendor, &idProduct, - &bInterfaceClass); + fields = sscanf(buf, "%x %x %x %x %x", &idVendor, &idProduct, + &bInterfaceClass, &refVendor, &refProduct); if (fields < 2) return -EINVAL; @@ -68,6 +70,16 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids, dynid->id.match_flags |= USB_DEVICE_ID_MATCH_INT_CLASS; } + if (fields > 4) { + const struct usb_device_id *id = id_table; + + for (; id->match_flags; id++) + if (id->idVendor == refVendor && id->idProduct == refProduct) { + dynid->id.driver_info = id->driver_info; + break; + } + } + spin_lock(&dynids->lock); list_add_tail(&dynid->node, &dynids->list); spin_unlock(&dynids->lock); @@ -109,7 +121,7 @@ static ssize_t new_id_store(struct device_driver *driver, { struct usb_driver *usb_drv = to_usb_driver(driver); - return usb_store_new_id(&usb_drv->dynids, driver, buf, count); + return usb_store_new_id(&usb_drv->dynids, usb_drv->id_table, driver, buf, count); } static DRIVER_ATTR_RW(new_id); |