Embedded 版 (精华区)

发信人: Zinux (Linux技工), 信区: Embedded_system
标  题: USB Device Drivers
发信站: 哈工大紫丁香 (2001年10月26日18:23:44 星期五), 转信

发信站: 武汉白云黄鹤站 (2001年08月10日12:54:25 星期五), 站内信件

Linux Magazine (http://www.linux-mag.com) July 2000



Copyright Linux Magazine ?2000



GEARHEADS ONLY
USB Device Drivers
by Alessandro Rubini

Figure One: A simple USB layout consisting of a PC with a USB keyboard
and mouse, as well as an associated USB tree.
The Universal Serial Bus, or USB, is a new type of peripheral
interconnect that has become popular in recent years and is now
standard equipment on most PCs and laptops. USB is an external
interface, in that USB devices plug into ports outside of your PC's
case; this is as opposed to internal interfaces, such as PCI.
case; this is as opposed to internal interfaces, such as PCI.

USB has a number of attractive features. First, it is multiplatform,
so USB devices work across different types of host hardware (for
example, Intel-based PCs as well as Macintosh computers). Second, USB
devices are both hot-swappable and "plug and play" -- not only can you
add and remove USB devices while the machine is running, but the
devices automatically configure themselves to use particular port and
interrupt numbers, saving the user from having to do this
configuration. USB can support up to 127 devices plugged into the host
using a tree structure.

USB devices connect to the host using standardized cables that carry
both power and data; the data link rate is 12 Mbits/sec with an
optional "low cost" link rate of 1.5 Mbit/ sec. The lower link rate is
intended for devices that don't require the full bandwidth and can be
made more cheaply (in part because less EMF protection is required at
the lower signalling rate).

USB is a standard backed by most major hardware manufacturers,
including Compaq, Intel, Microsoft, and NEC. If you want more
information, you can find details and the specification at
http://www.usb.org/.
http://www.usb.org/.

Until recently, the Linux kernel had no support for USB devices.
However, experimental USB support has been available since the Linux
2.2.7 kernel tree. The latest developments in USB are going on in the
2.3.x trees, and Linux 2.4 should be available sometime in the fall,
complete with USB support.

This discussion is based on version 2.3.99-pre3 of the Linux kernel,
the one that is current at time of this writing. I expect there to be
little or no differences between this version and the 2.4 version that
will be released in a few months. I chose to compile the USB subsystem
as modules and discuss the role of individual modules. The modularized
form makes it easier to understand the overall design, as compared to
a kernel with the whole USB subsystem linked in.

A USB device is still, at its lowest levels, a "character device" or a
"block device," but the programming interface offered to device-driver
writers has been simplified in order to take advantage of the common
hardware features offered by those devices, and to offer arbitration
of the bus and coordination in its use by the various drivers. We will
explore the concepts behind USB on a theoretical level this month, and
next month we will build on these ideas with some actual code-based
next month we will build on these ideas with some actual code-based
examples.




A Quick Tour of the Hardware

While USB stands for Universal Serial Bus, its physical structure is
not a bus, but rather a tree. Each transmission link can only connect
two nodes, called the "upstream" and "downstream" nodes, respectively.

To make the distinction clearer and to avoid endless cabling problems
like those we are accustomed to daily with serial interfaces, the USB
specification requires different connectors at the upstream and the
downstream end of the cables. What you see lurking in the back of your
computer is not "the USB connector" but rather "the upstream USB
connector," which can also be referred to as type "A."

Each non-leaf node in the tree is a USB hub. The host controller (the
hardware that is installed in the computer) implements a USB hub, as
this is the only way to spit out several communication channels toward
USB devices.
USB devices.


Figure Two: A "text-book" overly complex USB layout including hubs and
other peripherals in addition to a keyboard and mouse.
To preserve the tree structure, it is not possible for a device to
have two upstream connections -- while there exist USB devices that
can interconnect two computers by connecting to two different USB
busses, those devices are conceptually two separate USB peripherals,
each connected to its own bus. Figure One and Figure Two (pg. 82)
depict two typical USB environments -- simple and complex --with their
respective physical structures represented as trees.

As far as the host controller is concerned, all the implementations
currently fall under one of two classes: "Open Host Controller
Interface" (OHCI) and "Universal Host Controller Interface" (UHCI). In
Linux you can thus choose between two device drivers for your USB
subsystem: usb-ohci.o and usb-uhci.o. Also, the module usbcore.o is
required no matter what hardware you happen to have.

When a device is plugged into the bus, it identifies itself to the
system as one of several classes of peripherals; in order to use the
device you'll need to load a driver that claims ownership of that
device you'll need to load a driver that claims ownership of that
device and handles the associated communication protocol.

The USB protocol allows for a variety of device types and bandwidth
usage. To keep the discussion simple, I'll only stick to simple input
devices, like mice and keyboards. Those devices don't need a sustained
data rate or strict timing, so are the easiest to understand, as well
as the most commonly used.

The Various Modules and Their Interrelations


Figure Three: The various dependencies of the different Linux kernel
modules when the USB subsystem is compiled in modules.
When you compile the USB Linux subsystem as modules, you'll end up
with several kernel modules. While the internal communication among
them is somewhat complex, the dependencies of the modules are quite
straightforward, as depicted in Figure Three. Table One lists the main
entry points exported and used by each module.





Table One: Main Entry Points Exported and Used by Each Module

Module Symbols Exported by the Module Symbols Used at Load and Run
Time
usbcore.o
 usb_register()
usb_connect()
usb_alloc_bus();
usb_alloc_dev();
 usb_deregister();
usb_disconnect();
usb_free_bus();
usb_free_dev();
 register_chrdev();
register_filesystem();
kernel_thread();

usb-ohci.o
 --  pci_find_class();
request_irq();
usb_alloc_bus();
usb_alloc_dev();
usb_alloc_dev();

input.o
 input_register_device();
input_open_device();
input_event();
 input_unregister_device();
input_close_device();

keybdev.o
 --   input_register_handler();

mousedev.o
 --  input_register_handler();

usbmouse.o
 --  usb_register();
usb_submit_urb()
input_register_device();
input_event();

usbkbd.o
 --  usb_register();
 --  usb_register();
usb_submit_urb()
input_register_device();
input_event();


As shown, the usbcore module offers all the software infrastructure
needed for hardware handling while input offers a generic
input-management framework; all other modules stack on those two,
registering as either producers or consumers of information.

As far as hardware is concerned, the host controller device driver
(ohci or uhci) registers its functionality within usbcore's data
structures, as do the device-specific drivers (for example, usbmouse
and usbkbd). Their role differs in that the host controller produces
information (collected from the wire) while the other drivers consume
information (by decoding the data and pushing it to its final
destination).

Input management operates in a similar way: hardware drivers (usbmouse
and usbkbd) produce data and the generic input handlers (mousedev and
keybdev) consume data. Both kinds of modules stack on input.o,
registering their own entry points.
registering their own entry points.

The question still unanswered is how can a module push information to
another module by only registering a callback. If you are comfortable
with generic kernel drivers, you'll remember that things are usually
set up the other way around: the consumer module registers its
callback to be invoked whenever there is new data to consume. The USB
driver is laid out differently because it is designed as a
message-passing environment, instead of being a data-flow system like
most of the Linux kernel. The key data structure, the "message," is
called URB, short for USB Request Block.




How URBs Keep It All Together

When a USB hardware driver is loaded, it calls usb_alloc_ bus() to
register its own usb_operations data structure with usbcore.o (the
data structure is defined in <linux/ usb.h>, as is all other header
material relevant to this article). The registered operations include
submit_urb. and unlink_urb, so the software layer can initiate data
transfer to the hardware driver.
transfer to the hardware driver.

With the software layer and the hardware drivers in place, a specific
peripheral driver (like usbmouse.o) can register its own usb_driver
data structure by calling usb_ register().

The data structure includes pointers to a probe and a disconnect
function. The former is called by the USB framework whenever a new
device is detected and the latter whenever the device is unplugged
from the bus.

When the probe succeeds (i.e., the new USB device can be handled by
this device driver), the function submits its URB structure to the USB
engine (by calling usb_submit_ urb()), including in the URB a pointer
to its "completion handler," a callback that will be invoked at the
end of each hardware transaction.

Within usb_submit_urb, the URB is passed back to the host controller
interface, so that the hardware driver can fill the URB buffers with
relevant information and call the proper completion handler whenever a
data transfer happens.

While this description referred to mice and keyboards, the same design
While this description referred to mice and keyboards, the same design
rules apply to other USB peripheral devices. The difference is mainly
in how the hardware handles the individual transactions: not every
device works like a keyboard or mouse.

A digital video camera, to use one example, will need to push a
sustained data rate into the bus. The USB specification describes
several different transaction types, and all of them are handled by
the USB Linux subsystem using URBs.

Input Handling

Although the issue is not directly related to USB hardware, I think
it's interesting to see how USB input devices, like keyboards and
mice, are designed as part of a more generic input mechanism,
implemented in the source file drivers/ usb/input.c.

As already outlined (and shown in Table One), the USB modules for
keyboards and mice stack on the input module as "producers" of data,
while more generic modules (mousedev and keybdev) stack on input as
consumers of data.

Whenever a USB input driver's completion handler is invoked, it pushes
Whenever a USB input driver's completion handler is invoked, it pushes
the data just received to the input management engine, by calling
input_event().

A "consumer" module registers its own callbacks within input.o, by
calling input_register_handler() at load time. The input_handler data
structure includes pointers to three callbacks: connect, disconnect,
and event -- which are all that's needed for proper device management.
What actually consumes input data is the event handler.

The role of input_event(), as called by the completion function of the
peripheral USB driver, is that of distributing the input data to all
the registered handlers. Each handler will just ignore data it is not
interested in. Thus, if you didn't load keybdev.o, your USB keyboard
will be ignored by the system, even though you loaded the usbkbd
module and key-presses are correctly decoded and passed to the input
engine.

The input handling machinery is very interesting, in my opinion, as it
allows insertion of custom kernel modules in the event chain, both as
producers and consumers of input events.

A new event producer could push keyboard or mouse events down the
A new event producer could push keyboard or mouse events down the
system's chain even though it is not physically a keyboard, while a
new event consumer can associate special actions (any action) to input
events. This provides a flexible tool for people who play with
nonstandard devices or need to implement nonstandard behaviors in
their kernels.

In my next column we'll look at some code-based examples of the USB
module material that we have outlined here. Stay tuned.

Resources

http://www.usb.org/

Contains the USB specification and other interesting information about
USB, including general software issues.

/usr/src/linux/Documentation/usb

This directory documents device-specific aspects of USB support. The
file "URB.txt" is particularly interesting as it thoroughly describes
the URB data structure.


/usr/src/linux/Documentation/usb

This directory documents device-specific aspects of USB support. The
file "URB.txt" is particularly interesting as it thoroughly describes
the URB data structure.

http://linuxusbguide.sourceforge.net/

The "Linux-USB HOWTO." A lot of information on setting up and using
USB under Linux.




--
     .-.
     /v\     L  I  N  U  X
    // \\
   /(   )\   >The World is Linux Powered<
    ^^-^^
    T U X
※ 来源:·武汉白云黄鹤站 bbs.whnet.edu.cn·[FROM: 小百合BBS]


--

  puke! 
  技工而已

※ 来源:·哈工大紫丁香 bbs.hit.edu.cn·[FROM: 202.118.239.152]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:213.270毫秒