📄 pcf50606.c
字号:
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
BOOL
PCF_Close(
DWORD hOpenContext )
{
BOOL fRetVal = FALSE;
PPCF50606OPEN pContext = NULL;
PPCF50606OPEN pPcf50606Open = (PPCF50606OPEN)hOpenContext;
PPCF50606 pPCF50606 = (PPCF50606)pPcf50606Open->pPCF50606Device;
DEBUGMSG(ZONE_VERBOSE, (TEXT("PCF_Close()\r\n")));
// Walk the list to find the open context and delete it.
pContext = (PPCF50606OPEN)pPCF50606->pOpenContextHead;
// Head cannot be null if we are here
DEBUGCHK(NULL != pContext);
if (pContext->next == NULL)
{
// This means there is only one open context
ASSERT(pPcf50606Open->dwIndex = pContext->dwIndex);
// Deleting the only open context
CloseMsgQueue(pContext->msgQueuePCFRead);
LocalFree(pContext);
pPCF50606->pOpenContextHead = NULL;
pPCF50606->dwOpenCount = 0;
return TRUE;
}
// Walk the list to find the index we are going to close.
while (pContext->next != NULL &&
((PPCF50606OPEN)(pContext->next))->dwIndex != pPcf50606Open->dwIndex)
{
pContext = (PPCF50606OPEN)pContext->next;
}
if (pContext->next == NULL)
{
// This should not happen. We couldn't find the open index in our list
DEBUGCHK(0);
fRetVal = FALSE;
}
else
{
// Found it! Free up the resources
pContext->next = ((PPCF50606OPEN)(pContext->next))->next;
pContext = (PPCF50606OPEN)pContext->next;
CloseMsgQueue(pContext->msgQueuePCFRead);
LocalFree(pContext);
pContext = NULL;
fRetVal = TRUE;
}
return fRetVal;
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
DWORD
PCF_Read(
DWORD hOpenContext,
LPVOID pBuffer,
DWORD Count)
{
DEBUGMSG(ZONE_VERBOSE, (TEXT("PCF_Read()\r\n")));
return((DWORD) -1);
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
DWORD
PCF_Write(
DWORD hOpenContext,
LPCVOID pBuffer,
DWORD Count)
{
DEBUGMSG(ZONE_VERBOSE, (TEXT("PCF_Write()\r\n")));
return((DWORD) -1);
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
DWORD
PCF_Seek(
DWORD hOpenContext,
long Amount,
WORD Type)
{
DEBUGMSG(ZONE_VERBOSE, (TEXT("PCF_Seek()\r\n")));
return((DWORD) -1);
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
void
PCF_PowerUp(DWORD hDeviceContext)
{
DWORD bytesReturned;
PPCF50606 pPCF50606 = (PPCF50606)hDeviceContext;
RETAILMSG(ZONE_VERBOSE, (TEXT("PCF50606: PCF_PowerUp.\r\n")));
// Initial low level I2C processor registers;
XllpPI2CInit((P_XLLP_PI2C_T)pPCF50606->v_pPI2CRegs,
(P_XLLP_GPIO_T)pPCF50606->v_pGPIORegs,
(P_XLLP_CLKMGR_T)pPCF50606->v_pClkRegs,
(XLLP_UINT32_T)0);
// Set Interrupt mask registers
// Input interrupt masks
pPCF50606->pcfRegisterCache[INT1M] = ~INT1MASK_RUN_DEFAULT;
// Charger interrupt masks
pPCF50606->pcfRegisterCache[INT2M] = ~INT2MASK_RUN_DEFAULT;
// Analog interrupt masks
pPCF50606->pcfRegisterCache[INT3M] = ~INT3MASK_RUN_DEFAULT;
// Write to PCF50606
bytesReturned = PDD_I2CWrite(&pPCF50606->csI2CAccess,
pPCF50606->v_pI2CRegs,
pPCF50606->v_pOstRegs,
INT1M,
pPCF50606->pcfRegisterCache+INT1M,
(DWORD)3);
// Turn on falling edge detection
pPCF50606->v_pGPIORegs->GFER0 |= XLLP_BIT_0;
// Clear pending edge interrupt
pPCF50606->v_pGPIORegs->GEDR0 &= ~(XLLP_BIT_0);
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
void
PCF_PowerDown(
DWORD hDeviceContext)
{
DWORD bytesReturned;
PPCF50606 pPCF50606 = (PPCF50606)hDeviceContext;
//
// Set Interrupt mask registers to set which of the pcf50606 interrupts
// will interrupt and wake up the host from sleep
//
// Input interrupt masks
pPCF50606->pcfRegisterCache[INT1M] = ~INT1MASK_SLEEP_DEFAULT;
// Charger interrupt masks
pPCF50606->pcfRegisterCache[INT2M] = ~INT2MASK_SLEEP_DEFAULT;
// Analog interrupt masks
pPCF50606->pcfRegisterCache[INT3M] = ~INT3MASK_SLEEP_DEFAULT;
// Write to PCF50606
bytesReturned = PDD_I2CWrite(&pPCF50606->csI2CAccess,
pPCF50606->v_pI2CRegs,
pPCF50606->v_pOstRegs,
INT1M,
pPCF50606->pcfRegisterCache+INT1M,
(DWORD)3);
// turn off the 3.3V_A1 supply rail
pPCF50606->pcfRegisterCache[D3REGC1] = 0xd8;
bytesReturned = PDD_I2CWrite(&pPCF50606->csI2CAccess,
pPCF50606->v_pI2CRegs,
pPCF50606->v_pOstRegs,
D3REGC1,
pPCF50606->pcfRegisterCache+D3REGC1,
(DWORD)1);
}
static BOOL PCFSetLEDState(PPCF50606 pPCF50606, UCHAR cLedNum, INT OffOnBlink, LONG *OnTime, LONG *OffTime)
{
BOOL fRetVal = FALSE;
UCHAR cGPOCRegisterAddress = 0;
UCHAR cLEDCRegisterAddress = 0;
UCHAR cPeriodValue = 0;
UCHAR cOnTimeValue = 0;
SETFNAME(_T("PCFSetLEDState"));
LONG TotalCycleTime = *OnTime + *OffTime;
//basic parameter checking
if((0 > OffOnBlink) || (2 < OffOnBlink))
{
DEBUGMSG(ZONE_ERROR,
(_T("%s: Invalid OffOnBlink state 0x%x\r\n"), pszFname, OffOnBlink));
SetLastError(ERROR_INVALID_PARAMETER);
}
else if((0 >= *OnTime) ||
(0 >= *OffTime))
{
DEBUGMSG(ZONE_ERROR,
(_T("%s: Negative or Zero OnTime (%duSec) or OffTime(%duSec) time.\r\n"), pszFname, *OnTime, *OffTime));
SetLastError(ERROR_INVALID_PARAMETER);
}
else
{
fRetVal = TRUE;
}
if(fRetVal)
{
if(1 == cLedNum)
{
cGPOCRegisterAddress = GPOC2;
cLEDCRegisterAddress = LEDC1;
}
else
{
cGPOCRegisterAddress = GPOC3;
cLEDCRegisterAddress = LEDC2;
}
//OFF
if(0 == OffOnBlink)
{
//Tristate Output
pPCF50606->pcfRegisterCache[cGPOCRegisterAddress] = 0;
PDD_I2CWrite(&pPCF50606->csI2CAccess,
pPCF50606->v_pI2CRegs,
pPCF50606->v_pOstRegs,
cGPOCRegisterAddress,
pPCF50606->pcfRegisterCache+cGPOCRegisterAddress,
(DWORD)1);
}
else if(2 >= OffOnBlink) //ON or Blinking
{
//set Output for LED control
pPCF50606->pcfRegisterCache[cGPOCRegisterAddress] = GPOC2_5_GPOOD_AC_M(GPOC2_5_LED1);
PDD_I2CWrite(&pPCF50606->csI2CAccess,
pPCF50606->v_pI2CRegs,
pPCF50606->v_pOstRegs,
cGPOCRegisterAddress,
pPCF50606->pcfRegisterCache+cGPOCRegisterAddress,
(DWORD)1);
if(1 == OffOnBlink) //ON
{
pPCF50606->pcfRegisterCache[cLEDCRegisterAddress] = LEDC_ACTSET | LEDC_PATTERN_M(PATTERN_ON_ALL);
PDD_I2CWrite(&pPCF50606->csI2CAccess,
pPCF50606->v_pI2CRegs,
pPCF50606->v_pOstRegs,
cLEDCRegisterAddress,
pPCF50606->pcfRegisterCache+cLEDCRegisterAddress,
(DWORD)1);
}
else
{
//match the closest cycle period possible with the period value table
for(cPeriodValue = 0; cPeriodValue < NUM_PERIOD_OPTIIONS; cPeriodValue++)
{
if(g_PcfLedPeriodOptions[cPeriodValue] > TotalCycleTime)
{
if(0 == cPeriodValue)
{
break;
}
else
{
DWORD DistanceFromA = TotalCycleTime - g_PcfLedPeriodOptions[cPeriodValue -1];
DWORD DistanceFromB = g_PcfLedPeriodOptions[cPeriodValue] - TotalCycleTime;
if(DistanceFromA > DistanceFromB)
{
break;
}
else
{
cPeriodValue--;
break;
}
}
}
}
if(NUM_PERIOD_OPTIIONS == cPeriodValue)
{
cPeriodValue--;
}
//match the closest on_time possible with the on_time table
for(cOnTimeValue = 0; cOnTimeValue < NUM_ON_TIME_OPTIIONS; cOnTimeValue++)
{
if(g_PcfLedOnTimeOptions[cOnTimeValue] > *OnTime)
{
if(0 == cOnTimeValue)
{
break;
}
else
{
DWORD DistanceFromA = *OnTime - g_PcfLedOnTimeOptions[cOnTimeValue -1];
DWORD DistanceFromB = g_PcfLedOnTimeOptions[cOnTimeValue] - *OnTime;
if(DistanceFromA > DistanceFromB)
{
break;
}
else
{
cOnTimeValue--;
break;
}
}
}
}
if(NUM_ON_TIME_OPTIIONS == cOnTimeValue)
{
cOnTimeValue--;
}
pPCF50606->pcfRegisterCache[cLEDCRegisterAddress] = LEDC_ACTSET | LEDC_PERIOD_M(cPeriodValue) | LEDC_PATTERN_M(cOnTimeValue);
PDD_I2CWrite(&pPCF50606->csI2CAccess,
pPCF50606->v_pI2CRegs,
pPCF50606->v_pOstRegs,
cLEDCRegisterAddress,
pPCF50606->pcfRegisterCache+cLEDCRegisterAddress,
(DWORD)1);
//fill in OffTime relative to period of cycle
*OffTime = TotalCycleTime - *OnTime;
}
}
}
return fRetVal;
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
BOOL
PCF_IOControl(
DWORD hOpenContext,
DWORD dwCode,
PBYTE pBufIn,
DWORD dwLenIn,
PBYTE pBufOut,
DWORD dwLenOut,
PDWORD pdwActualOut)
{
BOOL fRetVal = FALSE;
PPCF50606OPEN pPcf50606Open = (PPCF50606OPEN)hOpenContext;
PPCF50606 pPCF50606 = (PPCF50606)pPcf50606Open->pPCF50606Device;
SETFNAME(_T("PCF_IOControl"));
// Allow only kernel mode access
if (GetDirectCallerProcessId() != GetCurrentProcessId())
{
RETAILMSG(ZONE_ERROR, (TEXT("PCF_IOControl: User mode calls not allowed.\r\n")));
SetLastError(ERROR_ACCESS_DENIED);
return FALSE;
}
switch(dwCode)
{
case IOCTL_GET_PCF_MSGQUEUE:
__try {
*((PHANDLE) pBufOut) = pPcf50606Open->msgQueuePCFRead;
if(pdwActualOut)
{
*pdwActualOut = sizeof(HANDLE);
}
fRetVal = TRUE;
}
__except(EXCEPTION_EXECUTE_HANDLER) {
SetLastError(ERROR_INVALID_PARAMETER);
DEBUGMSG(ZONE_ERROR, (_T("%s: IOCTL_GET_PCF_MSGQUEUE Invalid Parameter pBufOut 0x%08x\r\n"),
pszFname, pBufOut));
}
break;
case IOCTL_GET_PCF_BATTERY_VOLTAGE:
__try {
*((PDWORD) pBufOut) = pPCF50606->pcfBattery.dwBatteryVolatge;
if(pdwActualOut)
{
*pdwActualOut = sizeof(DWORD);
}
fRetVal = TRUE;
}
__except(EXCEPTION_EXECUTE_HANDLER) {
SetLastError(ERROR_INVALID_PARAMETER);
DEBUGMSG(ZONE_ERROR, (_T("%s: IOCTL_GET_PCF_BATTERY_VOLTAGE Invalid Parameter pBufOut 0x%08x\r\n"),
pszFname, pBufOut));
}
break;
case IOCTL_SET_PCF_LED1:
case IOCTL_SET_PCF_LED2:
// sanity check parameters
if(pBufIn != NULL && dwLenIn == sizeof(struct NLED_SETTINGS_INFO))
{
struct NLED_SETTINGS_INFO *pIn = (struct NLED_SETTINGS_INFO*)pBufIn;
struct NLED_SETTINGS_INFO *pOut = (struct NLED_SETTINGS_INFO*)pBufOut;
__try {
LONG OnTime = pIn->OnTime;
LONG OffTime = pIn->OffTime;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -