ChangeSet 1.1757.66.23, 2004/07/14 15:00:02-07:00, david-b@pacbell.net

[PATCH] USB: usb gadget API updates

Gadget API updates, including new features:

    -	Adds several new optional calls that can be made to the
	USB peripheral controller:

	    * VBUS session reporting, for use mostly by external
	      transcievers (such as isp1301).  Detection of VBUS
	      power is the first step in enumeration, and usually
	      corresponds to a device being plugged into a hub.

	    * "Soft Connect" feature, wherein the D+ pullup is under
	      gadget driver control.  This is a second step during
	      enumeration, which lets the hub see the new device.
	      (Based on a patch by Alex Sanks <alex@netchip.com>.)

	    * Control over VBUS current draw.  So for example this is
	      what a gadget driver uses during SET_CONFIGURATION to
	      say "it's OK to draw 300 mA from VBUS to recharge".

    -	Basic interfaces to support device-side USB OTG.  Feature
	flags and descriptors are in <linux/usb_ch9.h> already.

	    * Reports whether the device has a Mini-AB port, so
	      that OTG support (desriptors etc) is required.

	    * Reports OTG device feature flags for HNP.  (The OTG
	      spec requires user interfaces to report this stuff.)
	      Say if this is a B-Peripheral or an A-Peripheral.

	    * Says that usb_gadget_wakeup() is how to access SRP,
	      and usb_gadget_disconnect() is how to access HNP.

    -	Minor updates/cleanups to comments (Linux 2.5-->2.6 etc)

Currently there's no support for SRP-only OTG devices.

Signed-off-by:	David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>


 include/linux/usb_gadget.h |  153 ++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 146 insertions(+), 7 deletions(-)


diff -Nru a/include/linux/usb_gadget.h b/include/linux/usb_gadget.h
--- a/include/linux/usb_gadget.h	2004-07-14 16:44:21 -07:00
+++ b/include/linux/usb_gadget.h	2004-07-14 16:44:21 -07:00
@@ -6,7 +6,7 @@
  * master many USB gadgets, but the gadgets are only slaved to one host.
  *
  *
- * (c) Copyright 2002-2003 by David Brownell
+ * (C) Copyright 2002-2004 by David Brownell
  * All Rights Reserved.
  *
  * This software is licensed under the GNU GPL version 2.
@@ -73,8 +73,6 @@
  */
 	// NOTE this is analagous to 'struct urb' on the host side,
 	// except that it's thinner and promotes more pre-allocation.
-	//
-	// ISSUE should this be allocated through the device?
 
 struct usb_request {
 	void			*buf;
@@ -116,8 +114,8 @@
 		dma_addr_t *dma, int gfp_flags);
 	void (*free_buffer) (struct usb_ep *ep, void *buf, dma_addr_t dma,
 		unsigned bytes);
-	// NOTE:  on 2.5, drivers may also use dma_map() and
-	// dma_sync_single_*() to manage dma overhead.
+	// NOTE:  on 2.6, drivers may also use dma_map() and
+	// dma_sync_single_*() to directly manage dma overhead. 
 
 	int (*queue) (struct usb_ep *ep, struct usb_request *req,
 		int gfp_flags);
@@ -453,7 +451,10 @@
 struct usb_gadget_ops {
 	int	(*get_frame)(struct usb_gadget *);
 	int	(*wakeup)(struct usb_gadget *);
-	int	(*set_selfpowered) (struct usb_gadget *, int value);
+	int	(*set_selfpowered) (struct usb_gadget *, int is_selfpowered);
+	int	(*vbus_session) (struct usb_gadget *, int is_active);
+	int	(*vbus_draw) (struct usb_gadget *, unsigned mA);
+	int	(*pullup) (struct usb_gadget *, int is_on);
 	int	(*ioctl)(struct usb_gadget *,
 				unsigned code, unsigned long param);
 };
