加班,还是悠着点吧,毕竟,多加班没好处!
今天,介绍下,关于PNP的操作,也就是即插即用。我们知道Windows支持PNP,但是,设备首先要声明,设备本身是支持的。
上一章,我们讲了很多关于WdfDeviceInitXXXXXX的函数。那些都是在创建设备对象之前,调用的。设置属性,以参数的形式传给创建设备对象的函数。
而我们的PNP的操作都是在设备对象创建后,声明的。这也合乎情理。还没有设备,怎么说支持。
这边,我先把这些函数列举一下,在重点介绍下PNP的操作。
VOID WdfDeviceSetAlignmentRequirement(
IN WDFDEVICE Device,
IN ULONG AlignmentRequirement
);
VOID WdfDeviceSetBusInformationForChildren(
IN WDFDEVICE Device,
IN PPNP_BUS_INFORMATION BusInformation
);
VOID WdfDeviceSetCharacteristics(
IN WDFDEVICE Device,
IN ULONG DeviceCharacteristics
);
VOID WdfDeviceSetDeviceInterfaceState(
IN WDFDEVICE Device,
IN CONST GUID* InterfaceClassGUID,
IN OPTIONAL PCUNICODE_STRING ReferenceString,
IN BOOLEAN IsInterfaceEnabled
);
VOID WdfDeviceSetDeviceState(
IN WDFDEVICE Device,
IN PWDF_DEVICE_STATE DeviceState
);
VOID WdfDeviceSetFailed(
IN WDFDEVICE Device,
IN WDF_DEVICE_FAILED_ACTION FailedAction
);
VOID WdfDeviceSetSpecialFileSupport(
IN WDFDEVICE Device,
IN WDF_SPECIAL_FILE_TYPE FileType,
IN BOOLEAN FileTypeIsSupported
);
VOID WdfDeviceSetStaticStopRemove(
IN WDFDEVICE Device,
IN BOOLEAN Stoppable
);
NTSTATUS WdfDeviceStopIdle(
IN WDFDEVICE Device,
IN BOOLEAN WaitForD0
);
NTSTATUS WdfDeviceWdmDispatchPreprocessedIrp(
WDFDEVICE Device,
PIRP Irp
);
PDEVICE_OBJECT WdfDeviceWdmGetAttachedDevice(
IN WDFDEVICE Device
);
PDEVICE_OBJECT WdfDeviceWdmGetDeviceObject(
IN WDFDEVICE hDevice
);
PDEVICE_OBJECT WdfDeviceWdmGetPhysicalDevice(
IN WDFDEVICE Device
);
这里重点介绍如下两个函数:
VOID WdfDeviceSetPnpCapabilities(
IN WDFDEVICE Device,
IN PWDF_DEVICE_PNP_CAPABILITIES PnpCapabilities
);
设置设备的PNP属性:我们来看WDF_DEVICE_PNP_CAPABILITIES:
typedef struct _WDF_DEVICE_PNP_CAPABILITIES {
ULONG Size;
WDF_TRI_STATE LockSupported;
WDF_TRI_STATE EjectSupported;
WDF_TRI_STATE Removable;
WDF_TRI_STATE DockDevice;
WDF_TRI_STATE UniqueID;
WDF_TRI_STATE SilentInstall;
WDF_TRI_STATE SurpriseRemovalOK;
WDF_TRI_STATE HardwareDisabled;
WDF_TRI_STATE NoDisplayInUI;
ULONG Address;
ULONG UINumber;
} WDF_DEVICE_PNP_CAPABILITIES, *PWDF_DEVICE_PNP_CAPABILITIES;
typedef enum _WDF_TRI_STATE {
WdfUseDefault,
WdfFalse,
WdfTrue
} WDF_TRI_STATE, *PWDF_TRI_STATE;
需要用宏来初始化:
WDF_DEVICE_PNP_CAPABILITIES pnpCaps;
WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);
pnpCaps.SurpriseRemovalOK = WdfTrue;
WdfDeviceSetPnpCapabilities(
device,
&pnpCaps
);
相信做个WDM驱动,就应该知道这些属性代表什么,MSDN中有详细的说明。这里不解释了。
还有一个函数:设置电源状态的WdfDeviceSetPowerCapabilities‘
VOID WdfDeviceSetPowerCapabilities(
IN WDFDEVICE Device,
IN PWDF_DEVICE_POWER_CAPABILITIES PowerCapabilities
);
再看下电源能力的结构体:
typedef struct _WDF_DEVICE_POWER_CAPABILITIES {
ULONG Size;
WDF_TRI_STATE DeviceD1;
WDF_TRI_STATE DeviceD2;
WDF_TRI_STATE WakeFromD0;
WDF_TRI_STATE WakeFromD1;
WDF_TRI_STATE WakeFromD2;
WDF_TRI_STATE WakeFromD3;
DEVICE_POWER_STATE DeviceState[PowerSystemMaximum];
DEVICE_POWER_STATE DeviceWake;
SYSTEM_POWER_STATE SystemWake;
ULONG D1Latency;
ULONG D2Latency;
ULONG D3Latency;
DEVICE_POWER_STATE IdealDxStateForSx;
} WDF_DEVICE_POWER_CAPABILITIES, *PWDF_DEVICE_POWER_CAPABILITIES;
typedef enum _DEVICE_POWER_STATE {
PowerDeviceUnspecified = 0,
PowerDeviceD0,
PowerDeviceD1,
PowerDeviceD2,
PowerDeviceD3,
PowerDeviceMaximum
} DEVICE_POWER_STATE, *PDEVICE_POWER_STATE;
typedef enum _DEVICE_POWER_STATE {
PowerDeviceUnspecified = 0,
PowerDeviceD0,
PowerDeviceD1,
PowerDeviceD2,
PowerDeviceD3,
PowerDeviceMaximum
} DEVICE_POWER_STATE, *PDEVICE_POWER_STATE;
我们来看用宏来初始化代码:
WDF_DEVICE_POWER_CAPABILITIES powerCaps;
WDF_DEVICE_POWER_CAPABILITIES_INIT(&powerCaps);
powerCaps.DeviceD1 = WdfTrue;
powerCaps.WakeFromD1 = WdfTrue;
powerCaps.DeviceWake = PowerDeviceD1;
powerCaps.DeviceState[PowerSystemWorking] = PowerDeviceD1;
powerCaps.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
powerCaps.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
powerCaps.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
powerCaps.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
powerCaps.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
WdfDeviceSetPowerCapabilities(
device,
&powerCaps
);