📄 platform.cpp
字号:
PMLOGMSG(ZONE_PLATFORM || ZONE_RESUME,
(_T("%s: suspending - notifying non-block drivers\r\n"), pszFname));
for(pdl = gpDeviceLists; pdl != NULL; pdl = pdl->pNext) {
if(*pdl->pGuid != idBlockDevices) {
UpdateClassDeviceStates(pdl);
}
}
// Notify the kernel that we are about to suspend. This gives the
// kernel an opportunity to clear wake source flags before we initiate
// the suspend process. If we don't do this and a wake source interrupt
// occurs between the time we call PowerOffSystem() and the time
// OEMPowerOff() is invoked it is hard for the kernel to know whether or
// not to suspend.
PMLOGMSG(ZONE_PLATFORM || ZONE_RESUME,
(_T("%s: calling KernelIoControl(IOCTL_HAL_PRESUSPEND)\r\n"), pszFname));
KernelIoControl(IOCTL_HAL_PRESUSPEND, NULL, 0, NULL, 0, NULL);
iCurrentPriority = CeGetThreadPriority(GetCurrentThread());
DEBUGCHK(iCurrentPriority != THREAD_PRIORITY_ERROR_RETURN);
if(iCurrentPriority != THREAD_PRIORITY_ERROR_RETURN) {
CeSetThreadPriority(GetCurrentThread(), giPreSuspendPriority);
Sleep(0);
CeSetThreadPriority(GetCurrentThread(), iCurrentPriority);
}
// Notify file systems that their block drivers will soon go away. After making
// this call, this thread is the only one that can access the file system
// (including registry and device drivers) without blocking. Unfortunately,
// this API takes and holds the file system critical section, so other threads
// attempting to access the registry or files may cause priority inversions.
// To avoid priority problem that may starve the PM, we may raise our own priority
// to a high level. Do this if giSuspendPriority is non-zero.
if(giSuspendPriority != 0) {
iPreSuspendPriority = CeGetThreadPriority(GetCurrentThread());
DEBUGCHK(iPreSuspendPriority != THREAD_PRIORITY_ERROR_RETURN);
PMLOGMSG(ZONE_PLATFORM,
(_T("%s: suspending: raising thread priority for 0x%08x from %d to %d\r\n"),
pszFname, GetCurrentThreadId(), iPreSuspendPriority, giSuspendPriority));
CeSetThreadPriority(GetCurrentThread(), giSuspendPriority);
}
FileSystemPowerFunction(FSNOTIFY_POWER_OFF);
gfFileSystemsAvailable = FALSE;
// update block device power states
PMLOGMSG(ZONE_PLATFORM || ZONE_RESUME,
(_T("%s: suspending - notifying block drivers\r\n"), pszFname));
pdl = GetDeviceListFromClass(&idBlockDevices);
if(pdl != NULL) {
UpdateClassDeviceStates(pdl);
}
// Handle resets and shutdowns here, after flushing files. Since Windows CE does
// not define a standard mechanism for handling shutdown (via POWER_STATE_OFF),
// OEMs will need to fill in the appropriate code here. Similarly, if an OEM does
// not support IOCTL_HAL_REBOOT, they should not support POWER_STATE_RESET.
if((dwNewStateFlags & POWER_STATE_RESET) != 0) {
// is this to be a cold boot?
if(_tcscmp(pszName, _T("coldreboot")) == 0) {
SetCleanRebootFlag();
}
// should not return from this call, but if we do just suspend the system
KernelLibIoControl((HANDLE)KMOD_OAL, IOCTL_HAL_REBOOT, NULL, 0, NULL, 0, NULL);
RETAILMSG(TRUE, (_T("PM: PlatformSetSystemPowerState: KernelIoControl(IOCTL_HAL_REBOOT) returned!\r\n")));
DEBUGCHK(FALSE); // break into the debugger
}
} else if(fResumeSystem) {
// we're waking up from a resume -- update block device power states
// so we can access the registry and/or files.
PMLOGMSG(ZONE_PLATFORM || ZONE_RESUME,
(_T("%s: resuming - notifying block drivers\r\n"), pszFname));
pdl = GetDeviceListFromClass(&idBlockDevices);
if(pdl != NULL) {
UpdateClassDeviceStates(pdl);
}
// Notify file systems that their block drivers are back.
FileSystemPowerFunction(FSNOTIFY_POWER_ON);
gfFileSystemsAvailable = TRUE;
// update all devices other than block devices
PMLOGMSG(ZONE_PLATFORM || ZONE_RESUME,
(_T("%s: resuming - notifying block drivers\r\n"), pszFname));
for(pdl = gpDeviceLists; pdl != NULL; pdl = pdl->pNext) {
if(*pdl->pGuid != idBlockDevices) {
UpdateClassDeviceStates(pdl);
}
}
// tell gwes to wake up
if(gpfnGwesPowerUp != NULL && gfGwesReady) {
gpfnGwesPowerUp(fWantStartupScreen);
fWantStartupScreen = FALSE;
}
// send out resume notification
pbb.Message = PBT_RESUME;
pbb.Flags = 0;
pbb.Length = 0;
pbb.SystemPowerState[0] = 0;
GenerateNotifications((PPOWER_BROADCAST) &pbb);
} else {
// update all devices without any particular ordering
UpdateAllDeviceStates();
}
// release the old state information
SystemPowerStateDestroy(pOldSystemPowerState);
while(pOldCeilingDx != NULL) {
PDEVICE_POWER_RESTRICTION pdpr = pOldCeilingDx->pNext;
PowerRestrictionDestroy(pOldCeilingDx);
pOldCeilingDx = pdpr;
}
// are we suspending?
if(fSuspendSystem) {
// Once file systems are disabled, discard code pages from drivers. This
// is a diagnostic tool to forcibly expose paging-related bugs that could
// cause apparently random system crashes or hangs. Optionally, OEMs can
// disable this for production systems to speed up resume times.
if(gfPageOutAllModules) {
BOOL fOk = PageOutModule(GetCurrentProcess(), PAGE_OUT_ALL_DEPENDENT_DLL);
DEBUGCHK(fOk);
}
// set a flag to notify the resume thread that this was a controlled
// suspend
gfSystemSuspended = TRUE;
PMLOGMSG(ZONE_PLATFORM || ZONE_RESUME, (_T("%s: calling PowerOffSystem()\r\n"), pszFname));
PowerOffSystem(); // sets a flag in the kernel for the scheduler
Sleep(0); // so we force the scheduler to run
PMLOGMSG(ZONE_PLATFORM || ZONE_RESUME, (_T("%s: back from PowerOffSystem()\r\n"), pszFname));
// clear the suspend flag
gfSystemSuspended = FALSE;
gfPasswordOn = 0 ;
}
else {
PMLOCK();
if ( fPasswordOn != gfPasswordOn ) {
if (gfGwesReady && gpfnShowStartupWindow && fPasswordOn )
gpfnShowStartupWindow();
gfPasswordOn = fPasswordOn;
}
PMUNLOCK();
}
} else {
// release the unused new state information
SystemPowerStateDestroy(pNewSystemPowerState);
while(pNewCeilingDx != NULL) {
PDEVICE_POWER_RESTRICTION pdpr = pNewCeilingDx->pNext;
PowerRestrictionDestroy(pNewCeilingDx);
pNewCeilingDx = pdpr;
}
}
}
// restore our priority if we updated it during a suspend transition
if(giSuspendPriority != 0 && iPreSuspendPriority != 0) {
PMLOGMSG(ZONE_PLATFORM, (_T("%s: restoring thread priority to %d\r\n"),
pszFname, iPreSuspendPriority));
CeSetThreadPriority(GetCurrentThread(), iPreSuspendPriority);
}
return dwStatus;
}
// This routine reads a power state timeout value from the registry. The
// timeout value should be expressed in seconds; this routine returns
// the timeout value in milliseconds.
DWORD
RegReadStateTimeout(HKEY hk, LPCTSTR pszName, DWORD dwDefault)
{
DWORD dwValue, dwSize, dwStatus;
dwSize = sizeof(dwValue);
dwStatus = RegQueryTypedValue(hk, pszName, &dwValue, &dwSize, REG_DWORD);
if(dwStatus != ERROR_SUCCESS) {
dwValue = dwDefault;
} else {
if(dwValue == 0) {
dwValue = INFINITE;
} else {
if(dwValue > MAXACTIVITYTIMEOUT) {
dwValue = MAXACTIVITYTIMEOUT;
}
}
}
// convert to milliseconds
if(dwValue != INFINITE) {
dwValue *= 1000;
}
return dwValue;
}
// This routine implements the main power manager event loop. This loop implements
// the power manager's response to external events, such as being docked in a cradle,
// running low on battery power, going on or off AC power, etc. This sample implementation
// simply monitors battery level changes and generates the appropriate notifications.
EXTERN_C VOID WINAPI
PlatformManageSystemPower(HANDLE hevReady)
{
BOOL fDone = FALSE;
HANDLE hqNotify = NULL;
HMODULE hmCoreDll = NULL;
SETFNAME(_T("PlatformManageSystemPower"));
PMLOGMSG(ZONE_INIT || ZONE_PLATFORM, (_T("+%s\r\n"), pszFname));
// determine thread priority settings while we're suspending (in case
// of priority inversion)
if(!GetPMThreadPriority(_T("PreSuspendPriority256"), &giPreSuspendPriority)) {
giPreSuspendPriority = DEF_PRESUSPEND_THREAD_PRIORITY;
}
if(!GetPMThreadPriority(_T("SuspendPriority256"), &giSuspendPriority)) {
giSuspendPriority = DEF_SUSPEND_THREAD_PRIORITY;
}
// Get pointers to GWES's suspend/routine APIs. These require GWES, so the OEM may
// not have them on this platform. Also get battery level APIs, which require a
// battery driver and may not be present.
hmCoreDll = (HMODULE) LoadLibrary(_T("coredll.dll"));
gfGwesReady = FALSE;
PmInitPowerStatus(hmCoreDll);
if(hmCoreDll != NULL) {
gpfnGwesPowerDown = (PFN_GwesPowerDown) GetProcAddress(hmCoreDll, _T("GwesPowerDown"));
gpfnGwesPowerUp = (PFN_GwesPowerUp) GetProcAddress(hmCoreDll, _T("GwesPowerUp"));
gpfnShowStartupWindow = (PFN_ShowStartupWindow) GetProcAddress(hmCoreDll, _T("ShowStartupWindow"));
// do we have both gwes suspend/resume APIs?
if(gpfnGwesPowerDown == NULL || gpfnGwesPowerUp == NULL) {
// no, ignore GWES
gpfnGwesPowerDown = NULL;
gpfnGwesPowerUp = NULL;
} else {
// monitor GWES apis
ghevGwesReady = OpenEvent(EVENT_ALL_ACCESS, FALSE, _T("SYSTEM/GweApiSetReady"));
DEBUGCHK(ghevGwesReady != NULL);
}
}
if (!fDone) {
DefaultPowerStateManager *pPowerStateManager = CreateDefaultPowerManager( NULL );
if (pPowerStateManager && pPowerStateManager->Init()) {
g_pPowerStateManager = pPowerStateManager ;
// we're up and running
SetEvent(hevReady);
g_pPowerStateManager->ThreadRun() ;
}
else {
ASSERT(FALSE);
if (pPowerStateManager)
delete pPowerStateManager;
PMLOGMSG(ZONE_INIT || ZONE_ERROR, (_T("%s: PowerStateManager Intialization Failed!!!\r\n"), pszFname));
}
if (g_pPowerStateManager) {
delete g_pPowerStateManager;
g_pPowerStateManager = NULL;
}
}
if(hmCoreDll != NULL) FreeLibrary(hmCoreDll);
PMLOGMSG(ZONE_PLATFORM, (_T("-%s: exiting\r\n"), pszFname));
}
// This routine is called when the system has resumed. It is responsible for
// determining why the system woke up and initiating the appropriate system
// power state transition. This routine is invoked in the context of the PM's
// resume thread.
// Note: this thread must be running at a higher priority than any thread
// that might suspend the system using SetSystemPowerState(). Otherwise it cannot
// tell whether it needs to update the system power state on its own. In general,
// OEMs should not suspend the system without calling SetSystemPowerState() -- the
// code in this routine that handles unexpected suspends is present only as a fallback.
EXTERN_C VOID WINAPI
PlatformResumeSystem(void)
{
SETFNAME(_T("PlatformResumeSystem"));
PMLOGMSG(ZONE_RESUME, (_T("+%s: suspend flag is %d\r\n"), pszFname, gfSystemSuspended));
// Was this an unexpected resume event? If so, there may be a thread priority problem
// or some piece of software suspended the system without calling SetSystemPowerState().
DEBUGCHK(gfSystemSuspended);
if (g_pPowerStateManager) {
g_pPowerStateManager->PlatformResumeSystem(gfSystemSuspended);
}
PMLOGMSG(ZONE_RESUME, (_T("-%s\r\n"), pszFname));
}
DWORD WINAPI PlatformSendSystemPowerState(LPCWSTR pwsState, DWORD dwStateHint, DWORD dwOptions)
{
DWORD dwReturn = ERROR_GEN_FAILURE;
if (g_pPowerStateManager) {
dwReturn = g_pPowerStateManager->SendSystemPowerState(pwsState, dwStateHint, dwOptions );
}
return dwReturn;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -