[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[patch 01/06] ti_usb, usbcore: help drivers to change device



Hi, debian-kernel Developers. So far i have nothing wrong with this
patchset, only some minor bureoucracy. Thus i'm sending its other parts.

---
Greg:

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.

Alan Stern



Signed-off-by: Alan Stern <stern@rowland.harvard.edu>

===

Right now this would be used by only one driver, so the code could be put 
into that driver instead of the core.  However I'm submitting it for the 
core, on the theory that if one driver can find a use for it, other ones 
eventually will too.

-
Yes, usbcore design is "a bad idea", thus we must accept this crutch!

comment-by: Oleg Verych
----
---
 drivers/usb/core/message.c |   59 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/usb.h        |    3 ++
 2 files changed, 62 insertions(+)

Index: linux-source-2.6.18/include/linux/usb.h
===================================================================
--- linux-source-2.6.18.orig/include/linux/usb.h	2007-02-23 09:05:41.626412250 +0100
+++ linux-source-2.6.18/include/linux/usb.h	2007-02-23 09:12:21.455400000 +0100
@@ -1038,6 +1038,9 @@
 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
Index: linux-source-2.6.18/drivers/usb/core/message.c
===================================================================
--- linux-source-2.6.18.orig/drivers/usb/core/message.c	2007-02-23 09:05:41.710417500 +0100
+++ linux-source-2.6.18/drivers/usb/core/message.c	2007-02-23 09:12:21.459400250 +0100
@@ -1508,6 +1508,65 @@
 	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);

--



Reply to: