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

📄 battif.c

📁 Windows CE 6.0 BSP for VOIP sample phone. Intel PXA270 platform.
💻 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 OR INDEMNITIES.
//
// 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.
//

//
// This module contains a stub implementation of the battery PDD.  OEMs
// that want to support the battery APIs on their platform can copy this
// file to their platform and link it into their own version of the power
// manager DLL.
//
// If the platform-specific power manager provides its own version of these
// entry points, this module will not be pulled into the link map from
// the pm_battapi library.
//
#include <windows.h>
#include <windev.h>
#include <types.h>
#include <memory.h>
#include <string.h>
#include <ceddk.h>
#include <devload.h>
#include <battimpl.h>

#include <bulverde_base_regs.h>
#include <plato.h>
#include <xllp_gpio.h>
#include <xllp_clkmgr.h>
#include <xllp_ost.h>
#include <xllp_i2c.h>
#include "pcf50606.h"


#include <battery.h>

// These are read from the registry
#define DEFAULT_BATTERY_MAX_VOLTAGE     4500
#define DEFAULT_BATTERY_VOLTAGE_HIGH    4000
#define DEFAULT_BATTERY_VOLTAGE_LOW     3600

#define BATTERY_MAX_VOLTAGE_TEXT     TEXT("MaxBatteryVoltage")
#define BATTERY_VOLTAGE_HIGH_TEXT    TEXT("BatteryVoltageHighLevel")
#define BATTERY_VOLTAGE_LOW_TEXT     TEXT("BatteryVoltageLowLevel")

#define PMIC_MESSAGE_LOOP_INTERVAL PCF50606_MAINTENANCE_POLLING_INTERVAL+1000

static DWORD gBatteryVoltage = 0x0;

static BOOL gfACOnline;
static BOOL gfBatteryCharging;
static BOOL gfBatteryDataValid;
static BOOL gfPwrCtrlrThreadRun;
static BOOL gBatteryDriverInitialized;
static HANDLE ghPCF;
static HANDLE ghmqPowerController;
static HANDLE ghPwrCtrlrThread;

static DWORD gdwBatteryMaxVoltage;
static DWORD gdwBatteryVoltageHigh;
static DWORD gdwBatteryVoltageLow;

SYSTEM_POWER_STATUS_EX2 gPowerStatus;

INT WINAPI BatteryMonitorThread(void);
INT WINAPI PowerControllerMessageThread(void);
INT WINAPI BatteryInitializationThread(void);

BOOL WINAPI BatteryDrvrGetStatus( PSYSTEM_POWER_STATUS_EX2 ,PBOOL );
static void UpdateBatteryStatus(void);
static void UpdateBatteryInfo(void);

static CRITICAL_SECTION BatteryStatusAccess;

typedef struct  
{
    BYTE  cPercent;
    DWORD dwVlotage;
}VoltageVsChargeType;

const VoltageVsChargeType g_VoltageVsChargeTable[18] =
{
{100, 4062},
{94,  3937},
{89,  3875},
{83,  3825},
{78,  3812},
{72,  3781},
{67,  3762},
{61,  3656},
{56,  3637},
{50,  3625},
{44,  3612},
{39,  3593},
{33,  3575},
{28,  3562},
{22,  3531},
{17,  3512},
{11,  3437},
{ 6,  3125}
};



//--------------------------------------------------------------------
// Function: LookupBatteryPercentage
// 
// Purpose:  Look up the aproximate battery charge based an battery voltage level
//
// Returns:  Percentage of charge left in battery
//
//---------------------------------------------------------------------
BYTE LookupBatteryPercentage(DWORD dwCurrVoltage)
{
    int i;

    for(i = 0; i < (sizeof(g_VoltageVsChargeTable)/sizeof(g_VoltageVsChargeTable[0])); i++)
    {
        if(dwCurrVoltage > g_VoltageVsChargeTable[i].dwVlotage)
        {
            return g_VoltageVsChargeTable[i].cPercent;
        }
    }

    return 0;
}

