Linux-USB Gadget(小玩意) API Framework(框架)
Last Modified: 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 basicconnectivity(连通性) 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 ordebugging(调试以排除故障) 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 kernel.org as tarballs, or from vendors supportingcustomized(自定义) 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 frameworkimprovements(改进).) 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.
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 USBspecification(规格) 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 anoptional(可选择的) 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.
- 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; simple gadget drivers may no longer need hardware-specific logic(逻辑).
- Convenience functions make it easier to test which of the currently configured(配置) controller chips is being used.
Other recent updates have included support for "soft connect", where the gadget driver controls the pullup(引体向上) used in enumeration(列举); declaringallowable(许可的) power consumption(消费), helping control things like battery recharge(再充电) rates; supporting external(外部的) transceiver(收发器) that sense VBUSsessions(会议); and peripheral-side OTG features(特色).
Controller Drivers
Drivers for several different usb device chips are available. Unless otherwise noted, these are full speed controllers. Many of the chips mentioned are highlyintegrated(完整) 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 NetChip net2280 supports high speed (40+ MByte/sec) and full speed (1.2 MByte/sec) USB through PCI (net2280, in 2.4 and 2.6 kernels(核心))
- Intel's PXA 25x and IXP4xx XScale/ARMv5TE processors(处理器) as seen in many PDAs (pxa2xx_udc, in 2.6 kernels with a 2.4 version available)
- Renesas SH3 processors: SH7705, SH7727 (superh_udc, 2.4 version available)
- Toshiba TC86c001 "Goku-S", on PCI (goku_udc, in 2.4 and 2.6 kernels)
- MediaQ 11xx, as found in the Dell Axim X5 PDA (mq11xx_udc, 2.6 version available)
- Hynix HMS30C7202 ARMv4 processors(处理器) (h7202_udc, 2.6 and 2.4 versions available from Pengutronix)
- National 9603/4 (n9604_udc, 2.4 version available)
- Texas Instruments OMAP processors, including ARMv5TEJ models (omap_udc, in 2.6 kernel(核心)) with USB OTG capabilities.
- Sharp LH7A40x ARMv4T processors (lh7a40x_udc, in 2.6 kernel)
- Samsung S3C2410 ARMv4T processors (s3c2410_udc, 2.6 version in use with Ipaq h1940)
- Atmel AT91 ARMv4T and ARMv5TEJ processors (at91_udc, a 2.6 version)
- Intel PXA 27x XScale/ARMv5TE processors(处理器) (pxa27x_udc, 2.6 version in development)
- The dummy_hcd driver simulates(模仿) a host-to-peripheral USB link within one kernel(核心); it can be a huge help when developing new gadget(小玩意) drivers.
- Mentor(指导者) Graphics supplies a preliminary(准备) GPL'd high speed stack, building on the gadget API and used with chips integrating(完整) their silicon(硅)design. (But not, at this writing, supporting USB OTG on Linux 2.6 kernels.)
- For Texas Instruments parts including the DaVinci tms320dm644x, TUSB 6010, and OMAP 2430, there's a much more robust(强健的) fork of that Mentor code. It's all but a rewrite, and supports high speed host-only, peripheral-only, and OTG modes.
- Netchip 2272, high speed, used in some uClinux systems (notably(值得注意的), it's integrated into some Blackfin distributions(分布))
- Atmel at32ap7000, high speed, the initial implementation(实现) of the new AVR32 system-on-chip platform.
- Freescale's highspeed(高速的) dual-role controller, integrated in at least the MPC834x PPC based system-on-chip.
- ... and others not listed here
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 changeconfigurations(配置), 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 supportisochronous(等时的) 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 Classspecifications(规格).
Gadget Drivers
At this writing there are several public "gadget(小玩意) drivers", each implementing(实施) a single common USB function so it will work with virtually(事实上) any USBperipheral(外围的) 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.
- Gadget Zero ... is essential for controller driver testing. It provides two configurations(配置): one for bulk(体积) traffic source/sink, and another for bulk traffic loopback(回送). On the device side it helps verify(核实) that the driver stack(堆) pass USB-IF and other tests (needed for at least USB branding). On thehost side it helps test the USB stack, such as the Linux-USB HCDs and usbcore. If built as a module, start it by modprobe g_zero; no other initialization(初始化)is needed. (Use the autoresume=N module parameter(参数) to make it try triggering(引发) remote(遥远的) wakeup(唤醒) N seconds after it's suspended(暂停).)
- Ethernet over USB ... the USB peripheral will enumerate(列举) to the host as an Ethernet device(装置), using the "usbnet" driver with Linux hosts or Microsoft's RNDIS driver with Windows hosts. Set it up like any other two-host Ethernet link; bridging it to the LAN from the USB host may be the easiest way to run. Linux hosts do this with CONFIG_BRIDGE and tools like "brctl". Windows XP hosts have a GUI for bridging; it comes up when the RNDIS driver creates a second network link.
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:
- CDC Ethernet ... the Communications Device Class (CDC) "Ethernet Model" protocol(协议) is the standard way for USB devices to expose Ethernet stylefunctionality(功能), with full specifications(规格) available at www.usb.org. Linux hosts prefer using CDC Ethernet; they use a class driver, and don't need vendor-specific updates. Most non-Linux hosts support CDC Ethernet, although to use it with MS-Windows you need a non-Microsoft driver.
- CDC Subset ... this minimalist(极简抽象派艺术的) protocol(协议) is used with controllers where hardware(计算机硬件) limitations(限制) (no altsetting support) prevent use of CDC Ethernet. Two examples of such controllers are the PXA25x and SuperH UDCs. The Linux "usbnet" driver handles this, but since it's not a standard class it might need vendor-specific updates. Few non-Linux hosts support this protocol.
- RNDIS ... when talking to MS-Windows hosts, RNDIS is used. RNDIS is Microsoft's analogue(类似物) of CDC Ethernet, with complex(复杂的) frame(框架)encapsulation(封装) and its own internal(内部的) RPC protocol. (This overview may help you, and a partial(局部的) protocol specification(规格) is available. For example, some requests from Windows 2000 and XP are undocumented.) Use the Documentation(文件材料)/usb/linux.inf file (convert(转变) to DOS CRLF format) to "install(安装)" the driver; the driver is bundled(捆绑的) in XP, and the url in linux.inf says where to get Microsoft's drivers for older Windows releases. For some step-by-step(按部就班的) instructions with WinXP screenshots(画面), see the gumstix wiki showing one way to use that "linux.inf" file. Don't forget to read the comments there, explaining how to shorcut past some needless(不必要的) complications(并发症) in those instructions.
To better support DHCP, ZCIP, and related network autoconfiguration, you'll want to manage Ethernet addresses so that each peripheral(外围的) reuses the sameunique(独特的) 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 bootfirmware(固件) 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
- GadgetFS ... since not every developer wants to program in the kernel(核心), or rely(依靠) specifically(特别地) on the Linux kernel APIs, a user mode API is available. An example user mode driver is usb.c. (It also needs usbstring.c and usbstring.h.) Notice how the device(装置) is initialized(初始化) by writing itsconfiguration(配置) and device descriptors(描述符号) to a file (such as /dev/gadget/$CHIP), and how the endpoints(端点) are initialized in similar ways (writing descriptors to /dev/gadget/$ENDPOINT). After initializing them, just read or write to the files to transfer(转让) data; or to handle events including control requests to retrieve(检索) string descriptors, configure(安装) alternate(交替) settings, and implement(实施) class or vendor(卖主) requests. On Linux 2.6 AIO (Async I/O) support is available, helping user mode drivers avoid i/o latencies(潜伏) and letting them stream data as quickly as in-kernel drivers can stream it.Note that user mode gadget(小玩意) drivers do not necesarily need to be licensed according to the GPL.
- Mass Storage Gadget ... implements the USB Mass Storage class, appearing to the host as a SCSI disk drive. This uses a file or block device as a backing store for the drive, like the "loop(环)" driver. (Read about how to set up the backing store.) The 2.6 version also lets you change the backing file associated(交往)with a given LUN. For example, you might specify(指定) the block device for an MMC card when that card is inserted (maybe using a hotplug script, or a GUI). Note that for MS-Windows interoperability(互操作性), your backing store needs to be formatted(格式化) with a DOS partition(划分) label(标签). Data partitions can then be formatted with VFAT (for the widest interoperability) or some other filesystem (such as ext3 or reiserfs, for use with Linux).
- Serial ... this exposes a tty style serial(连续的) line interface(界面), usable(可用的) with Minicom and similar tools. (There's no serial console(控制台)support at this time.) Most Linux hosts can talk to this using the generic(类的) usb-serial driver. The latest versions of this driver implement the CDC ACM class, as might be implemented by a cell phone or other modem. This driver works with the MS-Windows usbser.sys driver, the Linux cdc-acm driver, and many other USB Host systems. The 2.6.10 kernel(核心) has a detailed Documentation(文件材料)/usb/gadget(小玩意)_serial(电视连续剧).txt file with information on how to set up this driver with both Windows and Linux systems.
- MIDI ... this exposes an ALSA MIDI interface(界面), which will appear in /proc/asound/cards with both recording and playback(重放) support. On the gadget side, open the MIDI gadget like any other ALSA MIDI device(装置). Then you can write events to the host, or read them from the host.
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 orperipheral(外围的) 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:
- HID driver (userspace, with gadgetfs),
- "MTP" (Media Transfer Protocol, PTP++) driver (userspace, with gadgetfs),
- two different printer class drivers (used in various products),
- audio class driver (very experimental(实验的)).
- video class driver (very experimental).
Contributing
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.
Thanks!
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.
出自http://www.linux-usb.org/gadget/