aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core
diff options
context:
space:
mode:
authorWolfram Sang <wsa@the-dreams.de>2014-01-10 13:36:42 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-01-10 19:54:35 -0500
commit2fc82c2de604deabb86b0558be0a301bb2209a19 (patch)
tree968d174a545222b71a3e43d44ab10b21fb0c5ac4 /drivers/usb/core
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/core')
-rw-r--r--drivers/usb/core/driver.c18
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 @@
37 * and cause the driver to probe for all devices again. 37 * and cause the driver to probe for all devices again.
38 */ 38 */
39ssize_t usb_store_new_id(struct usb_dynids *dynids, 39ssize_t usb_store_new_id(struct usb_dynids *dynids,
40 const struct usb_device_id *id_table,
40 struct device_driver *driver, 41 struct device_driver *driver,
41 const char *buf, size_t count) 42 const char *buf, size_t count)
42{ 43{
@@ -44,11 +45,12 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
44 u32 idVendor = 0; 45 u32 idVendor = 0;
45 u32 idProduct = 0; 46 u32 idProduct = 0;
46 unsigned int bInterfaceClass = 0; 47 unsigned int bInterfaceClass = 0;
48 u32 refVendor, refProduct;
47 int fields = 0; 49 int fields = 0;
48 int retval = 0; 50 int retval = 0;
49 51
50 fields = sscanf(buf, "%x %x %x", &idVendor, &idProduct, 52 fields = sscanf(buf, "%x %x %x %x %x", &idVendor, &idProduct,
51 &bInterfaceClass); 53 &bInterfaceClass, &refVendor, &refProduct);
52 if (fields < 2) 54 if (fields < 2)
53 return -EINVAL; 55 return -EINVAL;
54 56
@@ -68,6 +70,16 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
68 dynid->id.match_flags |= USB_DEVICE_ID_MATCH_INT_CLASS; 70 dynid->id.match_flags |= USB_DEVICE_ID_MATCH_INT_CLASS;
69 } 71 }
70 72
73 if (fields > 4) {
74 const struct usb_device_id *id = id_table;
75
76 for (; id->match_flags; id++)
77 if (id->idVendor == refVendor && id->idProduct == refProduct) {
78 dynid->id.driver_info = id->driver_info;
79 break;
80 }
81 }
82
71 spin_lock(&dynids->lock); 83 spin_lock(&dynids->lock);
72 list_add_tail(&dynid->node, &dynids->list); 84 list_add_tail(&dynid->node, &dynids->list);
73 spin_unlock(&dynids->lock); 85 spin_unlock(&dynids->lock);
@@ -109,7 +121,7 @@ static ssize_t new_id_store(struct device_driver *driver,
109{ 121{
110 struct usb_driver *usb_drv = to_usb_driver(driver); 122 struct usb_driver *usb_drv = to_usb_driver(driver);
111 123
112 return usb_store_new_id(&usb_drv->dynids, driver, buf, count); 124 return usb_store_new_id(&usb_drv->dynids, usb_drv->id_table, driver, buf, count);
113} 125}
114static DRIVER_ATTR_RW(new_id); 126static DRIVER_ATTR_RW(new_id);
115 127