📄 battif.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 + -