summaryrefslogtreecommitdiffstats
path: root/include/linux/usb
diff options
context:
space:
mode:
authorRoger Quadros <roger.quadros@nokia.com>2011-05-09 13:08:06 +0300
committerGreg Kroah-Hartman <gregkh@suse.de>2011-05-10 14:14:57 -0700
commit1b9ba000177ee47bcc5b44c7c34e48e735f5f9b1 (patch)
tree8faa82465181387e1962786de7805912a8bacb66 /include/linux/usb
parent8eadef1526886db2a471c432d2c3d154de46f5c6 (diff)
downloadlinux-1b9ba000177ee47bcc5b44c7c34e48e735f5f9b1.tar.gz
linux-1b9ba000177ee47bcc5b44c7c34e48e735f5f9b1.tar.bz2
linux-1b9ba000177ee47bcc5b44c7c34e48e735f5f9b1.zip
usb: gadget: composite: Allow function drivers to pause control transfers
Some USB function drivers (e.g. f_mass_storage.c) need to delay or defer the data/status stages of standard control requests like SET_CONFIGURATION or SET_INTERFACE till they are done with their bookkeeping and are actually ready for accepting new commands to their interface. They can now achieve this functionality by returning USB_GADGET_DELAYED_STATUS in their setup handlers (e.g. set_alt()). The composite framework will then defer completion of the control transfer by not completing the data/status stages. This ensures that the host does not send new packets to the interface till the function driver is ready to take them. When the function driver that requested for USB_GADGET_DELAYED_STATUS is done with its bookkeeping, it should signal the composite framework to continue with the data/status stages of the control transfer. It can do so by invoking the new API usb_composite_setup_continue(). This is where the control transfer's data/status stages are completed and host can initiate new transfers. The DELAYED_STATUS mechanism is currently only supported if the expected data phase is 0 bytes (i.e. w_length == 0). Since SET_CONFIGURATION and SET_INTERFACE are the only cases that will use this mechanism, this is not a limitation. Signed-off-by: Roger Quadros <roger.quadros@nokia.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'include/linux/usb')
-rw-r--r--include/linux/usb/composite.h16
1 files changed, 15 insertions, 1 deletions
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index 882a084a8411..b78cba466d3d 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -37,6 +37,14 @@
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
+/*
+ * USB function drivers should return USB_GADGET_DELAYED_STATUS if they
+ * wish to delay the data/status stages of the control transfer till they
+ * are ready. The control transfer will then be kept from completing till
+ * all the function drivers that requested for USB_GADGET_DELAYED_STAUS
+ * invoke usb_composite_setup_continue().
+ */
+#define USB_GADGET_DELAYED_STATUS 0x7fff /* Impossibly large value */
struct usb_configuration;
@@ -285,6 +293,7 @@ struct usb_composite_driver {
extern int usb_composite_probe(struct usb_composite_driver *driver,
int (*bind)(struct usb_composite_dev *cdev));
extern void usb_composite_unregister(struct usb_composite_driver *driver);
+extern void usb_composite_setup_continue(struct usb_composite_dev *cdev);
/**
@@ -342,7 +351,12 @@ struct usb_composite_dev {
*/
unsigned deactivations;
- /* protects at least deactivation count */
+ /* the composite driver won't complete the control transfer's
+ * data/status stages till delayed_status is zero.
+ */
+ int delayed_status;
+
+ /* protects deactivations and delayed_status counts*/
spinlock_t lock;
};