IoSetCompletionRoutine(dx->HidIrp, (PIO_COMPLETION_ROUTINE)ReadComplete, &event, TRUE, TRUE, TRUE);
NTSTATUS status = IoCallDriver(dx->HidDevice, dx->HidIrp);
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
status = dx->HidIrp->IoStatus.Status;
}
// return IRP completion status
DebugPrint('ReadHidKbdInputReport: status %x', status);
BytesTxd = dx->HidIrp->IoStatus.Information;
if (BytesTxd>0) RtlCopyMemory(Buffer, dx->HidReport, BytesTxd);
return status;
}
NTSTATUS ReadComplete(IN PDEVICE_OBJECT fdo, IN PIRP Irp, IN PKEVENT Event) {
KeSetEvent(Event, 0, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
Even Better …
Two problems exist with the permanently allocated IRP solution I have just presented. The first is that the driver will not cope with two 'simultaneous' read requests as it uses the same buffer in each call. A quick fix to this problem would be to allow only one read request at a time. The next best solution is dropping the shared buffer; an MDL must then be allocated for the user buffer in each read request.
In fact, the best solution is not to use a permanently allocated IRP, but to reuse the Read IRP. If the HidKbd device uses Direct I/O, the operating system will even do the MDL allocation. In this version, the
The second problem with both the earlier techniques of calling the HID class driver is that they can be inefficient. In both the earlier cases, the call to
This technique should be used wherever possible. The HidKbd Create and Close IRP use this technique as they pass their IRPs to the HID class driver, which completes them in due course. However, it is probably still worth using events in the
The
The DDK header files define several other HID IOCTLs. However, some of these are used by the HID class driver when it talks to a minidriver. It is not clear if any of these are available to HID clients.
Conclusion
This chapter concludes my look at the Human Input Device class driver. It is straightforward to write a user mode application to communicate with a HID device. A Win32 program looks for devices that use the HID device interface. They must then interrogate each device to see if their capabilities are of interest. The program can then read input reports and send output reports.
If need be, you can write a kernel mode HID client. It is best if you use the Plug and Play Notification technique to find any devices that support the HID device interface. Then, you can get the device capabilities and send and receive reports in a broadly similar way to user mode applications.
Both user mode and kernel mode HID clients can make use of the HID parsing routines. These make it much easier to find HID device's capabilities and to generate and understand reports.
Appendix A
Information Resources
Microsoft is the best source of information for most core Windows device driver development issues. Various books and newsgroups are also available to help driver writers. You may well need to check out other sources of information particular to your type of driver. You may need to seek help from vendors, standards bodies, and trade associations, as well as other driver writers.
A Microsoft Developer Network (MSDN) Professional Subscription provides most of the basic information you need to write device drivers. You get all the basic tools, Driver Development Kits (DDKs), and beta test versions of the Microsoft operating systems. However, it is worth keeping an eye on the Microsoft websites, as helpful articles and late-breaking news can often be posted. You will also need a C or C++ compiler, such as Visual Studio. The crucial Microsoft web sites are:
http://www.microsoft.com/hwdev/
http://www.microsoft.com/hwdev/driver/
http://msdn.microsoft.com/developer/
The DDKs include many example drivers that are very useful. Searching through these examples will often show you how to use a particular function or technique. Alternatively, you can base your entire driver on an existing example. Needless to say, do not use code blindly — make sure you understand what is going on. Finally, the sample driver directories often contain useful documentation in the form of Word or text files.
Table A.1 Information resources
Advanced Configuration and Power Interface Specification, Revision 1.0 | http://www.teleport.com/~acpi/ |
Device Bay Interface Specification, Version 1.0 | http://www.device-bay.org |
Display Data Channel Standard, Version 3.0 | http://www.vesa.org |
Extended Display Identification Data Standard, Version 2.0 | |
El Torito — Bootable CD-ROM Format Specification, Version 1.0 | http://www.ptltd.com/techs/specs.html |
Compaq, Intel, Phoenix BIOS Boot Specification, Version 1.01 | |
Human Input Devices | http://www.usb.org/developers/ |
IEEE 1394 Information | ftp://ftp.symbios.com/pub/standards/io/ |