Книга: Writing Windows WDM Device Drivers

USB Client Driver Design

USB Client Driver Design

A USB client driver is a standard WDM driver with Plug and Play support. As described in Chapters 11 and 20, the USB hub driver detects when a new USB device is inserted. The PnP Manager uses the vendor ID or device class information to select the driver to run. The driver's AddDevice routine is called and other PnP IRPs are issued as normal. Client USB drivers never receive any hardware resources, such ports or interrupts, as the USB class drivers handle all the low-level I/O.

USB devices are particularly prone to surprise removals, when the user accidentally (or deliberately) pulls out the USB plug. In Windows 2000, you will receive a Surprise Removal PnP IRP, while in Windows 98, only a Remove Device PnP IRP. These requests must succeed even if there are open handles to the device. Any transfers that are in progress must be aborted.

By definition, a USB client driver makes calls, at its lower edge, to the USB class drivers. However, it can implement whatever upper edge it deems necessary. The UsbKbd example driver in this chapter exposes a device interface that allows Win32 applications to read raw keyboard data and issue various IOCTLs. However, your driver could take a totally different approach, depending on what your USB device does.

The UsbKbd example driver is based on the Wdm2 driver, with Power Management support removed. The UsbKbd driver source code is in the book software UsbKbdSys directory. I suggest that you use UsbKbd as the basis for your USB client driver. Most of the USB handling routines are in the file Usb.cpp. You will need to alter the upper edge interface that is implemented in the dispatch routines in Dispatch.cpp.

A real USB client driver should support Power Management. An article on the Microsoft website at www.microsoft.com/hwdev entitled "OnNow requirements in the USB Core Specification" discusses this issue.

Using UsbKbd

UsbKbd devices can be found by Win32 applications using the USBKBD_GUID device interface. When a handle to a UsbKbd device is opened, the UsbKbd driver starts talking to the USB peripheral. If the peripheral is a HID USB keyboard, its configuration is selected, thereby enabling the keyboard interrupt pipe. The UsbKbd Create IRP handler also obtains some more information from the device and the USB class drivers, displaying DebugPrint trace output in the checked build of the driver.

Closing the file handle deselects the keyboard's configuration.

The Win32 application can then use standard ReadFile calls to obtain raw keyboard data from UsbKbd. The raw data is in the form a HID keyboard input report, sent on a USB interrupt pipe. Chapter 22 details the format of this report precisely. All you need to know for now is that the first byte has all the modifier key bits (such as Shift, Control, etc.). The third and following bytes contain the HID keypress codes for all the keys that are currently pressed.

The time-out defaults to 10 seconds for ReadFile calls. One of the UsbKbd IOCTLs can be used to alter the time-out.

The UsbKbd driver also accepts WriteFile calls to change the state of the keyboard LEDs. The first byte of the WriteFile data is sent as a HID output report in a control transfer along the default pipe to Endpoint 0. The lower five bits of this byte are defined, though most keyboards just have three LEDs.

Table 21.1 shows the IOCTLs that UsbKbd supports. These functions are provided just to let you see how to exercise the USB interface. In most cases, you would not want to expose such IOCTLs for general use, although they might be useful for debugging purposes.

Table 21.1 UsbKbd IOCTLs

IOCTL_USBKBD_SET_READ_TIMEOUT Input ULONG Time-out in seconds Specifies the time-out for subsequent read requests
IOCTL_USBKBD_GET_DEVICE_DESCRIPTOR Output Received device descriptor Read the device descriptor.
IOCTL_USBKBD_GET_CONFIGURATION_DESCRIPTORS Output Received descriptors Read the first configuration descriptor, along with any associated, interface, endpoint, class and vendor descriptors.
IOCTL_USBKBD_GET_SPECIFIED_DESCRIPTOR Input ULONG Descriptor type, ULONG Descriptor size Read the specified descriptor into the given sized buffer
Output Received descriptor
IOCTL_USBKBD_GET_STATUSES Output 6-byte buffer for status values Read the device, first interface and first endpoint status values (16 bits each)
IOCTL_USBKBD_GET_FRAME_INFO Output 12-byte buffer for frame information Read the ULONG current frame length (in bits), the ULONG current frame number and the ULONG frame number for the next frame whose length can be altered

UsbKbd Installation

For your USB client driver, you will use a standard installation INF file. In the Version section, make sure that you include the following lines.

Class=USB
ClassGUID={36FC9E60-C465-11CF-8056-444553540000}

As described in Chapter 11, your driver will be loaded if it has the right Hardware ID. A Hardware ID is constructed using the vendor and product IDs in the device descriptor (e.g., USBVID_046A&PID_0001).

However, for USB keyboards, this approach does not work. Windows 98 and Windows 2000 have built in support for USB keyboards. In both cases, they load the Human Input Device (HID) class drivers. The standard keyboard driver then gets key input through HID client drivers.

I tried fiddling with the USB keyboard installation INF files for Windows 98 and Windows 2000. However, I could not persuade Windows to load UsbKbd in place of the standard drivers. I can only assume that the standard driver names are hard-coded into the kernel and that the Windows INF files are not really used.

My brutal solution to this problem was to replace the HID USB minidriver HidUsb.sys with the UsbKbd.sys driver executable. Windows uses HidUsb.sys to process HID USB devices. Replacing HidUsb.sys seems to work. Needless to say, this approach stops you from using the USB keyboard for normal typing. In addition, it stops you from using any other USB HID devices. Therefore, you will need to have a standard PCBIOS keyboard connected to the system, as well. Do not forget to save a copy of the HidUsb.sys file (or delete it and reinstall it from the Windows CD). You need a dual-boot PC if you are going to change HidUsb.sys in W2000.

If you do not have a HID USB keyboard at hand, you obviously cannot run these tests. However, I show some of the DebugPrint output later in this chapter, so you can see what is going on.

While developing the UsbKbd driver, I altered makefile.inc so that it copied the final executable, UsbKbd.sys, to overwrite HidUsb.sys. However, this command line has now been commented out, so you will have to do the copy yourself.

Trying out each new version of the UsbKbd driver was very easy. Simply unplugging and plugging in the USB cable caused the old driver to be unloaded and new one loaded. Windows 2000 displays a bugcheck on shutdown when HidUsb.sys is replaced by UsbKbd.sys. The simple solution is to unplug the USB keyboard before you shutdown.

Headers and Libraries

The USB header files that you might need to include are in the DDK.

usb100.h Various USB constants and structures
usbioctl.h IOCTL definitions
usbdlib.h URB building and assorted routines
usbdi.h USBDI routines, including URB structures

These header files generate two annoying compiler warnings which you can ignore. I also found that I needed to specifically mention the USB library in the SOURCES file.

TARGETLIBS=C:NTDDKLIBI386FREEUsbd.Lib

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


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