structures (i.e., usage page and usage values).
The maximum usage list length for a keyboard report is 14. This is made up of the six keys that the HID Report descriptor says can be pressed simultaneously, and the eight modifier keys, again that the Report descriptor says can be pressed simultaneously. Obviously, it is extremely unlikely that 14 keys can be pressed at the same time.
The next job, if desired, is to work out what has changed since the last input report. The
Listing 23.4 Decoding input report usages
const ULONG MaxPreviousUsages = 14;
USAGE_AND_PAGE Usages[MaxPreviousUsages];
USAGE PreviousUsages[MaxPreviousUsages];
void DecodeInputUsages(char* KbdReport, USHORT KbdReportLen, PHIDP_PREPARSED_DATA HidPreparsedData) {
// Get max number of USAGE_ANQ_PAGEs required for all input reports in
// top-level collection
ULONG MaxUsages = HidP_MaxUsageListLength(HidP_Input, 0, HidPreparsedData);
if (MaxUsages==0 || MaxUsages>MaxPreviousUsages) {
printf('XXX Invalid HidP_MaxUsageListLength returned %d
', MaxUsages);
return;
}
// Get usages set in given keyboard report
ULONG ValidUsages = MaxUsages;
NTSTATUS status = HidP_GetButtonsEx(HidP_Input, 0, Usages, &ValidUsages, HidPreparsedData, KbdReport, KbdReportLen);
if (status==HIDP_STATUS_SUCCESS) {
USAGE CurrentUsages[MaxPreviousUsages];
USAGE BreakUsages[MaxPreviousUsages];
USAGE MakeUsages[MaxPreviousUsages];
// Show current usages
memset(CurrentUsages, 0, sizeof(CurrentUsages));
printf(' Usages set: ');
for (ULONG i=0; i<ValidUsages; i++) {
printf( ' %02X:%02X', Usages[i].UsagePage, Usages[i].Usage);
CurrentUsages[i] = Usages[i].Usage;
}
// Work out differences compared to previous usages
HidP_UsageListDifference(PreviousUsages, CurrentUsages, BreakUsages, MakeUsages, MaxUsages);
// Print out usages broken and made
printf(' (Break: ');
for (i=0; i<MaxUsages; i++) {
if (BreakUsages[i]==0) break;
printf(' %02X', BreakUsages[i]);
}
printf(') (Make: ');
for(i=0; i<MaxUsages; i++) {
if (MakeUsages[i]==0) break;
printf(' %02X', MakeUsages[i]);
}
printf(')
');
// Save previous usages
memcpy(PreviousUsages, CurrentUsages, MaxUsages*sizeof(USAGE));
}
}
The
What Values Were Set in My Report?
Use the
Sending Output Reports
You send HID output reports using the Win32
The
SetLEDs(hHidKbd, OutputReportLen, HidPreparsedData, HID_USAGE_LED_SCROLL_LOCK);
A keyboard output report consists of just one byte. However, as before, the output buffer must have an extra byte at the beginning for the report ID. This is set to zero in this case, as keyboards do not use report IDs. SetLEDs allocates an output buffer and zeroes it.
You can call
Be careful if you are using a HID device that has more than one output report. HidP_SetButtons can only build one output report at a time.
Listing 23.5 Setting keyboard LEDs using an output HID report
void SetLEDs(HANDLE hHidKbd, USHORT OutputReportLen, PHIDP_PREPARSED_DATA HidPreparsedData,
USAGE Usage1/*=0*/, USAGE Usage2/*=0*/, USAGE Usage3/*=0*/) {
// Build Output report from given usage(s)
char* OutputReport = new char[OutputReportLen];
assert(OutputReport!=NULL);
memset(OutputReport, 0, OutputReportLen);
USAGE UsageList[3];
UsageList[0] = Usage1;
UsageList[1] = Usage2;
UsageList[2] = Usage3;
ULONG UsageLength = 0;