diff options
author | Wolfram Sang <wsa@the-dreams.de> | 2014-01-10 19:36:42 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-01-10 16:54:35 -0800 |
commit | 2fc82c2de604deabb86b0558be0a301bb2209a19 (patch) | |
tree | 968d174a545222b71a3e43d44ab10b21fb0c5ac4 /drivers/usb | |
parent | c63fe8f6ca3669f1d120ff70523e2911b9966574 (diff) |
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')
-rw-r--r-- | drivers/usb/core/driver.c | 18 | ||||
-rw-r--r-- | drivers/usb/serial/bus.c | 4 |
2 files changed, 18 insertions, 4 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 574f5a04c92..9b29e5c94be 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); diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c index 6335490d576..35a2373cde6 100644 --- a/drivers/usb/serial/bus.c +++ b/drivers/usb/serial/bus.c @@ -125,10 +125,12 @@ static ssize_t new_id_store(struct device_driver *driver, const char *buf, size_t count) { struct usb_serial_driver *usb_drv = to_usb_serial_driver(driver); - ssize_t retval = usb_store_new_id(&usb_drv->dynids, driver, buf, count); + ssize_t retval = usb_store_new_id(&usb_drv->dynids, usb_drv->id_table, + driver, buf, count); if (retval >= 0 && usb_drv->usb_driver != NULL) retval = usb_store_new_id(&usb_drv->usb_driver->dynids, + usb_drv->usb_driver->id_table, &usb_drv->usb_driver->drvwrap.driver, buf, count); return retval; |