Linux-USB Gadget API Framework
Last Modified: 8 June 2005
The API makes it easy for peripherals and other devices embedding GNU/Linux system software to act in the USB "device" (slave) role. The drivers implementing and using that API combine to make a useful driver framework for Linux systems that implement USB peripherals. Many Linux systems will not be able to use it, since they only have PC-style USB Host (master) hardware in a PC, workstation, or server. But when you're putting together embedded Linux systems, a USB peripheral controller option is routine; it's often integrated into processors. Smart gadgets like PDAs, printers, cell phones, cash registers, and network routers often rely on this type of "Device Controller" USB link as one of their basic connectivity options. Sometimes it will be the only option; there are Linux devices that rely on USB even for their power supplies.
This is the first such "USB Gadget" framework on GNU/Linux to support high speed (USB 2.0) devices and arbitrary numbers of endpoints, sharing core models and data structures with the "host side" USB API. It's designed for flexibility: the API handles simple devices, composite (multi-function) ones, multiple configurations, class (or vendor) specific functionality, and more. It a good base for integrating and re-using this type of driver code. Tests are available too, which can speed hardware bringup substantially.
Many developers have asked about easy ways to start working with this API. If you're comfortable working with embedded Linux platforms, many ARM systems already have Linux support for their integrated USB controllers. Otherwise, a lets you work on a standard PC, developing or debugging gadget drivers on computers you may already own.
Getting the Code
The API and several supporting drivers are included in current 2.4 and 2.6 Linux kernels, available through as tarballs, or from vendors supporting customized Linux distributions. The trees are no longer current, but the "mm" patchsets or various other GIT trees may well have more current code than the current mainstream kernel.
There may be other public trees with controller or gadget drivers too. The website includes pointers to a number of these; a USB network link can be extremely useful. Kernel trees that support specific System-on-Chip platforms often include a driver for that platform's USB Peripheral Controller.
The "gadget" framework is available in 2.6 kernels, as well as 2.4.23 and later. (2.4.27 is the first 2.4 kernel to bundle RNDIS support, and some other framework improvements.) At this writing, other than architecture- or board-specific setup, and the header files, all the gadget code is in the drivers/usb/gadget directory. It's easy to backport current 2.4 gadget code (e.g. 2.4.31) onto older 2.4 kernels. Most new development is based on 2.6 kernels; differences relevant to 2.4 based development are minor, mostly limited to kernel configuration and the 2.6 kernel's "generic DMA" and "driver model" infrastructure. Some 2.4 vendor kernels already include some of that code, making 2.6 backports even easier.
Parts of the Framework
The API standardizes a platform-neutral boundary between two software layers, but the software stack usually has several higher layers. The framework includes that API, some support software, and several drivers on each side of that API boundary, integrating well with other Linux subsystems. From the bottom up, those layers are:
- Peripheral Controller Drivers implement the gadget API, and are the only layers that talk directly to hardware. Different controller hardware will need different drivers, which may also need board-specific customization. These provide a software "gadget" device, visible in sysfs. You can think of that device as being the virtual hardware to which the higher level drivers are written. Other operating systems use other names for this component, perhaps labeling the API plus its libraries as a "Platform Independent Layer" and its implementation as a "Platform Specific Layer".
- Gadget Drivers use that gadget API, and can often be written to be hardware-neutral. Certain hardware facts need to affect the implementation of configuration management parts of ep0 logic. Those issues may be handled at various points: build time, initialization time, or run time. For example, some controllers have more endpoints than others, many don't support high speed or isochronous transfers, and sometimes endpoints have fixed configurations. A gadget driver implements one or more "functions", each providing a different capability to the USB host, such as a network link or speakers. Other operating systems use other names for this component, such as a "USB Client driver". (These are directly analagous to host side "interface drivers", except for multi-function "composite" gadget drivers.)
- Upper Layers, such as the network, file system, or block I/O subsystems. These generate and consume the data that the gadget driver transfers to the host through the controller driver. There will often be several such layers, perhaps including user mode components. (Again, this is directly analagous to what host side drivers do, though producer and consumer roles are probably reversed.) On most hardware, several different layers can be fed by the gadget driver at the same time. For example, the functions on a composite device might give hosts concurrent access to local audio, internet, and file servers.
There are two other components worth mentioning. The first is a layer that doesn't exist: a "mid layer", like the host-side "usbcore" (which is what the USB specification calls "USBD"). The USB host side needs such a layer to multiplex potentially hundreds of peripherals and drivers; the peripheral side has no such requirement. The Linux-USB host-side and peripheral-side driver stacks are directly analagous, except that only the host side has a mid layer. (The APIs are of course different; the peripheral side is much lower overhead, and serves a "slave" role not a "master" one.) The second is an optional component that exists only in USB-OTG systems: an OTG Controller Driver, switching control of the USB port between the gadget stack (as summarized above) and the USB host stack. (More is available.) "Layer cake" style architecture diagrams would put an OTG Controller Driver below the USB Peripheral and Host Controller Drivers, talking to both of those drivers as well as specialized hardware.
The Linux 2.6 kernel tree includes kerneldoc for this API, including a structural overview as well as API reference. You can generate a current version of that yourself directly with commands like "make pdfdocs", or use a (which may not be as up-to-date as what you make from current kernel sources).
Recent versions of this API have improved and grown the collection of gadget driver library helper functions. These aren't a separate library or midlayer, they're just object files optionally linked with gadget drivers that want their functions.
- The string descriptor utilities now do UTF-8 to UTF-16LE conversion, making it easy to support languages that don't use ISO-8859-1.
- Configuration buffer utilities combine null-terminated lists of USB descriptors, so it's easier to work with multiple or complex configurations. (USB Wireless Mobile class devices use such configurations.)
- Endpoint autoconfiguration hides some hardware-specific initialization issues from gadget drivers, such as endpoint addressing;