Linux USB "On-The-Go" (OTG) on OMAP H2

The new USB "On-The-Go" (OTG) capabilities are not yet widely understood, or even generally available. The most visible feature of OTG is that it defines the behavior of intelligent "Dual-Role" USB devices, such as cameras or wireless handsets, which act either as USB host or as USB peripheral. That role choice is made each time the device is used, rather than once when it's designed, giving a flexibility previously unknown with USB. Using a new kind of USB connector, OTG lets USB support more "peer to peer" style application models. You could

  • Hook a cell phone to a laptop to synchronize schedules, get new audio recordings, or swap other documents;
  • Print a picture from a camera to a USB printer;
  • Connect a USB keyboard to your PDA;
  • Update game data on your portable console over USB.

This document should be useful to developers investigating the use of Linux to implement OTG-capable products. It presents the USB OTG support contributed by Texas Instruments for the OMAP H2 software development platform running an Linux 2.6 kernel. That builds on the standard Linux USB host and peripheral side driver frameworks, making small additions as described here. It also includes drivers implementing OTG support on OMAP platforms.

OMAP H2 Platform

The H2 software development platform includes a Texas Instruments OMAP 5912/16xx series processor, with an ARM 926TEJ cpu, a DSP, battery power management, and a wealth of other features often used in cell phones. USB support includes:

  • Three integrated USB controllers: OHCI host, USB Device Controller (UDC), and an OTG controller, all supporting full speed USB (12 Mbit/s).
  • "Mini-AB" connector on the H2 sample board. All "dual-role" OTG devices should have exactly one such external USB connector.
  • External USB OTG transceiver, Philips ISP1301 (controlled over I2C), with an alternate software-visible wiring option.
  • USB VBUS is hooked up to a TI TPS65010 power controller (controlled over I2C) so that an A-role system can supply up to 500mA of current for battery charging to a B-role (default peripheral) H2. In A-role (default host), the H2 itself supplies 8mA.

The "Mini-AB" connector is compatible with standard USB 2.0 "Mini-B" connectors, which appear in some new USB peripherals.

Most OMAP processors support this and similar product designs. Register interfaces to the different USB controllers are largely source-compatible, although older chips don't support OTG.

OTG

It's reasonable to think about OTG support as revolving around that "Mini-AB" connector, since that's what demands the highly visible "dual-role" capability implemented by the OTG drivers. OTG uses two methods to chose device role:

  • The simplest is built into the special Mini-A to Mini-B cables that OTG uses: the Mini-A connector grounds the ID pin, while the Mini-B end of the cable doesn't. That controls startup in A-Host or B-Peripheral role, and is the only method needed unless you're hooking up to another dual-role device. Call this "cable based role switching"; some incomplete OTG implementations stop at this point.
  • When connected to a dual-role device, a fancier software-driven method can be used later: switching roles using the Host Negotiation Protocol (HNP). That protects against the inevitable cases where the cable gets hooked up going the "wrong" direction for at least one of the tasks at hand.

That dynamic role selection is the most procedurally visible aspect of OTG, but there's more to OTG than that; see the OTG specification (and errata). The primary target of OTG is battery powered devices, so several aspects of the specification support reduced power usage. These include a new Session Request Protocol (SRP), which may be supported even by single-role USB devices.

To someone providing hardware-level drivers, an OTG solution starts with support for the standard Linux-USB host side and peripheral side driver stacks. Add protocol support for SRP and HNP, match the state machines in the OTG specification well enough to pass OTG hardware and software compliance testing, and then your product can use the OTG logo.

USB OTG Logo
full-speed version

Outline

The current Linux kernel updates for OTG support break down as follows:

  • Programming Interfaces have been updated; mainstream Linux 2.6.9 kernels have all of these changes.
    • USB Device Controller Drivers export some new interfaces.
    • USB Gadget Drivers have some new responsibilities that involve using those new interfaces. Some still need to be updated accordingly, to work on dual-role systems.
    • The Linux-USB Host side "usbcore" module acquired a few new OTG-specific responsibilities affecting enumeration, which are mostly invisible to device drivers. It also needed to learn about USB suspend/resume and remote wakeup to fully support HNP. These relate to Linux power management interfaces.
    • The host side also needs to define an OTG "Targeted Peripheral List". Each product must define its own such list of "good" devices. Some component should probably also suspend inactive devices, saving power and/or initiating HNP protocol.
  • USB Controller Drivers are in Linux 2.6.8 and later OMAP kernels:
    • Responsibility for USB initialization belongs to the board-specific INIT_MACHINE call. This knows about chip-specific setup and creates platform devices as needed, making platform_data available to the various USB controller drivers.
    • Core OTG protocol support is wrapped in a otg_transceiver object. On H2, the isp1301_omap driver ties the transceiver the OMAP OTG controller, and talks to the OHCI and UDC drivers using the usb_bus and usb_gadget programming interfaces. Other boards might need to implement this differently.
    • The UDC needed a new omap_udc driver in the "USB Gadget" framework, providing immediate access to several standard gadget drivers (including Ethernet/RNDIS, Mass Storage, serial/ACM, and more). This UDC is quite full-featured, supporting numerous endpoints, DMA, and isochronous transfers; it can easily implement composite multi-function devices.
    • The OHCI host controller was already supported by Linux 2.6 kernels using ohci_hcd to access a large and growing set of Linux-USB device drivers.

