技术的乐趣在于分享,欢迎多多交流,多多沟通。
全部博文(877)
分类: Windows平台
2015-05-27 11:22:21
终于可以回家了,有一段时间没有回家了,挺想念家人的。好好的放松心情,好好的利用这段时间自己来休整一下。再出发。很多事情都可以再想一想。博客终于100了,呵呵。
Framework Objects
UMDF中一般会使用到如下的框架对象。
Driver Object IWDFDriver 驱动对象
Device Object IWDFDeivce 设备对象
File Object IWDFFile 文件对象
Interrupt Object IWDFInterrupt 中断对象
Queue Object IWDFIoQueue 队列对象
Request Object IWDFIoRequest 请求对象
Target Ojbect IWDFIoTarget 目标对象
USB device object IWDFUsbTargetDevice USB设备对象
USB pipe object IWDFUsbTargetPipe USB设备管道
USB interface object IWDFUsbInterface USB设备接口
Base object IWDFObject 代表通用的基本对象
Memory Object IWDFMemory 内存对象
在UMDF驱动对设备进行初始化之前,驱动管理器和反射器被操作系统装载,驱动主持进程被创建。为了保证设备启动成功,驱动管理器被装载并被完全初始化跟反射器初始化一起。
当设备被安装,PNP子系统装载反射器,如果装载还为完成,反射器联系驱动管理器创建驱动主持进程。在新创建的驱动主持进程内框架调用IDriverEntry::OnInitialize历程初始化UMDF驱动。
框架为每一个被驱动主持进程装载的设备创建一个设备对象。
Adding a Device Overview
Adding a Device
框架会为每一个驱动主持进程中的设备增加一个设备对象,框架调用驱动IDriverEntry::OnDeviceAdd例程,并传递IWDFDrvier和IWDFDevcieInitialize接口做为其参数。驱动必须在调用IWDFDriver::CreateDevice之前使用IWDFDeviceInitialize接口,下面是IWDFDeviceInitialize接口暴露的方法。
驱动调用IWDFDeviceInitialize::RetrieveDevicePropertyStore 得到IWDFNamedPropertyStore,得到或者设置设备相关的属性。
驱动调用IWDFDeviceInitialize::SetLockingConstraint方法指定框架如何调用其的回调函数。
驱动可以调用 IWDFDeviceInitialize::SetFilter 使能其设备为过滤设备。
当驱动初始化IWDFDeviceInitialize,对设备相关属性进行初始化后,可以调用IWDFDriver::CreateDevice创建UMDF的设备对象,当设备对象创建以后,驱动可以调用IWDFDevice::CreateIoQueue方法创建读写的IO队列。
PnP and Power Management Interfaces
当驱动创建框架设备对象,它可以注册一些PNP和电源的回调函数,当这些事件发生的时候,系统会调用这些回掉函数。
IPnpCallback
IPnpCallbackSelfManagedIo
IPnpCallbackHardware
IPowerPolicyCallbackWakeFromS0
IPowerPolicyCallbackWakeFromSx
Initializing UMDF Drivers
Power Policy Ownership in UMDF
对于每一个设备,必须有一个其设备驱动是其设备电源管理政策的拥有者。它必须为其设备选择合适的电源状态,在设备电源状态应该改变的时候,发送相关的请求给设备的驱动堆栈。
一般来说,但系统需要进入睡眠省电状态的时候,框架会要求你的设备总线驱动降低设备电源状态到D3(当然,你的设备也可以修改默认行为,如果你的设备支持唤醒的能力,你可以让框架可以设置你的设备睡眠状态为D1或D2,)当系统回到S0状态,框架请求总线驱动去恢复你的设备到D0状态。
设备电源管理政策的拥有者也必须对设备如下相关的功能进行使能和关闭。
系统在S0,设备在空闲情况下的进入低电源状态的能力。
当额外的事件发生,设备在睡眠状态下唤醒自身的能力。
当额外的事件发生,设备唤醒整个在睡眠中的系统的能力。
如果你的设备支持这些空闲睡眠和唤醒设备或系统的能力,你可以通过IPowerPolicyCallbackWakeFromS0或IPowerPolicyCallbackWakeFromSx接口来设置相关的事件回调函数。
一般来说,基于UMDF的驱动不是设备电源管理政策的管理者。设备内核模式的功能驱动默认是设备电源管理政策的拥有者。(如果没有内核模式功能驱动,而且总线驱动已经调用WdfPdoInitAssignRawDevice,总线驱动就是设备电源管理政策的拥有者)。如果你的UMDF驱动想成为设备电源管理政策的拥有者,驱动必须调用IWDFDeviceInitialize::SetPowerPolicyOwnership,而且内核模式默认的电源管理政策拥有者必须调用WdfDeviceInitSetPowerPolicyOwnership去关闭拥有者功能。
如果,你是为USB设备提供UMDF驱动,你想使你的设备驱动成为电源管理政策的拥有者,你必须在你的驱动INF文件中AddReg节增加如下的注册表键值。并且AddReg节必须在INF DDIInstall.HW下面。
[MyDriver_Install.NT.hw]
AddReg=MyDriver_AddReg
[MyDriver_AddReg]
HKR,,"WinUsbPowerPolicyOwnershipDisabled",0x00010001,1
框架会为设备电源管理政策的拥有者做如下的工作。
框架处理所有在你的驱动和其余驱动堆栈中有关电源政策相关的联系。你的驱动不需要请求总线驱动改变设备电源状态,因为框架会发出这些请求。
如果你的驱动注册了一些电源管理相关的事件回调函数,框架会在合适的时候调用它们完成设备睡眠或者唤醒系统的功能。
如果你的驱动允许用户改变相关的空闲和唤醒设定,框架提供用户接口界面在设备管理器显示的属性页面。
Supporting Idle Power-Down in UMDF Drivers
1,调用IWDFDevice2::AssignS0IdleSettings or IWDFDevice3::AssignS0IdleSettingsEx 指定:
设备将要进入的电源状态。
设备要保持多少时间的空闲状态,设备才可以进入低电源状态。
是否设备可以在总线上发现额外的事件和触发唤醒信号。
用户是否可以控制设备的空闲相关的设置。
在空闲一段时间后,是否框架可以把设备放在D3 code状态。
如果你的驱动使用UMDF1.11以后的驱动框架,你可以调用IWDFDevice3::AssignS0IdleSettingsEx 代替 IWDFDevice2::AssignS0IdleSettings。除了上面说到的,IWDFDevice3::AssignS0IdleSettingsEx 允许驱动去指定:
设备空闲休眠功能使能还是关闭。
当系统返回到S0的状态下,设备是否回到D0状态。
2,实现相关IPowerPolicyCallbackWakeFromS0接口的回调函数.
IPowerPolicyCallbackWakeFromS0::OnArmWakeFromS0,使能设备硬件(不是总线设备)去响应额外唤醒事件的发生.
IPowerPolicyCallbackWakeFromS0::OnDisarmWakeFromS0,关闭设备响应额外唤醒事件的能力.
IPowerPolicyCallbackWakeFromS0::OnWakeFromS0Triggered,通知驱动,总线发现了唤醒信号.
当所有的如下条件都吻合,框架开始计算设备的空闲时间:
在设备实例的电源管理队列中,没有任何等待或派遣到驱动的请求.如果请求已经被分发到驱动,并被驱动发送到IO目标对象,还没有结束,在这种情况下也不用考虑设备空闲。不在电源管理队列中的请求,对于设备空闲不用考虑。
如果驱动预前调用IWDFDevice::StopIdle,驱动调用IWDFDevice2::ResumeIdle.
如果设备电源管理政策的拥有者是设备总线驱动,总线设备的子设备都不在D0状态下。
如果你的驱动使能你的设备空闲睡眠的能力,你可能不得不使用IWDFDevice2::StopIdle.如果设备在D0状态下,这个方法可以避免设备空转直到驱动调用IWDFDevice2::ResumeIdle.在设备在低电源状态,调用IWDFDevice2::StopIdle,如果系统在S0状态下,框架请求总线驱动重新把设备设置为D0状态。
如果设备可以在低电源状态下唤醒自身,设备总线驱动参与唤醒设备。内核模式下的总线驱动做什么总线适配器必须的事情和使能或者关闭设备在低电源状态下唤醒能力
Supporting System Wake-Up in UMDF Drivers
当系统在低电源状态下,有些设备可以发现额外的事件,比如过来的网络包,然后唤醒系统。举例来说,如果PCI设备有唤醒系统的能力,在设备的电源管理寄存器中指定,它唤醒系统通过在PCI总线上发出电源管理事件信号(PME).
如果你的设备可以在低功耗的模式下唤醒系统,必须在IDriverEntry::OnDeviceAdd回调函数中执行如下两步:
1,调用IWDFDevice2::AssignSxWakeSetting指定:
设备将进入的低电源状态。
是否可以控制设备的空闲设定。
设备的唤醒能力是使能还是关闭。
2,实现相关IPowerPolicyCallbackWakeFromSx接口的回调函数.
IPowerPolicyCallbackWakeFromS0::OnArmWakeFromSx,使能设备硬件(不是总线设备)去响应额外唤醒事件的发生.
IPowerPolicyCallbackWakeFromS0::OnDisarmWakeFromSx,关闭设备响应额外唤醒事件的能力.
IPowerPolicyCallbackWakeFromS0::OnWakeFromSxTriggered,通知驱动,总线发现了唤醒信号.
User Control of Device Idle and Wake Behavior in UMDF
如果你的设备有空闲睡眠或者唤醒的能力,你可以决定是否让用户来控制这些功能的使能和关闭。
你的UMDF驱动可以使用IWDFDevice2::AssignSOIdleSettings方法来指定用户是否可以通过注册表相关选项来使能或者关闭设备空闲睡眠能力。
你的UMDF驱动可以使用IWDFDevice2::AssignSxWakeSettings方法来指定用户是否可以通过注册表相关选项来使能或者关闭设备唤醒能力。
当驱动调用AssignS0IdleSettings 方法时,它可以给用户控制设备空闲的能力,通过设置UserControlOfIdleSettings为IdleAllowUserControl,设置Enabled参数为WdfTrue或WdfUseDefault.
当驱动调用AssignSxWakeSettings 方法时,它可以给用户控制设备唤醒的能力,通过设置UserControlOfWakeSettings为WakeAllowUserControl,设置Enabled参数为WdfTrue或WdfUseDefault.
如果你的驱动允许用户来改变空闲休眠和唤醒的能力,框架会在设备管理的属性页面给出选项给用户选择,使能和关闭这些设备能力。(框架会通过用户的选择来修改IdleWakeingState和WakeFromSleepState注册表项,驱动以及其安装文件禁止读或修改这些注册表值)。
如果用户修改了这些设备相关的设定,框架会更新设备电源状态配合新的设定。比如,但用户关闭空闲睡眠功能的时候,设备已经因为空闲睡眠进入低电源状态,框架让设备进入工作状态。
你的驱动可以指定这些默认值为使能或者关闭状态。
如果你使用的UMDF版本为1.9以后的,框架会提供两个在设备的硬件子键\WDF下为驱动定义的两个注册表值WdfDefaultIdleInWorkingState 和WdfDefaultWakeFromSleepState,来使能或者关闭其功能的默认值。这些值是RDG_DWORD的,0代表关闭,1代表使能。
框架检查WdfDefaultIdleInWorkingState 这个主持表项的前提是,当驱动调用AssignS0IdleSettings 方法时,设置UserControlOfIdleSettings为IdleAllowUserControl,设置Enabled参数为WdfTrue或WdfUseDefault.
框架检查WdfDefaultWakeFromSleepState 这个主持表项的前提是, 当驱动调用AssignSxWakeSettings 方法时,设置UserControlOfWakeSettings为WakeAllowUserControl,设置Enabled参数为WdfTrue或WdfUseDefault.
A User Plugs in a Device
A User Unplugs a Device
A Device Enters a Low-Power State
当如下事件发生,设备离开其工作状态D0,进入低电源状态。
当系统还在S0工作状态,设备空闲,进入低电源状态,设备离开工作状态D0.
系统的电源状态从S0进入低电源状态(驱动可以调用IWDFDevice2::GetSystemPowerAction探测系统电源状态变化的原因)
对于每一个设备支持的基于UMDF的功能和过滤驱动,框架按如下的顺序,从驱动堆栈的最上层驱动来调用相关的例程。
1,如果驱动使用的自己管理的IO,框架调用IPnpCallbackSelfManagedIo::OnSelfManagedIoSuspend 回调函数。
2,框架停止所有的设备电源管理队列,调用IPnpCallbackSelfManagedIo::OnSelfManagedIoStop 回调函数。
3,如果驱动是设备电源政策的拥有者,调用IPowerPolicyCallbackWakeFromS0::OnArmWakeFromS0 或IPowerPolicyCallbackWakeFromSx::OnArmWakeFromSx 回调函数。
4,框架调用驱动的IPnpCallback::OnD0Exit 回调函数。
A Device Returns to Its Working State
如下的条件其中之一满足,设备从低电源状态返回到工作状态。
设备发现一个额外事件,触发总线上的唤醒信号。内核模式总线驱动发现了唤醒信号。
设备已经处于空闲状态,驱动调用IWDFDevice2::StopIdle.
系统的电源状态从低电源状态改变到S0状态。
对于设备支持的基于UMDF的功能驱动和过滤驱动,框架按照如下的顺序,从驱动堆栈的最低层开始调用驱动的相关例程。
1,框架调用驱动的IPnpCallback::OnD0Entry回调函数。
2,如果驱动是设备电源管理政策的拥有者,框架调用IPowerPolicyCallbackWakeFromS0::OnDisarmWakeFromS0 或 IPowerPolicyCallbackWakeFromSx::OnDisarmWakeFromSx 回调函数。
3,框架重启所有的设备电源管理IO队列,然后调用IQueueCallbackIoResume::OnIoResume 回调函数。
4,如果驱动使用自管理IO,框架调用IPnpCallbackSelfManagedIo::OnSelfManagedIoRestart 回调函数。
The PnP Manager Redistributes System Resources
如果用户增加一个设备到系统中,设备需要的系统资源已经被PNP管理器分发给另外的设备,PNP管理器尝试重新分配资源。
在这个处理中,PNP管理器停止设备,将设备带离D0状态。然后分发新的资源给设备,以至于设备可以重启,使用新的资源。
当重新分配资源的时候,如果基于UMDF的驱动提供了IPnpCallback::OnQueryStop回调函数,并已经否决了重新分配资源的时候,PNP不会选择设备资源的重新分配。
Power-Down Sequence
框架按照如下的顺序从驱动堆栈的最上层的驱动,开始关闭设备电源的操作。
1,如果驱动使用自管理的IO,框架调用驱动的IPnpCallbackSelfManagedIo::OnSelfManagedIoSuspend 回调函数。
2,框架停止所有的设备电源管理IO队列。
3,框架调用驱动的IPnpCallback::OnD0Exit回调函数。
4,框架调用驱动的IPnpCallbackHardware::OnReleaseHardware 回调函数,传递一个关联已经被PNP管理器分配给设备的资源列表。
Power-Up Sequence
框架按照如下的顺序从驱动堆栈的最底层的驱动,开始开启设备电源的操作。
1,框架调用驱动的 IPnpCallbackHardware::OnPrepareHardware 回调函数,并传递一个PNP分配给设备的硬件资源列表。
2,框架调用驱动的 IPnpCallback::OnD0Entry 回调函数。
3,框架重启所有的设备电源管理IO队列。
4,如果驱动使用自管理IO,框架调用IPnpCallbackSelfManagedIo::OnSelfManagedIoRestart 回调函数。
I/O Request Processing Operation Flow
Operation Flow with Single Device Stack
UMDF驱动只能在需要更多信息和读请求想关联的文件时,才可以调用IWDFIoRequest::GetCreateParameters方法.如果需要更多关于读请求的信息,UMDF驱动可以调用IWDFIoRequest::GetReadParameters 。
如果对于读操作的请求,如果不需要知道传送了多少个字节的时候,最好调用IWDFIoRequest::Complete 而不用调用IWDFIoRequest::CompleteWithInformation。UMDF驱动调用Complete or CompleteWithInformation,发出信号,只是读请求操作已经完成,
应用程序可以访问读到的数据。
Operation Flow with Double Device Stack
UMDF过滤和功能驱动如果需要更多和读请求相关连的文件信息的时候,可以调用IWDFIoRequest::GetCreateParameters ,如果需要知道更多读请求的信息,可以调用IWDFIoRequest::GetReadParameters 。
UMDF功能驱动调用IWDFIoRequest::Complete or IWDFIoRequest::CompleteWithInformation,通知过滤驱动,读操作已经完成,UMDF过滤驱动如果需要更多的信息关于读请求的完成,可以调用IWDFIoRequestCompletionParams。
UMDF过滤驱动调用Complete or CompleteWithInformation,声明读操作已经完成,应用程序可以访问读到的数据。
Sending I/O Requests to Lower Drivers
当驱动接收到一个IO请求,而自己不能处理的时候,它需要转发接收到的请求到设备堆栈的下层驱动。驱动可以调用IWDFIoRequest::Send方法转发请求。如果需要同步转发,可以设置Flags参数为WDF_REQUEST_SEND_OPTION_SYNCHRONOUS 。否则,驱动转发请求按照异步的方式。它应该注册一个完成例程。
Obtaining Parameters for I/O Requests
当驱动接收到一个IO请求,驱动可以使用IWDFIoRequest接口的函数来得到请求相关的参数.
IWDFIoRequest::GetCreateParameters or IWDFIoRequest2::GetCreateParametersEx
IWDFIoRequest::GetDeviceIoControlParameters
IWDFIoRequest::GetReadParameters
IWDFIoRequest::GetWriteParameters