joysticks and mice.
The following HID-specific class requests are supported on the default pipe. GET_REPORT and SET_REPORT get or send a specific input, output, or feature report. An idle rate can be defined using SET_IDLE and read using GET_IDLE. SET_PROTOCOL and GET_PROTOCOL are used for boot devices, as described in the following text.
A USB keyboard or mouse must be available during boot so the user can configure the BIOS settings, select the operating system, etc.
The BIOS can read the USB interface descriptor with relative ease. If it finds that
A boot keyboard input report is usually eight bytes long, in the format described in the previous chapter. Other requirements for a boot keyboard are given in the HID specification.
A mouse boot input report is at least three bytes long. The first three bits are the mouse button states. The second and third bytes are the X and Y displacements.
User Mode HID Clients
The DDK recommends that you talk to HID devices using a user mode application, if possible. This makes sense, as it is usually far easier to write and debug a Win32 application than a device driver. See the next section if you really need to write a HID client device driver. A user mode HID application has three main jobs to do.
1. Find all HID devices.
2. For each HID device, inspect its capabilities to see if it is of interest.
3. Read HID input reports or write HID output reports when needed. Alternatively send and receive feature reports.
The
The HID class driver registers all its device objects as having the HID device interface.
GUID HidGuid;
HidD_GetHidGuid(&HidGuid);
Going back to Chapter 5, you will see that
Note that
If the HID USB keyboard is unceremoniously unplugged while
Getting HID Capabilities
Some applications will simply want to look for the device vendor and product IDs. If you know the capabilities of your device, there is no need to do any more checking. However, you still need to get the preparsed data. If possible, you should write code that does not rely on specific vendor and product IDs.
Get the device ID using
Use
The first step when analyzing your device capabilities is to call
The HIDP_CAPS structure also contains much other useful information. First, it contains the maximum length of input, output, and feature reports in three fields. The first two of these values are saved, because they indicate how big a buffer to allocate to send and receive reports. The other HIDP_CAPS fields are used if you check the detailed control capabilities.
Listing 23.1 Getting a HID device's capabilities
bool GetCapabilities(HANDLE hHidKbd, PHIDP_PREPARSED_DATA& HidPreparsedData, USHORT& InputReportLen, USHORT& OutputReportLen) {
// Get attributes, i.e. find vendor and product ids
HIDD_ATTRIBUTES HidAttributes;
if (!HidD_GetAttributes(hHidKbd, &HidAttributes)) {
printf('XXX Could not get HID attributes
');
return false;
}
printf('HID attributes: VendorID=%04X, ProductID=%04X, VersionNumber=%04X
',
HidAttributes.VendorID, HidAttributes.ProductID, HidAttributes.VersionNumber);
// Get preparsed data
if (!HidD_GetPreparsedData( hHidKbd, &HidPreparsedData)) {
printf('XXX Could not get HID preparsed data
');
return false;
}
// Work out capabilities
HIDP_CAPS HidCaps;
bool found = false;
NTSTATUS status = HidP_GetCaps(HidPreparsedData, &HidCaps);
if (status==HIDP_STATUS_SUCCESS) {
printf('Top level Usage page %d usage %d
', HidCaps.UsagePage, HidCaps.Usage);
if (HidCaps.UsagePage==HID_USAGE_PAGE_GENERIC && HidCaps.Usage==HD_USAGE_GENERIC_KEYBOARD) {
printf(' Found HID keyboard
');
found = true;
}
// Remember max lengths of input and output reports
InputReportLen = HidCaps.InputReportByteLength;
OutputReportLen = HidCaps.OutputReportByteLength;
printf('InputReportByteLength %d
', HidCaps.InputReportByteLength);
printf('OutputReportByteLength %d
', HidCaps.OutputReportByteLength);
printf('FeatureReportByteLength %d
', HidCaps.FeatureReportByteLength);
printf('NumberLinkCollectionNodes %d
', HidCaps.NumberLinkCollectionNodes);
printf('NumberInputButtonCaps %d
', HidCaps.NumberInputButtonCaps);
printf('NumberInputValueCaps %d
', HidCaps.NumberInputValueCaps);
printf('NumberOutputButtonCaps %d
', HidCaps.NumberOutputButtonCaps);
printf('NumberOutputValueCaps %d
', HidCaps.NumberOutputValueCaps);
printf('NumberFeatureButtonCaps %d
', HidCaps.NumberFeatureButtonCaps);
printf('NumberFeatureValueCaps %d
', HidCaps.NumberFeatureValueCaps);