Programming Architecture
The authors of the USB specification anticipated that programmers would need to understand how to write host and device software without necessarily needing or wanting to understand the electrical characteristics of the bus. Chapter 5, USB Data Flow Model, and Chapter 9, USB Device Framework, of the specification describe the features most useful to driver authors. In this section, I ll summarize those chapters.
Device Hierarchy
Figure 12-1 illustrates the topology of a simple USB setup. A host controller unit connects to the system bus in the same way other I/O devices might. The operating system communicates with the host controller by means of I/O ports or memory registers, and it receives event notifications from the host controller through an ordinary interrupt signal. The host controller in turn connects to a tree of USB devices. One kind of device, called a hub, serves as a connection point for other devices. The host controller includes a root hub. Hubs can be daisy chained together to a maximum depth defined by the USB specification. Currently up to five hubs can be chained from the root hub, for an overall tree depth of seven. Other kinds of devices, such as cameras, mice, keyboards, and so on, plug in to hubs. For the sake of precision, USB uses the term function to describe a device that isn t a hub. The specification currently allows for up to 127 functions and hubs to be attached to the bus.
Figure 12-1. Hierarchy of USB devices.
High-Speed, Full-Speed, and Low-Speed Devices
The USB specification categorizes devices by communication speed. A USB 2.0 controller drives the bus at 480 megabits per second. Devices (both hubs and functions) can operate at high speed (480 megabits per second), full speed (12 megabits per second), or low speed (1.5 megabits per second). In USB 2.0, hubs are responsible for communicating with full-speed and low-speed devices using a scheme that interferes as little as possible with the high-speed signaling employed by the bus and high-speed devices.
The previous version of the USB specification (1.1) provided just for full-speed and low-speed devices. Communication normally occurs on a 1.1 bus at full speed, and hubs normally don t send data to low-speed devices. The operating system prefaces any message destined for a low-speed device with a special preamble packet that causes the hubs to temporarily enable the low-speed devices.
Power
The USB cable carries power as well as data signals. Each hub can supply electrical power to the devices attached to it and, in the case of subsidiary hubs, to downstream devices as well. USB imposes limits on how much power a bus-powered device can consume. These limits vary depending on whether the device is plugged in to a powered hub, how far the device is from the nearest powered hub, and so on. In addition, USB allows devices to operate in a suspended state and consume very little power just enough to support wake-up and configuration signalling. Instead of relying on bus power, you can build independently powered hubs and devices. (In fact, the Windows Hardware Quality Lab (WHQL) accepts bus-powered hub devices for testing only when they re part of a composite device rather than being real hubs with ports for plugging devices in to.)
USB devices are able to awaken the system from a low-power state. When the system goes to low power, the operating system places the USB in the low-power state as well. A device possessing an enabled remote wake-up feature can later signal upstream to awaken upstream hubs, the USB host controller, and eventually the entire system.
USB device designers should be aware of some limitations on wake-up signalling. First, remote system wake-up works only on a computer with an Advanced Configuration and Power Interface (ACPI)-enabled BIOS. Older systems support either Advanced Power Management (APM) or no power-management standard at all. I ve also found tremendous variability among PCs in their ability to support USB wake-up. On a trip to a computer superstore in mid-2002, I found only one notebook computer that would respond to a USB device s wake-up signal. I know of no principled way except by experimentation to find out when a given computer and operating system combination will work in this regard.
USB hubs can support a power-management feature called selective suspend. This feature allows a hub to suspend ports individually and has the overall purpose of facilitating power management in battery-operated devices. Windows XP supports this feature by means of a special I/O control (IOCTL) that I ll discuss later in this chapter.
What s in a Device?
In general, each USB device can have one or more configurations that govern how it behaves. See Figure 12-2. Configurations of a single device can differ in their power consumption, their ability to remotely wake the computer, and in their populations of interfaces. Microsoft drivers invariably work with just the first configuration of a device. The Microsoft support for composite devices won t engage if the device has multiple configurations. Consequently, multiconfiguration devices seem to be rare in practice, and Microsoft discourages people from designing new ones. I ve heard of just these few scenarios in which multiple configurations would make sense:
An Integrated Services Digital Network (ISDN) communications device that presents either two 56-Kb channels or one 128-Kb channel
A device that presents a simple configuration for use by the BIOS and a more complex one for use by Windows drivers
A trackball that can be configured as either a mouse or a joystick
Figure 12-2. Device configurations, interfaces, and endpoints.
Each configuration of a device embodies one or more interfaces that prescribe how software should access the hardware. This concept of an interface is similar to the concept I discussed in Chapter 2 in connection with naming devices. That is, devices that support the same interface are essentially interchangeable in terms of software because they respond to the same commands in the same specified way. Also, interfaces frequently have alternate settings that correspond to different bandwidth requirements.
A device interface exposes one or more endpoints, each of which serves as a terminus for a communications pipe. Figure 12-3 diagrams a layered communication model that illustrates the role of a pipe and an endpoint. At the lowest level, the USB wire connects the host bus controller to the bus interface on a device. At the second level, a control pipe connects system software to a logical device. At the third and highest level, a bundle of pipes connects client software with the collection of interfaces that constitutes the device s function. Information actually flows vertically up and down both sides of the diagram, but it s useful to think of the pipes as carrying information horizontally between the corresponding layers.
Figure 12-3. Layered model for USB communication.
A set of drivers provided by Microsoft occupies the lower edge of the system software box in the figure. These drivers include a host controller driver (USBOHCI.SYS, USBUHCD.SYS, or USBEHCI.SYS), a hub driver (USBHUB.SYS), and a library used by all the system and client drivers (USBD.SYS). For convenience, I ll lump all of these drivers together under the name parent driver. Collectively, these drivers manage the hardware connection and the mechanics of communicating over the various pipes. WDM drivers, such as the ones you and I might write, occupy the upper edge of the system software box. Broadly speaking, the job of a WDM driver is to translate requests from client software into transactions that the parent driver can carry out. Client software deals with the actual functionality of the device. For example, an image-rendering application might occupy the client software slot opposite a still-image function such as that of a digital camera.
Information Flow
USB defines four methods of transferring data, as summarized in Table 12-1. The methods differ in the amount of data that can be moved in a single transaction see the next section for an explanation of the term transaction in whether any particular periodicity or latency can be guaranteed, and in whether errors will be automatically corrected. Each method corresponds to a particular type of endpoint. In fact, endpoints of a given type (that is, control, bulk, interrupt, or isochronous) always communicate with the host by using the corresponding transfer type.
Transfer Type | Description | Lossless? | Latency Guarantee? |
Control | Used to send and receive structured information of a control nature | Yes | Best effort |
Bulk | Used to send or receive blocks of unstructured data | Yes | No |
Interrupt | Like a bulk pipe but includes a maximum latency | Yes | Polled at guaranteed minimum rate |
Isochronous | Used to send or receive blocks of unstructured data with guaranteed periodicity | No | Read or written at regular intervals |
Endpoints have several attributes in addition to their type. One endpoint attribute is the maximum amount of data that the endpoint can provide or consume in a single transaction. Table 12-2 indicates the maximum values for each endpoint type for each speed of device. In general, any single transfer can involve less than the maximum amount of data that the endpoint is capable of handling. Another attribute of an endpoint is its direction, described as either input (information moves from the device to the host) or output (information moves from the host to the device). Finally, each endpoint has a number that functions along with the input/output direction indicator as the address of the endpoint.
Transfer Type | High Speed | Full Speed | Low Speed |
Control | 64 | 8, 16, 32, or 64 | 8 |
Bulk | < 512 | 8, 16, 32, or 64 | NA (Low-speed devices can t have bulk endpoints.) |
Interrupt | < 1024 | < 64 | < 8 |
Isochronous | < 3072 | < 1023 | NA (Low-speed devices can t have isochronous endpoints.) |
USB uses a polling protocol in which the host requests the device to carry out some function on a more or less regular basis. When a device needs to send data to the host, the host must somehow note this and issue a request to the device to send the data. In particular, USB devices don t interrupt the host computer in the traditional sense. In place of an asynchronous interrupt, USB provides interrupt endpoints that the host polls periodically. The host polls interrupt and isochronous endpoints at a frequency specified by an option in the endpoint descriptor, as follows:
For a USB 2.0 device operating at high speed, the polling interval, bInterval, must be in the range 1 through 16, inclusive, and specifies polling every 2bInterval-1 microframes.
For a USB 2.0 device operating at full speed, the polling interval must be in the range 1 through 16, inclusive, and specifies polling every 2bInterval-1 frames.
For a USB 1.1 device operating at full speed, an isochronous endpoint must specify a polling interval of 1 and an interrupt endpoint can specify a polling interval of 1 through 255, inclusive. Note that a USB 2.0 host driver need not distinguish between 2.0 and 1.1 devices when interpreting the polling interval for an isochronous device, since 21-1 == 1.
For a USB 1.1 device operating at low speed, an interrupt endpoint must specify a polling interval of 10 through 255. There are no isochronous endpoints in a low-speed device.
Information Packaging
When a client program sends or receives data over a USB pipe, it first calls a Win32 API that ultimately causes the function driver (that s us) to receive an I/O request packet (IRP). The driver s job is to direct the client request into a pipe ending at the appropriate endpoint on the device. It submits the requests to the bus driver, which breaks the requests into transactions. The bus driver schedules the transactions for presentation to the hardware. Information flows on a USB 2.0 bus in microframes that occur once every 125 microseconds and on a USB 1.1 bus in frames that occur once every millisecond. The bus driver must correlate the duration of all outstanding transactions so as to fit them into frames and microframes. Figure 12-4 illustrates the result of this process.
Figure 12-4. Transaction and frame model for information flow.
When a host communicates over a USB 2.0 bus to a full-speed or low-speed device, the transaction translation feature of a hub provides intermediate buffering to allow the upstream bus (that is, the bus on the host side of the hub) to continue running at high speed. In effect, a USB 2.0 hub operates full-speed and low-speed downstream ports (that is, ports on the side of the hub away from the host) as a USB 1.1 bus, with frames scheduled every millisecond.
When a host communicates over a USB 1.1 bus to a low-speed device, it introduces a special preamble packet to switch the bus signalling to low speed for the duration of a single transaction. Except at these times, low-speed devices are out of the signalling circuit.
In USB, a transaction has one or more phases. A phase is a token, data, or handshake packet. Depending on the type, a transaction consists of a token phase, an optional data phase, and an optional handshake phase, as shown in Figure 12-5. During the token phase, the host transmits a packet of data to all currently configured devices. The token packet includes a device address and (often) an endpoint number. Only the addressed device will process the transaction; devices neither read nor write data on the bus for the duration of transactions addressed to other devices. During the data phase, data is placed on the bus. For output transactions, the host puts data on the bus and the addressed device consumes it. For input transactions, the roles are reversed and the device places data on the bus for consumption by the host. During the handshake phase, either the device or the host places a packet on the bus that provides status information. When a device provides the handshake packet, it can send an ACK packet to indicate successful receipt of information, a NAK packet to indicate that it s busy and didn t attempt to receive information, or a STALL packet to indicate that the transaction was correctly received but logically invalid in some way. When the host provides the handshake, it can send only an ACK packet.
Figure 12-5. Phases of a bus transaction.
USB 2.0 uses an additional handshaking packet for output operations to bulk endpoints, called NYET. This is either the Russian word for no or a contraction of not yet. NYET is part of a flow-control scheme called PING, and it means that the endpoint cannot accept another full packet. The host is expected to defer sending additional output for a period of time governed by the endpoint s bInterval attribute (which was not used for bulk endpoints in USB 1.1). The purpose of the PING protocol and the NYET handshake is to avoid tying up the bus with data packets that are going to be NAK ed by a busy device.
You ll notice that there s no handshake packet that means, I found a transmission error in this transaction. Whoever is waiting for an acknowledgment is expected to realize that lack of acknowledgment implies an error and to retry the transaction. The USB designers believe that errors will be infrequent, by the way, which means that any occasional delay because of retries won t have a big effect on throughput.
More About Device Addressing
The previous text says that all configured devices receive the electrical signals associated with every transaction. This is almost true, but a true renaissance programmer should know another detail. When a USB device first comes on line, it responds to a default address (which happens to be numerically 0, but you don t need to know that). Certain electrical signalling occurs to alert the host bus driver that a new device has arrived on the scene, whereupon the bus driver assigns a device address and sends a control transaction to tell device number 0 what its real address is. From then on, the device answers only to the real address.
States of an Endpoint
In general, an endpoint can be in any of the states illustrated in Figure 12-6. In the Idle state, the endpoint is ready to process a new transaction initiated by the host. In the Busy state, the endpoint is busy processing a transaction and can t handle a new one. If the host tries to initiate a transaction to a busy endpoint (other than a control endpoint, as described in the next section), the device will respond with a NAK handshake packet to cause the host to retry later. Errors that the device detects in its own functionality (not including transmission errors) cause the device to send a STALL handshake packet for its current transaction and to enter the Stalled state. Control endpoints automatically unstall when they get a new transaction, but the host must send a clear feature control request to any other kind of endpoint before addressing another request to a stalled endpoint.
Figure 12-6. States of an endpoint.
Control Transfers
A control transfer conveys control information to or from a control endpoint on a device. For example, one part of the overall process by which the operating system configures a USB device is performing input control transfers to read various descriptor structures kept on board the device. Another part of the configuration process involves an output control transfer to establish one of the many possible configurations as current and to enable one or more interfaces. Control transfers are lossless in that the bus driver retries erroneous transfers up to three times before giving up and reporting an error status to upstream software. As indicated in Table 12-2, control endpoints must specify a maximum data transfer length of 8, 16, 32, or 64 bytes. An individual transaction can involve less data than the indicated maximum but not more.
Control transactions are a high priority in USB. A device isn t allowed to claim business as an excuse to avoid handling a control transaction. Moreover, the bus driver reserves up to 10 percent of each frame time (20 percent of each microframe for a high-speed device) for control transactions.
Every device has at least one control endpoint numbered 0 that responds to input and output control transactions. Strictly speaking, endpoints belong to configurations, but endpoint 0 is an exception in that it terminates the default control pipe for a device. Endpoint 0 is active even before the device receives its configuration and no matter which other endpoints (if any) are available. A device need not have additional control endpoints besides endpoint 0 (although the USB specification allows for the possibility) because endpoint 0 can service most control requests perfectly well. If you define a vendor-specific request that can t complete within the frame, however, you should create an additional control endpoint to forestall having your on-board handler preempted by a new transaction.
Each control transfer includes a setup stage, which can be followed by an optional data stage in which additional data moves to or from the device, and a status stage, in which the device either responds with an ACK packet or a STALL packet or doesn t respond at all. Figure 12-7 diagrams the setup stage, which includes a SETUP token, a data phase (not to be confused with the data stage of the transfer), and a handshake phase. The data and status stages of a control transfer follow the same protocol rules as a bulk transfer, as shown in the next subsection. Devices are required to accept control transfers at all times and can therefore not respond with NAK to indicate a busy endpoint. Sending an invalid request to a control endpoint elicits a STALL response, but the device automatically clears the stall condition when it receives the next SETUP packet. This special case of stalling is called protocol stall in the USB specification see Section 8.5.3.4.
The SETUP token that prefaces a control transfer consists of 8 data bytes, as illustrated in Figure 12-8. In this and other data layout figures, I m showing data bytes in the order in which they re transmitted over the USB wire, but I m showing bits within individual bytes starting with the high-order bit. Bits are transmitted over the wire starting with the least-significant bit, but host software and device firmware typically work with data after the bits have been reversed. Intel computers and the USB bus protocols employ the little-endian data representation, in which the least-significant byte of a multibyte data item occupies the lowest address. The 8051 microprocessor used in several USB chip sets, including the Cypress Semiconductor chip set, is actually a big-endian computer. Firmware must therefore take care to reverse data bytes appropriately.
Figure 12-7. Phases of the setup stage of a control transfer.
Figure 12-8. Contents of a SETUP token.
Notice in Figure 12-8 that the first byte of a SETUP token indicates the direction of information flow, a request type, and the type of entity that is the target of the control transfer. The request types are standard (defined as part of the USB specification), class (defined by the USB working group responsible for a given class of device), and vendor (defined by the maker of the device). Control requests can be addressed to the device as a whole, to a specified interface, to a specified endpoint, or to some other vendor-specific entity on the device. The second byte of the SETUP token indicates which request of the type indicated in the first byte is being made. Table 12-3 lists the standard requests that are currently defined. For information about class-specific requests, consult the appropriate device class specification. (See the first URL I gave you at the beginning of this chapter for information on how to find these specifications.) Device manufacturers are free to define their own vendor-specific request codes. For example, Cypress Semiconductor uses the request code A0h to download firmware from the host.
NOTE
Remember that control requests that affect the state of a particular endpoint are sent to a control endpoint and not to the endpoint whose state is affected.
Request Code | Symbolic Name | Description | Possible Recipients |
0 | GET_STATUS | Gets status information | Any |
1 | CLEAR_FEATURE | Clears a two-state feature | Any |
2 |
| (Reserved) |
|
3 | SET_FEATURE | Sets a two-state feature | Any |
4 |
| (Reserved) |
|
5 | SET_ADDRESS | Sets device address | Device |
6 | GET_DESCRIPTOR | Gets device, configuration, or string descriptor | Device |
7 | SET_DESCRIPTOR | Sets a descriptor (optional) | Device |
8 | GET_CONFIGURATION | Gets current configuration index | Device |
9 | SET_CONFIGURATION | Sets new current configuration | Device |
10 | GET_INTERFACE | Gets current alternate setting index | Interface |
11 | SET_INTERFACE | Enables alternate setting | Interface |
12 | SYNCH_FRAME | Reports synchronization frame number | (Isochronous) Endpoint |
The remainder of the SETUP packet contains a value code whose meaning depends on which request is being made, an index value with similarly mutable meaning, and a length field that indicates how many bytes of data are to be transferred during the data stage of the control transaction. The index field contains the endpoint or interface number when a control request addresses an endpoint or an interface. A 0 value for the data length implies that this particular transaction has no data phase.
I m not going to exhaustively describe all of the details of the various standard control requests; you should consult Section 9.4 of the USB specification for full information. I do want to briefly discuss the concept of a device feature, however. USB envisages that any of the addressable entities belonging to a device can have features that can be represented by the state of a single bit. Two such features are standardized for all devices, and one additional feature is standardized for controllers, hubs, and high-speed-capable functions.
The DEVICE_REMOTE_WAKEUP feature a feature belonging to the device as a whole indicates whether the device should use its ability (if any) to remotely wake up the computer when external events occur. Host software (specifically, the bus driver) enables or disables this feature by addressing a SET_FEATURE or CLEAR_FEATURE command to the device and specifying the value code 1 to designate the wake-up feature. The DDK uses the symbolic name USB_FEATURE_REMOTE_WAKEUP for this feature code.
CAUTION
Be sure your device really will signal a wake-up before turning on the DEVICE_REMOTE_WAKEUP bit in the configuration descriptor. The WHQL tests for USB devices specifically verify that the feature works if it s advertised.
The ENDPOINT_HALT feature a feature belonging to an endpoint indicates whether the endpoint is in the functional stall state. Host software can force an endpoint to stall by sending the endpoint a SET_FEATURE command with the value code 0 to designate ENDPOINT_HALT. The firmware that manages the endpoint might independently decide to stall too. Host software (once again, the bus driver) clears the stall condition by sending a CLEAR_FEATURE command with the value code 0. The DDK uses the symbolic name USB_FEATURE_ENDPOINT_STALL for this feature code.
Setting the TEST_MODE feature a feature belonging to the device places the device in a special test mode to facilitate compliance testing. Apart from hubs and controllers, only devices that can operate at high speed support this feature. You don t clear the TEST_MODE feature to exit from test mode; you power cycle the device instead.
The USB specification doesn t prescribe ranges of device or endpoint feature codes for vendor use. To avoid possible standardization issues later, you should avoid defining device-level or endpoint-level features. Instead, define your own vendor-type control transactions. Notwithstanding this advice, later in this chapter I ll show you a sample driver (FEATURE) that controls the 7-segment LED display on the Cypress Semiconductor development board. For purposes of that sample, I defined an interface-level feature numbered 42. (USB currently defines a few interface-level features for power management, so you wouldn t want to emulate my example except for learning about how features work.)
Bulk Transfers
A bulk transfer conveys up to 512 bytes of data to or from a bulk endpoint on a high-speed device or up to 64 bytes of data to or from a bulk endpoint on a full-speed device. Like control transfers, bulk transfers are lossless. Unlike control transfers, bulk transfers don t have any particular guaranteed latency. If the host has room left over in a frame or microframe after accommodating other bandwidth reservations, it will schedule pending bulk transfers.
Figure 12-9 illustrates the phases that make up a bulk transfer. The transfer begins with either an IN or an OUT token that addresses the device and the endpoint. In the case of an output transaction, a data phase follows in which data moves from the host to the device and then a handshake phase in which the device provides status feedback. If the endpoint is busy and unable to accept new data, it generates a NAK packet during the handshake phase the host will retry the output transaction later. If the endpoint is stalled, it generates a STALL packet during the handshake phase the host must later clear the halt condition before retrying the transmission. If the endpoint receives and processes the data correctly, it generates an ACK packet in the handshake phase. The only remaining case is the one in which the endpoint doesn t correctly receive the data for some reason and simply doesn t generate a handshake the host will detect the absence of any acknowledgment and automatically retry up to three times.
Following the IN token that introduces an input bulk transfer, the device performs one of two operations. If it can, it sends data to the host, whereupon the host either generates an ACK handshake packet to indicate error-free receipt of the data or stays mute to indicate some sort of error. If the host detects an error, the absence of an ACK to the device causes the data to remain available the host will retry the input operation later on. If the endpoint is busy or halted, however, the device generates a NAK or STALL handshake instead of sending data. The NAK indicates that the host should retry the input operation later, and the STALL requires the host to eventually send a clear feature command to reset the halt condition.
High-speed bulk output endpoints use a flow control protocol designed to minimize the amount of bus time wasted in fruitless attempts to send data that the endpoint can t accept. In USB 1.1, an endpoint sends a NAK regarding a transfer it can t accept. In USB 2.0, however, a high-speed bulk endpoint descriptor s bInterval value indicates the NAK rate. If this value is 0, the endpoint never sends a NAK. Otherwise, it specifies the frequency (in microframes) with which the endpoint can send a NAK regarding an output transaction. The host can use a special PING packet to determine whether the endpoint is ready for output, and the endpoint can respond with either an ACK or a NAK. After a NAK, the host can then choose to wait bInterval packets before sending a PING again. After an ACK, the host sends an output packet. If the endpoint receives this normally, it replies with an ACK if it can accept another packet or with a NYET if it cannot.
Figure 12-9. Phases of a bulk or an interrupt transfer.
Interrupt Transfers
An interrupt transfer is similar to a bulk transfer insofar as the operation of the bus and the device is concerned. It moves up to 1024 bytes (high speed), 64 bytes (full speed), or 8 bytes (low speed) of data losslessly to or from an interrupt endpoint. The main difference between interrupt and bulk transfers has to do with latency. An interrupt endpoint specifies a polling interval as described earlier in this chapter. The host reserves sufficient bandwidth to make sure of performing an IN or OUT transaction directed toward the endpoint at least as frequently as the polling interval.
NOTE
USB devices don t generate asynchronous interrupts: they always respond to a poll. You might need to know that the Microsoft host controller drivers effectively round the polling interval specified in an interrupt endpoint descriptor down to a power of 2 no greater than 32. For example, an endpoint that specifies a polling interval of 31 milliseconds will actually be polled every 16 milliseconds. A specified polling interval between 32 and 255 milliseconds results in an actual polling interval of 32 milliseconds.
Isochronous Transfers
An isochronous transfer moves up to 3072 data bytes to or from a high-speed endpoint during each microframe or up to 1023 data bytes to or from a full-speed endpoint during every bus frame. Because of the guaranteed periodicity of isochronous transfers, they re ideal for time-sensitive data such as audio signals. The guarantee of periodicity comes at a price, however: isochronous transfers that fail because of data corruption don t get retried automatically in fact, with an isochronous transfer, late is just as bad as wrong, so there s no point in doing in a retry.
An isochronous transaction consists of an IN or OUT token followed by a data phase in which data moves to or from the host. No handshake phase occurs because no errors are retried. See Figure 12-10.
Figure 12-10. Phases of an isochronous transfer.
The host reserves up to 80 percent of the bus bandwidth (90 percent in the case of a USB 1.1 bus) for isochronous and interrupt transfers. In fact, system software needs to reserve bandwidth in advance to make sure that all active devices can be accommodated. In USB 1.1, the available bandwidth translates to approximately 1500 bytes per 1-millisecond frame, or roughly 1.5 maximum-size endpoints. In USB 2.0, the available bandwidth translates to about 7400 bytes per 125-microsecond microframe, or roughly 2.5 maximum-size endpoints. Taking account of the higher data rate, USB 2.0 has almost 20 times the isochronous capacity of USB 1.1.
Descriptors
USB devices maintain on-board data structures known as descriptors to allow for self-identification to host software. Table 12-4 lists the different descriptor types. Each descriptor begins with a 2-byte header containing the byte count of the entire descriptor (including the header) and a type code. As a matter of fact, if you ignore the special case of a string descriptor concerning which, see String Descriptors a bit further on the length of a descriptor is implied by its type because all descriptors of a given type have the same length. The explicit length is nonetheless present in the header to provide for future extensibility. Additional, type-specific data follows the fixed header.
In the remainder of this section, I ll describe the layout of each type of descriptor by using the data structures defined in the DDK (specifically, in USB100.H). The official rendition of this information is in Section 9.6 of the USB specification.
Descriptor Type | Description |
Device | Describes an entire device |
Device Qualifier | Device configuration information for the other speed of operation |
Configuration | Describes one of the configurations of a device |
Other Speed Configuration | Configuration descriptor for the other speed of operation |
Interface | Describes one of the interfaces that s part of a configuration |
Endpoint | Describes one of the endpoints belonging to an interface |
String | Contains a human-readable Unicode string describing the device, a configuration, an interface, or an endpoint |
Device Descriptors
Each device has a single device descriptor that identifies the device to host software. The host uses a GET_DESCRIPTOR control transaction directed to endpoint 0 to read this descriptor. The device descriptor has the following definition in the DDK:
typedef struct _USB_DEVICE_DESCRIPTOR { UCHAR bLength; UCHAR bDescriptorType; USHORT bcdUSB; UCHAR bDeviceClass; UCHAR bDeviceSubClass; UCHAR bDeviceProtocol; UCHAR bMaxPacketSize0; USHORT idVendor; USHORT idProduct; USHORT bcdDevice; UCHAR iManufacturer; UCHAR iProduct; UCHAR iSerialNumber; UCHAR bNumConfigurations; } USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR;
The bLength field in a device descriptor will equal 18, and the bDescriptor Type field will equal 1 to indicate that it s a device descriptor. The bcdUSB field contains a version code (in binary-coded decimal) indicating the version of the USB specification to which this descriptor conforms. New devices use the value 0x0200 here to indicate conformance with the 2.0 specification, whether they support high-speed, full-speed, or low-speed operation.
The values bDeviceClass, bDeviceSubClass, and bDeviceProtocol identify the type of device. Possible device class codes are defined by the USB specification and at the time of this writing include the codes listed in Table 12-5. Individual device class working groups within the USB committee define subclass and protocol codes for each device class. For example, the audio class has subclass codes for control, streaming, and MIDI streaming interfaces. And the mass storage class defines protocol codes for various methods of using endpoints for data transfer.
You can specify a class for an entire device or at the interface level, but in practice the device class, subclass, and protocol codes are often in an interface descriptor rather than in the device descriptor. (The device descriptor contains 0 for these codes in such cases.) USB also provides an escape valve for unusual types of devices in the form of the device class code 255. A vendor can use this type code to designate a nonstandard device for which the subclass and protocol codes provide the vendor-specific description. For example, a device built around the Cypress Semiconductor chip set comes on line with a device descriptor having class, subclass, and protocol codes all equal to 255. (The device has an extensive collection of endpoints and is also capable of accepting a vendor-specific control request to download firmware that will change the personality of the device to something else having its own [new] set of descriptors.)
The bMaxPacketSize0 field of the device descriptor gives the maximum size of a data packet for a control transfer over endpoint 0. There isn t a separate endpoint descriptor for this endpoint (which every device has to implement), so this field is the only place where the number can be presented. Since this field is at offset 7 within the descriptor, the host can always read enough of the descriptor to retrieve this value, even if endpoint 0 is capable only of the minimum size transfer (8 bytes). Once the host knows how big endpoint 0 transfers can be, it can structure subsequent requests appropriately.
The idVendor and idProduct fields specify a vendor code and a vendor-specific product identifier for the device. bcdDevice specifies a release number (such as 0x0100 for version 1.0) for the device. These three fields determine which driver the host software will load when it detects the device. The USB organization assigns vendor codes, and each vendor assigns its own product codes.
Symbolic Name in DDK Header | Class Code | Description |
USB_DEVICE_CLASS_RESERVED | 0 | Indicates that class codes are in the interface descriptors |
USB_DEVICE_CLASS_AUDIO | 1 | Devices used to manipulate analog or digital audio, voice, and other sound-related data (but not including transport mechanisms) |
USB_DEVICE_CLASS_COMMUNICATIONS | 2 | Telecommunications devices, such as modems, telephones, and answering machines |
USB_DEVICE_CLASS_HUMAN_INTERFACE | 3 | Human interface devices (HID devices), such as keyboards and mice |
USB_DEVICE_CLASS_MONITOR | 4 | Display monitors |
USB_DEVICE_CLASS_PHYSICAL_INTERFACE | 5 | HID devices involving real-time physical feedback, such as force-feedback joysticks |
USB_DEVICE_CLASS_POWER | 6 | HID devices that perform power management, such as batteries, chargers, and so on |
USB_DEVICE_CLASS_PRINTER | 7 | Printers |
USB_DEVICE_CLASS_STORAGE | 8 | Mass storage devices, such as disk and CD-ROM |
USB_DEVICE_CLASS_HUB | 9 | USB hubs |
| 10 | Communications data |
| 11 | SmartCard reader |
| 12 | Content security |
| 220 | Diagnostic device |
| 224 | Wireless controller (e.g., Bluetooth) |
| 254 | Application-specific (firmware update, Infrared Data Association [IrDA] bridge) |
USB_DEVICE_CLASS_VENDOR_SPECIFIC | 255 | Vendor-defined device class |
Device Version Numbering
Microsoft strongly encourages vendors to increment the device version number for each revision of hardware or firmware to facilitate downstream software updates. Often a vendor releases a new version of hardware along with a revised driver. Also, hardware updates sometimes invalidate software patches or filter drivers that were present so as to address earlier hardware bugs. An automatic update mechanism might therefore have trouble updating a system if it can t determine which revision of the hardware it s working with.The iManufacturer, iProduct, and iSerialNumber fields identify string descriptors that provide a human-readable description of the manufacturer, the product, and the unit serial number. These strings are optional, and a 0 value in one of these fields indicates the absence of the descriptor. If you put a serial number on a device, Microsoft recommends that you make it unique for each physical device. If you do so, and if your driver is digitally signed, the end user will be able to move the device around to different ports on the same computer and have it recognized as being the same device.
Lastly, the bNumConfigurations field indicates how many configurations the device is capable of. Microsoft drivers work only with the first configuration of a device. I ll explain later, in Configuration, what you might do for a device that has multiple configurations.
Device Qualifier Descriptor
High-speed-capable USB 2.0 devices can operate at either high speed or full speed. They deliver a device descriptor corresponding to the speed at which they are actually operating. They also deliver a Device Qualifier Descriptor that describes the device-level information that might be different if the device were operating at the other speed:
typedef struct _USB_DEVICE_QUALIFIER_DESCRIPTOR { UCHAR bLength; UCHAR bDescriptorType; USHORT bcdUSB; UCHAR bDeviceClass; UCHAR bDeviceSubClass; UCHAR bDeviceProtocol; UCHAR bMaxPacketSize0; UCHAR bNumConfigurations; UCHAR bReserved; } USB_DEVICE_QUALIFIER_DESCRIPTOR, *PUSB_DEVICE_QUALIFIER_DESCRIPTOR;
Apart from bLength (10) and bDescriptorType (6), all of these fields have exactly the same meaning as in a device descriptor. This descriptor doesn t repeat the vendor, product, device, manufacturer, product, and serial number fields of the device descriptor, which is constant for a device for all supported speeds.
Configuration Descriptors
Each device has one or more configuration descriptors that describe the various configurations of which the device is capable. System software reads a configuration descriptor by performing a GET_DESCRIPTOR control transaction addressed to endpoint 0. The DDK defines the configuration descriptor structure as follows:
typedef struct _USB_CONFIGURATION_DESCRIPTOR { UCHAR bLength; UCHAR bDescriptorType; USHORT wTotalLength; UCHAR bNumInterfaces; UCHAR bConfigurationValue; UCHAR iConfiguration; UCHAR bmAttributes; UCHAR MaxPower; } USB_CONFIGURATION_DESCRIPTOR, *PUSB_CONFIGURATION_DESCRIPTOR;
The bLength and bDescriptorType fields will be 9 and 2, respectively, to indicate a configuration descriptor 9 bytes in length. The wTotalLength field contains the total length of this configuration descriptor plus the interface and endpoint descriptors that are part of the configuration. In general, the host performs one GET_DESCRIPTOR request to retrieve the 9-byte configuration descriptor proper and then anotherGET_DESCRIPTOR request specifying this total length. The second request, therefore, transfers the grand unified descriptor. (It s impossible to retrieve interface and endpoint descriptors except as part of a configuration descriptor.)
The bNumInterfaces field indicates how many interfaces are part of the configuration. The count includes just the interfaces themselves, not each alternate setting of an interface. The purpose of this field is to allow for multifunction devices such as keyboards that have embedded locator (mouse and the like) functionality.
The bConfigurationValue field is an index that identifies the configuration. You use this value in a SET_CONFIGURATION control request to select the configuration. The first configuration descriptor for a device has a nonzero value here. (Selecting configuration 0 puts the device in an unconfigured state in which only endpoint 0 is active.)
The iConfiguration field is an optional string descriptor index pointing to a Unicode description of the configuration. The value 0 indicates the absence of a string description.
The bmAttributes byte contains a bit mask describing power and perhaps other characteristics of this configuration. See Table 12-6. The unmentioned bits are reserved for future standardization. A configuration supporting remote wake-up will have the remote wake-up attribute set. The high-order 2 bits interact with the MaxPower field of the configuration descriptor to describe the power characteristics of the configuration. Basically, every configuration sets the high-order bit (which used to mean the device was powered from the bus) and also sets MaxPower to the maximum number of two milliamp power units that it will draw from the bus. A configuration that uses some local power will also set the self-powered attribute bit.
Bit Mask | Symbolic Name | Description |
80h | USB_CONFIG_BUS_POWERED | Obsolete should always be set to 1 |
40h | USB_CONFIG_SELF_POWERED | Configuration is self-powered |
20h | USB_CONFIG_REMOTE_WAKEUP | Configuration has a remote wake-up feature |
Other Speed Configuration Descriptors
An Other Speed Configuration Descriptor is identical to the corresponding Configuration Descriptor except that it uses a different type code 7. A high-speed-capable device supplies this descriptor to describe a configuration as it would appear if the device were operating at the other speed of which it is capable.
Interface Descriptors
Each configuration has one or more interface descriptors that describe the interface or interfaces that provide device functionality. System software can fetch an interface descriptor only as part of a GET_DESCRIPTOR control request that retrieves the entire configuration descriptor of which the interface descriptor is a part. The DDK defines the interface descriptor structure as follows:
typedef struct _USB_INTERFACE_DESCRIPTOR { UCHAR bLength; UCHAR bDescriptorType; UCHAR bInterfaceNumber; UCHAR bAlternateSetting; UCHAR bNumEndpoints; UCHAR bInterfaceClass; UCHAR bInterfaceSubClass; UCHAR bInterfaceProtocol; UCHAR iInterface; } USB_INTERFACE_DESCRIPTOR, *PUSB_INTERFACE_DESCRIPTOR;
The bLength and bDescriptorType fields will be 9 and 4, respectively, to indicate an interface descriptor 9 bytes in length. bInterfaceNumber and bAlternateSetting are index values that can be used in a SET_INTERFACE control transaction to specify activation of the interface. You should number the interfaces within a configuration, and the alternate settings within an interface, starting with 0 because system software and firmware will often treat an interface number as an index into an array.
The bNumEndpoints field indicates how many endpoints other than 0, which is assumed to always be present are part of the interface.
The bInterfaceClass, bInterfaceSubClass, and bInterfaceProtocol fields describe the functionality provided by the interface. A nonzero class code should be one of the device class codes I discussed earlier, in which case the subclass and protocol codes will have the same meaning as well. Zero values in these fields are not allowed at the present time 0 is reserved for future standardization.
Finally, iInterface is the index of a string descriptor containing a Unicode description of the interface. The value 0 indicates that no string is present. You ll want to supply interface string descriptors for a composite device since the parent driver will use those strings when enumerating the interfaces as child devices.
Endpoint Descriptors
Each interface has zero or more endpoint descriptors that describe the endpoint or endpoints that handle transactions with the host. System software can fetch an endpoint descriptor only as part of a GET_DESCRIPTOR control request that retrieves the entire configuration descriptor of which the endpoint descriptor is a part. The DDK defines the endpoint descriptor structure as follows:
typedef struct _USB_ENDPOINT_DESCRIPTOR { UCHAR bLength; UCHAR bDescriptorType; UCHAR bEndpointAddress; UCHAR bmAttributes; USHORT wMaxPacketSize; UCHAR bInterval; } USB_ENDPOINT_DESCRIPTOR, *PUSB_ENDPOINT_DESCRIPTOR;
The bLength and bDescriptorType fields will be 7 and 5, respectively, to indicate an endpoint descriptor of length 7 bytes. bEndpointAddress encodes the directionality and number of the endpoint, as illustrated in Figure 12-11. For example, the address value 0x82 denotes an IN endpoint numbered 2, and the address 0x02 denotes an OUT endpoint that s also numbered 2. Except for endpoint 0, the USB specification allows you to have two different endpoints that share the same number but perform transfers in the opposite direction. Many USB chip sets don t support this overloading of endpoint number, though.
Figure 12-11. Bit assignments within an endpoint descriptor s address field.
Figure 12-12 illustrates the layout of bits within an endpoint descriptor s bmAttributes field. Bits 0 through 1 define the endpoint type, corresponding to the data transfer types listed in Table 12-1. Bits 2 through 5 define additional attributes for isochronous endpoints.
Figure 12-12. Bit assignments within an endpoint descriptor s attributes field.
The wMaxPacketSize value indicates the largest amount of data the endpoint can transfer during one transaction. Consult Figure 12-13 for a bit layout of this field. Table 12-2 lists the possible values for this field for each type of endpoint. For example, a control or bulk endpoint on a full-speed device specifies the value 8, 16, 32, or 64. High-speed interrupt and isochronous endpoints can perform 1, 2, or 3 transactions in a microframe, as indicated by the coding in bits 11 through 12 of this field. The additional transactions allow additional data to be transferred in a microframe. See Table 12-7.
Figure 12-13. Bit assignments within an endpoint descriptor s packet size field.
Number of Additional Transactions | Allowable wMaxPacketSize Values (Bits 0-10) | Total Amount of Data per Microframe |
0 | 1-1024 | < 1024 |
1 | 513-1024 | < 2048 |
2 | 683-1024 | < 3072 |
Interrupt and isochronous endpoint descriptors specify a polling interval in the bInterval field. As discussed earlier in this chapter, this number indicates how often the host should poll the endpoint for a possible data transfer. A high-speed bulk endpoint descriptor specifies its NAK rate in the bInterval field.
String Descriptors
A device, configuration, or endpoint descriptor contains optional string indexes that identify human-readable strings. The strings themselves are stored on the device in Unicode in the form of USB string descriptors. System software can read a string descriptor by addressing a GET_DESCRIPTOR control request to endpoint 0. The DDK declares the string descriptor structure as follows:
typedef struct _USB_STRING_DESCRIPTOR { UCHAR bLength; UCHAR bDescriptorType; WCHAR bString[1]; } USB_STRING_DESCRIPTOR, *PUSB_STRING_DESCRIPTOR;
The bLength value is variable, depending on how long the string data is. The bDescriptorType field will be 3 to indicate that this is a string descriptor. The bString data contains the string data itself without a null terminator.
USB devices can support strings in multiple languages. String number 0 is an array of supported language identifiers rather than a character string. (The string index 0 used in another descriptor denotes the absence of a string reference. Thus, index number 0 is available for this special use.) The language identifiers are of the same LANGID type that Win32 programs use. For example, 0x0409 is the code for American English. The USB specification prescribes that a device should return an error when asked for a string descriptor for a language that the device doesn t advertise supporting, so you should read the string-zero array before issuing requests for string descriptors. Consult Section 9.6.7 of the USB specification for more information about language identifiers.
Other Descriptors
USB is an evolving specification, and I can present only a snapshot of its evolution at the time of writing. Many USB class specifications define one or more class-specific descriptors that appear within the block of data returned by a request to read a configuration descriptor. Discussing these class-specific descriptors is beyond the scope of this work, except to mention that class-specific descriptors will follow the interface descriptor to which they apply and precede the endpoint descriptors for that interface.