ShowButtonCaps('Input button capabilities', HidP_Input, HidCaps.NumberInputButtonCaps, HidPreparsedData);
ShowButtonCaps('Output button capabilities', HidP_Output, HidCaps.NumberOutputButtonCaps, HidPreparsedData);
}
return found;
}
Why Get Button and Value Capabilities?
Some programs cannot just rely on the HIDP_CAPS
Each control in a HID device is seen by Windows as being either a
Each of the keys on a keyboard has a HID usage. All keyboard keys are in usage page 7. Within that usage page, most of the usages from 0 to 255 have key definitions. However, most Western keyboards produce usage codes in two ranges. Usages 0 to 101 contain most standard keys, while usages 224 to 231 represent the modifier keys such as Shift, Ctrl, Alt, etc. To be extra careful, check that the HID device generates usages in these two ranges.
Similarly to double check that the HID device has the correct LEDs check that its output report contains buttons in usage page 8, for LEDs. Within this usage page, usage 1 corresponds to NumLock, usage 2 with CapsLock, and usage 3 with ScrollLock.
Getting Button Capabilities
The HIDP_CAPS structure has fields that tell you how many button and value capabilities there are for each type of report. For example,
Each HIDP_BUTTON_CAPS structure has similar fields for the string descriptors and physical designators associated with controls. Finally, various link fields specify in which collection the buttons are. See the previous chapter for a description of collections.
Listing 23.2 Getting buttons capabilities
void ShowButtonCaps(char* Msg, HIDP_REPORT_TYPE ReportType, USHORT NumCaps, PHIDP_PREPARSED_DATA HidPreparsedData) {
if (NumCaps==0) return;
printf(' %s
', Msg);
HIDP_BUTTON_CAPS* ButtonCaps = new HIDP_BUTTON_CAPS[NumCaps];
if( ButtonCaps==NULL) return;
NTSTATUS status = HidP_GetButtonCaps(ReportType, ButtonCaps, &NumCaps, HidPreparsedData);
if (status==HIDP_STATUS_SUCCESS) {
for (USHORT i=0; i<NumCaps; i++) {
printf('ButtonCaps[%d].UsagePage %d
', i, ButtonCaps[i].UsagePage);
if (ButtonCaps[i].IsRange) printf('.Usages %d..%d
', ButtonCaps[i].Range.UsageMin, ButtonCaps[i].Range.UsageMax);
else printf('.Usage %d
', ButtonCaps[i].NotRange.Usage);
}
}
delete ButtonCaps;
}
Here is an excerpt from the output produced by the
Input button capabilities
ButtonCaps[0].UsagePage 7
.Usages 224..231
ButtonCaps[1].UsagePage 7
.Usages 0..101
Output button capabilities
ButtonCaps[0].UsagePage 8
.Usages 1..3
Use
Getting Value Capabilities
You can retrieve details of what control
Getting Collection Capabilities
The
Reading input reports from a HID device is straightforward. Listing 23.3 shows how this is done in the
First, allocate and zero a buffer to receive a report, with the size given in the HIDP_CAPS structure. A keyboard input report is always eight bytes long. However, the
Use
Listing 23.3 Reading keyboard input reports
DWORD TxdBytes;
char* InputReport = new char[InputReportLen];
assert(InputReport!=NULL);
// Loop until Esc pressed on keyboard
do {
if (!ReadFile( hHidKbd, InputReport, InputReportLen, &TxdBytes, NULL)) {
printf('XXX Could not read value %d
', GetLastError());
break;
} else if (TxdBytes==InputReportLen) {
printf(' Input report %d:', InputReport[0]);
for(USHORT i=1; i<InputReportLen; i++) printf(' %02X', InputReport[i]);
printf('
');
DecodeInputUsages(InputReport, InputReportLen, HidPreparsedData);
} else {
printf('XXX Wrong number of bytes read: %d
', TxdBytes);
break;
}
} while (InputReport[3]!=0x29);
delete InputReport;
What Buttons Were Set in My Report?
You could just look directly at the received buffer and work out what it means. However, the correct HID way to analyze reports is get the HID parsing routines to tell you what usages were set in the report. DecodeInputUsages, shown in Listing 23.4, does just this job. Indeed, it goes further by telling you what changes have occurred since the last input report. It prints out the usages that have just been 'made' and the ones have just been 'broken'.
The