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

📄 pwrbutton.c

📁 Windows CE 6.0 BSP for VOIPAC Board (PXA270) Version 2b.
💻 C
字号:
//
// 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.
//

/* Copyright 1999,2000,2001 Intel Corp.  */
/*++

Module Name:

  pwrbutton.c

Abstract:

  This module is intended as a home for threads that monitor and manage platform features.
  Intial implementation was for for monitoring SW21 on a Mainstone platform which is used
  to trigger SUSPEND/RESUME.

Notes:


--*/

#include <windows.h>
#include <windev.h>
#include <pm.h>
#include <bsp.h>
#include <xllp_pm.h>

#define SIZEOFARRAY(a)  (sizeof(a) / sizeof(a[0]))

#define QUEUE_ENTRIES   16
#define MAX_NAMELEN     64
#define QUEUE_SIZE      (QUEUE_ENTRIES*(sizeof(POWER_BROADCAST)+MAX_NAMELEN))

#define BULVERDE_BASE_REG_PA_PWRMGR 0x40F00000

#define MSCWR3_BIT_GPIO_RESET    (1<<1)
#define MSCWR3_BIT_GPIO_RESET_EN (1<<2)

//volatile MAINSTONEII_BLR_REGS *g_pBCRRegs  = NULL;

BOOL   g_FlagExitThrd = FALSE;
UINT32 g_Irq          = IRQ_GPIO1;
UINT32 g_SysIntr      = SYSINTR_PWRBTN;
HANDLE g_ButtonEvent  = NULL;
HANDLE g_ButtonThread = NULL;
HANDLE g_PwrMonThread = NULL;
HANDLE m_hReadMsgQ    = NULL;

