Programming the Microsoft Windows Driver Model
Reports and Report Descriptors
A HID device transfers information in a block known as a report. The report contains bit and integer fields formatted according to a report descriptor. Much of the HID specification and related documents describe the contents of reports and report descriptors in great detail. I ll analyze two sample report descriptors here to help you understand the specifications.
Sample Keyboard Descriptor
To start with, I suggest that you download the so-called HID Descriptor Tool (DT.EXE) from http://www.usb.org. The tool allows you to create and edit report descriptors using symbolic names. Figure 13-1 illustrates the user interface and one of the example descriptors that come with the tool.
Figure 13-1. Using the HID Tool to define a keyboard report descriptor.
The first item in the sample report descriptor establishes the usage page, which essentially specifies a namespace for interpreting certain numeric constants in subsequent elements of the descriptor. You need the HID Usage Tables document to interpret the numbers. For example, the usage code 6 means keyboard in the generic desktop page but sailing simulation device in the simulation controls page.
The second item specifies the usage for the next top-level collection in the descriptor. In the HID specification, a collection serves to group related data items. For example, a physical collection groups items collected at one geometric point, whereas an application collection groups items that might be familiar to applications. A further concept, the logical collection, allows related items to be grouped into a composite data structure, such as a byte count followed by data. These concepts are so abstract as to be nearly meaningless, and Microsoft assigns additional meaning, as follows:
-
A top-level collection, such as the one beginning with the third item in the keyboard sample, corresponds to an individually addressable entity. Acting as a bus driver, HIDCLASS creates a physical device object (PDO) for each top-level collection. The device identifier for the collection includes a generic compatible ID, based on the usage code. See Table 13-1. If the collection has any other usage, HIDCLASS won t create a compatible ID. Refer to Chapter 15 for more information about the importance of a compatible ID in locating a driver. The PDO then becomes the base of a PnP device stack for some type of device. Note that multiple top-level collections give rise to multiple device stacks. For this to work in practice, the device must use report identifiers to distinguish between the different collections.
-
A link collection is one nested within a top-level collection. Link collections provide an organizational hierarchy that applications can use to group related controls in a complex device. On a game pad, for example, one can use link collections to distinguish between buttons actuated by the left and right hands. There seems little point to this generality, however, when applications typically require end users to assign meanings to controls based on numbers rather than position in a hierarchy. But perhaps I just haven t seen enough applications and HID devices to make a comprehensive judgment.
Table 13-1. HIDCLASS-Compatible ID for Each Supported Usage Usage Page
Usage
Compatible ID
Generic desktop
Pointer or mouse
HID_DEVICE_SYSTEM_MOUSE
Keyboard or keypad
HID_DEVICE_SYSTEM_KEYBOARD
Joystick or game pad
HID_DEVICE_SYSTEM_GAME
System control
HID_DEVICE_SYSTEM_CONTROL
Consumer
(Any)
HID_DEVICE_SYSTEM_CONSUMER
Within the single top-level collection for the sample keyboard, the most important items are the main items named INPUT and OUTPUT. An INPUT item corresponds to a field in an input report, whereas an OUTPUT item corresponds to a field in an output report. There can also be FEATURE items that define fields in a feature report, but the keyboard sample doesn t include any of them. A number of global items precede the main items in order to describe the presentation and meaning of the data itself.
It s important to realize that INPUT, OUTPUT, and FEATURE report items can be interleaved in the report descriptor. The logical collection structure within a top-level collection isn t important in determining which data items appear together in a given report. Rather, the type of the items governs. Thus, the example keyboard descriptor mixes INPUT and OUTPUT items in a way that might suggest that there are five reports, or else a single bidirectional report. In reality, there is a single input report defined by the INPUT items and a single output report defined by the OUTPUT items.
The main items, along with all the qualifying global items, define the bit layout of a structured report. To visualize the report, assign bits from right to left and don t leave any unused bits for alignment purposes. Treat multibit values, including those that span byte boundaries, as little-endian (least significant bit on the right of the resulting picture). Subdivide the result into bytes, which the device transmits from right to left.
In the keyboard report, we have five data items in the collection, and they define an input report and an output report (see Figure 13-2):
-
An input item consisting of eight (REPORT_COUNT) single-bit values (REPORT_SIZE 1), each of which can vary from 0 (LOGICAL_MINI MUM) to 1 (LOGICAL_MAXIMUM). The meaning of the bits corresponds to keyboard usages (USAGE_PAGE) E0 through E7 (USAGE_MINI MUM and USAGE_MAXIMUM). In other words, byte 0 of the input report contains flag bits to indicate which of the shift-type keys on the keyboard are currently depressed.
-
A constant input item consisting of one (REPORT_COUNT) 8-bit value (REPORT_SIZE). This is byte 1 of the input report, and it s simply a placeholder that contains no valid data.
-
An output item consisting of five (REPORT_COUNT) single-bit (REPORT_SIZE) values. The LOGICAL_MINIMUM and LOGI CAL_MAXIMUM values previously specified apply to these values because they haven t been overridden. The meaning of the bits is different, however: they correspond to LEDs (USAGE_PAGE) with labels such as Num Lock (USAGE_MINIMUM and LOGICAL_MAXI MUM). In other words, the low-order 5 bits of byte 0 of the output report contain flags to control LEDs for the toggling keys.
-
A constant output item consisting of one (REPORT_COUNT) 3-bit (REPORT_SIZE) value. These 3 bits pad out the output report to a full byte.
-
An input item consisting of six (REPORT_COUNT) 8-bit values (REPORT_SIZE), ranging from 0 through 101 (LOGICAL_MINIMUM and LOGICAL_MAXIMUM) and corresponding to keys on a standard 101-key keyboard (USAGE_PAGE, USAGE_MINIMUM, and USAGE_MAXIMUM). In other words, bytes 2 through 7 of the input report contain the codes for up to six keys that are being simultaneously held down.
Figure 13-2. Layout of keyboard input and output reports.
HIDFAKE Descriptor
Figure 13-3 illustrates the report descriptor used in the HIDFAKE sample driver in the companion content. This report descriptor has a few features that are different from the keyboard sample:
-
The top-level application s usage is Gun Device from the Gaming Controls page. This was an artificial choice that I made to avoid difficulty installing the sample driver. For any usage listed in Table 13-1, HIDCLASS will supply a compatible device identifier along with the device s specific ID. Windows XP will then prefer a signed driver matching the compatible ID to an unsigned driver (such as HIDFAKE.SYS) matching the device s specific ID. (See Chapter 15 for more information about how Windows XP chooses drivers.) It s nearly impossible to switch to the specific driver.
-
I used three logical collections within the main collection. The logical collections merely serve to highlight the three-report structure of the descriptor. The sample would work perfectly well without them.
-
The descriptor includes an input report and two feature reports. The input report (1) contains a single button usage. The first feature report (2) is for returning a driver version number, and the second feature report (3) is to allow the test applet to control the state of the fake button.
Figure 13-3. Using the HID Tool to define the HIDFAKE report descriptor.
HIDFAKE illustrates one fine point about report descriptors. Feature reports pretty much need to have identifying numbers because the HID specification calls for them in the Get_Report_Request and Set_Report_Request control pipe commands. If any report in a top-level collection has an identifier, all reports in that collection must. In reality, though, HIDFAKE models a notional device that has a real button report and no feature reports. I defined the feature reports as a way for the test applet to communicate out of band with the driver. If we were dealing with a real device, therefore, the driver would have to insert a report identifier in each input report that it read from the device.