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

📄 platform.cpp

📁 此代码为WCE5.0下电源管理的源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    // 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;
    }
    
    // Determine whether we will allow unattended mode requests to 
    // influence how we suspend the system.
    gfSuspendToUnattendedMode = PlatformSuspendingToUnattendedMode();
    
    // get events from activity timers
    PMLOCK();
    pat = ActivityTimerFindByName(_T("UserActivity"));
    if(pat != NULL) {
        ghevSignalUserActivity = pat->hevReset;
        ghevUserActive = pat->hevActive;
        ghevUserInactive = pat->hevInactive;
    } else {
        ghevSignalUserActivity = NULL;
        ghevUserActive = NULL;
        ghevUserInactive = NULL;
    }
    PMUNLOCK();
    
    // 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);
        }
    }
    
    // create events
    ghevReloadActivityTimeouts = CreateEvent(NULL, FALSE, FALSE, _T("PowerManager/ReloadActivityTimeouts"));
    ghevRestartTimers = CreateEvent(NULL, FALSE, FALSE, NULL);
    ghevSystemIdleTimerReset = CreateEvent(NULL, FALSE, FALSE, _T("PowerManager/SystemIdleTimerReset"));
    if(ghevReloadActivityTimeouts == NULL 
        || ghevRestartTimers == NULL
        || ghevSystemIdleTimerReset == NULL) {
        PMLOGMSG(ZONE_WARN, (_T("%s: CreateEvent() failed for system event\r\n"), pszFname));
        goto done;
    }
    
    // check that all of our activity events exist
    if(ghevUserActive == NULL || ghevUserInactive == NULL) {
        PMLOGMSG(ZONE_WARN, (_T("%s: activity timer events not found\r\n"), pszFname));
        goto done;
    }
    
    // create our notification queue
    hqNotify = PmPolicyCreateNotificationQueue();
    if(hqNotify == NULL) {
        PMLOGMSG(ZONE_WARN, (_T("%s: PmPolicyCreateNotificationQueue() failed\r\n"), pszFname));
        goto done;
    }
        
    // we're up and running
    SetEvent(hevReady);
    
    // we don't want to start updating system power states until the PM is completely
    // up and running.  We'll wait for the first call to SetSystemPowerState() coming from
    // device.exe's initialization code as our signal to continue.
    PMLOGMSG(ZONE_INIT, (_T("%s: waiting for initialization to complete\r\n"),
        pszFname));
    hEvents[0] = ghevPmShutdown;
    hEvents[1] = ghevReloadActivityTimeouts;
    dwStatus = WaitForMultipleObjects(2, hEvents, FALSE, INFINITE);
    switch(dwStatus) {
    case (WAIT_OBJECT_0 + 0):
        PMLOGMSG(ZONE_INIT || ZONE_WARN, (_T("%s: shutdown event signaled, exiting\r\n"), 
            pszFname));
        fDone = TRUE;
        break;
    case (WAIT_OBJECT_0 + 1):
        PMLOGMSG(ZONE_INIT, (_T("%s: initialization complete\r\n"), pszFname));
        break;
    default:
        PMLOGMSG(ZONE_INIT || ZONE_WARN, 
            (_T("%s: WaitForMultipleObjects() returned %d, exiting\r\n"),
            pszFname, dwStatus));
        fDone = TRUE;
    }
    
    // get notifications in case of hive based registry
    ghevBootPhase2 = OpenEvent(EVENT_ALL_ACCESS, FALSE, _T("SYSTEM/BootPhase2"));
    
    // read the timeout values
    PlatformLoadTimeouts();
    
    // set up wait events -- assume user is active and system is active
    hEvents[0] = ghevPmShutdown;
    hEvents[1] = ghevReloadActivityTimeouts;
    hEvents[2] = hqNotify;
    hEvents[3] = ghevRestartTimers;
    hEvents[4] = ghevUserInactive;
    hEvents[5] = ghevSystemIdleTimerReset;
    if(ghevBootPhase2 != NULL) {
        hEvents[6] = ghevBootPhase2;
        dwNumEvents = dim(hEvents);
    } else {
        dwNumEvents = dim(hEvents) - 1;
    }
    dwTimeout = INFINITE;
    PMLOGMSG(ZONE_PLATFORM, (_T("%s: waiting for events\r\n"), pszFname));
    while(!fDone) {
        PLATFORM_ACTIVITY_EVENT eCurrentActivity = NoActivity;
        DWORD dwStartTime, dwElapsedTime;
        
        // wait for an event; keep track of elapsed time
        dwStartTime = GetTickCount();
        dwStatus = WaitForMultipleObjects(dwNumEvents, hEvents, FALSE, dwTimeout);
        dwElapsedTime = GetTickCount() - dwStartTime;
        PMLOGMSG(ZONE_PLATFORM, 
            (_T("%s: wait returned %d, elapsed time %d, timeout was %d\r\n"), pszFname,
            dwStatus, dwElapsedTime, dwTimeout));
        
#ifdef NOT_USED
        // sanity check
        if(WaitForSingleObject(ghevUserActive, 0) == WAIT_OBJECT_0) PMLOGMSG(TRUE, (_T("%s: user active signaled\r\n"), pszFname));
        if(WaitForSingleObject(ghevUserInactive, 0) == WAIT_OBJECT_0) PMLOGMSG(TRUE, (_T("%s: user inactive signaled\r\n"), pszFname));
#endif  // NOT_USED
        
        // figure out what happened
        switch(dwStatus) {
        case (WAIT_OBJECT_0 + 0):   // shutdown event signaled
            fDone = TRUE;
            eCurrentActivity = NoActivity;
            break;
        case (WAIT_OBJECT_0 + 1):   // reset timeout variables and restart timers
            PlatformLoadTimeouts();
            eCurrentActivity = RestartTimeouts;
            break;
        case (WAIT_OBJECT_0 + 2):   // notification from outside the PM
            {
                POWERPOLICYMESSAGE ppm;
                dwStatus = PmPolicyReadNotificationQueue(hqNotify, &ppm, sizeof(ppm));
                if(dwStatus == ERROR_SUCCESS) {
                    PMLOGMSG(ZONE_PLATFORM, (_T("%s: got request 0x%04x (data 0x%08x) from process 0x%08x\r\n"),
                        pszFname, ppm.dwMessage, ppm.dwData, ppm.hOwnerProcess));
                    switch(ppm.dwMessage) {
                    case PPN_POWERCHANGE:
                        if(PmUpdatePowerStatus()){
                            eCurrentActivity = PowerSourceChange;
                        }
                        break;
                    case PPN_UNATTENDEDMODE:
                        // somebody wants to enter or leave unattended mode
                        if(ppm.dwData != FALSE) {
                            eCurrentActivity = EnterUnattendedModeRequest;
                        } else {
                            eCurrentActivity = LeaveUnattendedModeRequest;
                        }
                        break;
                    case PPN_SUSPENDKEYPRESSED:
                        SuspendButtonPressed(gfSupportPowerButtonRelease);
                        break;
                    case PPN_SUSPENDKEYRELEASED:
                        SuspendButtonReleased(gfSupportPowerButtonRelease);
                        break;
                    default:
                        // unhandled notification type, ignore it
                        PMLOGMSG(ZONE_WARN, (_T("%s: unhandled policy notification 0x%04x (data 0x%08x)\r\n"), 
                            pszFname, ppm.dwMessage, ppm.dwData));
                        break;
                    }
                }
            }
            break;
        case (WAIT_OBJECT_0 + 3):   // restart timers
            eCurrentActivity = RestartTimeouts;
            break;
        case (WAIT_OBJECT_0 + 4):   // user activity or inactivity signaled
            if(hEvents[4] == ghevUserInactive) {
                eCurrentActivity = UserInactivity;
            } else {
                eCurrentActivity = UserActivity;
            }
            break;
        case (WAIT_OBJECT_0 + 5):   // somebody called SystemIdleTimerReset()
            eCurrentActivity = SystemIdleTimerWasReset;
            break;
        case (WAIT_OBJECT_0 + 6):   // hive based registry load complete
            DEBUGCHK(ghevBootPhase2 != NULL);
            
            // update timeouts in case they've been changed
            PlatformLoadTimeouts();
            eCurrentActivity = RestartTimeouts;

            // don't need to wait on this handle again
            dwNumEvents--;
            CloseHandle(ghevBootPhase2);
            ghevBootPhase2 = NULL;
            break;
        case WAIT_TIMEOUT:
            eCurrentActivity = Timeout;
            break;
        default:
            eCurrentActivity = NoActivity;
            PMLOGMSG(ZONE_WARN, (_T("%s: WaitForMultipleObjects() returned %d\r\n"), pszFname,
                GetLastError()));
            break;
        }
        
        // update system power state based on activity information
        dwTimeout = PlatformUpdateSystemPowerState(eCurrentActivity, dwElapsedTime);
        
        // determine which activity handles we need to wait on
        if(WaitForSingleObject(ghevUserActive, 0) == WAIT_OBJECT_0) {
            hEvents[4] = ghevUserInactive;
        } else {
            hEvents[4] = ghevUserActive;
        }
    }
    
