I am developing an upper filter driver for USB devices, registered as an upper filter in the {36fc9e60-...-444553540000}
USB class GUID, using the KMDF framework. My goal is to read the device descriptor during EvtWdfDevicePrepareHardware
to obtain the device's class, subclass, and serial number.
To achieve this, I plan to send an IRP with the IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION
control code to the lower PDO (obtained using WdfFdoInitWdmGetPhysicalDevice
). I prepared the UsbDescriptorRequest
structure and implemented the code to read the device descriptor, including the VID and PID.
However, in my current implementation, the VID and PID values retrieved are invalid. I’ve reviewed the code but haven’t identified the issue. Below is the relevant code. Can you help pinpoint the bug?
NTSTATUS status;
PDEVICE_OBJECT pdo;
IO_STATUS_BLOCK ioStatusBlock;
KEVENT event;
PIRP irp;
UCHAR Buffer[256];
USB_DESCRIPTOR_REQUEST descriptorRequest = { 0 };
ULONG descriptorRequestSize = sizeof(USB_DESCRIPTOR_REQUEST) + sizeof(USB_DEVICE_DESCRIPTOR);
PUSB_DEVICE_DESCRIPTOR deviceDescriptor = (PUSB_DEVICE_DESCRIPTOR)&descriptorRequest.Data[0];`
// Initialize the descriptor request
descriptorRequest.ConnectionIndex = 1; // Port index
descriptorRequest.SetupPacket.wValue = USB_DEVICE_DESCRIPTOR_TYPE << 8; // Device Descriptor
descriptorRequest.SetupPacket.wIndex = 0;
descriptorRequest.SetupPacket.wLength = sizeof(USB_DEVICE_DESCRIPTOR);
// Initialize synchronization event
KeInitializeEvent(&event, NotificationEvent, FALSE);
// Build the IRP
irp = IoBuildDeviceIoControlRequest(
IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,
dev_context->pdo,
&descriptorRequest,
sizeof(USB_DESCRIPTOR_REQUEST),
&descriptorRequest,
descriptorRequestSize,
TRUE,
&event,
&ioStatusBlock
);
if (!irp) {
KdPrint(("Failed to build IRP\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
// Send the IRP
status = IoCallDriver(pdo, irp);
if (status == STATUS_PENDING) {
// Wait for completion
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = ioStatusBlock.Status;
}
if (NT_SUCCESS(status)) {
// Parse the USB Device Descriptor
KdPrint(("USB VID: 0x%04x, PID: 0x%04x\n",
deviceDescriptor->idVendor,
deviceDescriptor->idProduct));
} else {
KdPrint(("Failed to send IOCTL to PDO. Status: 0x%x\n", status));
}