SW 개발

WM / Driver / 시스템 파워 변화 감시하기 / RequestPowerNotifications

. . . 2010. 3. 29. 18:14
반응형

Xeno's Study Blog (http://XenoStudy.tistory.com )
- 글쓴이 : Xeno
- 출처 : 인터넷
- 기타사항 : windows Mobile 에만 해당되는 사항임. 테스트완료

원본소스 출처 : http://groups.google.com/group/microsoft.public.windowsce.platbuilder/browse_thread/thread/c4fa6558743d079c/a9b58a9e96342ef3?lnk=gst&q=RequestPowerNotifications&rnum=1&pli=1

windows Mobile 의 경우 여러가지 power State 가 존재한다.
드라이버/App 모두 각 pwer State 마다 해줘야할 작업이 따로 있다고 하면 아래와 같은 코드로 간단히 event를 받아서 처리를 할수있다.

관련 MSDN
- RequestPowerNotifications() : http://msdn.microsoft.com/en-us/library/ms919833.aspx

 

#include <windows.h>
#include <PM.h>
// from pmimpl.h file.
#ifndef QUEUE_ENTRIES
#define QUEUE_ENTRIES       3
#endif
#ifndef MAX_NAMELEN
#define MAX_NAMELEN         128
#endif

#ifndef QUEUE_SIZE
#define QUEUE_SIZE          (QUEUE_ENTRIES * (sizeof(POWER_BROADCAST) +
(MAX_NAMELEN * sizeof(TCHAR))))
#endif

int WINAPI PMNotifyThread(LPVOID pvParam);
void PMNotification(HANDLE hMsgQ);

HANDLE ghPMNotifyQ = NULL;

int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPTSTR    lpCmdLine,
                   int       nCmdShow)
{
    MSGQUEUEOPTIONS msgQpm = {0};
    HANDLE hPwrNotify=NULL; // Power manager handle
    HANDLE hPMThread=NULL;

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

    ghPMNotifyQ= CreateMsgQueue(NULL, &msgQpm);

    if (ghPMNotifyQ == NULL)
    {
        DWORD dwErr = GetLastError();
        RETAILMSG(1, (TEXT(" PMNotify:CreateMessageQueue ERROR:%d \r\n"), dwErr));
        return 1;
    }

    // request Power notifications
    hPwrNotify = RequestPowerNotifications(ghPMNotifyQ, PBT_TRANSITION | PBT_RESUME);

    if (hPwrNotify == NULL)
    {
        DWORD dwErr = GetLastError();
        RETAILMSG(1, (TEXT(" PMNotify:RequestPowerNotifications ERROR:%d\r\n"), dwErr));
        return 2;
    }

    // Create PMNotifyThread
    hPMThread = CreateThread(NULL, 0,(LPTHREAD_START_ROUTINE )PMNotifyThread, NULL, 0, NULL);

    if(hPMThread)
    {
        // wait for PMNotifyThread done
        WaitForSingleObject(hPMThread, INFINITE);
        CloseHandle(hPMThread);

        if(hPwrNotify)
        {
            StopPowerNotifications(hPwrNotify);
        }
    }

 return 0;

}

// PMNotifyThread: Wait for Message from PM Driver.
//
int WINAPI PMNotifyThread(LPVOID pvParam)
{
    DWORD dwStatus;

     while (TRUE)
    {
        dwStatus = WaitForSingleObject(ghPMNotifyQ, INFINITE);

        if(dwStatus == WAIT_OBJECT_0)
        {
            PMNotification(ghPMNotifyQ);
        }
        else
        {
            RETAILMSG(1, (TEXT(" PMNotify: WaitForSingleObject returned %d(error %d)\r\n"),dwStatus, GetLastError()));
            break;
        }
    }

    return 0;

}

void PMNotification(HANDLE hMsgQ)
{
    UCHAR pmbuf[QUEUE_SIZE];
    int nBytesRead=0;
    DWORD dwFlags = 0;
    int dwCount = 0;

    memset(pmbuf, 0, sizeof(pmbuf));

    if ( !ReadMsgQueue(hMsgQ,
                       pmbuf,
                       QUEUE_SIZE,
                       (LPDWORD)&nBytesRead,
                       INFINITE,    // Timeout
                       &dwFlags))
    {
        DWORD dwErr = GetLastError();
        RETAILMSG(1, (TEXT(" ProcessPowerNotification: ReadMsgQueue:ERROR:%d\n"), dwErr));
    }
    else if(nBytesRead >= sizeof(POWER_BROADCAST))
    {
        // process power notifications
        //-----------------------------
        PPOWER_BROADCAST pPB = (PPOWER_BROADCAST) pmbuf;

        switch (pPB->Message)
        {
            case PBT_RESUME:
            RETAILMSG(1, (TEXT(" PMNotify:PBT_RESUME \r\n")));
            break;

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

            case PBT_POWERINFOCHANGE:
            RETAILMSG(1, (TEXT(" PMNotify:PBT_POWERSTATUSCHANGE: \r\n")));
            break;

            case PBT_TRANSITION:
            {
            switch (POWER_STATE(pPB->Flags))
            {
                case POWER_STATE_ON:
                break;
                
                case POWER_STATE_OFF:
                break;
                
                case POWER_STATE_CRITICAL:
                break;
                
                case POWER_STATE_BOOT:
                break;
                
                case POWER_STATE_IDLE:
                break;
                
                case POWER_STATE_SUSPEND:
                break;
                
                case POWER_STATE_RESET:
                break;
                
                default:
                break;
                }
                break;
            }

            default:
            break;
        }
    }
} 
반응형