// Power state monitor thread
INT WINAPI PwrMonThread(void)
{
    HANDLE hNotifications;
    MSGQUEUEOPTIONS msgOptions = {0};

    // Create a message queue for Power Manager notifications.
    msgOptions.dwSize        = sizeof(MSGQUEUEOPTIONS);
    msgOptions.dwFlags       = 0;
    msgOptions.dwMaxMessages = QUEUE_ENTRIES;
    msgOptions.cbMaxMessage  = sizeof(POWER_BROADCAST) + MAX_NAMELEN;
    msgOptions.bReadAccess   = TRUE;

    m_hReadMsgQ = CreateMsgQueue(NULL, &msgOptions);
    if ( m_hReadMsgQ == NULL )
    {
        DEBUGMSG(1, (TEXT("PWM: CreateMsgQueue(Read): error %d\r\n"), GetLastError()));
        g_FlagExitThrd = TRUE;
    }

    // Request Power notifications
    hNotifications = RequestPowerNotifications(m_hReadMsgQ, POWER_NOTIFY_ALL);
    if ( ! hNotifications )
    {
        DEBUGMSG(1, (TEXT("PWM: RequestPowerNotifications: error %d\r\n"), GetLastError()));
        g_FlagExitThrd = TRUE;
    }

    while(!g_FlagExitThrd)
    {
        int   iBytesInQueue = 0;
        DWORD dwFlags;
        UCHAR buf[QUEUE_SIZE];
        PPOWER_BROADCAST pB = (PPOWER_BROADCAST) buf;

        memset(buf, 0, QUEUE_SIZE);

        DEBUGMSG(1, (TEXT("PWM: Waiting for PM state transition notification\r\n")));

        // Read message from queue.
        if ( ! ReadMsgQueue(m_hReadMsgQ, buf, QUEUE_SIZE, &iBytesInQueue, INFINITE, &dwFlags) )
        {
            if(g_FlagExitThrd)
                break;
            DEBUGMSG(1, (TEXT("PWM: ReadMsgQueue: ERROR:%d\r\n"), GetLastError()));
        }
        else if ( iBytesInQueue < sizeof(POWER_BROADCAST) )
        {
            DEBUGMSG(1, (TEXT("PWM: Received short message: %d bytes, expected: %d\r\n"),
                                  iBytesInQueue, sizeof(POWER_BROADCAST)));
        }
        else
        {
            switch ( pB->Message )
            {
                case PBT_TRANSITION:

                    RETAILMSG(1, (TEXT("PWM: PBT_TRANSITION to system power state [Flags: 0x%x]: '%s'\r\n"),
                                  pB->Flags, pB->SystemPowerState));

                    switch ( POWER_STATE(pB->Flags) )
                    {
                        case POWER_STATE_ON:
                            DEBUGMSG(1, (TEXT("PWM: POWER_STATE_ON\r\n")));
                            break;

                        case POWER_STATE_OFF:
                            DEBUGMSG(1, (TEXT("PWM: POWER_STATE_OFF\r\n")));
                            break;

                        case POWER_STATE_CRITICAL:
                            DEBUGMSG(1, (TEXT("PWM: POWER_STATE_CRITICAL\r\n")));
                            break;

                        case POWER_STATE_BOOT:
                            DEBUGMSG(1, (TEXT("PWM: POWER_STATE_BOOT\r\n")));
                            break;

                        case POWER_STATE_IDLE:
                            DEBUGMSG(1, (TEXT("PWM: POWER_STATE_IDLE\r\n")));
                            break;

                        case POWER_STATE_SUSPEND:
                            DEBUGMSG(1, (TEXT("PWM: POWER_STATE_SUSPEND\r\n")));
                            break;

                        case POWER_STATE_RESET:
                            DEBUGMSG(1, (TEXT("PWM: POWER_STATE_RESET\r\n")));
                            break;

                        case POWER_STATE_PASSWORD:
                            DEBUGMSG(1, (TEXT("PWM: POWER_STATE_PASSWORD\r\n")));
                            break;

                        case 0:
                            DEBUGMSG(1,(TEXT("PWM: Power State Flags:0x%x\r\n"),pB->Flags));
                            break;

                        default:
                            DEBUGMSG(1,(TEXT("PWM: Unknown Power State Flags:0x%x\r\n"),pB->Flags));
                            break;
                    }
                    break;

                case PBT_RESUME:
                {
                    RETAILMSG(1, (TEXT("PWM: PBT_RESUME\r\n")));

                    // If GPIO1 resumed the system set the system state to ON
                    {
                        DWORD wakeSrc = SYSWAKE_UNKNOWN;
                        DWORD bytesRet= 0;
                        if (KernelIoControl(IOCTL_HAL_GET_WAKE_SOURCE, NULL, 0, &wakeSrc, sizeof(wakeSrc), &bytesRet) &&
                            (bytesRet == sizeof(wakeSrc))) {
                                if (SYSINTR_PWRBTN == wakeSrc) {
                                    SetSystemPowerState(NULL, POWER_STATE_ON, POWER_FORCE);
                                }
                        }
                        else {
                            NKDbgPrintfW(L"PWM: Error getting wake source\r\n");
                        }
                    }

                    break;
                }
                case PBT_POWERSTATUSCHANGE:
                    RETAILMSG(1, (TEXT("PWM: PBT_POWERSTATUSCHANGE\r\n")));
                    break;

                case PBT_POWERINFOCHANGE:
                {
                    PPOWER_BROADCAST_POWER_INFO ppbpi = (PPOWER_BROADCAST_POWER_INFO) pB->SystemPowerState;

                    RETAILMSG(1, (TEXT("PWM: PBT_POWERINFOCHANGE\r\n")));
                    RETAILMSG(1, (TEXT("PWM: \tAC line status %u, battery flag %u, backup flag %u, %d levels\r\n"),
                            ppbpi->bACLineStatus, ppbpi->bBatteryFlag,
                            ppbpi->bBackupBatteryFlag, ppbpi->dwNumLevels));
                    break;
                }

                default:
                    DEBUGMSG(1, (TEXT("PWM: Unknown Message:%d\r\n"), pB->Message));
                    break;
            }
        }
    }

    if ( hNotifications )
    {
        StopPowerNotifications(hNotifications);
        hNotifications = NULL;
    }

    if ( m_hReadMsgQ )
    {
        CloseMsgQueue(m_hReadMsgQ);
        m_hReadMsgQ = NULL;
    }

    DEBUGMSG(1, (TEXT("PWM: PwrMonThread Exiting\r\n")));

    return 0;
}

