within a URB.
As mentioned before, the USB class drivers are layered internally. In this case, the diagram shows that the OpenHCI USB host controller driver is in use. The OpenHCI driver will make some use of its lower driver, the PCI bus driver. However, it will do most of its work by talking directly to the OpenHCI USB Controller hardware. It will read and write memory and controller registers. It will almost certainly handle interrupts and use DMA to transfer information.
The USB controller hardware itself is responsible for the very last stage of the keyboard I/O request handling. It generates the appropriate signals on the USB bus, according to the instructions given to it by the USB class drivers. The USB keyboard understands these signals and responds according to its specification.
When a key is pressed on the keyboard, information percolates its way back up through the chain of drivers, ending up at one of the client drivers as a keypress input report.
Figure 8.7 HID USB Keyboard I/O Request handling
Just to complicate matters, the previous example does not involve just one device stack. Instead, there are actually four, as shown in Table 8.3.
A device stack must always end at a Physical Device Object (PDO). Each bus driver creates a PDO for each device it finds.
1. Starting from the HID Keyboard driver's FDO, going down the stack, there is an FDO created by the HID class driver and a PDO created by the USB bus driver. These three device objects are in the first device stack.
2. The DDK documentation says that the USB class drivers are layered internally, with a hub driver at the top and a host controller driver at the bottom (OpenHCI, in this case).
3. The USB host controller was originally found by the PCI bus driver. Therefore, the host controller itself has an FDO that is layered on top of a PDO created by the PCI bus driver.
4. The PCI bus was originally found by the Windows root bus driver. The final device stack therefore consists of the PCI bus FDO layered on top of the root bus PDO.
This arrangement looks complicated. However, if you are trying to use only the USB class drivers, you do not really care how they process your requests. All the details of the other device stacks are hidden from you.
Table 8.3 USB Keyboard device stacks
Driver | Device stack |
---|---|
HID Keyboard driver | HID Keyboard device FDO |
HID class device FDO | |
PDO (created by USB hub bus driver) | |
USB Hub USB | Hub device FDO |
PDO (created by USB host controller bus driver) | |
USB Host controller | USB Host Controller device FDO |
PDO (created by PCI bus driver) | |
PCI Adapter | PCI device FDO |
PDO (created by root bus driver) |
This example shows how several standard Windows system drivers have been used in the device stack for a USB keyboard. Each driver writer usually needs to know only the specification of the next layer down[20]. The USB Keyboard driver writer needs to understand only the HID class driver specification. Knowledge of the different USB controllers and how to use them is definitely not required.
The
The example also shows that the upper edge presented by a driver does not determine its lower edge. The HID class drivers accept standard read and write IRPs. However, it implements these by sending Internal IOCTLs to its own minidriver. The USB minidriver implements its upper edge by sending URBs to the USB class drivers in its own Internal IOCTLs.
Thus, you have to look at some of the earlier example figures with care. Figure 8.5 shows function, filter, and bus drivers in a smooth hierarchy. In real life, the chain of events is much more complicated, as I/O requests are processed by several drivers.
A filter driver must have the same upper and lower edge because it must slip into the stack without affecting other drivers. A filter can modify or inspect the requests in which it is interested. However, all other requests must be passed down the stack unmodified. It is possible for a filter driver to perform some extra checking, which will mean that some IRPs are never passed down. However, it is vital that user mode applications or higher-level drivers can continue to function normally.
Conclusion
This chapter has presented the background for Plug and Play device drivers, the messages they handle, and how they fit into the WDM device stack. The next chapter looks at how to implement Plug and Play in practice and illustrates it in the Wdm2 device driver.
Chapter 9
Plug and Play Implementation
The last chapter went through the theory of Plug and Play (PnP) and the device stack. This chapter looks at how to implement Plug and Play in practice, with a discussion of the advanced topics of Plug and Play Notification and Bus drivers.
The Wdm2 example includes full PnP and Power Management facilities. Power Management is described in the next chapter.
The
Implementing Plug and Play