// This routine obtains the most current battery/power status available
// on the platform.
static void UpdateBatteryInfo(void)
{
    DWORD   dwActualBytes;
    PSYSTEM_POWER_STATUS_EX2 ppowerstatus=&gPowerStatus;

    if (!DeviceIoControl(ghPCF, 
                         IOCTL_GET_PCF_BATTERY_VOLTAGE, 
                         NULL, 
                         0,
                         (PBYTE)&gBatteryVoltage,
                         sizeof(DWORD),
                         &dwActualBytes,
                         NULL))
    {
        DEBUGMSG(ZONE_ERROR, (_T("DeviceIoControl(IOCTL_GET_PCF_BATTERY_VOLTAGE) failed %d\r\n"), GetLastError()));
        gfBatteryDataValid = FALSE;
    }
}


// This routine fills in the structures pointed to by its parameters
// and returns TRUE if successful.  If there's an error, it returns FALSE.

static void UpdateBatteryStatus(void)
{
    PSYSTEM_POWER_STATUS_EX2 ppowerstatus=&gPowerStatus;

    // Update power status structure
    EnterCriticalSection(&BatteryStatusAccess);

    if (!gfBatteryDataValid)
    {
        ppowerstatus->BatteryFlag = BATTERY_FLAG_UNKNOWN;
    }
    else
    {
        ppowerstatus->ACLineStatus              = gfACOnline?AC_LINE_ONLINE:AC_LINE_OFFLINE;

        // May need to do something different when AC ONLINE
        if (gBatteryVoltage > 0)
            ppowerstatus->BatteryLifePercent    = LookupBatteryPercentage(gBatteryVoltage);
        else
            ppowerstatus->BatteryLifePercent    = 0;

        if(gBatteryVoltage > gdwBatteryVoltageHigh)
            ppowerstatus->BatteryFlag           = BATTERY_FLAG_HIGH;
        else 
            if(gBatteryVoltage > gdwBatteryVoltageLow)
                ppowerstatus->BatteryFlag       = BATTERY_FLAG_LOW;
            else 
                ppowerstatus->BatteryFlag       = BATTERY_FLAG_CRITICAL;

        ppowerstatus->BatteryVoltage            = gBatteryVoltage;
        ppowerstatus->Reserved1                 = 0;
        ppowerstatus->BatteryLifeTime           = BATTERY_LIFE_UNKNOWN;
        ppowerstatus->BatteryFullLifeTime       = BATTERY_LIFE_UNKNOWN;

        ppowerstatus->Reserved2                  = 0;
        ppowerstatus->BackupBatteryFlag          = BATTERY_FLAG_HIGH;
        ppowerstatus->BackupBatteryLifePercent   = 0;
        ppowerstatus->Reserved3                  = 0;
        ppowerstatus->BackupBatteryLifeTime      = BATTERY_LIFE_UNKNOWN;
        ppowerstatus->BackupBatteryFullLifeTime  = BATTERY_LIFE_UNKNOWN;

        ppowerstatus->BatteryChemistry           = BATTERY_CHEMISTRY_LION;
        ppowerstatus->BatteryCurrent             = 0;
        ppowerstatus->BatteryAverageCurrent      = 0;
        ppowerstatus->BatteryAverageInterval     = 0;
        ppowerstatus->BatterymAHourConsumed      = 0;
        ppowerstatus->BatteryTemperature         = 0;
        ppowerstatus->BackupBatteryVoltage       = 0;

        if(gfBatteryCharging)
            ppowerstatus->BatteryFlag= BATTERY_FLAG_CHARGING;
    }

    LeaveCriticalSection(&BatteryStatusAccess);
}


INT WINAPI PowerControllerMessageThread(void)
{
    DWORD dwPowerMessage = 0;
    DWORD dwNumberOfBytesRead = 0;
    DWORD dwFlags = 0;

    while(gfPwrCtrlrThreadRun)
    {
        ReadMsgQueue(ghmqPowerController,
                    (LPVOID)&dwPowerMessage,
                    sizeof(DWORD),
                    (LPDWORD)&dwNumberOfBytesRead,
                    PMIC_MESSAGE_LOOP_INTERVAL,
                    &dwFlags);

        // Process AC messages
        switch (dwPowerMessage & PCF_AC_MESSAGES_MASK)
        {
            case PCF_MSG_AC_CONNECTED:
                DEBUGMSG(ZONE_FUNCTION, (TEXT("PMIC MSG: AC insert\r\n")));
                gfACOnline = TRUE;
                break;

            case PCF_MSG_AC_DISCONNECTED:
                DEBUGMSG(ZONE_FUNCTION, (TEXT("PMIC MSG: AC remove\r\n")));
                gfACOnline = FALSE;
                break;
        }

        // Process Battery messages
        switch (dwPowerMessage & PCF_BATTERY_MESSAGE_MASK)
        {
            case PCF_MSG_BATTERY_FULL:
                DEBUGMSG(ZONE_FUNCTION, (TEXT("PMIC MSG: Batt full\r\n")));

                if (!gfACOnline)
                    gfBatteryDataValid = FALSE;
                break;
                
            case PCF_MSG_BATTERY_LOW:
                DEBUGMSG(ZONE_FUNCTION, (TEXT("PMIC MSG: Batt empty\r\n")));
                break;
                
            case PCF_MSG_BATTERY_VOLTAGE:
                DEBUGMSG(ZONE_FUNCTION, (TEXT("PMIC MSG: Batt voltage\r\n")));
                UpdateBatteryInfo();
                break;
        }
    }

    return 0;
}


//--------------------------------------------------------------------
// Function: BatteryPDDInitialize
// 
// Purpose:  Initialize the battery driver
//
// Returns:  TRUE success
//           FALSE failure
//
//---------------------------------------------------------------------
BOOL WINAPI 
BatteryPDDInitialize(LPCTSTR pszRegistryContext)
{
    DWORD dwActualBytes = 0;
    HANDLE hPwrCtrlrThread = NULL;
    HKEY hKey = NULL;
    
    // Initialize the global variables
    gBatteryVoltage = 0x0;
    gfACOnline = FALSE;
    gfBatteryCharging = FALSE;
    gfBatteryDataValid = TRUE;
    gBatteryDriverInitialized = FALSE;
    gfPwrCtrlrThreadRun = FALSE;
    ghPCF = INVALID_HANDLE_VALUE;
    ghPwrCtrlrThread = NULL;
    ghmqPowerController = NULL;
    gdwBatteryMaxVoltage = DEFAULT_BATTERY_MAX_VOLTAGE;
    gdwBatteryVoltageHigh = DEFAULT_BATTERY_VOLTAGE_HIGH;
    gdwBatteryVoltageLow = DEFAULT_BATTERY_VOLTAGE_LOW;

    InitializeCriticalSection(&BatteryStatusAccess);
    memset(&gPowerStatus,0,sizeof(gPowerStatus));

    // get registry values, if present, for the voltage thresholds
    hKey = OpenDeviceKey(pszRegistryContext);
    if(hKey != NULL) 
    {
        DWORD dwSize, dwStatus, dwType, dwValue;
        
        dwSize = sizeof(dwValue);
        dwStatus = RegQueryValueEx(hKey, BATTERY_MAX_VOLTAGE_TEXT, NULL, &dwType, (LPBYTE) &dwValue, &dwSize);
        if(dwStatus == ERROR_SUCCESS && dwType == REG_DWORD) 
        {
            gdwBatteryMaxVoltage = (DWORD) dwValue;
        }
        
        dwSize = sizeof(dwValue);
        dwStatus = RegQueryValueEx(hKey, BATTERY_VOLTAGE_HIGH_TEXT, NULL, &dwType, (LPBYTE) &dwValue, &dwSize);
        if(dwStatus == ERROR_SUCCESS && dwType == REG_DWORD) 
        {
            gdwBatteryVoltageHigh = (DWORD) dwValue;
        }

        dwSize = sizeof(dwValue);
        dwStatus = RegQueryValueEx(hKey, BATTERY_VOLTAGE_LOW_TEXT, NULL, &dwType, (LPBYTE) &dwValue, &dwSize);
        if(dwStatus == ERROR_SUCCESS && dwType == REG_DWORD) 
        {
            gdwBatteryVoltageLow = (DWORD) dwValue;
        }
        
        RegCloseKey(hKey);
    }

    // Open PMIC driver.
    ghPCF = CreateFile(TEXT("PCF1:"), 0, 0, NULL, 
                      OPEN_EXISTING,
                      FILE_ATTRIBUTE_NORMAL,
                      NULL);

    if (ghPCF == INVALID_HANDLE_VALUE)
    {
        DEBUGMSG(ZONE_ERROR, (_T("CreateFile(%s) failed %d\r\n"),TEXT("PCF1:"),GetLastError()));
        goto Error;
    }

    // Get message queue handle
    if (!DeviceIoControl(ghPCF, 
                         IOCTL_GET_PCF_MSGQUEUE, 
                         NULL, 
                         0,
                         &(PBYTE)ghmqPowerController,
                         sizeof(HANDLE),
                         &dwActualBytes,
                         NULL))
    {
        DEBUGMSG(ZONE_ERROR, (_T("DeviceIoControl(IOCTL_GET_PCF_MSGQUEUE) failed %d\r\n"), GetLastError()));
        goto Error;
    }

    // call UpdateBatteryInfo() so that the battery voltages are read and updated.
    UpdateBatteryInfo();

    gfPwrCtrlrThreadRun = TRUE;
    ghPwrCtrlrThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PowerControllerMessageThread, NULL, 0, NULL);
    if (ghPwrCtrlrThread == NULL)
    {
        DEBUGMSG(ZONE_ERROR, (_T("CreateThread failed. Err = %d\r\n"), GetLastError()));
        goto Error;
    }

    return TRUE;

Error:
    BatteryPDDDeinitialize();
    return FALSE;
}


void WINAPI 
BatteryPDDDeinitialize(void)
{
    gfPwrCtrlrThreadRun = FALSE;
    if (ghPwrCtrlrThread != NULL)
    {
        WaitForSingleObject(ghPwrCtrlrThread, PMIC_MESSAGE_LOOP_INTERVAL+100);
        CloseHandle(ghPwrCtrlrThread);
        ghPwrCtrlrThread = NULL;
    }

    if (ghPCF)
    {
        CloseHandle(ghPCF);
        ghPCF = NULL;
    }
    
    DeleteCriticalSection(&BatteryStatusAccess);
}

void WINAPI 
BatteryPDDResume(void)
{
}

void WINAPI 
BatteryPDDPowerHandler(BOOL bOff)
{
    //UNREFERENCED_PARAMETER(bOff);
}


BOOL WINAPI
BatteryPDDGetStatus(
                    PSYSTEM_POWER_STATUS_EX2 ppowerstatus,
                    PBOOL pfBatteriesChangedSinceLastCall)
{
    BOOL fRetVal = FALSE;

    DEBUGMSG(ZONE_BATTERY, (TEXT("GET STATUS: BatteryPDDGetStatus\r\n")));

    if(ppowerstatus)
    {
        UpdateBatteryStatus();

        memcpy(ppowerstatus,&gPowerStatus,sizeof(gPowerStatus));
        *pfBatteriesChangedSinceLastCall = FALSE;

        fRetVal = TRUE;
    }
    else
    {
        SetLastError(ERROR_INVALID_PARAMETER);
    }

    return fRetVal;
}

// This routine indicates how many battery levels will be reported in the
// BatteryFlag and BackupBatteryFlag fields of the PSYSTEM_POWER_STATUS_EX2
// filed in by BatteryPDDGetStatus().  This number ranges from 0 through 3.
// See the Platform Builder documentation for details.  The main battery
// level count is reported in the low word of the return value; the count 
// for the backup battery is in the high word.

LONG
BatteryPDDGetLevels(void)
{
    LONG lLevels = MAKELONG (3 /* main battery levels   */,  
                             3 /* backup battery levels */);

    return lLevels;
}

// This routine returns TRUE to indicate the pfBatteriesChangedSinceLastCall
// value filled in by BatteryPDDGetStatus() is valid.  If there is no way to
// tell that the platform's batteries have been changed this routine should
// return FALSE.

BOOL
BatteryPDDSupportsChangeNotification(void)
{
    return FALSE;
}

⌨️ 快捷键说明

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