// Power Button event thread
INT WINAPI ButtonThread(void)
{
    DWORD dwPwrFlags;
    TCHAR szPowerState[MAX_PATH];

    // Mainstone II general purpose switch settings
    UINT32 dwGPSWR = 0;

    while(!g_FlagExitThrd)
    {
        WaitForSingleObject(g_ButtonEvent, INFINITE);
        if(g_FlagExitThrd)
            break;

        // Delay 250ms and get switch settings. Will suspend or reset the device
        // if stays in the position for longer than 250ms.
//        dwGPSWR = g_pBCRRegs->gpsw;

        if(dwGPSWR & SW21_MASK)
        {
            // If any of the additional boot switch is sPBT_TRANSITIONet, reboot the device, else suspend.
            if(dwGPSWR & (CLEAN_BOOT_FLAG | HIVE_CLEAN_FLAG | FORMAT_PART_FLAG))
            {
                RETAILMSG(1, (TEXT("Reboot\r\n")));

                // Suspend the device
                SetSystemPowerState(NULL, POWER_STATE_RESET, POWER_FORCE);

                // Should not come back. Failed if it gets here.
                RETAILMSG(1, (TEXT("Reboot failed\r\n")));
            }
            else
            {
                // Suspend the device
                SetSystemPowerState(NULL, POWER_STATE_SUSPEND, 0);

                // ZZZzzzz.....

                //Note: After system resumes, PwrMonThread (PBT_RESUME) will set the system to 'ON' state

            }
        }
        else
        {
            // Back to "on" state if we are in "unattaneded" mode or "screenoff" mode.
            GetSystemPowerState(szPowerState,SIZEOFARRAY(szPowerState),&dwPwrFlags);

            if((wcscmp(szPowerState,L"unattended")==0) || (wcscmp(szPowerState,L"screenoff")==0))
            {
                // We are in"unattended" or "screenoff" mode. Go back to "on" state.
                SetSystemPowerState(NULL,POWER_STATE_ON,POWER_FORCE);

                // Block until the system is back to the "on" state.
                do
                {
                    Sleep(10);
                    GetSystemPowerState(szPowerState,SIZEOFARRAY(szPowerState),&dwPwrFlags);
                    DEBUGMSG(1, (TEXT("PWB: Power State: '%s'\r\n"), szPowerState));
                } while(!(POWER_STATE(dwPwrFlags) & POWER_STATE_ON));
            }
        }

        InterruptDone(g_SysIntr);
    }

    DEBUGMSG(1, (TEXT("PWB: PwrButtonThread Exiting\r\n")));

    return 0;
} // PWB_ButtonThread()


BOOL WINAPI DllEntry(HANDLE hInstDll, DWORD dwReason, LPVOID lpvReserved)
{
    switch (dwReason)
    {
        case DLL_PROCESS_ATTACH:
            DEBUGMSG(1, (TEXT("DllEntry: DLL_PROCESS_ATTACH (PID=x%08x)\r\n"), GetCurrentProcessId()));

            // don't need thread attach/detach messages
            DisableThreadLibraryCalls ((HMODULE)hInstDll);    
            break;

        case DLL_PROCESS_DETACH:
            DEBUGMSG(1, (TEXT("DllEntry: DLL_PROCESS_DETACH (PID=x%08x)\r\n"), GetCurrentProcessId()));
            break;
    }
    return (TRUE);
}

VOID PWB_PowerUp(VOID)
{
    DEBUGMSG(1, (TEXT("PWB_PowerUp:\r\n")));

    // GPIO1 follows SW21
    //
//    g_pBCRRegs->misc_wr3 &= ~MSCWR3_BIT_GPIO_RESET_EN;

    return;
} // PWB_PowerUp

BOOL PWB_PowerDown(VOID)
{
    DEBUGMSG(1, (TEXT("PWB_PowerDown:\r\n")));

    return(TRUE);
} // PWB_PowerDown

void PWB_UnMapAddresses(void)
{
/*    if(g_pBCRRegs)
    {
        MmUnmapIoSpace((void*)g_pBCRRegs, 0);
        g_pBCRRegs = NULL;
    }*/

    return;
}

BOOL PWB_MapAddresses(void)
{
/*    if (g_pBCRRegs==NULL)
    {
        PHYSICAL_ADDRESS PA = { MAINSTONEII_BASE_REG_PA_FPGA, 0 };
        g_pBCRRegs =(MAINSTONEII_BLR_REGS *) MmMapIoSpace(PA, sizeof(MAINSTONEII_BLR_REGS), FALSE);
    }

    if(!g_pBCRRegs)
    {
        goto CleanUp;
    }
*/
    return TRUE;

 CleanUp:

    DEBUGMSG(1, (TEXT("PWB_InitializeAddresses Failed\r\n")));
    PWB_UnMapAddresses();

    return FALSE;
}

