驅動和AP之間互相通訊有很多中方法,比如自訂Event然後AP通過等待Event的方式來和driver同步。但是很多標準的事件,比如電源狀況的改 變,SD卡插入等等通用的訊息在CE的內部是早有預留的。微軟透過訊息佇列的形式來告訴需要獲知相關訊息的AP來做處理,我們僅僅需要事先去瞭解系統有哪 些訊息佇列,然後在AP中寫代碼去捕捉就好了,本文就以獲知電池電量改變為例,講講訊息佇列的用法。
在WinCE的項目開發過程中經常要編寫AP來擷取電池的電量和電源的來源等資訊,由於WinCE底層的電池驅動一般以查詢的方式得到電池的狀態然後更新 到一個結構體中,AP可以調用GetSystemPowerStatusEx2來得到這個結構體的數值,為了即時的更新電池的資訊AP必須頻繁的調用函數 去得到資料更新。
其實WinCE的電源管理中已經整合了一種notify機制,會在電池資訊發生變化時發出提醒。
RequestPowerNotifications函數可以被AP用來請求接收這種提醒服務。
AP在調用這個API之前必須建立一個訊息佇列,可以用CreateMsgQueue來實現。
接受提醒的方式是使用WaitForSingleObject來實現,該函數會一直等待直到收到電源管理發來的提醒,然後AP可以去讀取訊息佇列中的資料來判定具體電源系統發生了哪些變化,然後做相關的事情比如更新UI的顯示等。
參考原始碼:
//#################################################################
#include
#define QUEUE_ENTRIES 3
#define MAX_NAMELEN 200
#define QUEUE_SIZE (QUEUE_ENTRIES * (sizeof(POWER_BROADCAST) + MAX_NAMELEN))
HANDLE hMsgQ;
DWORD WINAPI PowerChangeListen(void * temp_p)
{
UCHAR buf[QUEUE_SIZE];
unsigned long nRead = 0, flags = 0, res = 0;
while(1)
{
DWORD dwRes = WaitForSingleObject(hMsgQ,INFINITE);
if(dwRes==WAIT_OBJECT_0)
{
memset(&buf, 0, QUEUE_SIZE);
if (ReadMsgQueue(hMsgQ, &buf, QUEUE_SIZE, &nRead, INFINITE, &flags))
{
PPOWER_BROADCAST pB = (PPOWER_BROADCAST)&buf;
PPOWER_BROADCAST_POWER_INFO ppbpi = (PPOWER_BROADCAST_POWER_INFO) pB->SystemPowerState;
if(pB->Message==PBT_POWERINFOCHANGE)
{
//在這裡處理一些電池資訊相關資料改變的事情
// MessageBox(NULL,L"Battery info change",NULL,NULL);
NKDbgPrintfW(L"[Fred]Battery info change BatteryLifePercent=%d\r\n",ppbpi->bBatteryLifePercent);
}
if(pB->Message==PBT_POWERSTATUSCHANGE)
{
//在這裡處理一些電源輸入狀態改變 (AC/Battery)的事情
//MessageBox(NULL,L"Power input change",NULL,NULL);
NKDbgPrintfW(L"[Fred]Power input change ACIN=%d\r\n",ppbpi->bACLineStatus);
}
}
}
}
}
void Init_PowerNotify()
{
NKDbgPrintfW(L"[Fred]Init_PowerNotify++\r\n");
MSGQUEUEOPTIONS options = {0};
DWORD dwErr;
options.dwSize = sizeof(MSGQUEUEOPTIONS);
options.dwFlags = 0;
options.dwMaxMessages = QUEUE_ENTRIES;
options.cbMaxMessage = sizeof(POWER_BROADCAST) + MAX_NAMELEN;
options.bReadAccess = TRUE;
hMsgQ = CreateMsgQueue(NULL, &options);
if(!hMsgQ)
{
dwErr=GetLastError();
NKDbgPrintfW(L"[Fred]CreateMsgQueue failed\r\n");
RETAILMSG(1, (TEXT("[Fred]CreateMessageQueue ERROR:%d\n"), dwErr));
return;
}
HANDLE hNotifications = RequestPowerNotifications(hMsgQ, POWER_NOTIFY_ALL); // Flags
if (!hNotifications) {
dwErr = GetLastError();
RETAILMSG(1, (TEXT("[Fred]RequestPowerNotifications ERROR:%d\n"), dwErr));
StopPowerNotifications(hMsgQ);
return;
}
CreateThread(NULL, 0, PowerChangeListen, NULL, 0, NULL);
NKDbgPrintfW(L"[Fred]Init_PowerNotify--\r\n");
}
//###################################################################################
複製代碼AP可以把上面的代碼全部複製到自己的源碼中,然後在初始化的時候調用一次Init_PowerNotify,之後就可以等待訊息的發生(中文注釋部分)
來自:
http://blog.csdn.net/armeasy/archive/2009/10/09/4647131.aspx