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

📄 battdrvr.c

📁 pxa270平台 windows mobile 5.2 wm9713 触摸屏+音频驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/*******************************************************************************
 * Copyright (c) Microsoft Corporation.  All rights reserved.
 *
 *
 * Use of this source code is subject to the terms of the Microsoft end-user
 * license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
 * If you did not accept the terms of the EULA, you are not authorized to use
 * this source code. For a copy of the EULA, please see the LICENSE.RTF on your
 * install media.
 *
 *                                                                         *//**
 * @file   battdriver.c
 * @brief  Sample Battery Driver.
 *
 * This module contains a sample battery driver for windows CE.  It
 * exposes its interface to the system via a set of IOCTLs which device.exe
 * invokes on its behalf when one of the battery APIs are invoked.  The
 * following APIs are modeled in this way:
 *
 *      GetSystemPowerStatusEx
 *      GetSystemPowerStatusEx2
 *      BatteryGetLifeTimeInfo
 *      BatteryDrvrSupportsChangeNotification
 *      BatteryDrvrGetLevels
 *      BatteryNotifyOfTimeChange
 *
 * When it initializes, this driver is responsible for setting the battery
 * API ready event to indicate it is ready to receive IOCTLs in response
 * to these APIs.
 *
 * This example driver comes with a stubbed-out implementation of the
 * low-level battery interfaces.  OEMs that wish to produce their own
 * battery driver can write a module containing the low-level entry points
 * in their platform and simply link with the library containing this module.
 * The linker will bring in the rest of the driver as an MDD.
 *
 * The low-level interfaces necessary that must be overridden to produce
 * a platform-specific PDD are:
 *
 *      BatteryPDDInitialize
 *      BatteryPDDDeinitialize
 *      BatteryPDDGetStatus
 *      BatteryPDDGetLevels
 *      BatteryPDDSupportsChangeNotification
 *      BatteryPDDPowerHandler
 *      BatteryPDDResume
 *
 * @version $Id$
 *
 ******************************************************************************/

/*
 * Include files
 */

#define BATTERY_DATA_DEF    /** global battery driver variables defined here */

#include <battimpl.h>
#include <nkintr.h>
#include <devload.h>
#include <pmpolicy.h>

/*
 * Global Definitions
 */

#define DEF_BATTERYPOLLTIMEOUT          500         /** in milliseconds */

/** this structure contains startup parameters for the battery monitor
    thread */
typedef struct _batteryContext_tag {
    DWORD       dwPollTimeout;
    int         iPriority;
    SYSTEM_POWER_STATUS_EX2 st;
} BATTERY_CONTEXT, * PBATTERY_CONTEXT;

CRITICAL_SECTION gcsBattery;
PFN_BATTERY_PDD_IOCONTROL gpfnBatteryPddIOControl;
HANDLE ghevResume;
HANDLE ghtBattery;
BOOL gfExiting;
BATTERY_CONTEXT gBatteryContext;


/******************************************************************************
 * Function: BatteryThreadProc                                            *//**
 *
 * @brief   This thread handles resume notifications for the battery driver. It
 *          will also poll the battery for status updates at regular intervals,
 *          depending on the poll interval configuration in the registry.
 *
 *****************************************************************************/
DWORD WINAPI BatteryThreadProc(PVOID pvParam)
{
    BOOL fDone = FALSE;
    BOOL fOk;
    PBATTERY_CONTEXT pbc = (PBATTERY_CONTEXT) pvParam;
    SETFNAME(_T("Battery: BatteryThreadProc"));

    DEBUGCHK(ghevResume != NULL);
#ifndef WM_PRE_500			/* PREFAST_DEBUGCHK does not exist n 4.2 */
    PREFAST_DEBUGCHK(pbc != NULL);
#endif

    /** set my thread priority */
    DEBUGMSG(ZONE_RESUME,
        (_T("%s: thread priority is %d, timeout is %u, ID is 0x%08x\r\n"),
        pszFname, pbc->iPriority, pbc->dwPollTimeout, GetCurrentThreadId()));
    CeSetThreadPriority(GetCurrentThread(), pbc->iPriority);

    /** tell the Power Manager to initialize its battery state */
    fOk = PowerPolicyNotify(PPN_POWERCHANGE, 0);
    DEBUGCHK(fOk);

    /** wait for the system to resume */
    while(!fDone) {
        DWORD dwStatus = WaitForSingleObject(ghevResume, pbc->dwPollTimeout);
        switch(dwStatus) {
        case WAIT_TIMEOUT:
            {
                SYSTEM_POWER_STATUS_EX2 tmpst;

                /** update battery status information */
                LOCKBATTERY();
                dwStatus = BatteryAPIGetSystemPowerStatusEx2
                    (&tmpst, sizeof(tmpst), TRUE);
                DEBUGCHK(dwStatus == sizeof(pbc->st));
                UNLOCKBATTERY();

                /** has anything changed? */
                if(memcmp(&tmpst, &pbc->st, sizeof(pbc->st)) != 0) {
                    /** yes, update our global variable and notify the power
                        manager */
                    pbc->st = tmpst;
                    fOk = PowerPolicyNotify(PPN_POWERCHANGE, 0);
                    DEBUGCHK(fOk);
                }
            }
            break;
        case WAIT_OBJECT_0:	/** system has resumed */
            /** GetTickCount() stops incrementing during suspends, so we can
                stop and restart the battery stopwatch during resume. */
            DEBUGMSG(ZONE_RESUME, (_T("%s: system has resumed\r\n"), pszFname));
            BatteryAPIStopwatch(FALSE, FALSE);
            BatteryAPIStopwatch(TRUE, FALSE);
            BatteryPDDResume();
            break;
        default:
            DEBUGMSG(ZONE_RESUME,
                (_T("%s: WaitForSingleObject() returned %d, error %d\r\n"),
                pszFname, dwStatus, GetLastError()));
            fDone = TRUE;
            break;
        }

        /** check whether we're supposed to exit */
        if(gfExiting) fDone = TRUE;
    }

    DEBUGMSG(ZONE_RESUME, (_T("%s: exiting\r\n"), pszFname));
    return 0;
}


/******************************************************************************
 * Function: Init                                                         *//**
 *
 * @brief   This routine initializes the battery driver.  Since it should only
 *          be loaded once, it returns an error if this routine is called more
 *          than once.
 *
 *****************************************************************************/
DWORD Init( PVOID Context )
{
    DWORD dwHandle = 0;     /** assume failure */
    SETFNAME(_T("BattDrvr: Init"));

    DEBUGMSG(ZONE_INIT, (_T("%s: invoked w/ context 0x%08x\r\n"),
        pszFname, Context));

    /** have we already been loaded? */
    if(ghevResume == NULL) {
        /** get a handle to our API event */
        HANDLE hevReady =
            OpenEvent(EVENT_ALL_ACCESS, FALSE, BATTERY_API_EVENT_NAME);
        if(hevReady == NULL) {
            DEBUGMSG(ZONE_ERROR || ZONE_INIT,
                (_T("%s: fatal error: can't open API event\r\n"), pszFname));
            goto done;
        }

        // no, initialize global variables
        InitializeCriticalSection(&gcsBattery);
        gpfnBatteryPddIOControl = NULL;     // must be initialized by the PDD
        ghevResume = CreateEvent(NULL, FALSE, FALSE, NULL);
        if(ghevResume == NULL) {
            DEBUGMSG(ZONE_ERROR || ZONE_INIT,
                (_T("%s: CreateEvent() failed\r\n"), pszFname));
        } else {
            if(!BatteryPDDInitialize(Context)) {
                DEBUGMSG(ZONE_ERROR || ZONE_INIT,
                    (_T("%s: BatteryPDDInitialize() failed\r\n"), pszFname));
            } else {
                HKEY hk;
                DWORD dwLen;

                /** init defaults */
                gBatteryContext.dwPollTimeout = DEF_BATTERYPOLLTIMEOUT;
                gBatteryContext.iPriority = 249; /** THREAD_PRIORITY_HIGHEST */
                memset(&gBatteryContext.st, 0xFF, sizeof(gBatteryContext.st));

                /** get my thread priority configuration */
                hk = OpenDeviceKey(Context);
                if(hk != NULL) {
                    DWORD dwValue, dwType, dwSize, dwStatus;

                    /** get the thread priority */
                    dwSize = sizeof(dwValue);
                    dwStatus = RegQueryValueEx(hk, _T("PollPriority256"),
                        NULL, &dwType, (LPBYTE) &dwValue, &dwSize);
                    if(dwStatus == ERROR_SUCCESS && dwType == REG_DWORD) {
                        gBatteryContext.iPriority = (INT) dwValue;
                    }

                    /** get the polling interval */
                    dwSize = sizeof(dwValue);
                    dwStatus = RegQueryValueEx(hk, _T("PollInterval"), NULL,
                        &dwType, (LPBYTE) &dwValue, &dwSize);
                    if(dwStatus == ERROR_SUCCESS && dwType == REG_DWORD) {
                        gBatteryContext.dwPollTimeout = dwValue;
                    }

                    RegCloseKey(hk);
                }

                /** initialize battery update variables */
                dwLen = BatteryAPIGetSystemPowerStatusEx2
                    (&gBatteryContext.st, sizeof(gBatteryContext.st), TRUE);
                DEBUGCHK(dwLen == sizeof(gBatteryContext.st));

                /** start the battery monitor/resume thread */
                ghtBattery = CreateThread(NULL, 0, BatteryThreadProc,
                    &gBatteryContext, 0, NULL);
                if(ghtBattery == NULL) {
                    DEBUGMSG(ZONE_ERROR || ZONE_INIT,
                        (_T("%s: CreateThread() failed %d\r\n"), pszFname,
                        GetLastError()));
                } else {
                    /** notify the world that we're up and running */
                    SetEvent(hevReady);
                    CloseHandle(hevReady);

                    /** return success */
                    dwHandle = 1;
                }
            }
        }

done:
        /** clean up if something went wrong */
        if(dwHandle == 0) {
            if(ghtBattery != NULL) {
                DEBUGCHK(ghevResume != NULL);
                gfExiting = TRUE;
                SetEvent(ghevResume);
                WaitForSingleObject(ghtBattery, INFINITE);
                CloseHandle(ghtBattery);
                ghtBattery = NULL;
            }
            if(ghevResume != NULL) {
                CloseHandle(ghevResume);
                ghevResume = NULL;
            }
            DeleteCriticalSection(&gcsBattery);
        }
    }

    DEBUGMSG(ZONE_INIT, (_T("%s: returning %d\r\n"), pszFname, dwHandle));
    return dwHandle;
}

