1057 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			1057 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
| .. _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 ``include/uapi/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. That file is itself included by
 | |
| ``include/linux/usb/ch9.h``, which also contains declarations of a few
 | |
| utility routines for manipulating these data types; the implementations
 | |
| are in ``drivers/usb/common/common.c``.
 | |
| 
 | |
| .. kernel-doc:: drivers/usb/common/common.c
 | |
|    :export:
 | |
| 
 | |
| In addition, some functions useful for creating debugging output are
 | |
| defined in ``drivers/usb/common/debug.c``.
 | |
| 
 | |
| .. _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_GET_SPEED
 | |
|     Returns the speed of the device. The speed is returned as a
 | |
|     nummerical value in accordance with enum usb_device_speed
 | |
| 
 | |
|     File modification time is not updated by this request.
 | |
| 
 | |
| 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)
 | |
| 	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:
 |