⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 platform.cpp

📁 此代码为WCE5.0下电源管理的源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:

                // we're suspending; update all devices other than block devices,
                // in case any of them need to access the registry or write files.
                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
                    KernelIoControl(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);
                    }
                }
            } 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;
            }
            
            PMLOCK();
            if ( fPasswordOn != gfPasswordOn ) {
                if (gfGwesReady && gpfnShowStartupWindow && fPasswordOn )
                    gpfnShowStartupWindow();
                gfPasswordOn = fPasswordOn;
            }
            PMUNLOCK();
            // notify our state machine of this system power state change if this was
            // an external request
            if(!fInternal) {
                PlatformUpdateSystemPowerState(SystemPowerStateChange, INFINITE);
                DEBUGCHK(ghevRestartTimers != NULL);
                SetEvent(ghevRestartTimers);
            }
            
            // are we suspending?
            if(fSuspendSystem) {
                // clear activity flags
                ResetEvent(ghevUserActive);
                ResetEvent(ghevSignalUserActivity);
                ResetEvent(ghevSystemIdleTimerReset);
                
                // 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;
                
                // resume into an appropriate system power state
                PlatformUpdateSystemPowerState(Resume, INFINITE);
                DEBUGCHK(ghevRestartTimers != NULL);
                SetEvent(ghevRestartTimers);
                
                // tell gwes to wake up
                if(gpfnGwesPowerUp != NULL && gfGwesReady) {
                    gpfnGwesPowerUp(fWantStartupScreen);
                }
                
                // send out resume notification
                pbb.Message = PBT_RESUME;
                pbb.Flags = 0;
                pbb.Length = 0;
                pbb.SystemPowerState[0] = 0;
                GenerateNotifications((PPOWER_BROADCAST) &pbb);
            }
        } 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);
    }
    
    // if we're initializing, tell the management thread we're done
    if(fFirstCall) {
        if(ghevReloadActivityTimeouts != NULL) SetEvent(ghevReloadActivityTimeouts);
        fFirstCall = FALSE;
    }
    
    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 reads the system's timeout values from the registry.  It
// is called at boot time and whenever the reload event is signaled.
VOID
PlatformLoadTimeouts(VOID)
{
    DWORD dwStatus;
    TCHAR szPath[MAX_PATH];
    HKEY hk;
    SETFNAME(_T("PlatformLoadTimeouts"));

    // assume default values
    gdwACSuspendTimeout = DEF_ACSUSPENDTIMEOUT * 1000;
    gdwACResumingSuspendTimeout = DEF_ACRESUMINGSUSPENDTIMEOUT * 1000;
    gdwBattSuspendTimeout = DEF_BATTSUSPENDTIMEOUT * 1000;
    gdwBattResumingSuspendTimeout = DEF_BATTRESUMINGSUSPENDTIMEOUT * 1000;

    // get timeout thresholds for transitions between states
    wsprintf(szPath, _T("%s\\%s"), PWRMGR_REG_KEY, _T("Timeouts"));
    dwStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szPath, 0, 0, &hk);
    if(dwStatus == ERROR_SUCCESS) {
        // read system power state timeouts
        gdwACSuspendTimeout = RegReadStateTimeout(hk, _T("ACSuspendTimeout"), DEF_ACSUSPENDTIMEOUT);
        gdwACResumingSuspendTimeout = RegReadStateTimeout(hk, _T("ACResumingSuspendTimeout"), DEF_ACRESUMINGSUSPENDTIMEOUT);
        gdwBattSuspendTimeout = RegReadStateTimeout(hk, _T("BattSuspendTimeout"), DEF_BATTSUSPENDTIMEOUT);
        gdwBattResumingSuspendTimeout = RegReadStateTimeout(hk, _T("BattResumingSuspendTimeout"), DEF_BATTRESUMINGSUSPENDTIMEOUT);

        // release resources
        RegCloseKey(hk);
    }

    PMLOGMSG(ZONE_INIT || ZONE_PLATFORM, 
        (_T("%s: ACSuspendTimeout %d, ACResumingSuspendTimeout %d, BattSuspendTimeout %d, BattResumingSuspendTimeout %d\r\n"),
        pszFname, gdwACSuspendTimeout, gdwACResumingSuspendTimeout, gdwBattSuspendTimeout, 
        gdwBattResumingSuspendTimeout));
}

// This routine returns TRUE if the PM will automatically translate POWER_STATE_SUSPEND
// requests into "unattended" mode if there are outstanding requests to enter
// unattended mode when the suspend request is made.  If not, it returns FALSE.
BOOL
PlatformSuspendingToUnattendedMode(void)
{
    BOOL fSuspendToUnattendedMode = TRUE;
    DWORD dwStatus, dwValue, dwSize = sizeof(dwValue);
    HKEY hk;

    dwStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, PWRMGR_REG_KEY, 0, 0, &hk);
    if(dwStatus == ERROR_SUCCESS) {
        dwStatus = RegQueryTypedValue(hk, _T("SuspendToUnattendedMode"), &dwValue,
            &dwSize, REG_DWORD);
        if(dwStatus == ERROR_SUCCESS && dwValue == 0) {
            fSuspendToUnattendedMode = FALSE;
        }

        RegCloseKey(hk);
    }

    return fSuspendToUnattendedMode;
}

// 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 hEvents[7], hqNotify = NULL;
    DWORD dwTimeout, dwStatus, dwNumEvents;
    HMODULE hmCoreDll = NULL;
    PACTIVITY_TIMER pat;
    SETFNAME(_T("PlatformManageSystemPower"));
    
    PMLOGMSG(ZONE_INIT || ZONE_PLATFORM, (_T("+%s\r\n"), pszFname));
    
    // init globals
    ghevReloadActivityTimeouts = NULL;
    ghevRestartTimers = NULL;
    ghevSystemIdleTimerReset = NULL;
    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -