8 June 2005
The <linux/usb_gadget.h> 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 Net2280 PCI card lets you work on a standard PC, developing or debugging gadget drivers on computers you may already own.
The API and several supporting drivers are included in current 2.4 and 2.6 Linux kernels, available through kernel.org as tarballs, or from vendors supporting customized Linux distributions. The BitKeeper 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 handhelds.org 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 <linux/usb_*.h> 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.
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:
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 information about OTG on Linux 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 pre-generated version (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.
Other recent updates have included support for "soft connect", where the gadget driver controls the pullup used in enumeration; declaring allowable power consumption, helping control things like battery recharge rates; supporting external transceiver that sense VBUS sessions; and peripheral-side OTG features.
Drivers for several different usb device chips are available. Unless otherwise noted, these are full speed controllers. Many of the chips mentioned are highly integrated System-on-Chip (SOC) processors, typically integrating a 32-bit CPU core with cores for USB and numerous other features (such as signal processors) and optimized for efficient use on battery power. There are also several discrete USB controllers.
The controller driver is responsible for handling only a very few of the standard USB control requests, affecting device and endpoint state. (Those requests are frequently handled in hardware.) All other control requests, notably ones to return descriptors and change configurations, are delegated to the gadget driver. Another key responsibility of the controller driver is managing each endpoint's I/O queue, transferring data between the hardware and the gadget driver's buffers (often using DMA).
Certain hardware-specific attributes are visible through this API, since they can affect how gadget drivers must act. These are tested using gadget_is_*() macros, which work much like similar CPU and board testing macros; they frequently evaluate to "false" at compile-time. Not all controllers support isochronous transfers, as needed for audio and video class drivers. Most controllers support at least two bulk/interrupt endpoints, but ones with at least five such endpoints are usually needed to implement multi-function ("composite") devices. Hardware sometimes restricts how software can manage device configurations, in ways that may prevent implemention of multi-function devices, multi-configuration ones, or certain standard USB Device Class specifications.
At this writing there are several public "gadget drivers", each implementing a single common USB function so it will work with virtually any USB peripheral controller. (Drivers for composite gadgets, or for audio/video drivers requiring isochronous transfers, would not be able to work on at least some controller hardware. The gadget API does support such drivers.) You should plan on testing these in conjunction with the controller driver and system board you'll be using.
bash# : this implicitly loads the usb controller driver, and helps bash# : hosts use host_addr in config databases (win32 registry etc) bash# modprobe g_ether host_addr=00:dc:c8:f7:75:05 dev_addr=00:dd:dc:eb:6d:f1 bash# bash# : connect the device. bash# : then use dhcp, zcip or static configuration: bash# ifconfig usb0 10.0.0.105 bash# ip addr show usb0 2: usb0: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 100 link/ether 00:dd:dc:eb:6d:f1 brd ff:ff:ff:ff:ff:ff inet 10.0.0.105/8 brd 10.255.255.255 scope global usb0 bash# bash# : traffic will flow when the usb host is ready too bash#
This driver can interoperate with hosts running Linux, MS-Windows, and other operating systems; if the OS can talk to a cable modem, it probably supports this driver. To do this, it supports several modes:
To better support DHCP, ZCIP, and related network autoconfiguration, you'll want to manage Ethernet addresses so that each peripheral reuses the same unique address every time it boots. You should assign those addresses using a registered IEEE 802 company id; this will also make the device appear to Linux hosts as an "ethN" interface, not as "usbN". It's easy to do this without a separate ID PROM (or an initrd) if you're using boot firmware like U-Boot:
# manufacturing assigns Ethernet addresses; company id is xx:xx:xx setenv eth_a_host xx:xx:xx:01:23:45 setenv eth_a_gadget xx:xx:xx:67:89:ac setenv eth_i_vendor "Great Stuff, LLC" setenv eth_i_product "Our Cool Thing" setenv eth_args g_ether.host_addr=\$(eth_a_host) setenv eth_args $(eth_args) g_ether.dev_addr=\$(eth_a_gadget) setenv eth_args $(eth_args) g_ether.iManufacturer=\$(eth_i_vendor) setenv eth_args $(eth_args) g_ether.iProduct=\$(eth_i_product) # you can assign USB vendor/product/version codes too... setenv add_eth_args setenv bootargs $(eth_args) \$(bootargs) ... setenv bootcmd run add_eth_args\;bootm
That list doesn't yet include a dedicated file sharing protocol; for now, use NFS or SAMBA over an ethernet style link. A solution that's simpler to configure might use the USB-IF Still Image Capture Device class specification, which presents a hierarchical filesystem as well as some operations specific to cameras (setting focal length, shutter speed, etc) and capturing images. It builds on the "Picture Transfer Protocol" (PTP), which is supported both for GNU/Linux and Microsoft Windows. At this writing, there is no Linux kernel implementation of PTP on either host or peripheral side. However, there are host side user-mode implementations, such as gPhoto2.
Other controller and gadget drivers are in development, but are unreleased or not published here. Examples that have seen some degree of light include:
Yes, please! Bug fixes, gadget drivers (especially "class" drivers), and new USB device controller drivers will all be of interest. Discussions, patches, and similar work should be on the linux-usb-devel mailing list for now.
This work has been supported by patches, feedback, bug reports, hardware, and other contributions from many groups and individuals. Of particular note are NetChip Technology Inc, Agilent Technologies, Intel Corporation, Pengutronix, MontaVista Software, Auerswald GmbH, Texas Instruments, handhelds.org, Alan Stern, Al Borchers, Julian Back, David Meggy, gumstix, Andrew Zabolotny, Dmitry Krivoschokov, Hewlett-Packard Laboratories, and everyone who's contributed a patch or other feedback through the Linux-USB community.