4.7 电源管理 第三部分 ---- Windows CE设备驱动开发之电源管理

2019-07-13 22:23发布

Windows CE设备驱动开发之电源管理 第三部分  4.7.3、电源管理器接口 电源管理器有三种不同的使用者。 l         电源管理器能识别的设备的驱动程序。 l         可能需要更改系统电源状态或设备性能的应用程序。 l         需要电源事件通知的应用程序。 电源管理器使用不同的编程接口与这些使用者进行通讯。 4.7.3.1              设备驱动接口 电源管理器使用两种不同的机制与支持电源管理的设备驱动进行通讯。电源管理器向下调用设备驱动确定其设备性能,并更新其设备电源状态。设备向上调用电源管理器请求进行设备电源状态更改。向下调用在系统中以IOCTL方式实现。设备通过DevicePowerNotify API函数向上调用电源管理器。 由于电源管理器使用DeviceIoControl与支持电源管理的设备进行通讯,所以设备需要实现一个外部(expose)流接口。在某些情况下,可以用电源管理代理来实现外部流接口。网络驱动接口规约(NDIS)中实现了一个外部流接口,从而能使用RegisterPowerRelationship API函数进行对NDIS迷你接口的代理管理。电源管理器同时提供了一种与非流接口设备的通讯机制。这一方法由具有打开设备句柄、发送请求等功能的抽象层组成。例如:位于Public/Common/Oak/Drivers/Pm/Mdd/Pmdisplay.cpp的驱动程序实现了一个基于ExtEscape函数的通讯接口。 打开名称格式为COM1:、并实现了外部流接口的标准设备,可以对其进行读写。但是,电源管理器并不要求支持电源管理的设备必须使用这种命名格式;设备名称可以是任意唯一的字符串。例如:NDIS迷你接口可以被命名为VMINI1。 尽管Platform Builder提供的电源管理器仅支持流接口驱动,但OEM可以自由的实现其他的设备接口。可以为设备定义一个新的唯一类型全局标识符(GUID)来实现新的接口。不过,驱动程序在使用新接口时必须遵循标准电源管理设备驱动准则。 默认情况下,电源管理器可以发现下列GUID表示的设备类型: l         {A32942B7-920C-486b-B0E6-92A702A99B35} GUID类型为普通被管理设备。 l         {8DD679CE-8AB4-43c8-A14A-EA4963FAA715} GUID类型为块设备。 l         {98C5250D-C29A-4985-AE5F-AFE5367E5006} GUID类型为NDIS设备。 应用程序可以从HKEY_LOCAL_MACHINE/System/CurrentControlSet/Control/Power /Interfaces注册表键中获取可被管理的设备类型的列表。 当应用程序调用一个引用了指定设备的电源管理器API时,应用程序必须指定设备的GUID类型名。如果没有指定设备的GUID类型名,电源管理器会假定此设备为普通被管理设备类型。 有效的设备类型名需要有GUID前缀及反斜杠符号。例如:GUID {8DD679CE-8AB4-43c8-A14A-EA4963FAA715}/DSK1:表示引用一个名为DSK1的块设备。 电源管理器从注册表读取设备类型列表,使用RequestPowerNotifications决定此类型的设备在什么时候被载入。下面时设备类型列表的示例。 [HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Power/Interfaces]     "{A3292B7-920C-486b-B0E6-92A702A99B35}"="Generic power-manageable devices"     "{8DD679CE-8AB4-43c8-A14A-EA4963FAA715}"="Power-manageable block devices"     "{98C5250D-C29A-4985-AE5F-AFE5367E5006}"="Power-manageable NDIS miniports" Platform Builder附带的电源管理器以上述设置执行。如果不定义新的设备注册表键,在注册表中可以不包含上述设置。下面步骤说明了实现一个表示使用ExtEscape直接管理的显示驱动类型的过程。 1.     使用Guidgen.exe创建一个新的GUID类型,并将其添加到注册表中。 2.     为了识别GUID,需要修改电源管理器,并使用ExtEscape与设备通讯。 3.       调用AdvertiseInterface,使用新的GUID修改显示驱动。   4.7.3.1.1     IOCTL设备控制符 电源管理器使用下列IOCTL码与设备通讯: IOCTL 功能 IOCTL_POWER_CAPABILITIES 要求设备通知电源管理器它所支持的电源状态及其特性。 IOCTL_POWER_SET 要求设备更新其设备电源状态。 IOCTL_POWER_QUERY 询问设备是否准备好可以进入另外一个设备电源状态。 IOCTL_POWER_GET 要求设备通知电源管理器它现在的设备电源状态。 IOCTL_REGISTER_POWER_RELATIONSHIP 通知父设备登记它所控制的所有设备。   4.7.3.1.2     驱动到电源管理器的API函数 电源管理器为被管理设备提供下列函数,设备可以通过调用下列函数相电源管理器请求服务。 函数名 功能 DevicePowerNotify 设备驱动调用此函数请求电源管理器更新其设备电源状态。 RegisterPowerRelationship 总线驱动及其他代理电源管理器在需要拦截所有设备的电源IOCTL时调用此函数。 ReleasePowerRelationship 结束由RegisterPowerRelationship调用创建的代理关系。   4.7.3.2              应用程序接口 电源管理器提供了一些函数,使应用程序可以使用这些函数进行设备电源管理。下表中的API函数中,只有GetSystemPowerState、SetPowerRequirement及ReleasePowerRequirement是普通应用程序可以直接执行的。例如:应用程序可以调用SetSystemPowerState来挂起系统,但是电源管理器可以限制应用程序可以请求进入的系统电源状态。其他的API函数是为像控制面板这样的OEM应用程序准备的。下表是这些函数的说明。 函数名 功能 GetSystemPowerState 返回当前系统电源状态的名称。 SetSystemPowerState 请求电源管理器更改当前系统电源状态。 SetPowerRequirement 请求电源管理器将指定设备的电源状态维持在最小等级。 ReleasePowerRequirement 释放SetPowerRequirement设置的电源状态.将设备电源状态恢复到调用SetPowerRequirement之前的状态。 GetDevicePower 返回指定设备的当前电源状态。 SetDevicePower 请求电源管理器更改指定设备的当前电源状态。   4.7.3.2.1   系统电源状态设置 某些情况下,应用程序需要更改系统电源状态。在特定的Windows CE设备上,应用程序并不知道哪些电源状态可用,也不期望知道这些电源状态的特性。对应用程序而言,最好使用描述电源状态的掩码来调用SetSystemPowerState进行电源状态切换,而不要使用明确的状态名调用。电源管理器会将此掩码转换为对应的电源状态。例如:应用程序可以使用POWER_STATE_SUSPEND位元请求进行系统电源状态切换。根据在请求时系统是否在支架(cradle)中,电源管理器随后会切换到Suspend或SuspendCradle状态。如果设备被从支架中取下,电源管理器会将设备切换到Suspend状态。 电源管理器可以限定应用程序可以设置进入哪些系统电源状态。例如:如果电源管理器使用外部输入控制系统电源状态,那么,当系统使用电池供电时,将不会允许进入ACRun状态。Platform Builder附带的电源管理器仅允许应用程序设置系统进入Suspend状态。 下表描述了预定义的电源状态位元及其含义。 位元 描述 POWER_STATE_ON 高性能高功耗。 POWER_STATE_OFF 所有设备都被关闭。 POWER_STATE_CRITICAL 电池低电量。 POWER_STATE_BOOT 系统正在启动。 POWER_STATE_IDLE 空闲状态。 POWER_STATE_RESET 清除文件,关闭设备并调用KernelIoControl. POWER_STATE_SUSPEND 挂起操作系统并最终调用OEMPowerOff. Platform Builder附带的电源管理器并没有使用上表中全部状态。OEM可以根据其设备自行定义状态标记。 如果应用程序使用SetSystemPowerState请求进入一个新的电源状态,电源管理器将进行以下处理: l         广播PBT_TRANSITION通知。 l         如果需要更新所有设备的电源状态。如果设备已处于一个可被新的电源状态接受的电源状态下,电源管理器就不会进行IOCTL_POWER_SET请求。 l         如果设备从挂起状态恢复,电源管理器广播PBT_RESUME通知。   4.7.3.2.2   设备电源需求 在某些情况下应用程序需要改变电源管理器对系统电源状态的管理。例如:某页面调度程序需要使COM3:保持运行在D3或更高的状态,即使在挂起时也以此电源状态运行,从而在COM3:收到一个输入页时能唤醒系统。或者,例如一个流音频程序可能需要网卡及音频系统即便在系统使用电池供电,并以及空闲了一段时间的情况下也能保持在全功耗(Full Power)运行。电源管理器提供SetPowerRequirement API函数为有特定电源管理需求的应用程序提供支持。 SetPowerRequirement API函数允许应用程序请求电源管理器在设备电源状态上设置一个较低的下限。如果电源要求有效,电源管理器则不允许设备将自己的电源状态设为低于要求的下限值。当电源管理器更改系统电源状态时,如果设备需要维持在高于系统电源状态所允许的设备电源状态,电源管理器通常会使设备保持此电源状态。 当系统挂起时设备的电源需求通常会被取消。当系统处于挂起状态时,CPU将停止运行,中断服务也将停止。如果应用程序需要设备在挂起状态时能继续运行,可以在调用SetPowerRequirement时设置POWER_FORCE标记。进行此操作需要对应的设备驱动程序支持在系统挂起时自行停用。 电源管理器可能取消其他环境下的设备电源需求。例如,OEM厂商可能会重新解释系统电源状态POWER_STATE_CRITICAL标记,以便指示系统在使用电池供电,且电池处于低电量临界时,应关闭所有设备。   4.7.3.3              通知接口 电源管理器提供了一组API函数,从而允许应用程序获取电源相关事件的通知,并参与决策系统电源状态的切换。下表列出了相关的API函数。 函数 描述 RequestPowerNotifications 请求电源管理器发送电源事件通知。 StopPowerNotifications 取消由RequestPowerNotifications发出的通知请求。 通知信息通过消息队列传递。为了使用通知,应用程序需要创建一个消息队列,并通过RequestPowerNotifications API函数将消息队列句柄传递给电源管理器。通常将创建一个线程来监控消息队列,等待消息产生。 电源管理器定义了以下几种通知类型。 通知 描述 PBT_RESUME 当系统从挂起状态恢复时产生。 PBT_POWERSTATUSCHANGE 当系统在AC供电及其他供电方式(如电池)间切换时产生。 PBT_TRANSITION 当电源管理器进行系统电源状态变更时产生。