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

📄 pwstates.cpp

📁 LX 800 WindowsCE 6.0 BSP
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//

//
// This module implements a set of states defined by the MS Mobile Devices
// Division as a baseline for Pocket PC devices.  OEMs may choose to customize
// this file to support the hardware specific to their platform.
//

#include <pmimpl.h>
#include <nkintr.h>
#include <extfile.h>
#include <pmpolicy.h>
#include <Csync.h>
#include <cRegEdit.h>
#include <pwsdef.h>

typedef enum {
    NoTimeoutItem,
    SuspendTimeout,
    SystemActivityTimeout,
    UserActivityTimeout,
} TIMEOUT_ITEM, *PTIMEOUT_ITEM;

typedef enum { 
    On,                     // system is running normally with UI enabled
    UserIdle,               // User Idle state.
    SystemIdle,
    Resuming,               // system is determining what to do after a resume
    Suspend,                 // system suspended, all devices off (or wake-enabled)
    ColdReboot,
    Reboot,
    UnknownState = PM_UNKNOWN_POWER_STATE,       // Unknown
} PLATFORM_ACTIVITY_STATE, *PPLATFORM_ACTIVITY_STATE;
    
#define STRING_ON _T("on")
#define STRING_USERIDLE _T("useridle")
#define STRING_SYSTEMIDLE _T("systemidle")
#define STRING_RESUMING _T("resuming")
#define STRING_SUSPEND _T("suspend")
#define STRING_ColdReboot _T("coldreboot")
#define STRING_Reboot _T("reboot")

// platform-specific default values
#define DEF_TIMEOUTTOUSERIDLE           60          // in seconds, 0 to disable
#define DEF_TIMEOUTTOSYSTEMIDLE         300         // in seconds, 0 to disable
#define DEF_TIMEOUTTOSUSPEND            600         // in seconds, 0 to disable

extern DWORD RegReadStateTimeout(HKEY hk, LPCTSTR pszName, DWORD dwDefault);
// need "C" linkage for compatibility with C language PDD implementations
extern "C" extern POWER_BROADCAST_POWER_INFO gSystemPowerStatus;

class PowerStateManager: public DefaultPowerStateManager {
public:
    PowerStateManager(PVOID pParam) 
        : DefaultPowerStateManager (pParam)
    {
        m_fActiveManagement = TRUE;
    }
    ~PowerStateManager() {
        while (m_pPowerStateList!=NULL) {
            PowerState * pNextState = m_pPowerStateList->GetNextPowerState();
            delete m_pPowerStateList;
            m_pPowerStateList = pNextState;
        }
    }
    BOOL Init() {
        if (DefaultPowerStateManager::Init() && m_pSystemActivity && m_pUserActivity) { // This is required by Default PM.
            PlatformLoadTimeouts();
            ReInitTimeOuts();
            return CreatePowerStateList();
        }
        return FALSE;
    }

    virtual void ResetUserIdleTimeout(BOOL fIdle) {
        m_dwCurUserIdleTimeout = (fIdle? GetUserIdleTimeOut():INFINITE);
        if (m_dwCurUserIdleTimeout == 0 )
            m_dwCurUserIdleTimeout = INFINITE ;
        m_dwCurTimeoutToSystemIdle = (fIdle? GetSystemIdleTimeOut(): INFINITE);
        if (m_dwCurTimeoutToSystemIdle == 0)
            m_dwCurTimeoutToSystemIdle = INFINITE ;
    }
    virtual void ResetSystemIdleTimeTimeout(BOOL fIdle) {
        m_dwCurSuspendTimeout = (fIdle? GetSuspendTimeOut(): INFINITE);
        if (m_dwCurSuspendTimeout == 0)
            m_dwCurSuspendTimeout = INFINITE ;
    }
    virtual void SubtractTimeout(DWORD dwTicks) {
        if (m_dwCurSuspendTimeout != INFINITE )
            m_dwCurSuspendTimeout = (m_dwCurSuspendTimeout>dwTicks? m_dwCurSuspendTimeout- dwTicks: 0 );
        if (m_dwCurTimeoutToSystemIdle != INFINITE)
            m_dwCurTimeoutToSystemIdle = (m_dwCurTimeoutToSystemIdle>dwTicks? m_dwCurTimeoutToSystemIdle- dwTicks: 0 );
        if (m_dwCurUserIdleTimeout!= INFINITE)
            m_dwCurUserIdleTimeout =  (m_dwCurUserIdleTimeout> dwTicks? m_dwCurUserIdleTimeout - dwTicks: 0 );
    }
    virtual DWORD   ThreadRun() {
        SETFNAME(_T("PowerStateManager::ThreadRun"));
        // Assume First state is PowerStateOn. So please put POwerStateOn on the header.
        if (m_pPowerStateList) {
            // We need get first SetSystemPower from device to make initial power state correct.
            PowerState * pCurPowerState = GetFirstPowerState();
            if (pCurPowerState != NULL) {
                Lock();
                m_pCurPowerState =  pCurPowerState;
                pCurPowerState->EnterState();
                BOOL fDone = FALSE;
                // Create Legacy Registry modify notification event array.
                while (!fDone && pCurPowerState) {
                    PLATFORM_ACTIVITY_STATE curState = (PLATFORM_ACTIVITY_STATE) pCurPowerState->GetState();
                    PLATFORM_ACTIVITY_STATE newState = curState;
                    Unlock();
                    PLATFORM_ACTIVITY_EVENT activityEvent = pCurPowerState->WaitForEvent(INFINITE,0 ,NULL);
                    PMLOGMSG(ZONE_PLATFORM, (_T("%s: activityEvent = %d  \r\n"  ), pszFname,activityEvent)) ;
                    Lock();
                    if (pCurPowerState != m_pCurPowerState) {
                        if (activityEvent!= SystemPowerStateAPI) { 
                            PMLOGMSG(ZONE_ERROR|| ZONE_PLATFORM,(_T("Multiple Event happens during SentSystemPowerState %d, Event will evaluated in new state \r\n"),newState));
                        }
                        pCurPowerState = m_pCurPowerState;
                        newState = curState = (PLATFORM_ACTIVITY_STATE) pCurPowerState->GetState();
						PMLOGMSG(ZONE_PLATFORM, (_T("%s: Jack newState = %d  [pCurPowerState != m_pCurPowerState]\r\n"  ), pszFname, newState));
                        if ((PLATFORM_ACTIVITY_STATE) pCurPowerState->GetState() == Resuming 
                                || (PLATFORM_ACTIVITY_STATE)pCurPowerState->GetState() == Suspend) {
                            // Application call SetSystemPowerState set to Resuming or Suspend in other thread.
                            // This thread come back, calculate time elapsed and update it. So timeout is wrong 
                            // we need re-intialize timeout paramenter
                            ReInitTimeOuts( ) ;
                        }
                    }
                    switch (activityEvent) {
                    case PmShutDown :
                        fDone = TRUE;
                        break;
                    case PmReloadActivityTimeouts:
                        PlatformLoadTimeouts(); // No break we need run ReInitTimeouts.
                    case RestartTimeouts:
                    case PowerSourceChange: 
                    case SystemPowerStateChange:
                    case PowerButtonPressed: 
                    case AppButtonPressed:
                        ReInitTimeOuts();
                        pCurPowerState->DefaultEventHandle( activityEvent ) ;
                        break;
                    case SystemPowerStateAPI:
                        break;
                    default:
						PMLOGMSG(ZONE_PLATFORM, (_T("%s: Jack default case\r\n")));
                        pCurPowerState->DefaultEventHandle( activityEvent ) ;
                        break;
                    }
                    pCurPowerState = SetSystemState(pCurPowerState ) ;
                    ASSERT(pCurPowerState!=NULL);
                    m_pCurPowerState =  pCurPowerState; // Update current state.
                }
                Unlock();
            }
            else
                ASSERT(FALSE);
        }
        return 0;
    }
    virtual void ReAdjustTimeOuts( )  {
        if (m_dwCurSuspendTimeout > GetSuspendTimeOut() ) {
            if ((m_dwCurSuspendTimeout=GetSuspendTimeOut()) == 0 )
                m_dwCurSuspendTimeout = INFINITE ;
        }
        if (m_dwCurTimeoutToSystemIdle > GetSystemIdleTimeOut() ) {
            if ((m_dwCurTimeoutToSystemIdle=GetSystemIdleTimeOut()) == 0 )
                m_dwCurTimeoutToSystemIdle = INFINITE ;
        }
        if (m_dwCurUserIdleTimeout > GetUserIdleTimeOut() ) {
            if ((m_dwCurUserIdleTimeout=GetUserIdleTimeOut()) == 0)
                m_dwCurUserIdleTimeout = INFINITE ;
        }
    }
    
