您的位置:首页 > 其它

第三篇.WDF驱动之Helloworld

2014-11-24 10:54 183 查看
  借助Microsoft提供的kmdf框架,来理解一下驱动的一般流程.

驱动的开发流程

 

1 驱动程序入口函数

DriverEntry 
驱动程序的入口函数。   类似于 main函数

程序的标准入口函数是DriverEntry

与WDM不同,WDF的DriverEntry只负责创建和初始化WDFDRIVER对象,告诉WDF框架处理添加新设备连接的回调函数。

NTSTATUS  DriverEntry(PDRIVER-OBJECT DriverObj,PUNICODE-STRING  RegistryPath)

{

NTSTATUSstatus;

WDF-DRIVER-CONFIGconfig;

WDFDRIVER hDriver;

//初始化驱动配置结构,指定设备添加事件callback

WDF-DRIVER-CONFIG-INIT-NO-CONSTRAINTS(&config,MyEvtDeviceAdd);

//创建WDFDRIVER对象

status=WdfDriverCreate(DriverObj, RegistryPath,WDF-NO-OBJECT-ATTRIBUTES,

&config,//指向config结构的指针

NULL

);

return(status);

}

每当有新设备连接到系统时,WDF框架自动调用

EvtDeviceAdd设备添加callback。该回调函数初始化PNP和电源管理相关结构,设置相应的事件处理callbacks,然后创建WDFDEVICE对象和符号连接,初始化请求队列、中断处理等相关结构,设置相应的回调函数。

WDFSTATUSMyEvtDeviceAdd(WDFDRIVER Driver,PWDFDEVICE-INITDeviceInit)

{

WDFSTATUSstatus=STATUS-SUCCESS;

WDF-PNPPOWER-EVENT-CALLBACKS   pnpPowerCallbacks;

WDF-OBJECT-ATTRIBUTES   objAttributes;

WDFDEVICEdevice;

PMY-DEVICE-CONTEXTdevContext;

WDF-IO-QUEUE-CONFIGioCallbacks;

WDF-INTERRUPT-CONFIG    interruptConfig;

//初始化PnPPowerCallbacks,设置与PnP和电源管理相关

的事件回调函数

WDF-PNPPOWER-EVENT-CALLBACKS-INIT(&pnpPowerCallbacks);

pnpPowerCallbacks.EvtDevicePrepareHardware=MyEvtPrepareHardware;

pnpPowerCallbacks.EvtDeviceReleaseHardware=MyEvtReleaseHardware;

pnpPowerCallbacks.EvtDeviceD0Entry=MyEvtDeviceD0Entry;

pnpPowerCallbacks.EvtDeviceD0Exit=MyEvtDeviceD0Exit;

WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit,pnpPowerCallbacks);

//创建设备对象,初始化相关的属性

WDF-OBJECT-ATTRIBUTES-INIT(&objAttributes);

WDF-OBJECT-ATTRIBUTES-SET-CONTEXT-TYPE(&objAttributes,MY-DEVICE-CONTEXT);

//命名设备

status=WdfDeviceInitUpdateName(DeviceInit,L“\\de2vice\\WDFDEMO”)

;if(!NT-SUCCESS(status))return(status);

status=WdfDeviceCreate(&DeviceInit,&objAttributes,&device);

if(!NT-SUCCESS(status))return(status);

devContext=MyGetContextFromDevice(device);

 devContext->WdfDevice=device;

//创建符号连接

status=WdfDeviceCreateSymbolicLink(device,L“\\Dos2Devices\\WDFDEMO”);

if(!NT-SUCCESS(status))

return(status);//创建和初始化请求队列

WDF-IO-QUEUE-CONFIG-INIT(&ioCallbacks,WdfIo2QueueDispatchSerial,WDF-NO-EVENT-CALLBACK,WDF-NO-EVENT-CALLBACK);

ioCallbacks.EvtIoDeviceControl=MyEvtDeviceControlIoctl;

status=WdfDeviceCreateDefaultQueue(device,&ioCallbacks,WDF-NO-OBJECT-ATTRIBUTES,NULL);

