Here’s the descriptor:
HID_REPORT_DESCRIPTOR G_DefaultReportDescriptor[] = {
0x05, 0x0d, // USAGE_PAGE (Digitizers)
0x09, 0x04, // USAGE (Touch Screen)
0xa1, 0x01, // COLLECTION (Application)
0x85, REPORTID_TOUCH, // REPORT_ID (Touch)
0x09, 0x20, // USAGE (Stylus)
0xa1, 0x00, // COLLECTION (Physical)
0x09, 0x42, // USAGE (Tip Switch)
0x09, 0x32, // USAGE (In Range)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x06, // REPORT_COUNT (6)
0x81, 0x03, // INPUT (Cnst,Ary,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x03, // LOGICAL_MAXIMUM (1023)
0x75, 0x10, // REPORT_SIZE (16)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
0xc0, // END_COLLECTION
};
So I think that makes only one top level collection. However that’s appended to the existing URB:
case URB_FUNCTION_CONTROL_TRANSFER:
{
struct _URB_CONTROL_TRANSFER* pTransfer = (struct _URB_CONTROL_TRANSFER*) pUrb;
DbgPrint("pDescriptorRequest->TransferBufferLength = %d\n", pTransfer->TransferBufferLength);
if (pTransfer->SetupPacket[0] == 0x80 && pTransfer->SetupPacket[1] == 0x06 &&
pTransfer->SetupPacket[2] == 0x00 && pTransfer->SetupPacket[3] == 0x02 &&
pTransfer->SetupPacket[4] == 0x00 && pTransfer->SetupPacket[5] == 0x00 &&
pTransfer->SetupPacket[6] == 0x22 && pTransfer->SetupPacket[7] == 0x00) {
// Configuration Descriptor
PUCHAR buf = (PUCHAR)USBPcapURBGetBufferPointer(pTransfer->TransferBufferLength,
pTransfer->TransferBuffer, pTransfer->TransferBufferMDL);
size_t length = ((size_t)buf[0x1a] << 8) | (size_t)buf[0x19];
length += sizeof(G_DefaultReportDescriptor); // Append to existing report descriptor.
buf[0x1a] = (UCHAR)(length >> 8);
buf[0x19] = (UCHAR)(length & 0xFF);
}
else if (pTransfer->SetupPacket[0] == 0x81 && pTransfer->SetupPacket[1] == 0x06 &&
pTransfer->SetupPacket[2] == 0x00 && pTransfer->SetupPacket[3] == 0x22 &&
pTransfer->SetupPacket[4] == 0x00 && pTransfer->SetupPacket[5] == 0x00)
{
// HID Report Descriptor
// NOTE: Reallocating TransferBuffer is useless because it's a pointer provided by the upper driver.
// But since we reported a sizeof(G_DefaultReportDescriptor) length, it should be allocated the right size.
// Only the lower USB driver set TransferBufferLength back to 241, the original Report Descriptor size, which can be misleading.
PUCHAR buf = NULL;
size_t append_size = ((size_t)pTransfer->SetupPacket[7] << 8) | (size_t)pTransfer->SetupPacket[6];
if (append_size > sizeof(G_DefaultReportDescriptor)) {
append_size = sizeof(G_DefaultReportDescriptor);
}
buf = (PUCHAR)USBPcapURBGetBufferPointer(pTransfer->TransferBufferLength,
pTransfer->TransferBuffer, pTransfer->TransferBufferMDL);
RtlCopyMemory(&buf[pTransfer->TransferBufferLength], &G_DefaultReportDescriptor[0], append_size);
pTransfer->TransferBufferLength += append_size;
}
break;
}
David