The Windows Driver Model has two separate but equally important aspects. First, the core model describes the standard structure for device drivers. Second, Microsoft provides a series of bus and class drivers for common types of devices.
The core WDM model describes how device drivers are installed and started, and how they should service user requests and interact with hardware. A WDM device driver must fit into the Plug and Play (PnP) system that lets users plug in devices that can be configured in software.
Microsoft provides a series of system drivers that have all the basic functionality needed to service many standard types of device. The first type of system driver supports different types of bus, such as the Universal Serial Bus (USB), IEEE 1394 (FireWire) and Audio port devices. Other class drivers implement standard Windows facilities such as Human Input Devices (HID) and kernel streaming. Finally, the Still Image Architecture (STI) provides a framework for handling still images, scanners, etc.
These system class drivers can make it significantly easier to write some types of device driver. For example, the USB system drivers handle all the low-level communications across this bus. A well defined interface is made available to other drivers. This makes it fairly straightforward to issue requests to the USB bus.
Dispatch Routine Power Handling
Dispatch Routine Power Handling
Each Wdm2 I/O request dispatch routine must check that the Wdm2 device is powered up. Listing 10.8 shows how Wdm2Write calls PowerUpDevice to power the device up if necessary by calling SendDeviceSetPower. Finally, PowerUpDevice resets the idle counter using PoSetDeviceBusy.
Listing 10.8 Dispatch routine power handling
NTSTATUS Wdm2Write(IN PDEVICE_OBJECT fdo, IN PIRP Irp) {
// …
NTSTATUS status = PowerUpDevice(fdo);
if (!NT_SUCCESS(status)) return CompleteIrp(Irp, status, 0);
// …
}
NTSTATUS PowerUpDevice(IN PDEVICE_OBJECT fdo) {
PWDM2_DEVICE_EXTENSION dx = (PWDH2_DEVICE_EXTENSION)fdo->DeviceExtension;
// If need be, increase power
if (dx->PowerState>PowerDeviceD0) {
NTSTATUS status = SendDeviceSetPower(dx, PowerDeviceD0);
if (!NT_SUCCESS(status)) return status;
}
// Zero our idle counter
if (dx->PowerIdleCounter) PoSetDeviceBusy(dx->PowerIdleCounter);
return STATUS_SUCCESS;
}