The 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.

A USB compliant Host expects all requests to be processed within a maximum period of 5 seconds. It also specifies stricter timing for specific requests:

These timeout periods are quite acceptable for even the slowest of devices, but can be a restriction during debugging. 50 ms doesn't provide for many debugging characters to be sent at 9600 bps on an asynchronous serial port or for a In Circuit Debugger/Emulator to single step or to break execution to examine the internal Registers. As a result, USB requires some different debugging methods to that of other microcontroller projects.
Casually reading through the XP DDK, one may note the Host Controller Driver now has a USBUSER_OP_SEND_ONE_PACKET command which is commented to read “This API is used to implement the 'single step' USB transaction development tool.” While such a tool has not been released yet, we can only hope to see one soon.
Each request starts with a 8 byte long Setup Packet which has the following format,
OffsetFieldSizeValueDescription
0bmRequestType1Bit-Map
  • D7 Data Phase Transfer Direction
    • 0 = Host to Device
    • 1 = Device to Host
  • D6..5 Type
    • 0 = Standard
    • 1 = Class
    • 2 = Vendor
    • 3 = Reserved
  • D4..0 Recipient
    • 0 = Device
    • 1 = Interface
    • 2 = Endpoint
    • 3 = Other
    • 4..31 = Reserved
1bRequest1ValueRequest
2wValue2ValueValue
4wIndex2Index or OffsetIndex
6wLength2CountNumber of bytes to transfer if there is a data phase

The bmRequestType field will determine the direction of the request, type of request and designated recipient. The bRequest field determines the request being made. The bmRequestType is normally parsed and execution is branched to a number of handlers such as a Standard Device request handler, a Standard Interface request handler, a Standard Endpoint request handler, a Class Device request handler etc. How you parse the setup packet is entirely up to your preference. Others may choose to parse the bRequest first and then determine the type and recipient based on each request.

Standard requests are common to all USB device's and are detailed in the next coming pages. Class requests are common to classes of drivers. For example, all device conforming to the HID class will have a common set of class specific requests. These will differ to a device conforming to the communications class and differ again to that of a device conforming to the mass storage class.

And last of all are the vendor defined requests. These are requests which you as the USB device designer can assign. These are normally different from device to device, but this is all up to your implementation and imagination.

A common request can be directed to different recipients and based on the recipient perform different functions. A GetStatus Standard request for example, can be directed at the device, interface or endpoint. When directed to a device it returns flags indicating the status of remote wakeup and if the device is self powered. However if the same request is directed at the interface it always returns zero, or should it be directed at an endpoint will return the halt flag for the endpoint.

The wValue and wIndex fields allow parameters to be passed with the request. wLength is used the specify the number of bytes to be transferred should there be 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. The standard provides a single table grouping items by request. Considering most firmware will parse the setup packet by recipient we will opt to break up the requests based by recipient for easier examination and implementation.

Standard Device Requests

There are currently eight Standard Device requests, all of which are detailed in the table below.
bmRequestTypebRequestwValuewIndexwLengthData
1000 0000bGET_STATUS (0x00)ZeroZeroTwoDevice Status
0000 0000bCLEAR_FEATURE (0x01)Feature SelectorZeroZeroNone
0000 0000bSET_FEATURE (0x03)Feature SelectorZeroZeroNone
0000 0000bSET_ADDRESS (0x05)Device AddressZeroZeroNone
1000 0000bGET_DESCRIPTOR (0x06)Descriptor Type and IndexZero or Language IDDescriptor LengthDescriptor
0000 0000bSET_DESCRIPTOR (0x07)Descriptor Type and IndexZero or Language IDDescriptor LengthDescriptor
1000 0000bGET_CONFIGURATION (0x08)ZeroZero1Configuration Value
0000 0000bSET_CONFIGURATION (0x09)Configuration ValueZeroZeroNone

Standard Interface Requests

The specification currently defines five Standard Interface requests which are detailed in the table below. Interestingly enough, only two requests do anything intelligible.
bmRequestTypebRequestwValuewIndexwLengthData
1000 0001bGET_STATUS (0x00)ZeroInterfaceTwoInterface Status
0000 0001bCLEAR_FEATURE (0x01)Feature SelectorInterfaceZeroNone
0000 0001bSET_FEATURE (0x03)Feature SelectorInterfaceZeroNone
1000 0001bGET_INTERFACE (0x0A)ZeroInterfaceOneAlternate Interface
0000 0001bSET_INTERFACE (0x11)Alternative SettingInterfaceZeroNone

Standard Endpoint Requests

Standard Endpoint requests come in the four varieties listed below.
bmRequestTypebRequestwValuewIndexwLengthData
1000 0010bGET_STATUS (0x00)ZeroEndpointTwoEndpoint Status
0000 0010bCLEAR_FEATURE (0x01)Feature SelectorEndpointZeroNone
0000 0010bSET_FEATURE (0x03)Feature SelectorEndpointZeroNone
1000 0010bSYNCH_FRAME (0x12)ZeroEndpointTwoFrameNumber