@@ -467,6 +468,17 @@
  * @speed: Speed of current connection to USB host.
  * @is_dualspeed: True if the controller supports both high and full speed
  *	operation.  If it does, the gadget driver must also support both.
+ * @is_otg: True if the USB device port uses a Mini-AB jack, so that the
+ *	gadget driver must provide a USB OTG descriptor.
+ * @is_a_peripheral: False unless is_otg, the "A" end of a USB cable
+ *	is in the Mini-AB jack, and HNP has been used to switch roles
+ *	so that the "A" device currently acts as A-Peripheral, not A-Host.
+ * @a_hnp_support: OTG device feature flag, indicating that the A-Host
+ *	supports HNP at this port.
+ * @a_alt_hnp_support: OTG device feature flag, indicating that the A-Host
+ *	only supports HNP on a different root port.
+ * @b_hnp_enable: OTG device feature flag, indicating that the A-Host
+ *	enabled HNP support.
  * @name: Identifies the controller hardware type.  Used in diagnostics
  * 	and sometimes configuration.
  * @dev: Driver model state for this abstract device.
@@ -480,9 +492,14 @@
  *
  * Except for the driver data, all fields in this structure are
  * read-only to the gadget driver.  That driver data is part of the
- * "driver model" infrastructure in 2.5 (and later) kernels, and for
+ * "driver model" infrastructure in 2.6 (and later) kernels, and for
  * earlier systems is grouped in a similar structure that's not known
  * to the rest of the kernel.
+ *
+ * Values of the three OTG device feature flags are updated before the
+ * setup() call corresponding to USB_REQ_SET_CONFIGURATION, and before
+ * driver suspend() calls.  They are valid only when is_otg, and when the
+ * device is acting as a B-Peripheral (so is_a_peripheral is false).
  */
 struct usb_gadget {
 	/* readonly to gadget driver */
@@ -491,6 +508,11 @@
 	struct list_head		ep_list;	/* of usb_ep */
 	enum usb_device_speed		speed;
 	unsigned			is_dualspeed:1;
+	unsigned			is_otg:1;
+	unsigned			is_a_peripheral:1;
+	unsigned			b_hnp_enable:1;
+	unsigned			a_hnp_support:1;
+	unsigned			a_alt_hnp_support:1;
 	const char			*name;
 	struct device			dev;
 };
@@ -525,6 +547,10 @@
  * doesn't support such attempts, or its support has not been enabled
  * by the usb host.  Drivers must return device descriptors that report
  * their ability to support this, or hosts won't enable it.
+ *
+ * This may also try to use SRP to wake the host and start enumeration,
+ * even if OTG isn't otherwise in use.  OTG devices may also start
+ * remote wakeup even when hosts don't explicitly enable it.
  */
 static inline int usb_gadget_wakeup (struct usb_gadget *gadget)
 {
@@ -568,6 +594,107 @@
 	return gadget->ops->set_selfpowered (gadget, 0);
 }
 
+/**
+ * usb_gadget_vbus_connect - Notify controller that VBUS is powered
+ * @gadget:The device which now has VBUS power.
+ *
+ * This call is used by a driver for an external transceiver (or GPIO)
+ * that detects a VBUS power session starting.  Common responses include
+ * resuming the controller, activating the D+ (or D-) pullup to let the
+ * host detect that a USB device is attached, and starting to draw power
+ * (8mA or possibly more, especially after SET_CONFIGURATION).
+ *
+ * Returns zero on success, else negative errno.
+ */
+static inline int
+usb_gadget_vbus_connect(struct usb_gadget *gadget)
+{
+	if (!gadget->ops->vbus_session)
+		return -EOPNOTSUPP;
+	return gadget->ops->vbus_session (gadget, 1);
+}
+
+/**
+ * usb_gadget_vbus_draw - constrain controller's VBUS power usage
+ * @gadget:The device whose VBUS usage is being described
+ * @mA:How much current to draw, in milliAmperes.  This should be twice
+ *	the value listed in the configuration descriptor bMaxPower field.
+ *
+ * This call is used by gadget drivers during SET_CONFIGURATION calls,
+ * reporting how much power the device may consume.  For example, this
+ * could affect how quickly batteries are recharged.
+ *
+ * Returns zero on success, else negative errno.
+ */
+static inline int
+usb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA)
+{
+	if (!gadget->ops->vbus_draw)
+		return -EOPNOTSUPP;
+	return gadget->ops->vbus_draw (gadget, mA);
+}
+
+/**
+ * usb_gadget_vbus_disconnect - notify controller about VBUS session end
+ * @gadget:the device whose VBUS supply is being described
+ *
+ * This call is used by a driver for an external transceiver (or GPIO)
+ * that detects a VBUS power session ending.  Common responses include
+ * reversing everything done in usb_gadget_vbus_connect().
+ *
+ * Returns zero on success, else negative errno.
+ */
+static inline int
+usb_gadget_vbus_disconnect(struct usb_gadget *gadget)
+{
+	if (!gadget->ops->vbus_session)
+		return -EOPNOTSUPP;
+	return gadget->ops->vbus_session (gadget, 0);
+}
+
+/**
+ * usb_gadget_connect - software-controlled connect to USB host
+ * @gadget:the peripheral being connected
+ *
+ * Enables the D+ (or potentially D-) pullup.  The host will start
+ * enumerating this gadget when the pullup is active and a VBUS session
+ * is active (the link is powered).  This pullup is always enabled unless
+ * usb_gadget_disconnect() has been used to disable it.
+ *
+ * Returns zero on success, else negative errno.
+ */
+static inline int
+usb_gadget_connect (struct usb_gadget *gadget)
+{
+	if (!gadget->ops->pullup)
+		return -EOPNOTSUPP;
+	return gadget->ops->pullup (gadget, 1);
+}
+
+/**
+ * usb_gadget_disconnect - software-controlled disconnect from USB host
+ * @gadget:the peripheral being disconnected
+ *
+ * Disables the D+ (or potentially D-) pullup, which the host may see
+ * as a disconnect (when a VBUS session is active).  Not all systems
+ * support software pullup controls.
+ *
+ * This routine may be used during the gadget driver bind() call to prevent
+ * the peripheral from ever being visible to the USB host, unless later
+ * usb_gadget_connect() is called.  For example, user mode components may
+ * need to be activated before the system can talk to hosts.
+ *
+ * Returns zero on success, else negative errno.
+ */
+static inline int
+usb_gadget_disconnect (struct usb_gadget *gadget)
+{
+	if (!gadget->ops->pullup)
+		return -EOPNOTSUPP;
+	return gadget->ops->pullup (gadget, 0);
+}
+
+
 
 /*-------------------------------------------------------------------------*/
 
@@ -601,6 +728,12 @@
  * means the driver will handle setup() requests needed to enumerate (and
  * meet "chapter 9" requirements) then do some useful work.
  *
+ * If gadget->is_otg is true, the gadget driver must provide an OTG
+ * descriptor during enumeration, or else fail the bind() call.  In such
+ * cases, no USB traffic may flow until both bind() returns without
+ * having called usb_gadget_disconnect(), and the USB host stack has
+ * initialized.
+ *
  * Drivers use hardware-specific knowledge to configure the usb hardware.
  * endpoint addressing is only one of several hardware characteristics that
  * are in descriptors the ep0 implementation returns from setup() calls.
@@ -634,6 +767,12 @@
  * the (remote) host can't do that any longer; or an error state might
  * be cleared, to make the device behave identically whether or not
  * power is maintained.
+ *
+ * If the OTG b_hnp_enabled flag is set during a suspend() call, the
+ * device may use HNP to switch from "B-Peripheral" to "B-Host" mode
+ * (or back from "A-Peripheral" mode to the original "A-Host") if
+ * the gadget driver calls usb_gadget_disconnect() before the device
+ * is resumed.
  */
 struct usb_gadget_driver {
 	char			*function;
