diff options
-rw-r--r-- | Documentation/ABI/testing/sysfs-bus-usb | 10 | ||||
-rw-r--r-- | drivers/usb/core/driver.c | 18 | ||||
-rw-r--r-- | drivers/usb/serial/bus.c | 4 | ||||
-rw-r--r-- | include/linux/usb.h | 1 |
4 files changed, 27 insertions, 6 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb index 1430f584b266..614d451cee41 100644 --- a/Documentation/ABI/testing/sysfs-bus-usb +++ b/Documentation/ABI/testing/sysfs-bus-usb | |||
@@ -50,13 +50,19 @@ Description: | |||
50 | This may allow the driver to support more hardware than | 50 | This may allow the driver to support more hardware than |
51 | was included in the driver's static device ID support | 51 | was included in the driver's static device ID support |
52 | table at compile time. The format for the device ID is: | 52 | table at compile time. The format for the device ID is: |
53 | idVendor idProduct bInterfaceClass. | 53 | idVendor idProduct bInterfaceClass RefIdVendor RefIdProduct |
54 | The vendor ID and device ID fields are required, the | 54 | The vendor ID and device ID fields are required, the |
55 | interface class is optional. | 55 | rest is optional. The Ref* tuple can be used to tell the |
56 | driver to use the same driver_data for the new device as | ||
57 | it is used for the reference device. | ||
56 | Upon successfully adding an ID, the driver will probe | 58 | Upon successfully adding an ID, the driver will probe |
57 | for the device and attempt to bind to it. For example: | 59 | for the device and attempt to bind to it. For example: |
58 | # echo "8086 10f5" > /sys/bus/usb/drivers/foo/new_id | 60 | # echo "8086 10f5" > /sys/bus/usb/drivers/foo/new_id |
59 | 61 | ||
62 | Here add a new device (0458:7045) using driver_data from | ||
63 | an already supported device (0458:704c): | ||
64 | # echo "0458 7045 0 0458 704c" > /sys/bus/usb/drivers/foo/new_id | ||
65 | |||
60 | Reading from this file will list all dynamically added | 66 | Reading from this file will list all dynamically added |
61 | device IDs in the same format, with one entry per | 67 | device IDs in the same format, with one entry per |
62 | line. For example: | 68 | line. For example: |
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; |
diff --git a/include/linux/usb.h b/include/linux/usb.h index 512ab162832c..c716da18c668 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h | |||
@@ -965,6 +965,7 @@ struct usb_dynid { | |||
965 | }; | 965 | }; |
966 | 966 | ||
967 | extern ssize_t usb_store_new_id(struct usb_dynids *dynids, | 967 | extern ssize_t usb_store_new_id(struct usb_dynids *dynids, |
968 | const struct usb_device_id *id_table, | ||
968 | struct device_driver *driver, | 969 | struct device_driver *driver, |
969 | const char *buf, size_t count); | 970 | const char *buf, size_t count); |
970 | 971 | ||