FB pixel

How USB Works: Enumeration and Configuration (Part 3)New

Published


In the previous tutorial, we learned how the USB device communicates with the host controller. Now, in this, we’ll understand the genius of USB descriptors and their role in the process of enumeration and configuration, which makes a USB device hot-swappable, so without further due, let’s dive into it.

To understand the USB descriptors first we need to have a good understanding of what USB requests are! They are essentially just data packets sent from a host computer to a USB device to communicate with it. Below mentioned are the types of USB requests supported by the protocol.

  • Standard requests: These are defined by the USB specification and every device must understand them. They perform essential tasks like getting device information, setting configurations, and checking status.
  • Class requests: These are specific to a particular device class (e.g., printers, storage devices) and defined by the relevant class specification. They allow for more specific control over the device's functionalities.
  • Vendor requests: These are defined by the manufacturer of the device and allow for vendor-specific control and features.

The key point to note here is that the structure of all requests remain the same. Now with this understood we’ll see what USB descriptors are:

USB Descriptors

The term USB descriptors refers to small packets of information that act like an identity card for the device. These descriptors are like manuals packed into the device itself, and they tell the host everything it needs to know about the device to communicate and use it properly.

Types of Descriptors

1. Device Descriptor

Let’s suppose you just plugged in a new USB device to the computer, it could be a flash drive, printer, webcam, or anything else that uses USB. Well, you know that, right? How does the computer know what it is or how to talk to it? That’s where device descriptors come in!

When the device is plugged in, the first request the host makes from the device is of a device descriptor. It provides the host with all the essential information it needs to understand and interact with the device properly. The device descriptor is packed with the fields given in the table below.

Offset

Field

Size (Bytes)

Description

0

bLength

1

The length of the descriptor is 18 bytes.

1

bDescriptorType

1

The descriptor type is DEVICE (01h)

2

bcdUSB

2

USB specification version (BCD)

4

bDeviceClass

1

Device Class

5

bDeviceSubClass

1

Device subclass

6

bDeviceProtocol

1

Device Protocol

7

bMaxPacketSize0

1

Max Packet size for endpoint 0

8

idVendor

2

Vendor ID

10

idProduct

2

Product ID

12

bcdDevice

2

Device release number (BCD)

14

iManfacturer

1

Index of manufacturer string

16

iSerialNumber

1

Index of the serial number string

17

bNumConfigurations

1

Number of configurations supported

  1. bLength: It is the total length in bytes of the device descriptor.
  2. bcdUSB: This is a binary-coded decimal value that uses a format of 0xAABC, where A is the major version number, B is the minor version number, and C is the sub-minor version number to give a report of the USB version of the device, to help the host load the necessary driver. For example, USB 1.1 would have a value of 0x0110.
  3. bDeviceClass, bDeviceSubClass, and bDeviceProtocol are used by the host to identify a driver for a USB device during the enumeration process. Most USB devices define their classes in the interface descriptor and leave these fields as 00h.
  4. bMaxPacketSize reports the maximum number of packets supported by Endpoint 0. Depending on the device, the possible sizes are 8 bytes, 16 bytes, 32 bytes, and 64 bytes.
  5. iManufacturer, iProduct, and iSerialNumber are indices to string descriptors. String descriptors give details about the manufacturer, product, and serial number. If string descriptors exist, these variables should point to their index location. If no string exists, then the respective field should be assigned a value of zero.
  6. bNumConfigurations defines the total number of configurations the device can support. Multiple configurations allow the device to be configured differently depending on certain conditions, such as being bus-powered or self-powered.

2. Configuration Descriptor

Configuration descriptor provides essential information about a specific configuration of a USB device. It outlines how the device is organized and how it interacts with the host system. Key aspects covered in the configuration descriptor included are given in the table:

Offset

Field

Size (Bytes)

Description

0

bLength

1

The length of this descriptor is 9 bytes.

1

bDescriptorType

1

The descriptor type CONFIGURATION (02h).

2

wTotalLength

2

Total length, including interface and endpoint descriptors.

4

bNumInterfaces

1

The number of interfaces in this configuration

5

bConfigurationValue

1

Configuration value used by SET_CONFIGURATION to select this configuration

6

iConfiguration

1

Index of string that describes this configuration

7

bmAttributes

1

Bit 7: Reserved (set to 1)

Bit 6: Self-powered

