diff options
author | Valentina Manea <valentina.manea.m@gmail.com> | 2014-01-23 16:12:29 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-02-07 13:54:30 -0500 |
commit | b7945b77cd03094458f3624bc82a27e0d36e75d0 (patch) | |
tree | 55fa77ff4d051b90a69e2fca601dea3c3c7562c1 | |
parent | a6646ea683c0c73962cb67aea9be40b11b916de5 (diff) |
staging: usbip: convert usbip-host driver to usb_device_driver
This driver was previously an interface driver. Since USB/IP
exports a whole device, not just an interface, it would make
sense to be a device driver.
This patch also modifies the way userspace sees and uses a
shared device:
* the usbip_status file is no longer created for interface 0, but for
the whole device (such as
/sys/devices/pci0000:00/0000:00:01.2/usb1/1-1/usbip_status).
* per interface information, such as interface class or protocol, is
no longer sent/received; only device specific information is
transmitted.
* since the driver was moved one level below in the USB architecture,
there is no need to bind/unbind each interface, just the device as a
whole.
Signed-off-by: Valentina Manea <valentina.manea.m@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/staging/usbip/stub.h | 2 | ||||
-rw-r--r-- | drivers/staging/usbip/stub_dev.c | 150 | ||||
-rw-r--r-- | drivers/staging/usbip/stub_main.c | 6 | ||||
-rw-r--r-- | drivers/staging/usbip/stub_rx.c | 2 | ||||
-rw-r--r-- | drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c | 45 | ||||
-rw-r--r-- | drivers/staging/usbip/userspace/src/usbip_bind.c | 142 | ||||
-rw-r--r-- | drivers/staging/usbip/userspace/src/usbip_list.c | 19 | ||||
-rw-r--r-- | drivers/staging/usbip/userspace/src/usbip_unbind.c | 51 | ||||
-rw-r--r-- | drivers/staging/usbip/userspace/src/usbipd.c | 15 | ||||
-rw-r--r-- | drivers/usb/core/generic.c | 1 | ||||
-rw-r--r-- | drivers/usb/core/message.c | 1 | ||||
-rw-r--r-- | include/linux/usb.h | 4 |
12 files changed, 150 insertions, 288 deletions
diff --git a/drivers/staging/usbip/stub.h b/drivers/staging/usbip/stub.h index a73e437ec215..82e539a4fcff 100644 --- a/drivers/staging/usbip/stub.h +++ b/drivers/staging/usbip/stub.h | |||
@@ -93,7 +93,7 @@ struct bus_id_priv { | |||
93 | extern struct kmem_cache *stub_priv_cache; | 93 | extern struct kmem_cache *stub_priv_cache; |
94 | 94 | ||
95 | /* stub_dev.c */ | 95 | /* stub_dev.c */ |
96 | extern struct usb_driver stub_driver; | 96 | extern struct usb_device_driver stub_driver; |
97 | 97 | ||
98 | /* stub_main.c */ | 98 | /* stub_main.c */ |
99 | struct bus_id_priv *get_busid_priv(const char *busid); | 99 | struct bus_id_priv *get_busid_priv(const char *busid); |
diff --git a/drivers/staging/usbip/stub_dev.c b/drivers/staging/usbip/stub_dev.c index 76a1ff0e6275..b0bfd3430d47 100644 --- a/drivers/staging/usbip/stub_dev.c +++ b/drivers/staging/usbip/stub_dev.c | |||
@@ -279,21 +279,19 @@ static void stub_device_unusable(struct usbip_device *ud) | |||
279 | * | 279 | * |
280 | * Allocates and initializes a new stub_device struct. | 280 | * Allocates and initializes a new stub_device struct. |
281 | */ | 281 | */ |
282 | static struct stub_device *stub_device_alloc(struct usb_device *udev, | 282 | static struct stub_device *stub_device_alloc(struct usb_device *udev) |
283 | struct usb_interface *interface) | ||
284 | { | 283 | { |
285 | struct stub_device *sdev; | 284 | struct stub_device *sdev; |
286 | int busnum = interface_to_busnum(interface); | 285 | int busnum = udev->bus->busnum; |
287 | int devnum = interface_to_devnum(interface); | 286 | int devnum = udev->devnum; |
288 | 287 | ||
289 | dev_dbg(&interface->dev, "allocating stub device"); | 288 | dev_dbg(&udev->dev, "allocating stub device"); |
290 | 289 | ||
291 | /* yes, it's a new device */ | 290 | /* yes, it's a new device */ |
292 | sdev = kzalloc(sizeof(struct stub_device), GFP_KERNEL); | 291 | sdev = kzalloc(sizeof(struct stub_device), GFP_KERNEL); |
293 | if (!sdev) | 292 | if (!sdev) |
294 | return NULL; | 293 | return NULL; |
295 | 294 | ||
296 | sdev->interface = usb_get_intf(interface); | ||
297 | sdev->udev = usb_get_dev(udev); | 295 | sdev->udev = usb_get_dev(udev); |
298 | 296 | ||
299 | /* | 297 | /* |
@@ -322,7 +320,7 @@ static struct stub_device *stub_device_alloc(struct usb_device *udev, | |||
322 | 320 | ||
323 | usbip_start_eh(&sdev->ud); | 321 | usbip_start_eh(&sdev->ud); |
324 | 322 | ||
325 | dev_dbg(&interface->dev, "register new interface\n"); | 323 | dev_dbg(&udev->dev, "register new device\n"); |
326 | 324 | ||
327 | return sdev; | 325 | return sdev; |
328 | } | 326 | } |
@@ -332,32 +330,20 @@ static void stub_device_free(struct stub_device *sdev) | |||
332 | kfree(sdev); | 330 | kfree(sdev); |
333 | } | 331 | } |
334 | 332 | ||
335 | /* | 333 | static int stub_probe(struct usb_device *udev) |
336 | * If a usb device has multiple active interfaces, this driver is bound to all | ||
337 | * the active interfaces. However, usbip exports *a* usb device (i.e., not *an* | ||
338 | * active interface). Currently, a userland program must ensure that it | ||
339 | * looks at the usbip's sysfs entries of only the first active interface. | ||
340 | * | ||
341 | * TODO: use "struct usb_device_driver" to bind a usb device. | ||
342 | * However, it seems it is not fully supported in mainline kernel yet | ||
343 | * (2.6.19.2). | ||
344 | */ | ||
345 | static int stub_probe(struct usb_interface *interface, | ||
346 | const struct usb_device_id *id) | ||
347 | { | 334 | { |
348 | struct usb_device *udev = interface_to_usbdev(interface); | ||
349 | struct stub_device *sdev = NULL; | 335 | struct stub_device *sdev = NULL; |
350 | const char *udev_busid = dev_name(interface->dev.parent); | 336 | const char *udev_busid = dev_name(&udev->dev); |
351 | int err = 0; | 337 | int err = 0, config; |
352 | struct bus_id_priv *busid_priv; | 338 | struct bus_id_priv *busid_priv; |
353 | 339 | ||
354 | dev_dbg(&interface->dev, "Enter\n"); | 340 | dev_dbg(&udev->dev, "Enter\n"); |
355 | 341 | ||
356 | /* check we should claim or not by busid_table */ | 342 | /* check we should claim or not by busid_table */ |
357 | busid_priv = get_busid_priv(udev_busid); | 343 | busid_priv = get_busid_priv(udev_busid); |
358 | if (!busid_priv || (busid_priv->status == STUB_BUSID_REMOV) || | 344 | if (!busid_priv || (busid_priv->status == STUB_BUSID_REMOV) || |
359 | (busid_priv->status == STUB_BUSID_OTHER)) { | 345 | (busid_priv->status == STUB_BUSID_OTHER)) { |
360 | dev_info(&interface->dev, | 346 | dev_info(&udev->dev, |
361 | "%s is not in match_busid table... skip!\n", | 347 | "%s is not in match_busid table... skip!\n", |
362 | udev_busid); | 348 | udev_busid); |
363 | 349 | ||
@@ -383,60 +369,36 @@ static int stub_probe(struct usb_interface *interface, | |||
383 | return -ENODEV; | 369 | return -ENODEV; |
384 | } | 370 | } |
385 | 371 | ||
386 | if (busid_priv->status == STUB_BUSID_ALLOC) { | ||
387 | sdev = busid_priv->sdev; | ||
388 | if (!sdev) | ||
389 | return -ENODEV; | ||
390 | |||
391 | busid_priv->interf_count++; | ||
392 | dev_info(&interface->dev, | ||
393 | "usbip-host: register new interface (bus %u dev %u ifn %u)\n", | ||
394 | udev->bus->busnum, udev->devnum, | ||
395 | interface->cur_altsetting->desc.bInterfaceNumber); | ||
396 | |||
397 | /* set private data to usb_interface */ | ||
398 | usb_set_intfdata(interface, sdev); | ||
399 | |||
400 | err = stub_add_files(&interface->dev); | ||
401 | if (err) { | ||
402 | dev_err(&interface->dev, "stub_add_files for %s\n", | ||
403 | udev_busid); | ||
404 | usb_set_intfdata(interface, NULL); | ||
405 | busid_priv->interf_count--; | ||
406 | return err; | ||
407 | } | ||
408 | |||
409 | usb_get_intf(interface); | ||
410 | return 0; | ||
411 | } | ||
412 | |||
413 | /* ok, this is my device */ | 372 | /* ok, this is my device */ |
414 | sdev = stub_device_alloc(udev, interface); | 373 | sdev = stub_device_alloc(udev); |
415 | if (!sdev) | 374 | if (!sdev) |
416 | return -ENOMEM; | 375 | return -ENOMEM; |
417 | 376 | ||
418 | dev_info(&interface->dev, | 377 | dev_info(&udev->dev, |
419 | "usbip-host: register new device (bus %u dev %u ifn %u)\n", | 378 | "usbip-host: register new device (bus %u dev %u)\n", |
420 | udev->bus->busnum, udev->devnum, | 379 | udev->bus->busnum, udev->devnum); |
421 | interface->cur_altsetting->desc.bInterfaceNumber); | ||
422 | 380 | ||
423 | busid_priv->interf_count = 0; | ||
424 | busid_priv->shutdown_busid = 0; | 381 | busid_priv->shutdown_busid = 0; |
425 | 382 | ||
426 | /* set private data to usb_interface */ | 383 | config = usb_choose_configuration(udev); |
427 | usb_set_intfdata(interface, sdev); | 384 | if (config >= 0) { |
428 | busid_priv->interf_count++; | 385 | err = usb_set_configuration(udev, config); |
386 | if (err && err != -ENODEV) | ||
387 | dev_err(&udev->dev, "can't set config #%d, error %d\n", | ||
388 | config, err); | ||
389 | } | ||
390 | |||
391 | /* set private data to usb_device */ | ||
392 | dev_set_drvdata(&udev->dev, sdev); | ||
429 | busid_priv->sdev = sdev; | 393 | busid_priv->sdev = sdev; |
430 | 394 | ||
431 | err = stub_add_files(&interface->dev); | 395 | err = stub_add_files(&udev->dev); |
432 | if (err) { | 396 | if (err) { |
433 | dev_err(&interface->dev, "stub_add_files for %s\n", udev_busid); | 397 | dev_err(&udev->dev, "stub_add_files for %s\n", udev_busid); |
434 | usb_set_intfdata(interface, NULL); | 398 | dev_set_drvdata(&udev->dev, NULL); |
435 | usb_put_intf(interface); | ||
436 | usb_put_dev(udev); | 399 | usb_put_dev(udev); |
437 | kthread_stop_put(sdev->ud.eh); | 400 | kthread_stop_put(sdev->ud.eh); |
438 | 401 | ||
439 | busid_priv->interf_count = 0; | ||
440 | busid_priv->sdev = NULL; | 402 | busid_priv->sdev = NULL; |
441 | stub_device_free(sdev); | 403 | stub_device_free(sdev); |
442 | return err; | 404 | return err; |
@@ -461,13 +423,13 @@ static void shutdown_busid(struct bus_id_priv *busid_priv) | |||
461 | * called in usb_disconnect() or usb_deregister() | 423 | * called in usb_disconnect() or usb_deregister() |
462 | * but only if actconfig(active configuration) exists | 424 | * but only if actconfig(active configuration) exists |
463 | */ | 425 | */ |
464 | static void stub_disconnect(struct usb_interface *interface) | 426 | static void stub_disconnect(struct usb_device *udev) |
465 | { | 427 | { |
466 | struct stub_device *sdev; | 428 | struct stub_device *sdev; |
467 | const char *udev_busid = dev_name(interface->dev.parent); | 429 | const char *udev_busid = dev_name(&udev->dev); |
468 | struct bus_id_priv *busid_priv; | 430 | struct bus_id_priv *busid_priv; |
469 | 431 | ||
470 | dev_dbg(&interface->dev, "Enter\n"); | 432 | dev_dbg(&udev->dev, "Enter\n"); |
471 | 433 | ||
472 | busid_priv = get_busid_priv(udev_busid); | 434 | busid_priv = get_busid_priv(udev_busid); |
473 | if (!busid_priv) { | 435 | if (!busid_priv) { |
@@ -475,41 +437,29 @@ static void stub_disconnect(struct usb_interface *interface) | |||
475 | return; | 437 | return; |
476 | } | 438 | } |
477 | 439 | ||
478 | sdev = usb_get_intfdata(interface); | 440 | sdev = dev_get_drvdata(&udev->dev); |
479 | 441 | ||
480 | /* get stub_device */ | 442 | /* get stub_device */ |
481 | if (!sdev) { | 443 | if (!sdev) { |
482 | dev_err(&interface->dev, "could not get device"); | 444 | dev_err(&udev->dev, "could not get device"); |
483 | return; | 445 | return; |
484 | } | 446 | } |
485 | 447 | ||
486 | usb_set_intfdata(interface, NULL); | 448 | dev_set_drvdata(&udev->dev, NULL); |
487 | 449 | ||
488 | /* | 450 | /* |
489 | * NOTE: rx/tx threads are invoked for each usb_device. | 451 | * NOTE: rx/tx threads are invoked for each usb_device. |
490 | */ | 452 | */ |
491 | stub_remove_files(&interface->dev); | 453 | stub_remove_files(&udev->dev); |
492 | 454 | ||
493 | /* If usb reset is called from event handler */ | 455 | /* If usb reset is called from event handler */ |
494 | if (busid_priv->sdev->ud.eh == current) { | 456 | if (busid_priv->sdev->ud.eh == current) |
495 | busid_priv->interf_count--; | ||
496 | return; | 457 | return; |
497 | } | ||
498 | |||
499 | if (busid_priv->interf_count > 1) { | ||
500 | busid_priv->interf_count--; | ||
501 | shutdown_busid(busid_priv); | ||
502 | usb_put_intf(interface); | ||
503 | return; | ||
504 | } | ||
505 | |||
506 | busid_priv->interf_count = 0; | ||
507 | 458 | ||
508 | /* shutdown the current connection */ | 459 | /* shutdown the current connection */ |
509 | shutdown_busid(busid_priv); | 460 | shutdown_busid(busid_priv); |
510 | 461 | ||
511 | usb_put_dev(sdev->udev); | 462 | usb_put_dev(sdev->udev); |
512 | usb_put_intf(interface); | ||
513 | 463 | ||
514 | /* free sdev */ | 464 | /* free sdev */ |
515 | busid_priv->sdev = NULL; | 465 | busid_priv->sdev = NULL; |
@@ -523,28 +473,34 @@ static void stub_disconnect(struct usb_interface *interface) | |||
523 | } | 473 | } |
524 | } | 474 | } |
525 | 475 | ||
526 | /* | 476 | #ifdef CONFIG_PM |
527 | * Presence of pre_reset and post_reset prevents the driver from being unbound | ||
528 | * when the device is being reset | ||
529 | */ | ||
530 | 477 | ||
531 | static int stub_pre_reset(struct usb_interface *interface) | 478 | /* These functions need usb_port_suspend and usb_port_resume, |
479 | * which reside in drivers/usb/core/usb.h. Skip for now. */ | ||
480 | |||
481 | static int stub_suspend(struct usb_device *udev, pm_message_t message) | ||
532 | { | 482 | { |
533 | dev_dbg(&interface->dev, "pre_reset\n"); | 483 | dev_dbg(&udev->dev, "stub_suspend\n"); |
484 | |||
534 | return 0; | 485 | return 0; |
535 | } | 486 | } |
536 | 487 | ||
537 | static int stub_post_reset(struct usb_interface *interface) | 488 | static int stub_resume(struct usb_device *udev, pm_message_t message) |
538 | { | 489 | { |
539 | dev_dbg(&interface->dev, "post_reset\n"); | 490 | dev_dbg(&udev->dev, "stub_resume\n"); |
491 | |||
540 | return 0; | 492 | return 0; |
541 | } | 493 | } |
542 | 494 | ||
543 | struct usb_driver stub_driver = { | 495 | #endif /* CONFIG_PM */ |
496 | |||
497 | struct usb_device_driver stub_driver = { | ||
544 | .name = "usbip-host", | 498 | .name = "usbip-host", |
545 | .probe = stub_probe, | 499 | .probe = stub_probe, |
546 | .disconnect = stub_disconnect, | 500 | .disconnect = stub_disconnect, |
547 | .id_table = stub_table, | 501 | #ifdef CONFIG_PM |
548 | .pre_reset = stub_pre_reset, | 502 | .suspend = stub_suspend, |
549 | .post_reset = stub_post_reset, | 503 | .resume = stub_resume, |
504 | #endif | ||
505 | .supports_autosuspend = 0, | ||
550 | }; | 506 | }; |
diff --git a/drivers/staging/usbip/stub_main.c b/drivers/staging/usbip/stub_main.c index baf857f7cc88..bd7b83a9d758 100644 --- a/drivers/staging/usbip/stub_main.c +++ b/drivers/staging/usbip/stub_main.c | |||
@@ -254,7 +254,7 @@ static int __init usbip_host_init(void) | |||
254 | return -ENOMEM; | 254 | return -ENOMEM; |
255 | } | 255 | } |
256 | 256 | ||
257 | ret = usb_register(&stub_driver); | 257 | ret = usb_register_device_driver(&stub_driver, THIS_MODULE); |
258 | if (ret) { | 258 | if (ret) { |
259 | pr_err("usb_register failed %d\n", ret); | 259 | pr_err("usb_register failed %d\n", ret); |
260 | goto err_usb_register; | 260 | goto err_usb_register; |
@@ -271,7 +271,7 @@ static int __init usbip_host_init(void) | |||
271 | return ret; | 271 | return ret; |
272 | 272 | ||
273 | err_create_file: | 273 | err_create_file: |
274 | usb_deregister(&stub_driver); | 274 | usb_deregister_device_driver(&stub_driver); |
275 | err_usb_register: | 275 | err_usb_register: |
276 | kmem_cache_destroy(stub_priv_cache); | 276 | kmem_cache_destroy(stub_priv_cache); |
277 | return ret; | 277 | return ret; |
@@ -286,7 +286,7 @@ static void __exit usbip_host_exit(void) | |||
286 | * deregister() calls stub_disconnect() for all devices. Device | 286 | * deregister() calls stub_disconnect() for all devices. Device |
287 | * specific data is cleared in stub_disconnect(). | 287 | * specific data is cleared in stub_disconnect(). |
288 | */ | 288 | */ |
289 | usb_deregister(&stub_driver); | 289 | usb_deregister_device_driver(&stub_driver); |
290 | 290 | ||
291 | kmem_cache_destroy(stub_priv_cache); | 291 | kmem_cache_destroy(stub_priv_cache); |
292 | } | 292 | } |
diff --git a/drivers/staging/usbip/stub_rx.c b/drivers/staging/usbip/stub_rx.c index 5d1d4a183300..76e44d949232 100644 --- a/drivers/staging/usbip/stub_rx.c +++ b/drivers/staging/usbip/stub_rx.c | |||
@@ -550,7 +550,7 @@ static void stub_rx_pdu(struct usbip_device *ud) | |||
550 | int ret; | 550 | int ret; |
551 | struct usbip_header pdu; | 551 | struct usbip_header pdu; |
552 | struct stub_device *sdev = container_of(ud, struct stub_device, ud); | 552 | struct stub_device *sdev = container_of(ud, struct stub_device, ud); |
553 | struct device *dev = &sdev->interface->dev; | 553 | struct device *dev = &sdev->udev->dev; |
554 | 554 | ||
555 | usbip_dbg_stub_rx("Enter\n"); | 555 | usbip_dbg_stub_rx("Enter\n"); |
556 | 556 | ||
diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c b/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c index 71a449cf50db..86a867582de6 100644 --- a/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c +++ b/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c | |||
@@ -32,7 +32,6 @@ struct usbip_host_driver *host_driver; | |||
32 | 32 | ||
33 | #define SYSFS_OPEN_RETRIES 100 | 33 | #define SYSFS_OPEN_RETRIES 100 |
34 | 34 | ||
35 | /* only the first interface value is true! */ | ||
36 | static int32_t read_attr_usbip_status(struct usbip_usb_device *udev) | 35 | static int32_t read_attr_usbip_status(struct usbip_usb_device *udev) |
37 | { | 36 | { |
38 | char attrpath[SYSFS_PATH_MAX]; | 37 | char attrpath[SYSFS_PATH_MAX]; |
@@ -56,8 +55,8 @@ static int32_t read_attr_usbip_status(struct usbip_usb_device *udev) | |||
56 | * usbip_status to reappear. | 55 | * usbip_status to reappear. |
57 | */ | 56 | */ |
58 | 57 | ||
59 | snprintf(attrpath, SYSFS_PATH_MAX, "%s/%s:%d.%d/usbip_status", | 58 | snprintf(attrpath, SYSFS_PATH_MAX, "%s/usbip_status", |
60 | udev->path, udev->busid, udev->bConfigurationValue, 0); | 59 | udev->path); |
61 | 60 | ||
62 | while (retries > 0) { | 61 | while (retries > 0) { |
63 | if (stat(attrpath, &s) == 0) | 62 | if (stat(attrpath, &s) == 0) |
@@ -168,19 +167,18 @@ static void delete_nothing(void *unused_data) | |||
168 | 167 | ||
169 | static int refresh_exported_devices(void) | 168 | static int refresh_exported_devices(void) |
170 | { | 169 | { |
171 | /* sysfs_device of usb_interface */ | ||
172 | struct sysfs_device *suintf; | ||
173 | struct dlist *suintf_list; | ||
174 | /* sysfs_device of usb_device */ | 170 | /* sysfs_device of usb_device */ |
175 | struct sysfs_device *sudev; | 171 | struct sysfs_device *sudev; |
176 | struct dlist *sudev_list; | 172 | struct dlist *sudev_list; |
173 | struct dlist *sudev_unique_list; | ||
177 | struct usbip_exported_device *edev; | 174 | struct usbip_exported_device *edev; |
178 | 175 | ||
179 | sudev_list = dlist_new_with_delete(sizeof(struct sysfs_device), | 176 | sudev_unique_list = dlist_new_with_delete(sizeof(struct sysfs_device), |
180 | delete_nothing); | 177 | delete_nothing); |
181 | 178 | ||
182 | suintf_list = sysfs_get_driver_devices(host_driver->sysfs_driver); | 179 | sudev_list = sysfs_get_driver_devices(host_driver->sysfs_driver); |
183 | if (!suintf_list) { | 180 | |
181 | if (!sudev_list) { | ||
184 | /* | 182 | /* |
185 | * Not an error condition. There are simply no devices bound to | 183 | * Not an error condition. There are simply no devices bound to |
186 | * the driver yet. | 184 | * the driver yet. |
@@ -190,23 +188,13 @@ static int refresh_exported_devices(void) | |||
190 | return 0; | 188 | return 0; |
191 | } | 189 | } |
192 | 190 | ||
193 | /* collect unique USB devices (not interfaces) */ | 191 | dlist_for_each_data(sudev_list, sudev, struct sysfs_device) |
194 | dlist_for_each_data(suintf_list, suintf, struct sysfs_device) { | 192 | if (check_new(sudev_unique_list, sudev)) |
195 | /* get usb device of this usb interface */ | 193 | dlist_unshift(sudev_unique_list, sudev); |
196 | sudev = sysfs_get_device_parent(suintf); | ||
197 | if (!sudev) { | ||
198 | dbg("sysfs_get_device_parent failed: %s", suintf->name); | ||
199 | continue; | ||
200 | } | ||
201 | 194 | ||
202 | if (check_new(sudev_list, sudev)) { | 195 | dlist_for_each_data(sudev_unique_list, sudev, struct sysfs_device) { |
203 | /* insert item at head of list */ | ||
204 | dlist_unshift(sudev_list, sudev); | ||
205 | } | ||
206 | } | ||
207 | |||
208 | dlist_for_each_data(sudev_list, sudev, struct sysfs_device) { | ||
209 | edev = usbip_exported_device_new(sudev->path); | 196 | edev = usbip_exported_device_new(sudev->path); |
197 | |||
210 | if (!edev) { | 198 | if (!edev) { |
211 | dbg("usbip_exported_device_new failed"); | 199 | dbg("usbip_exported_device_new failed"); |
212 | continue; | 200 | continue; |
@@ -216,7 +204,7 @@ static int refresh_exported_devices(void) | |||
216 | host_driver->ndevs++; | 204 | host_driver->ndevs++; |
217 | } | 205 | } |
218 | 206 | ||
219 | dlist_destroy(sudev_list); | 207 | dlist_destroy(sudev_unique_list); |
220 | 208 | ||
221 | return 0; | 209 | return 0; |
222 | } | 210 | } |
@@ -356,9 +344,8 @@ int usbip_host_export_device(struct usbip_exported_device *edev, int sockfd) | |||
356 | } | 344 | } |
357 | 345 | ||
358 | /* only the first interface is true */ | 346 | /* only the first interface is true */ |
359 | snprintf(attr_path, sizeof(attr_path), "%s/%s:%d.%d/%s", | 347 | snprintf(attr_path, sizeof(attr_path), "%s/%s", |
360 | edev->udev.path, edev->udev.busid, | 348 | edev->udev.path, attr_name); |
361 | edev->udev.bConfigurationValue, 0, attr_name); | ||
362 | 349 | ||
363 | attr = sysfs_open_attribute(attr_path); | 350 | attr = sysfs_open_attribute(attr_path); |
364 | if (!attr) { | 351 | if (!attr) { |
diff --git a/drivers/staging/usbip/userspace/src/usbip_bind.c b/drivers/staging/usbip/userspace/src/usbip_bind.c index 9ecaf6e574df..8cfd2dbd9510 100644 --- a/drivers/staging/usbip/userspace/src/usbip_bind.c +++ b/drivers/staging/usbip/userspace/src/usbip_bind.c | |||
@@ -52,12 +52,8 @@ static int bind_usbip(char *busid) | |||
52 | char attr_name[] = "bind"; | 52 | char attr_name[] = "bind"; |
53 | char sysfs_mntpath[SYSFS_PATH_MAX]; | 53 | char sysfs_mntpath[SYSFS_PATH_MAX]; |
54 | char bind_attr_path[SYSFS_PATH_MAX]; | 54 | char bind_attr_path[SYSFS_PATH_MAX]; |
55 | char intf_busid[SYSFS_BUS_ID_SIZE]; | ||
56 | struct sysfs_device *busid_dev; | ||
57 | struct sysfs_attribute *bind_attr; | 55 | struct sysfs_attribute *bind_attr; |
58 | struct sysfs_attribute *bConfValue; | 56 | int failed = 0; |
59 | struct sysfs_attribute *bNumIntfs; | ||
60 | int i, failed = 0; | ||
61 | int rc, ret = -1; | 57 | int rc, ret = -1; |
62 | 58 | ||
63 | rc = sysfs_get_mnt_path(sysfs_mntpath, SYSFS_PATH_MAX); | 59 | rc = sysfs_get_mnt_path(sysfs_mntpath, SYSFS_PATH_MAX); |
@@ -76,39 +72,15 @@ static int bind_usbip(char *busid) | |||
76 | return -1; | 72 | return -1; |
77 | } | 73 | } |
78 | 74 | ||
79 | busid_dev = sysfs_open_device(bus_type, busid); | 75 | rc = sysfs_write_attribute(bind_attr, busid, SYSFS_BUS_ID_SIZE); |
80 | if (!busid_dev) { | 76 | if (rc < 0) { |
81 | dbg("sysfs_open_device %s failed: %s", busid, strerror(errno)); | 77 | dbg("bind driver at %s failed", busid); |
82 | goto err_close_bind_attr; | 78 | failed = 1; |
83 | } | ||
84 | |||
85 | bConfValue = sysfs_get_device_attr(busid_dev, "bConfigurationValue"); | ||
86 | bNumIntfs = sysfs_get_device_attr(busid_dev, "bNumInterfaces"); | ||
87 | |||
88 | if (!bConfValue || !bNumIntfs) { | ||
89 | dbg("problem getting device attributes: %s", | ||
90 | strerror(errno)); | ||
91 | goto err_close_busid_dev; | ||
92 | } | ||
93 | |||
94 | for (i = 0; i < atoi(bNumIntfs->value); i++) { | ||
95 | snprintf(intf_busid, SYSFS_BUS_ID_SIZE, "%s:%.1s.%d", busid, | ||
96 | bConfValue->value, i); | ||
97 | |||
98 | rc = sysfs_write_attribute(bind_attr, intf_busid, | ||
99 | SYSFS_BUS_ID_SIZE); | ||
100 | if (rc < 0) { | ||
101 | dbg("bind driver at %s failed", intf_busid); | ||
102 | failed = 1; | ||
103 | } | ||
104 | } | 79 | } |
105 | 80 | ||
106 | if (!failed) | 81 | if (!failed) |
107 | ret = 0; | 82 | ret = 0; |
108 | 83 | ||
109 | err_close_busid_dev: | ||
110 | sysfs_close_device(busid_dev); | ||
111 | err_close_bind_attr: | ||
112 | sysfs_close_attribute(bind_attr); | 84 | sysfs_close_attribute(bind_attr); |
113 | 85 | ||
114 | return ret; | 86 | return ret; |
@@ -118,15 +90,12 @@ err_close_bind_attr: | |||
118 | static int unbind_other(char *busid) | 90 | static int unbind_other(char *busid) |
119 | { | 91 | { |
120 | char bus_type[] = "usb"; | 92 | char bus_type[] = "usb"; |
121 | char intf_busid[SYSFS_BUS_ID_SIZE]; | ||
122 | struct sysfs_device *busid_dev; | 93 | struct sysfs_device *busid_dev; |
123 | struct sysfs_device *intf_dev; | 94 | struct sysfs_device *dev; |
124 | struct sysfs_driver *intf_drv; | 95 | struct sysfs_driver *drv; |
125 | struct sysfs_attribute *unbind_attr; | 96 | struct sysfs_attribute *unbind_attr; |
126 | struct sysfs_attribute *bConfValue; | ||
127 | struct sysfs_attribute *bDevClass; | 97 | struct sysfs_attribute *bDevClass; |
128 | struct sysfs_attribute *bNumIntfs; | 98 | int rc; |
129 | int i, rc; | ||
130 | enum unbind_status status = UNBIND_ST_OK; | 99 | enum unbind_status status = UNBIND_ST_OK; |
131 | 100 | ||
132 | busid_dev = sysfs_open_device(bus_type, busid); | 101 | busid_dev = sysfs_open_device(bus_type, busid); |
@@ -134,12 +103,11 @@ static int unbind_other(char *busid) | |||
134 | dbg("sysfs_open_device %s failed: %s", busid, strerror(errno)); | 103 | dbg("sysfs_open_device %s failed: %s", busid, strerror(errno)); |
135 | return -1; | 104 | return -1; |
136 | } | 105 | } |
106 | dbg("busid path: %s", busid_dev->path); | ||
137 | 107 | ||
138 | bConfValue = sysfs_get_device_attr(busid_dev, "bConfigurationValue"); | ||
139 | bDevClass = sysfs_get_device_attr(busid_dev, "bDeviceClass"); | 108 | bDevClass = sysfs_get_device_attr(busid_dev, "bDeviceClass"); |
140 | bNumIntfs = sysfs_get_device_attr(busid_dev, "bNumInterfaces"); | 109 | if (!bDevClass) { |
141 | if (!bConfValue || !bDevClass || !bNumIntfs) { | 110 | dbg("problem getting device attribute: %s", |
142 | dbg("problem getting device attributes: %s", | ||
143 | strerror(errno)); | 111 | strerror(errno)); |
144 | goto err_close_busid_dev; | 112 | goto err_close_busid_dev; |
145 | } | 113 | } |
@@ -149,62 +117,62 @@ static int unbind_other(char *busid) | |||
149 | goto err_close_busid_dev; | 117 | goto err_close_busid_dev; |
150 | } | 118 | } |
151 | 119 | ||
152 | for (i = 0; i < atoi(bNumIntfs->value); i++) { | 120 | dev = sysfs_open_device(bus_type, busid); |
153 | snprintf(intf_busid, SYSFS_BUS_ID_SIZE, "%s:%.1s.%d", busid, | 121 | if (!dev) { |
154 | bConfValue->value, i); | 122 | dbg("could not open device: %s", |
155 | intf_dev = sysfs_open_device(bus_type, intf_busid); | 123 | strerror(errno)); |
156 | if (!intf_dev) { | 124 | goto err_close_busid_dev; |
157 | dbg("could not open interface device: %s", | 125 | } |
158 | strerror(errno)); | ||
159 | goto err_close_busid_dev; | ||
160 | } | ||
161 | |||
162 | dbg("%s -> %s", intf_dev->name, intf_dev->driver_name); | ||
163 | 126 | ||
164 | if (!strncmp("unknown", intf_dev->driver_name, SYSFS_NAME_LEN)) | 127 | dbg("%s -> %s", dev->name, dev->driver_name); |
165 | /* unbound interface */ | ||
166 | continue; | ||
167 | 128 | ||
168 | if (!strncmp(USBIP_HOST_DRV_NAME, intf_dev->driver_name, | 129 | if (!strncmp("unknown", dev->driver_name, SYSFS_NAME_LEN)) { |
169 | SYSFS_NAME_LEN)) { | 130 | /* unbound interface */ |
170 | /* already bound to usbip-host */ | 131 | sysfs_close_device(dev); |
171 | status = UNBIND_ST_USBIP_HOST; | 132 | goto out; |
172 | continue; | 133 | } |
173 | } | ||
174 | 134 | ||
175 | /* unbinding */ | 135 | if (!strncmp(USBIP_HOST_DRV_NAME, dev->driver_name, |
176 | intf_drv = sysfs_open_driver(bus_type, intf_dev->driver_name); | 136 | SYSFS_NAME_LEN)) { |
177 | if (!intf_drv) { | 137 | /* already bound to usbip-host */ |
178 | dbg("could not open interface driver on %s: %s", | 138 | status = UNBIND_ST_USBIP_HOST; |
179 | intf_dev->name, strerror(errno)); | 139 | sysfs_close_device(dev); |
180 | goto err_close_intf_dev; | 140 | goto out; |
181 | } | 141 | } |
182 | 142 | ||
183 | unbind_attr = sysfs_get_driver_attr(intf_drv, "unbind"); | 143 | /* unbinding */ |
184 | if (!unbind_attr) { | 144 | drv = sysfs_open_driver(bus_type, dev->driver_name); |
185 | dbg("problem getting interface driver attribute: %s", | 145 | if (!drv) { |
186 | strerror(errno)); | 146 | dbg("could not open device driver on %s: %s", |
187 | goto err_close_intf_drv; | 147 | dev->name, strerror(errno)); |
188 | } | 148 | goto err_close_intf_dev; |
149 | } | ||
150 | dbg("device driver: %s", drv->path); | ||
189 | 151 | ||
190 | rc = sysfs_write_attribute(unbind_attr, intf_dev->bus_id, | 152 | unbind_attr = sysfs_get_driver_attr(drv, "unbind"); |
191 | SYSFS_BUS_ID_SIZE); | 153 | if (!unbind_attr) { |
192 | if (rc < 0) { | 154 | dbg("problem getting device driver attribute: %s", |
193 | /* NOTE: why keep unbinding other interfaces? */ | 155 | strerror(errno)); |
194 | dbg("unbind driver at %s failed", intf_dev->bus_id); | 156 | goto err_close_intf_drv; |
195 | status = UNBIND_ST_FAILED; | 157 | } |
196 | } | ||
197 | 158 | ||
198 | sysfs_close_driver(intf_drv); | 159 | rc = sysfs_write_attribute(unbind_attr, dev->bus_id, |
199 | sysfs_close_device(intf_dev); | 160 | SYSFS_BUS_ID_SIZE); |
161 | if (rc < 0) { | ||
162 | /* NOTE: why keep unbinding other interfaces? */ | ||
163 | dbg("unbind driver at %s failed", dev->bus_id); | ||
164 | status = UNBIND_ST_FAILED; | ||
200 | } | 165 | } |
201 | 166 | ||
167 | sysfs_close_driver(drv); | ||
168 | sysfs_close_device(dev); | ||
169 | |||
202 | goto out; | 170 | goto out; |
203 | 171 | ||
204 | err_close_intf_drv: | 172 | err_close_intf_drv: |
205 | sysfs_close_driver(intf_drv); | 173 | sysfs_close_driver(drv); |
206 | err_close_intf_dev: | 174 | err_close_intf_dev: |
207 | sysfs_close_device(intf_dev); | 175 | sysfs_close_device(dev); |
208 | err_close_busid_dev: | 176 | err_close_busid_dev: |
209 | status = UNBIND_ST_FAILED; | 177 | status = UNBIND_ST_FAILED; |
210 | out: | 178 | out: |
diff --git a/drivers/staging/usbip/userspace/src/usbip_list.c b/drivers/staging/usbip/userspace/src/usbip_list.c index 237e099337a1..8864fa2a7f0b 100644 --- a/drivers/staging/usbip/userspace/src/usbip_list.c +++ b/drivers/staging/usbip/userspace/src/usbip_list.c | |||
@@ -52,9 +52,8 @@ static int get_exported_devices(char *host, int sockfd) | |||
52 | struct op_devlist_reply reply; | 52 | struct op_devlist_reply reply; |
53 | uint16_t code = OP_REP_DEVLIST; | 53 | uint16_t code = OP_REP_DEVLIST; |
54 | struct usbip_usb_device udev; | 54 | struct usbip_usb_device udev; |
55 | struct usbip_usb_interface uintf; | ||
56 | unsigned int i; | 55 | unsigned int i; |
57 | int j, rc; | 56 | int rc; |
58 | 57 | ||
59 | rc = usbip_net_send_op_common(sockfd, OP_REQ_DEVLIST, 0); | 58 | rc = usbip_net_send_op_common(sockfd, OP_REQ_DEVLIST, 0); |
60 | if (rc < 0) { | 59 | if (rc < 0) { |
@@ -104,22 +103,6 @@ static int get_exported_devices(char *host, int sockfd) | |||
104 | printf("%11s: %s\n", "", udev.path); | 103 | printf("%11s: %s\n", "", udev.path); |
105 | printf("%11s: %s\n", "", class_name); | 104 | printf("%11s: %s\n", "", class_name); |
106 | 105 | ||
107 | for (j = 0; j < udev.bNumInterfaces; j++) { | ||
108 | rc = usbip_net_recv(sockfd, &uintf, sizeof(uintf)); | ||
109 | if (rc < 0) { | ||
110 | dbg("usbip_net_recv failed: usbip_usb_intf[%d]", | ||
111 | j); | ||
112 | |||
113 | return -1; | ||
114 | } | ||
115 | usbip_net_pack_usb_interface(0, &uintf); | ||
116 | |||
117 | usbip_names_get_class(class_name, sizeof(class_name), | ||
118 | uintf.bInterfaceClass, | ||
119 | uintf.bInterfaceSubClass, | ||
120 | uintf.bInterfaceProtocol); | ||
121 | printf("%11s: %2d - %s\n", "", j, class_name); | ||
122 | } | ||
123 | printf("\n"); | 106 | printf("\n"); |
124 | } | 107 | } |
125 | 108 | ||
diff --git a/drivers/staging/usbip/userspace/src/usbip_unbind.c b/drivers/staging/usbip/userspace/src/usbip_unbind.c index d5a9ab6af2a6..cace87838c24 100644 --- a/drivers/staging/usbip/userspace/src/usbip_unbind.c +++ b/drivers/staging/usbip/userspace/src/usbip_unbind.c | |||
@@ -47,12 +47,10 @@ static int unbind_device(char *busid) | |||
47 | int verified = 0; | 47 | int verified = 0; |
48 | int rc, ret = -1; | 48 | int rc, ret = -1; |
49 | 49 | ||
50 | char attr_name[] = "bConfigurationValue"; | 50 | char attr_name[] = "unbind"; |
51 | char sysfs_mntpath[SYSFS_PATH_MAX]; | 51 | char sysfs_mntpath[SYSFS_PATH_MAX]; |
52 | char busid_attr_path[SYSFS_PATH_MAX]; | 52 | char unbind_attr_path[SYSFS_PATH_MAX]; |
53 | struct sysfs_attribute *busid_attr; | 53 | struct sysfs_attribute *unbind_attr; |
54 | char *val = NULL; | ||
55 | int len; | ||
56 | 54 | ||
57 | /* verify the busid device is using usbip-host */ | 55 | /* verify the busid device is using usbip-host */ |
58 | usbip_host_drv = sysfs_open_driver(bus_type, USBIP_HOST_DRV_NAME); | 56 | usbip_host_drv = sysfs_open_driver(bus_type, USBIP_HOST_DRV_NAME); |
@@ -99,55 +97,34 @@ static int unbind_device(char *busid) | |||
99 | return -1; | 97 | return -1; |
100 | } | 98 | } |
101 | 99 | ||
102 | snprintf(busid_attr_path, sizeof(busid_attr_path), "%s/%s/%s/%s/%s/%s", | 100 | snprintf(unbind_attr_path, sizeof(unbind_attr_path), "%s/%s/%s/%s/%s/%s", |
103 | sysfs_mntpath, SYSFS_BUS_NAME, bus_type, SYSFS_DEVICES_NAME, | 101 | sysfs_mntpath, SYSFS_BUS_NAME, bus_type, SYSFS_DRIVERS_NAME, |
104 | busid, attr_name); | 102 | USBIP_HOST_DRV_NAME, attr_name); |
105 | 103 | ||
106 | /* read a device attribute */ | 104 | /* read a device attribute */ |
107 | busid_attr = sysfs_open_attribute(busid_attr_path); | 105 | unbind_attr = sysfs_open_attribute(unbind_attr_path); |
108 | if (!busid_attr) { | 106 | if (!unbind_attr) { |
109 | err("could not open %s/%s: %s", busid, attr_name, | 107 | err("could not open %s/%s: %s", busid, attr_name, |
110 | strerror(errno)); | 108 | strerror(errno)); |
111 | return -1; | 109 | return -1; |
112 | } | 110 | } |
113 | 111 | ||
114 | if (sysfs_read_attribute(busid_attr) < 0) { | ||
115 | err("problem reading attribute: %s", strerror(errno)); | ||
116 | goto err_out; | ||
117 | } | ||
118 | |||
119 | len = busid_attr->len; | ||
120 | val = malloc(len); | ||
121 | *val = *busid_attr->value; | ||
122 | sysfs_close_attribute(busid_attr); | ||
123 | |||
124 | /* notify driver of unbind */ | 112 | /* notify driver of unbind */ |
125 | rc = modify_match_busid(busid, 0); | 113 | rc = modify_match_busid(busid, 0); |
126 | if (rc < 0) { | 114 | if (rc < 0) { |
127 | err("unable to unbind device on %s", busid); | 115 | err("unable to unbind device on %s", busid); |
128 | goto err_out; | ||
129 | } | ||
130 | |||
131 | /* write the device attribute */ | ||
132 | busid_attr = sysfs_open_attribute(busid_attr_path); | ||
133 | if (!busid_attr) { | ||
134 | err("could not open %s/%s: %s", busid, attr_name, | ||
135 | strerror(errno)); | ||
136 | return -1; | ||
137 | } | 116 | } |
138 | 117 | ||
139 | rc = sysfs_write_attribute(busid_attr, val, len); | 118 | rc = sysfs_write_attribute(unbind_attr, busid, |
140 | if (rc < 0) { | 119 | SYSFS_BUS_ID_SIZE); |
141 | err("problem writing attribute: %s", strerror(errno)); | 120 | if (rc < 0) { |
142 | goto err_out; | 121 | dbg("bind driver at %s failed", busid); |
143 | } | 122 | } |
144 | sysfs_close_attribute(busid_attr); | 123 | sysfs_close_attribute(unbind_attr); |
145 | 124 | ||
146 | ret = 0; | 125 | ret = 0; |
147 | printf("unbind device on busid %s: complete\n", busid); | 126 | printf("unbind device on busid %s: complete\n", busid); |
148 | 127 | ||
149 | err_out: | ||
150 | free(val); | ||
151 | err_close_usbip_host_drv: | 128 | err_close_usbip_host_drv: |
152 | sysfs_close_driver(usbip_host_drv); | 129 | sysfs_close_driver(usbip_host_drv); |
153 | 130 | ||
diff --git a/drivers/staging/usbip/userspace/src/usbipd.c b/drivers/staging/usbip/userspace/src/usbipd.c index 7980f8b5517b..c2b3ced9ca6e 100644 --- a/drivers/staging/usbip/userspace/src/usbipd.c +++ b/drivers/staging/usbip/userspace/src/usbipd.c | |||
@@ -159,9 +159,7 @@ static int send_reply_devlist(int connfd) | |||
159 | { | 159 | { |
160 | struct usbip_exported_device *edev; | 160 | struct usbip_exported_device *edev; |
161 | struct usbip_usb_device pdu_udev; | 161 | struct usbip_usb_device pdu_udev; |
162 | struct usbip_usb_interface pdu_uinf; | ||
163 | struct op_devlist_reply reply; | 162 | struct op_devlist_reply reply; |
164 | int i; | ||
165 | int rc; | 163 | int rc; |
166 | 164 | ||
167 | reply.ndev = 0; | 165 | reply.ndev = 0; |
@@ -196,19 +194,6 @@ static int send_reply_devlist(int connfd) | |||
196 | dbg("usbip_net_send failed: pdu_udev"); | 194 | dbg("usbip_net_send failed: pdu_udev"); |
197 | return -1; | 195 | return -1; |
198 | } | 196 | } |
199 | |||
200 | for (i = 0; i < edev->udev.bNumInterfaces; i++) { | ||
201 | dump_usb_interface(&edev->uinf[i]); | ||
202 | memcpy(&pdu_uinf, &edev->uinf[i], sizeof(pdu_uinf)); | ||
203 | usbip_net_pack_usb_interface(1, &pdu_uinf); | ||
204 | |||
205 | rc = usbip_net_send(connfd, &pdu_uinf, | ||
206 | sizeof(pdu_uinf)); | ||
207 | if (rc < 0) { | ||
208 | dbg("usbip_net_send failed: pdu_uinf"); | ||
209 | return -1; | ||
210 | } | ||
211 | } | ||
212 | } | 197 | } |
213 | 198 | ||
214 | return 0; | 199 | return 0; |
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c index acbfeb0a0119..358ca8dd784f 100644 --- a/drivers/usb/core/generic.c +++ b/drivers/usb/core/generic.c | |||
@@ -155,6 +155,7 @@ int usb_choose_configuration(struct usb_device *udev) | |||
155 | } | 155 | } |
156 | return i; | 156 | return i; |
157 | } | 157 | } |
158 | EXPORT_SYMBOL_GPL(usb_choose_configuration); | ||
158 | 159 | ||
159 | static int generic_probe(struct usb_device *udev) | 160 | static int generic_probe(struct usb_device *udev) |
160 | { | 161 | { |
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index f829a1aad1c3..08d95e9d56c2 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
@@ -1920,6 +1920,7 @@ free_interfaces: | |||
1920 | usb_autosuspend_device(dev); | 1920 | usb_autosuspend_device(dev); |
1921 | return 0; | 1921 | return 0; |
1922 | } | 1922 | } |
1923 | EXPORT_SYMBOL_GPL(usb_set_configuration); | ||
1923 | 1924 | ||
1924 | static LIST_HEAD(set_config_list); | 1925 | static LIST_HEAD(set_config_list); |
1925 | static DEFINE_SPINLOCK(set_config_lock); | 1926 | static DEFINE_SPINLOCK(set_config_lock); |
diff --git a/include/linux/usb.h b/include/linux/usb.h index c716da18c668..f434619f3975 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h | |||
@@ -1668,6 +1668,10 @@ extern void usb_reset_endpoint(struct usb_device *dev, unsigned int epaddr); | |||
1668 | /* this request isn't really synchronous, but it belongs with the others */ | 1668 | /* this request isn't really synchronous, but it belongs with the others */ |
1669 | extern int usb_driver_set_configuration(struct usb_device *udev, int config); | 1669 | extern int usb_driver_set_configuration(struct usb_device *udev, int config); |
1670 | 1670 | ||
1671 | /* choose and set configuration for device */ | ||
1672 | extern int usb_choose_configuration(struct usb_device *udev); | ||
1673 | extern int usb_set_configuration(struct usb_device *dev, int configuration); | ||
1674 | |||
1671 | /* | 1675 | /* |
1672 | * timeouts, in milliseconds, used for sending/receiving control messages | 1676 | * timeouts, in milliseconds, used for sending/receiving control messages |
1673 | * they typically complete within a few frames (msec) after they're issued | 1677 | * they typically complete within a few frames (msec) after they're issued |