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 .) * 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 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 Signed-off-by: Greg Kroah-Hartman 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;