/******************************************************************************
 * Function: Init                                                         *//**
 *
 *****************************************************************************/
BOOL Deinit( DWORD dwContext )
{
    DEBUGMSG(ZONE_INIT, (_T("Battery: Deinit: invoked w/ context 0x%08x\r\n"),
        dwContext));

    DEBUGCHK(dwContext == 1);
    DEBUGCHK(ghevResume != NULL);

    /** notify the PDD */
    BatteryPDDDeinitialize();

    /** clean up global variables */
    if(ghtBattery != NULL) {
        gfExiting = TRUE;
        SetEvent(ghevResume);
        WaitForSingleObject(ghtBattery, INFINITE);
        CloseHandle(ghtBattery);
        ghtBattery = NULL;
    }
    if(ghevResume != NULL) {
        CloseHandle(ghevResume);
        ghevResume = NULL;
    }
    DeleteCriticalSection(&gcsBattery);

    DEBUGMSG(ZONE_INIT, (_T("Battery: Deinit: all done\r\n")));
    return TRUE;
}

/******************************************************************************
 * Function: IOControl                                                    *//**
 *
 *****************************************************************************/
BOOL IOControl( DWORD  dwContext, DWORD  Ioctl, PUCHAR pInBuf, DWORD  InBufLen,
    PUCHAR pOutBuf, DWORD  OutBufLen, PDWORD pdwBytesTransferred )
{
    DWORD  dwErr = ERROR_INVALID_PARAMETER;
    BOOL   bRc = FALSE;
    SETFNAME(_T("IOControl"));

    DEBUGMSG(ZONE_FUNCTION, (_T
("%s: IOCTL:0x%x, InBuf:0x%x, InBufLen:%d, OutBuf:0x%x, OutBufLen:0x%x)\r\n"),
        pszFname, Ioctl, pInBuf, InBufLen, pOutBuf, OutBufLen));

    switch (Ioctl) {
    case IOCTL_BATTERY_GETSYSTEMPOWERSTATUSEX2:
        /** sanity check parameters */
        if(pOutBuf != NULL && OutBufLen == sizeof(SYSTEM_POWER_STATUS_EX2)
            && pInBuf != NULL && InBufLen == sizeof(BOOL) && pdwBytesTransferred != NULL) {
            BOOL fOk = FALSE;
            BOOL fForce;

            /** get the force parameter */
            __try {
                fForce = *((BOOL *) pInBuf);
                fOk = TRUE;
            }
            __except(EXCEPTION_EXECUTE_HANDLER) {
                DEBUGMSG(ZONE_WARN, (_T
("%s: exception reading fForce in IOCTL_BATTERY_GETSYSTEMPOWERSTATUSEX\r\n"),
                    pszFname));
            }

            /** did we get the force parameter? */
            if(fOk) {
                DWORD dwStatus = 0;
                DEBUGCHK(fForce == TRUE || fForce == FALSE);

                /** get the data */
                LOCKBATTERY();
                __try {
                    dwStatus = BatteryAPIGetSystemPowerStatusEx2(
                        (PSYSTEM_POWER_STATUS_EX2) pOutBuf, OutBufLen, fForce);
                }
                __except(EXCEPTION_EXECUTE_HANDLER) {
                    DEBUGMSG(ZONE_WARN, (_T
("%s: exception reading status in IOCTL_BATTERY_GETSYSTEMPOWERSTATUSEX2\r\n"),
                        pszFname));
                    dwErr = ERROR_GEN_FAILURE;
                }
                UNLOCKBATTERY();

⌨️ 快捷键说明

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