aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/driver.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2005-11-16 16:41:28 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2006-01-04 16:48:32 -0500
commit733260ff9c45bd4db60f45d17e8560a4a68dff4d (patch)
treee7f09a9a9e2d7a9f22288c9777f7b03906a89e20 /drivers/usb/core/driver.c
parentddae41be6145f5f9cb4e6df35661a09121b90672 (diff)
[PATCH] USB: add dynamic id functionality to USB core
Echo the usb vendor and product id to the "new_id" file in the driver's sysfs directory, and then that driver will be able to bind to a device with those ids if it is present. Example: echo 0557 2008 > /sys/bus/usb/drivers/foo_driver/new_id adds the hex values 0557 and 2008 to the device id table for the foo_driver. Note, usb-serial drivers do not currently work with this capability yet. usb-storage also might have some oddities. Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/core/driver.c')
-rw-r--r--drivers/usb/core/driver.c218
1 files changed, 168 insertions, 50 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 921a21be651d..1c0611045379 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -27,6 +27,15 @@
27#include "hcd.h" 27#include "hcd.h"
28#include "usb.h" 28#include "usb.h"
29 29
30static int usb_match_one_id(struct usb_interface *interface,
31 const struct usb_device_id *id);
32
33struct usb_dynid {
34 struct list_head node;
35 struct usb_device_id id;
36};
37
38
30static int generic_probe(struct device *dev) 39static int generic_probe(struct device *dev)
31{ 40{
32 return 0; 41 return 0;
@@ -58,6 +67,96 @@ struct device_driver usb_generic_driver = {
58 * usb device or a usb interface. */ 67 * usb device or a usb interface. */
59int usb_generic_driver_data; 68int usb_generic_driver_data;
60 69
70#ifdef CONFIG_HOTPLUG
71
72/*
73 * Adds a new dynamic USBdevice ID to this driver,
74 * and cause the driver to probe for all devices again.
75 */
76static ssize_t store_new_id(struct device_driver *driver,
77 const char *buf, size_t count)
78{
79 struct usb_driver *usb_drv = to_usb_driver(driver);
80 struct usb_dynid *dynid;
81 u32 idVendor = 0;
82 u32 idProduct = 0;
83 int fields = 0;
84
85 fields = sscanf(buf, "%x %x", &idVendor, &idProduct);
86 if (fields < 2)
87 return -EINVAL;
88
89 dynid = kzalloc(sizeof(*dynid), GFP_KERNEL);
90 if (!dynid)
91 return -ENOMEM;
92
93 INIT_LIST_HEAD(&dynid->node);
94 dynid->id.idVendor = idVendor;
95 dynid->id.idProduct = idProduct;
96 dynid->id.match_flags = USB_DEVICE_ID_MATCH_DEVICE;
97
98 spin_lock(&usb_drv->dynids.lock);
99 list_add_tail(&usb_drv->dynids.list, &dynid->node);
100 spin_unlock(&usb_drv->dynids.lock);
101
102 if (get_driver(driver)) {
103 driver_attach(driver);
104 put_driver(driver);
105 }
106
107 return count;
108}
109static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
110
111static int usb_create_newid_file(struct usb_driver *usb_drv)
112{
113 int error = 0;
114
115 if (usb_drv->probe != NULL)
116 error = sysfs_create_file(&usb_drv->driver.kobj,
117 &driver_attr_new_id.attr);
118 return error;
119}
120
121static void usb_free_dynids(struct usb_driver *usb_drv)
122{
123 struct usb_dynid *dynid, *n;
124
125 spin_lock(&usb_drv->dynids.lock);
126 list_for_each_entry_safe(dynid, n, &usb_drv->dynids.list, node) {
127 list_del(&dynid->node);
128 kfree(dynid);
129 }
130 spin_unlock(&usb_drv->dynids.lock);
131}
132#else
133static inline int usb_create_newid_file(struct usb_driver *usb_drv)
134{
135 return 0;
136}
137
138static inline void usb_free_dynids(struct usb_driver *usb_drv)
139{
140}
141#endif
142
143static const struct usb_device_id *usb_match_dynamic_id(struct usb_interface *intf,
144 struct usb_driver *drv)
145{
146 struct usb_dynid *dynid;
147
148 spin_lock(&drv->dynids.lock);
149 list_for_each_entry(dynid, &drv->dynids.list, node) {
150 if (usb_match_one_id(intf, &dynid->id)) {
151 spin_unlock(&drv->dynids.lock);
152 return &dynid->id;
153 }
154 }
155 spin_unlock(&drv->dynids.lock);
156 return NULL;
157}
158
159
61/* called from driver core with usb_bus_type.subsys writelock */ 160/* called from driver core with usb_bus_type.subsys writelock */
62static int usb_probe_interface(struct device *dev) 161static int usb_probe_interface(struct device *dev)
63{ 162{
@@ -75,6 +174,8 @@ static int usb_probe_interface(struct device *dev)
75 return -EHOSTUNREACH; 174 return -EHOSTUNREACH;
76 175
77 id = usb_match_id(intf, driver->id_table); 176 id = usb_match_id(intf, driver->id_table);
177 if (!id)
178 id = usb_match_dynamic_id(intf, driver);
78 if (id) { 179 if (id) {
79 dev_dbg(dev, "%s - got id\n", __FUNCTION__); 180 dev_dbg(dev, "%s - got id\n", __FUNCTION__);
80 181
@@ -120,6 +221,64 @@ static int usb_unbind_interface(struct device *dev)
120 return 0; 221 return 0;
121} 222}
122 223
224/* returns 0 if no match, 1 if match */
225static int usb_match_one_id(struct usb_interface *interface,
226 const struct usb_device_id *id)
227{
228 struct usb_host_interface *intf;
229 struct usb_device *dev;
230
231 /* proc_connectinfo in devio.c may call us with id == NULL. */
232 if (id == NULL)
233 return 0;
234
235 intf = interface->cur_altsetting;
236 dev = interface_to_usbdev(interface);
237
238 if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
239 id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
240 return 0;
241
242 if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
243 id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
244 return 0;
245
246 /* No need to test id->bcdDevice_lo != 0, since 0 is never
247 greater than any unsigned number. */
248 if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
249 (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
250 return 0;
251
252 if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
253 (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
254 return 0;
255
256 if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
257 (id->bDeviceClass != dev->descriptor.bDeviceClass))
258 return 0;
259
260 if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
261 (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass))
262 return 0;
263
264 if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
265 (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
266 return 0;
267
268 if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
269 (id->bInterfaceClass != intf->desc.bInterfaceClass))
270 return 0;
271
272 if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) &&
273 (id->bInterfaceSubClass != intf->desc.bInterfaceSubClass))
274 return 0;
275
276 if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) &&
277 (id->bInterfaceProtocol != intf->desc.bInterfaceProtocol))
278 return 0;
279
280 return 1;
281}
123/** 282/**
124 * usb_match_id - find first usb_device_id matching device or interface 283 * usb_match_id - find first usb_device_id matching device or interface
125 * @interface: the interface of interest 284 * @interface: the interface of interest
@@ -184,16 +343,10 @@ static int usb_unbind_interface(struct device *dev)
184const struct usb_device_id *usb_match_id(struct usb_interface *interface, 343const struct usb_device_id *usb_match_id(struct usb_interface *interface,
185 const struct usb_device_id *id) 344 const struct usb_device_id *id)
186{ 345{
187 struct usb_host_interface *intf;
188 struct usb_device *dev;
189
190 /* proc_connectinfo in devio.c may call us with id == NULL. */ 346 /* proc_connectinfo in devio.c may call us with id == NULL. */
191 if (id == NULL) 347 if (id == NULL)
192 return NULL; 348 return NULL;
193 349
194 intf = interface->cur_altsetting;
195 dev = interface_to_usbdev(interface);
196
197 /* It is important to check that id->driver_info is nonzero, 350 /* It is important to check that id->driver_info is nonzero,
198 since an entry that is all zeroes except for a nonzero 351 since an entry that is all zeroes except for a nonzero
199 id->driver_info is the way to create an entry that 352 id->driver_info is the way to create an entry that
@@ -201,50 +354,8 @@ const struct usb_device_id *usb_match_id(struct usb_interface *interface,
201 device and interface. */ 354 device and interface. */
202 for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass || 355 for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass ||
203 id->driver_info; id++) { 356 id->driver_info; id++) {
204 357 if (usb_match_one_id(interface, id))
205 if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && 358 return id;
206 id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
207 continue;
208
209 if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
210 id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
211 continue;
212
213 /* No need to test id->bcdDevice_lo != 0, since 0 is never
214 greater than any unsigned number. */
215 if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
216 (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
217 continue;
218
219 if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
220 (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
221 continue;
222
223 if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
224 (id->bDeviceClass != dev->descriptor.bDeviceClass))
225 continue;
226
227 if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
228 (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass))
229 continue;
230
231 if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
232 (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
233 continue;
234
235 if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
236 (id->bInterfaceClass != intf->desc.bInterfaceClass))
237 continue;
238
239 if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) &&
240 (id->bInterfaceSubClass != intf->desc.bInterfaceSubClass))
241 continue;
242
243 if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) &&
244 (id->bInterfaceProtocol != intf->desc.bInterfaceProtocol))
245 continue;
246
247 return id;
248 } 359 }
249 360
250 return NULL; 361 return NULL;
@@ -268,6 +379,9 @@ int usb_device_match(struct device *dev, struct device_driver *drv)
268 if (id) 379 if (id)
269 return 1; 380 return 1;
270 381
382 id = usb_match_dynamic_id(intf, usb_drv);
383 if (id)
384 return 1;
271 return 0; 385 return 0;
272} 386}
273 387
@@ -296,6 +410,8 @@ int usb_register(struct usb_driver *new_driver)
296 new_driver->driver.probe = usb_probe_interface; 410 new_driver->driver.probe = usb_probe_interface;
297 new_driver->driver.remove = usb_unbind_interface; 411 new_driver->driver.remove = usb_unbind_interface;
298 new_driver->driver.owner = new_driver->owner; 412 new_driver->driver.owner = new_driver->owner;
413 spin_lock_init(&new_driver->dynids.lock);
414 INIT_LIST_HEAD(&new_driver->dynids.list);
299 415
300 usb_lock_all_devices(); 416 usb_lock_all_devices();
301 retval = driver_register(&new_driver->driver); 417 retval = driver_register(&new_driver->driver);
@@ -305,6 +421,7 @@ int usb_register(struct usb_driver *new_driver)
305 pr_info("%s: registered new driver %s\n", 421 pr_info("%s: registered new driver %s\n",
306 usbcore_name, new_driver->name); 422 usbcore_name, new_driver->name);
307 usbfs_update_special(); 423 usbfs_update_special();
424 usb_create_newid_file(new_driver);
308 } else { 425 } else {
309 printk(KERN_ERR "%s: error %d registering driver %s\n", 426 printk(KERN_ERR "%s: error %d registering driver %s\n",
310 usbcore_name, retval, new_driver->name); 427 usbcore_name, retval, new_driver->name);
@@ -330,6 +447,7 @@ void usb_deregister(struct usb_driver *driver)
330 pr_info("%s: deregistering driver %s\n", usbcore_name, driver->name); 447 pr_info("%s: deregistering driver %s\n", usbcore_name, driver->name);
331 448
332 usb_lock_all_devices(); 449 usb_lock_all_devices();
450 usb_free_dynids(driver);
333 driver_unregister(&driver->driver); 451 driver_unregister(&driver->driver);
334 usb_unlock_all_devices(); 452 usb_unlock_all_devices();
335 453