done:
    // clean up before exiting
    if(ghevReloadActivityTimeouts == NULL) { 
        CloseHandle(ghevReloadActivityTimeouts);
        ghevReloadActivityTimeouts = NULL;
    }
    if(ghevRestartTimers != NULL) {
        CloseHandle(ghevRestartTimers);
        ghevRestartTimers = NULL;
    }
    if(ghevSystemIdleTimerReset != NULL) {
        CloseHandle(ghevSystemIdleTimerReset);
        ghevSystemIdleTimerReset = NULL;
    }
    if(hqNotify != NULL) {
        PmPolicyCloseNotificationQueue(hqNotify);
        hqNotify = 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(!gfSystemSuspended) {
        // Unexpected resume -- go to the resuming state.  This should not happen unless
        // somebody is illegally calling PowerOffSystem() directly.
        PMLOGMSG(ZONE_WARN || ZONE_RESUME, (_T("%s: WARNING: unexpected resume!\r\n"), pszFname));
        
        // Go into the new state.  OEMs that choose to support unexpected resumes may want to
        // lock PM variables with PMLOCK(), then set the curDx and actualDx values for all
        // devices to PwrDeviceUnspecified before calling PmSetSystemPowerState_I().  This will
        // force an update IOCTL to all devices.
        PlatformUpdateSystemPowerState(Resume, INFINITE);
        DEBUGCHK(ghevRestartTimers != NULL);
        SetEvent(ghevRestartTimers);
    }

    PMLOGMSG(ZONE_RESUME, (_T("-%s\r\n"), pszFname));
}

⌨️ 快捷键说明

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