WINCE的電源管理
nbsp; 在windows ce中,顯示的控制是通過(guò)extescape函數(shù)。這是一個(gè)顯示和打印機(jī)驅(qū)動(dòng)的后門(mén)。windows ce顯示驅(qū)動(dòng)支持許多設(shè)備轉(zhuǎn)義代碼(escape codes),這些被公布在platform builder中。對(duì)于我們的目的來(lái)說(shuō),只有兩個(gè)轉(zhuǎn)義代碼被用到:setpowermanagement來(lái)設(shè)置顯示的電源狀態(tài)和queryescsupport來(lái)查詢(xún)是否setpowermanagement被驅(qū)動(dòng)支持。下面的例子打開(kāi)或關(guān)閉系統(tǒng)顯示通過(guò)顯示驅(qū)動(dòng),并且支持完全的轉(zhuǎn)義代碼: 前面的代碼通過(guò)調(diào)用extescape和queryescsupport命令來(lái)查詢(xún)是否支持轉(zhuǎn)移代碼。被查詢(xún)的命令首先交給輸入緩沖,如果setpowermanagement命令被支持,程序就填充video_power_management結(jié)構(gòu)并再次調(diào)用extescape設(shè)置電源狀態(tài)。 雖然這些轉(zhuǎn)義代碼允許應(yīng)用程序打開(kāi)或關(guān)閉顯示,windows ce沒(méi)有一個(gè)統(tǒng)一的方式來(lái)控制背光的亮度。每個(gè)系統(tǒng)都有它自己的oem特有方式來(lái)控制背光亮度。如果將來(lái)有一種標(biāo)準(zhǔn)的背光亮度控制方式,它將很可能放在extescape函數(shù)中。 打開(kāi)系統(tǒng)電源當(dāng)系統(tǒng)被掛起,應(yīng)用程序?qū)⒉辉龠\(yùn)行,因此當(dāng)系統(tǒng)喚醒時(shí),應(yīng)用程序看起來(lái)沒(méi)有被控制。然而,有一些方式來(lái)喚醒一個(gè)掛起的設(shè)備。首先,一個(gè)應(yīng)用程序通過(guò)給定一個(gè)時(shí)間,并使用11章提到的消息api(notification api)做系統(tǒng)被喚醒的計(jì)劃。在一般情況下,oem廠商會(huì)分配一些中斷條件,以便管理系統(tǒng)電源打開(kāi),或喚醒。這種方式的一個(gè)例子是一個(gè)系統(tǒng)當(dāng)防止了一個(gè)同步架(synchronization cradle)時(shí)被喚醒。 防止系統(tǒng)關(guān)閉電源相反的情況,防止系統(tǒng)掛起也是一個(gè)問(wèn)題。windows ce系統(tǒng)通常被設(shè)置為當(dāng)一段時(shí)間沒(méi)有用戶(hù)輸入就自動(dòng)掛起。要防止自動(dòng)掛起,一個(gè)應(yīng)用程序可以周期性地調(diào)用一下函數(shù): void winapi systemidletimerreset (void); 這個(gè)函數(shù)重設(shè)windows ce用來(lái)監(jiān)視用戶(hù)輸入的定時(shí)器。如果定時(shí)器到達(dá)預(yù)先的沒(méi)有用戶(hù)輸入的間隔,系統(tǒng)會(huì)自動(dòng)掛起。因?yàn)閽炱鸪瑫r(shí)值可以被改變,一個(gè)應(yīng)用程序需要知道超時(shí)值,這樣就要多一點(diǎn)調(diào)用systemidletimerreset。系統(tǒng)維護(hù)三個(gè)超時(shí)值,這些都能夠使用systemparametersinfo來(lái)查詢(xún)。傳遞給systemparametersinfo的常量的不同表現(xiàn),顯示如下: spi_getbatteryidletimeout 當(dāng)系統(tǒng)運(yùn)行在電池電源狀態(tài)下,離用戶(hù)最后輸入的時(shí)間 spi_getexternalidletimeout 當(dāng)系統(tǒng)運(yùn)行在ac電源狀態(tài)下,離用戶(hù)最后輸入的時(shí)間 spi_getwakeupidletimeout 在系統(tǒng)再次掛起時(shí)離系統(tǒng)被自動(dòng)喚醒的時(shí)間 要防止電源被自動(dòng)掛起,你需要查詢(xún)這三個(gè)值,并在最短時(shí)間內(nèi)返回之前調(diào)用systemidletimerreset。如果超時(shí)值被設(shè)置為0,表示超時(shí)值被禁止。 電源管理程序一個(gè)新的,獨(dú)立的電源管理組件在windows ce .net 4.0中被引入了。這個(gè)電源管理程序替代了許多gwes以前完成的函數(shù)。電源管理程序定義了一系列的電源狀態(tài),如d0,d1,d2,和d3。這些看起來(lái)神秘的名字被對(duì)應(yīng)于一些友好的系統(tǒng)級(jí)別名稱(chēng)。 對(duì)嵌入式系統(tǒng)來(lái)說(shuō),oem廠商定義了系統(tǒng)的電源狀態(tài)。例如,電源狀態(tài)可能是打開(kāi)(on),空閑(idle)和掛起(suspend)。其他電源狀態(tài)也被定義了,像screenoff, incradle, 和 onbattery。 從應(yīng)用程序的觀點(diǎn)看,新的電源管理程序提供了通知電源狀態(tài)改變的能力以及通過(guò)一系列的函數(shù)統(tǒng)一改變電源狀態(tài)的能力。 系統(tǒng)的電源狀態(tài)被定義在注冊(cè)表中,sdk定義了pwrmgr_reg_key,以致你不得不知道注冊(cè)表的字符串,但是當(dāng)常量沒(méi)定義的時(shí)間,電源管理程序注冊(cè)數(shù)據(jù)被保留在hkey_local_machinesystemcurrentcontrolsetcontrolpower。電源狀態(tài)被定義作為子鍵,位于key state。 電源通知電源管理程序一個(gè)十分受歡迎的特點(diǎn)是,可以在系統(tǒng)電源狀態(tài)改變時(shí)通知應(yīng)用程序。這可以讓?xiě)?yīng)用程序從手動(dòng)檢測(cè)電源狀態(tài)中解脫出來(lái)。一個(gè)應(yīng)用程序可以通過(guò)調(diào)用requestpowernotifications請(qǐng)求電源管理程序當(dāng)電源狀態(tài)改變的時(shí)候發(fā)送一個(gè)通知給應(yīng)用程序。電源管理程序會(huì)通過(guò)一個(gè)由應(yīng)用程序前面建立的消息隊(duì)列發(fā)送通知。 requestpowernotifications原型如下。 handle requestpowernotifications (handle hmsgq, dword flags); 第一個(gè)參數(shù)是一個(gè)應(yīng)用程序在之前建立的消息隊(duì)列的句柄。第二個(gè)參數(shù)是一系列參數(shù),表示應(yīng)用程序想接收的通知。 pbt_transition 接受系統(tǒng)電源狀態(tài)改變的通知。例如,當(dāng)系統(tǒng)從on到suspend。 pbt_resume 當(dāng)系統(tǒng)resume的時(shí)候接收通知。 pbt_powerstatuschange 當(dāng)系統(tǒng)在ac和電池之間切換的時(shí)候接收通知。 pbt_powerinfochange 當(dāng)系統(tǒng)電池級(jí)數(shù)變化時(shí)接收通知。 power_notify_all 接收所有的通知。 requestpowernotifications函數(shù)返回一個(gè)電源通知的句柄,失敗返回null。消息隊(duì)列建立的時(shí)候必須使應(yīng)用程序有讀權(quán)限,因?yàn)閼?yīng)用程序?qū)南㈥?duì)列中讀取電源通知。 要接收通知,應(yīng)用程序必須使用waitforsingleob-ject來(lái)阻塞消息句柄。像第10章所討論的,當(dāng)通知被放在隊(duì)列中時(shí),句柄將被signaled。實(shí)際的通知將由結(jié)構(gòu)power_broadcast表中被接收到。 typedef struct _power_broadcast { dword message; dword flags; dword length; wchar systempowerstate[1]; } power_broadcast, *ppower_broadcast; 第一個(gè)要注意的是,這個(gè)結(jié)構(gòu)長(zhǎng)度是可變的。最后一個(gè)字段,systempowerstate,是被定義為wchars類(lèi)型,但是可以填上非字符串?dāng)?shù)據(jù)。第一個(gè)字段是通知自己的標(biāo)識(shí),這個(gè)字段可以填前面pbt_標(biāo)志列表之一。flags區(qū)可以包括以下標(biāo)志,依賴(lài)于被接收的通知: power_state_on 系統(tǒng)處于on狀態(tài)。 power_state_off 系統(tǒng)處于off狀態(tài)。 power_state_critical 系統(tǒng)進(jìn)入了一個(gè)臨界off狀態(tài)。 power_state_boot 系統(tǒng)正在啟動(dòng)。 power_state_idle 系統(tǒng)進(jìn)入idle狀態(tài)。 power_state_suspend 系統(tǒng)被掛起。 power_state_reset 系統(tǒng)被復(fù)位。 最后兩個(gè)字段是相互關(guān)聯(lián)的。length字段是systempowerstate字段數(shù)據(jù)的長(zhǎng)度。systempowerstate中包含的數(shù)據(jù)依賴(lài)于被發(fā)送的通知。對(duì)于pbt_transition通知來(lái)說(shuō),systempowerstate字段包含一個(gè)新電源狀態(tài)的標(biāo)識(shí)字符串。這個(gè)字符串是以非0結(jié)尾的。為了結(jié)束字符串,使用length字段來(lái)指出字符串的長(zhǎng)度。注意,length字段是以字節(jié)為單位的,當(dāng)字符是雙字節(jié)的uncode字符時(shí),需要獲得字符串字符的長(zhǎng)度,就需要用length字段去除tchar的size。 對(duì)于pbt_powerinfochange通知來(lái)說(shuō),systempowerstate字段包含一個(gè)ppower_broadcast_power_info結(jié)構(gòu): typedef struct _power_broadcast_power_info { dword dwnumlevels; dword dwbatterylifetime; dword dwbatteryfulllifetime; dword dwbackupbatterylifetime; dword dwbackupbatteryfulllifetime; byte baclinestatus; byte bbatteryflag; byte bbatterylifepercent; byte bbackupbatteryflag; byte bbackupbatterylifepercent; } power_broadcast_power_info, *ppower_broadcast_power_info; 注意,這里有一些字段的名字和函數(shù)十分相似于前面討論的system_power_status_ex2結(jié)構(gòu)。 設(shè)置電源狀態(tài)電源管理程序提供的函數(shù)也允許應(yīng)用程序來(lái)控制電源狀態(tài)。有兩個(gè)方式來(lái)控制電源。第一個(gè)方式是應(yīng)用程序給定一個(gè)電源設(shè)定。第二個(gè)方式是應(yīng)用程序請(qǐng)求電源狀態(tài)不要低于給定的級(jí)別。 一個(gè)應(yīng)用程序通過(guò)調(diào)用函數(shù)setsystempowerstate可以請(qǐng)求特定的電源狀態(tài)。這個(gè)函數(shù)原型如下。 dword options); 電源狀態(tài)可以被請(qǐng)求通過(guò)指定前兩個(gè)參數(shù)。如果第一個(gè)參數(shù)是非零值,它指向一個(gè)字符串標(biāo)識(shí)被請(qǐng)求的狀態(tài)。這個(gè)字符串必須和注冊(cè)表中列出的電源狀態(tài)之一相匹配。 如果psstate 為 null,第二個(gè)參數(shù)stateflags,定義了請(qǐng)求的電源狀態(tài)。這個(gè)參數(shù)是從power_state_on直到power_state_reset狀態(tài)其中之一,這些在前面提到的power_broadcast結(jié)構(gòu)有描述。 比較特別的是power_state_reset標(biāo)志。這個(gè)標(biāo)志請(qǐng)求系統(tǒng)重起,使用setsystempowerstate的方法重起比通過(guò)直接使用ioctl_hal_reboot命令來(lái)調(diào)用kerneliocontrol的方法更好。調(diào)用 setsystempowerstate 會(huì)讓系統(tǒng)在重起設(shè)備之前任何還在緩沖中的數(shù)據(jù)保存到文件系統(tǒng)。 調(diào)用setsystempowerstate是一個(gè)直接改變電源狀態(tài)的方法。更巧妙的方法是通過(guò)調(diào)用setpowerrequirement來(lái)請(qǐng)求系統(tǒng)維持應(yīng)用程序所需最低限度的電源狀態(tài)。setsystempowerstate是假定應(yīng)用程序知道所需狀態(tài),而調(diào)用setpowerrequirement是允許系統(tǒng)對(duì)電源設(shè)定做優(yōu)化以滿足應(yīng)用程序的需要。一個(gè)使用setpowerrequirement會(huì)比較方便的例子是,一個(gè)使用串口的應(yīng)用程序需要串口在進(jìn)行通信時(shí)保持住電源狀態(tài)。setpowerrequirement被定義如下。 handle setpowerrequirement (pvoid pvdevice, cedevice_power_state devicestate, ulong deviceflags, pvoid pvsystemstate, ulong stateflags); 第一個(gè)參數(shù)指定了應(yīng)用程序需要維護(hù)電源狀態(tài)的設(shè)備。devicestate參數(shù)定義了設(shè)備的電源狀態(tài)。cedevice_power_state指定了狀態(tài)范圍是從d0(意味著設(shè)備是處于******功耗狀態(tài))到d4(表示設(shè)備被關(guān)閉)(譯者注:其實(shí)d0到d4的狀態(tài)的具體表現(xiàn),完全是由oem廠商可自定義的,對(duì)應(yīng)用程序開(kāi)發(fā)者來(lái)說(shuō),比如是在d1關(guān)lcd背光還是在d2,都是不確定的,微軟只給出標(biāo)準(zhǔn)定義,而不是實(shí)際定義)。deviceflags參數(shù)由兩個(gè)標(biāo)志合并而成:power_name,表示設(shè)備名有效;power_force,表示設(shè)備應(yīng)當(dāng)維持當(dāng)前狀態(tài)甚至當(dāng)系統(tǒng)掛起時(shí)。如果pvsystemstate不為null,它表示只有對(duì)于在pvsystemstate中已命名的電源請(qǐng)求才是有效的。設(shè)備可能無(wú)法更改請(qǐng)求的狀態(tài)。 應(yīng)用程序應(yīng)當(dāng)注銷(xiāo)通過(guò)調(diào)用releasepowerrequirement來(lái)注銷(xiāo)請(qǐng)求,原型如下。 dword releasepowerrequirement (handle hpowerreq); 這里唯一的參數(shù)是從setpowerrequirement里返回的句柄。 在下一章,我將就windows ce流設(shè)備驅(qū)動(dòng)和服務(wù),繼續(xù)探討有關(guān)系統(tǒng)的問(wèn)題。盡管大多數(shù)應(yīng)用程序開(kāi)發(fā)者可能不需要寫(xiě)一些設(shè)備驅(qū)動(dòng)或服務(wù),但是知道它們是如何和程序一起工作對(duì)我們也是有啟發(fā)的。讓我們一起來(lái)看一看吧。 |