最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【转】Linux中USB gadget架构简介

USB crifan 2885浏览 0评论

Linux-USB Gadget API Framework

Last Modified: 8 June 2005
http://www.linux-usb.org/gadget/

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.

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 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.

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 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; declaring allowable power consumption, helping control things like battery recharge rates; supporting external transceiver that sense VBUS sessions; 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 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 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 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.

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 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.

  • 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 the host 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.

    <font face="Arial">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: &lt;BROADCAST,MULTICAST,UP&gt; 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#</font>

    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 style functionality, 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 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:

    <font face="Arial"># manufacturing assigns Ethernet addresses; company id is xx:xx:xx
    setenv eth_a_host    xx:xx:xx:<strong>01:23:45</strong>
    setenv eth_a_gadget  xx:xx:xx:<strong>67:89:ac</strong>
    setenv eth_i_vendor  &quot;Great Stuff, LLC&quot;
    setenv eth_i_product &quot;Our Cool Thing&quot;
    setenv eth_args             g_ether.<strong>host_addr</strong>=$(eth_a_host)
    setenv eth_args $(eth_args) g_ether.<strong>dev_addr</strong>=$(eth_a_gadget)
    setenv eth_args $(eth_args) g_ether.<strong>iManufacturer</strong>=$(eth_i_vendor)
    setenv eth_args $(eth_args) g_ether.<strong>iProduct</strong>=$(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</font>
  • 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 its configuration 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.
  • File-backed Storage … implements the USB Mass Storage class (as CB, CBI, or BBB), 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 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:

  • 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.

转载请注明:在路上 » 【转】Linux中USB gadget架构简介

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
83 queries in 0.149 seconds, using 22.07MB memory