所有支持PnP的KMDF驱动不许有EvtDriverDeviceAdd回调函数。用于创建和初始化device对象和相关资源。
系统在发现驱动控制的一个设备时会调用它的EvtDriverDeviceAdd。
EvtDriverDeviceAdd创建了一个WDFDEVICE对象,用来表示设备和通过大量初始化任务让framework提供信息来创建它自己的内部结构。
EvtDriverDeviceAdd过程:
1.把消息填充到一个device initialization structure
2.创建device对象的context area
3.创建设备对象
4.启动tasks,例如创建I/O queue和device interface
bus driver启动的过程:参见chapter 6.3的Bus drivers
KMDF的device initialization structure
device object没有configuration structure,而是通过WDFDEVICE_INIT结构。
framework调用EvtDriverDeviceAdd,同时传一个指向WDFDEVICE_INT的指针,然后调用WdfDeviceInitXxx方法填充该结构。最后在创建WDFDEVICE对象时使用这些信息。
WdfDeviceInitXxx:
1.设置device characteristics
2.设置I/O类型
3.创建context area或给I/O请求设置其他的参数
4.注册PnP和power mgr回调函数
5.注册event回调函数(file create,close,cleanup)
对不同的对象还有其他不同的初始化任务。
KMDF FDO的初始化
WdfDeviceInitSetPowerPolicyEventCallbacks来注册关于idle in low-power state和wake signal的回调函数。
EvtDeviceFilterRemoveResourceRequirements和EvtDeviceFilterAddResourceRequirements callbacks增加移除来自于bus driver的resource requirements list资源。
用WdfFdoInitSetEventCallbacks来注册他们
EvtDeviceRemoveAddedResources?
其他WdfFdoInitXxx方法获得device属性、返回指向设备栈中的WDM PDO指针、提供注册表访问、及其他FDO任务
KMDF Filter DO的初始化
WdfFdoInitSetFilter来表示设备是一个filter,来使framework改变其对I/O request默认配置(不处理的请求自动传给下一个驱动)
可以像FDO一样调用WdfDeviceInitXxx方法
设备对象的context area
见第五章,nonpaged pool,driver-defined layout。。。
Osrusbfx2.h例子:
typedef struct _DEVICE_CONTEXT { WDFUSBDEVICE UsbDevice; WDFUSBINTERFACE UsbInterface; WDFUSBPIPE BulkReadPipe; WDFUSBPIPE BulkWritePipe; WDFUSBPIPE InterruptPipe; UCHAR CurrentSwitchState; WDFQUEUE InterrputMsgQueue; } DEVICE_CONTEXT, *PDEVICE_CONTEXT; WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_CONTEXT, GetDeviceContext)如图,
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME宏定义了type
所以当EvtDriverDeviceAdd回调被调用时,GetDeviceContext访问方法可以用DEVICE_CONTEXT来读写context area
要把设备对象关联到named context area上,driver必须在EvtDriverDeviceAdd中调用WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE来通过这些信息初始化attributes structure。
KMDF设备对象的创建
在driver调用WdfDeviceInitXxx来填充WDFDEVICE_INT结构后,它在attributes structure中设置参数。
参数包括context area的大小和类型,通常包含cleanup callback和同步范围。
driver把attributes structure和WDFDEVICE_INT传给WdfDeviceCreate来创建WDFDEVICE对象,增加到PnP设备栈中,返回handle
EvtDriverDeviceAdd的更多任务
1.若设备持有power policy时,需要设置deivce idle policy,wake配置
2.注册I/O回调,为设备对象创建I/O queue
3.按需要调用WdfDeviceCreateDeviceInterface创建device interface
4.若硬件支持中断,创建一个中断对象
5.创建WMI对象
在之后的启动设备过程中,在合适的时间初始化queue,连接interrupt对象。
KMDF的
EvtDriverDeviceAdd回调函数例子
Osrusbfx2的例子
NTSTATUS OsrFxEvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) { WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; WDF_OBJECT_ATTRIBUTES attributes; NTSTATUS status; WDFDEVICE device; WDF_DEVICE_PNP_CAPABILITIES pnpCaps; UNREFERENCED_PARAMETER(Driver); PAGED_CODE(); // Initialize the pnpPowerCallbacks structure. . . .// Code omitted. //[1] Register Plug and Play and power callbacks WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); //[2] Indicate what type of I/O this driver performs. WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered); //[3] Intialize the object attributes structure WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT); //[4] Call the framework to create the device object. status = WdfDeviceCreate(&DeviceInit, &attributes, &device); if (!NT_SUCCESS(status)) { return status; } // Set device PnP capabilities and configure and create I/O queues. . . .// Code omitted. //[5] Register a device interface. status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_OSRUSBFX2, NULL);// Reference String if (!NT_SUCCESS(status)) { return status; } return status; }