在 控制面板->显示中设置的是背光的超时时间
相应注册表项为:
[ HKEY_CURRENT_USER\ControlPanel\Backlight]
"BatteryTimeout"=dword: 3c
"ACTimeout"=dword:78
"UseBattery"=dword:1
"UseExt"=dword:1
"Brightness"=dword:0f
"UserC"=dword:1
"AdvancedCPL"="AdvBacklight"
在 控制面板->电源中设置的是系统超时时间
相应注册表项为:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Power\Timeouts]
"ACUserIdle"=dword:3c ; in seconds
"ACSystemIdle"=dword:12c ; in seconds
"ACSuspend"=dword:0 ; in seconds
"BattUserIdle"=dword:3c ; in seconds
"BattSystemIdle"=dword:b4 ; in seconds
"BattSuspend"=dword:12c ; in seconds
最后我发现,无论我在 控制面板->显示中设置多长时间,最终PM->PDD中读取的都是ACUserIdle
代码如下:
dwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE, szPath, 0, 0, &hk);
if(dwStatus == ERROR_SUCCESS)
{
// read system power state timeouts
gdwACTimeoutToUserIdle = RegReadStateTimeout(hk, _T("ACUserIdle"), DEF_TIMEOUTTOUSERIDLE);
gdwACTimeoutToSystemIdle = RegReadStateTimeout(hk, _T("ACSystemIdle"), DEF_TIMEOUTTOSYSTEMIDLE);
gdwACTimeoutToSuspend = RegReadStateTimeout(hk, _T("ACSuspend"), DEF_TIMEOUTTOSUSPEND);
gdwBattTimeoutToUserIdle = RegReadStateTimeout(hk, _T("BattUserIdle"), DEF_TIMEOUTTOUSERIDLE);
gdwBattTimeoutToSystemIdle = RegReadStateTimeout(hk, _T("BattSystemIdle"), DEF_TIMEOUTTOSYSTEMIDLE);
gdwBattTimeoutToSuspend = RegReadStateTimeout(hk, _T("BattSuspend"), DEF_TIMEOUTTOSUSPEND);
// release resources
RegCloseKey(hk);
}
请问:如果我想通过设置 控制面板->显示的超时时间将背光关掉,请问我是否需要修改PM相关代码
各位大侠是怎么实现的??
20 个解决方案
#1
在Bak_hw.cpp (d:\wince500\platform\smdk2440\src\drivers\backlight中修改如下:
//const TCHAR szevtUserInput[] = TEXT("UserInputEvent");
改为:
const TCHAR szevtUserInput[] = TEXT("PowerManager/ActivityTimer/UserActivity");
//const TCHAR szevtUserInput[] = TEXT("UserInputEvent");
改为:
const TCHAR szevtUserInput[] = TEXT("PowerManager/ActivityTimer/UserActivity");
#2
这个主要是注册表中修改的值没有实时传递到你的驱动中,你如果重启,就会有效果了。如果需要实时有效果,只要加一条设置有效的的方式就行了。
#3
网上有很多方法。开一个线程去等。把注册表值设置为线程超时值,超时后直接关,或者发D3。再在背光的IOCTL处理D3。具体参考BSP吧。我记的我以前通过2中方法实现过。
#4
PM只会使用[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Power\Timeouts]中的值,
[HKEY_CURRENT_USER\ControlPanel\Backlight]中的值是供背光驱动使用的,需要自己的代码进行处理吧。
[HKEY_CURRENT_USER\ControlPanel\Backlight]中的值是供背光驱动使用的,需要自己的代码进行处理吧。
#5
学习了,呵呵,以后有时间认真看一下
#6
总结以上各位的观点:
PM中是没有对背光超时时间:
[HKEY_CURRENT_USER\ControlPanel\Backlight]
"BatteryTimeout"=dword: 3c
"ACTimeout"=dword:78
"UseBattery"=dword:1
"UseExt"=dword:1
"Brightness"=dword:0f
"UserC"=dword:1
"AdvancedCPL"="AdvBacklight"
做相应处理的
如果要处理需要改PM->PDD层代码
或者直接在backlight驱动中开个线程,读注册表值处理超时时间
是这样吗?
可是我查了一下PXA270的很多BSP,最背光的处理都是这样的,并没有重新开线程处理这个timeout
难道是都没做这部分的处理吗??
另外有一个地方感到迷惑:
void UpdateBacklight(BKL_MDD_INFO *pBKLinfo, DWORD dwReason)
{
fTapOnPrev = IsTapOn(pBKLinfo);
dwTimeoutPrev = GetTimeout(pBKLinfo);
........
dwTimeoutNew = GetTimeout(pBKLinfo); //通过注册表读到BatteryTimeout或ACTimeout
fTapOnNew = IsTapOn(pBKLinfo);
// 'Tap On' settings just unchecked or 'Turn off backlight' timer option
// just selected:
fSetPowerOff = ( ((dwTimeoutPrev != TURNOFFIMMEDIATELY) && (dwTimeoutNew ==
TURNOFFIMMEDIATELY))|| ((fTapOnPrev && !fTapOnNew)));
// 'Tap On' setting just checked or 'Turn off backlight' timer option
// just deselected:
fReleasePwrOff = (((dwTimeoutPrev == TURNOFFIMMEDIATELY) && (dwTimeoutNew !=
TURNOFFIMMEDIATELY) )|| (!fTapOnPrev && fTapOnNew));
if(fSetPowerOff)
{
BKL_SetDevicePower(pBKLinfo, D4);
}
else if (fReleasePwrOff)
{
BKL_SetDevicePower(pBKLinfo, PwrDeviceUnspecified);
}
}
非常奇怪这段代码在这里的作用,首先dwTimeoutPrev 通过读注册表可以得到我设置的值
接着读到当前设置的值dwTimeoutNew ,
而#define TURNOFFIMMEDIATELY -1 , #define TURNOFFIMMEDIATELY -1
所以前面的部分
((dwTimeoutPrev != TURNOFFIMMEDIATELY) && (dwTimeoutNew == TURNOFFIMMEDIATELY))
永远不会为真
而((fTapOnPrev && !fTapOnNew)))只有电源状态发生变化的时候才为真
所以如果电源状态不发生变化fSetPowerOff和fReleasePwrOff永远不会为真
电源状态发生变化(如当前是BATT,插入AC电源充电)这时需要把电压状态调到D4吗??
那这段代码的意思是做什么呢??
PM中是没有对背光超时时间:
[HKEY_CURRENT_USER\ControlPanel\Backlight]
"BatteryTimeout"=dword: 3c
"ACTimeout"=dword:78
"UseBattery"=dword:1
"UseExt"=dword:1
"Brightness"=dword:0f
"UserC"=dword:1
"AdvancedCPL"="AdvBacklight"
做相应处理的
如果要处理需要改PM->PDD层代码
或者直接在backlight驱动中开个线程,读注册表值处理超时时间
是这样吗?
可是我查了一下PXA270的很多BSP,最背光的处理都是这样的,并没有重新开线程处理这个timeout
难道是都没做这部分的处理吗??
另外有一个地方感到迷惑:
void UpdateBacklight(BKL_MDD_INFO *pBKLinfo, DWORD dwReason)
{
fTapOnPrev = IsTapOn(pBKLinfo);
dwTimeoutPrev = GetTimeout(pBKLinfo);
........
dwTimeoutNew = GetTimeout(pBKLinfo); //通过注册表读到BatteryTimeout或ACTimeout
fTapOnNew = IsTapOn(pBKLinfo);
// 'Tap On' settings just unchecked or 'Turn off backlight' timer option
// just selected:
fSetPowerOff = ( ((dwTimeoutPrev != TURNOFFIMMEDIATELY) && (dwTimeoutNew ==
TURNOFFIMMEDIATELY))|| ((fTapOnPrev && !fTapOnNew)));
// 'Tap On' setting just checked or 'Turn off backlight' timer option
// just deselected:
fReleasePwrOff = (((dwTimeoutPrev == TURNOFFIMMEDIATELY) && (dwTimeoutNew !=
TURNOFFIMMEDIATELY) )|| (!fTapOnPrev && fTapOnNew));
if(fSetPowerOff)
{
BKL_SetDevicePower(pBKLinfo, D4);
}
else if (fReleasePwrOff)
{
BKL_SetDevicePower(pBKLinfo, PwrDeviceUnspecified);
}
}
非常奇怪这段代码在这里的作用,首先dwTimeoutPrev 通过读注册表可以得到我设置的值
接着读到当前设置的值dwTimeoutNew ,
而#define TURNOFFIMMEDIATELY -1 , #define TURNOFFIMMEDIATELY -1
所以前面的部分
((dwTimeoutPrev != TURNOFFIMMEDIATELY) && (dwTimeoutNew == TURNOFFIMMEDIATELY))
永远不会为真
而((fTapOnPrev && !fTapOnNew)))只有电源状态发生变化的时候才为真
所以如果电源状态不发生变化fSetPowerOff和fReleasePwrOff永远不会为真
电源状态发生变化(如当前是BATT,插入AC电源充电)这时需要把电压状态调到D4吗??
那这段代码的意思是做什么呢??
#7
ding!
#8
自己顶
#9
帮顶~~
#10
自己顶
#11
背光驱动里DWORD BL_MonitorThread(PVOID pParms)线程就有这个功能。
修改超时事件:
在Bak_hw.cpp (d:\wince500\platform\smdk2440\src\drivers\backlight中修改如下:
//const TCHAR szevtUserInput[] = TEXT("UserInputEvent");
改为:
const TCHAR szevtUserInput[] = TEXT("PowerManager/ActivityTimer/UserActivity");
修改超时事件:
在Bak_hw.cpp (d:\wince500\platform\smdk2440\src\drivers\backlight中修改如下:
//const TCHAR szevtUserInput[] = TEXT("UserInputEvent");
改为:
const TCHAR szevtUserInput[] = TEXT("PowerManager/ActivityTimer/UserActivity");
#12
在bkldrvmain.cpp监控线程函数中:
WORD fnBackLightThread(PVOID pvArgument)
我们可以找到:
while(1)
{
dwResult = WaitForMultipleObjects(BKL_NUM_EVENTS, &WaitEvents[0], FALSE, INFINITE);
……..
……..
While(1)死循环,不断检测各种和背光有关的各种状态,在看到死循环里面的WaitForMultipleObjects(BKL_NUM_EVENTS,&WaitEvents[0], FALSE, INFINITE);语句,调用了WaitForMultipleObjects多事件等待函数,但是却用了无限大的时间“INFINITE”作为等待时间,这显然没有把控制版面注册表中读回来的背光时间用上,所以做了一下改动:
//add by wxm
DWORD dwTimeoutGet;
//add by wxm
// add by wxm
dwTimeoutGet = GetTimeout(pBKLinfo)*1000;
dwResult = WaitForMultipleObjects(BKL_NUM_EVENTS, &WaitEvents[0], FALSE, dwTimeoutGet);
//add by wxm
把控制版面注册表中读回来的背光时间用上,同时在后面的switch(dwResult)中加入了:
case WAIT_TIMEOUT:
{
DEBUGMSG(1,(TEXT("WAIT_TIMEOUT \r\n")));
BackLightSetState(D4);
}
//add by wxm
break;
这样设置的背光时间到的时候,就可以进行背光的控制了。
WORD fnBackLightThread(PVOID pvArgument)
我们可以找到:
while(1)
{
dwResult = WaitForMultipleObjects(BKL_NUM_EVENTS, &WaitEvents[0], FALSE, INFINITE);
……..
……..
While(1)死循环,不断检测各种和背光有关的各种状态,在看到死循环里面的WaitForMultipleObjects(BKL_NUM_EVENTS,&WaitEvents[0], FALSE, INFINITE);语句,调用了WaitForMultipleObjects多事件等待函数,但是却用了无限大的时间“INFINITE”作为等待时间,这显然没有把控制版面注册表中读回来的背光时间用上,所以做了一下改动:
//add by wxm
DWORD dwTimeoutGet;
//add by wxm
// add by wxm
dwTimeoutGet = GetTimeout(pBKLinfo)*1000;
dwResult = WaitForMultipleObjects(BKL_NUM_EVENTS, &WaitEvents[0], FALSE, dwTimeoutGet);
//add by wxm
把控制版面注册表中读回来的背光时间用上,同时在后面的switch(dwResult)中加入了:
case WAIT_TIMEOUT:
{
DEBUGMSG(1,(TEXT("WAIT_TIMEOUT \r\n")));
BackLightSetState(D4);
}
//add by wxm
break;
这样设置的背光时间到的时候,就可以进行背光的控制了。
#13
12楼正解
请教:
1、UpdateBacklight函数中fSetPowerOff和fReleasePwrOff 的 作用是什么呢 ??
2、唤醒背光的机制PM是怎么实现的呢 ?
即:PM怎么知道当前状态是SYSTEMIDLE 当我点击触摸屏后PM需要调整到ON状态?
请教:
1、UpdateBacklight函数中fSetPowerOff和fReleasePwrOff 的 作用是什么呢 ??
2、唤醒背光的机制PM是怎么实现的呢 ?
即:PM怎么知道当前状态是SYSTEMIDLE 当我点击触摸屏后PM需要调整到ON状态?
#14
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进行背光灯状态的控制。
#15
To weixiao361:
非常感谢,几个不明白的地方这下基本都清楚了
对于唤醒那块:以前我是在每个唤醒源驱动中(如键盘,USB,TOUCH,SD等)定义同名事件
看来“wince用户输入事件 ("PowerManager/ActivityTimer/UserActivity")”
这个方法更标准;
请问:
1、在 "ActivityEvent"="PowerManager/ActivityTimer/UserActivity"
如何添加USB SD卡插入的 唤醒事件呢??
(我看common.reg中介绍 :input event (keyboard, mouse, or
touch))
2、除了背光唤醒之外,添加了PM后,系统进入到 useridle ,当我点击TOUCH,发现系统也会自动唤醒
到D0状态,这个不是我们手动添加进去的,是PM自带的功能,这样看来也应该是通过
"ActivityEvent"="PowerManager/ActivityTimer/UserActivity"
这种方式触发相应的事件,不过没在PM中找到相应的处理代码,不知道是不是这样实现的 ?
非常感谢,几个不明白的地方这下基本都清楚了
对于唤醒那块:以前我是在每个唤醒源驱动中(如键盘,USB,TOUCH,SD等)定义同名事件
看来“wince用户输入事件 ("PowerManager/ActivityTimer/UserActivity")”
这个方法更标准;
请问:
1、在 "ActivityEvent"="PowerManager/ActivityTimer/UserActivity"
如何添加USB SD卡插入的 唤醒事件呢??
(我看common.reg中介绍 :input event (keyboard, mouse, or
touch))
2、除了背光唤醒之外,添加了PM后,系统进入到 useridle ,当我点击TOUCH,发现系统也会自动唤醒
到D0状态,这个不是我们手动添加进去的,是PM自带的功能,这样看来也应该是通过
"ActivityEvent"="PowerManager/ActivityTimer/UserActivity"
这种方式触发相应的事件,不过没在PM中找到相应的处理代码,不知道是不是这样实现的 ?
#16
对于楼主的这俩个问题我也没有深入研究,据我所知UserActivity包括了键盘,鼠标,触摸屏等输入,至于触发机制只有等待高手回答, 对于楼主的如何添加USB SD卡插入的 唤醒事件的问题,也希望楼主解决以后和大家分享哈,呵呵
#17
哈哈 ,非标准的 我会
就是 在 USB SD初始化函数中加入同名事件,
hEvent = Create(...,"_BackLightWakeUpEvent_");
插入响应函数中加SetEvent(hEvent);
再在backlight驱动中waitformultipleObjects中加上这个事件就行了
就是 在 USB SD初始化函数中加入同名事件,
hEvent = Create(...,"_BackLightWakeUpEvent_");
插入响应函数中加SetEvent(hEvent);
再在backlight驱动中waitformultipleObjects中加上这个事件就行了
#18
看看先
#19
根据http://www.cnblogs.com/we-hjb/archive/2010/01/27/1657973.html
仅仅修改注册表中的键值并不能实时生效,应用程序通过注册表读写API修改该键下的DWORD值(十六进制以秒为单位),完成修改后,必须通知PM使用新设置的超时时间,实现的参考代码如下:
HANDLE hReloadActivityTimeouts;
hReloadActivityTimeouts = OpenEvent(EVENT_ALL_ACCESS, FALSE, _T("PowerManager/ReloadActivityTimeouts"));
if(hReloadActivityTimeouts)
{
SetEvent(hReloadActivityTimeouts);
CloseHandle(hReloadActivityTimeouts);
}
把上边这段加到驱动里就行了
仅仅修改注册表中的键值并不能实时生效,应用程序通过注册表读写API修改该键下的DWORD值(十六进制以秒为单位),完成修改后,必须通知PM使用新设置的超时时间,实现的参考代码如下:
HANDLE hReloadActivityTimeouts;
hReloadActivityTimeouts = OpenEvent(EVENT_ALL_ACCESS, FALSE, _T("PowerManager/ReloadActivityTimeouts"));
if(hReloadActivityTimeouts)
{
SetEvent(hReloadActivityTimeouts);
CloseHandle(hReloadActivityTimeouts);
}
把上边这段加到驱动里就行了
#20
#21
#1
在Bak_hw.cpp (d:\wince500\platform\smdk2440\src\drivers\backlight中修改如下:
//const TCHAR szevtUserInput[] = TEXT("UserInputEvent");
改为:
const TCHAR szevtUserInput[] = TEXT("PowerManager/ActivityTimer/UserActivity");
//const TCHAR szevtUserInput[] = TEXT("UserInputEvent");
改为:
const TCHAR szevtUserInput[] = TEXT("PowerManager/ActivityTimer/UserActivity");
#2
这个主要是注册表中修改的值没有实时传递到你的驱动中,你如果重启,就会有效果了。如果需要实时有效果,只要加一条设置有效的的方式就行了。
#3
网上有很多方法。开一个线程去等。把注册表值设置为线程超时值,超时后直接关,或者发D3。再在背光的IOCTL处理D3。具体参考BSP吧。我记的我以前通过2中方法实现过。
#4
PM只会使用[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Power\Timeouts]中的值,
[HKEY_CURRENT_USER\ControlPanel\Backlight]中的值是供背光驱动使用的,需要自己的代码进行处理吧。
[HKEY_CURRENT_USER\ControlPanel\Backlight]中的值是供背光驱动使用的,需要自己的代码进行处理吧。
#5
学习了,呵呵,以后有时间认真看一下
#6
总结以上各位的观点:
PM中是没有对背光超时时间:
[HKEY_CURRENT_USER\ControlPanel\Backlight]
"BatteryTimeout"=dword: 3c
"ACTimeout"=dword:78
"UseBattery"=dword:1
"UseExt"=dword:1
"Brightness"=dword:0f
"UserC"=dword:1
"AdvancedCPL"="AdvBacklight"
做相应处理的
如果要处理需要改PM->PDD层代码
或者直接在backlight驱动中开个线程,读注册表值处理超时时间
是这样吗?
可是我查了一下PXA270的很多BSP,最背光的处理都是这样的,并没有重新开线程处理这个timeout
难道是都没做这部分的处理吗??
另外有一个地方感到迷惑:
void UpdateBacklight(BKL_MDD_INFO *pBKLinfo, DWORD dwReason)
{
fTapOnPrev = IsTapOn(pBKLinfo);
dwTimeoutPrev = GetTimeout(pBKLinfo);
........
dwTimeoutNew = GetTimeout(pBKLinfo); //通过注册表读到BatteryTimeout或ACTimeout
fTapOnNew = IsTapOn(pBKLinfo);
// 'Tap On' settings just unchecked or 'Turn off backlight' timer option
// just selected:
fSetPowerOff = ( ((dwTimeoutPrev != TURNOFFIMMEDIATELY) && (dwTimeoutNew ==
TURNOFFIMMEDIATELY))|| ((fTapOnPrev && !fTapOnNew)));
// 'Tap On' setting just checked or 'Turn off backlight' timer option
// just deselected:
fReleasePwrOff = (((dwTimeoutPrev == TURNOFFIMMEDIATELY) && (dwTimeoutNew !=
TURNOFFIMMEDIATELY) )|| (!fTapOnPrev && fTapOnNew));
if(fSetPowerOff)
{
BKL_SetDevicePower(pBKLinfo, D4);
}
else if (fReleasePwrOff)
{
BKL_SetDevicePower(pBKLinfo, PwrDeviceUnspecified);
}
}
非常奇怪这段代码在这里的作用,首先dwTimeoutPrev 通过读注册表可以得到我设置的值
接着读到当前设置的值dwTimeoutNew ,
而#define TURNOFFIMMEDIATELY -1 , #define TURNOFFIMMEDIATELY -1
所以前面的部分
((dwTimeoutPrev != TURNOFFIMMEDIATELY) && (dwTimeoutNew == TURNOFFIMMEDIATELY))
永远不会为真
而((fTapOnPrev && !fTapOnNew)))只有电源状态发生变化的时候才为真
所以如果电源状态不发生变化fSetPowerOff和fReleasePwrOff永远不会为真
电源状态发生变化(如当前是BATT,插入AC电源充电)这时需要把电压状态调到D4吗??
那这段代码的意思是做什么呢??
PM中是没有对背光超时时间:
[HKEY_CURRENT_USER\ControlPanel\Backlight]
"BatteryTimeout"=dword: 3c
"ACTimeout"=dword:78
"UseBattery"=dword:1
"UseExt"=dword:1
"Brightness"=dword:0f
"UserC"=dword:1
"AdvancedCPL"="AdvBacklight"
做相应处理的
如果要处理需要改PM->PDD层代码
或者直接在backlight驱动中开个线程,读注册表值处理超时时间
是这样吗?
可是我查了一下PXA270的很多BSP,最背光的处理都是这样的,并没有重新开线程处理这个timeout
难道是都没做这部分的处理吗??
另外有一个地方感到迷惑:
void UpdateBacklight(BKL_MDD_INFO *pBKLinfo, DWORD dwReason)
{
fTapOnPrev = IsTapOn(pBKLinfo);
dwTimeoutPrev = GetTimeout(pBKLinfo);
........
dwTimeoutNew = GetTimeout(pBKLinfo); //通过注册表读到BatteryTimeout或ACTimeout
fTapOnNew = IsTapOn(pBKLinfo);
// 'Tap On' settings just unchecked or 'Turn off backlight' timer option
// just selected:
fSetPowerOff = ( ((dwTimeoutPrev != TURNOFFIMMEDIATELY) && (dwTimeoutNew ==
TURNOFFIMMEDIATELY))|| ((fTapOnPrev && !fTapOnNew)));
// 'Tap On' setting just checked or 'Turn off backlight' timer option
// just deselected:
fReleasePwrOff = (((dwTimeoutPrev == TURNOFFIMMEDIATELY) && (dwTimeoutNew !=
TURNOFFIMMEDIATELY) )|| (!fTapOnPrev && fTapOnNew));
if(fSetPowerOff)
{
BKL_SetDevicePower(pBKLinfo, D4);
}
else if (fReleasePwrOff)
{
BKL_SetDevicePower(pBKLinfo, PwrDeviceUnspecified);
}
}
非常奇怪这段代码在这里的作用,首先dwTimeoutPrev 通过读注册表可以得到我设置的值
接着读到当前设置的值dwTimeoutNew ,
而#define TURNOFFIMMEDIATELY -1 , #define TURNOFFIMMEDIATELY -1
所以前面的部分
((dwTimeoutPrev != TURNOFFIMMEDIATELY) && (dwTimeoutNew == TURNOFFIMMEDIATELY))
永远不会为真
而((fTapOnPrev && !fTapOnNew)))只有电源状态发生变化的时候才为真
所以如果电源状态不发生变化fSetPowerOff和fReleasePwrOff永远不会为真
电源状态发生变化(如当前是BATT,插入AC电源充电)这时需要把电压状态调到D4吗??
那这段代码的意思是做什么呢??
#7
ding!
#8
自己顶
#9
帮顶~~
#10
自己顶
#11
背光驱动里DWORD BL_MonitorThread(PVOID pParms)线程就有这个功能。
修改超时事件:
在Bak_hw.cpp (d:\wince500\platform\smdk2440\src\drivers\backlight中修改如下:
//const TCHAR szevtUserInput[] = TEXT("UserInputEvent");
改为:
const TCHAR szevtUserInput[] = TEXT("PowerManager/ActivityTimer/UserActivity");
修改超时事件:
在Bak_hw.cpp (d:\wince500\platform\smdk2440\src\drivers\backlight中修改如下:
//const TCHAR szevtUserInput[] = TEXT("UserInputEvent");
改为:
const TCHAR szevtUserInput[] = TEXT("PowerManager/ActivityTimer/UserActivity");
#12
在bkldrvmain.cpp监控线程函数中:
WORD fnBackLightThread(PVOID pvArgument)
我们可以找到:
while(1)
{
dwResult = WaitForMultipleObjects(BKL_NUM_EVENTS, &WaitEvents[0], FALSE, INFINITE);
……..
……..
While(1)死循环,不断检测各种和背光有关的各种状态,在看到死循环里面的WaitForMultipleObjects(BKL_NUM_EVENTS,&WaitEvents[0], FALSE, INFINITE);语句,调用了WaitForMultipleObjects多事件等待函数,但是却用了无限大的时间“INFINITE”作为等待时间,这显然没有把控制版面注册表中读回来的背光时间用上,所以做了一下改动:
//add by wxm
DWORD dwTimeoutGet;
//add by wxm
// add by wxm
dwTimeoutGet = GetTimeout(pBKLinfo)*1000;
dwResult = WaitForMultipleObjects(BKL_NUM_EVENTS, &WaitEvents[0], FALSE, dwTimeoutGet);
//add by wxm
把控制版面注册表中读回来的背光时间用上,同时在后面的switch(dwResult)中加入了:
case WAIT_TIMEOUT:
{
DEBUGMSG(1,(TEXT("WAIT_TIMEOUT \r\n")));
BackLightSetState(D4);
}
//add by wxm
break;
这样设置的背光时间到的时候,就可以进行背光的控制了。
WORD fnBackLightThread(PVOID pvArgument)
我们可以找到:
while(1)
{
dwResult = WaitForMultipleObjects(BKL_NUM_EVENTS, &WaitEvents[0], FALSE, INFINITE);
……..
……..
While(1)死循环,不断检测各种和背光有关的各种状态,在看到死循环里面的WaitForMultipleObjects(BKL_NUM_EVENTS,&WaitEvents[0], FALSE, INFINITE);语句,调用了WaitForMultipleObjects多事件等待函数,但是却用了无限大的时间“INFINITE”作为等待时间,这显然没有把控制版面注册表中读回来的背光时间用上,所以做了一下改动:
//add by wxm
DWORD dwTimeoutGet;
//add by wxm
// add by wxm
dwTimeoutGet = GetTimeout(pBKLinfo)*1000;
dwResult = WaitForMultipleObjects(BKL_NUM_EVENTS, &WaitEvents[0], FALSE, dwTimeoutGet);
//add by wxm
把控制版面注册表中读回来的背光时间用上,同时在后面的switch(dwResult)中加入了:
case WAIT_TIMEOUT:
{
DEBUGMSG(1,(TEXT("WAIT_TIMEOUT \r\n")));
BackLightSetState(D4);
}
//add by wxm
break;
这样设置的背光时间到的时候,就可以进行背光的控制了。
#13
12楼正解
请教:
1、UpdateBacklight函数中fSetPowerOff和fReleasePwrOff 的 作用是什么呢 ??
2、唤醒背光的机制PM是怎么实现的呢 ?
即:PM怎么知道当前状态是SYSTEMIDLE 当我点击触摸屏后PM需要调整到ON状态?
请教:
1、UpdateBacklight函数中fSetPowerOff和fReleasePwrOff 的 作用是什么呢 ??
2、唤醒背光的机制PM是怎么实现的呢 ?
即:PM怎么知道当前状态是SYSTEMIDLE 当我点击触摸屏后PM需要调整到ON状态?
#14
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进行背光灯状态的控制。
#15
To weixiao361:
非常感谢,几个不明白的地方这下基本都清楚了
对于唤醒那块:以前我是在每个唤醒源驱动中(如键盘,USB,TOUCH,SD等)定义同名事件
看来“wince用户输入事件 ("PowerManager/ActivityTimer/UserActivity")”
这个方法更标准;
请问:
1、在 "ActivityEvent"="PowerManager/ActivityTimer/UserActivity"
如何添加USB SD卡插入的 唤醒事件呢??
(我看common.reg中介绍 :input event (keyboard, mouse, or
touch))
2、除了背光唤醒之外,添加了PM后,系统进入到 useridle ,当我点击TOUCH,发现系统也会自动唤醒
到D0状态,这个不是我们手动添加进去的,是PM自带的功能,这样看来也应该是通过
"ActivityEvent"="PowerManager/ActivityTimer/UserActivity"
这种方式触发相应的事件,不过没在PM中找到相应的处理代码,不知道是不是这样实现的 ?
非常感谢,几个不明白的地方这下基本都清楚了
对于唤醒那块:以前我是在每个唤醒源驱动中(如键盘,USB,TOUCH,SD等)定义同名事件
看来“wince用户输入事件 ("PowerManager/ActivityTimer/UserActivity")”
这个方法更标准;
请问:
1、在 "ActivityEvent"="PowerManager/ActivityTimer/UserActivity"
如何添加USB SD卡插入的 唤醒事件呢??
(我看common.reg中介绍 :input event (keyboard, mouse, or
touch))
2、除了背光唤醒之外,添加了PM后,系统进入到 useridle ,当我点击TOUCH,发现系统也会自动唤醒
到D0状态,这个不是我们手动添加进去的,是PM自带的功能,这样看来也应该是通过
"ActivityEvent"="PowerManager/ActivityTimer/UserActivity"
这种方式触发相应的事件,不过没在PM中找到相应的处理代码,不知道是不是这样实现的 ?
#16
对于楼主的这俩个问题我也没有深入研究,据我所知UserActivity包括了键盘,鼠标,触摸屏等输入,至于触发机制只有等待高手回答, 对于楼主的如何添加USB SD卡插入的 唤醒事件的问题,也希望楼主解决以后和大家分享哈,呵呵
#17
哈哈 ,非标准的 我会
就是 在 USB SD初始化函数中加入同名事件,
hEvent = Create(...,"_BackLightWakeUpEvent_");
插入响应函数中加SetEvent(hEvent);
再在backlight驱动中waitformultipleObjects中加上这个事件就行了
就是 在 USB SD初始化函数中加入同名事件,
hEvent = Create(...,"_BackLightWakeUpEvent_");
插入响应函数中加SetEvent(hEvent);
再在backlight驱动中waitformultipleObjects中加上这个事件就行了
#18
看看先
#19
根据http://www.cnblogs.com/we-hjb/archive/2010/01/27/1657973.html
仅仅修改注册表中的键值并不能实时生效,应用程序通过注册表读写API修改该键下的DWORD值(十六进制以秒为单位),完成修改后,必须通知PM使用新设置的超时时间,实现的参考代码如下:
HANDLE hReloadActivityTimeouts;
hReloadActivityTimeouts = OpenEvent(EVENT_ALL_ACCESS, FALSE, _T("PowerManager/ReloadActivityTimeouts"));
if(hReloadActivityTimeouts)
{
SetEvent(hReloadActivityTimeouts);
CloseHandle(hReloadActivityTimeouts);
}
把上边这段加到驱动里就行了
仅仅修改注册表中的键值并不能实时生效,应用程序通过注册表读写API修改该键下的DWORD值(十六进制以秒为单位),完成修改后,必须通知PM使用新设置的超时时间,实现的参考代码如下:
HANDLE hReloadActivityTimeouts;
hReloadActivityTimeouts = OpenEvent(EVENT_ALL_ACCESS, FALSE, _T("PowerManager/ReloadActivityTimeouts"));
if(hReloadActivityTimeouts)
{
SetEvent(hReloadActivityTimeouts);
CloseHandle(hReloadActivityTimeouts);
}
把上边这段加到驱动里就行了