Windows CE设备驱动开发之电源管理
4.7電源管理
電源管理模塊管理設(shè)備電源,從而全面改進(jìn)操作系統(tǒng)的電源使用效率;它所有設(shè)備的電源使用,同時能與不支持電源管理的應(yīng)用程序及驅(qū)動程序共存。
使用電源管理可以有效的減少目標(biāo)設(shè)備的電源消耗,同時,能在運行、空閑、復(fù)位及掛起電源狀態(tài)時維持并保護RAM中的文件系統(tǒng)。
電源管理具有以下特性:
使設(shè)備具有自行電源管理功能的框架;
建立一種在系統(tǒng)中使設(shè)備電源在掛起和恢復(fù)狀態(tài)間切換的機制;
一個對系統(tǒng)環(huán)境、電源狀態(tài)、設(shè)備電源狀態(tài)有統(tǒng)一認(rèn)識的模塊。你可以定制電源管理模塊,使全系統(tǒng)的電源分配適合您的設(shè)備;
當(dāng)系統(tǒng)掛起或恢復(fù)時,使系統(tǒng)跳過所有代碼調(diào)用PowerOffSystem函數(shù)。
對于支持電源管理的驅(qū)動程序,在設(shè)備枚舉時應(yīng)盡量準(zhǔn)確的向電源管理模塊報告其性能,然后將收到來自電源管理模塊的獲取或更改其電源狀態(tài)的請求。對于自行管理電源的設(shè)備,必須通過DevicePowerNotify向電源管理模塊發(fā)送請求來更改電源狀態(tài)。
電源管理模塊與設(shè)備在一個正常的線程執(zhí)行環(huán)境中通過調(diào)用DeviceIoControl進(jìn)行通訊。
?
4.7.1、??????????? 電源管理架構(gòu)
在不依賴Windows CE電源管理模型的情況下,只能對設(shè)備進(jìn)行簡單的管理。電源管理器為OEM廠商提供了較大的靈活性,同時驅(qū)動開發(fā)人員也不用為了兼容電源管理模型而犧牲驅(qū)動程序性能。在基本的Windows CE電源模型中,在操作系統(tǒng)掛起或恢復(fù)時,設(shè)備會收到標(biāo)識信息(notification)。這一標(biāo)識信息在中斷處理時產(chǎn)生,所以設(shè)備在掛起狀態(tài)時可以做什么工作,有多長時間做這一工作被嚴(yán)格限制。下圖描述了Windows CE電源管理的結(jié)構(gòu)。
使用電源管理器時,設(shè)備會從I/O控制代碼(IOCTLs)收到電源狀態(tài)改變通知。因為IOCTLs在線程中執(zhí)行,在線程中驅(qū)動開發(fā)者可以更為靈活的處理電源狀態(tài)改變。使用IOCTLs還能夠區(qū)分設(shè)備電源狀態(tài)與系統(tǒng)電源狀態(tài)。這樣,在系統(tǒng)運行時可以將部分設(shè)備關(guān)閉,而某些設(shè)備也可以在系統(tǒng)掛起時一直開啟。
除了管理設(shè)備電源,電源管理器還向應(yīng)用程序通知其它與電源相關(guān)事件的發(fā)生。例如:當(dāng)系統(tǒng)從掛起狀態(tài)恢復(fù)運行時,電源管理器會向相關(guān)應(yīng)用程序發(fā)出通知。
電源管理器是一個名為pm.dll的動態(tài)鏈接庫,系統(tǒng)運行時被Device.exe進(jìn)程直接調(diào)用。當(dāng)電源管理API被調(diào)用時,Device.exe調(diào)用pm.dll的入口函數(shù)。在Platform Builder 4.0及其后續(xù)版本中提供了Pm.dll的源代碼,OEM廠商可以根據(jù)其設(shè)備修改Pm.dll。
電源管理器擔(dān)任設(shè)備、應(yīng)用程序及預(yù)定義的操作系統(tǒng)電源狀態(tài)的仲裁者。電源管理器定義了下列規(guī)則,使上述三部分以這些規(guī)則進(jìn)行通訊:
l???????? 系統(tǒng)電源狀態(tài)限定了所有設(shè)備的最大功耗;
l???????? 應(yīng)用程序以最小功耗來獲取指定設(shè)備的最低性能等級。
l???????? 當(dāng)設(shè)備功耗在其最大功耗與最小功耗范圍內(nèi)時,電源管理器允許設(shè)備自行管理其電源。
l???????? 如果最小功耗高于最大功耗,那么,在應(yīng)用程序請求設(shè)備運行期間,設(shè)備電源將持續(xù)提升。
l???????? 設(shè)備可以在一個或多個電源狀態(tài)下運行。電源狀態(tài)以有限的數(shù)字表示。詳見設(shè)備電源狀態(tài)章節(jié)。
l???????? 系統(tǒng)轉(zhuǎn)為掛起狀態(tài)后,對應(yīng)用程序有用的最小功耗將被取消。
l???????? 系統(tǒng)電源狀態(tài)是描述所有設(shè)備中最大的設(shè)備電源狀態(tài)。系統(tǒng)電源狀態(tài)由OEM廠商定義,并在注冊表中描述,同時,在電源管理器中可以加入部分支持代碼。OEM廠商可以定義任意數(shù)量的系統(tǒng)電源狀態(tài)。詳見系統(tǒng)電源狀態(tài)章節(jié)。
在電源管理器框架內(nèi)部,OEM廠商可以定義系統(tǒng)電源狀態(tài)來設(shè)定最大設(shè)備電源狀態(tài)。設(shè)備調(diào)用DevicePowerNotify來控制其電源等級,應(yīng)用程序調(diào)用SetPowerRequirement來確認(rèn)它們需要使用的設(shè)備是否正在合適的性能等級運行。
?
4.7.1.1????????????? 電源管理器和ACPI/APM
電源管理器并不涉及高級配置與電源接口(ACPI)或高級電源管理(APM)。ACPI規(guī)范將系統(tǒng)電源狀態(tài)定義為一個從高功率/高性能到低功率/低性能的線性集。Windows CE電源管理器允許OEM廠商定義任意數(shù)目的系統(tǒng)電源狀態(tài),但并不要求定義的系統(tǒng)電源狀態(tài)是線性的。
我們鼓勵開發(fā)者根據(jù)情況定義操作系統(tǒng)電源狀態(tài),并根據(jù)設(shè)備定位或環(huán)境控制設(shè)備電源。例如:開發(fā)者可以定義系統(tǒng)電源狀態(tài),據(jù)此可以做到在裝置不在支架(cradle)中時可以關(guān)閉某些設(shè)備,或者當(dāng)系統(tǒng)使用外接交流電源時允許設(shè)備運行在高功耗電源等級。同樣的,開發(fā)者可以根據(jù)系統(tǒng)環(huán)境定義不同的空閑、掛起狀態(tài)。開發(fā)者需要定制電源管理器并保證在適當(dāng)或必須的時候在各種電源狀態(tài)間切換。
系統(tǒng)電源狀態(tài)與ACPI模式有顯著的區(qū)別。然而,設(shè)備電源狀態(tài)表面上看起來與ACPI規(guī)范中的設(shè)備電源狀態(tài)類似,但實際上,他們?nèi)杂屑?xì)微的區(qū)別。例如:在Windows CE中D3電源狀態(tài)被設(shè)定為在操作系統(tǒng)掛起時可使指定設(shè)備擔(dān)任喚醒源的功能。
4.7.1.2????????????? 電源掛起、恢復(fù)回調(diào)函數(shù)
掛起和恢復(fù)電源事件的回調(diào)函數(shù)與電源管理器無關(guān)。當(dāng)CPU被停止,操作系統(tǒng)將進(jìn)入掛起狀態(tài),這時回調(diào)函數(shù)會被系統(tǒng)調(diào)用。并在OEMPowerOff被調(diào)用前立即執(zhí)行。在電源管理器請求關(guān)閉系統(tǒng)電源并進(jìn)入掛起狀態(tài)之前,電源管理器會時常對設(shè)備驅(qū)動進(jìn)行IOCTL調(diào)用。當(dāng)然,情況并不總是這樣。電源管理器框架允許設(shè)備在系統(tǒng)運行時被關(guān)閉,也允許設(shè)備在系統(tǒng)掛起時處于開啟狀態(tài)。
當(dāng)設(shè)備電源狀態(tài)為D0,D1或D2,如果掉電事件發(fā)生時,開發(fā)者可以自行決定進(jìn)行何種處理。此時,通常關(guān)閉設(shè)備電源,并在加電事件發(fā)生時恢復(fù)供電。如果設(shè)備可以不依賴CPU即可運行,在掛起狀態(tài)時或許可以使此設(shè)備運行。如果設(shè)備在掛起期間一直處于供電狀態(tài),那可能是電源管理器配置錯誤,或者是應(yīng)用程序使用POWER_FORCE標(biāo)記對此設(shè)備進(jìn)行了SetPowerRequirement調(diào)用。
?
4.7.1.3????????????? 其他電源管理API
電源管理器創(chuàng)建于標(biāo)準(zhǔn)的Windows CE電源體系結(jié)構(gòu)的上層。所以,不管電源管理器如何運行,流接口設(shè)備驅(qū)動程序在系統(tǒng)掛起或恢復(fù)時總是通過XXX_PowerUp和XXX_PowerDown獲取通知。下表列出了與電源管理相關(guān)的API。
| 函數(shù)名 | 功能描述 |
| GetSystemPowerStatusEx2 | 獲取電池狀態(tài)信息。 |
| PowerPolicyNotify | 以事件的形式通知電源管理器,以便執(zhí)行必要的處理,從而實現(xiàn)OEM創(chuàng)建的電源策略。 |
| OEMIdle | 被系統(tǒng)內(nèi)核調(diào)用。在沒有線程需要運行時將處理器置為空閑狀態(tài)。 |
| OEMPowerOff | 當(dāng)關(guān)機按鈕被按下,或圖形、窗體、事件子系統(tǒng)(GWES)超時時被調(diào)用。使處理器進(jìn)入掛起狀態(tài)。 |
| XXX_PowerDown (Device Manager) | 掛起設(shè)備電源。僅用于能被軟件控制關(guān)閉的設(shè)備。 |
| XXX_PowerUp (Device Manager) | 恢復(fù)設(shè)備電源。 |
?
Windows CE設(shè)備驅(qū)動開發(fā)之電源管理??????第二部分
4.7.2、電源狀態(tài)
電源管理器期望所有被管理的設(shè)備能支持一個或多個設(shè)備電源狀態(tài)。設(shè)備電源狀態(tài)的數(shù)量是有限的。設(shè)備必須通知電源管理器其功耗特性。設(shè)備常以功耗換取性能。
電源管理器在OEM定義的系統(tǒng)電源狀態(tài)下管理設(shè)備電源狀態(tài)。系統(tǒng)電源狀態(tài)在注冊表中定義,可以用任意數(shù)字定義。系統(tǒng)電源狀態(tài)會給設(shè)備電源狀態(tài)設(shè)置一個上限。
某些應(yīng)用程序可能需要特定設(shè)備保持運行在指定的設(shè)備功率等級上。例如:當(dāng)一個音頻播放程序在播放音樂時,可能需要網(wǎng)卡及音頻解碼器保持運行在高功率等級。視頻播放程序可能需要網(wǎng)絡(luò)、音頻,同時可能要使顯示設(shè)備在進(jìn)入屏幕保護模式后一直顯示,并保持背光常亮。應(yīng)用程序可以請求電源管理器設(shè)置最小設(shè)備電源狀態(tài),電源管理器會調(diào)用SetPowerRequirement和ReleasePowerRequirement系統(tǒng)API來進(jìn)行設(shè)置。
4.7.2.1????????????? 設(shè)備電源狀態(tài)
設(shè)備電源狀態(tài)是預(yù)定義的靜態(tài)值。電源管理器將設(shè)備狀態(tài)傳給驅(qū)動程序,驅(qū)動程序負(fù)責(zé)將其映射為自身的設(shè)備性能,然后在物理設(shè)備上進(jìn)行狀態(tài)轉(zhuǎn)換。
下表是對各種設(shè)備電源狀態(tài)的描述。
| 設(shè)備電源狀態(tài) | 注冊表鍵值 | 描述 |
| Full on | D0 | 此狀態(tài)表示設(shè)備已開啟或正在運行。設(shè)備將以系統(tǒng)允許的最大功耗及最高性能運行。 |
| Low on | D1 | 此狀態(tài)表示設(shè)備已開啟或正在運行,但以低于D0狀態(tài)的功耗及性能運行。D1狀態(tài)適用于設(shè)備已經(jīng)被使用,但以較低的性能運行即可,沒有必要以最大性能運行,會產(chǎn)生額外的功率消耗。 |
| Standby | D2 | 此狀態(tài)表示設(shè)備被部分供電,保證設(shè)備在需要時能自動喚醒。 |
| Sleep | D3 | 睡眠狀態(tài)。保證喚醒的最小供電,在需要時能自動喚醒并初始化。 |
| Off | D4 | 關(guān)閉狀態(tài),不供電。 |
一種物理設(shè)備并不能支持上述所有的設(shè)備電源狀態(tài)。但是,所有的設(shè)備都必須支持D0設(shè)備電源狀態(tài)。如果驅(qū)動程序收到請求,要求其將設(shè)備進(jìn)入它不支持的電源狀態(tài),驅(qū)動程序應(yīng)使設(shè)備進(jìn)入下一個支持的電源狀態(tài)。例如:電源管理器請求設(shè)備進(jìn)入D2電源狀態(tài),但設(shè)備并不支持D2狀態(tài),這時如果設(shè)備支持D3或D4狀態(tài),驅(qū)動程序應(yīng)使設(shè)備進(jìn)入D3或D4狀態(tài)。如果某一設(shè)備需要進(jìn)入D3狀態(tài),但是此設(shè)備卻不能喚醒系統(tǒng),那么應(yīng)使此設(shè)備進(jìn)入D4狀態(tài)。上述這些規(guī)則可以使驅(qū)動程序的執(zhí)行簡單化。
電源管理器有選擇的將系統(tǒng)電源狀態(tài)映射為對應(yīng)的設(shè)備電源狀態(tài)。例如:如果設(shè)備僅支持D0及D4電源狀態(tài),那么,電源管理器不會直接請求設(shè)備進(jìn)入D4電源狀態(tài)。如果D3或D4被設(shè)為此設(shè)備的最小電源狀態(tài),電源管理器會一直等待直到系統(tǒng)進(jìn)入D3或D4狀態(tài)時,再將設(shè)備設(shè)為D4狀態(tài)。如果此設(shè)備的最小電源狀態(tài)被設(shè)為D0、D1或D2,電源管理器將使設(shè)備一直運行于D0狀態(tài)。
當(dāng)設(shè)備驅(qū)動程序被加載時,應(yīng)將設(shè)備設(shè)為D0狀態(tài)。在驅(qū)動程序被卸載時,應(yīng)將設(shè)備設(shè)為D4狀態(tài)。如果在啟動時設(shè)備進(jìn)入了D0外的其他設(shè)備電源狀態(tài),那么可以在處理IOCTL_POWER_CAPABILITIES時發(fā)出一個DevicePowerNotify請求。
?
4.7.2.2????????????? 系統(tǒng)電源狀態(tài)
系統(tǒng)電源狀態(tài)由OEM定義,并由OEM引用。OEM可以將其命名為像On,SystemIdle,OnBattery,InCradle,OutOfCradle等名稱。這些名稱并沒有被系統(tǒng)預(yù)定義,也不要求將其定義為線性序列。系統(tǒng)電源狀態(tài)在系統(tǒng)配置注冊表鍵中定義。Windows CE并沒有限制可以定義多少種系統(tǒng)電源狀態(tài)。
當(dāng)然,也可以創(chuàng)建系統(tǒng)電源狀態(tài)與預(yù)定義的設(shè)備電源狀態(tài)的顯式映射。顯式映射需要在注冊表中定義。系統(tǒng)電源狀態(tài)明確的制定系統(tǒng)中所有設(shè)備的最大設(shè)備電源狀態(tài)。
電源管理器示例定義了On,UserIdle,SystemIdle及Suspend四種系統(tǒng)電源狀態(tài)。當(dāng)用戶使用系統(tǒng)時,電源狀態(tài)設(shè)為On。如果用戶停止使用,電源狀態(tài)被設(shè)為UserIdle。當(dāng)用戶在一定的周期內(nèi)(如30s)不使用系統(tǒng),則進(jìn)入SystemIdle狀態(tài);只要設(shè)備驅(qū)動程序處于活動狀態(tài),系統(tǒng)將一直保持在SystemIdle狀態(tài)。如果設(shè)備驅(qū)動程序停止活動,系統(tǒng)進(jìn)入Suspend狀態(tài)。
UserIdle狀態(tài)用于用戶正在使用設(shè)備,但卻沒有操作設(shè)備。例如,用戶一直觀看屏幕顯示,但沒有手動操作。SystemIdle狀態(tài)被用于用戶沒有直接使用設(shè)備,但處理器仍在繼續(xù)運行。例如,在傳輸文件期間,用戶可能人為設(shè)備已處于空閑狀態(tài),但實際上處理器依舊在持續(xù)運行,直到文件傳輸完成。
電源管理器示例實現(xiàn)了根據(jù)UserActivity和SystemActivity定時器對用戶及系統(tǒng)活動進(jìn)行判斷。在定時器超時后,根據(jù)當(dāng)前系統(tǒng)供電狀況(使用外接電源或電池)進(jìn)行不同的系統(tǒng)電源狀態(tài)切換。
Platform Builder提供的Windows CE運行時image示例均使用外接電源供電模式。你可以選擇實現(xiàn)一套在使用電池供電時的電源狀態(tài)。復(fù)制電源管理器示例代碼的PDD目錄,并對其做適當(dāng)?shù)男薷募纯伞?/span>
4.7.2.2.1?? 將系統(tǒng)電源狀態(tài)映射為設(shè)備電源狀態(tài)
在注冊表系統(tǒng)配置中明確定義系統(tǒng)電源狀態(tài)名稱。系統(tǒng)電源狀態(tài)到設(shè)備電源狀態(tài)的映射在注冊表的每一個電源狀態(tài)名稱鍵值下被枚舉。如下示例代碼:
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Power/State/Example] ??? Default=dword:0; D0 ??? Flags=dword:10000; POWER_STATE_ON ??? COM1:=dword1; D1上面的注冊表片段定義了名為Example的系統(tǒng)電源狀態(tài),并設(shè)置了除COM1:被限制為最高運行于D1設(shè)備電源狀態(tài)外,其他的所有設(shè)備最高均可運行于D0設(shè)備電源狀態(tài)。其中Flags列是一個標(biāo)識碼,用于表示Pm.h頭文件中定義的POWER_STATE_ON標(biāo)記。如果需要,OEM可以定義自己的電源狀態(tài)標(biāo)記。
下表列出了鍵值名稱及其描述。
| 鍵名 | 描述 |
| Name | 系統(tǒng)電源狀態(tài)名稱 |
| Flags | 標(biāo)識碼。用于表示在Pm.h頭文件中預(yù)定義的類似于POWER_STATE_ON的標(biāo)記。 |
| Default | 表示在此系統(tǒng)電源狀態(tài)下時,所有設(shè)備的默認(rèn)設(shè)備電源狀態(tài)。此鍵值用數(shù)字表示,0代表D0,1代表D1,以此類推。 |
| DeviceName | 設(shè)置在此系統(tǒng)電源狀態(tài)下指定設(shè)備的最大設(shè)備電源狀態(tài)。可以對任意數(shù)目的設(shè)備進(jìn)行定義。 |
?
電源管理器支持多種設(shè)備類型的映射。例如:NDIS迷你接口及塊設(shè)備驅(qū)動器設(shè)備類型在Pm.h中會被指定為其自身的GUID類型。其他類型被管理設(shè)備的默認(rèn)值也可以在注冊表中指定。例如:
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Power/State/Example/{98C5250D-C29A-4985-AE5F-AFE5367E5006}] ??? Default=dword:1; D1 ??? "CISCO1"=dword:0; D0上面注冊表片段設(shè)置電源管理器限值所有NDIS迷你接口設(shè)備在Example系統(tǒng)電源狀態(tài)下時均運行于D1設(shè)備電源狀態(tài),只有名為CISCO1的設(shè)備最高可運行于D0狀態(tài)。
?
4.7.2.2.2?? 系統(tǒng)電源狀態(tài)切換
電源管理器在下列情況下進(jìn)行系統(tǒng)電源狀態(tài)切換:
l???????? OEM定義的狀態(tài)切換事件發(fā)生。
l???????? 應(yīng)用程序調(diào)用SetSystemPowerState。
OEM定義的事件可能包含設(shè)備供電從外接電源切換為使用電池供電,延長系統(tǒng)空閑周期,將設(shè)備插入底座(Cradle),電池電量低等。OEM需要根據(jù)情況修改電源管理器,以便判斷兩種系統(tǒng)電源狀態(tài)間的切換是否合理,并在必要時切換系統(tǒng)電源狀態(tài)。Platform Builder提供的電源管理器源代碼僅支持在設(shè)備從外接電源切換為使用電池供電時進(jìn)行系統(tǒng)電源狀態(tài)切換。
應(yīng)用程序可以使用系統(tǒng)電源狀態(tài)名或表示系統(tǒng)電源狀態(tài)的數(shù)值為參數(shù)調(diào)用SetSystemPowerState函數(shù)。如果應(yīng)用程序了解OEM定義的系統(tǒng)電源狀態(tài),那么可以選擇使用電源狀態(tài)名進(jìn)行顯式調(diào)用。對于獨立于平臺的應(yīng)用程序,則設(shè)置數(shù)值進(jìn)行調(diào)用,并允許電源管理器決定如何進(jìn)行電源狀態(tài)映射。電源管理器可對應(yīng)用程序能請求的狀態(tài)進(jìn)行限制。
?
4.7.2.2.3?? 系統(tǒng)電源狀態(tài)示例
下面的注冊表片段是表示系統(tǒng)電源狀態(tài)到設(shè)備電源狀態(tài)映射的示例。
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Power/State/On] ??? "Default"=dword:0?????????? ; D0 ??? "Flags"=dword:10000???????? ; POWER_STATE_ON [HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Power/State/UserIdle] ??? "Default"=dword:1?????????? ; D1 ??? "Flags"=dword:0 [HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Power/State/SystemIdle] ??? "Default"=dword:2?????????? ; D2 ??? "Flags"=dword:0 [HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Power/State/Suspend] ??? "Default"=dword:3?????????? ; D3 ??? "Flags"=dword:200000??????? ; POWER_STATE_SUSPEND ; @CESYSGEN IF CE_MODULES_NDIS [HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Power/State/Suspend/{98C5250D-C29A-4985-AE5F-AFE5367E5006}] ??? "Default"=dword:4?????????? ; D4 ; @CESYSGEN ENDIF CE_MODULES_NDIS下表描述了上面注冊表片段的映射方式。
| 系統(tǒng)電源狀態(tài) | 設(shè)備電源狀態(tài) |
| On | D0 |
| UserIdle | D1 |
| SystemIdle | D2 |
| Suspend | D3。NDIS迷你接口單獨被映射為D4。 |
當(dāng)系統(tǒng)使用上面的注冊表配置,并進(jìn)入Suspend狀態(tài),除了NDIS迷你接口會被關(guān)閉外,其他可喚醒源都將處于可激活狀態(tài)。如果有設(shè)備不支持D3狀態(tài),它將自動進(jìn)入D4狀態(tài)。
應(yīng)用程序可以使用SetPowerRequirement創(chuàng)建設(shè)備電源要求。也可以使用電源管理器控制面板程序創(chuàng)建附加的設(shè)備電源要求。
?
4.7.2.3????????????? 設(shè)備及系統(tǒng)電源狀態(tài)名稱
電源管理器要求使用小寫字母命名設(shè)備及系統(tǒng)電源狀態(tài)名稱。一些類似于wsprintf(buf, "%u", n)或不區(qū)分大小寫的比較這樣的操作,會涉及區(qū)位表(Locale table)查詢。區(qū)位表(Locale table)在Wince.nls內(nèi)存映射文件中被實現(xiàn)。在掛起期間,電源管理器不能使用FileSystemPowerFunction訪問文件系統(tǒng)。從掛起的線程中訪問文件系統(tǒng)可能造成操作系統(tǒng)死鎖。如果Wince.nls中必須的頁面無法在內(nèi)存中找到,就會產(chǎn)生死鎖。
在處理API調(diào)用時,電源管理器將名稱轉(zhuǎn)換為小寫字母。然而,在掛起及恢復(fù)狀態(tài)時,電源管理器在文件系統(tǒng)操作被禁止后訪問注冊表。這時不能將注冊表設(shè)置項轉(zhuǎn)換為小寫。所以必須將系統(tǒng)電源狀態(tài)注冊表設(shè)置改為小寫字母。例如:WAV1:應(yīng)被描述為wav1:。其他類似于注冊表HKLM/Drivers/Builtin下的用于控制設(shè)備驅(qū)動加載的設(shè)置項不用修改。
Windows CE設(shè)備驅(qū)動開發(fā)之電源管理 第三部分?
4.7.3、電源管理器接口
電源管理器有三種不同的使用者。
l???????? 電源管理器能識別的設(shè)備的驅(qū)動程序。
l???????? 可能需要更改系統(tǒng)電源狀態(tài)或設(shè)備性能的應(yīng)用程序。
l???????? 需要電源事件通知的應(yīng)用程序。
電源管理器使用不同的編程接口與這些使用者進(jìn)行通訊。
4.7.3.1????????????? 設(shè)備驅(qū)動接口
電源管理器使用兩種不同的機制與支持電源管理的設(shè)備驅(qū)動進(jìn)行通訊。電源管理器向下調(diào)用設(shè)備驅(qū)動確定其設(shè)備性能,并更新其設(shè)備電源狀態(tài)。設(shè)備向上調(diào)用電源管理器請求進(jìn)行設(shè)備電源狀態(tài)更改。向下調(diào)用在系統(tǒng)中以IOCTL方式實現(xiàn)。設(shè)備通過DevicePowerNotify API函數(shù)向上調(diào)用電源管理器。
由于電源管理器使用DeviceIoControl與支持電源管理的設(shè)備進(jìn)行通訊,所以設(shè)備需要實現(xiàn)一個外部(expose)流接口。在某些情況下,可以用電源管理代理來實現(xiàn)外部流接口。網(wǎng)絡(luò)驅(qū)動接口規(guī)約(NDIS)中實現(xiàn)了一個外部流接口,從而能使用RegisterPowerRelationship API函數(shù)進(jìn)行對NDIS迷你接口的代理管理。電源管理器同時提供了一種與非流接口設(shè)備的通訊機制。這一方法由具有打開設(shè)備句柄、發(fā)送請求等功能的抽象層組成。例如:位于Public/Common/Oak/Drivers/Pm/Mdd/Pmdisplay.cpp的驅(qū)動程序?qū)崿F(xiàn)了一個基于ExtEscape函數(shù)的通訊接口。
打開名稱格式為COM1:、并實現(xiàn)了外部流接口的標(biāo)準(zhǔn)設(shè)備,可以對其進(jìn)行讀寫。但是,電源管理器并不要求支持電源管理的設(shè)備必須使用這種命名格式;設(shè)備名稱可以是任意唯一的字符串。例如:NDIS迷你接口可以被命名為VMINI1。
盡管Platform Builder提供的電源管理器僅支持流接口驅(qū)動,但OEM可以自由的實現(xiàn)其他的設(shè)備接口。可以為設(shè)備定義一個新的唯一類型全局標(biāo)識符(GUID)來實現(xiàn)新的接口。不過,驅(qū)動程序在使用新接口時必須遵循標(biāo)準(zhǔn)電源管理設(shè)備驅(qū)動準(zhǔn)則。
默認(rèn)情況下,電源管理器可以發(fā)現(xiàn)下列GUID表示的設(shè)備類型:
l???????? {A32942B7-920C-486b-B0E6-92A702A99B35} 此GUID類型為普通被管理設(shè)備。
l???????? {8DD679CE-8AB4-43c8-A14A-EA4963FAA715} 此GUID類型為塊設(shè)備。
l???????? {98C5250D-C29A-4985-AE5F-AFE5367E5006} 此GUID類型為NDIS設(shè)備。
應(yīng)用程序可以從HKEY_LOCAL_MACHINE/System/CurrentControlSet/Control/Power /Interfaces注冊表鍵中獲取可被管理的設(shè)備類型的列表。
當(dāng)應(yīng)用程序調(diào)用一個引用了指定設(shè)備的電源管理器API時,應(yīng)用程序必須指定設(shè)備的GUID類型名。如果沒有指定設(shè)備的GUID類型名,電源管理器會假定此設(shè)備為普通被管理設(shè)備類型。
有效的設(shè)備類型名需要有GUID前綴及反斜杠符號。例如:GUID {8DD679CE-8AB4-43c8-A14A-EA4963FAA715}/DSK1:表示引用一個名為DSK1的塊設(shè)備。
電源管理器從注冊表讀取設(shè)備類型列表,使用RequestPowerNotifications決定此類型的設(shè)備在什么時候被載入。下面時設(shè)備類型列表的示例。
[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附帶的電源管理器以上述設(shè)置執(zhí)行。如果不定義新的設(shè)備注冊表鍵,在注冊表中可以不包含上述設(shè)置。下面步驟說明了實現(xiàn)一個表示使用ExtEscape直接管理的顯示驅(qū)動類型的過程。
1.???? 使用Guidgen.exe創(chuàng)建一個新的GUID類型,并將其添加到注冊表中。
2.???? 為了識別GUID,需要修改電源管理器,并使用ExtEscape與設(shè)備通訊。
3.?????? 調(diào)用AdvertiseInterface,使用新的GUID修改顯示驅(qū)動。
?
4.7.3.1.1???? IOCTL設(shè)備控制符
電源管理器使用下列IOCTL碼與設(shè)備通訊:
| IOCTL | 功能 |
| IOCTL_POWER_CAPABILITIES | 要求設(shè)備通知電源管理器它所支持的電源狀態(tài)及其特性。 |
| IOCTL_POWER_SET | 要求設(shè)備更新其設(shè)備電源狀態(tài)。 |
| IOCTL_POWER_QUERY | 詢問設(shè)備是否準(zhǔn)備好可以進(jìn)入另外一個設(shè)備電源狀態(tài)。 |
| IOCTL_POWER_GET | 要求設(shè)備通知電源管理器它現(xiàn)在的設(shè)備電源狀態(tài)。 |
| IOCTL_REGISTER_POWER_RELATIONSHIP | 通知父設(shè)備登記它所控制的所有設(shè)備。 |
?
4.7.3.1.2???? 驅(qū)動到電源管理器的API函數(shù)
電源管理器為被管理設(shè)備提供下列函數(shù),設(shè)備可以通過調(diào)用下列函數(shù)相電源管理器請求服務(wù)。
| 函數(shù)名 | 功能 |
| DevicePowerNotify | 設(shè)備驅(qū)動調(diào)用此函數(shù)請求電源管理器更新其設(shè)備電源狀態(tài)。 |
| RegisterPowerRelationship | 總線驅(qū)動及其他代理電源管理器在需要攔截所有設(shè)備的電源IOCTL時調(diào)用此函數(shù)。 |
| ReleasePowerRelationship | 結(jié)束由RegisterPowerRelationship調(diào)用創(chuàng)建的代理關(guān)系。 |
?
4.7.3.2????????????? 應(yīng)用程序接口
電源管理器提供了一些函數(shù),使應(yīng)用程序可以使用這些函數(shù)進(jìn)行設(shè)備電源管理。下表中的API函數(shù)中,只有GetSystemPowerState、SetPowerRequirement及ReleasePowerRequirement是普通應(yīng)用程序可以直接執(zhí)行的。例如:應(yīng)用程序可以調(diào)用SetSystemPowerState來掛起系統(tǒng),但是電源管理器可以限制應(yīng)用程序可以請求進(jìn)入的系統(tǒng)電源狀態(tài)。其他的API函數(shù)是為像控制面板這樣的OEM應(yīng)用程序準(zhǔn)備的。下表是這些函數(shù)的說明。
| 函數(shù)名 | 功能 |
| GetSystemPowerState | 返回當(dāng)前系統(tǒng)電源狀態(tài)的名稱。 |
| SetSystemPowerState | 請求電源管理器更改當(dāng)前系統(tǒng)電源狀態(tài)。 |
| SetPowerRequirement | 請求電源管理器將指定設(shè)備的電源狀態(tài)維持在最小等級。 |
| ReleasePowerRequirement | 釋放SetPowerRequirement設(shè)置的電源狀態(tài).將設(shè)備電源狀態(tài)恢復(fù)到調(diào)用SetPowerRequirement之前的狀態(tài)。 |
| GetDevicePower | 返回指定設(shè)備的當(dāng)前電源狀態(tài)。 |
| SetDevicePower | 請求電源管理器更改指定設(shè)備的當(dāng)前電源狀態(tài)。 |
?
4.7.3.2.1?? 系統(tǒng)電源狀態(tài)設(shè)置
某些情況下,應(yīng)用程序需要更改系統(tǒng)電源狀態(tài)。在特定的Windows CE設(shè)備上,應(yīng)用程序并不知道哪些電源狀態(tài)可用,也不期望知道這些電源狀態(tài)的特性。對應(yīng)用程序而言,最好使用描述電源狀態(tài)的掩碼來調(diào)用SetSystemPowerState進(jìn)行電源狀態(tài)切換,而不要使用明確的狀態(tài)名調(diào)用。電源管理器會將此掩碼轉(zhuǎn)換為對應(yīng)的電源狀態(tài)。例如:應(yīng)用程序可以使用POWER_STATE_SUSPEND位元請求進(jìn)行系統(tǒng)電源狀態(tài)切換。根據(jù)在請求時系統(tǒng)是否在支架(cradle)中,電源管理器隨后會切換到Suspend或SuspendCradle狀態(tài)。如果設(shè)備被從支架中取下,電源管理器會將設(shè)備切換到Suspend狀態(tài)。
電源管理器可以限定應(yīng)用程序可以設(shè)置進(jìn)入哪些系統(tǒng)電源狀態(tài)。例如:如果電源管理器使用外部輸入控制系統(tǒng)電源狀態(tài),那么,當(dāng)系統(tǒng)使用電池供電時,將不會允許進(jìn)入ACRun狀態(tài)。Platform Builder附帶的電源管理器僅允許應(yīng)用程序設(shè)置系統(tǒng)進(jìn)入Suspend狀態(tài)。
下表描述了預(yù)定義的電源狀態(tài)位元及其含義。
| 位元 | 描述 |
| POWER_STATE_ON | 高性能高功耗。 |
| POWER_STATE_OFF | 所有設(shè)備都被關(guān)閉。 |
| POWER_STATE_CRITICAL | 電池低電量。 |
| POWER_STATE_BOOT | 系統(tǒng)正在啟動。 |
| POWER_STATE_IDLE | 空閑狀態(tài)。 |
| POWER_STATE_RESET | 清除文件,關(guān)閉設(shè)備并調(diào)用KernelIoControl. |
| POWER_STATE_SUSPEND | 掛起操作系統(tǒng)并最終調(diào)用OEMPowerOff. |
Platform Builder附帶的電源管理器并沒有使用上表中全部狀態(tài)。OEM可以根據(jù)其設(shè)備自行定義狀態(tài)標(biāo)記。
如果應(yīng)用程序使用SetSystemPowerState請求進(jìn)入一個新的電源狀態(tài),電源管理器將進(jìn)行以下處理:
l???????? 廣播PBT_TRANSITION通知。
l???????? 如果需要更新所有設(shè)備的電源狀態(tài)。如果設(shè)備已處于一個可被新的電源狀態(tài)接受的電源狀態(tài)下,電源管理器就不會進(jìn)行IOCTL_POWER_SET請求。
l???????? 如果設(shè)備從掛起狀態(tài)恢復(fù),電源管理器廣播PBT_RESUME通知。
?
4.7.3.2.2?? 設(shè)備電源需求
在某些情況下應(yīng)用程序需要改變電源管理器對系統(tǒng)電源狀態(tài)的管理。例如:某頁面調(diào)度程序需要使COM3:保持運行在D3或更高的狀態(tài),即使在掛起時也以此電源狀態(tài)運行,從而在COM3:收到一個輸入頁時能喚醒系統(tǒng)。或者,例如一個流音頻程序可能需要網(wǎng)卡及音頻系統(tǒng)即便在系統(tǒng)使用電池供電,并以及空閑了一段時間的情況下也能保持在全功耗(Full Power)運行。電源管理器提供SetPowerRequirement API函數(shù)為有特定電源管理需求的應(yīng)用程序提供支持。
SetPowerRequirement API函數(shù)允許應(yīng)用程序請求電源管理器在設(shè)備電源狀態(tài)上設(shè)置一個較低的下限。如果電源要求有效,電源管理器則不允許設(shè)備將自己的電源狀態(tài)設(shè)為低于要求的下限值。當(dāng)電源管理器更改系統(tǒng)電源狀態(tài)時,如果設(shè)備需要維持在高于系統(tǒng)電源狀態(tài)所允許的設(shè)備電源狀態(tài),電源管理器通常會使設(shè)備保持此電源狀態(tài)。
當(dāng)系統(tǒng)掛起時設(shè)備的電源需求通常會被取消。當(dāng)系統(tǒng)處于掛起狀態(tài)時,CPU將停止運行,中斷服務(wù)也將停止。如果應(yīng)用程序需要設(shè)備在掛起狀態(tài)時能繼續(xù)運行,可以在調(diào)用SetPowerRequirement時設(shè)置POWER_FORCE標(biāo)記。進(jìn)行此操作需要對應(yīng)的設(shè)備驅(qū)動程序支持在系統(tǒng)掛起時自行停用。
電源管理器可能取消其他環(huán)境下的設(shè)備電源需求。例如,OEM廠商可能會重新解釋系統(tǒng)電源狀態(tài)POWER_STATE_CRITICAL標(biāo)記,以便指示系統(tǒng)在使用電池供電,且電池處于低電量臨界時,應(yīng)關(guān)閉所有設(shè)備。
?
4.7.3.3????????????? 通知接口
電源管理器提供了一組API函數(shù),從而允許應(yīng)用程序獲取電源相關(guān)事件的通知,并參與決策系統(tǒng)電源狀態(tài)的切換。下表列出了相關(guān)的API函數(shù)。
| 函數(shù) | 描述 |
| RequestPowerNotifications | 請求電源管理器發(fā)送電源事件通知。 |
| StopPowerNotifications | 取消由RequestPowerNotifications發(fā)出的通知請求。 |
通知信息通過消息隊列傳遞。為了使用通知,應(yīng)用程序需要創(chuàng)建一個消息隊列,并通過RequestPowerNotifications API函數(shù)將消息隊列句柄傳遞給電源管理器。通常將創(chuàng)建一個線程來監(jiān)控消息隊列,等待消息產(chǎn)生。
電源管理器定義了以下幾種通知類型。
| 通知 | 描述 |
| PBT_RESUME | 當(dāng)系統(tǒng)從掛起狀態(tài)恢復(fù)時產(chǎn)生。 |
| PBT_POWERSTATUSCHANGE | 當(dāng)系統(tǒng)在AC供電及其他供電方式(如電池)間切換時產(chǎn)生。 |
| PBT_TRANSITION | 當(dāng)電源管理器進(jìn)行系統(tǒng)電源狀態(tài)變更時產(chǎn)生。 |
?
Windows CE設(shè)備驅(qū)動開發(fā)之電源管理 第四部分
4.7.4、設(shè)備電源管理指南
電源管理器對設(shè)備功耗、性能及響應(yīng)時間并沒有進(jìn)行嚴(yán)格的限制。只是在用戶角度而言D0及D1狀態(tài)下是可操作的,而更高編號的電源狀態(tài)比D0及D1消耗更少的電源。
本指南的目的是為了使OEM廠商能更容易的定義有意義的系統(tǒng)電源狀態(tài),而不用了解特定設(shè)備的詳細(xì)功耗要求。
4.7.4.1????????????? 設(shè)備電源自管理(Device Power Self-Management)
一些設(shè)備自行管理其電源的過程可能比較復(fù)雜。當(dāng)設(shè)備處于休止?fàn)顟B(tài)時,驅(qū)動程序開發(fā)人員希望能降低它們的功耗。降低功耗一般會同時降低設(shè)備性能,所以當(dāng)這些設(shè)備被使用時,也需要提升其性能等級。提升性能的同時也會增大設(shè)備功耗。
這些設(shè)備往往根據(jù)其被使用頻繁程度來動態(tài)的提升或降低其設(shè)備電源狀態(tài)。但電壓自管理的實際算法根據(jù)設(shè)備特性的不同而不同。
電源管理器的DevicePowerNotify API函數(shù)允許驅(qū)動開發(fā)人員請求電源管理器調(diào)整設(shè)備的電源狀態(tài)。如果所請求的設(shè)備電源狀態(tài)在允許的范圍內(nèi)(即最大及最小值之間),電源管理器將允許對設(shè)備電源狀態(tài)的調(diào)整。最大值為系統(tǒng)電源狀態(tài)要求的值,最小值由應(yīng)用程序調(diào)用SetPowerRequirement API設(shè)定。
如果電源管理器設(shè)備請求的電源狀態(tài)調(diào)整,電源管理器將調(diào)用對應(yīng)的設(shè)備API更新設(shè)備電源狀態(tài),如:使用設(shè)備的IOCTL_POWER_SET函數(shù)。在調(diào)用DevicePowerNotify函數(shù)時,需要遵循以下要求:
l???????? 當(dāng)DevicePowerNotify調(diào)用成功后設(shè)備不能立即更新其電源狀態(tài),直到IOCTL_POWER_SET被引發(fā)時才能更新。
l???????? 驅(qū)動開發(fā)人員不能認(rèn)為DevicePowerNotify調(diào)用成功就意味著電源管理器一定會引發(fā)IOCTL_POWER_SET。
l???????? 驅(qū)動開發(fā)人員不能認(rèn)為IOCTL_POWER_SET會被作為DevicePowerNotify調(diào)用的結(jié)果而被立即引發(fā)。
l???????? 當(dāng)能夠喚醒系統(tǒng)的設(shè)備進(jìn)入D3狀態(tài)后,不應(yīng)再使用DevicePowerNotify來請求D3狀態(tài)。
一些設(shè)備能夠支持D0到D4設(shè)備電源狀態(tài)以外的其他電源等級。如果需要,驅(qū)動開發(fā)人員可以將此類設(shè)備的多個電源等級映射到電源管理器所能識別的某一設(shè)備電源狀態(tài)。設(shè)備可以不依賴電源管理器在每個設(shè)備電源狀態(tài)的允許范圍內(nèi)自由的進(jìn)行電源自管理。但是,設(shè)備仍然需要使用DevicePowerNotify進(jìn)行設(shè)備電源狀態(tài)切換。
自管理示例
對于一個實現(xiàn)了所有五種電源狀態(tài)的設(shè)備,如果在一定的時間周期內(nèi)無活動,需要動態(tài)的從D0降到D1狀態(tài),或從D1降到D2狀態(tài)。這是因為D2狀態(tài)的耗電量更少,而且設(shè)備很少需要響應(yīng)。如果設(shè)備發(fā)覺需要活動,但其不在D0狀態(tài),設(shè)備將嘗試進(jìn)入D0狀態(tài)。
這樣一個設(shè)備的中斷服務(wù)線程可能與下面的示例代碼類似。
while(!fDone) {
??? dwStatus = WaitForSingleObject(hInterruptEvent, dwTimeout);
??? switch(dwStatus) {
??? case WAIT_OBJECT_0: // device activity
??????? // service device
??????? ...
??????? if(deviceDx != D0 && !fBoostRequested) {
??????????? fBoostRequested = TRUE;
??????????? DevicePowerNotify(pszDeviceName, D0, POWER_DRIVER | POWER_NAME);
?
??????? }
??????? dwTimeout = INACTIVITY_TIMEOUT;
??????? break;
??? case WAIT_TIMEOUT:? // device inactive
? ??????if(deviceDx < D2 && !fReductionRequested) {
??????????? fReductionRequested = TRUE;
??????????? DevicePowerNotify(pszDeviceName, deviceDx + 1, POWER_DRIVER | POWER_NAME);
?
??????? }
??????? if(deviceDx >= D2) {
??????????? dwTimeout = INFINITE;
???? ???}
??? default:??????????? // error handling
??????? break;
??? }
}
設(shè)備的DeviceIoControl處理程序可能包含下列示例代碼。
case IOCTL_POWER_SET:
??? // update device registers
??? ...
??? deviceDx = *(PCEDEVICE_POWER_STATE) pOutBuf;
??? fBoostRequested = FALSE;
??? fReductionRequested = FALSE;
??? break;
上面驅(qū)動程序代碼僅表明了是否請求了狀態(tài)切換,而不是是否已經(jīng)切換。這一點非常重要,因為設(shè)備可能在D2狀態(tài)時請求進(jìn)入D0狀態(tài),但是由于當(dāng)前的電源情況,電源管理器可能僅將其設(shè)為D1狀態(tài)。在下一次設(shè)備活動時,設(shè)備會再次請求進(jìn)入D0狀態(tài),而電源管理器可能只允許其運行在D1狀態(tài)。明白了狀態(tài)切換請求的過程,能夠避免在設(shè)備進(jìn)入活動狀態(tài)前進(jìn)行額外的電源管理API調(diào)用。同樣的處理邏輯也用于當(dāng)設(shè)備非活動超時時電源狀態(tài)降低的過程。
設(shè)備的中斷服務(wù)程序在調(diào)用DevicePowerNotify函數(shù)前設(shè)置fBoostRequested和fReductionRequested標(biāo)記。這是因為DevicePowerNotify調(diào)用可能導(dǎo)致調(diào)用IOCTL_POWER_SET而在同一線程中再次進(jìn)入驅(qū)動程序。DeviceIoControl調(diào)用會清除標(biāo)記,從而使驅(qū)動程序在之后能進(jìn)一步調(diào)整設(shè)備電源狀態(tài)。
4.7.4.2????????????? 如何為驅(qū)動程序添加電源管理(How to Add Power Management to a Device Driver)
開發(fā)者可以為驅(qū)動程序添加電源管理支持,以便能夠降低目標(biāo)設(shè)備的功耗。為此,驅(qū)動程序必須導(dǎo)出流接口。如果已經(jīng)實現(xiàn)了流接口,那么可以開始添加電源管理支持。
硬件及軟件假定
你掌握了如何從命令行創(chuàng)建WinCE運行時鏡像。詳見Build Tool
| 步驟 | 相關(guān)主題 |
| 1. 創(chuàng)建一個流接口驅(qū)動。 | How to Create a Device Driver |
| 2. 為流接口驅(qū)動添加IOCTLs。關(guān)于電源管理IOCTLs的更多信息,見Power Management IOCTLs. | Power-Manageable Device Drivers |
| 3. 通知電源管理器,驅(qū)動程序支持電源管理。見Power Management Functions. | 無 |
| 4. 在驅(qū)動程序中實現(xiàn)設(shè)備電源狀態(tài)。關(guān)于設(shè)備電源狀態(tài)的更多信息,見Device Power States. | Power Management Implementation in Drivers |
| 5. 編譯驅(qū)動程序。如果編譯無錯,那么你已成功為流接口驅(qū)動添加了電源管理。詳見Troubleshooting: Building a Driver. | Building a Device Driver from the Command Line |
| 6. 調(diào)試驅(qū)動程序. | How to Debug a Device Driver |
4.7.4.3????????????? 電源可管理設(shè)備驅(qū)動(Power-Manageable Device Drivers)
為了創(chuàng)建一個支持電源管理的設(shè)備驅(qū)動程序,必須先定義一個non-COM-related設(shè)備接口。non-COM-related設(shè)備接口表示設(shè)備支持電源管理。可以使用以下方式定義這一設(shè)備接口:
l???????? 可以在用于激活設(shè)備的注冊表鍵的IClass值中定義接口。
l???????? 可以使用驅(qū)動程序的Init函數(shù)在活動注冊表中定義IClass值。
l???????? 可以調(diào)用ActivateDeviceEx函數(shù)并使用REGINI參數(shù)來定義IClass值。
l???????? 可以在驅(qū)動程序中顯式的調(diào)用AdvertiseInterface。
關(guān)于為電源管理定義non-COM-related接口的更多信息,參見設(shè)備接口通知。可以通過調(diào)用RequestPowerNotifications函數(shù)為電源管理通知注冊設(shè)備驅(qū)動程序,同時將句柄傳遞給電源管理通知專用的消息隊列。如果驅(qū)動程序需要響應(yīng)電源通知并進(jìn)行相關(guān)處理,就必須這么做。通常情況下,一旦驅(qū)動程序?qū)崿F(xiàn)了電源管理支持,那么此驅(qū)動只需要處理電源管理器的DeviceIoControl調(diào)用。
電源管理器通過IOCTL碼與設(shè)備通訊。下表列出了電源管理器與設(shè)備通訊時使用的IOCTL碼:
| Function | Description |
| IOCTL_POWER_CAPABILITIES | 請求設(shè)備驅(qū)動返回設(shè)備支持的電源狀態(tài)及相關(guān)特征 |
| IOCTL_POWER_SET | 請求驅(qū)動更新設(shè)備的電源狀態(tài) |
| IOCTL_POWER_QUERY | 電源管理器詢問設(shè)備是否準(zhǔn)備好進(jìn)行狀態(tài)切換 |
| IOCTL_POWER_GET | 請求驅(qū)動返回當(dāng)前設(shè)備的電源狀態(tài) |
| IOCTL_REGISTER_POWER_RELATIONSHIP | 通知父設(shè)備注冊所有它所控制的設(shè)備 |
?
你可以實現(xiàn)并使用可選的IOCTL_POWER_QUERY控制碼,以便在驅(qū)動程序還沒有準(zhǔn)備好改變電源狀態(tài)時,延遲電源切換。你可以通過修改MDD層來支持IOCTL_POWER_QUERY,雖然這樣修改可能會導(dǎo)致MDD層與電源管理器的未來版本不兼容。
4.7.4.4????????????? 在驅(qū)動程序中實現(xiàn)電源管理(Power Management Implementation in Drivers)
在配置驅(qū)動程序支持電源管理時,要確定驅(qū)動程序每個入口點的電源狀態(tài)。如果確定電源狀態(tài)正確無誤,那么驅(qū)動程序會根據(jù)目標(biāo)設(shè)備的當(dāng)前電源狀態(tài)以適當(dāng)?shù)姆绞竭\行。
確保在XXX_PowerUp被調(diào)用時驅(qū)動程序不會給目標(biāo)設(shè)備加電。而應(yīng)該恢復(fù)電源管理器設(shè)置的電源狀態(tài),很可能是D3或D4這樣的狀態(tài)值。同樣,在XXX_PowerDown被調(diào)用時不會關(guān)閉目標(biāo)設(shè)備電源。
注意:如果在掛起前目標(biāo)設(shè)備一直沒有加電,電源管理器也沒有向其發(fā)送請求。這種情況下,驅(qū)動程序沒有正確配置,所以要在驅(qū)動程序中重新配置。
4.7.4.5????????????? 在流接口驅(qū)動中實現(xiàn)電源管理(Power Management Implementation in Stream Interface Drivers)
在驅(qū)動程序能夠支持電源管理之前,必須先導(dǎo)出一個流接口。導(dǎo)出的流接口會提供一組入口點以便實現(xiàn)標(biāo)準(zhǔn)文件I/O函數(shù),這些函數(shù)會被kernel使用。
關(guān)于導(dǎo)出流接口的更多信息,見流接口驅(qū)動實現(xiàn)(Stream Interface Driver Implementation)。
除流接口函數(shù)外,驅(qū)動程序還必須支持IOCTL_POWER_CAPABILITIES和IOCTL_POWER_SET這兩個IOCTL。
關(guān)于IOCTL_POWER_SET的更多信息,見IOCTL_POWER_SET請求處理(IOCTL_POWER_SET Request Processing)。
關(guān)于IOCTL_POWER_CAPABILITIE的更多信息,見設(shè)備電源特性(Device Power Capabilities)。
一旦配置了流接口,就可以進(jìn)一步配置驅(qū)動程序來支持電源管理。更多信息參見 4.4在驅(qū)動程序中實現(xiàn)電源管理。
4.7.4.6????????????? 設(shè)備類型名(Class-Qualified Device Names)
自Windows CE .NET 4.10起,支持電源管理的設(shè)備可分屬于不同的設(shè)備類型。這些設(shè)備類型由預(yù)定義類型和自定義類型組成。電源管理器API函數(shù)可以接受設(shè)備名稱,也可以接受有效地設(shè)備類型名稱(class-qualified device names)。例如,下面列出的每一名稱都是有效的設(shè)備名稱:
l???????? COM1:
l???????? {A32942B7-920C-486b-B0E6-92A702A99B35}/COM1:
l???????? {98C5250D-C29A-4985-AE5F-AFE5367E5006}/CISCO1
l???????? {8DD679CE-8AB4-43c8-A14A-EA4963FAA715}/DSK1:
如果某個設(shè)備的類型無效,那么此設(shè)備將被假定屬于默認(rèn)設(shè)備類型。例如,上面COM1:和{A32942B7-920C-486b-B0E6-92A702A99B35}/COM1:是等效的。
4.7.4.7????????????? 設(shè)備初始化(Device Initialization Responsibilities)
在初始化期間,設(shè)備驅(qū)動程序應(yīng)將設(shè)備置為D0狀態(tài),同時在電源管理器通過IOCTL_POWER_CAPABILITIES詢問時應(yīng)盡可能準(zhǔn)確的匯報設(shè)備特性。
4.7.4.8????????????? IOCTL_POWER_SET請求處理(IOCTL_POWER_SET Request Processing)
電源管理器使用IOCTL_POWER_SET(設(shè)備的IOCTL碼)來調(diào)整設(shè)備的電源狀態(tài)。在實現(xiàn)此IOCTL碼時,驅(qū)動程序開發(fā)人員應(yīng)了解下列內(nèi)容:
l???????? 設(shè)備并不一定需要支持所有五種設(shè)備電源狀態(tài),但至少必須支持D0狀態(tài);如果設(shè)備僅支持D0狀態(tài),那么它也不需要處理IOCTL_POWER_SET。
l???????? 電源管理器可能會要求設(shè)備進(jìn)入任何設(shè)備電源狀態(tài),并不僅僅是設(shè)備聲明支持的幾個。
l???????? 如果一個設(shè)備被要求進(jìn)入一個它并不支持的電源狀態(tài),它就會進(jìn)入另一個它支持的更高功耗的狀態(tài)。例如,一個設(shè)備并不支持D2,它會被要求進(jìn)入D1。
l???????? 電源管理器可能會通過發(fā)出IOCTL_POWER_SET,使設(shè)備再次進(jìn)入它已經(jīng)處于的當(dāng)前狀態(tài)。在這種情況下,設(shè)備驅(qū)動程序簡單的返回成功即可。
l???????? 設(shè)備的電源狀態(tài)不一定與系統(tǒng)的電源狀態(tài)同步,因為它可能受到應(yīng)用程序需求的限制。
?
4.7.4.9????????????? 掛起及恢復(fù)處理(Suspend and Resume Handling)
?
支持電源管理的流設(shè)備驅(qū)動程序通過XXX_PowerDown及XXX_PowerUp不斷接收系統(tǒng)掛起/恢復(fù)狀態(tài)通知。這些通知在內(nèi)核調(diào)用OEMPowerOff之前的中斷處理中發(fā)出。PowerDown/PowerUp回調(diào)機制與電源管理器無關(guān),----。
Power managed stream device drivers will continue to receive notifications of system suspend and resume states through their XXX_PowerDown (Device Manager) and XXX_PowerUp (Device Manager). These notifications are sent in an interrupt context just before the kernel calls OEMPowerOff. The PowerDown/PowerUp callback mechanism is independent of the Power Manager and allows legacy device drivers to function under Microsoft? Windows? CE .NET 4.0 and later.
驅(qū)動開發(fā)人員應(yīng)該知道,當(dāng)系統(tǒng)進(jìn)入掛起狀態(tài),處理器將不再運行。理論上,電源管理器會根據(jù)電源狀態(tài)映射,使設(shè)備進(jìn)入對應(yīng)的設(shè)備電源狀態(tài)。然而,掛起系統(tǒng)電源狀態(tài)或應(yīng)用程序的設(shè)備電源需求可能不適合某些設(shè)備。例如,多媒體應(yīng)用程序可能要求音頻設(shè)備保持運行在D0狀態(tài)。如果音頻芯片需要頻繁使用處理器設(shè)置DMA緩存,驅(qū)動開發(fā)人員可判定此設(shè)備在系統(tǒng)掛起狀態(tài)不適合運行于D0狀態(tài),并關(guān)閉設(shè)備電源。
驅(qū)動開發(fā)者必須知道在系統(tǒng)處于掛起狀態(tài)時設(shè)備適合使用哪些電源狀態(tài),從而依此實現(xiàn)其驅(qū)動程序。這一方法適合保守的驅(qū)動開發(fā)人員在系統(tǒng)掛起期間進(jìn)行電源管理決策。但是,在系統(tǒng)掛起時并不是所有的設(shè)備都必須被關(guān)閉。例如,如果音頻設(shè)備可以不依賴處理器播放音樂,那么它可以在系統(tǒng)掛起期間保持供電。
如果驅(qū)動開發(fā)人員在掛起期間改變了設(shè)備的電源狀態(tài),就必須在系統(tǒng)恢復(fù)的同時恢復(fù)設(shè)備的電源狀態(tài)。在系統(tǒng)掛起期間,這些設(shè)備應(yīng)盡量保證其實際行為對電源管理器而言是透明的。
當(dāng)支持電源管理的流設(shè)備通過ActivateDeviceEx被加載時,可以自動通知電源管理器。在注冊表HKEY_LOCAL_MACHINE/CurrentControlSet/Control/Power/Interfaces鍵值下的所有設(shè)備在加載時都需要通知電源管理器。如果這些設(shè)備的注冊表IClass鍵值(REG_MULTI_SZ類型)中包含類似"{A32942B7-920C-486b-B0E6-92A702A99B35}"的GUID,那么在其被加載時電源管理器會收到通知。
設(shè)備在收到IOCTL_POWER_CAPABILITIES控制碼后,可以通過調(diào)用DevicePowerNotify函數(shù)管理其自身電源。在設(shè)備處理IOCTL期間,電源管理器允許設(shè)備自行管理電源。
如果OEM廠商選擇實現(xiàn)非流接口的設(shè)備API,就需要定制電源管理器,使其使用新的機制與設(shè)備通訊。
?
4.7.4.10????????? D3設(shè)備狀態(tài)和系統(tǒng)喚醒(Device State D3 and System Wakeup)
D3設(shè)備電源狀態(tài)需要特殊考慮,因為它并不是僅僅用于限定設(shè)備的功耗等級。設(shè)備可以運行與D3狀態(tài),從而在掛起狀態(tài)時喚醒系統(tǒng),但者并不是必須的。
下列指南說明了如何在驅(qū)動程序中添加D3狀態(tài)支持:
l???????? 可以從掛起狀態(tài)喚醒系統(tǒng)的設(shè)備不應(yīng)通過DevicePowerNotify請求進(jìn)入D3狀態(tài)。這是因為在系統(tǒng)進(jìn)入掛起狀態(tài)前,不應(yīng)存在喚醒源。----。
Devices that can wake the system from a suspend state should not request the D3 state through DevicePowerNotify. This is because enabling a device as a wake source is not always appropriate, unless the system is going to enter a suspend state. The driver cannot distinguish IOCTL_POWER_SET requests for D3 that it has initiated itself from those initiated by the Power Manager as part of a system power state transition.
l???????? 可以將支持喚醒的設(shè)備的D2與D3狀態(tài)定義為相同的電壓等級,當(dāng)然D2狀態(tài)不支持喚醒功能。
l???????? 不能從掛起狀態(tài)喚醒系統(tǒng),但是具有一個能保持設(shè)備運行最低功耗模式的設(shè)備,在電源自管理過程中可以使用D3狀態(tài)。
l???????? 如果一個非喚醒源設(shè)備運行在D3狀態(tài),并且系統(tǒng)掛起,那么它應(yīng)在XXX_PowerDown處理過程切換到D4狀態(tài);同時在XXX_PowerUp處理中恢復(fù)到D3狀態(tài)。如果做不到,就不能支持D3狀態(tài),而應(yīng)在請求進(jìn)入D3狀態(tài)時直接切換到D4狀態(tài)。
l???????? 上述指南隱含說明了支持D3狀態(tài)的設(shè)備不一定能在掛起狀態(tài)喚醒系統(tǒng)。
總之,OEM廠商設(shè)計系統(tǒng)電源狀態(tài)時,應(yīng)用程序開發(fā)者調(diào)用SetPowerRequirement時都需要考慮系統(tǒng)掛起期間D3狀態(tài)的特殊性。上述指南同時描述了OEM廠商和應(yīng)用程序開發(fā)者可以在掛起期間要求設(shè)備進(jìn)入D3狀態(tài),而不用考慮設(shè)備是否支持喚醒功能。
?
4.7.4.11????????? 設(shè)備電源特性(Device Power Capabilities)
IOCTL_POWER_CAPABILITIES在即插即用設(shè)備枚舉時從驅(qū)動程序中查詢設(shè)備的具體特性,包括潛伏周期(latency)、功耗、系統(tǒng)喚醒及啟動功率(Inrush)。在驅(qū)動程序響應(yīng)此IOCTL時也同時匯報他所支持的設(shè)備電源狀態(tài)。電源管理器一般不會要求設(shè)備進(jìn)入它所不支持的電源狀態(tài)。但是,驅(qū)動開發(fā)人員不能認(rèn)為這種情況不會產(chǎn)生。因為設(shè)備制造商可以定制電源管理器,設(shè)備制造商可能會忽略POWER_CAPABILITIES結(jié)構(gòu)的DeviceDx字段。
?
Windows CE設(shè)備驅(qū)動開發(fā)之電源管理 第五部分
4.7.1、活動定時器(Activity Timers)
在初始化時,電源管理器從注冊表中讀取活動定時器名稱列表。對于每個定時器,電源管理器都會檢查其超時時間(以秒為單位)以及可選的喚醒源列表。然后創(chuàng)建下列事件:
l???????? 定時器重置事件
l???????? 活動狀態(tài)手動重置事件
l???????? 手動重置事件
如果超時與不產(chǎn)生重置事件的定時器到期關(guān)聯(lián),電源管理器將重置活動事件并設(shè)置非活動事件。如果重置事件產(chǎn)生,電源管理器重置非活動事件并設(shè)置活動事件。
下列示例代碼是配置一個活動計時器的注冊表設(shè)置: [HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Power/ActivityTimers/SystemActivity]
??? "Timeout"=dword:A
"WakeSources"=multi_sz:"0x20"
上面注冊表設(shè)置會引發(fā)電源管理器創(chuàng)建三個事件,分別名為:PowerManager/ActivityTimer/SystemActivity、PowerManager/SystemActivity_Active及 PowerManager/SystemActivity_Inactive。第一個事件是一個自動重置事件,任何驅(qū)動程序都可能通過發(fā)送信號表明系統(tǒng)處于活動狀態(tài)。支持重置活動定時器的驅(qū)動程序應(yīng)從注冊表中讀取定時器的重置事件名稱。其他兩個是手動重置事件,這兩個事件在同一時刻只會產(chǎn)生一個,而不會同時發(fā)生。驅(qū)動程序、應(yīng)用程序或電源管理器自身都可能打開這些事件的句柄,以便確定定時器是否到期。這些事件表明了活動定時器的狀態(tài)。重置事件是活動定時器的輸入,狀態(tài)事件是其對應(yīng)的輸出。
除了創(chuàng)建事件,這一注冊表設(shè)置項還將一個喚醒源與此活動定時器關(guān)聯(lián)。如果系統(tǒng)恢復(fù),并且電源管理器確定系統(tǒng)是由此活動定時器對應(yīng)的喚醒源所喚醒,那么此活動定時器將被置為活動。電源管理器使用IOCTL_HAL_GET_WAKE_SOURCE內(nèi)核IOCTL來確定是什么設(shè)備喚醒了系統(tǒng)。----。。
In addition to creating events, this set of registry entries associates a wake source identifier with the activity timer. If the OS resumes and the Power Manager determines that the wake source corresponding to this ID caused the system to resume, it will set the associated activity timer to active. The Power Manager uses the IOCTL_HAL_GET_WAKE_SOURCE kernel IOCTL to determine what woke the system. The active timer allows the development workstation that is in finite state to manage OS power state transitions to use the activity timer as input. It then uses that input to make a decision as to which system power state is the most appropriate to enter during the resume process. For example, the Power Manager might enter an OS power state in which the display and backlight are off. The Power Manager enters this state so that network synchronization can occur without disturbing the user.
驅(qū)動程序可以在適當(dāng)?shù)臅r候重置活動定時器,而在同一時刻可能有多個驅(qū)動打開句柄來重置活動定時器事件。驅(qū)動在重置活動定時器時需要從注冊表讀取事件名稱。OEM廠商可以對注冊表進(jìn)行定制,通過定制注冊表,OEM廠商可以決定電源管理器如何理解驅(qū)動程序的活動。潛在的活動源包含打開句柄重置活動定時器事件的所有驅(qū)動。
會有多個線程打開句柄手動重置活動/非活動事件并等待其確定系統(tǒng)狀態(tài)。例如,屏幕背光驅(qū)動可以使用為活動定時器創(chuàng)建的一對事件來判斷如何控制背光的電源及亮度。
當(dāng)系統(tǒng)掛起時,電源管理器重置正在活動的與活動定時器關(guān)聯(lián)的手動重置事件。在系統(tǒng)恢復(fù)時,電源管理器會檢測所有活動定時器,來判斷是否是由與活動定時器關(guān)聯(lián)的喚醒源引發(fā)了系統(tǒng)恢復(fù)。如果找到匹配項,就表明系統(tǒng)恢復(fù)是由其對應(yīng)的喚醒源產(chǎn)生的活動事件引發(fā)的。
?
4.7.5.1????????????? 活動定時器行為(Activity Timer Behavior)
各種驅(qū)動程序都可以重置活動定時器,但是重置活動定時器會導(dǎo)致電源管理器產(chǎn)生一個定時器管理線程。這會給目標(biāo)設(shè)備CPU造成額外負(fù)擔(dān)。為了解決這個問題,當(dāng)活動事件從非活動狀態(tài)變位活動狀態(tài)時,電源管理器在定時器超時前不會再檢測重置事件。如果在此期間產(chǎn)生了活動事件,電源管理器不會處理而會持續(xù)等待。如果直到定時器超時都沒有重置事件,那么活動定時器會到期,同時手動重置事件的狀態(tài)會改變。
?
4.7.5.2????????????? 活動定時器超時及控制面板的電源選項(Activity Timer Time-outs and the Power Control Panel Utility)
?
活動定時器超時表示電源管理器在等待多長時間后可以判定某一活動源是非活動的。這會引發(fā)一個非活動事件。控制面板中的設(shè)置工具可以確定在保持非活動狀態(tài)多長時間后,電源管理器會進(jìn)行系統(tǒng)電源狀態(tài)切換。
活動定時器超時時間應(yīng)小于系統(tǒng)電源狀態(tài)超時時間,但應(yīng)大于預(yù)期的活動時間間隔。例如,系統(tǒng)狀態(tài)超時可能是幾分鐘,而用戶活動定時器可能是10秒。這樣可以預(yù)防在正常操作時頻繁的進(jìn)行活動定時器狀態(tài)切換。
控制面板的電源選項工具中列出的超時時間是累加的。也就是說,如果每個超時時間都設(shè)置為1分鐘,系統(tǒng)會在3分鐘后掛起。因為每個超時時間表示一次系統(tǒng)電源狀態(tài)切換,而系統(tǒng)直到掛起會進(jìn)行3次狀態(tài)切換。
?
4.7.5.3????????????? 活動定時器事件(Activity Timer Events)
?
開發(fā)者可以設(shè)置在驅(qū)動程序中活動定時器事件。電源管理器在等待定時器到期期間不會等待定時器重置事件。在活動定時器超時后,電源管理器會檢測在此期間是否有重置事件被設(shè)置。如果沒有設(shè)置重置事件,定時器會被認(rèn)為已經(jīng)到期。如果有重置事件被設(shè)置,電源管理器將在此等待定時器。電源管理器僅在定時器到期且在此期間沒有產(chǎn)生重置事件,或在非活動期間第一次產(chǎn)生重置事件時更新手動重置定時器事件。
如果驅(qū)動程序線程運行在較高優(yōu)先級時,電源管理器的活動定時器線程不會運行,即使電源管理器正在等待定時器重置事件。默認(rèn)情況下,活動定時器線程運行在THREAD_PRIORITY_ABOVE_NORMAL優(yōu)先級,而大多數(shù)驅(qū)動程序運行在THREAD_PRIORITY_HIGHEST或更高優(yōu)先級。這將導(dǎo)致活動定時器線程不能搶占驅(qū)動程序線程。
?
4.7.5.4????????????? 活動定時器重置(Activity Timer Resets)
可以設(shè)置電源管理器來監(jiān)測哪些應(yīng)用程序正在使用socket,這比僅監(jiān)測socket是否連接要好。網(wǎng)絡(luò)協(xié)議棧并沒有直接支持此功能。當(dāng)然,你可以創(chuàng)建一個線程,周期性的循環(huán)調(diào)用GetTcpStatistics和GetUdpStatistics函數(shù)來確定是否有TCP或UDP報文收發(fā)操作。如果收到或發(fā)送了報文,線程可以重置活動定時器。此線程可以實現(xiàn)為作為電源管理器一部分的可安裝設(shè)備驅(qū)動程序;或作為某應(yīng)用程序的一部分來實現(xiàn)。
注意:如果本地應(yīng)用程序使用socket進(jìn)行進(jìn)程間通訊(IPC)時,GetTcpStatistics和GetUdpStatistics函數(shù)可能會返回環(huán)回通訊數(shù)據(jù)。
?
4.7.2、??????????? 掛起超時支持(Suspend Time-out Support)
你可能需要使WindowsCE設(shè)備處于非活動狀態(tài)一段時間后進(jìn)入掛起狀態(tài)。可以使用以下方式進(jìn)入掛起狀態(tài):
l???????? GWES會維持一個依據(jù)用戶輸入的空閑定時器(Idle timer),并在其處于非活動狀態(tài)一段時間后掛起系統(tǒng)。這種方法用于Windows CE .NET 4.1 之前版本。
l???????? 電源管理器可以根據(jù)活動定時器、輸入電源及其他輸入來管理系統(tǒng)電源狀態(tài)。開發(fā)者可以定制電源管理器,使其能在你選擇掛起(如開始菜單的掛起按鈕)時掛起系統(tǒng)。
l???????? 可以編寫一個獨立的應(yīng)用程序來決定什么時候掛起系統(tǒng)。這種情況下,GWES和電源管理器都必須配置為不對掛起狀態(tài)進(jìn)行管理。
上述三種情況下,都是通過調(diào)用PowerOffSystem從而使電源管理器來掛起系統(tǒng)。三種情況的不同之處在于如何使系統(tǒng)進(jìn)入掛起狀態(tài)。開發(fā)者應(yīng)只使用其中一種方法,以便避免GWES、電源管理器及應(yīng)用程序間的沖突。
如果電源管理器正在管理系統(tǒng)超時,SystemIdleTimerReset函數(shù)會通知GWES不應(yīng)出現(xiàn)屏幕保護程序。
4.7.6.1????????????? GWES掛起超時(GWES Suspend Time-outs)
下表列出控制系統(tǒng)進(jìn)入掛起狀態(tài)的注冊表鍵值。這些值以DWORD類型保存在注冊表HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Power鍵下。如果值為0,表示禁用此功能。
| 注冊表值名稱 | 默認(rèn)值 | 描述 |
| BattPowerOff | 300 (5分鐘) | 表示當(dāng)系統(tǒng)使用電池供電時,在多少秒無用戶輸入后會掛起系統(tǒng)。 |
| ExtPowerOff | 0 (禁用) | 表示當(dāng)系統(tǒng)使用外接電源供電時,在多少秒無用戶輸入后會掛起系統(tǒng)。 |
| WakeupPowerOff | 60 (1分鐘) | 表示當(dāng)系統(tǒng)被非用戶輸入事件喚醒后(例如鬧鐘),在多少秒無活動時會掛起系統(tǒng)。 |
| ScreenPowerOff | 0 (禁用) | 在GWES發(fā)送APM_POWERBROADCAST, PBT_APMUSERIDLE消息給任務(wù)欄前,多少秒無用戶輸入。 |
為了使GWES控制掛起超時,必須使用這些注冊表設(shè)置。同時必須防止電源管理器控制系統(tǒng)掛起狀態(tài)。在示例電源管理器實現(xiàn)中,可以通過從注冊表中移除電源管理器超時定義來實現(xiàn)此功能。當(dāng)GWES管理系統(tǒng)掛起超時時,它通過調(diào)用SetSystemPowerState函數(shù)使電源管理器將系統(tǒng)切換到掛起狀態(tài)。
?
4.7.6.2????????????? 電源管理器掛起超時(Power Manager Suspend Time-outs)
?
示例電源管理器的實現(xiàn)依據(jù)系統(tǒng)電源、用戶活動及系統(tǒng)活動進(jìn)行掛起超時管理。示例電源管理器實現(xiàn)了超時可配置。由于電源管理器可以被OEM廠商定制,所以下列描述并不適用于所有Windows CE設(shè)備。OEM控制電源管理器如何、在什么時候改變系統(tǒng)電源狀態(tài)。
下面列出了控制電源管理器進(jìn)行系統(tǒng)電源狀態(tài)切換的注冊表值:
ACUserIdle
ACSystemIdle
ACSuspend
BattUserIdle
BattSystemIdle
BattSuspend
BatteryPoll
這些DWORD值保存在HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Power/Timeouts注冊表鍵下。0值表示不會產(chǎn)生超時。示例電源管理器并沒有提供忽略系統(tǒng)電源狀態(tài)的方法,OEM可以選擇實現(xiàn)此類方法。
為了使電源管理器能更好的管理系統(tǒng)電源狀態(tài),這些設(shè)置必須在注冊表中出現(xiàn)。示例電源管理器是根據(jù)ACUserIdle進(jìn)行電源管理的。
注意:為了防止GWES與電源管理器間的沖突,應(yīng)禁用GWES電源管理。在電源管理器管理系統(tǒng)電源時,可能會限制應(yīng)用程序不能進(jìn)入某些系統(tǒng)電源狀態(tài)。
Note?? To prevent conflicts between GWES and the Power Manager, you need to disable GWES power management as described previously. When the Power Manager is actively managing system power, it may restrict applications from entering arbitrary system power states.
如果要刷新系統(tǒng)狀態(tài)切換定時器,應(yīng)創(chuàng)建一個名為PowerManager/ReloadActivityTimeouts的自動重置事件,并在此事件的處理過程中調(diào)用SetEvent。這樣可以使電源管理器再次從注冊表中讀取狀態(tài)切換定時器設(shè)置。
注冊表設(shè)置:
[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Power/Timeouts]
??? "ACUserIdle"=dword:3c; 以秒為單位
??? "ACSystemIdle"=dword:12c; 以秒為單位
??? "ACSuspend"=dword:0; 以秒為單位
??? "BattUserIdle"=dword:3c; 以秒為單位
??? "BattSystemIdle"=dword:b4; 以秒為單位
??? "BattSuspend"=dword:12c; 以秒為單位
??? "BatteryPoll"=dword:1f4; 電池輪詢間隔時間,以毫秒為單位
?
?
4.7.6.3????????????? 應(yīng)用程序掛起超時(Application Suspend Time-outs)
OEM廠商有可能會編寫應(yīng)用程序直接對系統(tǒng)電源狀態(tài)進(jìn)行管理,而這樣就不需要定制電源管理器。為此,應(yīng)用程序必須禁用GWES及電源管理器的電源管理功能,并自行處理電源狀態(tài)切換。禁用電源管理器及GWES電源管理功能的更多信息,參見6.2 電源管理器掛起超時。
電源管理器可能不能確定從掛起狀態(tài)恢復(fù)時,應(yīng)恢復(fù)到哪個電源狀態(tài)。如果OEM廠商允許系統(tǒng)在掛起后完全恢復(fù),那么可以不考慮這個問題。但是,如果OEM廠商需要部分喚醒系統(tǒng),就可能需要修改電源管理器。
總結(jié)
以上是生活随笔為你收集整理的Windows CE设备驱动开发之电源管理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: wince 串口调试信息输出
- 下一篇: 阿拉伯系统的建立