Difference between revisions of "USB"
(2 intermediate revisions by the same user not shown) | |||
Line 37: | Line 37: | ||
==== Limits on transfer size ==== | ==== Limits on transfer size ==== | ||
Bulk transfer size should always be smaller than 4 MB and the Control transfers even less. | Bulk transfer size should always be smaller than 4 MB and the Control transfers even less. | ||
− | See [[http://msdn.microsoft.com/en-us/library/windows/hardware/ff538112%28v=vs.85%29.aspx | + | See [[http://msdn.microsoft.com/en-us/library/windows/hardware/ff538112%28v=vs.85%29.aspx MSDN about this issue]]. |
Using transfer- and packet sizes which are too large may result in unexpected | Using transfer- and packet sizes which are too large may result in unexpected | ||
behavior and may cause software crashes or even a reboot of the PC. | behavior and may cause software crashes or even a reboot of the PC. | ||
Line 438: | Line 438: | ||
The strings are encoded in the Unicode format and products can be made to | The strings are encoded in the Unicode format and products can be made to | ||
support multiple languages. String Index 0 should return a list of supported languages. | support multiple languages. String Index 0 should return a list of supported languages. | ||
+ | |||
+ | Only exception is the string used for the serial number. | ||
+ | Unicode characters are allowed, but the OS (e.g. Windows) may not see the difference between 2 devices connected to the computer when both VID and PID are the same. | ||
+ | Windows will only accept characters not containing a comma (",") and only ASCII-characters with an ASCII-code between 0x20 ... 0x7F (hex). | ||
+ | When other characters are used for the serial number, Windows will consider the device not having a serial number. | ||
== Setup Packet == | == Setup Packet == | ||
Line 515: | Line 520: | ||
=== Standard Device Requests === | === Standard Device Requests === | ||
− | + | {| class="wikitable"- style="border-collapse: collapse; border-width: 1px; border-style: solid; border-color: #000" | |
− | {| class=" | + | ! class="col0" style="border-style: solid; border-width: 1px"| bmRequestType |
− | ! class="col0" | bmRequestType | + | ! class="col1 leftalign" style="border-style: solid; border-width: 1px" | bRequest |
− | ! class="col1 leftalign" | bRequest | + | ! class="col2 leftalign" style="border-style: solid; border-width: 1px"| wValue |
− | ! class="col2 leftalign" | wValue | + | ! class="col3 leftalign" style="border-style: solid; border-width: 1px"| wIndex |
− | ! class="col3 leftalign" | wIndex | + | ! class="col4" style="border-style: solid; border-width: 1px"| wLength |
− | ! class="col4" | wLength | + | ! class="col5 leftalign" style="border-style: solid; border-width: 1px"| Data |
− | ! class="col5 leftalign" | Data | ||
|- class="row1" | |- class="row1" | ||
− | | class="col0 leftalign" | 1000 0000b | + | | class="col0 leftalign" style="border-style: solid; border-width: 1px"| 1000 0000b |
− | | class="col1 leftalign" | GET_STATUS (0x00) | + | | class="col1 leftalign" style="border-style: solid; border-width: 1px"| GET_STATUS (0x00) |
− | | class="col2 leftalign" | Zero | + | | class="col2 leftalign" style="border-style: solid; border-width: 1px"| Zero |
− | | class="col3 leftalign" | Zero | + | | class="col3 leftalign" style="border-style: solid; border-width: 1px"| Zero |
− | | class="col4 leftalign" | Two | + | | class="col4 leftalign" style="border-style: solid; border-width: 1px"| Two |
− | | class="col5 leftalign" | Device Status | + | | class="col5 leftalign" style="border-style: solid; border-width: 1px"| Device Status |
|- class="row2" | |- class="row2" | ||
− | | class="col0 leftalign" | 0000 0000b | + | | class="col0 leftalign" style="border-style: solid; border-width: 1px"| 0000 0000b |
− | | class="col1 leftalign" | SET_ADDRESS (0x05) | + | | class="col1 leftalign" style="border-style: solid; border-width: 1px"| SET_ADDRESS (0x05) |
− | | class="col2 leftalign" | Device Address | + | | class="col2 leftalign" style="border-style: solid; border-width: 1px"| Device Address |
− | | class="col3 leftalign" | Zero | + | | class="col3 leftalign" style="border-style: solid; border-width: 1px"| Zero |
− | | class="col4 leftalign" | Zero | + | | class="col4 leftalign" style="border-style: solid; border-width: 1px"| Zero |
− | | class="col5 leftalign" | None | + | | class="col5 leftalign" style="border-style: solid; border-width: 1px"| None |
|- class="row3" | |- class="row3" | ||
− | | class="col0 leftalign" | 0000 0000b | + | | class="col0 leftalign" style="border-style: solid; border-width: 1px"| 0000 0000b |
− | | class="col1 leftalign" | CLEAR_FEATURE (0x01) | + | | class="col1 leftalign" style="border-style: solid; border-width: 1px"| CLEAR_FEATURE (0x01) |
− | | class="col2 leftalign" | Feature Selector | + | | class="col2 leftalign" style="border-style: solid; border-width: 1px"| Feature Selector |
− | | class="col3 leftalign" | Zero | + | | class="col3 leftalign" style="border-style: solid; border-width: 1px"| Zero |
− | | class="col4 leftalign" | Zero | + | | class="col4 leftalign" style="border-style: solid; border-width: 1px"| Zero |
− | | class="col5 leftalign" | None | + | | class="col5 leftalign" style="border-style: solid; border-width: 1px"| None |
|- class="row4" | |- class="row4" | ||
− | | class="col0 leftalign" | 0000 0000b | + | | class="col0 leftalign" style="border-style: solid; border-width: 1px"| 0000 0000b |
− | | class="col1 leftalign" | SET_FEATURE (0x03) | + | | class="col1 leftalign" style="border-style: solid; border-width: 1px"| SET_FEATURE (0x03) |
− | | class="col2 leftalign" | Feature Selector | + | | class="col2 leftalign" style="border-style: solid; border-width: 1px"| Feature Selector |
− | | class="col3 leftalign" | Zero | + | | class="col3 leftalign" style="border-style: solid; border-width: 1px"| Zero |
− | | class="col4 leftalign" | Zero | + | | class="col4 leftalign" style="border-style: solid; border-width: 1px"| Zero |
− | | class="col5 leftalign" | None | + | | class="col5 leftalign" style="border-style: solid; border-width: 1px"| None |
|- class="row5" | |- class="row5" | ||
− | | class="col0 leftalign" | 1000 0000b | + | | class="col0 leftalign" style="border-style: solid; border-width: 1px"| 1000 0000b |
− | | class="col1 leftalign" | GET_DESCRIPTOR (0x06) | + | | class="col1 leftalign" style="border-style: solid; border-width: 1px"| GET_DESCRIPTOR (0x06) |
− | | class="col2" | Descriptor Type & Index | + | | class="col2" style="border-style: solid; border-width: 1px"| Descriptor Type & Index |
− | | class="col3" | Zero or Language ID | + | | class="col3" style="border-style: solid; border-width: 1px"| Zero or Language ID |
− | | class="col4" | Descriptor Length | + | | class="col4" style="border-style: solid; border-width: 1px"| Descriptor Length |
− | | class="col5" | Descriptor | + | | class="col5" style="border-style: solid; border-width: 1px"| Descriptor |
|- class="row6" | |- class="row6" | ||
− | | class="col0 leftalign" | 0000 0000b | + | | class="col0 leftalign" style="border-style: solid; border-width: 1px"| 0000 0000b |
− | | class="col1 leftalign" | SET_DESCRIPTOR (0x07) | + | | class="col1 leftalign" style="border-style: solid; border-width: 1px"| SET_DESCRIPTOR (0x07) |
− | | class="col2" | Descriptor Type & Index | + | | class="col2" style="border-style: solid; border-width: 1px"| Descriptor Type & Index |
− | | class="col3" | Zero or Language ID | + | | class="col3" style="border-style: solid; border-width: 1px"| Zero or Language ID |
− | | class="col4" | Descriptor Length | + | | class="col4" style="border-style: solid; border-width: 1px"| Descriptor Length |
− | | class="col5" | Descriptor | + | | class="col5" style="border-style: solid; border-width: 1px"| Descriptor |
|- class="row7" | |- class="row7" | ||
− | | class="col0 leftalign" | 1000 0000b | + | | class="col0 leftalign" style="border-style: solid; border-width: 1px"| 1000 0000b |
− | | class="col1" | GET_CONFIGURATION (0x08) | + | | class="col1" style="border-style: solid; border-width: 1px"| GET_CONFIGURATION (0x08) |
− | | class="col2 leftalign" | Zero | + | | class="col2 leftalign" style="border-style: solid; border-width: 1px"| Zero |
− | | class="col3 leftalign" | Zero | + | | class="col3 leftalign" style="border-style: solid; border-width: 1px"| Zero |
− | | class="col4 leftalign" | 1 | + | | class="col4 leftalign" style="border-style: solid; border-width: 1px"| 1 |
− | | class="col5 leftalign" | Configuration Value | + | | class="col5 leftalign" style="border-style: solid; border-width: 1px"| Configuration Value |
|- class="row8" | |- class="row8" | ||
− | | class="col0 leftalign" | 0000 0000b | + | | class="col0 leftalign" style="border-style: solid; border-width: 1px"| 0000 0000b |
− | | class="col1" | SET_CONFIGURATION (0x09) | + | | class="col1" style="border-style: solid; border-width: 1px"| SET_CONFIGURATION (0x09) |
− | | class="col2 leftalign" | Configuration Value | + | | class="col2 leftalign" style="border-style: solid; border-width: 1px"| Configuration Value |
− | | class="col3 leftalign" | Zero | + | | class="col3 leftalign" style="border-style: solid; border-width: 1px"| Zero |
− | | class="col4 leftalign" | Zero | + | | class="col4 leftalign" style="border-style: solid; border-width: 1px"| Zero |
− | | class="col5 leftalign" | None | + | | class="col5 leftalign" style="border-style: solid; border-width: 1px"| None |
− | |} | + | |} |
The '''Get Status''' request directed at the device will return two bytes during the | The '''Get Status''' request directed at the device will return two bytes during the | ||
Line 638: | Line 642: | ||
It should contain the value of ''bConfigurationValue'' of the desired configuration | It should contain the value of ''bConfigurationValue'' of the desired configuration | ||
descriptor in the lower byte of ''wValue'' to select which configuration to enable. | descriptor in the lower byte of ''wValue'' to select which configuration to enable. | ||
− | |||
=== Standard Interface Requests === | === Standard Interface Requests === |
Latest revision as of 23:19, 15 June 2012
Contents
Introduction to USB
USB Speeds
The USB bus is available in several versions, which also operate at a different speed.
- USB 1.1 - Low Speed - 1.5Mbits/s
- USB 1.1 - Full Speed - 12Mbits/s
- USB 2.0 - High Speed - 480Mbits/s
- USB 3.0 - Super Speed - 5000Mbits/s
USB 1.1 and USB 2.0 are pin- and plug-compatible, which means their cables can be interchanged. (given the cables can handle the higher speeds for USB 2.0)
USB 3.0 is downwards compatible, but the USB 3.0 cables cannot be used with older USB products, because they have an extra connector for the 5 Gbps (full duplex) data connection.
Topology
The Universal Serial Bus is host-controlled, which means there can only be one host per bus. The name would suggest the devices can attach to a bus or even daisy-chain, but it is more of a star topology and needs hubs to connect more devices to the bus. (upto 127 per bus/host)
Difference in host controller specifications
The USB host controllers have their own specifications.
- USB 1.1:
- UHCI (Universal Host Controller Interface) developed by Intel which puts more of the burden on software (Microsoft) and allowing for cheaper hardware
- OHCI (Open Host Controller Interface) developed by Compaq, Microsoft and National Semiconductor which places more of the burden on hardware(Intel) and makes for simpler software.
- USB 2.0:
- EHCI (Enhanced Host Controller Interface)
- USB 3.0:
- XHCI (Extensible Host Controller Interface)
Usually for the user these different specifications don't matter much. The only real difference is that the USB-stack of the OS used may put some limits on the transfer-size, depending on the used specification.
Limits on transfer size
Bulk transfer size should always be smaller than 4 MB and the Control transfers even less. See [MSDN about this issue]. Using transfer- and packet sizes which are too large may result in unexpected behavior and may cause software crashes or even a reboot of the PC.
Pipe | Windows 2000 | XP and Server 2003 | Vista and 7 |
---|---|---|---|
Control (default endpoint) | 4k | 4k | 4k |
Control (other endpoint) | 64k | 64k | 64k |
Interrupt | Undetermined | Unlimited | 4096k |
UHCI Bulk | Undetermined | 4096k | |
OHCI Bulk | 256k | 256k | |
EHCI Bulk | 3344k | 4096k | |
XHCI Bulk | ?? | ?? | |
Isochronous (full speed) | 256 frames | 256 frames | 256 frames |
Isochronous (high speed) | 1024 frames | 1024 frames | 1024 frames |
Encoding
USB 1.1 and USB 2.0 both use NRZI (Non Return to Zero Invert) encoding scheme to send data with a sync field to synchronize the host and receiver clocks. So sending a '1' will swap the polarity of the two data lines and sending a '0' will keep the last state. This means that sending too many consecutive '0' may lead to loss of synchronization between the host and reciever clocks. After 6 times a '0' the USB tranceiver will add an extra '1', which will be removed at the receiving end. However this may lead to extra bandwith use which cannot be used to transfer data. (up to 16.6%)
USB 3.0 does not use this kind of encoding, but instead uses 8b/10b, which adds 25% of extra bandwidth usage, but this loss isn't depending on the data being sent.
USB Product-ID and Vendor-ID
Officially it is only possible to buy one vendor-ID from USB-if (the organisation behind the USB standard) which costs 2000 US$. With such a vendor-ID comes 216 product-ID combinations. There has been a number of people who bought such a vendor-ID of which they sold product-IDs for about euro 10 each. However, after these were bought, USB-if changed the rules and it is now forbidden to resell these product-IDs. There is a number of dealers who still keep selling these product-IDs, but the status of these numbers is unknown. One of these is vendor-ID 0x16C0, which is still assigned to "Voti".
USB communication
An USB device is addressed by its function. This function can be a scanner or a printer, or some other peripheral. When a host will address a function, it must send a packet to the address of an USB device and in that USB device to an endpoint. The last part to access a function is the direction in which the data will flow.
Endpoints
Endpoints can be described as sources or sinks of data. As the bus is host centric, endpoints occur at the end of the communications channel at the USB function. At the software layer, your device driver may send a packet to your devices EP1 for example. As the data is flowing out from the host, it will end up in the EP1 OUT buffer. The firmware will then read this data. If it wants to return data, the function cannot simply write to the bus as the bus is controlled by the host. Therefore it writes data to EP1 IN which sits in the buffer until such time when the host sends a IN packet to that endpoint requesting the data. Endpoints can also be seen as the interface between the hardware of the function device and the firmware running on the function device.
All devices must support endpoint zero. This is the endpoint which receives all of the devices control and status requests during enumeration and throughout the duration while the device is operational on the bus.
Transfer Type |
Control | Interrupt | Bulk | Isochronous |
---|---|---|---|---|
Typical use | Device initialisation and management |
Mouse and Keyboard |
Printer and Mass Storage |
Streaming Audio and Video |
Low-speed support |
Yes | Yes | No | No |
Error correction |
Yes | Yes | Yes | No |
Guaranteed Delivery Rate |
No | No | No | Yes |
Guaranteed Bandwidth |
Yes (10%) | Yes (90%) | No | Yes (90%) |
Guaranteed Latency |
No | Yes | No | Yes |
Pipes
While the device sends and receives data on a series of endpoints, the client software transfers data through pipes. A pipe is a logical connection between the host and endpoint(s). Pipes will also have a set of parameters associated with them such as how much bandwidth is allocated to it, what transfer type (Control, Bulk, Iso or Interrupt) it uses, a direction of data flow and maximum packet/buffer sizes. For example the default pipe is a bi-directional pipe made up of endpoint zero in and endpoint zero out with a control transfer type.
USB defines two types of pipes:
- Control Pipes or Message Pipes have a defined USB format. They are host controlled, which are initiated by a request sent from the host. Data is then transferred in the desired direction, dictated by the request. Therefore message pipes allow data to flow in both directions but will only support control transfers.
- Data Pipes or Stream Pipes have no defined USB format, that is you can send any type of data down a stream pipe and can retrieve the data out the other end. Data flows sequentially and has a pre-defined direction, either in or out. Stream pipes will support bulk, isochronous and interrupt transfer types. Stream pipes can either be controlled by the host or device.
Endpoint Types
The Universal Serial Bus specification defines four transfer/endpoint types,
- Control Transfers
- Interrupt Transfers
- Isochronous Transfers
- Bulk Transfers
Control Transfers
Control transfers have two uses. Control transfers carry the requests that are defined by the USB specification and used by the host to learn about and configure devices. Control transfers can also carry requests defined by a class or vendor for any purpose.
Properties of Control Transfers:
- Typical use: Identification and configuration
- Required on any USB device
- No Guaranteed Latency
- Message Pipe - Bidirectional
- Error detection and next period retry.
- High Speed:
- Bytes per millisecond: 15872
- Max possible per pipe: Thirty-one 64-byte transactions per microframe
- Full Speed:
- Bytes per millisecond: 832
- Max possible per pipe: Thirteen 64-byte transaction per frame
- Low Speed:
- Bytes per millisecond: 24
- Max possible per pipe: Three 8-byte transactions
Interrupt Transfers
Any one who has had experience of interrupt requests on microcontrollers will know that interrupts are device generated. However under USB if a device requires the attention of the host, it must wait until the host polls it before it can report that it needs urgent attention!
Properties of Interrupt Transfers:
- Typical use: Mouse, Keyboard
- Guaranteed Latency
- Stream Pipe - Unidirectional (USB 1.0 supports IN only)
- Error detection and next period retry.
- High Speed:
- Bytes per millisecond: 24576
- Max possible per pipe: Three 1024-byte transactions per microframe
- Full Speed:
- Bytes per millisecond: 64
- Max possible per pipe: One 64-byte transaction per frame
- Low Speed:
- Bytes per millisecond: 0.8
- Max possible per pipe: 8 bytes per 10 milliseconds
Interrupt transfers are typically non-periodic, small device "initiated"
communication requiring bounded latency.
An Interrupt request is queued by the device until the host polls the USB device asking for data.
The maximum data payload size is:
- For low-speed devices: 8 bytes
- For full-speed devices: 64 bytes
- For high-speed devices: 1024 bytes
Isochronous Transfers
Isochronous transfers occur continuously and periodically. They typically contain time sensitive information, such as an audio or video stream. If there were a delay or retry of data in an audio stream, then you would expect some erratic audio containing glitches. The beat may no longer be in sync. However if a packet or frame was dropped every now and again, it is less likely to be noticed by the listener.
Properties of Isochronous Transfers:
- Typical use: Streaming audio/video
- Guaranteed access to USB bandwidth.
- Bounded latency.
- Stream Pipe - Unidirectional
- Error detection via CRC, but no retry or guarantee of delivery.
- Full & high speed modes only.
- High Speed:
- Bytes per millisecond: 24576
- Max possible per pipe: Three 1024-byte transactions per microframe
- Full Speed:
- Bytes per millisecond: 1023
- Max possible per pipe: One 1023-byte transaction per frame
The maximum data payload size specified in the endpoint descriptor of an Isochronous Endpoint.
This can be up to:
- For full-speed devices: 1023 bytes
- For high-speed devices: 1024 bytes
When using a large payload, it may also be advised to specify a series of alternative interfaces with varying isochronous payload sizes. If during enumeration, the host cannot enable the preferred isochronous endpoint due to bandwidth restrictions, it has something to fall back on rather than just failing completely.
Bulk Transfers
Bulk transfers are intended for situations where the rate of transfer isn't critical. Such examples could include a print-job sent to a printer or an image generated from a scanner. Bulk transfers provide error correction in the form of a CRC16 field on the data payload and error detection/re-transmission mechanisms ensuring data is transmitted and received without error.
Bulk transfers will use spare un-allocated bandwidth on the bus after all other transactions have been allocated. If the bus is busy with isochronous and/or interrupt then bulk data may slowly trickle over the bus. As a result Bulk transfers should only be used for time insensitive communication as there is no guarantee of latency.
Properties of Bulk Transfers:
- Typical use: Printer, scanner, hard drive
- Error detection via CRC, with guarantee of delivery.
- No guarantee of bandwidth or minimum latency.
- Stream Pipe - Unidirectional
- Full & high speed modes only.
- High Speed:
- Bytes per millisecond: 53248
- Max possible per pipe: Thirteen 512-byte transactions per microframe
- Full Speed:
- Bytes per millisecond: 1216
- Max possible per pipe: Nineteen 64-byte transactions per frame
Maximum packet size:
- Full speed endpoints: either 8, 16, 32 or 64 bytes
- High speed endpoints: up to 512 bytes
A bulk transfer is considered complete when it has transferred the exact amount of data requested, transferred a packet less than the maximum endpoint size, or transferred a zero-length packet.
USB Descriptors
All USB devices have a hierarchy of descriptors which describe to the host information such as what the device is, who makes it, what version of USB it supports, how many ways it can be configured, the number of endpoints and their types etc.
The more common USB descriptors are
- Device Descriptors
- Configuration Descriptors
- Interface Descriptors
- Endpoint Descriptors
- String Descriptors
Device Descriptor
The device descriptor of a USB device represents the entire device. As a result a USB device can only have one device descriptor.
It specifies some basic, yet important information about the device such as:
- Supported USB version
- Maximum packet size
- Vendor- and Product ID
- Number of Possible configurations
Configuration Descriptor
The majority of USB devices has only one Configuration Descriptor.
The configuration descriptor specifies values such as:
- Amount of power this particular configuration uses
- Whether the device is self or bus powered
- Number of interfaces
When a device is enumerated, the host reads the device descriptors and can make a decision of which configuration to enable.
Only one configuration can be enabled at a time.
Interface Descriptor
The interface descriptor could be seen as a header or grouping of the endpoints into a functional group performing a single feature of the device. For example you could have a multi-function fax/scanner/printer device. Interface descriptor one could describe the endpoints of the fax function, Interface descriptor two the scanner function and Interface descriptor three the printer function. Unlike the configuration descriptor, there is no limitation as to having only one interface enabled at a time.
A device could have 1 or many interface descriptors enabled at once.
N.B. Windows always represents different reported interfaces as separate devices.
Alternative Settings
An interface descriptor can have an Alternative Setting, which allows an interface to change settings on the fly. When a configuration is enabled, the interface descriptors with bAlternativeSettings set to zero is used. During operation the host can send a SetInterface Standard Device Request to that interface to switch to one of the alternative settings.
For example, the alternative setting may describe Bulk pipes as type of transfer for an endpoint while the "original" interface descriptor describes Interrupt pipes.
Endpoint Descriptor
Each endpoint descriptor is used to specify:
- type of transfer (Control, Isochronous, Bulk, Interrupt)
- direction
- polling interval
- maximum packet size
Endpoint zero, the default control endpoint is always assumed to be a control endpoint and as such never has a descriptor.
MaxPktSize is calculated by multiplying the low-order 11 bits of wMaxPacketSize by the value represented by 1 + the next 2 bits (bits 11 and 12).
wMaxPacketSize = buffer[4] | (buffer[5] << 8); wMaxPacketSize = (wMaxPacketSize & 0x7FF) * (1 + ((wMaxPacketSize >> 11) & 0x3));
String Descriptors
String descriptors provide human readable information and are optional. If they are not used, any string index fields of descriptors must be set to zero indicating there is no string descriptor available.
The strings are encoded in the Unicode format and products can be made to support multiple languages. String Index 0 should return a list of supported languages.
Only exception is the string used for the serial number. Unicode characters are allowed, but the OS (e.g. Windows) may not see the difference between 2 devices connected to the computer when both VID and PID are the same. Windows will only accept characters not containing a comma (",") and only ASCII-characters with an ASCII-code between 0x20 ... 0x7F (hex). When other characters are used for the serial number, Windows will consider the device not having a serial number.
Setup Packet
Every USB device must respond to setup packets on the default pipe. The setup packets are used for detection and configuration of the device and carry out common functions such as setting the USB device's address, requesting a device descriptor or checking the status of a endpoint.
Offset | Field | Size | Value | Description |
---|---|---|---|---|
0 | bmRequestType | 1 | Bit-Map | Bit 7 Data Phase Transfer Direction |
0 = Host to Device | ||||
1 = Device to Host | ||||
Bit 6..5 Type | ||||
0 = Standard | ||||
1 = Class | ||||
2 = Vendor | ||||
3 = Reserved | ||||
Bit 4..0 Recipient | ||||
0 = Device | ||||
1 = Interface | ||||
2 = Endpoint | ||||
3 = Other | ||||
4..31 = Reserved | ||||
1 | bRequest | 1 | Value | Request |
2 | wValue | 2 | Value | Value |
4 | wIndex | 2 | Index or Offset | Index |
6 | wLength | 2 | Count | Number of bytes to transfer if there is a data phase |
Standard Requests
Section 9.4 of the USB specification details the "Standard Device" requests required to be implemented for every USB device.
Standard Device Requests
bmRequestType | bRequest | wValue | wIndex | wLength | Data |
---|---|---|---|---|---|
1000 0000b | GET_STATUS (0x00) | Zero | Zero | Two | Device Status |
0000 0000b | SET_ADDRESS (0x05) | Device Address | Zero | Zero | None |
0000 0000b | CLEAR_FEATURE (0x01) | Feature Selector | Zero | Zero | None |
0000 0000b | SET_FEATURE (0x03) | Feature Selector | Zero | Zero | None |
1000 0000b | GET_DESCRIPTOR (0x06) | Descriptor Type & Index | Zero or Language ID | Descriptor Length | Descriptor |
0000 0000b | SET_DESCRIPTOR (0x07) | Descriptor Type & Index | Zero or Language ID | Descriptor Length | Descriptor |
1000 0000b | GET_CONFIGURATION (0x08) | Zero | Zero | 1 | Configuration Value |
0000 0000b | SET_CONFIGURATION (0x09) | Configuration Value | Zero | Zero | None |
The Get Status request directed at the device will return two bytes during the data stage with the following format:
D15 | D14 | D13 | D12 | D11 | D10 | D9 | D8 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Reserved | Remote Wakeup | Self Powered |
If D0 is set, then this indicates the device is self powered. If clear, the device is bus powered.
If D1 is set, the device has remote wakeup enabled and can wake the host up during suspend. The remote wakeup bit can be set by the SetFeature and ClearFeature requests with a feature selector of DEVICE_REMOTE_WAKEUP (0x01)
Clear Feature and Set Feature requests can be used to set boolean features. When the designated recipient is the device, the only two feature selectors available are DEVICE_REMOTE_WAKEUP and TEST_MODE. Test mode allows the device to exhibit various conditions. These are further documented in the USB Specification Revision 2.0.
Set Address is used during enumeration to assign a unique address to the USB device. The address is specified in wValue and can only be a maximum of 127.
Set Descriptor / Get Descriptor is used to return the specified descriptor in wValue. A request for the configuration descriptor will return the device descriptor and all interface and endpoint descriptors in the one request.
- Endpoint Descriptors cannot be accessed directly by a GetDescriptor/SetDescriptor Request.
- Interface Descriptors cannot be accessed directly by a GetDescriptor/SetDescriptor Request.
- String Descriptors include a Language ID in wIndex to allow for multiple language support.
Get Configuration / Set Configuration is used to request or set the current device configuration. In the case of a Get Configuration request, a byte will be returned during the data stage indicating the devices status.
- zero value => device is not configured
- non-zero value => device is configured
Set Configuration is used to enable a device. It should contain the value of bConfigurationValue of the desired configuration descriptor in the lower byte of wValue to select which configuration to enable.
Standard Interface Requests
The USB specification describes 5 standard interface requests, but only the GET_INTERFACE and SET_INTERFACE are useful. They can be used to get/set the alternative settings
Standard Endpoint Requests
bmRequestType | bRequest | wValue | Windex | wLength | Data |
---|---|---|---|---|---|
1000 0010b | GET_STATUS (0x00) | Zero | Endpoint | Two | Endpoint Status |
0000 0010b | CLEAR_FEATURE (0x01) | Feature | Selector | Endpoint Zero | None |
0000 0010b | SET_FEATURE (0x03) | Feature | Selector | Endpoint Zero | None |
1000 0010b | SYNCH_FRAME (0x12) | Zero | Endpoint | Two | Frame Number |
The wIndex field is used to specify the referring endpoint and direction
for requests directed to an endpoint. Its format is:
D15 | D14 | D13 | D12 | D11 | D10 | D9 | D8 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Reserved | Dir | Reserved | Endpoint Number |
Get Status returns two bytes indicating the status (Halted/Stalled) of a endpoint.
Only the least significant bit indicates a halt-status.
Clear Feature and Set Feature are used to set Endpoint Features.
Error handling
When a transfer to/from the device fails, the corresponding pipe is put into a halted state. No further transfers for that pipe are processed until the error condition on the pipe is cleared.
The following types of error recovery can be tried:
- Reset pipe: clears the error condition on the pipe on which the error occurred
- Reset port: resets the USB device thereby bringing it to a clean state
- Cycle Port: resets the USB device and in addition performs PNP re-enumeration of the client driver stack
Each of these actions require to cancel all I/O. A typical action to cancel all I/O would be to perform an abort pipe operation and wait for it to complete. No new IO for that pipe or device should be send until the Reset/Cycle operation is complete.
Reset pipe
This is the first step that should be done to recover from a USB error if a previous transfer to its non-default pipe failed. Failure can be due to a device error (such as USBD_STATUS_STALL_PID or USBD_STATUS_BABBLE_DETECTED), or due to an error reported by the host controller (such as USBD_STATUS_XACT_ERROR).
To reset the pipe, the following steps must be performed:
- Cancel all I/O (if any) for the faulting pipe and wait for it to complete.
- Request a reset pipe operation.
Note that performing a reset pipe without an abort pipe will only clear the error state and not cancel the sent request. So the "previous" request may still return data when a new request is sent. This previous request may still write to a buffer which is not in use anymore.
Reset Port
If even after resetting the pipe a transfer to the pipe still fails, the client driver can request a reset port operation. Reset port is more expensive than resetting the pipe and may result in more state loss.
To reset the port, the following steps must be performed:
- Cancel all IO (if any) for the device and wait for it to complete.
- Request a reset port operation.
In response to a reset port request, the core USB stack performs the following steps:
- Resets the USB device and re-enumerates it on the USB bus.
- Brings it to the same configuration as it was before the reset.
- Ensures that all the client driver's pipe handles remain valid.
Note that the entire device will be reset, which will also impact other functions of a multi-function device.
Cycle Port
Cycle port operation is similar to the device being unplugged and then plugged back in, except that the device is not electrically disconnected. Think of it as software unplug and re-plug. Cycle port may be used if the client driver itself wants to re-rebuild its PNP stack, in addition to resetting the device.
To cycle the port, the following steps must be performed:
- Cancel all IO (if any) for the device and wait for it to complete.
- Request a cycle port operation.
As a result of cycle port operation any application that has a handle open to the device will get a device removal notification (assuming the application registered for it).