BOOL PWB_Deinit(DWORD p1)
{
    DEBUGMSG(1, (TEXT("PWB_DeInit(x%08x):\r\n"), p1));

    g_FlagExitThrd = TRUE;

    if(g_ButtonEvent)
    {
        SetEvent(g_ButtonEvent);
        InterruptDisable(g_SysIntr);
        CloseHandle(g_ButtonEvent);
    }

    // Signal PwrMonThread to finish (closing the handle will force ReadMsgQueue to return)
    if ( m_hReadMsgQ )
    {
        CloseMsgQueue(m_hReadMsgQ);
        m_hReadMsgQ = NULL;
    }

    // Wait for threads to finish
    WaitForSingleObject(g_ButtonThread, INFINITE);
    WaitForSingleObject(g_PwrMonThread, INFINITE);

    if(g_ButtonThread)
        CloseHandle(g_ButtonThread);

    if(g_PwrMonThread)
        CloseHandle(g_PwrMonThread);

    PWB_UnMapAddresses();

    return (TRUE);
}

DWORD PWB_Init(DWORD p1, DWORD p2)
{
    BOOL result;

    DEBUGMSG(1, (TEXT("PWB_Init(x%08x,x%08x):\r\n"), p1, p2));

    if (!PWB_MapAddresses())
    {
        DEBUGMSG(1, (TEXT("PWB_Init: PWB_InitializeAddresses Failed\r\n")));
        goto CleanUp;
    }

    g_ButtonEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    if( !g_ButtonEvent)
    {
        DEBUGMSG(1, (TEXT("PWB_Init: Failed to create Intterupt Event\r\n")));
        goto CleanUp;
    }

    result = InterruptInitialize(g_SysIntr, g_ButtonEvent, NULL, 0);
    if(!result)
    {
        DEBUGMSG(1, (TEXT("InterruptInitialize() failed. GetLastError=0x%x\r\n"),GetLastError()));
        goto CleanUp;
    }

    g_ButtonThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) ButtonThread, NULL, 0, NULL);
    if ( g_ButtonThread == NULL )
    {
        DEBUGMSG(1, (TEXT("PWB_Init: Failed to create Button Intterupt Thread\r\n")));
        goto CleanUp;
    }

    g_PwrMonThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) PwrMonThread, NULL, 0, NULL);
    if ( g_PwrMonThread == NULL )
    {
        DEBUGMSG(1, (TEXT("PWB_Init: Failed to create Power Monitor Thread\r\n")));
        goto CleanUp;
    }

    PWB_PowerUp();

    KernelIoControl(IOCTL_HAL_ENABLE_WAKE, &g_SysIntr, sizeof(g_SysIntr), NULL, 0, NULL);

    DEBUGMSG(1, (TEXT("PWB_Init: Success\r\n")));
    return(TRUE);

 CleanUp:

    PWB_Deinit(0);
    return (FALSE);
}

DWORD PWB_Open (DWORD dwData, DWORD dwAccess, DWORD dwShareMode)
{
    DEBUGMSG(1, (TEXT("PWB_Open:\r\n")));
    return(0x12345678);
}

BOOL PWB_Close(DWORD dwData)
{
    DEBUGMSG(1, (TEXT("PWB_Close:\r\n")));
    return (TRUE);
}

DWORD PWB_Read (DWORD dwData,  LPVOID pBuf, DWORD Len)
{
    return (0);
}

DWORD PWB_Write(DWORD dwData, LPCVOID pBuf, DWORD Len)
{
    return (0);
}

DWORD PWB_Seek (DWORD dwData, long pos, DWORD type)
{
    return (DWORD)-1;
}

BOOL PWB_IOControl(DWORD hOpenContext,DWORD dwCode,PBYTE pBufIn,DWORD dwLenIn,PBYTE pBufOut,DWORD dwLenOut,PDWORD pdwActualOut)
{
    return(FALSE);
}

⌨️ 快捷键说明

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