Книга: Writing Windows WDM Device Drivers

HID Class Driver

HID Class Driver

The HID class driver is the key to using HID in Windows. It uses HID minidrivers to talk to actual devices. It handles requests from clients, directing them to the correct minidriver.

When a new HID device is found by the Plug and Play Manager, the installation INF file eventually ensures that the HID class driver and the appropriate minidriver are loaded.

The HID class driver uses the minidriver to read the HID and Report descriptors. The HID class driver then creates a device object for each of the top-level collections described in the Report descriptor. Each device object is registered as belonging to the HID class device interface.

User mode and kernel mode clients can use the HID class device interface GUID to identify all the available HID devices. The client must get the device capabilities to see if the device is of interest. If you were looking for a HID keyboard, you would ignore a HID mouse.

Each request to the HID class driver eventually ends up as a call to the appropriate HID minidriver. Each minidriver knows how to send and receive HID reports, for example. This chapter does not describe how to write minidrivers; this subject is covered in the DDK.

HID Class Driver Characteristics

The HID class driver responds to Create, Close, Read, Write, and IOCTL IRPs. Read and Write requests are used for input, output, and feature reports. IOCTLs are used to retrieve HID device capabilities. User mode applications should not use the IOCTLs directly. Instead, various HidD… routines are supplied to make the job easier.

Ring Buffer

The HID class driver has a buffer for each device for input reports. This holds input reports until a client reads them. This is a "ring buffer", so if the reports are not read quickly enough, new reports may overwrite the old reports (i.e., data may get lost).

A kernel mode client can get and set the ring buffer size using two IOCTLs.

Multiple Open Handles

In Windows 98, more than one program can access a single HID device at the same time. For example, if a HID keyboard is attached then a Windows kernel mode driver will be loaded to talk to it. This driver ensures that any key presses are routed into the normal keyboard driver. You can also open up another handle to the device object in the HID class driver that represents the HID keyboard. Therefore, in W98 at least, any input reports are received on all open handles.

However in Windows 2000, the HID keyboard driver opens a HID keyboard for exclusive access. Therefore the HidKbdUser user mode program and the HidKbd driver are unable to talk to the keyboard. I was able to develop this code in the Beta 2 version of W2000, when the keyboard was not opened for exclusive access.

Windows HID Clients

Windows 98 and Windows 2000 have built in support for various types of common HID device (e.g., keyboards, mice, game ports, audio controls, and the DirectInput system). The standard installation INF files load the required drivers automatically. If you plug in a HID USB keyboard, for example, the relevant system drivers are loaded and you should be able to start typing straightaway[56].

Figure 23.1 shows the Windows 2000 drivers that are loaded to service a "legacy" keyboard and a HID USB keyboard. The situation is identical in Windows 98, apart from the driver filenames. For mouse input and game ports, the driver diagrams are almost identical. However, in Windows 2000, all the game port input is now done using HID with a HID joystick minidriver.

The Win32 subsystem still uses the standard keyboard driver, KbdClass.sys in W2000, to get all its keyboard input. This interrogates the 8042 legacy keyboard in the same way as NT 4 and earlier. However, the keyboard driver can also get its input from a HID keyboard. An intermediate driver, KbdHid.sys in W2000, is used. I assume that KbdHid.sys does all the hard work of interrogating the HID class driver, and it simply returns 8042 equivalent scan codes to the main keyboard driver.

The keyboard auto-repeat feature is not usually present in a HID keyboard. Either the KbdClass.sys or the KbdHid.sys driver must implement auto-repeat. Similarly, the Ctrl+Alt+Del key combination must be detected by one of these drivers. Quite correctly, it is not a feature of HID class driver.

I understand that KbdHid.sys driver always tries to keep two outstanding read requests for a keyboard: one to detect a key being depressed and one to detect a key being released. Combined with the HID class driver ring buffer, this technique should ensure that no key presses are lost.

In the future, it would be neater if Microsoft rearranged this keyboard driver layout. They would have to write a HID minidriver for the legacy 8042 port. All keyboard input would then come through the HID class driver. Although this approach might be slower, it should not matter for such a relatively slow device as a keyboard.

In addition, the figure shows that a user mode client can also access the HID keyboard as a HID device. It will receive regular HID input reports, as shown later. It will not receive 8042 equivalent scan codes. As I mentioned previously, all input reports are received by both KbdHid.sys and the user mode client.

Figure 23.1 Windows and a user mode client using a HID keyboard


Header Files

Table 23.1 shows the HID header files that you need to include. In the Windows 98 DDK, these files are in the srchidinc directory. In the Windows 2000 DDK, most headers are in the standard inc directory, while the others are in srcwdmhidinc.

Table 23.1 HID header files

hidсlass.h IOCTL codes
hidpddi.h Other parsing library routines
hidpi.h Parsing routines (i.e., HidP… functions and structures)
hidport.h Minidriver header
hidsdi.h User-mode HidD… functions
hidtoken.h Report descriptor item constants
hidusage.h Standard usage values

HID USB Minidriver

HID evolved from the USB specification, but is now a general purpose input device model. Nonetheless, HID fits neatly into the USB model. The HID class is one of the classes defined in the USB Specifications.

At present, the USB bus is one of the few places where HID devices can be found. The HID class driver talks to the USB device stack through the HidUsb.sys driver.

A HID USB device has the standard USB device, configuration, interface, and endpoint descriptors. In addition, it has the class-specific HID, Report, and Physical descriptors described in the previous chapter.

The standard USB device descriptor has zeroes for its class, subclass, and protocol. The standard interface descriptor has constant USB_DEVICE_CLASS_HUMAN_INTERFACE (0x03) in its bInterfaceClass field, iInterfaceSubClass is set to 1 if the device supports a boot protocol, described in the following text. In this case, bInterfaceProtocol is 1 for a keyboard and 2 for a mouse.

A USB request for the Configuration descriptor usually returns the HID descriptor before the endpoint descriptors[57]. The report and physical descriptors must be specifically asked for, using the following codes.

HID Descriptor HID_HID_DESCRIPTOR_TYPE 0x21
Report descriptor HID_REPORT_DESCRIPTOR_TYPE 0x22
Physical Descriptor HID_PHYSICAL_DESCRIPTOR_TYPE 0x23

A HID USB device uses the default control pipe endpoint 0 and one interrupt pipe. The control pipe is used for standard USB purposes and for sending and receiving reports, etc. The interrupt pipe is used to return new input reports.

USB HID devices support the notion of an idle rate. Whenever an interrupt request is received from the host, the USB HID device can either return a report or a NAK to indicate that nothing has changed. In the former case, no input state may have changed and so host processing of the report will waste time. The idle rate determines how often the HID USB device returns a report. If at any time during the idle rate period, an input report changes, the HID USB device does return an input report at the next interrupt. The recommended idle rate for keyboards is 500ms and infinity for joysticks and mice.

The following HID-specific class requests are supported on the default pipe. GET_REPORT and SET_REPORT get or send a specific input, output, or feature report. An idle rate can be defined using SET_IDLE and read using GET_IDLE. SET_PROTOCOL and GET_PROTOCOL are used for boot devices, as described in the following text.

USB Boot Devices

A USB keyboard or mouse must be available during boot so the user can configure the BIOS settings, select the operating system, etc.

The BIOS can read the USB interface descriptor with relative ease. If it finds that iInterfaceSubClass field is 1, the device must be a keyboard or mouse that supports the boot protocol. The Report descriptor for boot keyboards and mice must be in a standard format. Therefore, the BIOS does not have to read and decode the Report descriptor. It simply uses the SET_PROTOCOL command to enable the standard reports.

A boot keyboard input report is usually eight bytes long, in the format described in the previous chapter. Other requirements for a boot keyboard are given in the HID specification.

A mouse boot input report is at least three bytes long. The first three bits are the mouse button states. The second and third bytes are the X and Y displacements.

Оглавление книги


Генерация: 0.976. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз