diff options
author | Wolfram Sang <wsa@the-dreams.de> | 2014-01-10 13:36:42 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-01-10 19:54:35 -0500 |
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 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 | */ |
39 | ssize_t usb_store_new_id(struct usb_dynids *dynids, | 39 | ssize_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 | } |
114 | static DRIVER_ATTR_RW(new_id); | 126 | static DRIVER_ATTR_RW(new_id); |
115 | 127 | ||
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c index 6335490d5760..35a2373cde67 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, | |||
125 | const char *buf, size_t count) | 125 | const char *buf, size_t count) |
126 | { | 126 | { |
127 | struct usb_serial_driver *usb_drv = to_usb_serial_driver(driver); | 127 | struct usb_serial_driver *usb_drv = to_usb_serial_driver(driver); |
128 | ssize_t retval = usb_store_new_id(&usb_drv->dynids, driver, buf, count); | 128 | ssize_t retval = usb_store_new_id(&usb_drv->dynids, usb_drv->id_table, |
129 | driver, buf, count); | ||
129 | 130 | ||
130 | if (retval >= 0 && usb_drv->usb_driver != NULL) | 131 | if (retval >= 0 && usb_drv->usb_driver != NULL) |
131 | retval = usb_store_new_id(&usb_drv->usb_driver->dynids, | 132 | retval = usb_store_new_id(&usb_drv->usb_driver->dynids, |
133 | usb_drv->usb_driver->id_table, | ||
132 | &usb_drv->usb_driver->drvwrap.driver, | 134 | &usb_drv->usb_driver->drvwrap.driver, |
133 | buf, count); | 135 | buf, count); |
134 | return retval; | 136 | return retval; |