---
description: >-
  Before we start we have to learn some basics about the USB protocol and the
  communication between host and device.
---

# A brief introduction to the USB protocol

For each USB device, one of the two data lines is pulled to a high level via a pull-up resistor. Depending on whether this resistor is connected to **D+** or **D-**, it is either a full speed device (pull-up for D +) or a low speed device (pull-up for D-).

![](https://2801891837-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvA_nizlqrtUSmfwyso%2F-Ly-aYdBqUAHwL55fFlv%2F-Ly-bLbkJOAxqlLN7Iob%2Fimage.png?alt=media\&token=af52f229-f063-4812-b244-aaa5f7e55197)

The end of a USB connection that is closer to the host is called the _upstream end transceiver_ and the end that is closer to the device is called the _downstream end transceiver_. The data lines of the upstream end transceiver are pulled to ground via pull-down resistors.

![](https://2801891837-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvA_nizlqrtUSmfwyso%2F-Ly-aYdBqUAHwL55fFlv%2F-Ly-bcyw5XMnUV7iAd2d%2Fimage.png?alt=media\&token=d5f9a0e2-294a-4bd1-a50b-86c06b52c235)

Each USB device is also described by a minimum number of bit fields, the so-called **descriptors**.

![](https://www.kampis-elektroecke.de/wp-content/uploads/2020/01/DescriptorEN.png)

* Each device has a **device descriptor** that provides very general information, such as the USB version used or the manufacturer or product ID or the number of device configurations.

| Offset | Field              | Size | Description                                                                               |
| ------ | ------------------ | ---- | ----------------------------------------------------------------------------------------- |
| 0      | bLength            | 1    | Descriptor size in bytes.                                                                 |
| 1      | bDescriptorType    | 1    | DEVICE descriptor (=1).                                                                   |
| 2      | bcdUSB             | 2    | USB version.                                                                              |
| 4      | bDeviceClass       | 1    | Class code, assigned by the USB-IF.                                                       |
| 5      | bDeviceSubClass    | 1    | Sub class code, assigned by the USB-IF.                                                   |
| 6      | bDeviceProtocol    | 1    | Protocol code, assigned by the USB-IF.                                                    |
| 7      | bMaxPacketSize0    | 1    | <p>Maximum transmission size in bytes for endpoint 0. </p><p>Must be 8, 16, 32 or 64.</p> |
| 8      | idVendor           | 2    | Vendor id, assigned by the USB-IF.                                                        |
| 10     | idProduct          | 2    | Product id, assigned by the USB-IF.                                                       |
| 12     | bcdDevice          | 2    | Device release number.                                                                    |
| 14     | iManufacturer      | 1    | <p>Index for the string descriptor that describes </p><p>the manufacturer.</p>            |
| 15     | iProduct           | 1    | <p>Index for the string descriptor that describes</p><p>the product.</p>                  |
| 16     | iSerialNumber      | 1    | <p>Index for the string descriptor that describes </p><p>the serial number.</p>           |
| 17     | bNumConfigurations | 1    | Device configurations used by the device.                                                 |

* The different device configurations are mapped using **configuration descriptors**. B. describe the current consumption or the number of interfaces of a device configuration. The host can only activate one device configuration at a time.

| Offset | Field               | Size | Description                                                                      |
| ------ | ------------------- | ---- | -------------------------------------------------------------------------------- |
| 0      | bLength             | 1    | Descriptor size in bytes.                                                        |
| 1      | bDescriptorType     | 1    | CONFIGURATION descriptor (=2).                                                   |
| 2      | wTotalLength        | 2    | Size of the complete configuration in bytes.                                     |
| 4      | bNumInterfaces      | 1    | Number of interfaces.                                                            |
| 5      | bConfigurationValue | 1    | Configuration index for this configuration descriptor.                           |
| 6      | iConfiguration      | 1    | <p>Index for the string descriptor that describes </p><p>this configuration.</p> |
| 7      | bmAttributes        | 1    | Interface attributes.                                                            |
| 8      | bMaxPower           | 1    | Power consumption of the device (2 mA / bit).                                    |

* Each interface is described by an **interface descriptor** and, unlike the device configurations, several interfaces can be active at the same time. An interface descriptor describes i. e. the number of endpoints and the class of a device.

| Offset | Field              | Size | Description                                                                    |
| ------ | ------------------ | ---- | ------------------------------------------------------------------------------ |
| 0      | bLength            | 1    | Descriptor size in bytes.                                                      |
| 1      | bDescriptorType    | 1    | INTERFACE descriptor (=4).                                                     |
| 2      | bInterfaceNumber   | 1    | Interface id.                                                                  |
| 3      | bAlternateSetting  | 1    | Additional settings for this interface.                                        |
| 4      | bNumEndpoints      | 1    | <p>Number of endpoints used by this interface </p><p>(without endpoint 0).</p> |
| 5      | bInterfaceClass    | 1    | Interface class code, assigned by the USB-IF.                                  |
| 6      | bInterfaceSubClass | 1    | Interface sub class code, assigned by the USB-IF.                              |
| 7      | bInterfaceProtocol | 1    | Interface protocol code, assigned by the USB-IF.                               |
| 8      | iInterface         | 1    | <p>Index for the string descriptor that describes </p><p>this interface.</p>   |

* The individual endpoints of each interface are described by **endpoint descriptors**. These include e.g. information such as the size of the end point and whether it is an _IN_ or _OUT_ endpoint.

| Offset | Field            | Size | Description                                                                                       |
| ------ | ---------------- | ---- | ------------------------------------------------------------------------------------------------- |
| 0      | bLength          | 1    | Descriptor size in bytes.                                                                         |
| 1      | bDescriptorType  | 1    | INTERFACE descriptor (=5).                                                                        |
| 2      | bEndpointAddress | 1    | Endpoint address.                                                                                 |
| 3      | bmAttributes     | 1    | Endpoint attributes.                                                                              |
| 4      | wMaxPacketSize   | 2    | Endpoint message size                                                                             |
| 6      | bInterval        | 1    | Polling interval. 1 ms / bit for low and high speed devices, 125 µs / bit for high speed devices. |

* Optional **string descriptors**
  * Manufacturer String
  * Product String
  * Serial Number String

**String descriptor 0**

| Offset     | Field           | Size | Description                |
| ---------- | --------------- | ---- | -------------------------- |
| 0          | bLength         | 1    | Descriptor size in bytes.  |
| 1          | bDescriptorType | 1    | INTERFACE descriptor (=3). |
| 2          | wLANGID\[0]     | 2    | LANGID code 0              |
| ...        | ...             | ...  | ...                        |
| 2 + x \* 2 | wLANGID\[x]     | 2    | LANGID code x              |

**Common string descriptor**

| Offset | Field           | Size | Description                |
| ------ | --------------- | ---- | -------------------------- |
| 0      | bLength         | 1    | Descriptor size in bytes.  |
| 1      | bDescriptorType | 1    | INTERFACE descriptor (=3). |
| 2      | bString         | 2    | Unicode string             |

A communication between host and device require the help of endpoints and pipelines. Each endpoint is defined as a sink or source of data and is connected to the host via a pipeline. In total, each USB device can have up to 16 _IN_ and 16 _OUT_ endpoints, whereby the size is variable and usually depends on the USB controller used. A special end point is **endpoint 0**, because this end point is used both as an IN and an OUT end point. This end point is also the standard end point that is used when configuring the device.

A data transfer at is called a **USB transaction**. The USB standard knows three different types of transactions:

| Transaction | Description                                                                    |
| ----------- | ------------------------------------------------------------------------------ |
| _IN_        | Data transmission from device to host.                                         |
| _OUT_       | Data transmission from host to device.                                         |
| _SETUP_     | <p>OUT transmission to send/request</p><p> configuration and control data.</p> |

Such a transaction can be carried out with one of four different types of transfer, each type of transfer offering its own particular advantages.

| Transmission | Package size in bytes                                                                     | Description                                                                                  |
| ------------ | ----------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
| Bulk         | <p>Low speed: Not defined</p><p>Full speed: 8, 16, 32, 64</p><p>High speed: Up to 512</p> | <p>Use this mode to transmit many data </p><p>without error. No guaranteed bandwidth.</p>    |
| Interrupt    | <p>Low speed: 1 to 8</p><p>Full speed: 1 to 64</p><p>High speed: Up to 1024</p>           | <p>Use this to send new data from inputs in </p><p>a device to host communication </p>       |
| Isochronous  | <p>Low speed: Not allowed</p><p>Full speed: Up to 1023</p><p>High speed: Up to 1024</p>   | <p>Guaranteed bandwidth but without</p><p> error detection.</p>                              |
| Control      | <p>Low speed:  8</p><p>Full speed: 8, 16, 32, 64</p><p>High speed: 64</p>                 | <p>Bidirectional transmission for device </p><p>configuration. Only used for endpoint 0.</p> |

To communicate with the host, each USB device must be able to understand and operate a certain number of commands, the so-called **standard requests**. The host uses these requests to request as much information as possible about the new device. After the host has collected all the necessary information, the requests are used for the configuration and initialization of the inserted USB device.

| **bmRequestType**                 | **bReqest**                     | **wValue**                                      | **wIndex**                                 | **wLength**     | **Data**                                                          |
| --------------------------------- | ------------------------------- | ----------------------------------------------- | ------------------------------------------ | --------------- | ----------------------------------------------------------------- |
| <p>0x00</p><p>0x01</p><p>0x02</p> | <p>CLEAR_FEATURE<br>(1)</p>     | Feature                                         | <p>Null</p><p>Interface</p><p>Endpoint</p> | 0               | -                                                                 |
| 0x80                              | <p>GET_CONFIGURATION<br>(8)</p> | 0                                               | 0                                          | 1               | Configuration                                                     |
| 0x80                              | <p>GET_DESCRIPTOR<br>(6)</p>    | <p>Descriptor type (H) </p><p>and index (L)</p> | Null or language id                        | Descriptor size | Descriptor                                                        |
| 0x81                              | <p>GET_INTERFACE<br>(10)</p>    | 0                                               | Interface                                  | 1               | Interface                                                         |
| <p>0x80</p><p>0x81</p><p>0x82</p> | <p>GET_STATUS<br>(0)</p>        | 0                                               | <p>0</p><p>Interface</p><p>Endpoint</p>    | 2               | <p>Device status</p><p>Interface status</p><p>Endpoint status</p> |
| 0x00                              | <p>SET_ADDRESS<br>(5)</p>       | Device address                                  | 0                                          | 0               | -                                                                 |
| 0x00                              | <p>SET_CONFIGURATION<br>(9)</p> | Configuration                                   | 0                                          | 0               | -                                                                 |
| 0x00                              | <p>SET_DESCRIPTOR<br>(7)</p>    | <p>Descriptor type (H) </p><p>and index (L)</p> | Null oder language id                      | Descriptor size | Descriptor                                                        |
| <p>0x00</p><p>0x01</p><p>0x02</p> | <p>SET_FEATURE<br>(3)</p>       | Feature                                         | <p>0</p><p>Interface</p><p>Endpunkt</p>    | 0               | -                                                                 |
| 0x01                              | <p>SET_INTERFACE<br>(11)</p>    | Interface                                       | Interface                                  | 0               | -                                                                 |
| 0x82                              | <p>SYNCH_FRAME<br>(12)</p>      | 0                                               | Endpoint                                   | 2               | Frame counter                                                     |

As soon as a new USB device is plugged in, one of the two data lines is pulled to a high level, which informs the host about a new device. Before the host begins to "poll" the new device, it performs a reset of the device by pulling both data lines to low for at least 10 seconds (this is **not** a hardware reset!). The reset resets the address of the USB device to 0. This address can now be used by the host to configure the device using endpoint 0. Before the actual communication, however, the host must first determine the size of the end point 0, which is stored in the device descriptor of the connected device (bit field _bMaxPacketSize0_).

The host starts the query of the device descriptor with a control transfer. Each control transfer contains a _SETUP_ stage, which contains a _SETUP_ transaction and an 8-byte setup package, which specifies the request of the host. This setup package contains all the request details from the host to the device and is filled by the host with the corresponding values ​​of the request. In the _DATA_ Stage, the device then replies with the requested data if the request from the host requires a response from the device. Finally, the host sends a CRC in the _STATUS_ stage and if the transmission was error-free, the message is confirmed by the device with an ACK.&#x20;

After the second reset, the host transmit a _SET\_ADDRESS_ request to set the USB address of the connected device. The address used depends on the devices already connected and is variable. The host then transmit a new _GET\_DESCRIPTOR_ request, only that in this case _wLength_ is set to **18**, which corresponds to the complete length of the device descriptor. The device responds again with the device descriptor, only this time the host does not abort the transfer, but receives all data and acknowledges the transfer with an ACK. The host now knows how the device is structured and carries out further requests to request all other descriptors. As soon as the host is sure which device it is, it loads an appropriate driver (e.g. a mouse driver) and the device can be used.
