diff options
| -rw-r--r-- | drivers/usb/core/message.c | 59 | ||||
| -rw-r--r-- | include/linux/usb.h | 3 |
2 files changed, 62 insertions, 0 deletions
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 49cfd7928a1c..333b22c68aa4 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
| @@ -1493,6 +1493,65 @@ free_interfaces: | |||
| 1493 | return 0; | 1493 | return 0; |
| 1494 | } | 1494 | } |
| 1495 | 1495 | ||
| 1496 | struct set_config_request { | ||
| 1497 | struct usb_device *udev; | ||
| 1498 | int config; | ||
| 1499 | struct work_struct work; | ||
| 1500 | }; | ||
| 1501 | |||
| 1502 | /* Worker routine for usb_driver_set_configuration() */ | ||
| 1503 | static void driver_set_config_work(void *_req) | ||
| 1504 | { | ||
| 1505 | struct set_config_request *req = _req; | ||
| 1506 | |||
| 1507 | usb_lock_device(req->udev); | ||
| 1508 | usb_set_configuration(req->udev, req->config); | ||
| 1509 | usb_unlock_device(req->udev); | ||
| 1510 | usb_put_dev(req->udev); | ||
| 1511 | kfree(req); | ||
| 1512 | } | ||
| 1513 | |||
| 1514 | /** | ||
| 1515 | * usb_driver_set_configuration - Provide a way for drivers to change device configurations | ||
| 1516 | * @udev: the device whose configuration is being updated | ||
| 1517 | * @config: the configuration being chosen. | ||
| 1518 | * Context: In process context, must be able to sleep | ||
| 1519 | * | ||
| 1520 | * Device interface drivers are not allowed to change device configurations. | ||
| 1521 | * This is because changing configurations will destroy the interface the | ||
| 1522 | * driver is bound to and create new ones; it would be like a floppy-disk | ||
| 1523 | * driver telling the computer to replace the floppy-disk drive with a | ||
| 1524 | * tape drive! | ||
| 1525 | * | ||
| 1526 | * Still, in certain specialized circumstances the need may arise. This | ||
| 1527 | * routine gets around the normal restrictions by using a work thread to | ||
| 1528 | * submit the change-config request. | ||
| 1529 | * | ||
| 1530 | * Returns 0 if the request was succesfully queued, error code otherwise. | ||
| 1531 | * The caller has no way to know whether the queued request will eventually | ||
| 1532 | * succeed. | ||
| 1533 | */ | ||
| 1534 | int usb_driver_set_configuration(struct usb_device *udev, int config) | ||
| 1535 | { | ||
| 1536 | struct set_config_request *req; | ||
| 1537 | |||
| 1538 | req = kmalloc(sizeof(*req), GFP_KERNEL); | ||
| 1539 | if (!req) | ||
| 1540 | return -ENOMEM; | ||
| 1541 | req->udev = udev; | ||
| 1542 | req->config = config; | ||
| 1543 | INIT_WORK(&req->work, driver_set_config_work, req); | ||
| 1544 | |||
| 1545 | usb_get_dev(udev); | ||
| 1546 | if (!schedule_work(&req->work)) { | ||
| 1547 | usb_put_dev(udev); | ||
| 1548 | kfree(req); | ||
| 1549 | return -EINVAL; | ||
| 1550 | } | ||
| 1551 | return 0; | ||
| 1552 | } | ||
| 1553 | EXPORT_SYMBOL_GPL(usb_driver_set_configuration); | ||
| 1554 | |||
| 1496 | // synchronous request completion model | 1555 | // synchronous request completion model |
| 1497 | EXPORT_SYMBOL(usb_control_msg); | 1556 | EXPORT_SYMBOL(usb_control_msg); |
| 1498 | EXPORT_SYMBOL(usb_bulk_msg); | 1557 | EXPORT_SYMBOL(usb_bulk_msg); |
diff --git a/include/linux/usb.h b/include/linux/usb.h index 26d8a5f36896..f104efa04d79 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h | |||
| @@ -1099,6 +1099,9 @@ extern int usb_clear_halt(struct usb_device *dev, int pipe); | |||
| 1099 | extern int usb_reset_configuration(struct usb_device *dev); | 1099 | extern int usb_reset_configuration(struct usb_device *dev); |
| 1100 | extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate); | 1100 | extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate); |
| 1101 | 1101 | ||
| 1102 | /* this request isn't really synchronous, but it belongs with the others */ | ||
| 1103 | extern int usb_driver_set_configuration(struct usb_device *udev, int config); | ||
| 1104 | |||
| 1102 | /* | 1105 | /* |
| 1103 | * timeouts, in milliseconds, used for sending/receiving control messages | 1106 | * timeouts, in milliseconds, used for sending/receiving control messages |
| 1104 | * they typically complete within a few frames (msec) after they're issued | 1107 | * they typically complete within a few frames (msec) after they're issued |