Bit 5: Remote wakeup

8

bMaxPower

1

Maximum power required for this configuration.

  1. wTotalLength: It is the length of the configuration descriptor of the USB device.
  2. bNumInterfaces: It defines the total number of possible interfaces in this particular configuration and should have a minimum value of 1.
  3. bConfigurationValue: It defines the number of available configurations on the device.
  4. bmAttributes: It defines parameters for the USB device. If the device is bus-powered, bit 6 is set to 0; if the device is self-powered, then bit 6 is set to 1. If the USB device supports remote wakeup, bit 5 is set to 1. If remote wakeup is not supported, bit 5 is set to 0.
  5. bMaxPower: It defines the maximum power consumption drawn from the bus when the device is fully operational.

3. Interface Association Descriptor (IAD)

The main purpose of IAD is to group multiple interfaces together into a single functional unit. This ensures that the host computer recognizes and interacts with them as a unified entity. Well, the early USB specifications didn't natively support multi-interface functions. To address this limitation and add support for the latest, more complex devices, IADs were introduced.

Offset

Field

Size (Bytes)

Description

0

bLength

1

Description size in bytes

1

bDescriptorType

1

Descriptor type = INTERFACE ASSOCIATION (0Bh)

2

bFirstInterface

1

Number identifying the first interface associated with the function

3

bInterfaceCount

1

The number of contiguous interfaces associated with the function

4

bFunctionClass

1

Class code

5

bFunctionSubClass

1

Subclass code

6

bFunctionProtocol

1

Protocol code

7

iFunction

1

Index of string descriptor for the function

  • bLength: Total length of the descriptor (8 bytes).
  • bDescriptorType: Identifies it as an IAD (0x0B).
  • bFirstInterface: Number of the first interface belonging to the function.
  • bInterfaceCount: Number of interfaces in the function.
  • bFunctionClass, bFunctionSubClass, bFunctionProtocol: Class, subclass, and protocol codes for the function.
  • iFunction: Optional index of a string descriptor for the function's name.

4. Interface Descriptor

It is a data structure that defines a collection of endpoints within a USB device. It acts as a blueprint for how a device communicates with the host computer. Each interface represents a distinct function of the device. The main purpose of IAD is to provide information about a specific interface to the host, including:

  • Class code (e.g., audio, HID, mass storage)
  • Endpoints (channels for data transfer)
  • Protocol used for communication
  • Alternate settings (different configurations for the same interface)

The below given table defines what the packet contains:

Offset

Field

Size (Bytes)

Description

0

bLength

1

The length of this descriptor is 9 bytes

1

bDescriptorType

1

Descriptor type = INTERFACE (04h)

2

bInterfaceNumber

1

Zero based index of this interface

3

bAlternateSetting

1

Alternate setting value

4

bNumEndpoints

1

Number of endpoints used by this interface (not including EP0)

5

bInterfaceClass

1

Interface class

6

bInterfaceSubclass

1

Interface subclass

7

bInterfaceProtocol

1

Interface protocol

8

iInterface

1

Index to string describing this interface

  1. bLength: Total length of the descriptor
  2. bDescriptorType: Identifies it as an interface descriptor
  3. bInterfaceNumber: Unique number for the interface
  4. bAlternateSetting: Number of the alternate setting being described
  5. bNumEndpoints: Number of endpoints used by the interfacebInterfaceClass,
  6. bInterfaceSubClass, bInterfaceProtocol: Define the device class and specific protocoliInterface: Index of a string descriptor providing a human-readable name

5. Endpoint Descriptor

This descriptor provides essential information about a specific endpoint within a USB device. It tells the host computer how to communicate with that endpoint for data transfer. Each endpoint has a unique channel for data flow in a particular direction (either IN or OUT).
The table given below represents the structure of the endpoint descriptor:

Offset

Field

Size (Bytes)

Description

0

bLength

1

The length of this descriptor is 7 bytes

1

bDescriptorType

1

The type of descriptor is ENDPOINT (05h)

2

bEndpointAddress

1

Bit 3...0: The endpoint number

Bit 6...4: Reserved, reset to zero
Bit 7: Direction. Ignored for Control
0 = OUT endpoint
1 = IN endpoint

3

bmAttributes

1

