Lesson 5: Implementing Power Management for a Device Driver
As mentioned in Chapter 3, power management is important for Windows Embedded CE devices. The operating system includes a Power Manager (PM.dll), which is a kernel component that integrates with Device Manager to enable devices to manage their own power states and applications to set power requirements for certain devices. The primary purpose of Power Manager is to optimize power consumption and to provide an API to system components, drivers, and applications for power notifications and control. Although Power Manager does not impose strict requirements on power consumption or capabilities in any particular power state, it is beneficial to add power management features to a device driver so that you can manage the state of your hardware components in a way that is consistent with the power state of the target device. For more information about Power Manager, device and system power states, and power management features supported in Windows Embedded CE 6.0, read Chapter 3, 'Performing System Programming.'
After this lesson, you will be able to:
¦ Identify the power management interface for device drivers.
¦ Implement power management in a device driver.
Estimated lesson time: 30 minutes.
Power Manager Device Drivers Interface
Power Manager interacts with power management-enabled drivers through the XXX_PowerUp, XXX_PowerDown, and XXX_IOControl functions. For example, the device driver itself can request a change of the device power level from Power Manager by calling the DevicePowerNotify function. In response, Power Manager calls XXX_IOControl with an IO control code of IOCTL_POWER_SET passing in the requested device power state. It might seem overcomplicated for a device driver to change the power state of its own device through Power Manager, yet this procedure ensures a consistent behavior and positive end-user experience. If an application requested a specific power level for the device, Power Manager might not call the IOCTL_POWER_SET handler in response to DevicePowerNotify. Accordingly, device drivers should not assume that successful calls to DevicePowerNotify result in a call to the IOCTL_POWER_SET handler or that any calls to IOCTL_POWER_SET are the result of a DevicePowerNotify call. Power Manager can send notifications to a device driver in many situations, such as during a system power state transition. To receive power management notifications, device drivers must advertise that they are power management enabled, either statically through the IClass registry entry in the driver's registry subkey or dynamically by using the AdvertiseInterface function.
XXX_PowerUp and XXX_PowerDown
You can use the XXX_PowerUp and XXX_PowerDown stream interface functions to implement suspend and resume functionality. The kernel calls XXX_PowerDown right before powering down the CPU and XXX_PowerUp right after powering it up. It is important to note that the system operates in single-threaded mode during these stages with most system calls disabled. For this reason, Microsoft recommends using the XXX_IOControl function instead of XXX_PowerUp and XXX_PowerDown to implement power management features, including suspend and resume functionality.
If you implement suspend and resume functionality based on the XXX_PowerUp and XXX_PowerDown functions, avoid calling system APIs, particularly thread-blocking APIs, such as WaitForSingleObject. Blocking the active thread in single-threaded mode causes an unrecoverable system lockup.
IOControl
The best way to implement power manager in a stream driver is to add support for power management I/O control codes to the driver's IOControl function. When you notify Power Manager about your driver's power management capabilities through an IClass registry entry or the AdvertiseInterface function, your driver receives corresponding notification messages.
Table 6-8 lists the IOCTLs that Power Manager can send to a device driver to perform power management-related tasks.
Table 6-8 Power management IOCTLs
Function | Description |
---|---|
IOCTL_POWER_CAPABILITIES | Requests information on what power states the driver supports. Note that the driver can still be set to other power states (D0 through D4). |
IOCTL_POWER_GET | Requests the current power state of the driver. |
IOCTL_POWER_SET | Sets the power state of the driver. The driver maps the received power state number to actual settings and changes the device state. The new device driver power state should be returned to Power Manager in the output buffer. |
IOCTL_POWER_QUERY | Power Manger checks to see if the driver is able to change the state of the device. This function is deprecated. |