You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
980 lines
38 KiB
980 lines
38 KiB
<?xml version="1.0" encoding="UTF-8"?> |
|
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" |
|
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []> |
|
|
|
<book id="Linux-USB-API"> |
|
<bookinfo> |
|
<title>The Linux-USB Host Side API</title> |
|
|
|
<legalnotice> |
|
<para> |
|
This documentation is free software; you can redistribute |
|
it and/or modify it under the terms of the GNU General Public |
|
License as published by the Free Software Foundation; either |
|
version 2 of the License, or (at your option) any later |
|
version. |
|
</para> |
|
|
|
<para> |
|
This program is distributed in the hope that it will be |
|
useful, but WITHOUT ANY WARRANTY; without even the implied |
|
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
|
See the GNU General Public License for more details. |
|
</para> |
|
|
|
<para> |
|
You should have received a copy of the GNU General Public |
|
License along with this program; if not, write to the Free |
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
|
MA 02111-1307 USA |
|
</para> |
|
|
|
<para> |
|
For more details see the file COPYING in the source |
|
distribution of Linux. |
|
</para> |
|
</legalnotice> |
|
</bookinfo> |
|
|
|
<toc></toc> |
|
|
|
<chapter id="intro"> |
|
<title>Introduction to USB on Linux</title> |
|
|
|
<para>A Universal Serial Bus (USB) is used to connect a host, |
|
such as a PC or workstation, to a number of peripheral |
|
devices. USB uses a tree structure, with the host as the |
|
root (the system's master), hubs as interior nodes, and |
|
peripherals as leaves (and slaves). |
|
Modern PCs support several such trees of USB devices, usually |
|
one USB 2.0 tree (480 Mbit/sec each) with |
|
a few USB 1.1 trees (12 Mbit/sec each) that are used when you |
|
connect a USB 1.1 device directly to the machine's "root hub". |
|
</para> |
|
|
|
<para>That master/slave asymmetry was designed-in for a number of |
|
reasons, one being ease of use. It is not physically possible to |
|
assemble (legal) USB cables incorrectly: all upstream "to the host" |
|
connectors are the rectangular type (matching the sockets on |
|
root hubs), and all downstream connectors are the squarish type |
|
(or they are built into the peripheral). |
|
Also, the host software doesn't need to deal with distributed |
|
auto-configuration since the pre-designated master node manages all that. |
|
And finally, at the electrical level, bus protocol overhead is reduced by |
|
eliminating arbitration and moving scheduling into the host software. |
|
</para> |
|
|
|
<para>USB 1.0 was announced in January 1996 and was revised |
|
as USB 1.1 (with improvements in hub specification and |
|
support for interrupt-out transfers) in September 1998. |
|
USB 2.0 was released in April 2000, adding high-speed |
|
transfers and transaction-translating hubs (used for USB 1.1 |
|
and 1.0 backward compatibility). |
|
</para> |
|
|
|
<para>Kernel developers added USB support to Linux early in the 2.2 kernel |
|
series, shortly before 2.3 development forked. Updates from 2.3 were |
|
regularly folded back into 2.2 releases, which improved reliability and |
|
brought <filename>/sbin/hotplug</filename> support as well more drivers. |
|
Such improvements were continued in the 2.5 kernel series, where they added |
|
USB 2.0 support, improved performance, and made the host controller drivers |
|
(HCDs) more consistent. They also simplified the API (to make bugs less |
|
likely) and added internal "kerneldoc" documentation. |
|
</para> |
|
|
|
<para>Linux can run inside USB devices as well as on |
|
the hosts that control the devices. |
|
But USB device drivers running inside those peripherals |
|
don't do the same things as the ones running inside hosts, |
|
so they've been given a different name: |
|
<emphasis>gadget drivers</emphasis>. |
|
This document does not cover gadget drivers. |
|
</para> |
|
|
|
</chapter> |
|
|
|
<chapter id="host"> |
|
<title>USB Host-Side API Model</title> |
|
|
|
<para>Host-side drivers for USB devices talk to the "usbcore" APIs. |
|
There are two. One is intended for |
|
<emphasis>general-purpose</emphasis> drivers (exposed through |
|
driver frameworks), and the other is for drivers that are |
|
<emphasis>part of the core</emphasis>. |
|
Such core drivers include the <emphasis>hub</emphasis> driver |
|
(which manages trees of USB devices) and several different kinds |
|
of <emphasis>host controller drivers</emphasis>, |
|
which control individual busses. |
|
</para> |
|
|
|
<para>The device model seen by USB drivers is relatively complex. |
|
</para> |
|
|
|
<itemizedlist> |
|
|
|
<listitem><para>USB supports four kinds of data transfers |
|
(control, bulk, interrupt, and isochronous). Two of them (control |
|
and bulk) use bandwidth as it's available, |
|
while the other two (interrupt and isochronous) |
|
are scheduled to provide guaranteed bandwidth. |
|
</para></listitem> |
|
|
|
<listitem><para>The device description model includes one or more |
|
"configurations" per device, only one of which is active at a time. |
|
Devices that are capable of high-speed operation must also support |
|
full-speed configurations, along with a way to ask about the |
|
"other speed" configurations which might be used. |
|
</para></listitem> |
|
|
|
<listitem><para>Configurations have one or more "interfaces", each |
|
of which may have "alternate settings". Interfaces may be |
|
standardized by USB "Class" specifications, or may be specific to |
|
a vendor or device.</para> |
|
|
|
<para>USB device drivers actually bind to interfaces, not devices. |
|
Think of them as "interface drivers", though you |
|
may not see many devices where the distinction is important. |
|
<emphasis>Most USB devices are simple, with only one configuration, |
|
one interface, and one alternate setting.</emphasis> |
|
</para></listitem> |
|
|
|
<listitem><para>Interfaces have one or more "endpoints", each of |
|
which supports one type and direction of data transfer such as |
|
"bulk out" or "interrupt in". The entire configuration may have |
|
up to sixteen endpoints in each direction, allocated as needed |
|
among all the interfaces. |
|
</para></listitem> |
|
|
|
<listitem><para>Data transfer on USB is packetized; each endpoint |
|
has a maximum packet size. |
|
Drivers must often be aware of conventions such as flagging the end |
|
of bulk transfers using "short" (including zero length) packets. |
|
</para></listitem> |
|
|
|
<listitem><para>The Linux USB API supports synchronous calls for |
|
control and bulk messages. |
|
It also supports asynchronous calls for all kinds of data transfer, |
|
using request structures called "URBs" (USB Request Blocks). |
|
</para></listitem> |
|
|
|
</itemizedlist> |
|
|
|
<para>Accordingly, the USB Core API exposed to device drivers |
|
covers quite a lot of territory. You'll probably need to consult |
|
the USB 2.0 specification, available online from www.usb.org at |
|
no cost, as well as class or device specifications. |
|
</para> |
|
|
|
<para>The only host-side drivers that actually touch hardware |
|
(reading/writing registers, handling IRQs, and so on) are the HCDs. |
|
In theory, all HCDs provide the same functionality through the same |
|
API. In practice, that's becoming more true on the 2.5 kernels, |
|
but there are still differences that crop up especially with |
|
fault handling. Different controllers don't necessarily report |
|
the same aspects of failures, and recovery from faults (including |
|
software-induced ones like unlinking an URB) isn't yet fully |
|
consistent. |
|
Device driver authors should make a point of doing disconnect |
|
testing (while the device is active) with each different host |
|
controller driver, to make sure drivers don't have bugs of |
|
their own as well as to make sure they aren't relying on some |
|
HCD-specific behavior. |
|
(You will need external USB 1.1 and/or |
|
USB 2.0 hubs to perform all those tests.) |
|
</para> |
|
|
|
</chapter> |
|
|
|
<chapter id="types"><title>USB-Standard Types</title> |
|
|
|
<para>In <filename><linux/usb/ch9.h></filename> you will find |
|
the USB data types defined in chapter 9 of the USB specification. |
|
These data types are used throughout USB, and in APIs including |
|
this host side API, gadget APIs, and usbfs. |
|
</para> |
|
|
|
!Iinclude/linux/usb/ch9.h |
|
|
|
</chapter> |
|
|
|
<chapter id="hostside"><title>Host-Side Data Types and Macros</title> |
|
|
|
<para>The host side API exposes several layers to drivers, some of |
|
which are more necessary than others. |
|
These support lifecycle models for host side drivers |
|
and devices, and support passing buffers through usbcore to |
|
some HCD that performs the I/O for the device driver. |
|
</para> |
|
|
|
|
|
!Iinclude/linux/usb.h |
|
|
|
</chapter> |
|
|
|
<chapter id="usbcore"><title>USB Core APIs</title> |
|
|
|
<para>There are two basic I/O models in the USB API. |
|
The most elemental one is asynchronous: drivers submit requests |
|
in the form of an URB, and the URB's completion callback |
|
handle the next step. |
|
All USB transfer types support that model, although there |
|
are special cases for control URBs (which always have setup |
|
and status stages, but may not have a data stage) and |
|
isochronous URBs (which allow large packets and include |
|
per-packet fault reports). |
|
Built on top of that is synchronous API support, where a |
|
driver calls a routine that allocates one or more URBs, |
|
submits them, and waits until they complete. |
|
There are synchronous wrappers for single-buffer control |
|
and bulk transfers (which are awkward to use in some |
|
driver disconnect scenarios), and for scatterlist based |
|
streaming i/o (bulk or interrupt). |
|
</para> |
|
|
|
<para>USB drivers need to provide buffers that can be |
|
used for DMA, although they don't necessarily need to |
|
provide the DMA mapping themselves. |
|
There are APIs to use used when allocating DMA buffers, |
|
which can prevent use of bounce buffers on some systems. |
|
In some cases, drivers may be able to rely on 64bit DMA |
|
to eliminate another kind of bounce buffer. |
|
</para> |
|
|
|
!Edrivers/usb/core/urb.c |
|
!Edrivers/usb/core/message.c |
|
!Edrivers/usb/core/file.c |
|
!Edrivers/usb/core/driver.c |
|
!Edrivers/usb/core/usb.c |
|
!Edrivers/usb/core/hub.c |
|
</chapter> |
|
|
|
<chapter id="hcd"><title>Host Controller APIs</title> |
|
|
|
<para>These APIs are only for use by host controller drivers, |
|
most of which implement standard register interfaces such as |
|
EHCI, OHCI, or UHCI. |
|
UHCI was one of the first interfaces, designed by Intel and |
|
also used by VIA; it doesn't do much in hardware. |
|
OHCI was designed later, to have the hardware do more work |
|
(bigger transfers, tracking protocol state, and so on). |
|
EHCI was designed with USB 2.0; its design has features that |
|
resemble OHCI (hardware does much more work) as well as |
|
UHCI (some parts of ISO support, TD list processing). |
|
</para> |
|
|
|
<para>There are host controllers other than the "big three", |
|
although most PCI based controllers (and a few non-PCI based |
|
ones) use one of those interfaces. |
|
Not all host controllers use DMA; some use PIO, and there |
|
is also a simulator. |
|
</para> |
|
|
|
<para>The same basic APIs are available to drivers for all |
|
those controllers. |
|
For historical reasons they are in two layers: |
|
<structname>struct usb_bus</structname> is a rather thin |
|
layer that became available in the 2.2 kernels, while |
|
<structname>struct usb_hcd</structname> is a more featureful |
|
layer (available in later 2.4 kernels and in 2.5) that |
|
lets HCDs share common code, to shrink driver size |
|
and significantly reduce hcd-specific behaviors. |
|
</para> |
|
|
|
!Edrivers/usb/core/hcd.c |
|
!Edrivers/usb/core/hcd-pci.c |
|
!Idrivers/usb/core/buffer.c |
|
</chapter> |
|
|
|
<chapter id="usbfs"> |
|
<title>The USB Filesystem (usbfs)</title> |
|
|
|
<para>This chapter presents the Linux <emphasis>usbfs</emphasis>. |
|
You may prefer to avoid writing new kernel code for your |
|
USB driver; that's the problem that usbfs set out to solve. |
|
User mode device drivers are usually packaged as applications |
|
or libraries, and may use usbfs through some programming library |
|
that wraps it. Such libraries include |
|
<ulink url="http://libusb.sourceforge.net">libusb</ulink> |
|
for C/C++, and |
|
<ulink url="http://jUSB.sourceforge.net">jUSB</ulink> for Java. |
|
</para> |
|
|
|
<note><title>Unfinished</title> |
|
<para>This particular documentation is incomplete, |
|
especially with respect to the asynchronous mode. |
|
As of kernel 2.5.66 the code and this (new) documentation |
|
need to be cross-reviewed. |
|
</para> |
|
</note> |
|
|
|
<para>Configure usbfs into Linux kernels by enabling the |
|
<emphasis>USB filesystem</emphasis> option (CONFIG_USB_DEVICEFS), |
|
and you get basic support for user mode USB device drivers. |
|
Until relatively recently it was often (confusingly) called |
|
<emphasis>usbdevfs</emphasis> although it wasn't solving what |
|
<emphasis>devfs</emphasis> was. |
|
Every USB device will appear in usbfs, regardless of whether or |
|
not it has a kernel driver. |
|
</para> |
|
|
|
<sect1 id="usbfs-files"> |
|
<title>What files are in "usbfs"?</title> |
|
|
|
<para>Conventionally mounted at |
|
<filename>/proc/bus/usb</filename>, usbfs |
|
features include: |
|
<itemizedlist> |
|
<listitem><para><filename>/proc/bus/usb/devices</filename> |
|
... a text file |
|
showing each of the USB devices on known to the kernel, |
|
and their configuration descriptors. |
|
You can also poll() this to learn about new devices. |
|
</para></listitem> |
|
<listitem><para><filename>/proc/bus/usb/BBB/DDD</filename> |
|
... magic files |
|
exposing the each device's configuration descriptors, and |
|
supporting a series of ioctls for making device requests, |
|
including I/O to devices. (Purely for access by programs.) |
|
</para></listitem> |
|
</itemizedlist> |
|
</para> |
|
|
|
<para> Each bus is given a number (BBB) based on when it was |
|
enumerated; within each bus, each device is given a similar |
|
number (DDD). |
|
Those BBB/DDD paths are not "stable" identifiers; |
|
expect them to change even if you always leave the devices |
|
plugged in to the same hub port. |
|
<emphasis>Don't even think of saving these in application |
|
configuration files.</emphasis> |
|
Stable identifiers are available, for user mode applications |
|
that want to use them. HID and networking devices expose |
|
these stable IDs, so that for example you can be sure that |
|
you told the right UPS to power down its second server. |
|
"usbfs" doesn't (yet) expose those IDs. |
|
</para> |
|
|
|
</sect1> |
|
|
|
<sect1 id="usbfs-fstab"> |
|
<title>Mounting and Access Control</title> |
|
|
|
<para>There are a number of mount options for usbfs, which will |
|
be of most interest to you if you need to override the default |
|
access control policy. |
|
That policy is that only root may read or write device files |
|
(<filename>/proc/bus/BBB/DDD</filename>) although anyone may read |
|
the <filename>devices</filename> |
|
or <filename>drivers</filename> files. |
|
I/O requests to the device also need the CAP_SYS_RAWIO capability, |
|
</para> |
|
|
|
<para>The significance of that is that by default, all user mode |
|
device drivers need super-user privileges. |
|
You can change modes or ownership in a driver setup |
|
when the device hotplugs, or maye just start the |
|
driver right then, as a privileged server (or some activity |
|
within one). |
|
That's the most secure approach for multi-user systems, |
|
but for single user systems ("trusted" by that user) |
|
it's more convenient just to grant everyone all access |
|
(using the <emphasis>devmode=0666</emphasis> option) |
|
so the driver can start whenever it's needed. |
|
</para> |
|
|
|
<para>The mount options for usbfs, usable in /etc/fstab or |
|
in command line invocations of <emphasis>mount</emphasis>, are: |
|
|
|
<variablelist> |
|
<varlistentry> |
|
<term><emphasis>busgid</emphasis>=NNNNN</term> |
|
<listitem><para>Controls the GID used for the |
|
/proc/bus/usb/BBB |
|
directories. (Default: 0)</para></listitem></varlistentry> |
|
<varlistentry><term><emphasis>busmode</emphasis>=MMM</term> |
|
<listitem><para>Controls the file mode used for the |
|
/proc/bus/usb/BBB |
|
directories. (Default: 0555) |
|
</para></listitem></varlistentry> |
|
<varlistentry><term><emphasis>busuid</emphasis>=NNNNN</term> |
|
<listitem><para>Controls the UID used for the |
|
/proc/bus/usb/BBB |
|
directories. (Default: 0)</para></listitem></varlistentry> |
|
|
|
<varlistentry><term><emphasis>devgid</emphasis>=NNNNN</term> |
|
<listitem><para>Controls the GID used for the |
|
/proc/bus/usb/BBB/DDD |
|
files. (Default: 0)</para></listitem></varlistentry> |
|
<varlistentry><term><emphasis>devmode</emphasis>=MMM</term> |
|
<listitem><para>Controls the file mode used for the |
|
/proc/bus/usb/BBB/DDD |
|
files. (Default: 0644)</para></listitem></varlistentry> |
|
<varlistentry><term><emphasis>devuid</emphasis>=NNNNN</term> |
|
<listitem><para>Controls the UID used for the |
|
/proc/bus/usb/BBB/DDD |
|
files. (Default: 0)</para></listitem></varlistentry> |
|
|
|
<varlistentry><term><emphasis>listgid</emphasis>=NNNNN</term> |
|
<listitem><para>Controls the GID used for the |
|
/proc/bus/usb/devices and drivers files. |
|
(Default: 0)</para></listitem></varlistentry> |
|
<varlistentry><term><emphasis>listmode</emphasis>=MMM</term> |
|
<listitem><para>Controls the file mode used for the |
|
/proc/bus/usb/devices and drivers files. |
|
(Default: 0444)</para></listitem></varlistentry> |
|
<varlistentry><term><emphasis>listuid</emphasis>=NNNNN</term> |
|
<listitem><para>Controls the UID used for the |
|
/proc/bus/usb/devices and drivers files. |
|
(Default: 0)</para></listitem></varlistentry> |
|
</variablelist> |
|
|
|
</para> |
|
|
|
<para>Note that many Linux distributions hard-wire the mount options |
|
for usbfs in their init scripts, such as |
|
<filename>/etc/rc.d/rc.sysinit</filename>, |
|
rather than making it easy to set this per-system |
|
policy in <filename>/etc/fstab</filename>. |
|
</para> |
|
|
|
</sect1> |
|
|
|
<sect1 id="usbfs-devices"> |
|
<title>/proc/bus/usb/devices</title> |
|
|
|
<para>This file is handy for status viewing tools in user |
|
mode, which can scan the text format and ignore most of it. |
|
More detailed device status (including class and vendor |
|
status) is available from device-specific files. |
|
For information about the current format of this file, |
|
see the |
|
<filename>Documentation/usb/proc_usb_info.txt</filename> |
|
file in your Linux kernel sources. |
|
</para> |
|
|
|
<para>This file, in combination with the poll() system call, can |
|
also be used to detect when devices are added or removed: |
|
<programlisting>int fd; |
|
struct pollfd pfd; |
|
|
|
fd = open("/proc/bus/usb/devices", O_RDONLY); |
|
pfd = { fd, POLLIN, 0 }; |
|
for (;;) { |
|
/* The first time through, this call will return immediately. */ |
|
poll(&pfd, 1, -1); |
|
|
|
/* To see what's changed, compare the file's previous and current |
|
contents or scan the filesystem. (Scanning is more precise.) */ |
|
}</programlisting> |
|
Note that this behavior is intended to be used for informational |
|
and debug purposes. It would be more appropriate to use programs |
|
such as udev or HAL to initialize a device or start a user-mode |
|
helper program, for instance. |
|
</para> |
|
</sect1> |
|
|
|
<sect1 id="usbfs-bbbddd"> |
|
<title>/proc/bus/usb/BBB/DDD</title> |
|
|
|
<para>Use these files in one of these basic ways: |
|
</para> |
|
|
|
<para><emphasis>They can be read,</emphasis> |
|
producing first the device descriptor |
|
(18 bytes) and then the descriptors for the current configuration. |
|
See the USB 2.0 spec for details about those binary data formats. |
|
You'll need to convert most multibyte values from little endian |
|
format to your native host byte order, although a few of the |
|
fields in the device descriptor (both of the BCD-encoded fields, |
|
and the vendor and product IDs) will be byteswapped for you. |
|
Note that configuration descriptors include descriptors for |
|
interfaces, altsettings, endpoints, and maybe additional |
|
class descriptors. |
|
</para> |
|
|
|
<para><emphasis>Perform USB operations</emphasis> using |
|
<emphasis>ioctl()</emphasis> requests to make endpoint I/O |
|
requests (synchronously or asynchronously) or manage |
|
the device. |
|
These requests need the CAP_SYS_RAWIO capability, |
|
as well as filesystem access permissions. |
|
Only one ioctl request can be made on one of these |
|
device files at a time. |
|
This means that if you are synchronously reading an endpoint |
|
from one thread, you won't be able to write to a different |
|
endpoint from another thread until the read completes. |
|
This works for <emphasis>half duplex</emphasis> protocols, |
|
but otherwise you'd use asynchronous i/o requests. |
|
</para> |
|
|
|
</sect1> |
|
|
|
|
|
<sect1 id="usbfs-lifecycle"> |
|
<title>Life Cycle of User Mode Drivers</title> |
|
|
|
<para>Such a driver first needs to find a device file |
|
for a device it knows how to handle. |
|
Maybe it was told about it because a |
|
<filename>/sbin/hotplug</filename> event handling agent |
|
chose that driver to handle the new device. |
|
Or maybe it's an application that scans all the |
|
/proc/bus/usb device files, and ignores most devices. |
|
In either case, it should <function>read()</function> all |
|
the descriptors from the device file, |
|
and check them against what it knows how to handle. |
|
It might just reject everything except a particular |
|
vendor and product ID, or need a more complex policy. |
|
</para> |
|
|
|
<para>Never assume there will only be one such device |
|
on the system at a time! |
|
If your code can't handle more than one device at |
|
a time, at least detect when there's more than one, and |
|
have your users choose which device to use. |
|
</para> |
|
|
|
<para>Once your user mode driver knows what device to use, |
|
it interacts with it in either of two styles. |
|
The simple style is to make only control requests; some |
|
devices don't need more complex interactions than those. |
|
(An example might be software using vendor-specific control |
|
requests for some initialization or configuration tasks, |
|
with a kernel driver for the rest.) |
|
</para> |
|
|
|
<para>More likely, you need a more complex style driver: |
|
one using non-control endpoints, reading or writing data |
|
and claiming exclusive use of an interface. |
|
<emphasis>Bulk</emphasis> transfers are easiest to use, |
|
but only their sibling <emphasis>interrupt</emphasis> transfers |
|
work with low speed devices. |
|
Both interrupt and <emphasis>isochronous</emphasis> transfers |
|
offer service guarantees because their bandwidth is reserved. |
|
Such "periodic" transfers are awkward to use through usbfs, |
|
unless you're using the asynchronous calls. However, interrupt |
|
transfers can also be used in a synchronous "one shot" style. |
|
</para> |
|
|
|
<para>Your user-mode driver should never need to worry |
|
about cleaning up request state when the device is |
|
disconnected, although it should close its open file |
|
descriptors as soon as it starts seeing the ENODEV |
|
errors. |
|
</para> |
|
|
|
</sect1> |
|
|
|
<sect1 id="usbfs-ioctl"><title>The ioctl() Requests</title> |
|
|
|
<para>To use these ioctls, you need to include the following |
|
headers in your userspace program: |
|
<programlisting>#include <linux/usb.h> |
|
#include <linux/usbdevice_fs.h> |
|
#include <asm/byteorder.h></programlisting> |
|
The standard USB device model requests, from "Chapter 9" of |
|
the USB 2.0 specification, are automatically included from |
|
the <filename><linux/usb/ch9.h></filename> header. |
|
</para> |
|
|
|
<para>Unless noted otherwise, the ioctl requests |
|
described here will |
|
update the modification time on the usbfs file to which |
|
they are applied (unless they fail). |
|
A return of zero indicates success; otherwise, a |
|
standard USB error code is returned. (These are |
|
documented in |
|
<filename>Documentation/usb/error-codes.txt</filename> |
|
in your kernel sources.) |
|
</para> |
|
|
|
<para>Each of these files multiplexes access to several |
|
I/O streams, one per endpoint. |
|
Each device has one control endpoint (endpoint zero) |
|
which supports a limited RPC style RPC access. |
|
Devices are configured |
|
by hub_wq (in the kernel) setting a device-wide |
|
<emphasis>configuration</emphasis> that affects things |
|
like power consumption and basic functionality. |
|
The endpoints are part of USB <emphasis>interfaces</emphasis>, |
|
which may have <emphasis>altsettings</emphasis> |
|
affecting things like which endpoints are available. |
|
Many devices only have a single configuration and interface, |
|
so drivers for them will ignore configurations and altsettings. |
|
</para> |
|
|
|
|
|
<sect2 id="usbfs-mgmt"> |
|
<title>Management/Status Requests</title> |
|
|
|
<para>A number of usbfs requests don't deal very directly |
|
with device I/O. |
|
They mostly relate to device management and status. |
|
These are all synchronous requests. |
|
</para> |
|
|
|
<variablelist> |
|
|
|
<varlistentry><term>USBDEVFS_CLAIMINTERFACE</term> |
|
<listitem><para>This is used to force usbfs to |
|
claim a specific interface, |
|
which has not previously been claimed by usbfs or any other |
|
kernel driver. |
|
The ioctl parameter is an integer holding the number of |
|
the interface (bInterfaceNumber from descriptor). |
|
</para><para> |
|
Note that if your driver doesn't claim an interface |
|
before trying to use one of its endpoints, and no |
|
other driver has bound to it, then the interface is |
|
automatically claimed by usbfs. |
|
</para><para> |
|
This claim will be released by a RELEASEINTERFACE ioctl, |
|
or by closing the file descriptor. |
|
File modification time is not updated by this request. |
|
</para></listitem></varlistentry> |
|
|
|
<varlistentry><term>USBDEVFS_CONNECTINFO</term> |
|
<listitem><para>Says whether the device is lowspeed. |
|
The ioctl parameter points to a structure like this: |
|
<programlisting>struct usbdevfs_connectinfo { |
|
unsigned int devnum; |
|
unsigned char slow; |
|
}; </programlisting> |
|
File modification time is not updated by this request. |
|
</para><para> |
|
<emphasis>You can't tell whether a "not slow" |
|
device is connected at high speed (480 MBit/sec) |
|
or just full speed (12 MBit/sec).</emphasis> |
|
You should know the devnum value already, |
|
it's the DDD value of the device file name. |
|
</para></listitem></varlistentry> |
|
|
|
<varlistentry><term>USBDEVFS_GETDRIVER</term> |
|
<listitem><para>Returns the name of the kernel driver |
|
bound to a given interface (a string). Parameter |
|
is a pointer to this structure, which is modified: |
|
<programlisting>struct usbdevfs_getdriver { |
|
unsigned int interface; |
|
char driver[USBDEVFS_MAXDRIVERNAME + 1]; |
|
};</programlisting> |
|
File modification time is not updated by this request. |
|
</para></listitem></varlistentry> |
|
|
|
<varlistentry><term>USBDEVFS_IOCTL</term> |
|
<listitem><para>Passes a request from userspace through |
|
to a kernel driver that has an ioctl entry in the |
|
<emphasis>struct usb_driver</emphasis> it registered. |
|
<programlisting>struct usbdevfs_ioctl { |
|
int ifno; |
|
int ioctl_code; |
|
void *data; |
|
}; |
|
|
|
/* user mode call looks like this. |
|
* 'request' becomes the driver->ioctl() 'code' parameter. |
|
* the size of 'param' is encoded in 'request', and that data |
|
* is copied to or from the driver->ioctl() 'buf' parameter. |
|
*/ |
|
static int |
|
usbdev_ioctl (int fd, int ifno, unsigned request, void *param) |
|
{ |
|
struct usbdevfs_ioctl wrapper; |
|
|
|
wrapper.ifno = ifno; |
|
wrapper.ioctl_code = request; |
|
wrapper.data = param; |
|
|
|
return ioctl (fd, USBDEVFS_IOCTL, &wrapper); |
|
} </programlisting> |
|
File modification time is not updated by this request. |
|
</para><para> |
|
This request lets kernel drivers talk to user mode code |
|
through filesystem operations even when they don't create |
|
a character or block special device. |
|
It's also been used to do things like ask devices what |
|
device special file should be used. |
|
Two pre-defined ioctls are used |
|
to disconnect and reconnect kernel drivers, so |
|
that user mode code can completely manage binding |
|
and configuration of devices. |
|
</para></listitem></varlistentry> |
|
|
|
<varlistentry><term>USBDEVFS_RELEASEINTERFACE</term> |
|
<listitem><para>This is used to release the claim usbfs |
|
made on interface, either implicitly or because of a |
|
USBDEVFS_CLAIMINTERFACE call, before the file |
|
descriptor is closed. |
|
The ioctl parameter is an integer holding the number of |
|
the interface (bInterfaceNumber from descriptor); |
|
File modification time is not updated by this request. |
|
</para><warning><para> |
|
<emphasis>No security check is made to ensure |
|
that the task which made the claim is the one |
|
which is releasing it. |
|
This means that user mode driver may interfere |
|
other ones. </emphasis> |
|
</para></warning></listitem></varlistentry> |
|
|
|
<varlistentry><term>USBDEVFS_RESETEP</term> |
|
<listitem><para>Resets the data toggle value for an endpoint |
|
(bulk or interrupt) to DATA0. |
|
The ioctl parameter is an integer endpoint number |
|
(1 to 15, as identified in the endpoint descriptor), |
|
with USB_DIR_IN added if the device's endpoint sends |
|
data to the host. |
|
</para><warning><para> |
|
<emphasis>Avoid using this request. |
|
It should probably be removed.</emphasis> |
|
Using it typically means the device and driver will lose |
|
toggle synchronization. If you really lost synchronization, |
|
you likely need to completely handshake with the device, |
|
using a request like CLEAR_HALT |
|
or SET_INTERFACE. |
|
</para></warning></listitem></varlistentry> |
|
|
|
</variablelist> |
|
|
|
</sect2> |
|
|
|
<sect2 id="usbfs-sync"> |
|
<title>Synchronous I/O Support</title> |
|
|
|
<para>Synchronous requests involve the kernel blocking |
|
until the user mode request completes, either by |
|
finishing successfully or by reporting an error. |
|
In most cases this is the simplest way to use usbfs, |
|
although as noted above it does prevent performing I/O |
|
to more than one endpoint at a time. |
|
</para> |
|
|
|
<variablelist> |
|
|
|
<varlistentry><term>USBDEVFS_BULK</term> |
|
<listitem><para>Issues a bulk read or write request to the |
|
device. |
|
The ioctl parameter is a pointer to this structure: |
|
<programlisting>struct usbdevfs_bulktransfer { |
|
unsigned int ep; |
|
unsigned int len; |
|
unsigned int timeout; /* in milliseconds */ |
|
void *data; |
|
};</programlisting> |
|
</para><para>The "ep" value identifies a |
|
bulk endpoint number (1 to 15, as identified in an endpoint |
|
descriptor), |
|
masked with USB_DIR_IN when referring to an endpoint which |
|
sends data to the host from the device. |
|
The length of the data buffer is identified by "len"; |
|
Recent kernels support requests up to about 128KBytes. |
|
<emphasis>FIXME say how read length is returned, |
|
and how short reads are handled.</emphasis>. |
|
</para></listitem></varlistentry> |
|
|
|
<varlistentry><term>USBDEVFS_CLEAR_HALT</term> |
|
<listitem><para>Clears endpoint halt (stall) and |
|
resets the endpoint toggle. This is only |
|
meaningful for bulk or interrupt endpoints. |
|
The ioctl parameter is an integer endpoint number |
|
(1 to 15, as identified in an endpoint descriptor), |
|
masked with USB_DIR_IN when referring to an endpoint which |
|
sends data to the host from the device. |
|
</para><para> |
|
Use this on bulk or interrupt endpoints which have |
|
stalled, returning <emphasis>-EPIPE</emphasis> status |
|
to a data transfer request. |
|
Do not issue the control request directly, since |
|
that could invalidate the host's record of the |
|
data toggle. |
|
</para></listitem></varlistentry> |
|
|
|
<varlistentry><term>USBDEVFS_CONTROL</term> |
|
<listitem><para>Issues a control request to the device. |
|
The ioctl parameter points to a structure like this: |
|
<programlisting>struct usbdevfs_ctrltransfer { |
|
__u8 bRequestType; |
|
__u8 bRequest; |
|
__u16 wValue; |
|
__u16 wIndex; |
|
__u16 wLength; |
|
__u32 timeout; /* in milliseconds */ |
|
void *data; |
|
};</programlisting> |
|
</para><para> |
|
The first eight bytes of this structure are the contents |
|
of the SETUP packet to be sent to the device; see the |
|
USB 2.0 specification for details. |
|
The bRequestType value is composed by combining a |
|
USB_TYPE_* value, a USB_DIR_* value, and a |
|
USB_RECIP_* value (from |
|
<emphasis><linux/usb.h></emphasis>). |
|
If wLength is nonzero, it describes the length of the data |
|
buffer, which is either written to the device |
|
(USB_DIR_OUT) or read from the device (USB_DIR_IN). |
|
</para><para> |
|
At this writing, you can't transfer more than 4 KBytes |
|
of data to or from a device; usbfs has a limit, and |
|
some host controller drivers have a limit. |
|
(That's not usually a problem.) |
|
<emphasis>Also</emphasis> there's no way to say it's |
|
not OK to get a short read back from the device. |
|
</para></listitem></varlistentry> |
|
|
|
<varlistentry><term>USBDEVFS_RESET</term> |
|
<listitem><para>Does a USB level device reset. |
|
The ioctl parameter is ignored. |
|
After the reset, this rebinds all device interfaces. |
|
File modification time is not updated by this request. |
|
</para><warning><para> |
|
<emphasis>Avoid using this call</emphasis> |
|
until some usbcore bugs get fixed, |
|
since it does not fully synchronize device, interface, |
|
and driver (not just usbfs) state. |
|
</para></warning></listitem></varlistentry> |
|
|
|
<varlistentry><term>USBDEVFS_SETINTERFACE</term> |
|
<listitem><para>Sets the alternate setting for an |
|
interface. The ioctl parameter is a pointer to a |
|
structure like this: |
|
<programlisting>struct usbdevfs_setinterface { |
|
unsigned int interface; |
|
unsigned int altsetting; |
|
}; </programlisting> |
|
File modification time is not updated by this request. |
|
</para><para> |
|
Those struct members are from some interface descriptor |
|
applying to the current configuration. |
|
The interface number is the bInterfaceNumber value, and |
|
the altsetting number is the bAlternateSetting value. |
|
(This resets each endpoint in the interface.) |
|
</para></listitem></varlistentry> |
|
|
|
<varlistentry><term>USBDEVFS_SETCONFIGURATION</term> |
|
<listitem><para>Issues the |
|
<function>usb_set_configuration</function> call |
|
for the device. |
|
The parameter is an integer holding the number of |
|
a configuration (bConfigurationValue from descriptor). |
|
File modification time is not updated by this request. |
|
</para><warning><para> |
|
<emphasis>Avoid using this call</emphasis> |
|
until some usbcore bugs get fixed, |
|
since it does not fully synchronize device, interface, |
|
and driver (not just usbfs) state. |
|
</para></warning></listitem></varlistentry> |
|
|
|
</variablelist> |
|
</sect2> |
|
|
|
<sect2 id="usbfs-async"> |
|
<title>Asynchronous I/O Support</title> |
|
|
|
<para>As mentioned above, there are situations where it may be |
|
important to initiate concurrent operations from user mode code. |
|
This is particularly important for periodic transfers |
|
(interrupt and isochronous), but it can be used for other |
|
kinds of USB requests too. |
|
In such cases, the asynchronous requests described here |
|
are essential. Rather than submitting one request and having |
|
the kernel block until it completes, the blocking is separate. |
|
</para> |
|
|
|
<para>These requests are packaged into a structure that |
|
resembles the URB used by kernel device drivers. |
|
(No POSIX Async I/O support here, sorry.) |
|
It identifies the endpoint type (USBDEVFS_URB_TYPE_*), |
|
endpoint (number, masked with USB_DIR_IN as appropriate), |
|
buffer and length, and a user "context" value serving to |
|
uniquely identify each request. |
|
(It's usually a pointer to per-request data.) |
|
Flags can modify requests (not as many as supported for |
|
kernel drivers). |
|
</para> |
|
|
|
<para>Each request can specify a realtime signal number |
|
(between SIGRTMIN and SIGRTMAX, inclusive) to request a |
|
signal be sent when the request completes. |
|
</para> |
|
|
|
<para>When usbfs returns these urbs, the status value |
|
is updated, and the buffer may have been modified. |
|
Except for isochronous transfers, the actual_length is |
|
updated to say how many bytes were transferred; if the |
|
USBDEVFS_URB_DISABLE_SPD flag is set |
|
("short packets are not OK"), if fewer bytes were read |
|
than were requested then you get an error report. |
|
</para> |
|
|
|
<programlisting>struct usbdevfs_iso_packet_desc { |
|
unsigned int length; |
|
unsigned int actual_length; |
|
unsigned int status; |
|
}; |
|
|
|
struct usbdevfs_urb { |
|
unsigned char type; |
|
unsigned char endpoint; |
|
int status; |
|
unsigned int flags; |
|
void *buffer; |
|
int buffer_length; |
|
int actual_length; |
|
int start_frame; |
|
int number_of_packets; |
|
int error_count; |
|
unsigned int signr; |
|
void *usercontext; |
|
struct usbdevfs_iso_packet_desc iso_frame_desc[]; |
|
};</programlisting> |
|
|
|
<para> For these asynchronous requests, the file modification |
|
time reflects when the request was initiated. |
|
This contrasts with their use with the synchronous requests, |
|
where it reflects when requests complete. |
|
</para> |
|
|
|
<variablelist> |
|
|
|
<varlistentry><term>USBDEVFS_DISCARDURB</term> |
|
<listitem><para> |
|
<emphasis>TBS</emphasis> |
|
File modification time is not updated by this request. |
|
</para><para> |
|
</para></listitem></varlistentry> |
|
|
|
<varlistentry><term>USBDEVFS_DISCSIGNAL</term> |
|
<listitem><para> |
|
<emphasis>TBS</emphasis> |
|
File modification time is not updated by this request. |
|
</para><para> |
|
</para></listitem></varlistentry> |
|
|
|
<varlistentry><term>USBDEVFS_REAPURB</term> |
|
<listitem><para> |
|
<emphasis>TBS</emphasis> |
|
File modification time is not updated by this request. |
|
</para><para> |
|
</para></listitem></varlistentry> |
|
|
|
<varlistentry><term>USBDEVFS_REAPURBNDELAY</term> |
|
<listitem><para> |
|
<emphasis>TBS</emphasis> |
|
File modification time is not updated by this request. |
|
</para><para> |
|
</para></listitem></varlistentry> |
|
|
|
<varlistentry><term>USBDEVFS_SUBMITURB</term> |
|
<listitem><para> |
|
<emphasis>TBS</emphasis> |
|
</para><para> |
|
</para></listitem></varlistentry> |
|
|
|
</variablelist> |
|
</sect2> |
|
|
|
</sect1> |
|
|
|
</chapter> |
|
|
|
</book> |
|
<!-- vim:syntax=sgml:sw=4 |
|
-->
|
|
|