USB (Universal Serial Bus) is a hardware and protocol specification for interconnecting various devices to a host controller. We supply a USB stack that implements the USB protocol and allows user-written class drivers to communicate with USB devices.
We also supply a USB driver library (usbd_*()) for class drivers to use in order to communicate with the USB stack. Note that a class driver can be considered a “client” of the USB stack.
The stack is implemented as a standalone process that registers the pathname of /dev/io-usb/io-usb (by default). Currently, the stack contains the hub class driver within it.
The stack supports the three industry-standard HCI types:
We provide separate servers for each type (devu-ohci.so, devu-uhci.so, and devu-ehci.so). Note that USB devices don't care whether a computer has an OHCI, UHCI, or an EHCI controller.
The client library provides functions to allocate data buffers in shared memory; the stack manages these data buffers and gives the client library access to them. This means that all data transfers must use the provided buffers.
As a result, a class driver must reside on the same physical node as the USB stack. The clients of the class driver, however, can be network-distributed. The advantage of this approach is that no additional memory copy occurs between the time that the data is received by the USB stack and the time that it's delivered to the class driver (and vice versa).
With the QNX Neutrino OS, the USB enumerator attaches to the USB stack and waits for device insertions. When a device insertion is detected, the enumerator looks in the configuration manager's database to see which class driver it should start. It then starts the appropriate driver, which provides for that class of device. For example, a USB Ethernet class driver would register with io-pkt* and bring the interface up.
For small, deeply embedded systems, the enumerator isn't required. The class drivers can be started individually — they'll wait around for their particular devices to be detected by the stack. At that point, they'll provide the appropriate services for that class of device, just as if they'd been started by the enumerator. When a device is removed, the enumerator will shut down the class driver.
For more information about device enumeration, see the Controlling How Neutrino Starts chapter of the Neutrino User's Guide.
A class driver typically performs the following operations:
In this context, the term “pipe” is a USB-specific term that has nothing to do with standard POSIX “pipes” (as used, for example, in the command line ls | more). In USB terminology, a “pipe” is simply a handle; something that identifies a connection to an endpoint. |