    virtual DWORD GetSmallestTimeout(PTIMEOUT_ITEM pTimeoutItem) {
        DWORD dwReturn = INFINITE;
        TIMEOUT_ITEM activeEvent = NoTimeoutItem;
        if (dwReturn > m_dwCurSuspendTimeout) {
            dwReturn = m_dwCurSuspendTimeout;
            activeEvent = SuspendTimeout ;
        }
        if (dwReturn > m_dwCurTimeoutToSystemIdle) {
            dwReturn = m_dwCurTimeoutToSystemIdle;
            activeEvent = SystemActivityTimeout ;
        }
        if (dwReturn > m_dwCurUserIdleTimeout ) {
            dwReturn = m_dwCurUserIdleTimeout;
            activeEvent = UserActivityTimeout;
        }
        if (pTimeoutItem) {
            *pTimeoutItem = activeEvent;
        }
        return dwReturn;
    }
    void DisableUserIdleTimeout() { m_dwCurUserIdleTimeout = INFINITE; };
    void DisableSuspendTimeout() { m_dwCurSuspendTimeout = INFINITE; };
    void DisableSystemIdleTimeout() { m_dwCurTimeoutToSystemIdle = INFINITE; };
    // Timer Function.
    virtual void ReInitTimeOuts() {
        m_dwCurSuspendTimeout = GetSuspendTimeOut();
        m_dwCurTimeoutToSystemIdle = GetSystemIdleTimeOut();
        m_dwCurUserIdleTimeout = GetUserIdleTimeOut() ;
        // If timer is not set. It is not supported.
        if (m_dwCurUserIdleTimeout == 0 )
            m_dwCurUserIdleTimeout = INFINITE ;
        if (m_dwCurTimeoutToSystemIdle == 0)
            m_dwCurTimeoutToSystemIdle = INFINITE ;
        if (m_dwCurSuspendTimeout == 0)
            m_dwCurSuspendTimeout = INFINITE ;
    }
    virtual void   PlatformResumeSystem(BOOL fSuspened) {
        SETFNAME(_T("PowerStateManager::PlatformResumeSystem"));
        TCHAR szResumeState[MAX_PATH];
        DWORD dwStatus;
        HANDLE hevActivityReset = NULL;
        
        PMLOGMSG(ZONE_RESUME, (_T("+%s: suspend flag is %d\r\n"), pszFname, fSuspened));
        
        // 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(fSuspened);
        if(!fSuspened) {
            // Unexpected resume -- turn everything back on.  OEMs may choose to customize this
            // routine to dynamically determine which system power state is most appropriate rather
            // than using PlatformMapPowerStateHint().
            PMLOGMSG(ZONE_WARN || ZONE_RESUME, (_T("%s: WARNING: unexpected resume!\r\n"), pszFname));
            dwStatus = PlatformMapPowerStateHint(POWER_STATE_ON, szResumeState, dim(szResumeState));
            DEBUGCHK(dwStatus == ERROR_SUCCESS);
            
            // 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.
            dwStatus = PmSetSystemPowerState_I(szResumeState, 0, POWER_FORCE, TRUE);
            DEBUGCHK(dwStatus == ERROR_SUCCESS);
        } else if(m_fActiveManagement) {
            DWORD dwWakeSource, dwBytesReturned;
            BOOL fOk;
            
            // get the system wake source to help determine which power state we resume into
            fOk = KernelIoControl(IOCTL_HAL_GET_WAKE_SOURCE, NULL, 0, &dwWakeSource, 
                sizeof(dwWakeSource), &dwBytesReturned);
            if(fOk) {
                // ioctl succeeded (not all platforms necessarily support it), but sanity check
                // the return value, just in case.
                if(dwBytesReturned != sizeof(dwWakeSource)) {
                    PMLOGMSG(ZONE_WARN, (_T("%s: KernelIoControl() returned an invalid size %d\r\n"),
                        pszFname, dwBytesReturned));
                } else {
                    // look for an activity timer corresponding to this wake source
                    PACTIVITY_TIMER pat = ActivityTimerFindByWakeSource(dwWakeSource);
                    if(pat != NULL) {
                        PMLOGMSG(ZONE_RESUME || ZONE_TIMERS, (_T("%s: signaling '%s' activity at resume\r\n"),
                            pszFname, pat->pszName));
                        hevActivityReset = pat->hevReset;
                    }
                }
            }
            
            // did we find an activity timer?
            if(hevActivityReset == NULL) {
                PMLOGMSG(ZONE_RESUME, (_T("%s: assuming user activity\r\n"), pszFname));
                hevActivityReset = (m_pUserActivity!=NULL ?m_pUserActivity->hevReset: NULL);
            }
        }
        
        // is there an activity timer we need to reset?
        if(hevActivityReset != NULL) {
            // found a timer, elevate the timer management priority thread so that it 
            // executes before the suspending thread
            DWORD dwOldPriority = CeGetThreadPriority(ghtActivityTimers);
            DWORD dwNewPriority = (CeGetThreadPriority(GetCurrentThread()) - 1);
            DEBUGCHK(dwNewPriority >= 0);
            SetEvent(hevActivityReset);
            CeSetThreadPriority(ghtActivityTimers, dwNewPriority);
            CeSetThreadPriority(ghtActivityTimers, dwOldPriority);
        }
        
        PMLOGMSG(ZONE_RESUME, (_T("-%s\r\n"), pszFname));
    }

protected:        
    virtual void    PlatformLoadTimeouts() {
        DWORD dwStatus;
        TCHAR szPath[MAX_PATH];
        HKEY hk;
        SETFNAME(_T("PowerStateManager::PlatformLoadTimeouts"));

        // assume default values
        m_dwACSuspendTimeout = DEF_TIMEOUTTOSUSPEND * 1000;
        m_dwACTimeoutToSystemIdle = DEF_TIMEOUTTOSYSTEMIDLE * 1000 ;
        m_dwACUserIdleTimeout = DEF_TIMEOUTTOUSERIDLE * 1000;
        
        m_dwBattSuspendTimeout = DEF_TIMEOUTTOSUSPEND * 1000;
        m_dwBattTimeoutToSystemIdle = DEF_TIMEOUTTOSYSTEMIDLE * 1000 ;
        m_dwBattUserIdleTimeout = DEF_TIMEOUTTOUSERIDLE * 1000;

⌨️ 快捷键说明

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