aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorWolfram Sang <wsa@the-dreams.de>2014-01-10 19:36:42 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-01-10 16:54:35 -0800
commit2fc82c2de604deabb86b0558be0a301bb2209a19 (patch)
tree968d174a545222b71a3e43d44ab10b21fb0c5ac4 /drivers/usb
parentc63fe8f6ca3669f1d120ff70523e2911b9966574 (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.c18
-rw-r--r--drivers/usb/serial/bus.c4
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;