|  | .. _usb-hostside-api: | 
|  |  | 
|  | =========================== | 
|  | The Linux-USB Host Side API | 
|  | =========================== | 
|  |  | 
|  | Introduction to USB on Linux | 
|  | ============================ | 
|  |  | 
|  | 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 | 
|  | a few USB 3.0 (5 GBit/s) or USB 3.1 (10 GBit/s) and some legacy | 
|  | USB 2.0 (480 MBit/s) busses just in case. | 
|  |  | 
|  | That master/slave asymmetry was designed-in for a number of reasons, one | 
|  | being ease of use. It is not physically possible to mistake upstream and | 
|  | downstream or it does not matter with a type C plug (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. | 
|  |  | 
|  | Kernel developers added USB support to Linux early in the 2.2 kernel | 
|  | series and have been developing it further since then. Besides support | 
|  | for each new generation of USB, various host controllers gained support, | 
|  | new drivers for peripherals have been added and advanced features for latency | 
|  | measurement and improved power management introduced. | 
|  |  | 
|  | 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: *gadget drivers*. This document does not | 
|  | cover gadget drivers. | 
|  |  | 
|  | USB Host-Side API Model | 
|  | ======================= | 
|  |  | 
|  | Host-side drivers for USB devices talk to the "usbcore" APIs. There are | 
|  | two. One is intended for *general-purpose* drivers (exposed through | 
|  | driver frameworks), and the other is for drivers that are *part of the | 
|  | core*. Such core drivers include the *hub* driver (which manages trees | 
|  | of USB devices) and several different kinds of *host controller | 
|  | drivers*, which control individual busses. | 
|  |  | 
|  | The device model seen by USB drivers is relatively complex. | 
|  |  | 
|  | -  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. | 
|  |  | 
|  | -  The device description model includes one or more "configurations" | 
|  | per device, only one of which is active at a time. Devices are supposed | 
|  | to be capable of operating at lower than their top | 
|  | speeds and may provide a BOS descriptor showing the lowest speed they | 
|  | remain fully operational at. | 
|  |  | 
|  | -  From USB 3.0 on configurations have one or more "functions", which | 
|  | provide a common functionality and are grouped together for purposes | 
|  | of power management. | 
|  |  | 
|  | -  Configurations or functions 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. | 
|  |  | 
|  | 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. *Most USB devices are simple, | 
|  | with only one function, one configuration, one interface, and one alternate | 
|  | setting.* | 
|  |  | 
|  | -  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. | 
|  |  | 
|  | -  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. | 
|  |  | 
|  | -  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). | 
|  |  | 
|  | Accordingly, the USB Core API exposed to device drivers covers quite a | 
|  | lot of territory. You'll probably need to consult the USB 3.0 | 
|  | specification, available online from www.usb.org at no cost, as well as | 
|  | class or device specifications. | 
|  |  | 
|  | 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, but there are still differences | 
|  | that crop up especially with fault handling on the less common controllers. | 
|  | 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. | 
|  |  | 
|  | .. _usb_chapter9: | 
|  |  | 
|  | USB-Standard Types | 
|  | ================== | 
|  |  | 
|  | In ``<linux/usb/ch9.h>`` 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, usb character | 
|  | devices and debugfs interfaces. | 
|  |  | 
|  | .. kernel-doc:: include/linux/usb/ch9.h | 
|  | :internal: | 
|  |  | 
|  | .. _usb_header: | 
|  |  | 
|  | Host-Side Data Types and Macros | 
|  | =============================== | 
|  |  | 
|  | 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. | 
|  |  | 
|  | .. kernel-doc:: include/linux/usb.h | 
|  | :internal: | 
|  |  | 
|  | USB Core APIs | 
|  | ============= | 
|  |  | 
|  | 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 handles 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). | 
|  |  | 
|  | 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. | 
|  |  | 
|  | .. kernel-doc:: drivers/usb/core/urb.c | 
|  | :export: | 
|  |  | 
|  | .. kernel-doc:: drivers/usb/core/message.c | 
|  | :export: | 
|  |  | 
|  | .. kernel-doc:: drivers/usb/core/file.c | 
|  | :export: | 
|  |  | 
|  | .. kernel-doc:: drivers/usb/core/driver.c | 
|  | :export: | 
|  |  | 
|  | .. kernel-doc:: drivers/usb/core/usb.c | 
|  | :export: | 
|  |  | 
|  | .. kernel-doc:: drivers/usb/core/hub.c | 
|  | :export: | 
|  |  | 
|  | Host Controller APIs | 
|  | ==================== | 
|  |  | 
|  | These APIs are only for use by host controller drivers, most of which | 
|  | implement standard register interfaces such as XHCI, 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). XHCI was designed with USB 3.0. It | 
|  | continues to shift support for functionality into hardware. | 
|  |  | 
|  | 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 and a virtual host controller to pipe USB over the network. | 
|  |  | 
|  | The same basic APIs are available to drivers for all those controllers. | 
|  | For historical reasons they are in two layers: :c:type:`struct | 
|  | usb_bus <usb_bus>` is a rather thin layer that became available | 
|  | in the 2.2 kernels, while :c:type:`struct usb_hcd <usb_hcd>` | 
|  | is a more featureful layer | 
|  | that lets HCDs share common code, to shrink driver size and | 
|  | significantly reduce hcd-specific behaviors. | 
|  |  | 
|  | .. kernel-doc:: drivers/usb/core/hcd.c | 
|  | :export: | 
|  |  | 
|  | .. kernel-doc:: drivers/usb/core/hcd-pci.c | 
|  | :export: | 
|  |  | 
|  | .. kernel-doc:: drivers/usb/core/buffer.c | 
|  | :internal: | 
|  |  | 
|  | The USB character device nodes | 
|  | ============================== | 
|  |  | 
|  | This chapter presents the Linux character device nodes. You may prefer | 
|  | to avoid writing new kernel code for your USB driver. User mode device | 
|  | drivers are usually packaged as applications or libraries, and may use | 
|  | character devices through some programming library that wraps it. | 
|  | Such libraries include: | 
|  |  | 
|  | - `libusb <http://libusb.sourceforge.net>`__ for C/C++, and | 
|  | - `jUSB <http://jUSB.sourceforge.net>`__ for Java. | 
|  |  | 
|  | Some old information about it can be seen at the "USB Device Filesystem" | 
|  | section of the USB Guide. The latest copy of the USB Guide can be found | 
|  | at http://www.linux-usb.org/ | 
|  |  | 
|  | .. note:: | 
|  |  | 
|  | - They were used to be implemented via *usbfs*, but this is not part of | 
|  | the sysfs debug interface. | 
|  |  | 
|  | - 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. | 
|  |  | 
|  | What files are in "devtmpfs"? | 
|  | ----------------------------- | 
|  |  | 
|  | Conventionally mounted at ``/dev/bus/usb/``, usbfs features include: | 
|  |  | 
|  | -  ``/dev/bus/usb/BBB/DDD`` ... 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.) | 
|  |  | 
|  | 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. *Don't even | 
|  | think of saving these in application configuration files.* 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. Pleast note that it doesn't (yet) expose those IDs. | 
|  |  | 
|  | /dev/bus/usb/BBB/DDD | 
|  | -------------------- | 
|  |  | 
|  | Use these files in one of these basic ways: | 
|  |  | 
|  | - *They can be read,* 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. | 
|  |  | 
|  | - *Perform USB operations* using *ioctl()* 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 | 
|  | *half duplex* protocols, but otherwise you'd use asynchronous i/o | 
|  | requests. | 
|  |  | 
|  | Each connected USB device has one file.  The ``BBB`` indicates the bus | 
|  | number.  The ``DDD`` indicates the device address on that bus.  Both | 
|  | of these numbers are assigned sequentially, and can be reused, so | 
|  | you can't rely on them for stable access to devices.  For example, | 
|  | it's relatively common for devices to re-enumerate while they are | 
|  | still connected (perhaps someone jostled their power supply, hub, | 
|  | or USB cable), so a device might be ``002/027`` when you first connect | 
|  | it and ``002/048`` sometime later. | 
|  |  | 
|  | These files can be read as binary data.  The binary data consists | 
|  | of first the device descriptor, then the descriptors for each | 
|  | configuration of the device.  Multi-byte fields in the device descriptor | 
|  | are converted to host endianness by the kernel.  The configuration | 
|  | descriptors are in bus endian format! The configuration descriptor | 
|  | are wTotalLength bytes apart. If a device returns less configuration | 
|  | descriptor data than indicated by wTotalLength there will be a hole in | 
|  | the file for the missing bytes.  This information is also shown | 
|  | in text form by the ``/sys/kernel/debug/usb/devices`` file, described later. | 
|  |  | 
|  | These files may also be used to write user-level drivers for the USB | 
|  | devices.  You would open the ``/dev/bus/usb/BBB/DDD`` file read/write, | 
|  | read its descriptors to make sure it's the device you expect, and then | 
|  | bind to an interface (or perhaps several) using an ioctl call.  You | 
|  | would issue more ioctls to the device to communicate to it using | 
|  | control, bulk, or other kinds of USB transfers.  The IOCTLs are | 
|  | listed in the ``<linux/usbdevice_fs.h>`` file, and at this writing the | 
|  | source code (``linux/drivers/usb/core/devio.c``) is the primary reference | 
|  | for how to access devices through those files. | 
|  |  | 
|  | Note that since by default these ``BBB/DDD`` files are writable only by | 
|  | root, only root can write such user mode drivers.  You can selectively | 
|  | grant read/write permissions to other users by using ``chmod``.  Also, | 
|  | usbfs mount options such as ``devmode=0666`` may be helpful. | 
|  |  | 
|  |  | 
|  | Life Cycle of User Mode Drivers | 
|  | ------------------------------- | 
|  |  | 
|  | 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 ``/sbin/hotplug`` | 
|  | event handling agent chose that driver to handle the new device. Or | 
|  | maybe it's an application that scans all the ``/dev/bus/usb`` device files, | 
|  | and ignores most devices. In either case, it should :c:func:`read()` | 
|  | 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. | 
|  |  | 
|  | 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. | 
|  |  | 
|  | 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.) | 
|  |  | 
|  | 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. *Bulk* transfers are easiest to use, but only their sibling | 
|  | *interrupt* transfers work with low speed devices. Both interrupt and | 
|  | *isochronous* 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. | 
|  |  | 
|  | 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. | 
|  |  | 
|  | The ioctl() Requests | 
|  | -------------------- | 
|  |  | 
|  | To use these ioctls, you need to include the following headers in your | 
|  | userspace program:: | 
|  |  | 
|  | #include <linux/usb.h> | 
|  | #include <linux/usbdevice_fs.h> | 
|  | #include <asm/byteorder.h> | 
|  |  | 
|  | The standard USB device model requests, from "Chapter 9" of the USB 2.0 | 
|  | specification, are automatically included from the ``<linux/usb/ch9.h>`` | 
|  | header. | 
|  |  | 
|  | 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 | 
|  | :ref:`usb-error-codes`). | 
|  |  | 
|  | 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 *configuration* that | 
|  | affects things like power consumption and basic functionality. The | 
|  | endpoints are part of USB *interfaces*, which may have *altsettings* | 
|  | 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. | 
|  |  | 
|  | Management/Status Requests | 
|  | ~~~~~~~~~~~~~~~~~~~~~~~~~~ | 
|  |  | 
|  | 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. | 
|  |  | 
|  | USBDEVFS_CLAIMINTERFACE | 
|  | 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). | 
|  |  | 
|  | 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. | 
|  |  | 
|  | This claim will be released by a RELEASEINTERFACE ioctl, or by | 
|  | closing the file descriptor. File modification time is not updated | 
|  | by this request. | 
|  |  | 
|  | USBDEVFS_CONNECTINFO | 
|  | Says whether the device is lowspeed. The ioctl parameter points to a | 
|  | structure like this:: | 
|  |  | 
|  | struct usbdevfs_connectinfo { | 
|  | unsigned int   devnum; | 
|  | unsigned char  slow; | 
|  | }; | 
|  |  | 
|  | File modification time is not updated by this request. | 
|  |  | 
|  | *You can't tell whether a "not slow" device is connected at high | 
|  | speed (480 MBit/sec) or just full speed (12 MBit/sec).* You should | 
|  | know the devnum value already, it's the DDD value of the device file | 
|  | name. | 
|  |  | 
|  | USBDEVFS_GETDRIVER | 
|  | Returns the name of the kernel driver bound to a given interface (a | 
|  | string). Parameter is a pointer to this structure, which is | 
|  | modified:: | 
|  |  | 
|  | struct usbdevfs_getdriver { | 
|  | unsigned int  interface; | 
|  | char          driver[USBDEVFS_MAXDRIVERNAME + 1]; | 
|  | }; | 
|  |  | 
|  | File modification time is not updated by this request. | 
|  |  | 
|  | USBDEVFS_IOCTL | 
|  | Passes a request from userspace through to a kernel driver that has | 
|  | an ioctl entry in the *struct usb_driver* it registered:: | 
|  |  | 
|  | 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); | 
|  | } | 
|  |  | 
|  | File modification time is not updated by this request. | 
|  |  | 
|  | 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. | 
|  |  | 
|  | USBDEVFS_RELEASEINTERFACE | 
|  | 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. | 
|  |  | 
|  | .. warning:: | 
|  |  | 
|  | *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.* | 
|  |  | 
|  | USBDEVFS_RESETEP | 
|  | 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. | 
|  |  | 
|  | .. Warning:: | 
|  |  | 
|  | *Avoid using this request. It should probably be removed.* 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. | 
|  |  | 
|  | USBDEVFS_DROP_PRIVILEGES | 
|  | This is used to relinquish the ability to do certain operations | 
|  | which are considered to be privileged on a usbfs file descriptor. | 
|  | This includes claiming arbitrary interfaces, resetting a device on | 
|  | which there are currently claimed interfaces from other users, and | 
|  | issuing USBDEVFS_IOCTL calls. The ioctl parameter is a 32 bit mask | 
|  | of interfaces the user is allowed to claim on this file descriptor. | 
|  | You may issue this ioctl more than one time to narrow said mask. | 
|  |  | 
|  | Synchronous I/O Support | 
|  | ~~~~~~~~~~~~~~~~~~~~~~~ | 
|  |  | 
|  | 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. | 
|  |  | 
|  | USBDEVFS_BULK | 
|  | Issues a bulk read or write request to the device. The ioctl | 
|  | parameter is a pointer to this structure:: | 
|  |  | 
|  | struct usbdevfs_bulktransfer { | 
|  | unsigned int  ep; | 
|  | unsigned int  len; | 
|  | unsigned int  timeout; /* in milliseconds */ | 
|  | void          *data; | 
|  | }; | 
|  |  | 
|  | 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. *FIXME say how read | 
|  | length is returned, and how short reads are handled.*. | 
|  |  | 
|  | USBDEVFS_CLEAR_HALT | 
|  | 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. | 
|  |  | 
|  | Use this on bulk or interrupt endpoints which have stalled, | 
|  | returning ``-EPIPE`` 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. | 
|  |  | 
|  | USBDEVFS_CONTROL | 
|  | Issues a control request to the device. The ioctl parameter points | 
|  | to a structure like this:: | 
|  |  | 
|  | struct usbdevfs_ctrltransfer { | 
|  | __u8   bRequestType; | 
|  | __u8   bRequest; | 
|  | __u16  wValue; | 
|  | __u16  wIndex; | 
|  | __u16  wLength; | 
|  | __u32  timeout;  /* in milliseconds */ | 
|  | void   *data; | 
|  | }; | 
|  |  | 
|  | 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 ``linux/usb.h``). 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). | 
|  |  | 
|  | 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.) *Also* there's no way | 
|  | to say it's not OK to get a short read back from the device. | 
|  |  | 
|  | USBDEVFS_RESET | 
|  | 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. | 
|  |  | 
|  | .. warning:: | 
|  |  | 
|  | *Avoid using this call* until some usbcore bugs get fixed, since | 
|  | it does not fully synchronize device, interface, and driver (not | 
|  | just usbfs) state. | 
|  |  | 
|  | USBDEVFS_SETINTERFACE | 
|  | Sets the alternate setting for an interface. The ioctl parameter is | 
|  | a pointer to a structure like this:: | 
|  |  | 
|  | struct usbdevfs_setinterface { | 
|  | unsigned int  interface; | 
|  | unsigned int  altsetting; | 
|  | }; | 
|  |  | 
|  | File modification time is not updated by this request. | 
|  |  | 
|  | 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.) | 
|  |  | 
|  | USBDEVFS_SETCONFIGURATION | 
|  | Issues the :c:func:`usb_set_configuration()` 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. | 
|  |  | 
|  | .. warning:: | 
|  |  | 
|  | *Avoid using this call* until some usbcore bugs get fixed, since | 
|  | it does not fully synchronize device, interface, and driver (not | 
|  | just usbfs) state. | 
|  |  | 
|  | Asynchronous I/O Support | 
|  | ~~~~~~~~~~~~~~~~~~~~~~~~ | 
|  |  | 
|  | 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. | 
|  |  | 
|  | 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). | 
|  |  | 
|  | Each request can specify a realtime signal number (between SIGRTMIN and | 
|  | SIGRTMAX, inclusive) to request a signal be sent when the request | 
|  | completes. | 
|  |  | 
|  | 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:: | 
|  |  | 
|  | 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[]; | 
|  | }; | 
|  |  | 
|  | 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. | 
|  |  | 
|  | USBDEVFS_DISCARDURB | 
|  | *TBS* File modification time is not updated by this request. | 
|  |  | 
|  | USBDEVFS_DISCSIGNAL | 
|  | *TBS* File modification time is not updated by this request. | 
|  |  | 
|  | USBDEVFS_REAPURB | 
|  | *TBS* File modification time is not updated by this request. | 
|  |  | 
|  | USBDEVFS_REAPURBNDELAY | 
|  | *TBS* File modification time is not updated by this request. | 
|  |  | 
|  | USBDEVFS_SUBMITURB | 
|  | *TBS* | 
|  |  | 
|  | The USB devices | 
|  | =============== | 
|  |  | 
|  | The USB devices are now exported via debugfs: | 
|  |  | 
|  | -  ``/sys/kernel/debug/usb/devices`` ... 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. | 
|  |  | 
|  | /sys/kernel/debug/usb/devices | 
|  | ----------------------------- | 
|  |  | 
|  | 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 below. | 
|  |  | 
|  | This file, in combination with the poll() system call, can also be used | 
|  | to detect when devices are added or removed:: | 
|  |  | 
|  | int fd; | 
|  | struct pollfd pfd; | 
|  |  | 
|  | fd = open("/sys/kernel/debug/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.) */ | 
|  | } | 
|  |  | 
|  | 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. | 
|  |  | 
|  | In this file, each device's output has multiple lines of ASCII output. | 
|  |  | 
|  | I made it ASCII instead of binary on purpose, so that someone | 
|  | can obtain some useful data from it without the use of an | 
|  | auxiliary program.  However, with an auxiliary program, the numbers | 
|  | in the first 4 columns of each ``T:`` line (topology info: | 
|  | Lev, Prnt, Port, Cnt) can be used to build a USB topology diagram. | 
|  |  | 
|  | Each line is tagged with a one-character ID for that line:: | 
|  |  | 
|  | T = Topology (etc.) | 
|  | B = Bandwidth (applies only to USB host controllers, which are | 
|  | virtualized as root hubs) | 
|  | D = Device descriptor info. | 
|  | P = Product ID info. (from Device descriptor, but they won't fit | 
|  | together on one line) | 
|  | S = String descriptors. | 
|  | C = Configuration descriptor info. (* = active configuration) | 
|  | I = Interface descriptor info. | 
|  | E = Endpoint descriptor info. | 
|  |  | 
|  | /sys/kernel/debug/usb/devices output format | 
|  | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 
|  |  | 
|  | Legend:: | 
|  | d = decimal number (may have leading spaces or 0's) | 
|  | x = hexadecimal number (may have leading spaces or 0's) | 
|  | s = string | 
|  |  | 
|  |  | 
|  |  | 
|  | Topology info | 
|  | ^^^^^^^^^^^^^ | 
|  |  | 
|  | :: | 
|  |  | 
|  | T:  Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=dddd MxCh=dd | 
|  | |   |      |      |       |       |      |        |        |__MaxChildren | 
|  | |   |      |      |       |       |      |        |__Device Speed in Mbps | 
|  | |   |      |      |       |       |      |__DeviceNumber | 
|  | |   |      |      |       |       |__Count of devices at this level | 
|  | |   |      |      |       |__Connector/Port on Parent for this device | 
|  | |   |      |      |__Parent DeviceNumber | 
|  | |   |      |__Level in topology for this bus | 
|  | |   |__Bus number | 
|  | |__Topology info tag | 
|  |  | 
|  | Speed may be: | 
|  |  | 
|  | ======= ====================================================== | 
|  | 1.5	Mbit/s for low speed USB | 
|  | 12	Mbit/s for full speed USB | 
|  | 480	Mbit/s for high speed USB (added for USB 2.0); | 
|  | also used for Wireless USB, which has no fixed speed | 
|  | 5000	Mbit/s for SuperSpeed USB (added for USB 3.0) | 
|  | ======= ====================================================== | 
|  |  | 
|  | For reasons lost in the mists of time, the Port number is always | 
|  | too low by 1.  For example, a device plugged into port 4 will | 
|  | show up with ``Port=03``. | 
|  |  | 
|  | Bandwidth info | 
|  | ^^^^^^^^^^^^^^ | 
|  |  | 
|  | :: | 
|  |  | 
|  | B:  Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd | 
|  | |   |                       |         |__Number of isochronous requests | 
|  | |   |                       |__Number of interrupt requests | 
|  | |   |__Total Bandwidth allocated to this bus | 
|  | |__Bandwidth info tag | 
|  |  | 
|  | Bandwidth allocation is an approximation of how much of one frame | 
|  | (millisecond) is in use.  It reflects only periodic transfers, which | 
|  | are the only transfers that reserve bandwidth.  Control and bulk | 
|  | transfers use all other bandwidth, including reserved bandwidth that | 
|  | is not used for transfers (such as for short packets). | 
|  |  | 
|  | The percentage is how much of the "reserved" bandwidth is scheduled by | 
|  | those transfers.  For a low or full speed bus (loosely, "USB 1.1"), | 
|  | 90% of the bus bandwidth is reserved.  For a high speed bus (loosely, | 
|  | "USB 2.0") 80% is reserved. | 
|  |  | 
|  |  | 
|  | Device descriptor info & Product ID info | 
|  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | 
|  |  | 
|  | :: | 
|  |  | 
|  | D:  Ver=x.xx Cls=xx(s) Sub=xx Prot=xx MxPS=dd #Cfgs=dd | 
|  | P:  Vendor=xxxx ProdID=xxxx Rev=xx.xx | 
|  |  | 
|  | where:: | 
|  |  | 
|  | D:  Ver=x.xx Cls=xx(sssss) Sub=xx Prot=xx MxPS=dd #Cfgs=dd | 
|  | |   |        |             |      |       |       |__NumberConfigurations | 
|  | |   |        |             |      |       |__MaxPacketSize of Default Endpoint | 
|  | |   |        |             |      |__DeviceProtocol | 
|  | |   |        |             |__DeviceSubClass | 
|  | |   |        |__DeviceClass | 
|  | |   |__Device USB version | 
|  | |__Device info tag #1 | 
|  |  | 
|  | where:: | 
|  |  | 
|  | P:  Vendor=xxxx ProdID=xxxx Rev=xx.xx | 
|  | |   |           |           |__Product revision number | 
|  | |   |           |__Product ID code | 
|  | |   |__Vendor ID code | 
|  | |__Device info tag #2 | 
|  |  | 
|  |  | 
|  | String descriptor info | 
|  | ^^^^^^^^^^^^^^^^^^^^^^ | 
|  | :: | 
|  |  | 
|  | S:  Manufacturer=ssss | 
|  | |   |__Manufacturer of this device as read from the device. | 
|  | |      For USB host controller drivers (virtual root hubs) this may | 
|  | |      be omitted, or (for newer drivers) will identify the kernel | 
|  | |      version and the driver which provides this hub emulation. | 
|  | |__String info tag | 
|  |  | 
|  | S:  Product=ssss | 
|  | |   |__Product description of this device as read from the device. | 
|  | |      For older USB host controller drivers (virtual root hubs) this | 
|  | |      indicates the driver; for newer ones, it's a product (and vendor) | 
|  | |      description that often comes from the kernel's PCI ID database. | 
|  | |__String info tag | 
|  |  | 
|  | S:  SerialNumber=ssss | 
|  | |   |__Serial Number of this device as read from the device. | 
|  | |      For USB host controller drivers (virtual root hubs) this is | 
|  | |      some unique ID, normally a bus ID (address or slot name) that | 
|  | |      can't be shared with any other device. | 
|  | |__String info tag | 
|  |  | 
|  |  | 
|  |  | 
|  | Configuration descriptor info | 
|  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | 
|  | :: | 
|  |  | 
|  | C:* #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA | 
|  | | | |       |       |      |__MaxPower in mA | 
|  | | | |       |       |__Attributes | 
|  | | | |       |__ConfiguratioNumber | 
|  | | | |__NumberOfInterfaces | 
|  | | |__ "*" indicates the active configuration (others are " ") | 
|  | |__Config info tag | 
|  |  | 
|  | USB devices may have multiple configurations, each of which act | 
|  | rather differently.  For example, a bus-powered configuration | 
|  | might be much less capable than one that is self-powered.  Only | 
|  | one device configuration can be active at a time; most devices | 
|  | have only one configuration. | 
|  |  | 
|  | Each configuration consists of one or more interfaces.  Each | 
|  | interface serves a distinct "function", which is typically bound | 
|  | to a different USB device driver.  One common example is a USB | 
|  | speaker with an audio interface for playback, and a HID interface | 
|  | for use with software volume control. | 
|  |  | 
|  | Interface descriptor info (can be multiple per Config) | 
|  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | 
|  | :: | 
|  |  | 
|  | I:* If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=ssss | 
|  | | | |      |      |       |             |      |       |__Driver name | 
|  | | | |      |      |       |             |      |          or "(none)" | 
|  | | | |      |      |       |             |      |__InterfaceProtocol | 
|  | | | |      |      |       |             |__InterfaceSubClass | 
|  | | | |      |      |       |__InterfaceClass | 
|  | | | |      |      |__NumberOfEndpoints | 
|  | | | |      |__AlternateSettingNumber | 
|  | | | |__InterfaceNumber | 
|  | | |__ "*" indicates the active altsetting (others are " ") | 
|  | |__Interface info tag | 
|  |  | 
|  | A given interface may have one or more "alternate" settings. | 
|  | For example, default settings may not use more than a small | 
|  | amount of periodic bandwidth.  To use significant fractions | 
|  | of bus bandwidth, drivers must select a non-default altsetting. | 
|  |  | 
|  | Only one setting for an interface may be active at a time, and | 
|  | only one driver may bind to an interface at a time.  Most devices | 
|  | have only one alternate setting per interface. | 
|  |  | 
|  |  | 
|  | Endpoint descriptor info (can be multiple per Interface) | 
|  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | 
|  |  | 
|  | :: | 
|  |  | 
|  | E:  Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=dddss | 
|  | |   |        |            |         |__Interval (max) between transfers | 
|  | |   |        |            |__EndpointMaxPacketSize | 
|  | |   |        |__Attributes(EndpointType) | 
|  | |   |__EndpointAddress(I=In,O=Out) | 
|  | |__Endpoint info tag | 
|  |  | 
|  | The interval is nonzero for all periodic (interrupt or isochronous) | 
|  | endpoints.  For high speed endpoints the transfer interval may be | 
|  | measured in microseconds rather than milliseconds. | 
|  |  | 
|  | For high speed periodic endpoints, the ``EndpointMaxPacketSize`` reflects | 
|  | the per-microframe data transfer size.  For "high bandwidth" | 
|  | endpoints, that can reflect two or three packets (for up to | 
|  | 3KBytes every 125 usec) per endpoint. | 
|  |  | 
|  | With the Linux-USB stack, periodic bandwidth reservations use the | 
|  | transfer intervals and sizes provided by URBs, which can be less | 
|  | than those found in endpoint descriptor. | 
|  |  | 
|  | Usage examples | 
|  | ~~~~~~~~~~~~~~ | 
|  |  | 
|  | If a user or script is interested only in Topology info, for | 
|  | example, use something like ``grep ^T: /sys/kernel/debug/usb/devices`` | 
|  | for only the Topology lines.  A command like | 
|  | ``grep -i ^[tdp]: /sys/kernel/debug/usb/devices`` can be used to list | 
|  | only the lines that begin with the characters in square brackets, | 
|  | where the valid characters are TDPCIE.  With a slightly more able | 
|  | script, it can display any selected lines (for example, only T, D, | 
|  | and P lines) and change their output format.  (The ``procusb`` | 
|  | Perl script is the beginning of this idea.  It will list only | 
|  | selected lines [selected from TBDPSCIE] or "All" lines from | 
|  | ``/sys/kernel/debug/usb/devices``.) | 
|  |  | 
|  | The Topology lines can be used to generate a graphic/pictorial | 
|  | of the USB devices on a system's root hub.  (See more below | 
|  | on how to do this.) | 
|  |  | 
|  | The Interface lines can be used to determine what driver is | 
|  | being used for each device, and which altsetting it activated. | 
|  |  | 
|  | The Configuration lines could be used to list maximum power | 
|  | (in milliamps) that a system's USB devices are using. | 
|  | For example, ``grep ^C: /sys/kernel/debug/usb/devices``. | 
|  |  | 
|  |  | 
|  | Here's an example, from a system which has a UHCI root hub, | 
|  | an external hub connected to the root hub, and a mouse and | 
|  | a serial converter connected to the external hub. | 
|  |  | 
|  | :: | 
|  |  | 
|  | T:  Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12   MxCh= 2 | 
|  | B:  Alloc= 28/900 us ( 3%), #Int=  2, #Iso=  0 | 
|  | D:  Ver= 1.00 Cls=09(hub  ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1 | 
|  | P:  Vendor=0000 ProdID=0000 Rev= 0.00 | 
|  | S:  Product=USB UHCI Root Hub | 
|  | S:  SerialNumber=dce0 | 
|  | C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr=  0mA | 
|  | I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub | 
|  | E:  Ad=81(I) Atr=03(Int.) MxPS=   8 Ivl=255ms | 
|  |  | 
|  | T:  Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12   MxCh= 4 | 
|  | D:  Ver= 1.00 Cls=09(hub  ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1 | 
|  | P:  Vendor=0451 ProdID=1446 Rev= 1.00 | 
|  | C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA | 
|  | I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub | 
|  | E:  Ad=81(I) Atr=03(Int.) MxPS=   1 Ivl=255ms | 
|  |  | 
|  | T:  Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=1.5  MxCh= 0 | 
|  | D:  Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1 | 
|  | P:  Vendor=04b4 ProdID=0001 Rev= 0.00 | 
|  | C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA | 
|  | I:  If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=01 Prot=02 Driver=mouse | 
|  | E:  Ad=81(I) Atr=03(Int.) MxPS=   3 Ivl= 10ms | 
|  |  | 
|  | T:  Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#=  4 Spd=12   MxCh= 0 | 
|  | D:  Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1 | 
|  | P:  Vendor=0565 ProdID=0001 Rev= 1.08 | 
|  | S:  Manufacturer=Peracom Networks, Inc. | 
|  | S:  Product=Peracom USB to Serial Converter | 
|  | C:* #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr=100mA | 
|  | I:  If#= 0 Alt= 0 #EPs= 3 Cls=00(>ifc ) Sub=00 Prot=00 Driver=serial | 
|  | E:  Ad=81(I) Atr=02(Bulk) MxPS=  64 Ivl= 16ms | 
|  | E:  Ad=01(O) Atr=02(Bulk) MxPS=  16 Ivl= 16ms | 
|  | E:  Ad=82(I) Atr=03(Int.) MxPS=   8 Ivl=  8ms | 
|  |  | 
|  |  | 
|  | Selecting only the ``T:`` and ``I:`` lines from this (for example, by using | 
|  | ``procusb ti``), we have | 
|  |  | 
|  | :: | 
|  |  | 
|  | T:  Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12   MxCh= 2 | 
|  | T:  Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12   MxCh= 4 | 
|  | I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub | 
|  | T:  Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=1.5  MxCh= 0 | 
|  | I:  If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=01 Prot=02 Driver=mouse | 
|  | T:  Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#=  4 Spd=12   MxCh= 0 | 
|  | I:  If#= 0 Alt= 0 #EPs= 3 Cls=00(>ifc ) Sub=00 Prot=00 Driver=serial | 
|  |  | 
|  |  | 
|  | Physically this looks like (or could be converted to):: | 
|  |  | 
|  | +------------------+ | 
|  | |  PC/root_hub (12)|   Dev# = 1 | 
|  | +------------------+   (nn) is Mbps. | 
|  | Level 0           |  CN.0   |  CN.1  |   [CN = connector/port #] | 
|  | +------------------+ | 
|  | / | 
|  | / | 
|  | +-----------------------+ | 
|  | Level 1   | Dev#2: 4-port hub (12)| | 
|  | +-----------------------+ | 
|  | |CN.0 |CN.1 |CN.2 |CN.3 | | 
|  | +-----------------------+ | 
|  | \           \____________________ | 
|  | \_____                          \ | 
|  | \                          \ | 
|  | +--------------------+      +--------------------+ | 
|  | Level 2      | Dev# 3: mouse (1.5)|      | Dev# 4: serial (12)| | 
|  | +--------------------+      +--------------------+ | 
|  |  | 
|  |  | 
|  |  | 
|  | Or, in a more tree-like structure (ports [Connectors] without | 
|  | connections could be omitted):: | 
|  |  | 
|  | PC:  Dev# 1, root hub, 2 ports, 12 Mbps | 
|  | |_ CN.0:  Dev# 2, hub, 4 ports, 12 Mbps | 
|  | |_ CN.0:  Dev #3, mouse, 1.5 Mbps | 
|  | |_ CN.1: | 
|  | |_ CN.2:  Dev #4, serial, 12 Mbps | 
|  | |_ CN.3: | 
|  | |_ CN.1: |