Bits 1..0: Transfer Type
00 = Control
01 = Isochronous
10 = Bulk
11 = Interrupt
If not an isochronous endpoint, bits 5...2 are reserved and must be set to zero.
If isochronous, they are defined as follows:
Bits 3..2: Synchronization Type
00 = No Synchronization
01 = Asynchronous
10 = Adaptive
11 = Synchronous
Bits 5..4: Usage Type
00 = Data endpoint
01 = Feedback endpoint
10 = Implicit feedback Data endpoint
11 = Reserved

4

wMaxPacketSize

2

Maximum packet size for this endpoint

5

bInterval

1

Polling interval in milliseconds for interrupt endpoints (1 for isochronous endpoints, ignored for control or bulk)

  1. bLength: Total length of the descriptor (7 bytes).bDescriptorType: Identifies it as an endpoint descriptor (0x05).
  2. bEndpointAddress: Specifies the endpoint's address and direction (bit 7 indicates IN or OUT).
  3. bmAttributes: Defines the endpoint's transfer type (control, interrupt, bulk, or isochronous).
  4. wMaxPacketSize: Indicates the maximum packet size the endpoint can handle.
  5. bInterval: For interrupt and isochronous endpoints, specify the polling interval.

6. String Descriptor

This descriptor provides human-readable text strings to describe various aspects of a USB device. It is optional but recommended for user-friendliness and compatibility. When it comes to languages a device can support multiple and it can provide different string descriptors for each supported language. A string descriptor can have the following information:

  • Device name
  • Manufacturer name
  • Product name
  • Serial number
  • Interface name
  • Endpoint name
  • Configuration names

Offset

Field

Size (Bytes)

Description

0

bLength

1

The length of this descriptor is 7 bytes

1

bDescriptorType

1

The descriptor type is STRING (03h).

2

bString

-or

wLangID

Varies

Unicode encoded text string

-or

LANGID code

  1. bLength: Total length of the descriptor (variable).
  2. bDescriptorType: Identifies it as a string descriptor (0x03).
  3. bString: Language code (e.g., 0 for English, 4097 for US English).
  4. wString: Unicode text string encoded in UTF-16LE.

Well, until now, the tutorial might seem a little too informative with just tables and definitions, right? But now, we’ll learn about the usage of these tables in the enumeration and configuration process, which makes the USB protocol universal and the devices using this protocol hot-swappable.

USB Enumeration and Configuration

The magic of hot-pluggable USB devices is made possible by the three step process of

  1. Dynamic Detection
  2. Enumeration
  3. Configuration

Dynamic Detection

The host controller monitors the USB ports for the transition on D+ and D- lines, the transition on the D+ and D- line of the port indictes a newly connected device and determines the speed of the device as discussed in the USB speed section. But there is catch here! The host can only determine whether the device supports Low- or Full- Speed what about the High-Speed devices? Keep this in mind, the answer to this is given in the next part only!

As soon as the USB host detects the speed of the device, it resets the device by pulling both the D+ and D- lines of the port low. This is made possible by the D+ and D- lines on the port having pull-down resistors attached to them on the host’s side. The reset state is issued by the host controller by pulling the D+ and D- lines low for more than 2.5 us, and the host controller holds this state for 10ms. During the reset state, a high-speed device issues a single K-state. A High-Speed hub detects this and responds with a series of “KJKJKJ” patterns. The device detects this pattern and removes its pull-up resistor from its D+ line. If this pattern is not returned from the hub, it means the hub doesn’t support High-Speed devices and the device operates on Full-Speed.

Enumeration and Configuration

Now, that the host has the information about the device speed, it starts communicating with the device through the control endpoint (EP0) on the default address i.e., 00h. The important point to note here is that only one device can enumerated at a time which means only one device can acquire 00h address at a time. The control endpoint is bidirectional, and control transactions are carried out with this endpoint. In the previous tutorial, we understood how control transactions are carried out; in this tutorial, we’ll understand their significance.

The host sends a GET_DESCRIPTOR command to the device to get a device descriptor from the device, from which it determines the maximum packet size supported by endpoint zero from the eighth byte of the device descriptor (bMaxPacketSize0).

Figure 1.1: Request for Device Descriptor
Figure 1.1: Request for Device Descriptor

Well, the question may arise: If the maximum packet size for the control endpoint is not available beforehand, how did the host receive the device descriptor of 18 bytes? Well, let’s suppose the maximum packet supported for the control endpoint is 8 bytes, then the device sends the descriptor into smaller chunks of 8-8-2 bytes, this is applicable to all types of descriptors.

