Input report 0: 00 00 00 00 00 00 00 00 A released
Usages set: (Break: 04) (Make: )
Input report 0: 00 00 05 00 00 00 00 00 B pressed
Usages set: 07:05 (Break: ) (Make: 05)
Input report 0: 00 00 00 00 00 00 00 00 B released
Usages set: (Break: 05) (Make: )
Input report 0: 00 00 06 00 00 00 00 00 C pressed
Usages set: 07:06 (Break: ) (Make: 06)
Input report 0: 00 00 00 00 00 00 00 00 C released
Usages set: (Break: 06) (Make: )
Input report 0: 00 00 29 00 00 00 00 00 Esc pressed
Usages set: 07:29 (Break: ) (Make: 29)
Test 3
Output report: 00
Wrote output report OK
Output report: 04
Wrote output report OK
Output report: 02
Wrote output report OK
Output report: 01
Wrote output report OK
Output report: 06
Wrote output report OK
Output report: 05
Wrote output report OK
Output report: 03
Wrote output report OK
Output report: 07
Wrote output report OK
Output report: 00
Wrote output report OK
Test 4
CloseHandle worked
Kernel Mode HID Clients
A device driver can talk to a HID device using the HID class driver. As mentioned previously, it is far easier to write a user mode application to control a HID device. However, you may find that it is necessary to write a HID client driver (e.g., if you need to implement an existing device API). A kernel client should be more efficient than a user mode client, though speed ought not to be a problem for most human input devices.
A kernel mode HID client can take one of two main forms, depending on how it relates to devices. An 'AddDevice' HID client uses installation files (as usual) to layer itself above the HID class driver for each device. Alternatively, 'Plug and Play Notification' HID client driver is not initially associated with any one device. Instead, it receives notifications when a HID device arrives or disappears. A PnP Notification HID client makes its own device objects if a HID device of interest arrives.
As I have not examined Plug and Play Notification before, this chapter's example driver, HidKbd, uses this technique.
'AddDevice' HID Clients
An 'AddDevice' HID client will look like all the previous WDM device drivers. The driver is loaded using installation INF files in the normal way. The driver's AddDevice routine is called when a suitable device is loaded. The driver must handle Plug and Play IRPs in the same way as usual.
An 'AddDevice' HID client makes calls to the HID class driver by calling the
As is usual for WDM drivers, your driver's upper edge may be completely different. For example, the kbdhid.sys system keyboard driver has an upper edge that reports 8042 equivalent key presses. However, kbdhid.sys makes HID requests on its lower edge to find the HID keyboard data.
Things can now get complicated. Note that user mode clients will still be able to find the HID device. If they try to send HID requests to the HID device, these requests will be routed to your driver first. If your driver implements some other upper edge, it will not recognize these requests. Or, if you are being very clever, you could recognize when HID operations have been requested and route them straight through to the HID class driver. If you do this job, you are acting as a HID filter driver.
All in all, it is probably easier if you do not use the 'AddDevice' device technique when writing a HID client driver. Therefore, I shall take a close look at how to write a Plug and Play Notification client. However, kernel mode PnP Notification does not seem to work in Windows 98, so you will have to write an 'AddDevice' client.
'PnP Notification' HID Clients
A PnP Notification HID client is usually an NT style driver. Therefore, it is not loaded as a result of a device being plugged in. As an NT style driver, it is usually loaded when the system boots up. Installation INF files are not used. Instead, you must write a custom installation program, as described in Chapter 11.
The
In this case, the device interface change callback is informed whenever any HID device is plugged into the system. The HidKbd code then interrogates the device to see if it is a HID keyboard. If it is, it creates a HidKbd device.
Just to complicate matters, HidKbd now has two options. First, it can layer itself over the HID device so that is becomes part of the device stack for this device. However, this suffers from the same drawbacks as the 'AddDevice' technique, that user mode requests to the HID device would be routed to HidKbd.
The HidKbd driver takes the second option. HidKbd stores a pointer to the HID device object, but does not layer itself above the HID device. Both HidKbd and a user mode application can therefore call the HID class driver safely.
Kernel mode drivers can register to receive three different types of notification events. As far as I can tell, none of these notifications work in Windows 98, as calling
Table 23.2 shows how to call
If you register to receive EventCategoryHardwareProfileChange events, you are supposed to receive hardware profile change events. The callback is told whether a
Registering for EventCategoryTargetDeviceChange events asks for notifications when a target device is removed. You must pass a PFILE_OBJECT as the EventCategoryFlags. The callback is told whether a
Table 23.2 IoRegisterPlugPlayNotification function
NTSTATUS IoRegisterPlugPlayNotification | (IRQL==PASSIVE_LEVEL) |
---|