if(!NT-SUCCESS(status))return(status);

//创建和初始化中断对象,MyIsr和MyDpc分别是中断服务例程和DPC例程

WDF-INTERRUPT-CONFIG-INIT(&interruptConfig,FALSE,MyIsr,MyDpc);

interruptConfig.EvtInterruptEnable=MyEvtInterruptEnable;//中断使能

interruptConfig.EvtInterruptDisable=MyEvtInterruptDisable;//中断禁止

status=WdfInterruptCreate(device,&interruptConfig,&objAttributes,&devContext->WdfInterrupt);

//一些其他初始化操作(略)

return(status);}

开发WDF驱动程序下一步的工作就是编写各事件处理回调函数,当相应事件发生时,WDF框架会自动调用指定的回调函数进行处理。其中EvtDevicePrepareHardware回调函数在分配资源的时候被调用,框架将分配给设备的资源传递给回调函数,回调函数保存需要的资源,将共享内存映射到内核虚拟地址空间。与此对应的是EvtDeviceReleaseHardware回调函数,每当设备释放所占用的资源时,框架都将调用它。

EvtDeviceD0Entry和EvtDeviceD0Exit事件callbacks则分别在设备即将进入和离开D0电源状态时调用。EvtIoDeviceControl,EvtIoRead,EvtIoWrite等回调函数分别用来处理DeviceControl,Read,WriteI/O请求。当框架获得一个I/O请求时,它首先确定该请求应该放入哪个请求队列。如果驱动程序没有提供指定的队列,WDF框架默认将请求放入缺省请求队列会自动调用对应的回调函数。然后,框架寻找处理该请求的回调函数,如果驱动程序提供了相应的callback,则调用它处理请求。对于没有指定回调函数的I/O请求,WDF调用EvtIoStart回调函数处理。如果EvtIoStartcallback也不存在,框架将返回STATUS-NOT-SUPPORTED。

设备中断的管理由EvtInterruptEnablecallback、EvtInterruptDisablecallback、中断服务例程(ISR)和DpcForISr例程实现。WDF框架在调用EvtDeviceD0Entrycallback和注册ISR后,通过调用EvtInterruptEnable回调函数使能设备中断;而EvtInterruptDisable回调函数则在设备离开D0状态,EvtDeviceD0Exitcallback调用前获得调用,完成禁止设备中断的工作。此外,中断服务例程和DpcForIsr例程具体完成中断服务的功能,与WDM驱动程序相似。

 

2 创建驱动对象

WdfDriverCreate根据给定的属性配置创建driver对象.特别注意的是  这里设置了SampleDriverEvtDeviceAdd函数,也就是创建driver时,会调用的
用于添加设备对象的方法。

 

3 创建设备对象

SampleDriverEvtDeviceAdd //这个是wdfDriverCreate时自己指定的

在 SampleDriverEvtDeviceAdd函数中通过调用WdfDeviceCreate函数,根据配置的属性创建对应的设备

 

4 创建设备接口

WdfDeviceCreateDeviceInterface创建一个唯一的接口(UUID)用于应用层程序通信,调用驱动层接口。
 

5 创建驱动处理队列

SampleDriverQueueInitialize
The I/O dispatchcallbacks for the frameworks device object
     are configured in this function.
     A single default I/O Queue is configuredfor parallel request
     processing, and a driver context memoryallocation is created
     to hold our structureQUEUE_CONTEXT.
 
       WdfIoQueueCreate创建一个事件队列用于处理驱动 I/O事件。需要注意的是,创建时

可以通过配置回调函数,来处理自己关心的那些事件。另外注意配置队列的分发方式:WdfIoQueueDispatchParallel

 

6 处理驱动的事件

SampleDriverEvtIoDeviceControl函数是在配置队列时设置的 用于处理IO控制的回调函数。大部分设备接口都是在这个函数中完成的。
 

7 驱动的卸载回调

驱动的卸载时调用的函数是  在driver创建时设置的,如果没有需要 可以不设置的。
attributes.EvtCleanupCallback。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息