引用 13 楼 cppprogram 的回复:
12楼正解
请教:
1、UpdateBacklight函数中fSetPowerOff和fReleasePwrOff 的 作用是什么呢 ??
2、唤醒背光的机制PM是怎么实现的呢 ?
即:PM怎么知道当前状态是SYSTEMIDLE 当我点击触摸屏后PM需要调整到ON状态?
1、这个问题楼主在六楼已经分析了,#define TURNOFFIMMEDIATELY -1 并不代表着((dwTimeoutPrev != TURNOFFIMMEDIATELY) && (dwTimeoutNew == TURNOFFIMMEDIATELY))
永远不会为真,因为-1在int型下是一个很大的数,如果新的dwTimeoutNew设置为无限大,那就是等于-1了,这时候fSetPowerOff就可以为真,这样就可以set poweroff, 这里为什么要进入D4状态我也不知道,期待大虾来解答,同理fReleasePwrOff就是从poweroff 状态退出了。
2、唤醒背光灯机制:(这里我是在Wince 6.0下改的)
(1) 背光控制当然要在用户有输入的时候把背光打开了,但是这个MDD中没有提到过这件事,我们只有自己加于一个进程来检测了。wince用户输入事件 ("PowerManager/ActivityTimer/UserActivity"),这个在楼上的几位都提到了;
首先我们在bkli.h 的BKL_MDD_INFO 结构体定义中加入输入事件的定义
//add by wxm
HANDLE hInputEvent; //输入触发事件
//add by wxm
在bkldrvapi.cpp 中加入:输入事件的赋值
//add by wxm
const TCHAR szevtUserInput[] = TEXT("PowerManager/ActivityTimer/UserActivity");
//add by wxm
创建事件:
//add by wxm
pBKLinfo->hInputEvent = CreateEvent(NULL, FALSE, FALSE, szevtUserInput);
if(NULL == pBKLinfo->hExitEvent)
{
RETAILMSG(ZONE_ERROR, (TEXT("BLK_Init:hInputEvent OpenDeviceKey failed with %u\r\n"), dwStatus));
goto error;
}
//add by wxm
在bkldrvmian.cpp中加入:
事件检测中的位置:
//add by wxm
#define BKL_EVENT_INPUT 4
//add by wxm
等待事件赋值:
//add by wxm
WaitEvents[BKL_EVENT_INPUT] = pBKLinfo->hInputEvent;
//add by wxm
输入事件的处理:
//add by wxm
case(WAIT_OBJECT_0 + BKL_EVENT_INPUT):
{
DEBUGMSG(ZONE_BACKLIGHT,(TEXT("BKL_EVENT_INPUT\r\n")));
BackLightSetState(D0);
}
break;
通过以上的修改就只要有输入事件比如触摸屏输入时就可以点亮背光灯了。
(2)关于楼主提到的SYSTEMIDLE 状态,在Wince的电源管理中我们经常用到的状态有有On, ,UserIdle,SystemIdle,Suspend四种状态,要想在这些不同的电源状态中对背光灯进行控制,那么我们就要用到设备电源管理驱动。下面是一些关于电源管理的简单介绍。
电源管理模块并不直接实现对子设备的电源开关控制,子设备的电源控制是由各个设备驱动来控制的.电源管理模块透过设备驱动的IOCTLs来请求设备控制自身电源.系统电源状态是灵活自由设定的,而设备电源状态是固定的,最多有5个:D0,D1,D2,D3,D4代表Full on,Low on, Standby, Sleep, Off这5个状态.
不是所有的设备驱动都支持电源管理(至少,在电源管理出现前的早期的设备驱动不会支持).电源管理模块对设备驱动提出了一个规范和架构,满足规范的驱动纳入电源管理.对于流驱动控制的设备,要支持电源管理要满足的条件,简单来说有:1.声明自己是支持电源管理的(Iclass值).2.驱动中实现电源管理模块所要求的IOCTLs.3.驱动加载时候要汇报所支持的电源状态和相关特征.4.***_PowerDown和***_PowerUp接口接收系统休眠和唤醒通知.此外,设计驱动还应该了解:设备不一定具备所有5种状态,但至少可以工作在D0;电源管理模块可能会要求设备进入任何设备电源状态,并不仅仅是设备所汇报自己支持的那几个;如果被要求进入不支持的状态,应该进入另一个它所支持的更高功耗的状态;当前状态不需要重复设置;设备电源状态不一定和系统的电源状态同步.除了流驱动外,还有许多内建驱动需要支持电源管理功能.简单总结:1.显示驱动通过ExtCode接口(SETPOWERMANAGEMENT命令,类似IOCTLs)来控制显示驱动的电源,还控制背灯.2键盘驱动的接口KeybdDriverPowerHandler.3.触摸屏是TouchPanelPowerHandler.4.内建网络miniport驱动是MiniportReset接口.5.PCMCIA驱动是PowerUp和PowerDown.还有打印机,红外等一些内建驱动.
介绍完后我们就转回背光灯的电源管理控制。
首先说的是如何声明设备是支持电源管理的,一般比较方便的方法是在注册表中加入Iclass 值,同样的我们在背光灯的注册表中(红色部分)看到了它也是支持电源管理的:
; Backlight driver
IF BSP_NOBACKLIGHT !
[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\Backlight]
"DLL"="ms2_backlight.DLL"
"Prefix"="BKL"
"Order"=dword:1
"Index"=dword:1
"IClass"="{A32942B7-920C-486b-B0E6-92A702A99B35}"
ENDIF BSP_NOBACKLIGHT !
同时在bkldrvapi.cpp的
extern "C" BOOL BKL_IOControl(.......)函数中加入设备电源管理支持的状态赋值:
//add by wxm
// support D0, D1, D2, D3, D4
pBKLinfo->ucSupportedStatesMask = 0x1F;
PowerCaps->DeviceDx = 0x1F;
//add by wxm
同时屏蔽掉原来的设备支持状态赋值:
// PowerCaps->DeviceDx = BacklightGetSupportedStates();
// support D0, D4
//pBKLinfo->ucSupportedStatesMask = PowerCaps->DeviceDx; //0x11
// ASSERT(pBKLinfo->ucSupportedStatesMask < 0x20);
这样的话,系统由其他状态进入SYSTEMIDLE状态时就会进入
case IOCTL_POWER_SET:
这个case进行背光灯状态的控制。