After the driver creates the device object,
it sets additional power policy options related to idling and wake
signals before its EvtDriverDeviceAdd callback returns.
The idle settings include the following:
Idle time-outs, so that KMDF can transition the device out of the working state when it is not being used.
The power state in which to idle the device.
A Boolean that indicates whether a user can change the idle settings.
The WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT
function initializes the structure that holds the idle settings. The
driver passes a pointer to the structure and an enumerator that
describes whether the device can generate a wake signal when the system
is in SO (the fully powered, operational state). The IdleCannotWakeFromSO enumerator indicates that the device and driver do not support wake-up for SO. IdleCanWakeFromSO indicates that the device and driver support wake-up from SO. USB drivers that support Selective Suspend specify IdleUsbSelectiveSuspend.
The driver also sets a 60-second idle time-out,
which indicates that the framework will attempt to put the device in a
low-power state when it has been idle for more than 60 seconds.
By default, KMDF puts the driver in state D3 when idle and enables the user to control the idle settings. A driver can change these defaults by setting values for the DxState field and the UserControlOfIdleSettings field in the WDF_DEVICE_POWER_POWER_IDLE_SETTINGS structure.
To register these settings, the driver then calls the WdfDEviceAssignSOIdleSettings method on the WDFDEVICE object.
Next, the driver sets the wake-up policy. To initialize the policy settings to default values, the driver uses the WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_INIT function. The defaults provide for the following:
The device can wake up the system, but a
user can override this default through a property page in Control
Panel. This setting is appropriate for drivers that use the framework’s
WMI support to provide a property page through which a user can select
the devices that are enabled to wake up the system.
The device is put in its lowest powered state (D3) when the system goes into a sleep state.
A call to WdfDeviceAssignSxWakeSettings registers these settings.
1. Code to Set Power Policy
The following code shows how the Featured Toaster sets these power policy settings. This code is excerpted from the ToasterEvtDeviceAdd function in the file toaster.c.
//
// Set the idle power policy to put the device in Dx if the
// device
// is not used for the specified IdleTimeout time. Since
// this is a
// virtual device, we tell the framework that we cannot wake it
// if we sleep in SO. The only way to bring the device to DO is
// if the device receives an I/O request from the system.
//
WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings,
IdleCannotWakeFromSO);
idleSettings.IdleTimeout = 60000; // 60 secs idle timeout
status = WdfDeviceAssignSOIdleSettings(device, &idleSettings);
if(!NT_SUCCESS(status)) {
KdPrint(("WdfDEviceAssignSOIdleSettings failed 0x%x\n",
status));
return status;
}
//
// Set the wait-wake policy.
//
WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_INIT(
&wakeSettings);
status = WdfDeviceAssignSxWakeSettings(device, &wakeSettings);
if(!NT_SUCCESS(status)) {
//
// We are probably enumerated on a bus that doesn't support
// Sx-wake. Do not fail the device add just because we can't
// support wait-wake.
//
KdPrint(("WdfDEviceAssignSxWakeSettings failed 0x%x\n",
status));
status = STATUS_SUCCESS;
}
The sample driver sets power policy idle characteristics and an idle timeout in the idleSetting structure, and then calls WdfDEviceAssignSOIdleSettings
method, passing as parameters this structure and the handle to the
device object that is received when it created the device object. It
then proceeds in a similar fashion to set the wake-up characteristics.
If the call to WdfDeviceAssignScWakeSettings fails, the sample driver resets the failure status to STATUS_SUCCESS. The reason is that this method fails if the underlying bus does not support wake from Sx
states. If the device is on such a bus, the driver should not fail the
add-device request. Instead, it simply resets the failure status and
continues processing.