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

Functional and Physical Device Objects

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)
Upper Edge Definitions

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 upper edge of a driver is the specification of how to use it. The upper edge of the HID class driver responds to standard read and write IRPs. However, the upper edge of the USB class drivers only responds to Internal IOCTL IRPs. This is a sensible option for the USB class drivers, as it is not appropriate for user mode drivers to call them directly. User mode programs could not adhere to the timing requirements of the USB class drivers.

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 Wdm1Test user mode application tests some of the Wdm2 PnP functionality. The Wdm1Notify Win32 program displays PnP Notification device change events for the Wdm2 device interface.

Implementing Plug and Play

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату
×