Linux Device Drivers (3rd Edition) [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Linux Device Drivers (3rd Edition) [Electronic resources] - نسخه متنی

Jonathan Corbet, Greg Kroah-Hartman, Alessandro Rubini

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید








13.1. USB Device Basics


A USB device is a very complex thing, as described in the official
USB documentation (available at http://www.usb.org). Fortunately, the Linux
kernel provides a subsystem called the USB
core
to handle most of the complexity. This chapter
describes the interaction between a driver and the USB core. Figure 13-1 shows how USB devices
consist of configurations, interfaces, and endpoints and how USB
drivers bind to USB interfaces, not the entire USB device.


Figure 13-2. USB device overview


13.1.1. Endpoints


The most basic form of
USB
communication is through something called an
endpoint. A USB endpoint can carry data in
only one direction, either from the host computer to the device
(called an OUT endpoint) or from the device to
the host computer (called an IN endpoint).
Endpoints can be thought of as unidirectional pipes.

A USB endpoint can be one of four different types that describe how
the data is transmitted:

CONTROL


Control endpoints are used to allow access to different parts of the
USB device. They are commonly used for configuring the device,
retrieving information about the device, sending commands to the
device, or retrieving status reports about the device. These
endpoints are usually small in size. Every USB device has a control
endpoint called "endpoint 0" that
is used by the USB core to configure the device at insertion time.
These transfers are guaranteed by the USB protocol to always have
enough reserved bandwidth to make it through to the device.


INTERRUPT


Interrupt endpoints transfer small amounts of data at a fixed rate
every time the USB host asks the device for data. These endpoints are
the primary transport method for USB keyboards and mice. They are
also commonly used to send data to USB devices to control the device,
but are not generally used to transfer large amounts of data. These
transfers are guaranteed by the USB protocol to always have enough
reserved bandwidth to make it through.


BULK


Bulk endpoints transfer large amounts of data. These endpoints are
usually much larger (they can hold more characters at once) than
interrupt endpoints. They are common for devices that need to
transfer any data that must get through with no data loss. These
transfers are not guaranteed by the USB protocol to always make it
through in a specific amount of time. If there is not enough room on
the bus to send the whole BULK packet, it is split up across multiple
transfers to or from the device. These endpoints are common on
printers, storage, and network devices.


ISOCHRONOUS


Isochronous endpoints also transfer large amounts of data, but the
data is not always guaranteed to make it through. These endpoints are
used in devices that can handle loss of data, and rely more on
keeping a constant stream of data flowing. Real-time data
collections, such as audio and video devices, almost always use these
endpoints.



Control and bulk endpoints are used for asynchronous data transfers,
whenever the driver decides to use them. Interrupt and isochronous
endpoints are periodic. This means that these endpoints are set up to
transfer data at fixed times continuously, which causes their
bandwidth to be reserved by the USB core.

USB endpoints are described in the kernel with the structure
struct usb_host_endpoint. This
structure contains the real endpoint information in another structure
called struct
usb_endpoint_descriptor. The latter structure
contains all of the USB-specific data in the exact format that the
device itself specified. The fields of this structure that drivers
care about are:

bEndpointAddress


This is the USB address of this specific endpoint. Also included in
this 8-bit value is the direction of the endpoint. The bitmasks
USB_DIR_OUT and USB_DIR_IN can
be placed against this field to determine if the data for this
endpoint is directed to the device or to the host.


bmAttributes


This is the type of endpoint. The bitmask
USB_ENDPOINT_XFERTYPE_MASK should be placed
against this value in order to determine if the endpoint is of type
USB_ENDPOINT_XFER_ISOC,
USB_ENDPOINT_XFER_BULK, or of type
USB_ENDPOINT_XFER_INT. These macros define a
isochronous, bulk, and interrupt endpoint, respectively.


wMaxPacketSize


This is the maximum size in bytes that this endpoint can handle at
once. Note that it is possible for a driver to send amounts of data
to an endpoint that is bigger than this value, but the data will be
divided up into wMaxPacketSize chunks when
actually transmitted to the device. For high-speed devices, this
field can be used to support a high-bandwidth mode for the endpoint
by using a few extra bits in the upper part of the value. See the USB
specification for more details about how this is done.


bInterval


If this endpoint is of type interrupt, this value is the interval
setting for the endpointthat is, the time between interrupt
requests for the endpoint. The value is represented in milliseconds.



The fields of this structure do not have a
"traditional" Linux kernel naming
scheme. This is because these fields directly correspond to the field
names in the USB specification. The USB kernel programmers felt that
it was more important to use the specified names, so as to reduce
confusion when reading the specification, than it was to have
variable names that look familiar to Linux programmers.


13.1.2. Interfaces


USB endpoints are bundled up

into
interfaces. USB interfaces handle only one
type of a USB logical connection, such as a mouse, a keyboard, or a
audio stream. Some USB devices have multiple interfaces, such as a
USB speaker that might consist of two interfaces: a USB keyboard for
the buttons and a USB audio stream. Because a USB interface
represents basic functionality, each USB driver controls an
interface; so, for the speaker example, Linux needs two different
drivers for one hardware device.

USB interfaces may have alternate settings, which are different
choices for parameters of the interface. The initial state of a
interface is in the first setting, numbered 0.
Alternate settings can be used to control individual endpoints in
different ways, such as to reserve different amounts of USB bandwidth
for the device. Each device with an isochronous endpoint uses
alternate settings for the same interface.

USB interfaces are described in the kernel with the
struct usb_interface structure.
This structure is what the USB core passes to USB drivers and is what
the USB driver then is in charge of controlling. The important fields
in this structure are:

struct usb_host_interface *altsetting


An array of interface structures containing all of the alternate
settings that may be selected for this interface. Each
struct usb_host_interface
consists of a set of endpoint configurations as defined by the
struct usb_host_endpoint
structure described above. Note that these interface structures are
in no particular order.


unsigned num_altsetting


The number of alternate settings pointed to by the
altsetting pointer.


struct usb_host_interface *cur_altsetting


A pointer into the array altsetting, denoting the
currently active setting for this interface.


int minor


If the USB driver bound to this interface uses the USB major number,
this variable contains the minor number assigned by the USB core to
the interface. This is valid only after a successful call to
usb_register_dev (described later in this
chapter).



There are other fields in the struct
usb_interface structure, but USB drivers do not
need to be aware of them.


13.1.3. Configurations


USB interfaces are t

hemselves bundled up into
configurations. A USB device can have multiple
configurations and might switch between them in order to change the
state of the device. For example, some devices that allow firmware to
be downloaded to them contain multiple configurations to accomplish
this. A single configuration can be enabled only at one point in
time. Linux does not handle multiple configuration USB devices very
well, but, thankfully, they are rare.

Linux describes USB configurations with the structure
struct usb_host_config and
entire USB devices with the structure struct
usb_device. USB device drivers do not generally
ever need to read or write to any values in these structures, so they
are not defined in detail here. The curious reader can find
descriptions of them in the file
include/linux/usb.h in the kernel source tree.

A USB device driver commonly has to convert data from a given
struct usb_interface structure
into a struct usb_device
structure that the USB core needs for a wide range of function calls.
To do this, the function interface_to_usbdev is
provided. Hopefully, in the future, all USB calls that currently need
a struct usb_device will be
converted to take a struct
usb_interface parameter and will not require the
drivers to do the conversion.

So to summarize, USB devices are quite complex and are made up of
lots of different logical units. The relationships among
these units can be simply described as follows:

  • Devices usually have one or more configurations.

  • Configurations often have one or more interfaces.

  • Interfaces usually have one or more settings.

  • Interfaces have zero or more endpoints.



    / 202