After getting the device descriptor, the host resets the device again and assigns a new address for the USB device by sending a SET_ADDRESS command to the the device using a control transaction. All communication beyond this point will use the new address. After the device returns from its reset, the host issues a command, GET_DESCRIPTOR, using the newly assigned address, to read the descriptors from the device. However, this time all the descriptors are read. The host uses this information to learn about the device and its abilities. This information includes the number of peripheral interfaces, power connection method, and the required maximum power. This request not only returns the configuration descriptor, but all other descriptors associated with it such as the interface descriptor and the endpoint descriptor.

After all descriptors are received, the host sets a specific device configuration using the SET_CONFIGURATION request and the host load a device driver. The host searches for a driver to manage communication between itself and the device. Windows machine use its .inf files to locate a match for the devices Product ID and Vendor ID. The device is now in the configured state and the required power can be drawn from VBUS and is now ready for use in an application.

Figure 1.2: Enumeration Flow
Figure 1.2: Enumeration Flow

This concludes the enumeration and configuration process, which enables the host controller to get a full manual on how to communicate with the USB device without the need for external drivers or supporting software.

USB Classes

USB classes refer to different specifications or standards that define the capabilities and functionalities of USB devices and interfaces. These classes ensure compatibility between devices made by different manufacturers. Here are some common USB classes:

Standard Classes

Standard classes are defined by official USB specifications and are intended for common device types. They are compatible across different operating systems and host devices. Some examples of standard classes include:

  • USB Human Interface Device (HID) : This class is used for devices such as keyboards, mice, game controllers, and joysticks. It allows these devices to be recognized by the operating system without needing additional drivers.
  • USB Mass Storage : Devices such as USB flash drives, external hard drives, and memory card readers fall under this class. They allow for easy storage and retrieval of data.
  • USB Audio : This class is used for audio devices such as speakers, microphones, headphones, and sound cards. It allows for the transmission of audio data over USB connections.
  • USB Video : Devices like webcams and digital cameras that capture or stream video use this class. USB video devices typically follow the USB video device class (UVC) standard.
  • USB Printer : Printers and multifunction devices that support printing, scanning, and faxing often adhere to the USB printer class specification.
  • USB Communication Device Class (CDC) : This class encompasses devices like modems, serial ports, and network adapters. It facilitates communication between devices and a host computer.

Vendor Specific Classes

Vendor-specific classes are are not part of the official USB specifications but are implemented by vendors to provide specialized functionalities or features unique to their products and allow manufacturers more flexibility in designing their devices. These classes may require vendor-specific drivers or software to operate properly and may not be compatible with all operating systems or host devices.

Viewing USB Descriptors

On Windows

We can view the USB descriptors on Windows using USB Device Tree Viewer, which is free software and can be downloaded using this link. Here are a few snapshots of the descriptor information for a USB thumb drive.

Figure 2.1: Device Descriptor
Figure 2.1: Device Descriptor
Figure 2.2: Configuration Descriptor
Figure 2.2: Configuration Descriptor
Figure 2.3: Interface and Endpoint Descriptor
Figure 2.3: Interface and Endpoint Descriptor
Figure 2.4: String Descriptor
Figure 2.4: String Descriptor

On Linux

On Linux there is no need to install any additional software, we can use Linux USB utilities packages, by using the command lsusb on the terminal.

Figure 2.5: lsusb
Figure 2.5: lsusb

In figure 2.5, you can see the usb storage device is attached on Bus 001 and the device address is 002. We can use the options available along with lsusb command to get the device descriptors. We will target the specific device using -s option and -v to get the descriptors.

Figure 2.6: Descriptors on Linux
Figure 2.6: Descriptors on Linux

This tutorial series on USB 2.0 specification covered how the USB data transmission takes place on the physical level, different USB speeds, and power delivery of the bus. Next, we learned how communication is carried out on the bus by polling mechanism used by the host controller, and in this tutorial, we covered how USB descriptors act like manuals stored in the USB device itself, which are given to the host controller during different stages of enumeration and configuration for utilizing the functionalities of the USB device.

Make Bread with our CircuitBread Toaster!

Get the latest tools and tutorials, fresh from the toaster.

What are you looking for?