From: Alan Stern <[EMAIL PROTECTED]>

It's generally a bad idea for USB interface drivers to try to change a
device's configuration, and usbcore doesn't provide any way for them
to do it.  However in a few exceptional circumstances it can make
sense.  This patch (as767) adds a roundabout mechanism to help drivers
that may need it.

Signed-off-by: Alan Stern <[EMAIL PROTECTED]>
Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>
---
 drivers/usb/core/message.c |   59 ++++++++++++++++++++++++++++++++++++++++++++
 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 49cfd79..333b22c 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1493,6 +1493,65 @@ free_interfaces:
        return 0;
 }
 
+struct set_config_request {
+       struct usb_device       *udev;
+       int                     config;
+       struct work_struct      work;
+};
+
+/* Worker routine for usb_driver_set_configuration() */
+static void driver_set_config_work(void *_req)
+{
+       struct set_config_request *req = _req;
+
+       usb_lock_device(req->udev);
+       usb_set_configuration(req->udev, req->config);
+       usb_unlock_device(req->udev);
+       usb_put_dev(req->udev);
+       kfree(req);
+}
+
+/**
+ * usb_driver_set_configuration - Provide a way for drivers to change device 
configurations
+ * @udev: the device whose configuration is being updated
+ * @config: the configuration being chosen.
+ * Context: In process context, must be able to sleep
+ *
+ * Device interface drivers are not allowed to change device configurations.
+ * This is because changing configurations will destroy the interface the
+ * driver is bound to and create new ones; it would be like a floppy-disk
+ * driver telling the computer to replace the floppy-disk drive with a
+ * tape drive!
+ *
+ * Still, in certain specialized circumstances the need may arise.  This
+ * routine gets around the normal restrictions by using a work thread to
+ * submit the change-config request.
+ *
+ * Returns 0 if the request was succesfully queued, error code otherwise.
+ * The caller has no way to know whether the queued request will eventually
+ * succeed.
+ */
+int usb_driver_set_configuration(struct usb_device *udev, int config)
+{
+       struct set_config_request *req;
+
+       req = kmalloc(sizeof(*req), GFP_KERNEL);
+       if (!req)
+               return -ENOMEM;
+       req->udev = udev;
+       req->config = config;
+       INIT_WORK(&req->work, driver_set_config_work, req);
+
+       usb_get_dev(udev);
+       if (!schedule_work(&req->work)) {
+               usb_put_dev(udev);
+               kfree(req);
+               return -EINVAL;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(usb_driver_set_configuration);
+
 // synchronous request completion model
 EXPORT_SYMBOL(usb_control_msg);
 EXPORT_SYMBOL(usb_bulk_msg);
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 26d8a5f..f104efa 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -1099,6 +1099,9 @@ extern int usb_clear_halt(struct usb_dev
 extern int usb_reset_configuration(struct usb_device *dev);
 extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate);
 
+/* this request isn't really synchronous, but it belongs with the others */
+extern int usb_driver_set_configuration(struct usb_device *udev, int config);
+
 /*
  * timeouts, in milliseconds, used for sending/receiving control messages
  * they typically complete within a few frames (msec) after they're issued
-- 
1.4.2.1


-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to