The USB HID protocol

HID reports

This document covers:

Keyboard

The keyboard is still the most important interface device (because the current version of HID doesn't support brain-computer interface).

Input reports

A keyboard will send "press key" and "release key" information to the operating system, which will interpret it differently depending on the current application. For example, many computer games accept single letters as commands, whereas a text application will simply add the letter to the text.

When the OS receives a "press key" report, it writes the letter or uses it as a command as explained above. It will keep performing the same action, again and again, until it receives a "release key" report.

The usual format for keyboard reports is the following byte array:

[modifier, reserved, Key1, Key2, Key3, Key4, Key6, Key7]

Note that this report can send six simultaneous key events. Their order in the report doesn't matter, since the OS must keep track of the timing of each key press.

The reserved byte might be used by vendors, but is mostly useless.

When you press the letter 'a' on a USB keyboard, the following report will be sent over the USB interrupt pipe:

'a' report:     [0, 0, 4, 0, 0, 0, 0, 0]

This '4' value is the Keycode for the letter 'a', as described in USB HID Usage Tables (Section 10: Keyboard/Keypad Page). That document defines the report formats for all standardized HIDs.

After releasing the key, the following report will be sent:

null report:    [0, 0, 0, 0, 0, 0, 0, 0]

'4' is replaced with '0'; an array of zeros means nothing is being pressed.

For an uppercase 'A', the report will also need to contain a 'Left Shift' modifier. The modifier byte is actually a bitmap, which means that each bit corresponds to one key:

With left shift pressed, out report will look like that:

'A' report:     [2, 0, 4, 0, 0, 0, 0, 0]

Output reports

We want the OS to be able to control our keyboard's LEDs, for instance when another keyboard enables Caps Lock. To do this, the OS writes a separate one-byte output report that defines the state of each LED.

Feature reports

There is another type of report, Feature Reports, which allows to set the internal properties of a device.

Report descriptors

The power of USB HID resides in report descriptors. Instead of defining a fixed report format for each possible device, the USB HID specification provides a way for devices to describe what their reports will look like.

A report descriptor is a list of items. They are a short series of bytes (two or three), containing each item type and its value. For instance, a "Usage Page" item of size 1 has type 0x05, and is followed by a byte describing the HID Usage Page (USBHID UsageTables) in which the device lies.

Here are the items of our keyboard:

Mouse

The Mouse report format is simpler:

[Buttons, X-translation, Y-translation]

And the report descriptor is now pretty easy to understand:

Further reading

The USB specification is quite bulky, and navigation is not always easy. Here are some pointers to documentation sections that are of interest to BLE HID:

I don't have a proper index in my PDF version of USBHID, so here is the one I use to navigate:

The USBHID UsageTables is annex A of the previous document, and contains all standardized usage:

Next: HID-over-GATT