0, // interface index
&OutputData, NULL, 1, // Output data
NULL);
// Call the USB driver
DebugPrintMsg("Sending set report");
NTSTATUS status = CallUSBDI(dx, urb);
// Check statuses
if (!NT_SUCCESS(status) || !USBD_SUCCESS(urb->UrbHeader.Status)) {
DebugPrint("status %x URB status %x", status, urb->UrbHeader.Status);
status = STATUS_UNSUCCESSFUL;
}
ExFreePool(urb);
return status;
}
Other Issues
The UsbGetStatuses routine shows how to read status words from the device, interface, and endpoint using the Get Status URB. These words are bundled into a 6-byte buffer in response to the UsbKbd IOCTL_USBKBD_GET_STATUSES request.
The UsbKbd IOCTL_USBKBD_GET_FRAME_INFO request is handled in the UsbGetFrameInfo routine. UsbGetFrameInfo uses the Get Current Frame Number and Get Frame Length URBs to find out the required information. Both these URBs are built by hand, as there are no UsbBuild…Request helper macros. The frame numbers returned are 32-bit ULONGs, not the USB SOF number that goes from 0-0x7FF.
The Win32 UsbKbdTest program puts the UsbKbd driver through its paces. Obviously, you must have a USB-enabled PC and a USB keyboard to try out this code. For the benefit of those who do not, I am reproducing both the UsbKbdTest output and the UsbKbd DebugPrint trace output in Listings 21.8 and 21.9.
You will first have to "install" the UsbKbd.sys driver by copying it into the Windows System32\drivers directory to replace HidUsb.sys. Do not forget to put the old HidUsb.sys back when you are finished.
The UsbKbdTest program does the following jobs.
1. Open a handle to the first driver that supports the USBKBD_GUID device interface.
2. Read the device descriptor.
3. Read the configuration descriptor, interface descriptor, etc. The UsbKbdTest output has been amended in Listing 21.8 to show each descriptor.
4. Read the HID report descriptor, type 0x22.
5. Set the read time-out to 15 seconds.
6. Keep reading keyboard input data until the Esc key is pressed (code 0x29). The output listing has been annotated to show when I have pressed these keys: Ctr+Alt+Del, then A, B, C and Esc.
7. Write a series of bit combinations to flash the keyboard LEDs, with a ⅓-second delay between changes.
8. Read the device, interface, and endpoint status words.
9. Read the frame length and frame numbers.
10. Close the file handle.
Armed with all the relevant specifications, you can decode what all the descriptors and keyboard data mean. The UsbKbd trace output lists some more useful information.
Listing 21.8 UsbKbdTest output
Test 1
Symbolic link is \\?\usb#vid_046a&pid_0001#7&4#{c0cf0646-5f6e-11d2-b677-00c0dfe4c1f3}
Opened OK
Test 2
Device descriptor is 12 01 00 01 00 00 00 08 6A 04 01 00 05 03 00 00 00 01
Test 3
Configuration descriptors are
09 02 22 00 01 01 00 A0 32 Configuration descriptor
09 04 00 00 01 03 01 01 00 Interface descriptor
07 05 81 03 08 00 08 Endpoint descriptor
09 21 00 01 00 01 22 3F 00 HID descriptor
Test 4
HID Report descriptor is 05 01 09 06 A1 01 05 07 19 E0 29 E7 15 00 25 01 75 01 95 08 81 02 75 08 95 01 81 01 05 08 19 01 29 03 75 01 95 03 91 02 75 05 95 01 91 01 05 07 19 00 29 65 15 00 25 65 75 08 95 06 81 00 C0
Test 5
Read time-out set
Test 6
Kbd report 1 0 0 0 0 0 0 0 Ctrl
Kbd report 5 0 0 0 0 0 0 0 Ctrl+Alt
Kbd report 5 0 63 0 0 0 0 0 Ctrl+Alt+Del
Kbd report 4 0 0 0 0 0 0 0 Alt
Kbd report 0 0 4 0 0 0 0 0 A
Kbd report 0 0 5 0 0 0 0 0 B
Kbd report 0 0 6 0 0 0 0 0 C
Kbd report 0 0 29 0 0 0 0 0 Esc
Test 7
Wrote 1 OK
Wrote 2 OK
Wrote 3 OK
Wrote 4 OK
Wrote 5 OK
Wrote 6 OK
Wrote 7 OK
Wrote ff OK
Wrote 0 OK
Test 8
Statuses are 0 0 0
Test 9
FrameLength 11999 bits. FrameNumber 1847715. FrameAlterNumber 1847715
Test 10
CloseHandle worked
Listing 21.9 UsbKbdTest corresponding DebugPrint trace output in W2000
CreateFile
16:34:09.567 Create File is
16:34:09.567 USBDI version 00000200 Supported version 00000100
16:34:09.567 Getting port status
16:34:09.567 Got port status 00000003
16:34:09.567 Getting basic configuration descriptor
16:34:09.567 Got basic config descr. MaxPower 50 units of 2mA
16:34:09.567 Getting full configuration descriptors
16:34:09.577 Selecting configuration
16:34:09.677 Select configuration worked
16:34:09.577 interface Class 3 NumberOfPipes 1
16:34:09.577 PipeHandle = 80973FC0
16:34:09.577 Pipes[0] EndpointAddress 81 Interval 8ms PipeType 3 MaximumTransferSize 4096
16:34:09.577 Getting bus info
16:34:09.577 Bus info: TotalBandwidth 12000, ConsumedBandwidth 0 and ControllerNameLength 32
16:34:09.577 Controller name is \DosDevices\HCD0
16:34:09.577 Getting descriptor type 03
16:34:09.577 No string descriptors
16:34:09.577 Sending Get Idle request
16:34:09.577 Idle rate is 125 units of 4ms
Get device descriptor using IOCTL_USBKBD_GET_DEVICE_DESCRIPTOR
16:34:09.577 DeviceIoControl: Control code 00222008 InputLength 0 OutputLength 50
16:34:09.577 Getting device descriptor 16:34:09.577 DeviceIoControl: 18 bytes written
Get all configuration descriptors using IOCTL_USBKBD_GET_CONFIGURATION_DESCRIPTORS
16:34:09.587 DeviceIoControl: Control code 0022200C InputLength 0 OutputLength 500
16:34:09.587 Getting basic configuration descriptor
16:34:09.587 Got basic config descr. MaxPower 50 units of 2mA
16:34:09.587 Getting full configuration descriptors
16:34:09.587 DeviceIoControl: 34 bytes written
Get HID Report Descriptor using IOCTL_USBKBD_GET_SPECIFIED_DESCRIPTOR
16:34:09.597 DeviceIoControl: Control code 00222010 InputLength 8 OutputLength 500
16:34:09.597 Getting descriptor type 22
16:34:09.597 DeviceIoControl: 63 bytes written
Set read timeout using IOCTL_USBKBD_SET_READ_TIMEOUT
16:34:09.617 DeviceIoControl: Control code 00222004 InputLength 4 OutputLength 0
16:34:09.617 USB timeout set to 15
16:34:09.617 DeviceIoControl: 0 bytes written
Read Ctrl+Alt+Del key presses
Читать дальше