These points are addressed in the rest of this document, in that same order.

Programming Interface Updates

It was a goal to keep these interface changes small, and to have them be useful outside of OTG support where possible. That way the new code paths can get better testing, rather than being used only for (currently uncommon) OTG devices.

In particular, this doesn't change the existing programming models or calls for host side USB (still uses urb and usb_device ) or for peripheral side USB (still uses usb_request and usb_gadget ). At some point it might become desirable to move away from "URB" to a lighter weight model like "usb_request", and maybe to a more symmetric programming interface; but that's not necessary at this time.

Peripheral Side: USB Device Controller

Several OTG state flags, and a few new usb_gadget_*() calls, are all the changes needed in the gadget programming interfaces. The flags support user interface reporting requirements for OTG devices, and the calls support new USB state transitions (some of which are also useful for non-OTG systems). Except for the flag reporting whether the gadget is_otg , the state flags are current only when the gadget driver could participate in HNP: after it receives the SET_CONFIGURATION request, or before it suspends. In addition, if HNP is ever enabled, it can't be disabled without re-enumerating the device.

struct usb_gadget {
...
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;
...
};

/* used by external USB transceiver */
int usb_gadget_vbus_connect(struct usb_gadget *gadget);
int usb_gadget_vbus_disconnect(struct usb_gadget *gadget);

/* call this during SET_CONFIGURATION */
int usb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA);

/* these logically control the USB D+ pullup */
int usb_gadget_connect(struct usb_gadget *gadget);
int usb_gadget_disconnect(struct usb_gadget *gadget);

In addition, usb_gadget_wakeup() is now defined as the way SRP may be invoked. If the device is in a USB suspend state, remote wakeup is used (and OTG peripherals don't always need hosts to enable wakeup). If there's no VBUS power, SRP may be used instead.

There's kerneldoc for all of those, and many of the symbols have the same meaning as in the OTG specification. For example, b_hnp_enable is the device feature flag that may be set by the USB A-Host; if it's set, the B-Peripheral device may be well into an HNP-driven role switch when suspend() is called.

Peripheral Side: Gadget Drivers

To see how those are used in drivers, see the small changes to Gadget Zero which, using omap_udc , were sufficient to pass the USBCV OTG tests. All USB gadget drivers that will be used on OTG-capable hardware should have corresponding changes; at this writing, some of the gadget drivers still haven't been modified to know about OTG.

  • Provide an OTG descriptor in each configuration, when gadget->is_otg is true.
  • Report HNP availability "through the user interface" (printk, LED, etc) at SET_CONFIGURATION
  • Report start of HNP role switch (B-Peripheral to B-Host, or A-Peripheral to A-Host) "through the user interface" as suspend starts.

This framework is currently not set up to handle the SRP-only subset of OTG; that would need another gadget flag. Also, so far there's no gadgetfs support for OTG: OTG feature flags aren't exported to user mode drivers, though user mode drivers can certainly provide OTG descriptors if they know (out of band) that they're appropriate.

Host Side: usbcore

There are several updates that affect host side support for OTG dual-role devices.

OTG Enumeration and the Targeted Peripherals List

USB enumeration (khubd and usb_new_device ) needed updates:

  • When an OTG A-host enumerates an OTG dual-role device, and it's directly connected to a root hub port, it's responsible for setting one of the HNP device features before it issues any SET_CONFIGURATION. For now, it immediately sets b_hnp_enable on the B-Peripheral (unless a_alt_hnp_support is appropriate instead, because it's not on the OTG port).
  • Check the OTG Targeted Peripheral List, which is kept in the drivers/usb/core/otg_whitelist.h file. In addition to a whitelist of device IDs, this holds a single blacklist entry for the OTG HNP test device (which always triggers HNP from a dual-role device).
  • Devices on the whitelist are allowed to configure.
  • Devices not on the whitelist trigger a diagnostic, and normally disable the device. Instead of being disabled, dual-role devices may be immediately switched to host role using HNP, in case this device is on the other's whitelist. (For developer/tester convenience, the "disable" step can be prevented with a Kconfig option.)
  • The OTG controller driver needs to be able to ask the HCD to start enumeration "immediately", starting at least the port reset before a one millisecond HNP timer expires.

So that the updated enumeration code can set OTG device features appropriately, the usb_bus interface reports which port has the Mini-AB connector. It also provides more visibility of key HNP protocol state, reporting if this is a B-Host rather than an A-Host (so that it shouldn't set OTG device features during enumeration); and whether the A-Host has set b_hnp_enable on the B-Peripheral (needed by OTG controllers and drivers). (This information is not currently visible in sysfs.)

struct usb_bus {
...
u8 otg_port; /* 0, or index of OTG/HNP port */
unsigned is_b_host:1; /* true during some HNP roleswitches */
unsigned b_hnp_enable:1; /* OTG: did A-Host enable HNP? */
...
};

CONFIG_USB_SUSPEND

The CONFIG_USB_SUSPEND patch adds generic experimental support for USB suspend/resume to Linux, as needed to implement HNP.

/* selective suspend/resume */
extern int usb_suspend_device(struct usb_device *dev, u32 state);
extern int usb_resume_device(struct usb_device *dev);

你可能感兴趣的:(linux,struct,features,interface,Descriptor,initialization)