diff options
Diffstat (limited to 'pn54x/dnld')
-rw-r--r-- | pn54x/dnld/phDnldNfc.c | 1294 | ||||
-rw-r--r-- | pn54x/dnld/phDnldNfc.h | 141 | ||||
-rw-r--r-- | pn54x/dnld/phDnldNfc_Cmd.h | 41 | ||||
-rw-r--r-- | pn54x/dnld/phDnldNfc_Internal.c | 1215 | ||||
-rw-r--r-- | pn54x/dnld/phDnldNfc_Internal.h | 209 | ||||
-rw-r--r-- | pn54x/dnld/phDnldNfc_Status.h | 68 | ||||
-rw-r--r-- | pn54x/dnld/phDnldNfc_Utils.c | 87 | ||||
-rw-r--r-- | pn54x/dnld/phDnldNfc_Utils.h | 27 | ||||
-rw-r--r-- | pn54x/dnld/phNxpNciHal_Dnld.c | 1808 | ||||
-rw-r--r-- | pn54x/dnld/phNxpNciHal_Dnld.h | 24 |
10 files changed, 4914 insertions, 0 deletions
diff --git a/pn54x/dnld/phDnldNfc.c b/pn54x/dnld/phDnldNfc.c new file mode 100644 index 0000000..d2258ef --- /dev/null +++ b/pn54x/dnld/phDnldNfc.c @@ -0,0 +1,1294 @@ +/* + * Copyright (C) 2010-2014 NXP Semiconductors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Download Component + * Download Interface routines implementation + */ + +#include <dlfcn.h> +#include <phDnldNfc_Internal.h> +#include <phNxpConfig.h> +#include <phNxpLog.h> +#include <phTmlNfc.h> + +static void* + pFwLibHandle; /* Global firmware lib handle used in this file only */ +uint16_t wMwVer = 0; /* Middleware version no */ +uint16_t wFwVer = 0; /* Firmware version no */ +#if (NFC_NXP_CHIP_TYPE != PN547C2) +uint8_t gRecFWDwnld; // flag set to true to indicate dummy FW download +#endif +static pphDnldNfc_DlContext_t gpphDnldContext = NULL; /* Download contex */ +static pphDnldNfc_RspCb_t UserCb; /* Upper layer call back function */ +static void* UserCtxt; /* Pointer to upper layer context */ +#undef EEPROM_Read_Mem_IMP + +/* Function prototype declaration */ +static void phDnldNfc_ReadComplete(void* pContext, NFCSTATUS status, + void* pInfo); + +/******************************************************************************* +** +** Function phDnldNfc_Reset +** +** Description Performs a soft reset of the download module +** +** Parameters pNotify - notify caller after getting response +** pContext - caller context +** +** Returns NFC status: +** NFCSTATUS_SUCCESS - reset request to NFCC is successful +** NFCSTATUS_FAILED - reset request failed due to internal +** error +** NFCSTATUS_NOT_ALLOWED - command not allowed +** Other command specific errors +** +*******************************************************************************/ +NFCSTATUS phDnldNfc_Reset(pphDnldNfc_RspCb_t pNotify, void* pContext) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + + if ((NULL == pNotify) || (NULL == pContext)) { + NXPLOG_FWDNLD_E("Invalid Input Parameters!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } else { + if (phDnldNfc_TransitionIdle != gpphDnldContext->tDnldInProgress) { + NXPLOG_FWDNLD_E("Dnld Cmd Request in Progress..Cannot Continue!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_BUSY); + } else { + (gpphDnldContext->FrameInp.Type) = phDnldNfc_FTNone; + (gpphDnldContext->tCmdId) = PH_DL_CMD_RESET; + (gpphDnldContext->tRspBuffInfo.pBuff) = NULL; + (gpphDnldContext->tRspBuffInfo.wLen) = 0; + (gpphDnldContext->tUserData.pBuff) = NULL; + (gpphDnldContext->tUserData.wLen) = 0; + (gpphDnldContext->UserCb) = pNotify; + (gpphDnldContext->UserCtxt) = pContext; + + wStatus = phDnldNfc_CmdHandler(gpphDnldContext, phDnldNfc_EventReset); + + if (NFCSTATUS_PENDING == wStatus) { + NXPLOG_FWDNLD_D("Reset Request submitted successfully"); + } else { + NXPLOG_FWDNLD_E("Reset Request Failed!!"); + } + } + } + + return wStatus; +} + +/******************************************************************************* +** +** Function phDnldNfc_GetVersion +** +** Description Retrieves Hardware version, ROM Code version, Protected Data +** version, Trim data version, User data version, and Firmware +** version information +** +** Parameters pVersionInfo - response buffer which gets updated with +** complete version info from NFCC +** pNotify - notify caller after getting response +** pContext - caller context +** +** Returns NFC status: +** NFCSTATUS_SUCCESS - GetVersion request to NFCC is successful +** NFCSTATUS_FAILED - GetVersion request failed due to internal +** error +** NFCSTATUS_NOT_ALLOWED - command not allowed +** Other command specific errors +** +*******************************************************************************/ +NFCSTATUS phDnldNfc_GetVersion(pphDnldNfc_Buff_t pVersionInfo, + pphDnldNfc_RspCb_t pNotify, void* pContext) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + + if ((NULL == pVersionInfo) || (NULL == pNotify) || (NULL == pContext)) { + NXPLOG_FWDNLD_E("Invalid Input Parameters!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } else { + if (phDnldNfc_TransitionIdle != gpphDnldContext->tDnldInProgress) { + NXPLOG_FWDNLD_E("Dnld Cmd Request in Progress..Cannot Continue!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_BUSY); + } else { + if ((NULL != pVersionInfo->pBuff) && (0 != pVersionInfo->wLen)) { + (gpphDnldContext->tRspBuffInfo.pBuff) = pVersionInfo->pBuff; + (gpphDnldContext->tRspBuffInfo.wLen) = pVersionInfo->wLen; + (gpphDnldContext->FrameInp.Type) = phDnldNfc_FTNone; + (gpphDnldContext->tCmdId) = PH_DL_CMD_GETVERSION; + (gpphDnldContext->tUserData.pBuff) = NULL; + (gpphDnldContext->tUserData.wLen) = 0; + (gpphDnldContext->UserCb) = pNotify; + (gpphDnldContext->UserCtxt) = pContext; + + wStatus = phDnldNfc_CmdHandler(gpphDnldContext, phDnldNfc_EventGetVer); + + if (NFCSTATUS_PENDING == wStatus) { + NXPLOG_FWDNLD_D("GetVersion Request submitted successfully"); + } else { + NXPLOG_FWDNLD_E("GetVersion Request Failed!!"); + } + } else { + NXPLOG_FWDNLD_E("Invalid Buff Parameters!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } + } + } + + return wStatus; +} + +/******************************************************************************* +** +** Function phDnldNfc_GetSessionState +** +** Description Retrieves the current session state of NFCC +** +** Parameters pSession - response buffer which gets updated with complete +** version info from NFCC +** pNotify - notify caller after getting response +** pContext - caller context +** +** Returns NFC status: +** NFCSTATUS_SUCCESS - GetSessionState request to NFCC is +** successful +** NFCSTATUS_FAILED - GetSessionState request failed due to +** internal error +** NFCSTATUS_NOT_ALLOWED - command not allowed +** Other command specific errors +** +*******************************************************************************/ +NFCSTATUS phDnldNfc_GetSessionState(pphDnldNfc_Buff_t pSession, + pphDnldNfc_RspCb_t pNotify, + void* pContext) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + + if ((NULL == pSession) || (NULL == pNotify) || (NULL == pContext)) { + NXPLOG_FWDNLD_E("Invalid Input Parameters!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } else { + if (phDnldNfc_TransitionIdle != gpphDnldContext->tDnldInProgress) { + NXPLOG_FWDNLD_E("Dnld Cmd Request in Progress..Cannot Continue!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_BUSY); + } else { + if ((NULL != pSession->pBuff) && (0 != pSession->wLen)) { + (gpphDnldContext->tRspBuffInfo.pBuff) = pSession->pBuff; + (gpphDnldContext->tRspBuffInfo.wLen) = pSession->wLen; + (gpphDnldContext->FrameInp.Type) = phDnldNfc_FTNone; + (gpphDnldContext->tCmdId) = PH_DL_CMD_GETSESSIONSTATE; + (gpphDnldContext->tUserData.pBuff) = NULL; + (gpphDnldContext->tUserData.wLen) = 0; + (gpphDnldContext->UserCb) = pNotify; + (gpphDnldContext->UserCtxt) = pContext; + + wStatus = + phDnldNfc_CmdHandler(gpphDnldContext, phDnldNfc_EventGetSesnSt); + + if (NFCSTATUS_PENDING == wStatus) { + NXPLOG_FWDNLD_D("GetSessionState Request submitted successfully"); + } else { + NXPLOG_FWDNLD_E("GetSessionState Request Failed!!"); + } + } else { + NXPLOG_FWDNLD_E("Invalid Buff Parameters!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } + } + } + + return wStatus; +} + +/******************************************************************************* +** +** Function phDnldNfc_CheckIntegrity +** +** Description Inspects the integrity of EEPROM and FLASH contents of the +** NFCC, provides CRC for each section +** NOTE: The user data section CRC is valid only after fresh +** download +** +** Parameters bChipVer - current ChipVersion for including additional +** parameters in request payload +** pCRCData - response buffer which gets updated with +** respective section CRC status and CRC bytes from +** NFCC +** pNotify - notify caller after getting response +** pContext - caller context +** +** Returns NFC status: +** NFCSTATUS_SUCCESS - CheckIntegrity request is successful +** NFCSTATUS_FAILED - CheckIntegrity request failed due to +** internal error +** NFCSTATUS_NOT_ALLOWED - command not allowed +** Other command specific errors +** +*******************************************************************************/ +NFCSTATUS phDnldNfc_CheckIntegrity(uint8_t bChipVer, pphDnldNfc_Buff_t pCRCData, + pphDnldNfc_RspCb_t pNotify, void* pContext) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + + if ((NULL == pNotify) || (NULL == pContext)) { + NXPLOG_FWDNLD_E("Invalid Input Parameters!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } else { + if (phDnldNfc_TransitionIdle != gpphDnldContext->tDnldInProgress) { + NXPLOG_FWDNLD_E("Dnld Cmd Request in Progress..Cannot Continue!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_BUSY); + } else { + if ((PHDNLDNFC_HWVER_MRA2_1 == bChipVer) || + (PHDNLDNFC_HWVER_MRA2_2 == bChipVer) +#if (NFC_NXP_CHIP_TYPE == PN551) + || (PHDNLDNFC_HWVER_PN551_MRA1_0 == bChipVer) +#elif (NFC_NXP_CHIP_TYPE == PN548C2) + || (PHDNLDNFC_HWVER_PN548AD_MRA1_0 == bChipVer) +#elif (NFC_NXP_CHIP_TYPE == PN553) + || (PHDNLDNFC_HWVER_PN553_MRA1_0 == bChipVer) || + (PHDNLDNFC_HWVER_PN553_MRA1_0_UPDATED & bChipVer) +#endif + ) { + (gpphDnldContext->FrameInp.Type) = phDnldNfc_ChkIntg; + } else { + (gpphDnldContext->FrameInp.Type) = phDnldNfc_FTNone; + } + + if ((NULL != pCRCData->pBuff) && (0 != pCRCData->wLen)) { + (gpphDnldContext->tRspBuffInfo.pBuff) = pCRCData->pBuff; + (gpphDnldContext->tRspBuffInfo.wLen) = pCRCData->wLen; + (gpphDnldContext->tCmdId) = PH_DL_CMD_CHECKINTEGRITY; + (gpphDnldContext->tUserData.pBuff) = NULL; + (gpphDnldContext->tUserData.wLen) = 0; + (gpphDnldContext->UserCb) = pNotify; + (gpphDnldContext->UserCtxt) = pContext; + + wStatus = + phDnldNfc_CmdHandler(gpphDnldContext, phDnldNfc_EventIntegChk); + + if (NFCSTATUS_PENDING == wStatus) { + NXPLOG_FWDNLD_D("CheckIntegrity Request submitted successfully"); + } else { + NXPLOG_FWDNLD_E("CheckIntegrity Request Failed!!"); + } + } else { + NXPLOG_FWDNLD_E("Invalid Buff Parameters!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } + } + } + + return wStatus; +} +/******************************************************************************* +** +** Function phDnldNfc_ReadLog +** +** Description Retrieves log data from EEPROM +** +** Parameters pData - response buffer which gets updated with data from +** EEPROM +** pNotify - notify caller after getting response +** pContext - caller context +** +** Returns NFC status: +** NFCSTATUS_SUCCESS - Read request to NFCC is successful +** NFCSTATUS_FAILED - Read request failed due to internal error +** NFCSTATUS_NOT_ALLOWED - command not allowed +** Other command specific errors +** +*******************************************************************************/ +NFCSTATUS phDnldNfc_ReadLog(pphDnldNfc_Buff_t pData, pphDnldNfc_RspCb_t pNotify, + void* pContext) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + + if ((NULL == pNotify) || (NULL == pData) || (NULL == pContext)) { + NXPLOG_FWDNLD_E("Invalid Input Parameters!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } else { + if (phDnldNfc_TransitionIdle != gpphDnldContext->tDnldInProgress) { + NXPLOG_FWDNLD_E("Dnld Cmd Request in Progress..Cannot Continue!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_BUSY); + } else { + if ((NULL != pData->pBuff) && (0 != pData->wLen)) { + (gpphDnldContext->tCmdId) = PH_DL_CMD_READ; + (gpphDnldContext->FrameInp.Type) = phDnldNfc_FTRead; + (gpphDnldContext->FrameInp.dwAddr) = PHDNLDNFC_EEPROM_LOG_START_ADDR; + (gpphDnldContext->tRspBuffInfo.pBuff) = pData->pBuff; + (gpphDnldContext->tRspBuffInfo.wLen) = pData->wLen; + (gpphDnldContext->tUserData.pBuff) = NULL; + (gpphDnldContext->tUserData.wLen) = 0; + (gpphDnldContext->UserCb) = pNotify; + (gpphDnldContext->UserCtxt) = pContext; + + memset(&(gpphDnldContext->tRWInfo), 0, + sizeof(gpphDnldContext->tRWInfo)); + + wStatus = phDnldNfc_CmdHandler(gpphDnldContext, phDnldNfc_EventRead); + + if (NFCSTATUS_PENDING == wStatus) { + NXPLOG_FWDNLD_D("Read Request submitted successfully"); + } else { + NXPLOG_FWDNLD_E("Read Request Failed!!"); + } + } else { + NXPLOG_FWDNLD_E("Invalid Buff Parameters!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } + } + } + + return wStatus; +} + +/******************************************************************************* +** +** Function phDnldNfc_Write +** +** Description Writes requested data of length len to desired EEPROM/FLASH +** address +** +** Parameters bRecoverSeq - flag to indicate whether recover sequence data +** needs to be written or not +** pData - data buffer to write into EEPROM/FLASH by user +** pNotify - notify caller after getting response +** pContext - caller context +** +** Returns NFC status: +** NFCSTATUS_SUCCESS - Write request to NFCC is successful +** NFCSTATUS_FAILED - Write request failed due to internal +** error +** NFCSTATUS_NOT_ALLOWED - command not allowed +** Other command specific errors +** +*******************************************************************************/ +NFCSTATUS phDnldNfc_Write(bool_t bRecoverSeq, pphDnldNfc_Buff_t pData, + pphDnldNfc_RspCb_t pNotify, void* pContext) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + uint8_t* pImgPtr = NULL; + uint16_t wLen = 0; + phDnldNfc_Buff_t tImgBuff; + + if ((NULL == pNotify) || (NULL == pContext)) { + NXPLOG_FWDNLD_E("Invalid Input Parameters!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } else { + if (phDnldNfc_TransitionIdle != gpphDnldContext->tDnldInProgress) { + NXPLOG_FWDNLD_E("Dnld Cmd Request in Progress..Cannot Continue!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_BUSY); + } else { + if (NULL != pData) { + pImgPtr = pData->pBuff; + wLen = pData->wLen; + } else { + if (bRecoverSeq == false) { + pImgPtr = (uint8_t*)gpphDnldContext->nxp_nfc_fw; + wLen = gpphDnldContext->nxp_nfc_fw_len; + + } else { + if (PH_DL_STATUS_PLL_ERROR == (gpphDnldContext->tLastStatus)) { + wStatus = phDnldNfc_LoadRecInfo(); + } else if (PH_DL_STATUS_SIGNATURE_ERROR == + (gpphDnldContext->tLastStatus)) { + wStatus = phDnldNfc_LoadPKInfo(); + } else { + } + + if (NFCSTATUS_SUCCESS == wStatus) { + pImgPtr = (uint8_t*)gpphDnldContext->nxp_nfc_fwp; + wLen = gpphDnldContext->nxp_nfc_fwp_len; + } else { + NXPLOG_FWDNLD_E("Platform Recovery Image extraction Failed!!"); + pImgPtr = NULL; + wLen = 0; + } + } + } + + if ((NULL != pImgPtr) && (0 != wLen)) { + tImgBuff.pBuff = pImgPtr; + tImgBuff.wLen = wLen; + + (gpphDnldContext->tCmdId) = PH_DL_CMD_WRITE; + (gpphDnldContext->FrameInp.Type) = phDnldNfc_FTWrite; + (gpphDnldContext->tRspBuffInfo.pBuff) = NULL; + (gpphDnldContext->tRspBuffInfo.wLen) = 0; + (gpphDnldContext->tUserData.pBuff) = pImgPtr; + (gpphDnldContext->tUserData.wLen) = wLen; + (gpphDnldContext->bResendLastFrame) = false; + + memset(&(gpphDnldContext->tRWInfo), 0, + sizeof(gpphDnldContext->tRWInfo)); + (gpphDnldContext->tRWInfo.bFirstWrReq) = true; + (gpphDnldContext->UserCb) = pNotify; + (gpphDnldContext->UserCtxt) = pContext; + + wStatus = phDnldNfc_CmdHandler(gpphDnldContext, phDnldNfc_EventWrite); + + if (NFCSTATUS_PENDING == wStatus) { + NXPLOG_FWDNLD_D("Write Request submitted successfully"); + } else { + NXPLOG_FWDNLD_E("Write Request Failed!!"); + } + } else { + NXPLOG_FWDNLD_E("Download Image Primitives extraction failed!!"); + wStatus = NFCSTATUS_FAILED; + } + } + } + + return wStatus; +} + +/******************************************************************************* +** +** Function phDnldNfc_Log +** +** Description Provides a full page free write to EEPROM +** +** Parameters pData - data buffer to write into EEPROM/FLASH by user +** pNotify - notify caller after getting response +** pContext - caller context +** +** Returns NFC status: +** NFCSTATUS_SUCCESS - Write request to NFCC is successful +** NFCSTATUS_FAILED - Write request failed due to internal +** error +** NFCSTATUS_NOT_ALLOWED - command not allowed +** Other command specific error +** +*******************************************************************************/ +NFCSTATUS phDnldNfc_Log(pphDnldNfc_Buff_t pData, pphDnldNfc_RspCb_t pNotify, + void* pContext) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + + if ((NULL == pNotify) || (NULL == pData) || (NULL == pContext)) { + NXPLOG_FWDNLD_E("Invalid Input Parameters!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } else { + if (phDnldNfc_TransitionIdle != gpphDnldContext->tDnldInProgress) { + NXPLOG_FWDNLD_E("Dnld Cmd Request in Progress..Cannot Continue!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_BUSY); + } else { + if ((NULL != (pData->pBuff)) && + ((0 != (pData->wLen) && (PHDNLDNFC_MAX_LOG_SIZE >= (pData->wLen))))) { + (gpphDnldContext->tCmdId) = PH_DL_CMD_LOG; + (gpphDnldContext->FrameInp.Type) = phDnldNfc_FTLog; + (gpphDnldContext->tRspBuffInfo.pBuff) = NULL; + (gpphDnldContext->tRspBuffInfo.wLen) = 0; + (gpphDnldContext->tUserData.pBuff) = (pData->pBuff); + (gpphDnldContext->tUserData.wLen) = (pData->wLen); + + memset(&(gpphDnldContext->tRWInfo), 0, + sizeof(gpphDnldContext->tRWInfo)); + (gpphDnldContext->UserCb) = pNotify; + (gpphDnldContext->UserCtxt) = pContext; + + wStatus = phDnldNfc_CmdHandler(gpphDnldContext, phDnldNfc_EventLog); + + if (NFCSTATUS_PENDING == wStatus) { + NXPLOG_FWDNLD_D("Log Request submitted successfully"); + } else { + NXPLOG_FWDNLD_E("Log Request Failed!!"); + } + } else { + NXPLOG_FWDNLD_E("Invalid Input Parameters for Log!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } + } + } + + return wStatus; +} + +/******************************************************************************* +** +** Function phDnldNfc_Force +** +** Description Used as an emergency recovery procedure for NFCC due to +** corrupt settings of system platform specific parameters by +** the host +** +** Parameters pInputs - input buffer which contains clk src & clk freq +** settings for desired platform +** pNotify - notify caller after getting response +** pContext - caller context +** +** Returns NFC status: +** NFCSTATUS_SUCCESS - Emergency Recovery request is successful +** NFCSTATUS_FAILED - Emergency Recovery failed due to internal +** error +** NFCSTATUS_NOT_ALLOWED - command not allowed +** Other command specific errors +** +*******************************************************************************/ +NFCSTATUS phDnldNfc_Force(pphDnldNfc_Buff_t pInputs, pphDnldNfc_RspCb_t pNotify, + void* pContext) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + uint8_t bClkSrc = 0x00, bClkFreq = 0x00; + uint8_t bPldVal[3] = { + 0x11, 0x00, 0x00}; /* default values to be used if input not provided */ + + if ((NULL == pNotify) || (NULL == pContext)) { + NXPLOG_FWDNLD_E("Invalid Input Parameters!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } else { + if (phDnldNfc_TransitionIdle != gpphDnldContext->tDnldInProgress) { + NXPLOG_FWDNLD_E("Dnld Cmd Request in Progress..Cannot Continue!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_BUSY); + } else { + (gpphDnldContext->tCmdId) = PH_DL_CMD_FORCE; + (gpphDnldContext->FrameInp.Type) = phDnldNfc_FTForce; + (gpphDnldContext->tRspBuffInfo.pBuff) = NULL; + (gpphDnldContext->tRspBuffInfo.wLen) = 0; + + if ((0 != (pInputs->wLen)) || (NULL != (pInputs->pBuff))) { + if (CLK_SRC_XTAL == (pInputs->pBuff[0])) { + bClkSrc = phDnldNfc_ClkSrcXtal; + } else if (CLK_SRC_PLL == (pInputs->pBuff[0])) { + bClkSrc = phDnldNfc_ClkSrcPLL; + if (CLK_FREQ_13MHZ == (pInputs->pBuff[1])) { + bClkFreq = phDnldNfc_ClkFreq_13Mhz; + } else if (CLK_FREQ_19_2MHZ == (pInputs->pBuff[1])) { + bClkFreq = phDnldNfc_ClkFreq_19_2Mhz; + } else if (CLK_FREQ_24MHZ == (pInputs->pBuff[1])) { + bClkFreq = phDnldNfc_ClkFreq_24Mhz; + } else if (CLK_FREQ_26MHZ == (pInputs->pBuff[1])) { + bClkFreq = phDnldNfc_ClkFreq_26Mhz; + } else if (CLK_FREQ_38_4MHZ == (pInputs->pBuff[1])) { + bClkFreq = phDnldNfc_ClkFreq_38_4Mhz; + } else if (CLK_FREQ_52MHZ == (pInputs->pBuff[1])) { + bClkFreq = phDnldNfc_ClkFreq_52Mhz; + } else { + NXPLOG_FWDNLD_E( + "Invalid Clk Frequency !! Using default value of 19.2Mhz.."); + bClkFreq = phDnldNfc_ClkFreq_19_2Mhz; + } + + } else if (CLK_SRC_PADDIRECT == (pInputs->pBuff[0])) { + bClkSrc = phDnldNfc_ClkSrcPad; + } else { + NXPLOG_FWDNLD_E("Invalid Clk src !! Using default value of PLL.."); + bClkSrc = phDnldNfc_ClkSrcPLL; + } + + bPldVal[0] = 0U; + bPldVal[0] = ((bClkSrc << 3U) | bClkFreq); + } else { + NXPLOG_FWDNLD_E("Clk src inputs not provided!! Using default values.."); + } + + (gpphDnldContext->tUserData.pBuff) = bPldVal; + (gpphDnldContext->tUserData.wLen) = sizeof(bPldVal); + + memset(&(gpphDnldContext->tRWInfo), 0, sizeof(gpphDnldContext->tRWInfo)); + (gpphDnldContext->UserCb) = pNotify; + (gpphDnldContext->UserCtxt) = pContext; + + wStatus = phDnldNfc_CmdHandler(gpphDnldContext, phDnldNfc_EventForce); + + if (NFCSTATUS_PENDING == wStatus) { + NXPLOG_FWDNLD_D("Force Command Request submitted successfully"); + } else { + NXPLOG_FWDNLD_E("Force Command Request Failed!!"); + } + } + } + + return wStatus; +} + +/******************************************************************************* +** +** Function phDnldNfc_SetHwDevHandle +** +** Description Stores the HwDev handle to download context. The handle is +** required for subsequent operations +** +** Parameters None +** +** Returns None - +** +*******************************************************************************/ +void phDnldNfc_SetHwDevHandle(void) { + pphDnldNfc_DlContext_t psDnldContext = NULL; + + if (NULL == gpphDnldContext) { + NXPLOG_FWDNLD_D("Allocating Mem for Dnld Context.."); + /* Create the memory for Download Mgmt Context */ + psDnldContext = + (pphDnldNfc_DlContext_t)malloc(sizeof(phDnldNfc_DlContext_t)); + + if (psDnldContext != NULL) { + (void)memset((void*)psDnldContext, 0, sizeof(phDnldNfc_DlContext_t)); + gpphDnldContext = psDnldContext; + } else { + NXPLOG_FWDNLD_E("Error Allocating Mem for Dnld Context..") + } + } else { + (void)memset((void*)gpphDnldContext, 0, sizeof(phDnldNfc_DlContext_t)); + } + return; +} + +/******************************************************************************* +** +** Function phDnldNfc_ReSetHwDevHandle +** +** Description Frees the HwDev handle to download context. +** +** Parameters None +** +** Returns None - +** +*******************************************************************************/ +void phDnldNfc_ReSetHwDevHandle(void) { + if (gpphDnldContext != NULL) { + NXPLOG_FWDNLD_E("Freeing Mem for Dnld Context..") + free(gpphDnldContext); + gpphDnldContext = NULL; + } +} + +/******************************************************************************* +** +** Function phDnldNfc_RawReq +** +** Description Sends raw frame request to NFCC. +** It is currently used for sending an NCI RESET cmd after +** doing a production key update +** +** Parameters pFrameData - input buffer, contains raw frame packet to be +** sent to NFCC +** pRspData - response buffer received from NFCC +** pNotify - notify caller after getting response +** pContext - caller context +** +** Returns NFC status: +** NFCSTATUS_SUCCESS - GetSessionState request to NFCC is +** successful +** NFCSTATUS_FAILED - GetSessionState request failed due to +** internal error +** NFCSTATUS_NOT_ALLOWED - command not allowed +** Other command specific errors +** +*******************************************************************************/ +NFCSTATUS phDnldNfc_RawReq(pphDnldNfc_Buff_t pFrameData, + pphDnldNfc_Buff_t pRspData, + pphDnldNfc_RspCb_t pNotify, void* pContext) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + + if ((NULL == pFrameData) || (NULL == pNotify) || (NULL == pRspData) || + (NULL == pContext)) { + NXPLOG_FWDNLD_E("Invalid Input Parameters!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } else { + if (phDnldNfc_TransitionIdle != gpphDnldContext->tDnldInProgress) { + NXPLOG_FWDNLD_E("Raw Cmd Request in Progress..Cannot Continue!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_BUSY); + } else { + if (((NULL != pFrameData->pBuff) && (0 != pFrameData->wLen)) && + ((NULL != pRspData->pBuff) && (0 != pRspData->wLen))) { + (gpphDnldContext->tRspBuffInfo.pBuff) = pRspData->pBuff; + (gpphDnldContext->tRspBuffInfo.wLen) = pRspData->wLen; + (gpphDnldContext->FrameInp.Type) = phDnldNfc_FTRaw; + (gpphDnldContext->tCmdId) = PH_DL_CMD_NONE; + (gpphDnldContext->tUserData.pBuff) = pFrameData->pBuff; + (gpphDnldContext->tUserData.wLen) = pFrameData->wLen; + (gpphDnldContext->UserCb) = pNotify; + (gpphDnldContext->UserCtxt) = pContext; + + wStatus = phDnldNfc_CmdHandler(gpphDnldContext, phDnldNfc_EventRaw); + + if (NFCSTATUS_PENDING == wStatus) { + NXPLOG_FWDNLD_D("RawFrame Request submitted successfully"); + } else { + NXPLOG_FWDNLD_E("RawFrame Request Failed!!"); + } + } else { + NXPLOG_FWDNLD_E("Invalid Buff Parameters!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } + } + } + + return wStatus; +} + +/******************************************************************************* +** +** Function phDnldNfc_InitImgInfo +** +** Description Extracts image information and stores it in respective +** variables, to be used internally for write operation +** +** Parameters None +** +** Returns NFC status +** +*******************************************************************************/ +NFCSTATUS phDnldNfc_InitImgInfo(void) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + uint8_t* pImageInfo = NULL; + uint16_t ImageInfoLen = 0; + char fwFileName[256]; + char fwpathName[256]; + char* pathName = NULL; + + /* if memory is not allocated then allocate memory for download context + * structure */ + phDnldNfc_SetHwDevHandle(); + + /*Read Firmware file name from config file*/ + if (GetNxpStrValue(NAME_NXP_FW_NAME, fwFileName, sizeof(fwFileName)) == + true) { + strcpy(fwpathName, FW_DLL_ROOT_DIR); + strncat(fwpathName, fwFileName, strlen(fwFileName)); + pathName = fwpathName; + } + +/* load the library and get the image info pointer */ +#if (NFC_NXP_CHIP_TYPE != PN547C2) + if (gRecFWDwnld == true) + wStatus = phDnldNfc_LoadRecoveryFW(pathName, &pImageInfo, &ImageInfoLen); + else +#endif + wStatus = phDnldNfc_LoadFW(pathName, &pImageInfo, &ImageInfoLen); + + NXPLOG_FWDNLD_E("FW Image Length - ImageInfoLen %d", ImageInfoLen); + NXPLOG_FWDNLD_E("FW Image Info Pointer - pImageInfo %p", pImageInfo); + + if ((pImageInfo == NULL) || (ImageInfoLen == 0)) { + NXPLOG_FWDNLD_E( + "Image extraction Failed - invalid imginfo or imginfolen!!"); + wStatus = NFCSTATUS_FAILED; + } + + if (wStatus != NFCSTATUS_SUCCESS) { + NXPLOG_FWDNLD_E("Error loading libpn54x_fw !!\n"); + } + + /* get the MW version */ + if (NFCSTATUS_SUCCESS == wStatus) { + // NXPLOG_FWDNLD_D("MW Major Version Num - %x",NXP_MW_VERSION_MAJ); + // NXPLOG_FWDNLD_D("MW Minor Version Num - %x",NXP_MW_VERSION_MIN); + wMwVer = (((uint16_t)(NXP_MW_VERSION_MAJ) << 8U) | (NXP_MW_VERSION_MIN)); + } + + if (NFCSTATUS_SUCCESS == wStatus) { + gpphDnldContext->nxp_nfc_fw = (uint8_t*)pImageInfo; + gpphDnldContext->nxp_nfc_fw_len = ImageInfoLen; + if ((NULL != gpphDnldContext->nxp_nfc_fw) && + (0 != gpphDnldContext->nxp_nfc_fw_len)) { + NXPLOG_FWDNLD_E("FW Major Version Num - %x", + gpphDnldContext->nxp_nfc_fw[5]); + NXPLOG_FWDNLD_E("FW Minor Version Num - %x", + gpphDnldContext->nxp_nfc_fw[4]); + NXPLOG_FWDNLD_E("FW Image Length - %d", ImageInfoLen); + NXPLOG_FWDNLD_E("FW Image Info Pointer - %p", pImageInfo); + + /* get the FW version */ + wFwVer = (((uint16_t)(gpphDnldContext->nxp_nfc_fw[5]) << 8U) | + (gpphDnldContext->nxp_nfc_fw[4])); + wStatus = NFCSTATUS_SUCCESS; + } else { + NXPLOG_FWDNLD_E("Image details extraction Failed!!"); + wStatus = NFCSTATUS_FAILED; + } + } + + return wStatus; +} + +/******************************************************************************* +** +** Function phDnldNfc_LoadRecInfo +** +** Description Extracts recovery sequence image information and stores it +** in respective variables, to be used internally for write +** operation +** +** Parameters None +** +** Returns NFC status +** +*******************************************************************************/ +NFCSTATUS phDnldNfc_LoadRecInfo(void) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + uint8_t* pImageInfo = NULL; + uint16_t ImageInfoLen = 0; + + /* if memory is not allocated then allocate memory for donwload context + * structure */ + phDnldNfc_SetHwDevHandle(); +#if (NFC_NXP_CHIP_TYPE != PN547C2) + if (gRecFWDwnld == true) + wStatus = + phDnldNfc_LoadRecoveryFW(PLATFORM_LIB_PATH, &pImageInfo, &ImageInfoLen); + else +#endif + wStatus = phDnldNfc_LoadFW(PLATFORM_LIB_PATH, &pImageInfo, &ImageInfoLen); + if ((pImageInfo == NULL) || (ImageInfoLen == 0)) { + NXPLOG_FWDNLD_E( + "Image extraction Failed - invalid imginfo or imginfolen!!"); + wStatus = NFCSTATUS_FAILED; + } + + /* load the PLL recovery image library */ + if (wStatus != NFCSTATUS_SUCCESS) { + NXPLOG_FWDNLD_E("Error loading libpn54x_fw_platform !!\n"); + } + + if (NFCSTATUS_SUCCESS == wStatus) { + /* fetch the PLL recovery image pointer and the image length */ + gpphDnldContext->nxp_nfc_fwp = (uint8_t*)pImageInfo; + gpphDnldContext->nxp_nfc_fwp_len = ImageInfoLen; + if ((NULL != gpphDnldContext->nxp_nfc_fwp) && + (0 != gpphDnldContext->nxp_nfc_fwp_len)) { + NXPLOG_FWDNLD_D("Recovery Image Length - %d", ImageInfoLen); + NXPLOG_FWDNLD_D("Recovery Image Info Pointer - %p", pImageInfo); + wStatus = NFCSTATUS_SUCCESS; + } else { + NXPLOG_FWDNLD_E("Recovery Image details extraction Failed!!"); + wStatus = NFCSTATUS_FAILED; + } + } + + return wStatus; +} + +/******************************************************************************* +** +** Function phDnldNfc_LoadPKInfo +** +** Description Extracts production sequence image information and stores it +** in respective variables, to be used internally for write +** operation +** +** Parameters None +** +** Returns NFC status +** +*******************************************************************************/ +NFCSTATUS phDnldNfc_LoadPKInfo(void) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + uint8_t* pImageInfo = NULL; + uint16_t ImageInfoLen = 0; + + /* if memory is not allocated then allocate memory for donwload context + * structure */ + phDnldNfc_SetHwDevHandle(); + +/* load the PKU image library */ +#if (NFC_NXP_CHIP_TYPE != PN547C2) + if (gRecFWDwnld == true) + wStatus = + phDnldNfc_LoadRecoveryFW(PKU_LIB_PATH, &pImageInfo, &ImageInfoLen); + else +#endif + wStatus = phDnldNfc_LoadFW(PKU_LIB_PATH, &pImageInfo, &ImageInfoLen); + if ((pImageInfo == NULL) || (ImageInfoLen == 0)) { + NXPLOG_FWDNLD_E( + "Image extraction Failed - invalid imginfo or imginfolen!!"); + wStatus = NFCSTATUS_FAILED; + } + + if (wStatus != NFCSTATUS_SUCCESS) { + NXPLOG_FWDNLD_E("Error loading libpn54x_fw_pku !!\n"); + } + + if (NFCSTATUS_SUCCESS == wStatus) { + /* fetch the PKU image pointer and the image length */ + gpphDnldContext->nxp_nfc_fwp = (uint8_t*)pImageInfo; + gpphDnldContext->nxp_nfc_fwp_len = ImageInfoLen; + + if ((NULL != gpphDnldContext->nxp_nfc_fwp) && + (0 != gpphDnldContext->nxp_nfc_fwp_len)) { + NXPLOG_FWDNLD_D("PKU Image Length - %d", ImageInfoLen); + NXPLOG_FWDNLD_D("PKU Image Info Pointer - %p", pImageInfo); + wStatus = NFCSTATUS_SUCCESS; + } else { + NXPLOG_FWDNLD_E("PKU Image details extraction Failed!!"); + wStatus = NFCSTATUS_FAILED; + } + } + + return wStatus; +} + +/******************************************************************************* +** +** Function phDnldNfc_CloseFwLibHandle +** +** Description Closes previously opened fw library handle as part of +** dynamic loader processing +** +** Parameters None +** +** Returns None +** +*******************************************************************************/ +void phDnldNfc_CloseFwLibHandle(void) { + NFCSTATUS wStatus; + + wStatus = phDnldNfc_UnloadFW(); + if (wStatus != NFCSTATUS_SUCCESS) { + NXPLOG_FWDNLD_E("free library FAILED !!\n"); + } else { + NXPLOG_FWDNLD_E("free library SUCCESS !!\n"); + } + return; +} + +/******************************************************************************* +** +** Function phDnldNfc_LoadFW +** +** Description Load the firmware version form firmware lib +** +** Parameters pathName - Firmware image path +** pImgInfo - Firmware image handle +** pImgInfoLen - Firmware image length +** +** Returns NFC status +** +*******************************************************************************/ +NFCSTATUS phDnldNfc_LoadFW(const char* pathName, uint8_t** pImgInfo, + uint16_t* pImgInfoLen) { + void* pImageInfo = NULL; + void* pImageInfoLen = NULL; + if (pathName == NULL) { +#if (NFC_NXP_CHIP_TYPE == PN548C2) + pathName = "/system/vendor/firmware/libpn548ad_fw.so"; +#elif (NFC_NXP_CHIP_TYPE == PN551) + pathName = "/system/vendor/firmware/libpn551_fw.so"; +#elif (NFC_NXP_CHIP_TYPE == PN553) + pathName = "/system/vendor/firmware/libpn553_fw.so"; +#else + pathName = "/system/vendor/firmware/libpn547_fw.so"; +#endif + } + + /* check if the handle is not NULL then free the library */ + if (pFwLibHandle != NULL) { + phDnldNfc_UnloadFW(); + pFwLibHandle = NULL; + } + + /* load the DLL file */ + pFwLibHandle = dlopen(pathName, RTLD_LAZY); + NXPLOG_FWDNLD_D("@@@%s", pathName); + + /* if library load failed then handle will be NULL */ + if (pFwLibHandle == NULL) { + NXPLOG_FWDNLD_E( + "NULL handler : unable to load the library file, specify correct path"); + return NFCSTATUS_FAILED; + } + + dlerror(); /* Clear any existing error */ + + /* load the address of download image pointer and image size */ + pImageInfo = (void*)dlsym(pFwLibHandle, "gphDnldNfc_DlSeq"); + + if (dlerror() || (NULL == pImageInfo)) { + NXPLOG_FWDNLD_E("Problem loading symbol : gphDnldNfc_DlSeq"); + return NFCSTATUS_FAILED; + } + (*pImgInfo) = (*(uint8_t**)pImageInfo); + + pImageInfoLen = (void*)dlsym(pFwLibHandle, "gphDnldNfc_DlSeqSz"); + if (dlerror() || (NULL == pImageInfoLen)) { + NXPLOG_FWDNLD_E("Problem loading symbol : gphDnldNfc_DlSeqSz"); + return NFCSTATUS_FAILED; + } + + (*pImgInfoLen) = (uint16_t)(*((uint16_t*)pImageInfoLen)); + + return NFCSTATUS_SUCCESS; +} + +#if (NFC_NXP_CHIP_TYPE != PN547C2) +/******************************************************************************* +** +** Function phDnldNfc_LoadRecoveryFW +** +** Description Load the dummy firmware version form firmware lib for +** recovery. This will change the FW version of the NFCC +** firmware and enable flashing of firmware of same version. +** +** Parameters pathName - Firmware image path +** pImgInfo - Firmware image handle +** pImgInfoLen - Firmware image length +** +** Returns NFCSTATUS +** +*******************************************************************************/ +NFCSTATUS phDnldNfc_LoadRecoveryFW(const char* pathName, uint8_t** pImgInfo, + uint16_t* pImgInfoLen) { + void* pImageInfo = NULL; + void* pImageInfoLen = NULL; + + /* check for path name */ + if (pathName == NULL) { +#if (NFC_NXP_CHIP_TYPE == PN548C2) + pathName = "/system/vendor/firmware/libpn548ad_fw.so"; +#elif (NFC_NXP_CHIP_TYPE == PN551) + pathName = "/system/vendor/firmware/libpn551_fw.so"; +#elif (NFC_NXP_CHIP_TYPE == PN553) + pathName = "/system/vendor/firmware/libpn553_fw.so"; +#else + pathName = "/system/vendor/firmware/libpn547_fw.so"; +#endif + } + + /* check if the handle is not NULL then free the library */ + if (pFwLibHandle != NULL) { + phDnldNfc_UnloadFW(); + pFwLibHandle = NULL; + } + /* load the DLL file */ + pFwLibHandle = dlopen(pathName, RTLD_LAZY); + NXPLOG_FWDNLD_D("phDnldNfc_LoadRecoveryFW %s ", pathName); + + /* if library load failed then handle will be NULL */ + if (pFwLibHandle == NULL) { + NXPLOG_FWDNLD_E( + "NULL handler : unable to load the library file, specify correct path"); + return NFCSTATUS_FAILED; + } + + dlerror(); /* Clear any existing error */ + + /* load the address of download image pointer and image size */ + pImageInfo = (void*)dlsym(pFwLibHandle, "gphDnldNfc_DummyDlSeq"); + + if (dlerror() || (NULL == pImageInfo)) { + NXPLOG_FWDNLD_E("Problem loading symbol : gphDnldNfc_DummyDlSeq"); + return NFCSTATUS_FAILED; + } + + (*pImgInfo) = (*(uint8_t**)pImageInfo); + pImageInfoLen = (void*)dlsym(pFwLibHandle, "gphDnldNfc_DlSeqDummyFwSz"); + if (dlerror() || (NULL == pImageInfoLen)) { + NXPLOG_FWDNLD_E("Problem loading symbol : gphDnldNfc_DlSeqDummyFwSz"); + return NFCSTATUS_FAILED; + } + + (*pImgInfoLen) = (uint16_t)(*((uint16_t*)pImageInfoLen)); + + return NFCSTATUS_SUCCESS; +} +#endif + +/******************************************************************************* +** +** Function phDnldNfc_UnloadFW +** +** Description Deinit the firmware handle +** +** Parameters None +** +** Returns NFC status +** +*******************************************************************************/ +NFCSTATUS phDnldNfc_UnloadFW(void) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + int32_t status; + + /* check if the handle is not NULL then free the library */ + if (pFwLibHandle != NULL) { + status = dlclose(pFwLibHandle); + pFwLibHandle = NULL; + + dlerror(); /* Clear any existing error */ + if (status != 0) { + wStatus = NFCSTATUS_FAILED; + NXPLOG_FWDNLD_E("Free library file failed"); + } + } + + return wStatus; +} + +#ifdef EEPROM_Read_Mem_IMP +/******************************************************************************* +** +** Function phDnldNfc_ReadMem +** +** Description Dumps the contents of EEPROM. The handle is required for +** subsequent operations +** +** Parameters pHwRef - pointer to the hardware device +** pNotify - notify caller after getting response +** pContext - caller context +** +** Returns NFC status: +** NFCSTATUS_SUCCESS - request to NFCC is successful +** NFCSTATUS_FAILED - request failed due to internal error +** NFCSTATUS_NOT_ALLOWED - command not allowed +** Other command specific errors +** +*******************************************************************************/ +NFCSTATUS phDnldNfc_ReadMem(void* pHwRef, pphDnldNfc_RspCb_t pNotify, + void* pContext) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + uint32_t wAddr = 0x2011C0; /* eeprom platform specific area start address */ + uint32_t wRdAddr = 0; + uint8_t* pAddr; + static uint8_t bRdData[3519]; /* buffer to hold the read data */ + static phDnldNfc_Buff_t Data; + + if ((NULL == pNotify) || (NULL == pContext)) { + NXPLOG_FWDNLD_E("Invalid Input Parameters!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } else { + /* Call Tml Ioctl to enable download mode */ + wStatus = phTmlNfc_IoCtl(phTmlNfc_e_EnableDownloadMode); + + if (NFCSTATUS_SUCCESS == wStatus) { + /* Set the obtained device handle to download module */ + phDnldNfc_SetHwDevHandle(); + } else { + wStatus = NFCSTATUS_FAILED; + } + + if (NFCSTATUS_SUCCESS == wStatus) { + pAddr = (uint8_t*)&wAddr; + + wRdAddr = (pAddr[3]); + wRdAddr <<= 8; + wRdAddr |= (pAddr[2]); + wRdAddr <<= 8; + wRdAddr |= (pAddr[1]); + wRdAddr <<= 8; + wRdAddr |= (pAddr[0]); + + Data.pBuff = bRdData; + Data.wLen = sizeof(bRdData); + UserCb = pNotify; + UserCtxt = pContext; + + wStatus = phDnldNfc_Read(&Data, wRdAddr, + (pphDnldNfc_RspCb_t)phDnldNfc_ReadComplete, + gpphDnldContext); + } else { + Data.pBuff = NULL; + Data.wLen = 0; + wStatus = NFCSTATUS_FAILED; + } + + if (NFCSTATUS_PENDING == wStatus) { + NXPLOG_FWDNLD_D("Read Request submitted successfully.."); + } else { + NXPLOG_FWDNLD_E("Read Request submission failed!!"); + } + } + + return wStatus; +} + +/******************************************************************************* +** +** Function phDnldNfc_ReadComplete +** +** Description Read complete +** +** Parameters pContext - caller layer context +** status - status of the transaction +** pInfo - transaction info +** +** Returns None +** +*******************************************************************************/ +static void phDnldNfc_ReadComplete(void* pContext, NFCSTATUS status, + void* pInfo) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + UNUSED(pContext); + + /* Call Tml Ioctl to enable/restore normal mode */ + wStatus = phTmlNfc_IoCtl(phTmlNfc_e_EnableNormalMode); + + if (NFCSTATUS_SUCCESS == wStatus) { + NXPLOG_FWDNLD_D("Read Done!!"); + } + + UserCb(&UserCtxt, status, pInfo); + + return; +} + +/******************************************************************************* +** +** Function phDnldNfc_Read +** +** Description Retrieves requested data of specified length from desired +** EEPROM address +** +** Parameters pData - response buffer which gets updated with data from +** EEPROM +** dwRdAddr - EEPROM address for data read +** pNotify - notify caller after getting response +** pContext - caller context +** +** Returns NFC status: +** NFCSTATUS_SUCCESS - Read request to NFCC is successful +** NFCSTATUS_FAILED - Read request failed due to internal error +** NFCSTATUS_NOT_ALLOWED - command not allowed +** Other command specific errors +** +*******************************************************************************/ +NFCSTATUS phDnldNfc_Read(pphDnldNfc_Buff_t pData, uint32_t dwRdAddr, + pphDnldNfc_RspCb_t pNotify, void* pContext) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + + if ((NULL == pNotify) || (NULL == pData) || (NULL == pContext)) { + NXPLOG_FWDNLD_E("Invalid Input Parameters!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } else { + if (phDnldNfc_TransitionIdle != gpphDnldContext->tDnldInProgress) { + NXPLOG_FWDNLD_E("Dnld Cmd Request in Progress..Cannot Continue!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_BUSY); + } else { + if ((NULL != pData->pBuff) && (0 != pData->wLen)) { + (gpphDnldContext->tCmdId) = PH_DL_CMD_READ; + (gpphDnldContext->FrameInp.Type) = phDnldNfc_FTRead; + (gpphDnldContext->FrameInp.dwAddr) = dwRdAddr; + (gpphDnldContext->tRspBuffInfo.pBuff) = pData->pBuff; + (gpphDnldContext->tRspBuffInfo.wLen) = pData->wLen; + (gpphDnldContext->tUserData.pBuff) = NULL; + (gpphDnldContext->tUserData.wLen) = 0; + (gpphDnldContext->UserCb) = pNotify; + (gpphDnldContext->UserCtxt) = pContext; + + memset(&(gpphDnldContext->tRWInfo), 0, + sizeof(gpphDnldContext->tRWInfo)); + + wStatus = phDnldNfc_CmdHandler(gpphDnldContext, phDnldNfc_EventRead); + + if (NFCSTATUS_PENDING == wStatus) { + NXPLOG_FWDNLD_D("Read Request submitted successfully"); + } else { + NXPLOG_FWDNLD_E("Read Request Failed!!"); + } + } else { + NXPLOG_FWDNLD_E("Invalid Buff Parameters!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } + } + } + + return wStatus; +} +#endif diff --git a/pn54x/dnld/phDnldNfc.h b/pn54x/dnld/phDnldNfc.h new file mode 100644 index 0000000..5b7e420 --- /dev/null +++ b/pn54x/dnld/phDnldNfc.h @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2010-2014 NXP Semiconductors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Firmware Download Interface File + */ +#ifndef PHDNLDNFC_H +#define PHDNLDNFC_H + +#include <phNfcStatus.h> + +/* + * + * Callback for handling the received data/response from PN54X. + * Parameters to be passed/registered to download context during respective + * download function call: + * pContext - Upper layer context + * wStatus - Status of the transaction + * pInfo - Contains the Transaction Info + */ +typedef void (*pphDnldNfc_RspCb_t)(void* pContext, NFCSTATUS wStatus, + void* pInfo); + +#define PHLIBNFC_FWDNLD_SESSNOPEN (0x01U) /* download session is Open */ +#define PHLIBNFC_FWDNLD_SESSNCLOSED (0x00U) /* download session is Closed */ + +#define PHDNLDNFC_HWVER_MRA1_0 (0x01U) /* ChipVersion MRA1.0 */ +#define PHDNLDNFC_HWVER_MRA1_1 (0x02U) /* ChipVersion MRA1.1 */ +#define PHDNLDNFC_HWVER_MRA2_0 (0x03U) /* ChipVersion MRA2.0 */ +#define PHDNLDNFC_HWVER_MRA2_1 (0x04U) /* ChipVersion MRA2.1 */ +#define PHDNLDNFC_HWVER_MRA2_2 (0x05U) /* ChipVersion MRA2.2 */ + +/* PN548AD ChipVersion MRA1.0 */ +#define PHDNLDNFC_HWVER_PN548AD_MRA1_0 (0x08U) + +/* PN551 ChipVersion MRA1.0 */ +#define PHDNLDNFC_HWVER_PN551_MRA1_0 (0x08U) +/* PN553-NCI1.0 ChipVersion MRA1.0 */ +#define PHDNLDNFC_HWVER_PN553_MRA1_0 (0x0BU) +/* PN553 A0 -> 0x40 hardware version + PN553 B0 -> 0x41 + PN80T A0 -> 0x50 + PN80T B0 -> 0x51 */ +#define PHDNLDNFC_HWVER_PN553_MRA1_0_UPDATED (0x40U) +/* + * Enum definition contains Download Life Cycle States + */ +typedef enum phDnldNfc_LC { + phDnldNfc_LCCreat = 11, /* Life Cycle Creation*/ + phDnldNfc_LCInit = 13, /* Life Cycle Initializing */ + phDnldNfc_LCOper = 17, /* Life Cycle Operational */ + phDnldNfc_LCTerm = 19 /* Life Cycle Termination */ +} phDnldNfc_LC_t; + +/* + * Enum definition contains Clk Source Options for Force command request + */ +typedef enum phDnldNfc_ClkSrc { + phDnldNfc_ClkSrcXtal = 1U, /* Crystal */ + phDnldNfc_ClkSrcPLL = 2U, /* PLL output */ + phDnldNfc_ClkSrcPad = 3U /* Directly use clk on CLK_IN Pad */ +} phDnldNfc_ClkSrc_t; + +/* + * Enum definition contains Clk Frequency value for Force command request + */ +typedef enum phDnldNfc_ClkFreq { + phDnldNfc_ClkFreq_13Mhz = 0U, /* 13Mhz Clk Frequency */ + phDnldNfc_ClkFreq_19_2Mhz = 1U, /* 19.2Mhz Clk Frequency */ + phDnldNfc_ClkFreq_24Mhz = 2U, /* 24Mhz Clk Frequency */ + phDnldNfc_ClkFreq_26Mhz = 3U, /* 26Mhz Clk Frequency */ + phDnldNfc_ClkFreq_38_4Mhz = 4U, /* 38.4Mhz Clk Frequency */ + phDnldNfc_ClkFreq_52Mhz = 5U /* 52Mhz Clk Frequency */ +} phDnldNfc_ClkFreq_t; + +/* + * Struct contains buffer where user payload shall be stored + */ +typedef struct phDnldNfc_Buff { + uint8_t* pBuff; /*pointer to the buffer where user payload shall be stored*/ + uint16_t wLen; /*Buffer length*/ +} phDnldNfc_Buff_t, *pphDnldNfc_Buff_t; /* pointer to #phDnldNfc_Buff_t */ + +/* +*********************** Function Prototype Declaration ************************* +*/ + +extern NFCSTATUS phDnldNfc_Reset(pphDnldNfc_RspCb_t pNotify, void* pContext); +extern NFCSTATUS phDnldNfc_GetVersion(pphDnldNfc_Buff_t pVersionInfo, + pphDnldNfc_RspCb_t pNotify, + void* pContext); +extern NFCSTATUS phDnldNfc_CheckIntegrity(uint8_t bChipVer, + pphDnldNfc_Buff_t pCRCData, + pphDnldNfc_RspCb_t pNotify, + void* pContext); +extern NFCSTATUS phDnldNfc_GetSessionState(pphDnldNfc_Buff_t pSession, + pphDnldNfc_RspCb_t pNotify, + void* pContext); +extern NFCSTATUS phDnldNfc_Force(pphDnldNfc_Buff_t pInputs, + pphDnldNfc_RspCb_t pNotify, void* pContext); +extern NFCSTATUS phDnldNfc_Read(pphDnldNfc_Buff_t pData, uint32_t dwRdAddr, + pphDnldNfc_RspCb_t pNotify, void* pContext); +extern NFCSTATUS phDnldNfc_ReadLog(pphDnldNfc_Buff_t pData, + pphDnldNfc_RspCb_t pNotify, void* pContext); +extern NFCSTATUS phDnldNfc_Write(bool_t bRecoverSeq, pphDnldNfc_Buff_t pData, + pphDnldNfc_RspCb_t pNotify, void* pContext); +extern NFCSTATUS phDnldNfc_Log(pphDnldNfc_Buff_t pData, + pphDnldNfc_RspCb_t pNotify, void* pContext); +extern void phDnldNfc_SetHwDevHandle(void); +void phDnldNfc_ReSetHwDevHandle(void); +extern NFCSTATUS phDnldNfc_ReadMem(void* pHwRef, pphDnldNfc_RspCb_t pNotify, + void* pContext); +extern NFCSTATUS phDnldNfc_RawReq(pphDnldNfc_Buff_t pFrameData, + pphDnldNfc_Buff_t pRspData, + pphDnldNfc_RspCb_t pNotify, void* pContext); +extern NFCSTATUS phDnldNfc_InitImgInfo(void); +extern NFCSTATUS phDnldNfc_LoadRecInfo(void); +extern NFCSTATUS phDnldNfc_LoadPKInfo(void); +extern void phDnldNfc_CloseFwLibHandle(void); +extern NFCSTATUS phDnldNfc_LoadFW(const char* pathName, uint8_t** pImgInfo, + uint16_t* pImgInfoLen); +#if (NFC_NXP_CHIP_TYPE != PN547C2) +extern NFCSTATUS phDnldNfc_LoadRecoveryFW(const char* pathName, + uint8_t** pImgInfo, + uint16_t* pImgInfoLen); +#endif +extern NFCSTATUS phDnldNfc_UnloadFW(void); +#endif /* PHDNLDNFC_H */ diff --git a/pn54x/dnld/phDnldNfc_Cmd.h b/pn54x/dnld/phDnldNfc_Cmd.h new file mode 100644 index 0000000..31992f6 --- /dev/null +++ b/pn54x/dnld/phDnldNfc_Cmd.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2010-2014 NXP Semiconductors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Firmware Download command values + */ + +#ifndef PHDNLDNFC_CMD_H +#define PHDNLDNFC_CMD_H + +#include <phNfcStatus.h> + +/* + * Enum definition contains Firmware Download Command Ids + */ +typedef enum phDnldNfc_CmdId { + PH_DL_CMD_NONE = 0x00, /* Invalid Cmd */ + PH_DL_CMD_RESET = 0xF0, /* Reset */ + PH_DL_CMD_GETVERSION = 0xF1, /* Get Version */ + PH_DL_CMD_CHECKINTEGRITY = 0xE0, /* Check Integrity */ + PH_DL_CMD_WRITE = 0xC0, /* Write */ + PH_DL_CMD_READ = 0xA2, /* Read */ + PH_DL_CMD_LOG = 0xA7, /* Log */ + PH_DL_CMD_FORCE = 0xD0, /* Force */ + PH_DL_CMD_GETSESSIONSTATE = 0xF2 /* Get Session State */ +} phDnldNfc_CmdId_t; + +#endif /* PHDNLDNFC_CMD_H */ diff --git a/pn54x/dnld/phDnldNfc_Internal.c b/pn54x/dnld/phDnldNfc_Internal.c new file mode 100644 index 0000000..2a66af1 --- /dev/null +++ b/pn54x/dnld/phDnldNfc_Internal.c @@ -0,0 +1,1215 @@ +/* + * Copyright (C) 2010-2014 NXP Semiconductors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Internal Download Management routines + * Download Component + */ + +#include <phDnldNfc_Internal.h> +#include <phDnldNfc_Utils.h> +#include <phNxpLog.h> +#include <phNxpNciHal_utils.h> +#include <phTmlNfc.h> + +/* Minimum length of payload including 1 byte CmdId */ +#define PHDNLDNFC_MIN_PLD_LEN (0x04U) + +/* Offset of Length byte within the frame */ +#define PHDNLDNFC_FRAME_HDR_OFFSET (0x00) +/* Offset of FrameId within the frame */ +#define PHDNLDNFC_FRAMEID_OFFSET (PHDNLDNFC_FRAME_HDR_LEN) +/* Offset of status byte within the frame */ +#define PHDNLDNFC_FRAMESTATUS_OFFSET PHDNLDNFC_FRAMEID_OFFSET +/* Offset within frame where payload starts*/ +#define PHDNLDNFC_PLD_OFFSET (PHDNLDNFC_MIN_PLD_LEN - 1) + +#define PHDNLDNFC_FRAME_RDDATA_OFFSET \ + ((PHDNLDNFC_FRAME_HDR_LEN) + \ + (PHDNLDNFC_MIN_PLD_LEN)) /* recvd frame offset where data starts */ + +/* Size of first secure write frame Signature */ +#define PHDNLDNFC_FRAME_SIGNATURE_SIZE (0xC0U) +/* Size of first secure write frame payload */ +#define PHDNLDNFC_FIRST_FRAME_PLD_SIZE (0xE4U) + +/* Status response for first fragmented write frame */ +#define PHDNLDNFC_FIRST_FRAGFRAME_RESP (0x2DU) +/* Status response for subsequent fragmented write frame */ +#define PHDNLDNFC_NEXT_FRAGFRAME_RESP (0x2EU) + +#define PHDNLDNFC_SET_HDR_FRAGBIT(n) \ + ((n) | (1 << 10)) /* Header chunk bit set macro */ +#define PHDNLDNFC_CLR_HDR_FRAGBIT(n) \ + ((n) & ~(1U << 10)) /* Header chunk bit clear macro */ +#define PHDNLDNFC_CHK_HDR_FRAGBIT(n) \ + ((n)&0x04) /* macro to check if frag bit is set in Hdr */ + +/* Timeout value to wait for response from NFCC */ +#define PHDNLDNFC_RSP_TIMEOUT (2500) +/* Timeout value to wait before resending the last frame */ +#define PHDNLDNFC_RETRY_FRAME_WRITE (50) + +/* size of EEPROM user data length */ +#define PHDNLDNFC_USERDATA_EEPROM_LENSIZE (0x02U) +/* size of EEPROM offset */ +#define PHDNLDNFC_USERDATA_EEPROM_OFFSIZE (0x02U) + +#ifdef NXP_PN547C1_DOWNLOAD +/* EEPROM offset and length value for PN547C1 */ +/* 16 bits offset indicating user data area start location */ +#define PHDNLDNFC_USERDATA_EEPROM_OFFSET (0x003CU) +/* 16 bits length of user data area */ +#define PHDNLDNFC_USERDATA_EEPROM_LEN (0x0DC0U) +#else + +#if (NFC_NXP_CHIP_TYPE == PN548C2) +/* EEPROM offset and length value for PN548AD */ +/* 16 bits offset indicating user data area start location */ +#define PHDNLDNFC_USERDATA_EEPROM_OFFSET (0x02BCU) +/* 16 bits length of user data area */ +#define PHDNLDNFC_USERDATA_EEPROM_LEN (0x0C00U) +#elif (NFC_NXP_CHIP_TYPE == PN551) +/* EEPROM offset and length value for PN551 */ +/* 16 bits offset indicating user data area start location */ +#define PHDNLDNFC_USERDATA_EEPROM_OFFSET (0x02BCU) +/* 16 bits length of user data area */ +#define PHDNLDNFC_USERDATA_EEPROM_LEN (0x0C00U) +#else +/* EEPROM offset and length value for PN547C2 */ +/* 16 bits offset indicating user data area start location */ +#define PHDNLDNFC_USERDATA_EEPROM_OFFSET (0x023CU) +/* 16 bits length of user data area */ +#define PHDNLDNFC_USERDATA_EEPROM_LEN (0x0C80U) +#endif + +#endif +#define PH_LIBNFC_VEN_RESET_ON_DOWNLOAD_TIMEOUT (1) + +/* Function prototype declarations */ +static void phDnldNfc_ProcessSeqState(void* pContext, + phTmlNfc_TransactInfo_t* pInfo); +static void phDnldNfc_ProcessRWSeqState(void* pContext, + phTmlNfc_TransactInfo_t* pInfo); +static NFCSTATUS phDnldNfc_ProcessFrame(void* pContext, + phTmlNfc_TransactInfo_t* pInfo); +static NFCSTATUS phDnldNfc_ProcessRecvInfo(void* pContext, + phTmlNfc_TransactInfo_t* pInfo); +static NFCSTATUS phDnldNfc_BuildFramePkt(pphDnldNfc_DlContext_t pDlContext); +static NFCSTATUS phDnldNfc_CreateFramePld(pphDnldNfc_DlContext_t pDlContext); +static NFCSTATUS phDnldNfc_SetupResendTimer(pphDnldNfc_DlContext_t pDlContext); +static NFCSTATUS phDnldNfc_UpdateRsp(pphDnldNfc_DlContext_t pDlContext, + phTmlNfc_TransactInfo_t* pInfo, + uint16_t wPldLen); +static void phDnldNfc_RspTimeOutCb(uint32_t TimerId, void* pContext); +static void phDnldNfc_ResendTimeOutCb(uint32_t TimerId, void* pContext); + +/* +*************************** Function Definitions *************************** +*/ + +/******************************************************************************* +** +** Function phDnldNfc_CmdHandler +** +** Description Download Command Handler Mechanism +** - holds the sub states for each command processing +** - coordinates with TML download thread to complete a +** download command request +** - calls the user callback on completion of a cmd +** +** Parameters pContext - pointer to the download context structure +** TrigEvent - event requested by user +** +** Returns NFC status: +** NFCSTATUS_PENDING - download request sent to NFCC +** successfully,response pending +** NFCSTATUS_BUSY - handler is busy processing a download +** request +** NFCSTATUS_INVALID_PARAMETER - one or more of the supplied +** parameters could not be +** interpreted properly +** Other errors +** +*******************************************************************************/ +NFCSTATUS phDnldNfc_CmdHandler(void* pContext, phDnldNfc_Event_t TrigEvent) { + NFCSTATUS status = NFCSTATUS_SUCCESS; + pphDnldNfc_DlContext_t pDlCtxt = (pphDnldNfc_DlContext_t)pContext; + + if (NULL == pDlCtxt) { + NXPLOG_FWDNLD_E("Invalid Input Parameter!!"); + status = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } else { + switch (TrigEvent) { + case phDnldNfc_EventReset: + case phDnldNfc_EventGetVer: + case phDnldNfc_EventIntegChk: + case phDnldNfc_EventGetSesnSt: + case phDnldNfc_EventRaw: { + if (phDnldNfc_EventInvalid == (pDlCtxt->tCurrEvent)) { + NXPLOG_FWDNLD_D("Processing Normal Sequence.."); + pDlCtxt->tCurrEvent = TrigEvent; + pDlCtxt->tDnldInProgress = phDnldNfc_TransitionBusy; + + phDnldNfc_ProcessSeqState(pDlCtxt, NULL); + + status = pDlCtxt->wCmdSendStatus; + } else { + NXPLOG_FWDNLD_E("Prev Norml Sequence not completed/restored!!"); + status = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED); + } + break; + } + case phDnldNfc_EventWrite: + case phDnldNfc_EventRead: + case phDnldNfc_EventLog: + case phDnldNfc_EventForce: { + if (phDnldNfc_EventInvalid == (pDlCtxt->tCurrEvent)) { + NXPLOG_FWDNLD_D("Processing R/W Sequence.."); + pDlCtxt->tCurrEvent = TrigEvent; + pDlCtxt->tDnldInProgress = phDnldNfc_TransitionBusy; + + phDnldNfc_ProcessRWSeqState(pDlCtxt, NULL); + + status = pDlCtxt->wCmdSendStatus; + } else { + NXPLOG_FWDNLD_E("Prev R/W Sequence not completed/restored!!"); + status = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED); + } + break; + } + default: { + /* Unknown Event */ + NXPLOG_FWDNLD_E("Unknown Event Parameter!!"); + status = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + break; + } + } + } + + return status; +} + +/******************************************************************************* +** +** Function phDnldNfc_ProcessSeqState +** +** Description Processes all cmd/resp sequences except read & write +** +** Parameters pContext - pointer to the download context structure +** pInfo - pointer to the Transaction buffer updated by TML +** Thread +** +** Returns None +** +*******************************************************************************/ +static void phDnldNfc_ProcessSeqState(void* pContext, + phTmlNfc_TransactInfo_t* pInfo) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + NFCSTATUS wIntStatus; + uint32_t TimerId; + pphDnldNfc_DlContext_t pDlCtxt = (pphDnldNfc_DlContext_t)pContext; + + if (NULL == pDlCtxt) { + NXPLOG_FWDNLD_E("Invalid Input Parameter!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } else { + switch (pDlCtxt->tCurrState) { + case phDnldNfc_StateInit: { + NXPLOG_FWDNLD_D("Initializing Sequence.."); + + if (0 == (pDlCtxt->TimerInfo.dwRspTimerId)) { + TimerId = phOsalNfc_Timer_Create(); + + if (0 == TimerId) { + NXPLOG_FWDNLD_W("Response Timer Create failed!!"); + wStatus = NFCSTATUS_INSUFFICIENT_RESOURCES; + pDlCtxt->wCmdSendStatus = wStatus; + break; + } else { + NXPLOG_FWDNLD_D("Response Timer Created Successfully"); + (pDlCtxt->TimerInfo.dwRspTimerId) = TimerId; + (pDlCtxt->TimerInfo.TimerStatus) = 0; + (pDlCtxt->TimerInfo.wTimerExpStatus) = 0; + } + } + pDlCtxt->tCurrState = phDnldNfc_StateSend; + } + case phDnldNfc_StateSend: { + wStatus = phDnldNfc_BuildFramePkt(pDlCtxt); + + if (NFCSTATUS_SUCCESS == wStatus) { + pDlCtxt->tCurrState = phDnldNfc_StateRecv; + + wStatus = phTmlNfc_Write( + (pDlCtxt->tCmdRspFrameInfo.aFrameBuff), + (uint16_t)(pDlCtxt->tCmdRspFrameInfo.dwSendlength), + (pphTmlNfc_TransactCompletionCb_t)&phDnldNfc_ProcessSeqState, + pDlCtxt); + } + pDlCtxt->wCmdSendStatus = wStatus; + break; + } + case phDnldNfc_StateRecv: { + wStatus = phDnldNfc_ProcessRecvInfo(pContext, pInfo); + + if (NFCSTATUS_SUCCESS == wStatus) { + wStatus = phOsalNfc_Timer_Start((pDlCtxt->TimerInfo.dwRspTimerId), + PHDNLDNFC_RSP_TIMEOUT, + &phDnldNfc_RspTimeOutCb, pDlCtxt); + + if (NFCSTATUS_SUCCESS == wStatus) { + NXPLOG_FWDNLD_D("Response timer started"); + pDlCtxt->TimerInfo.TimerStatus = 1; + pDlCtxt->tCurrState = phDnldNfc_StateTimer; + } else { + NXPLOG_FWDNLD_W("Response timer not started"); + pDlCtxt->tCurrState = phDnldNfc_StateResponse; + } + /* Call TML_Read function and register the call back function */ + wStatus = phTmlNfc_Read( + pDlCtxt->tCmdRspFrameInfo.aFrameBuff, + (uint16_t)PHDNLDNFC_CMDRESP_MAX_BUFF_SIZE, + (pphTmlNfc_TransactCompletionCb_t)&phDnldNfc_ProcessSeqState, + (void*)pDlCtxt); + + /* set read status to pDlCtxt->wCmdSendStatus to enable callback */ + pDlCtxt->wCmdSendStatus = wStatus; + break; + } else { + /* Setting TimerExpStatus below to avoid frame processing in response + * state */ + (pDlCtxt->TimerInfo.wTimerExpStatus) = NFCSTATUS_RF_TIMEOUT; + pDlCtxt->tCurrState = phDnldNfc_StateResponse; + } + } + case phDnldNfc_StateTimer: { + if (1 == (pDlCtxt->TimerInfo.TimerStatus)) /*Is Timer Running*/ + { + /*Stop Timer*/ + (void)phOsalNfc_Timer_Stop(pDlCtxt->TimerInfo.dwRspTimerId); + (pDlCtxt->TimerInfo.TimerStatus) = 0; /*timer stopped*/ + } + pDlCtxt->tCurrState = phDnldNfc_StateResponse; + } + case phDnldNfc_StateResponse: { + if (NFCSTATUS_RF_TIMEOUT != (pDlCtxt->TimerInfo.wTimerExpStatus)) { + /* Process response */ + wStatus = phDnldNfc_ProcessFrame(pContext, pInfo); + } else { + if (phDnldNfc_EventReset != pDlCtxt->tCurrEvent) { + wStatus = (pDlCtxt->TimerInfo.wTimerExpStatus); + } else { + wStatus = NFCSTATUS_SUCCESS; + } + (pDlCtxt->TimerInfo.wTimerExpStatus) = 0; + } + + /* Abort TML read operation which is always kept open */ + wIntStatus = phTmlNfc_ReadAbort(); + + if (NFCSTATUS_SUCCESS != wIntStatus) { + /* TODO:-Action to take in this case:-Tml read abort failed!? */ + NXPLOG_FWDNLD_W("Tml Read Abort failed!!"); + } + + pDlCtxt->tCurrEvent = phDnldNfc_EventInvalid; + pDlCtxt->tDnldInProgress = phDnldNfc_TransitionIdle; + pDlCtxt->tCurrState = phDnldNfc_StateInit; + + /* Delete the timer & reset timer primitives in context */ + (void)phOsalNfc_Timer_Delete(pDlCtxt->TimerInfo.dwRspTimerId); + (pDlCtxt->TimerInfo.dwRspTimerId) = 0; + (pDlCtxt->TimerInfo.TimerStatus) = 0; + (pDlCtxt->TimerInfo.wTimerExpStatus) = 0; + + if ((NULL != (pDlCtxt->UserCb)) && (NULL != (pDlCtxt->UserCtxt))) { + pDlCtxt->UserCb((pDlCtxt->UserCtxt), wStatus, + &(pDlCtxt->tRspBuffInfo)); + } + break; + } + default: { + pDlCtxt->tCurrEvent = phDnldNfc_EventInvalid; + pDlCtxt->tDnldInProgress = phDnldNfc_TransitionIdle; + break; + } + } + } + + return; +} + +/******************************************************************************* +** +** Function phDnldNfc_ProcessRWSeqState +** +** Description Processes read/write cmd/rsp sequence +** +** Parameters pContext - pointer to the download context structure +** pInfo - pointer to the Transaction buffer updated by TML +** Thread +** +** Returns None +** +*******************************************************************************/ +static void phDnldNfc_ProcessRWSeqState(void* pContext, + phTmlNfc_TransactInfo_t* pInfo) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + NFCSTATUS wIntStatus = wStatus; + uint32_t TimerId; + pphDnldNfc_DlContext_t pDlCtxt = (pphDnldNfc_DlContext_t)pContext; + + if (NULL == pDlCtxt) { + NXPLOG_FWDNLD_E("Invalid Input Parameter!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } else { + switch (pDlCtxt->tCurrState) { + case phDnldNfc_StateInit: { + if (0 == (pDlCtxt->TimerInfo.dwRspTimerId)) { + TimerId = phOsalNfc_Timer_Create(); + + if (0 == TimerId) { + NXPLOG_FWDNLD_E("Response Timer Create failed!!"); + wStatus = NFCSTATUS_INSUFFICIENT_RESOURCES; + } else { + NXPLOG_FWDNLD_D("Response Timer Created Successfully"); + (pDlCtxt->TimerInfo.dwRspTimerId) = TimerId; + (pDlCtxt->TimerInfo.TimerStatus) = 0; + (pDlCtxt->TimerInfo.wTimerExpStatus) = 0; + } + } + pDlCtxt->tCurrState = phDnldNfc_StateSend; + } + case phDnldNfc_StateSend: { + if (pDlCtxt->bResendLastFrame == false) { + wStatus = phDnldNfc_BuildFramePkt(pDlCtxt); + } else { + pDlCtxt->bResendLastFrame = false; + } + + if (NFCSTATUS_SUCCESS == wStatus) { + pDlCtxt->tCurrState = phDnldNfc_StateRecv; + + wStatus = phTmlNfc_Write( + (pDlCtxt->tCmdRspFrameInfo.aFrameBuff), + (uint16_t)(pDlCtxt->tCmdRspFrameInfo.dwSendlength), + (pphTmlNfc_TransactCompletionCb_t)&phDnldNfc_ProcessRWSeqState, + pDlCtxt); + } + pDlCtxt->wCmdSendStatus = wStatus; + break; + } + case phDnldNfc_StateRecv: { + wStatus = phDnldNfc_ProcessRecvInfo(pContext, pInfo); + + if (NFCSTATUS_SUCCESS == wStatus) { + /* processing For Pipelined write before calling timer below */ + wStatus = phOsalNfc_Timer_Start((pDlCtxt->TimerInfo.dwRspTimerId), + PHDNLDNFC_RSP_TIMEOUT, + &phDnldNfc_RspTimeOutCb, pDlCtxt); + + if (NFCSTATUS_SUCCESS == wStatus) { + NXPLOG_FWDNLD_D("Response timer started"); + pDlCtxt->TimerInfo.TimerStatus = 1; + pDlCtxt->tCurrState = phDnldNfc_StateTimer; + } else { + NXPLOG_FWDNLD_W("Response timer not started"); + pDlCtxt->tCurrState = phDnldNfc_StateResponse; + /* Todo:- diagnostic in this case */ + } + /* Call TML_Read function and register the call back function */ + wStatus = phTmlNfc_Read( + pDlCtxt->tCmdRspFrameInfo.aFrameBuff, + (uint16_t)PHDNLDNFC_CMDRESP_MAX_BUFF_SIZE, + (pphTmlNfc_TransactCompletionCb_t)&phDnldNfc_ProcessRWSeqState, + (void*)pDlCtxt); + + /* set read status to pDlCtxt->wCmdSendStatus to enable callback */ + pDlCtxt->wCmdSendStatus = wStatus; + break; + } else { + /* Setting TimerExpStatus below to avoid frame processing in reponse + * state */ + (pDlCtxt->TimerInfo.wTimerExpStatus) = NFCSTATUS_RF_TIMEOUT; + pDlCtxt->tCurrState = phDnldNfc_StateResponse; + } + } + case phDnldNfc_StateTimer: { + if (1 == (pDlCtxt->TimerInfo.TimerStatus)) /*Is Timer Running*/ + { + /* Stop Timer */ + (void)phOsalNfc_Timer_Stop(pDlCtxt->TimerInfo.dwRspTimerId); + (pDlCtxt->TimerInfo.TimerStatus) = 0; /*timer stopped*/ + } + pDlCtxt->tCurrState = phDnldNfc_StateResponse; + } + case phDnldNfc_StateResponse: { + if (NFCSTATUS_RF_TIMEOUT != (pDlCtxt->TimerInfo.wTimerExpStatus)) { + /* Process response */ + wStatus = phDnldNfc_ProcessFrame(pContext, pInfo); + + if (NFCSTATUS_BUSY == wStatus) { + /* store the status for use in subsequent processing */ + wIntStatus = wStatus; + + /* setup the resend wait timer */ + wStatus = phDnldNfc_SetupResendTimer(pDlCtxt); + + if (NFCSTATUS_SUCCESS == wStatus) { + /* restore the last mem_bsy status to avoid re-building frame + * below */ + wStatus = wIntStatus; + } + } + } else { + wStatus = (pDlCtxt->TimerInfo.wTimerExpStatus); + (pDlCtxt->TimerInfo.wTimerExpStatus) = 0; + } + + if ((0 != (pDlCtxt->tRWInfo.wRemBytes)) && + (NFCSTATUS_SUCCESS == wStatus)) { + /* Abort TML read operation which is always kept open */ + wIntStatus = phTmlNfc_ReadAbort(); + + if (NFCSTATUS_SUCCESS != wIntStatus) { + NXPLOG_FWDNLD_W("Tml read abort failed!"); + } + + wStatus = phDnldNfc_BuildFramePkt(pDlCtxt); + + if (NFCSTATUS_SUCCESS == wStatus) { + pDlCtxt->tCurrState = phDnldNfc_StateRecv; + wStatus = phTmlNfc_Write( + (pDlCtxt->tCmdRspFrameInfo.aFrameBuff), + (uint16_t)(pDlCtxt->tCmdRspFrameInfo.dwSendlength), + (pphTmlNfc_TransactCompletionCb_t)&phDnldNfc_ProcessRWSeqState, + pDlCtxt); + + /* TODO:- Verify here if TML_Write returned NFC_PENDING status & + take appropriate + action otherwise ?? */ + } + } else if (NFCSTATUS_BUSY == wStatus) { + /* No processing to be done,since resend wait timer should have + * already been started */ + } else { + (pDlCtxt->tRWInfo.bFramesSegmented) = false; + /* Abort TML read operation which is always kept open */ + wIntStatus = phTmlNfc_ReadAbort(); + + if (NFCSTATUS_SUCCESS != wIntStatus) { + NXPLOG_FWDNLD_W("Tml read abort failed!"); + } + + pDlCtxt->tCurrEvent = phDnldNfc_EventInvalid; + pDlCtxt->tDnldInProgress = phDnldNfc_TransitionIdle; + pDlCtxt->tCurrState = phDnldNfc_StateInit; + pDlCtxt->bResendLastFrame = false; + + /* Delete the timer & reset timer primitives in context */ + (void)phOsalNfc_Timer_Delete(pDlCtxt->TimerInfo.dwRspTimerId); + (pDlCtxt->TimerInfo.dwRspTimerId) = 0; + (pDlCtxt->TimerInfo.TimerStatus) = 0; + (pDlCtxt->TimerInfo.wTimerExpStatus) = 0; + + if ((NULL != (pDlCtxt->UserCb)) && (NULL != (pDlCtxt->UserCtxt))) { + pDlCtxt->UserCb((pDlCtxt->UserCtxt), wStatus, + &(pDlCtxt->tRspBuffInfo)); + } + } + break; + } + default: { + pDlCtxt->tCurrEvent = phDnldNfc_EventInvalid; + pDlCtxt->tDnldInProgress = phDnldNfc_TransitionIdle; + break; + } + } + } + + return; +} + +/******************************************************************************* +** +** Function phDnldNfc_BuildFramePkt +** +** Description Forms the frame packet +** +** Parameters pDlContext - pointer to the download context structure +** +** Returns NFC status +** +*******************************************************************************/ +static NFCSTATUS phDnldNfc_BuildFramePkt(pphDnldNfc_DlContext_t pDlContext) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + uint16_t wFrameLen = 0; + uint16_t wCrcVal; + uint8_t* pFrameByte; + + if (NULL == pDlContext) { + NXPLOG_FWDNLD_E("Invalid Input Parameter!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } else { + if (phDnldNfc_FTWrite == (pDlContext->FrameInp.Type)) { + if ((0 == (pDlContext->tUserData.wLen)) || + (NULL == (pDlContext->tUserData.pBuff))) { + NXPLOG_FWDNLD_E("Invalid Input Parameter(s) for Write!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } else { + if ((pDlContext->tRWInfo.bFirstWrReq) == true) { + (pDlContext->tRWInfo.wRemBytes) = (pDlContext->tUserData.wLen); + (pDlContext->tRWInfo.wOffset) = 0; + } + } + } else if (phDnldNfc_FTRead == (pDlContext->FrameInp.Type)) { + if ((0 == (pDlContext->tRspBuffInfo.wLen)) || + (NULL == (pDlContext->tRspBuffInfo.pBuff))) { + NXPLOG_FWDNLD_E("Invalid Input Parameter(s) for Read!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } else { + if ((pDlContext->tRWInfo.bFramesSegmented) == false) { + NXPLOG_FWDNLD_D("Verifying RspBuffInfo for Read Request.."); + wFrameLen = (pDlContext->tRspBuffInfo.wLen) + PHDNLDNFC_MIN_PLD_LEN; + + (pDlContext->tRWInfo.wRWPldSize) = + (PHDNLDNFC_CMDRESP_MAX_PLD_SIZE - PHDNLDNFC_MIN_PLD_LEN); + (pDlContext->tRWInfo.wRemBytes) = (pDlContext->tRspBuffInfo.wLen); + (pDlContext->tRWInfo.dwAddr) = (pDlContext->FrameInp.dwAddr); + (pDlContext->tRWInfo.wOffset) = 0; + (pDlContext->tRWInfo.wBytesRead) = 0; + + if (PHDNLDNFC_CMDRESP_MAX_PLD_SIZE < wFrameLen) { + (pDlContext->tRWInfo.bFramesSegmented) = true; + } + } + } + } else if (phDnldNfc_FTLog == (pDlContext->FrameInp.Type)) { + if ((0 == (pDlContext->tUserData.wLen)) || + (NULL == (pDlContext->tUserData.pBuff))) { + NXPLOG_FWDNLD_E("Invalid Input Parameter(s) for Log!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } + } else { + } + + if (NFCSTATUS_SUCCESS == wStatus) { + wStatus = phDnldNfc_CreateFramePld(pDlContext); + } + + if (NFCSTATUS_SUCCESS == wStatus) { + wFrameLen = 0; + wFrameLen = (pDlContext->tCmdRspFrameInfo.dwSendlength); + + if (phDnldNfc_FTRaw != (pDlContext->FrameInp.Type)) { + if (phDnldNfc_FTWrite != (pDlContext->FrameInp.Type)) { + pFrameByte = (uint8_t*)&wFrameLen; + + pDlContext->tCmdRspFrameInfo.aFrameBuff[PHDNLDNFC_FRAME_HDR_OFFSET] = + pFrameByte[1]; + pDlContext->tCmdRspFrameInfo + .aFrameBuff[PHDNLDNFC_FRAME_HDR_OFFSET + 1] = pFrameByte[0]; + + NXPLOG_FWDNLD_D("Inserting FrameId .."); + pDlContext->tCmdRspFrameInfo.aFrameBuff[PHDNLDNFC_FRAMEID_OFFSET] = + (pDlContext->tCmdId); + + wFrameLen += PHDNLDNFC_FRAME_HDR_LEN; + } else { + if (0 != (pDlContext->tRWInfo.wRWPldSize)) { + if ((pDlContext->tRWInfo.bFramesSegmented) == true) { + /* Turning ON the Fragmentation bit in FrameLen */ + wFrameLen = PHDNLDNFC_SET_HDR_FRAGBIT(wFrameLen); + } + + pFrameByte = (uint8_t*)&wFrameLen; + + pDlContext->tCmdRspFrameInfo + .aFrameBuff[PHDNLDNFC_FRAME_HDR_OFFSET] = pFrameByte[1]; + pDlContext->tCmdRspFrameInfo + .aFrameBuff[PHDNLDNFC_FRAME_HDR_OFFSET + 1] = pFrameByte[0]; + + /* To ensure we have no frag bit set for crc calculation */ + wFrameLen = PHDNLDNFC_CLR_HDR_FRAGBIT(wFrameLen); + + wFrameLen += PHDNLDNFC_FRAME_HDR_LEN; + } + } + if (wFrameLen > PHDNLDNFC_CMDRESP_MAX_BUFF_SIZE) { + NXPLOG_FWDNLD_D("wFrameLen exceeds the limit"); + return NFCSTATUS_FAILED; + } + /* calculate CRC16 */ + wCrcVal = phDnldNfc_CalcCrc16((pDlContext->tCmdRspFrameInfo.aFrameBuff), + wFrameLen); + + pFrameByte = (uint8_t*)&wCrcVal; + + /* Insert the computed Crc value */ + pDlContext->tCmdRspFrameInfo.aFrameBuff[wFrameLen] = pFrameByte[1]; + pDlContext->tCmdRspFrameInfo.aFrameBuff[wFrameLen + 1] = pFrameByte[0]; + + wFrameLen += PHDNLDNFC_FRAME_CRC_LEN; + } + + (pDlContext->tCmdRspFrameInfo.dwSendlength) = wFrameLen; + NXPLOG_FWDNLD_D("Frame created successfully"); + } else { + NXPLOG_FWDNLD_E("Frame creation failed!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED); + } + } + + return wStatus; +} + +/******************************************************************************* +** +** Function phDnldNfc_CreateFramePld +** +** Description Forms the frame payload +** +** Parameters pDlContext - pointer to the download context structure +** +** Returns NFC status +** +*******************************************************************************/ +static NFCSTATUS phDnldNfc_CreateFramePld(pphDnldNfc_DlContext_t pDlContext) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + uint16_t wBuffIdx = 0; + uint16_t wChkIntgVal = 0; + uint16_t wFrameLen = 0; + + if (NULL == pDlContext) { + NXPLOG_FWDNLD_E("Invalid Input Parameter!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } else { + memset((pDlContext->tCmdRspFrameInfo.aFrameBuff), 0, + PHDNLDNFC_CMDRESP_MAX_BUFF_SIZE); + (pDlContext->tCmdRspFrameInfo.dwSendlength) = 0; + + if (phDnldNfc_FTNone == (pDlContext->FrameInp.Type)) { + (pDlContext->tCmdRspFrameInfo.dwSendlength) += PHDNLDNFC_MIN_PLD_LEN; + } else if (phDnldNfc_ChkIntg == (pDlContext->FrameInp.Type)) { + (pDlContext->tCmdRspFrameInfo.dwSendlength) += PHDNLDNFC_MIN_PLD_LEN; + + wChkIntgVal = PHDNLDNFC_USERDATA_EEPROM_OFFSET; + memcpy(&(pDlContext->tCmdRspFrameInfo + .aFrameBuff[PHDNLDNFC_FRAME_RDDATA_OFFSET]), + &wChkIntgVal, sizeof(wChkIntgVal)); + + wChkIntgVal = PHDNLDNFC_USERDATA_EEPROM_LEN; + memcpy(&(pDlContext->tCmdRspFrameInfo + .aFrameBuff[PHDNLDNFC_FRAME_RDDATA_OFFSET + + PHDNLDNFC_USERDATA_EEPROM_OFFSIZE]), + &wChkIntgVal, sizeof(wChkIntgVal)); + + (pDlContext->tCmdRspFrameInfo.dwSendlength) += + PHDNLDNFC_USERDATA_EEPROM_LENSIZE; + (pDlContext->tCmdRspFrameInfo.dwSendlength) += + PHDNLDNFC_USERDATA_EEPROM_OFFSIZE; + } else if (phDnldNfc_FTWrite == (pDlContext->FrameInp.Type)) { + wBuffIdx = (pDlContext->tRWInfo.wOffset); + + if ((pDlContext->tRWInfo.bFramesSegmented) == false) { + wFrameLen = (pDlContext->tUserData.pBuff[wBuffIdx]); + wFrameLen <<= 8; + wFrameLen |= (pDlContext->tUserData.pBuff[wBuffIdx + 1]); + + (pDlContext->tRWInfo.wRWPldSize) = wFrameLen; + } + + if ((pDlContext->tRWInfo.wRWPldSize) > PHDNLDNFC_CMDRESP_MAX_PLD_SIZE) { + if ((pDlContext->tRWInfo.bFirstChunkResp) == false) { + (pDlContext->tRWInfo.wRemChunkBytes) = wFrameLen; + (pDlContext->tRWInfo.wOffset) += PHDNLDNFC_FRAME_HDR_LEN; + wBuffIdx = (pDlContext->tRWInfo.wOffset); + } + + if (PHDNLDNFC_CMDRESP_MAX_PLD_SIZE < + (pDlContext->tRWInfo.wRemChunkBytes)) { + (pDlContext->tRWInfo.wBytesToSendRecv) = + PHDNLDNFC_CMDRESP_MAX_PLD_SIZE; + (pDlContext->tRWInfo.bFramesSegmented) = true; + } else { + (pDlContext->tRWInfo.wBytesToSendRecv) = + (pDlContext->tRWInfo.wRemChunkBytes); + (pDlContext->tRWInfo.bFramesSegmented) = false; + } + + memcpy(&(pDlContext->tCmdRspFrameInfo + .aFrameBuff[PHDNLDNFC_FRAMEID_OFFSET]), + &(pDlContext->tUserData.pBuff[wBuffIdx]), + (pDlContext->tRWInfo.wBytesToSendRecv)); + } else { + (pDlContext->tRWInfo.wRWPldSize) = 0; + (pDlContext->tRWInfo.wBytesToSendRecv) = + (wFrameLen + PHDNLDNFC_FRAME_HDR_LEN); + + memcpy(&(pDlContext->tCmdRspFrameInfo.aFrameBuff[0]), + &(pDlContext->tUserData.pBuff[wBuffIdx]), + (pDlContext->tRWInfo.wBytesToSendRecv)); + } + (pDlContext->tCmdRspFrameInfo.dwSendlength) += + (pDlContext->tRWInfo.wBytesToSendRecv); + } else if (phDnldNfc_FTRead == (pDlContext->FrameInp.Type)) { + (pDlContext->tRWInfo.wBytesToSendRecv) = + ((pDlContext->tRWInfo.wRemBytes) > (pDlContext->tRWInfo.wRWPldSize)) + ? (pDlContext->tRWInfo.wRWPldSize) + : (pDlContext->tRWInfo.wRemBytes); + + wBuffIdx = (PHDNLDNFC_PLD_OFFSET + + ((sizeof(pDlContext->tRWInfo.wBytesToSendRecv)) % + PHDNLDNFC_MIN_PLD_LEN) - + 1); + + memcpy(&(pDlContext->tCmdRspFrameInfo.aFrameBuff[wBuffIdx]), + &(pDlContext->tRWInfo.wBytesToSendRecv), + (sizeof(pDlContext->tRWInfo.wBytesToSendRecv))); + + wBuffIdx += sizeof(pDlContext->tRWInfo.wBytesToSendRecv); + + memcpy(&(pDlContext->tCmdRspFrameInfo.aFrameBuff[wBuffIdx]), + &(pDlContext->tRWInfo.dwAddr), sizeof(pDlContext->tRWInfo.dwAddr)); + + (pDlContext->tCmdRspFrameInfo.dwSendlength) += + (PHDNLDNFC_MIN_PLD_LEN + (sizeof(pDlContext->tRWInfo.dwAddr))); + } else if (phDnldNfc_FTLog == (pDlContext->FrameInp.Type)) { + (pDlContext->tCmdRspFrameInfo.dwSendlength) += PHDNLDNFC_MIN_PLD_LEN; + + wBuffIdx = (PHDNLDNFC_MIN_PLD_LEN + PHDNLDNFC_FRAME_HDR_LEN); + + memcpy(&(pDlContext->tCmdRspFrameInfo.aFrameBuff[wBuffIdx]), + (pDlContext->tUserData.pBuff), (pDlContext->tUserData.wLen)); + + (pDlContext->tCmdRspFrameInfo.dwSendlength) += + (pDlContext->tUserData.wLen); + } else if (phDnldNfc_FTForce == (pDlContext->FrameInp.Type)) { + (pDlContext->tCmdRspFrameInfo.dwSendlength) += PHDNLDNFC_MIN_PLD_LEN; + + wBuffIdx = PHDNLDNFC_PLD_OFFSET; + + memcpy(&(pDlContext->tCmdRspFrameInfo.aFrameBuff[wBuffIdx]), + (pDlContext->tUserData.pBuff), (pDlContext->tUserData.wLen)); + } else if (phDnldNfc_FTRaw == (pDlContext->FrameInp.Type)) { + if ((0 == (pDlContext->tUserData.wLen)) || + (NULL == (pDlContext->tUserData.pBuff))) { + NXPLOG_FWDNLD_E("Invalid Input Parameter(s) for Raw Request!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } else { + memcpy(&(pDlContext->tCmdRspFrameInfo.aFrameBuff[wBuffIdx]), + (pDlContext->tUserData.pBuff), (pDlContext->tUserData.wLen)); + + (pDlContext->tCmdRspFrameInfo.dwSendlength) += + (pDlContext->tUserData.wLen); + } + } else { + } + } + + return wStatus; +} + +/******************************************************************************* +** +** Function phDnldNfc_ProcessFrame +** +** Description Processes response frame received +** +** Parameters pContext - pointer to the download context structure +** pInfo - pointer to the Transaction buffer updated by TML +** Thread +** +** Returns NFCSTATUS_SUCCESS - parameters successfully validated +** NFCSTATUS_INVALID_PARAMETER - invalid parameters +** +*******************************************************************************/ +static NFCSTATUS phDnldNfc_ProcessFrame(void* pContext, + phTmlNfc_TransactInfo_t* pInfo) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + uint16_t wCrcVal, wRecvdCrc, wRecvdLen, wPldLen; + pphDnldNfc_DlContext_t pDlCtxt = (pphDnldNfc_DlContext_t)pContext; + + if ((NULL == pDlCtxt) || (NULL == pInfo)) { + NXPLOG_FWDNLD_E("Invalid Input Parameters!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } else { + if ((PH_DL_STATUS_OK != pInfo->wStatus) || (0 == pInfo->wLength) || + (NULL == pInfo->pBuff)) { + NXPLOG_FWDNLD_E("Dnld Cmd Request Failed!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED); + } else { + if (phDnldNfc_FTRaw == (pDlCtxt->FrameInp.Type)) { + if ((0 != (pDlCtxt->tRspBuffInfo.wLen)) && + (NULL != (pDlCtxt->tRspBuffInfo.pBuff))) { + memcpy((pDlCtxt->tRspBuffInfo.pBuff), (pInfo->pBuff), + (pInfo->wLength)); + + (pDlCtxt->tRspBuffInfo.wLen) = (pInfo->wLength); + } else { + NXPLOG_FWDNLD_E("Cannot update Response buff with received data!!"); + } + } else { + /* calculate CRC16 */ + wCrcVal = phDnldNfc_CalcCrc16( + (pInfo->pBuff), ((pInfo->wLength) - PHDNLDNFC_FRAME_CRC_LEN)); + + wRecvdCrc = 0; + wRecvdCrc = (((uint16_t)(pInfo->pBuff[(pInfo->wLength) - 2]) << 8U) | + (pInfo->pBuff[(pInfo->wLength) - 1])); + + if (wRecvdCrc == wCrcVal) { + wRecvdLen = + (((uint16_t)(pInfo->pBuff[PHDNLDNFC_FRAME_HDR_OFFSET]) << 8U) | + (pInfo->pBuff[PHDNLDNFC_FRAME_HDR_OFFSET + 1])); + + wPldLen = ((pInfo->wLength) - + (PHDNLDNFC_FRAME_HDR_LEN + PHDNLDNFC_FRAME_CRC_LEN)); + + if (wRecvdLen != wPldLen) { + NXPLOG_FWDNLD_E("Invalid frame payload length received"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED); + } else { + wStatus = phDnldNfc_UpdateRsp(pDlCtxt, pInfo, (wPldLen - 1)); + } + } else { + NXPLOG_FWDNLD_E("Invalid frame received"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED); + } + } + } + } + + return wStatus; +} + +/******************************************************************************* +** +** Function phDnldNfc_ProcessRecvInfo +** +** Description Processes the response during the state phDnldNfc_StateRecv +** +** Parameters pContext - pointer to the download context structure +** pInfo - pointer to the Transaction buffer updated by TML +** Thread +** +** Returns NFCSTATUS_SUCCESS - parameters successfully validated +** NFCSTATUS_INVALID_PARAMETER - invalid parameters +** +*******************************************************************************/ +static NFCSTATUS phDnldNfc_ProcessRecvInfo(void* pContext, + phTmlNfc_TransactInfo_t* pInfo) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + + if (NULL != pContext) { + if (NULL == pInfo) { + NXPLOG_FWDNLD_E("Invalid pInfo received from TML!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED); + } else { + wStatus = PHNFCSTATUS(pInfo->wStatus); + + if (NFCSTATUS_SUCCESS == wStatus) { + NXPLOG_FWDNLD_D("Send Success"); + } else { + NXPLOG_FWDNLD_E("Tml Write error!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED); + } + } + } else { + NXPLOG_FWDNLD_E("Invalid context received from TML!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED); + } + + return wStatus; +} + +/******************************************************************************* +** +** Function phDnldNfc_SetupResendTimer +** +** Description Sets up the timer for resending the previous write frame +** +** Parameters pDlContext - pointer to the download context structure +** +** Returns NFC status +** +*******************************************************************************/ +static NFCSTATUS phDnldNfc_SetupResendTimer(pphDnldNfc_DlContext_t pDlContext) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + + wStatus = phOsalNfc_Timer_Start((pDlContext->TimerInfo.dwRspTimerId), + PHDNLDNFC_RETRY_FRAME_WRITE, + &phDnldNfc_ResendTimeOutCb, pDlContext); + + if (NFCSTATUS_SUCCESS == wStatus) { + NXPLOG_FWDNLD_D("Frame Resend wait timer started"); + (pDlContext->TimerInfo.TimerStatus) = 1; + pDlContext->tCurrState = phDnldNfc_StateTimer; + } else { + NXPLOG_FWDNLD_W("Frame Resend wait timer not started"); + (pDlContext->TimerInfo.TimerStatus) = 0; /*timer stopped*/ + pDlContext->tCurrState = phDnldNfc_StateResponse; + /* Todo:- diagnostic in this case */ + } + + return wStatus; +} + +#if !defined(PH_LIBNFC_VEN_RESET_ON_DOWNLOAD_TIMEOUT) +#error PH_LIBNFC_VEN_RESET_ON_DOWNLOAD_TIMEOUT has to be defined +#endif + +/******************************************************************************* +** +** Function phDnldNfc_RspTimeOutCb +** +** Description Callback function in case of timer expiration +** +** Parameters TimerId - expired timer id +** pContext - pointer to the download context structure +** +** Returns None +** +*******************************************************************************/ +static void phDnldNfc_RspTimeOutCb(uint32_t TimerId, void* pContext) { + pphDnldNfc_DlContext_t pDlCtxt = (pphDnldNfc_DlContext_t)pContext; + + if (NULL != pDlCtxt) { + UNUSED(TimerId); + + if (1 == pDlCtxt->TimerInfo.TimerStatus) { + /* No response received and the timer expired */ + pDlCtxt->TimerInfo.TimerStatus = 0; /* Reset timer status flag */ + + NXPLOG_FWDNLD_D("%x", pDlCtxt->tLastStatus); + +#if (PH_LIBNFC_VEN_RESET_ON_DOWNLOAD_TIMEOUT == TRUE) + if (PH_DL_STATUS_SIGNATURE_ERROR == pDlCtxt->tLastStatus) { + /* Do a VEN Reset of the chip. */ + NXPLOG_FWDNLD_E("Performing a VEN Reset"); + phTmlNfc_IoCtl(phTmlNfc_e_EnableNormalMode); + phTmlNfc_IoCtl(phTmlNfc_e_EnableDownloadMode); + NXPLOG_FWDNLD_E("VEN Reset Done"); + } +#endif + + (pDlCtxt->TimerInfo.wTimerExpStatus) = NFCSTATUS_RF_TIMEOUT; + + if ((phDnldNfc_EventRead == pDlCtxt->tCurrEvent) || + (phDnldNfc_EventWrite == pDlCtxt->tCurrEvent)) { + phDnldNfc_ProcessRWSeqState(pDlCtxt, NULL); + } else { + phDnldNfc_ProcessSeqState(pDlCtxt, NULL); + } + } + } + + return; +} + +/******************************************************************************* +** +** Function phDnldNfc_ResendTimeOutCb +** +** Description Callback function in case of Frame Resend Wait timer +** expiration +** +** Parameters TimerId - expired timer id +** pContext - pointer to the download context structure +** +** Returns None +** +*******************************************************************************/ +static void phDnldNfc_ResendTimeOutCb(uint32_t TimerId, void* pContext) { + pphDnldNfc_DlContext_t pDlCtxt = (pphDnldNfc_DlContext_t)pContext; + + if (NULL != pDlCtxt) { + UNUSED(TimerId); + + if (1 == pDlCtxt->TimerInfo.TimerStatus) { + /* No response received and the timer expired */ + pDlCtxt->TimerInfo.TimerStatus = 0; /* Reset timer status flag */ + + (pDlCtxt->TimerInfo.wTimerExpStatus) = 0; + + pDlCtxt->tCurrState = phDnldNfc_StateSend; + + /* set the flag to trigger last frame re-transmission */ + pDlCtxt->bResendLastFrame = true; + + phDnldNfc_ProcessRWSeqState(pDlCtxt, NULL); + } + } + + return; +} + +/******************************************************************************* +** +** Function phDnldNfc_UpdateRsp +** +** Description verifies the payload status byte and copies data +** to response buffer if successful +** +** Parameters pDlContext - pointer to the download context structure +** pInfo - pointer to the Transaction buffer updated by TML +** Thread +** wPldLen - Length of the payload bytes to copy to response +** buffer +** +** Returns NFC status +** +*******************************************************************************/ +static NFCSTATUS phDnldNfc_UpdateRsp(pphDnldNfc_DlContext_t pDlContext, + phTmlNfc_TransactInfo_t* pInfo, + uint16_t wPldLen) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + uint16_t wReadLen = 0; + + if ((NULL == pDlContext) || (NULL == pInfo)) { + NXPLOG_FWDNLD_E("Invalid Input Parameters!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); + } else { + if (PH_DL_CMD_WRITE == (pDlContext->tCmdId)) { + if (PH_DL_STATUS_OK == (pInfo->pBuff[PHDNLDNFC_FRAMESTATUS_OFFSET])) { + /* first write frame response received case */ + if ((pDlContext->tRWInfo.bFirstWrReq) == true) { + NXPLOG_FWDNLD_D("First Write Frame Success Status received!!"); + (pDlContext->tRWInfo.bFirstWrReq) = false; + } + + if ((pDlContext->tRWInfo.bFirstChunkResp) == true) { + if ((pDlContext->tRWInfo.bFramesSegmented) == false) { + NXPLOG_FWDNLD_D("Chunked Write Frame Success Status received!!"); + (pDlContext->tRWInfo.wRemChunkBytes) -= + (pDlContext->tRWInfo.wBytesToSendRecv); + (pDlContext->tRWInfo.bFirstChunkResp) = false; + } else { + NXPLOG_FWDNLD_E("UnExpected Status received!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED); + } + } + + if (NFCSTATUS_SUCCESS == wStatus) { + (pDlContext->tRWInfo.wRemBytes) -= + (pDlContext->tRWInfo.wBytesToSendRecv); + (pDlContext->tRWInfo.wOffset) += + (pDlContext->tRWInfo.wBytesToSendRecv); + } + } else if (((pDlContext->tRWInfo.bFirstChunkResp) == false) && + ((pDlContext->tRWInfo.bFramesSegmented) == true) && + (PHDNLDNFC_FIRST_FRAGFRAME_RESP == + (pInfo->pBuff[PHDNLDNFC_FRAMESTATUS_OFFSET]))) { + (pDlContext->tRWInfo.bFirstChunkResp) = true; + (pDlContext->tRWInfo.wRemChunkBytes) -= + (pDlContext->tRWInfo.wBytesToSendRecv); + (pDlContext->tRWInfo.wRemBytes) -= + ((pDlContext->tRWInfo.wBytesToSendRecv) + PHDNLDNFC_FRAME_HDR_LEN); + (pDlContext->tRWInfo.wOffset) += (pDlContext->tRWInfo.wBytesToSendRecv); + + /* first write frame response received case */ + if ((pDlContext->tRWInfo.bFirstWrReq) == true) { + NXPLOG_FWDNLD_D("First Write Frame Success Status received!!"); + (pDlContext->tRWInfo.bFirstWrReq) = false; + } + } else if (((pDlContext->tRWInfo.bFirstChunkResp) == true) && + ((pDlContext->tRWInfo.bFramesSegmented) == true) && + (PHDNLDNFC_NEXT_FRAGFRAME_RESP == + (pInfo->pBuff[PHDNLDNFC_FRAMESTATUS_OFFSET]))) { + (pDlContext->tRWInfo.wRemChunkBytes) -= + (pDlContext->tRWInfo.wBytesToSendRecv); + (pDlContext->tRWInfo.wRemBytes) -= + (pDlContext->tRWInfo.wBytesToSendRecv); + (pDlContext->tRWInfo.wOffset) += (pDlContext->tRWInfo.wBytesToSendRecv); + } else if (PH_DL_STATUS_FIRMWARE_VERSION_ERROR == + (pInfo->pBuff[PHDNLDNFC_FRAMESTATUS_OFFSET])) { + NXPLOG_FWDNLD_E( + "FW version Error !!!could be either due to FW major version " + "mismatch or Firmware Already Up To Date !!"); + (pDlContext->tRWInfo.bFirstWrReq) = false; + /* resetting wRemBytes to 0 to avoid any further write frames send */ + (pDlContext->tRWInfo.wRemBytes) = 0; + (pDlContext->tRWInfo.wOffset) = 0; + wStatus = NFCSTATUS_FW_VERSION_ERROR; + } else if (PH_DL_STATUS_PLL_ERROR == + (pInfo->pBuff[PHDNLDNFC_FRAMESTATUS_OFFSET])) { + NXPLOG_FWDNLD_E("PLL Error Status received!!"); + (pDlContext->tLastStatus) = PH_DL_STATUS_PLL_ERROR; + wStatus = NFCSTATUS_WRITE_FAILED; + } else if (PH_DL_STATUS_SIGNATURE_ERROR == + (pInfo->pBuff[PHDNLDNFC_FRAMESTATUS_OFFSET])) { + NXPLOG_FWDNLD_E("Signature Mismatch Error received!!"); + /* save the status for use in loading the relevant recovery image + * (either signature or platform) */ + (pDlContext->tLastStatus) = PH_DL_STATUS_SIGNATURE_ERROR; + wStatus = NFCSTATUS_REJECTED; + } else if (PH_DL_STATUS_MEM_BSY == + (pInfo->pBuff[PHDNLDNFC_FRAMESTATUS_OFFSET])) { + NXPLOG_FWDNLD_E("Mem Busy Status received!!"); + (pDlContext->tLastStatus) = PH_DL_STATUS_MEM_BSY; + wStatus = NFCSTATUS_BUSY; + } else { + NXPLOG_FWDNLD_E("Unsuccessful Status received!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED); + } + } else if (PH_DL_CMD_READ == (pDlContext->tCmdId)) { + if (PH_DL_STATUS_OK == (pInfo->pBuff[PHDNLDNFC_FRAMESTATUS_OFFSET])) { + wReadLen = (((uint16_t)(pInfo->pBuff[PHDNLDNFC_FRAMESTATUS_OFFSET + 3]) + << 8U) | + (pInfo->pBuff[PHDNLDNFC_FRAMESTATUS_OFFSET + 2])); + + if (wReadLen != (pDlContext->tRWInfo.wBytesToSendRecv)) { + NXPLOG_FWDNLD_E("Desired Length bytes not received!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED); + } else { + memcpy( + &(pDlContext->tRspBuffInfo.pBuff[(pDlContext->tRWInfo.wOffset)]), + &(pInfo->pBuff[PHDNLDNFC_FRAME_RDDATA_OFFSET]), wReadLen); + + (pDlContext->tRWInfo.wBytesRead) += wReadLen; + + (pDlContext->tRspBuffInfo.wLen) = (pDlContext->tRWInfo.wBytesRead); + + (pDlContext->tRWInfo.wRemBytes) -= + (pDlContext->tRWInfo.wBytesToSendRecv); + (pDlContext->tRWInfo.dwAddr) += + (pDlContext->tRWInfo.wBytesToSendRecv); + (pDlContext->tRWInfo.wOffset) += + (pDlContext->tRWInfo.wBytesToSendRecv); + } + } else { + NXPLOG_FWDNLD_E("Unsuccessful Status received!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED); + } + } else { + if (PH_DL_STATUS_OK == (pInfo->pBuff[PHDNLDNFC_FRAMESTATUS_OFFSET])) { + if ((0 != (pDlContext->tRspBuffInfo.wLen)) && + (NULL != (pDlContext->tRspBuffInfo.pBuff))) { + memcpy((pDlContext->tRspBuffInfo.pBuff), + &(pInfo->pBuff[PHDNLDNFC_FRAMESTATUS_OFFSET + 1]), wPldLen); + + (pDlContext->tRspBuffInfo.wLen) = wPldLen; + } + } else { + NXPLOG_FWDNLD_E("Unsuccessful Status received!!"); + wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED); + } + } + } + + return wStatus; +} diff --git a/pn54x/dnld/phDnldNfc_Internal.h b/pn54x/dnld/phDnldNfc_Internal.h new file mode 100644 index 0000000..9a9d422 --- /dev/null +++ b/pn54x/dnld/phDnldNfc_Internal.h @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2010-2014 NXP Semiconductors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Internal Primitives (Functions + Variables) used for Firmware Download + */ +#ifndef PHDNLDNFC_INTERNAL_H +#define PHDNLDNFC_INTERNAL_H + +#include <phDnldNfc.h> +#include <phDnldNfc_Cmd.h> +#include <phDnldNfc_Status.h> + +#define PHDNLDNFC_CMDRESP_MAX_BUFF_SIZE \ + (0x100U) /* DL Host Frame Buffer Size for all CMD/RSP \ + except pipelined WRITE */ +#if (PHDNLDNFC_CMDRESP_MAX_BUFF_SIZE > PHNFC_I2C_FRAGMENT_SIZE) +#undef PHDNLDNFC_CMDRESP_MAX_BUFF_SIZE +#define PHDNLDNFC_CMDRESP_MAX_BUFF_SIZE (PHNFC_I2C_FRAGMENT_SIZE) +#endif + +/* DL Host Short Frame Buffer Size for pipelined WRITE RSP */ +#define PHDNLDNFC_WRITERSP_BUFF_SIZE (0x08U) + +/* DL Host Frame Buffer Header Length */ +#define PHDNLDNFC_FRAME_HDR_LEN (0x02U) +/* DL Host Frame Buffer CRC Length */ +#define PHDNLDNFC_FRAME_CRC_LEN (PHDNLDNFC_FRAME_HDR_LEN) +#define PHDNLDNFC_FRAME_ID_LEN (0x01U) /* Length of Cmd Id */ + +/* size of EEPROM/Flash address */ +#define PHDNLDNFC_EEFL_ADDR_SIZE (0x03U) +/* 2 Byte size of data */ +#define PHDNLDNFC_DATA_SIZE (PHDNLDNFC_FRAME_HDR_LEN) + +/* Start of EEPROM address for log */ +#define PHDNLDNFC_EEPROM_LOG_START_ADDR (0x201F80U) +/* End of EEPROM address for log */ +#define PHDNLDNFC_EEPROM_LOG_END_ADDR (0x201FBFU) + +#define PHDNLDNFC_MAX_LOG_SIZE \ + ((PHDNLDNFC_EEPROM_LOG_END_ADDR - PHDNLDNFC_EEPROM_LOG_START_ADDR) + 1) + +/* DL Max Payload Size */ +#define PHDNLDNFC_CMDRESP_MAX_PLD_SIZE \ + ((PHDNLDNFC_CMDRESP_MAX_BUFF_SIZE) - \ + (PHDNLDNFC_FRAME_HDR_LEN + PHDNLDNFC_FRAME_CRC_LEN)) + +/* + * Enum definition contains Download Event Types + */ +typedef enum phDnldNfc_Event { + phDnldNfc_EventInvalid = 0x00, /*Invalid Event Value*/ + phDnldNfc_EventReset, /* Reset event */ + phDnldNfc_EventGetVer, /* Get Version event*/ + phDnldNfc_EventWrite, /* Write event*/ + phDnldNfc_EventRead, /* Read event*/ + phDnldNfc_EventIntegChk, /* Integrity Check event*/ + phDnldNfc_EventGetSesnSt, /* Get Session State event*/ + phDnldNfc_EventLog, /* Log event*/ + phDnldNfc_EventForce, /* Force event*/ + phDnldNfc_EventRaw, /* Raw Req/Rsp event,used currently for sending NCI RESET + cmd */ + phDnldNfc_EVENT_INT_MAX /* Max Event Count*/ +} phDnldNfc_Event_t; + +/* + * Enum definition contains Download Handler states for each event requested + */ +typedef enum phDnldNfc_State { + phDnldNfc_StateInit = 0x00, /* Handler init state */ + phDnldNfc_StateSend, /* Send frame to NFCC state */ + phDnldNfc_StateRecv, /* Recv Send complete State */ + phDnldNfc_StateTimer, /* State to stop prev set timer on Recv or handle timed + out scenario */ + phDnldNfc_StateResponse, /* Process response from NFCC state */ + phDnldNfc_StatePipelined, /* Write requests to be pipelined state */ + phDnldNfc_StateInvalid /* Invalid Handler state */ +} phDnldNfc_State_t; + +/* + * Enum definition contains Download Handler Transition + */ +typedef enum phDnldNfc_Transition { + phDnldNfc_TransitionIdle = + 0x00, /* Handler in Idle state - No Download in progress */ + phDnldNfc_TransitionBusy, /* Handler is busy processing download request */ + phDnldNfc_TransitionInvalid /* Invalid Handler Transition */ +} phDnldNfc_Transition_t; + +/* + * Enum definition contains the Frame input type for CmdId in process + */ +typedef enum { + phDnldNfc_FTNone = 0, /* input type None */ + phDnldNfc_ChkIntg, /* user eeprom offset & len to be added for Check Integrity + Request */ + phDnldNfc_FTWrite, /* Frame inputs for Write request */ + phDnldNfc_FTLog, /* Frame inputs for Log request */ + phDnldNfc_FTForce, /* Frame input for Force cmd request */ + phDnldNfc_FTRead, /* Addr input required for read request */ + phDnldNfc_FTRaw /* Raw Req/Rsp type */ +} phDnldNfc_FrameInputType_t; + +/* + * Contains Host Frame Buffer information. + */ +typedef struct phDnldNfc_FrameInfo { + uint16_t dwSendlength; /* length of the payload */ + uint8_t + aFrameBuff[PHDNLDNFC_CMDRESP_MAX_BUFF_SIZE]; /* Buffer to store command + that needs to be sent*/ +} phDnldNfc_FrameInfo_t, + *pphDnldNfc_FrameInfo_t; /* pointer to #phDnldNfc_FrameInfo_t */ + +/* + * Frame Input Type & Value for CmdId in Process + */ +typedef struct phDnldNfc_FrameInput { + phDnldNfc_FrameInputType_t + Type; /* Type of frame input required for current cmd in process */ + uint32_t dwAddr; /* Address value required for Read/Write Cmd*/ +} phDnldNfc_FrameInput_t, + *pphDnldNfc_FrameInput_t; /* pointer to #phDnldNfc_FrameInput_t */ + +/* + * Context for the response timeout + */ +typedef struct phDnldNfc_RspTimerInfo { + uint32_t dwRspTimerId; /* Timer for Core to handle response */ + uint8_t TimerStatus; /* 0 = Timer not running 1 = timer running*/ + NFCSTATUS wTimerExpStatus; /* Holds the status code on timer expiry */ +} phDnldNfc_RspTimerInfo_t; + +/* + * Read/Write Processing Info + */ +typedef struct phDnldNfc_RWInfo { + uint32_t dwAddr; /* current Addr updated for read/write */ + uint16_t wOffset; /* current offset within the user buffer to read/write */ + uint16_t wRemBytes; /* Remaining bytes to read/write */ + uint16_t wRemChunkBytes; /* Remaining bytes within the chunked frame */ + uint16_t wRWPldSize; /* Size of the read/write payload per transaction */ + uint16_t wBytesToSendRecv; /* Num of Bytes being written/read currently */ + uint16_t wBytesRead; /* Bytes read from read cmd currently */ + bool_t bFramesSegmented; /* Flag to indicate if Read/Write frames are + segmented */ + bool_t bFirstWrReq; /* Flag to indicate if this is the first write frame being + sent */ + bool_t + bFirstChunkResp; /* Flag to indicate if we got the first chunk response */ +} phDnldNfc_RWInfo_t, *pphDnldNfc_RWInfo_t; /* pointer to #phDnldNfc_RWInfo_t */ + +/* + * Download context structure + */ +typedef struct phDnldNfc_DlContext { + const uint8_t* nxp_nfc_fw; /* Pointer to firmware version from image */ + const uint8_t* + nxp_nfc_fwp; /* Pointer to firmware version from get_version cmd */ + uint16_t nxp_nfc_fwp_len; /* Length of firmware image length */ + uint16_t nxp_nfc_fw_len; /* Firmware image length */ + bool_t bResendLastFrame; /* Flag to resend the last write frame after MEM_BSY + status */ + phDnldNfc_Transition_t + tDnldInProgress; /* Flag to indicate if download request is ongoing */ + phDnldNfc_Event_t tCurrEvent; /* Current event being processed */ + phDnldNfc_State_t tCurrState; /* Current state being processed */ + pphDnldNfc_RspCb_t UserCb; /* Upper layer call back function */ + void* UserCtxt; /* Pointer to upper layer context */ + phDnldNfc_Buff_t tUserData; /* Data buffer provided by caller */ + phDnldNfc_Buff_t + tRspBuffInfo; /* Buffer to store payload field of the received response*/ + phDnldNfc_FrameInfo_t tCmdRspFrameInfo; /* Buffer to hold the cmd/resp frame + except pipeline write */ + phDnldNfc_FrameInfo_t + tPipeLineWrFrameInfo; /* Buffer to hold the pipelined write frame */ + NFCSTATUS + wCmdSendStatus; /* Holds the status of cmd request made to cmd handler */ + phDnldNfc_CmdId_t tCmdId; /* Cmd Id of the currently processed cmd */ + phDnldNfc_FrameInput_t + FrameInp; /* input value required for current cmd in process */ + phDnldNfc_RspTimerInfo_t + TimerInfo; /* Timer context handled into download context*/ + phDnldNfc_Buff_t tTKey; /* Defualt Transport Key provided by caller */ + phDnldNfc_RWInfo_t tRWInfo; /* Read/Write segmented frame info */ + phDnldNfc_Status_t tLastStatus; /* saved status to distinguish signature or + pltform recovery */ +} phDnldNfc_DlContext_t, + *pphDnldNfc_DlContext_t; /* pointer to #phDnldNfc_DlContext_t structure */ + +/* The phDnldNfc_CmdHandler function declaration */ +extern NFCSTATUS phDnldNfc_CmdHandler(void* pContext, + phDnldNfc_Event_t TrigEvent); + +#endif /* PHDNLDNFC_INTERNAL_H */ diff --git a/pn54x/dnld/phDnldNfc_Status.h b/pn54x/dnld/phDnldNfc_Status.h new file mode 100644 index 0000000..a5b9125 --- /dev/null +++ b/pn54x/dnld/phDnldNfc_Status.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2010-2014 NXP Semiconductors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Firmware Download Status Values + */ +#ifndef PHDNLDNFC_STATUS_H +#define PHDNLDNFC_STATUS_H + +#include <phNfcStatus.h> + +/* reusing LibNfcStatus.h value below as a placeholder for now, need to find + the right value */ +#define NFCSTATUS_ABORTED (0x0096) /* Command aborted */ + +/* + * Enum definition contains Firmware Download Status codes + */ +typedef enum phDnldNfc_Status { + PH_DL_STATUS_PLL_ERROR = 0x0D, + PH_DL_STATUS_LC_WRONG = 0x13, + PH_DL_STATUS_LC_TERMINATION_NOT_SUPPORTED = 0x14, + PH_DL_STATUS_LC_CREATION_NOT_SUPPORTED = 0x15, + PH_DL_STATUS_LC_UNKNOWN = 0x16, + PH_DL_STATUS_AUTHENTICATION_ERROR = 0x19, + PH_DL_STATUS_NOT_AUTHENTICATED = 0x1A, + PH_DL_STATUS_AUTHENTICATION_LOST = 0x1B, + PH_DL_STATUS_WRITE_PROTECTED = 0x1C, + PH_DL_STATUS_READ_PROTECTED = 0x1D, + PH_DL_STATUS_ADDR_RANGE_OFL_ERROR = 0x1E, + PH_DL_STATUS_BUFFER_OFL_ERROR = 0x1F, + PH_DL_STATUS_MEM_BSY = 0x20, + PH_DL_STATUS_SIGNATURE_ERROR = 0x21, + PH_DL_STATUS_SESSION_WAS_OPEN = 0x22, + PH_DL_STATUS_SESSION_WAS_CLOSED = 0x23, + /* the Firmware version passed to CommitSession is not greater than + the EEPROM resident stored Firmware version number */ + PH_DL_STATUS_FIRMWARE_VERSION_ERROR = 0x24, + PH_DL_STATUS_LOOPBACK_DATA_MISSMATCH_ERROR = 0x25, + /*****************************/ + PH_DL_STATUS_HOST_PAYLOAD_UFL_ERROR = 0x26, + PH_DL_STATUS_HOST_PAYLOAD_OFL_ERROR = 0x27, + PH_DL_STATUS_PROTOCOL_ERROR = 0x28, + /* Download codes re-mapped to generic entries */ + PH_DL_STATUS_INVALID_ADDR = NFCSTATUS_INVALID_PARAMETER, + PH_DL_STATUS_GENERIC_ERROR = NFCSTATUS_FAILED, + PH_DL_STATUS_ABORTED_CMD = NFCSTATUS_ABORTED, + PH_DL_STATUS_FLASH_WRITE_PROTECTED = PH_DL_STATUS_WRITE_PROTECTED, + PH_DL_STATUS_FLASH_READ_PROTECTED = PH_DL_STATUS_READ_PROTECTED, + PH_DL_STATUS_USERDATA_WRITE_PROTECTED = PH_DL_STATUS_WRITE_PROTECTED, + PH_DL_STATUS_USERDATA_READ_PROTECTED = PH_DL_STATUS_READ_PROTECTED, + PH_DL_STATUS_OK = NFCSTATUS_SUCCESS +} phDnldNfc_Status_t; + +#endif /* PHDNLDNFC_STATUS_H */ diff --git a/pn54x/dnld/phDnldNfc_Utils.c b/pn54x/dnld/phDnldNfc_Utils.c new file mode 100644 index 0000000..014ca66 --- /dev/null +++ b/pn54x/dnld/phDnldNfc_Utils.c @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2010-2014 NXP Semiconductors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Download Component + * Download Utility routines implementation + */ + +#include <phDnldNfc_Utils.h> +#include <phNxpLog.h> + +static uint16_t const aCrcTab[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, + 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, + 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, + 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, + 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, + 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, + 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, + 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, + 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, + 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, + 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, + 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, + 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, + 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, + 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, + 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, + 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, + 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, + 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, + 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, + 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, + 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, + 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, + 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, + 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, + 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0}; + +/******************************************************************************* +** +** Function phDnldNfc_CalcCrc16 +** +** Description Calculates CRC16 for the frame buffer +** +** Parameters pBuff - CRC16 calculation input buffer +** wLen - input buffer length +** +** Returns wCrc - computed 2 byte CRC16 value +** +*******************************************************************************/ +uint16_t phDnldNfc_CalcCrc16(uint8_t* pBuff, uint16_t wLen) { + uint16_t wTmp; + uint16_t wValue; + uint16_t wCrc = 0xffff; + uint32_t i; + + if ((NULL == pBuff) || (0 == wLen)) { + NXPLOG_FWDNLD_W("Invalid Params supplied!!"); + } else { + /* Perform CRC calculation according to ccitt with a initial value of 0x1d0f + */ + for (i = 0; i < wLen; i++) { + wValue = 0x00ffU & (uint16_t)pBuff[i]; + wTmp = (wCrc >> 8U) ^ wValue; + wCrc = (wCrc << 8U) ^ aCrcTab[wTmp]; + } + } + + return wCrc; +} diff --git a/pn54x/dnld/phDnldNfc_Utils.h b/pn54x/dnld/phDnldNfc_Utils.h new file mode 100644 index 0000000..4b4e2af --- /dev/null +++ b/pn54x/dnld/phDnldNfc_Utils.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2010-2014 NXP Semiconductors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Firmware Download Utilities File + */ +#ifndef PHDNLDNFC_UTILS_H +#define PHDNLDNFC_UTILS_H + +#include <phDnldNfc.h> + +extern uint16_t phDnldNfc_CalcCrc16(uint8_t* pBuff, uint16_t wLen); + +#endif /* PHDNLDNFC_UTILS_H */ diff --git a/pn54x/dnld/phNxpNciHal_Dnld.c b/pn54x/dnld/phNxpNciHal_Dnld.c new file mode 100644 index 0000000..42cadba --- /dev/null +++ b/pn54x/dnld/phNxpNciHal_Dnld.c @@ -0,0 +1,1808 @@ +/* + * Copyright (C) 2012-2014 NXP Semiconductors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <phDnldNfc.h> +#include <phNxpConfig.h> +#include <phNxpLog.h> +#include <phNxpNciHal_Dnld.h> +#include <phNxpNciHal_utils.h> +#include <phTmlNfc.h> + +/* Macro */ +#define PHLIBNFC_IOCTL_DNLD_MAX_ATTEMPTS 3 +#define PHLIBNFC_IOCTL_DNLD_GETVERLEN (0x0BU) +#define PHLIBNFC_IOCTL_DNLD_GETVERLEN_MRA2_1 (0x09U) +#define PHLIBNFC_DNLD_MEM_READ (0xECU) +#define PHLIBNFC_DNLD_MEM_WRITE (0xEDU) +#define PHLIBNFC_DNLD_READ_LOG (0xEEU) +#define NFC_MEM_READ (0xD0U) +#define NFC_MEM_WRITE (0xD1U) +#define NFC_FW_DOWNLOAD (0x09F7U) + +/* External global variable to get FW version */ +extern uint16_t wFwVer; +extern uint16_t wMwVer; +#if (NFC_NXP_CHIP_TYPE != PN547C2) +extern uint8_t gRecFWDwnld; +#endif +/* RF Configuration structure */ +typedef struct phLibNfc_IoctlSetRfConfig { + uint8_t bNumOfParams; /* Number of Rf configurable parameters to be set */ + uint8_t* pInputBuffer; /* Buffer containing Rf configurable parameters */ + uint8_t bSetSysPmuFlag; /* Flag to decide wether to set SystemPmu or no from + the first byte */ +} phLibNfc_IoctlSetRfConfig; + +/* Structure to hold information from EEPROM */ +typedef struct phLibNfc_EELogParams { + uint16_t wCurrMwVer; /* Holds current MW version on the chip */ + uint16_t wCurrFwVer; /* Holds current FW version on the chip */ + uint16_t wNumDnldTrig; /* Total number of times dnld has been attempted */ + uint16_t wNumDnldSuccess; /* Total number of times dnld has been successful */ + uint16_t wNumDnldFail; /* Total number of times dnld has Failed */ + uint16_t wDnldFailCnt; /* holds the number of times dnld has failed,will be + reset on success */ + bool_t bConfig; /* Flag to be set in dnld mode after successful dnld,to be + reset in NCI Mode + after setting the NCI configuration */ +} phLibNfc_EELogParams_t; + +/* FW download module context structure */ +typedef struct { + bool_t bDnldEepromWrite; /* Flag to indicate eeprom write request*/ + bool_t + bSkipSeq; /* Flag to indicate FW download sequence to be skipped or not */ + bool_t bSkipReset; /* Flag to indicate Reset cmd to be skipped or not in FW + download sequence */ + bool_t bSkipForce; /* Flag to indicate Force cmd to be skipped or not in FW + recovery sequence */ + bool_t bPrevSessnOpen; /* Flag to indicate previous download session is open + or not */ + bool_t bLibNfcCtxtMem; /* flag to indicate if mem was allocated for + gpphLibNfc_Context */ + bool_t bDnldInitiated; /* Flag to indicate if fw upgrade was initiated */ + bool_t + bSendNciCmd; /* Flag to indicate if NCI cmd to be sent or not,after PKU */ + uint8_t bChipVer; /* holds the hw chip version */ + bool_t bDnldRecovery; /* Flag to indicate if dnld recovery sequence needs to + be triggered */ + bool_t bForceDnld; /* Flag to indicate if forced download option is enabled */ + bool_t bRetryDnld; /* Flag to indicate retry download after successful + recovery complete */ + uint8_t + bDnldAttempts; /* Holds the count of no. of dnld attempts made.max 3 */ + uint16_t IoctlCode; /* Ioctl code*/ + bool_t bDnldAttemptFailed; /* Flag to indicate last download attempt failed */ + NFCSTATUS bLastStatus; /* Holds the actual download write attempt status */ + phLibNfc_EELogParams_t + tLogParams; /* holds the params that could be logged to reserved EE + address */ + uint8_t bClkSrcVal; /* Holds the System clock source read from config file */ + uint8_t + bClkFreqVal; /* Holds the System clock frequency read from config file */ +} phNxpNciHal_fw_Ioctl_Cntx_t; + +/* Global variables used in this file only*/ +static phNxpNciHal_fw_Ioctl_Cntx_t gphNxpNciHal_fw_IoctlCtx; + +/* Local function prototype */ +static NFCSTATUS phNxpNciHal_fw_dnld_reset(void* pContext, NFCSTATUS status, + void* pInfo); + +static void phNxpNciHal_fw_dnld_reset_cb(void* pContext, NFCSTATUS status, + void* pInfo); + +static NFCSTATUS phNxpNciHal_fw_dnld_force(void* pContext, NFCSTATUS status, + void* pInfo); + +static void phNxpNciHal_fw_dnld_force_cb(void* pContext, NFCSTATUS status, + void* pInfo); + +static void phNxpNciHal_fw_dnld_normal_cb(void* pContext, NFCSTATUS status, + void* pInfo); + +static NFCSTATUS phNxpNciHal_fw_dnld_normal(void* pContext, NFCSTATUS status, + void* pInfo); + +static void phNxpNciHal_fw_dnld_get_version_cb(void* pContext, NFCSTATUS status, + void* pInfo); + +static NFCSTATUS phNxpNciHal_fw_dnld_get_version(void* pContext, + NFCSTATUS status, void* pInfo); + +static void phNxpNciHal_fw_dnld_get_sessn_state_cb(void* pContext, + NFCSTATUS status, + void* pInfo); + +static NFCSTATUS phNxpNciHal_fw_dnld_get_sessn_state(void* pContext, + NFCSTATUS status, + void* pInfo); + +static void phNxpNciHal_fw_dnld_log_read_cb(void* pContext, NFCSTATUS status, + void* pInfo); + +static NFCSTATUS phNxpNciHal_fw_dnld_log_read(void* pContext, NFCSTATUS status, + void* pInfo); + +static void phNxpNciHal_fw_dnld_write_cb(void* pContext, NFCSTATUS status, + void* pInfo); + +static NFCSTATUS phNxpNciHal_fw_dnld_write(void* pContext, NFCSTATUS status, + void* pInfo); + +static void phNxpNciHal_fw_dnld_chk_integrity_cb(void* pContext, + NFCSTATUS status, void* pInfo); + +static NFCSTATUS phNxpNciHal_fw_dnld_chk_integrity(void* pContext, + NFCSTATUS status, + void* pInfo); + +static void phNxpNciHal_fw_dnld_log_cb(void* pContext, NFCSTATUS status, + void* pInfo); + +static NFCSTATUS phNxpNciHal_fw_dnld_log(void* pContext, NFCSTATUS status, + void* pInfo); + +static void phNxpNciHal_fw_dnld_send_ncicmd_Cb(void* pContext, NFCSTATUS status, + void* pInfo); + +static NFCSTATUS phNxpNciHal_fw_dnld_send_ncicmd(void* pContext, + NFCSTATUS status, void* pInfo); + +static NFCSTATUS phNxpNciHal_fw_dnld_recover(void* pContext, NFCSTATUS status, + void* pInfo); + +static NFCSTATUS phNxpNciHal_fw_dnld_complete(void* pContext, NFCSTATUS status, + void* pInfo); + +/* Internal function to verify Crc Status byte received during CheckIntegrity */ +static NFCSTATUS phLibNfc_VerifyCrcStatus(uint8_t bCrcStatus); + +static void phNxpNciHal_fw_dnld_recover_cb(void* pContext, NFCSTATUS status, + void* pInfo); + +static NFCSTATUS phNxpNciHal_fw_seq_handler( + NFCSTATUS (*seq_handler[])(void* pContext, NFCSTATUS status, void* pInfo)); + +/* Array of pointers to start fw download seq */ +static NFCSTATUS (*phNxpNciHal_dwnld_seqhandler[])(void* pContext, + NFCSTATUS status, + void* pInfo) = { +#if (NFC_NXP_CHIP_TYPE == PN547C2) + phNxpNciHal_fw_dnld_normal, + phNxpNciHal_fw_dnld_normal, +#endif + phNxpNciHal_fw_dnld_get_sessn_state, + phNxpNciHal_fw_dnld_get_version, + phNxpNciHal_fw_dnld_log_read, + phNxpNciHal_fw_dnld_write, + phNxpNciHal_fw_dnld_get_sessn_state, + phNxpNciHal_fw_dnld_get_version, + phNxpNciHal_fw_dnld_log, + phNxpNciHal_fw_dnld_chk_integrity, + NULL}; + +#if (NFC_NXP_CHIP_TYPE != PN547C2) +/* Array of pointers to start dummy fw download seq */ +static NFCSTATUS (*phNxpNciHal_dummy_rec_dwnld_seqhandler[])(void* pContext, + NFCSTATUS status, + void* pInfo) = { + phNxpNciHal_fw_dnld_normal, + phNxpNciHal_fw_dnld_normal, + phNxpNciHal_fw_dnld_get_sessn_state, + phNxpNciHal_fw_dnld_get_version, + phNxpNciHal_fw_dnld_log_read, + phNxpNciHal_fw_dnld_write, + NULL}; +#endif + +/* Download Recovery Sequence */ +static NFCSTATUS (*phNxpNciHal_dwnld_rec_seqhandler[])(void* pContext, + NFCSTATUS status, + void* pInfo) = { + phNxpNciHal_fw_dnld_reset, phNxpNciHal_fw_dnld_force, + phNxpNciHal_fw_dnld_recover, phNxpNciHal_fw_dnld_send_ncicmd, NULL}; + +/* Download Log Sequence */ +static NFCSTATUS (*phNxpNciHal_dwnld_log_seqhandler[])(void* pContext, + NFCSTATUS status, + void* pInfo) = { + phNxpNciHal_fw_dnld_log, NULL}; + +/******************************************************************************* +** +** Function phNxpNciHal_fw_dnld_reset_cb +** +** Description Download Reset callback +** +** Returns None +** +*******************************************************************************/ +static void phNxpNciHal_fw_dnld_reset_cb(void* pContext, NFCSTATUS status, + void* pInfo) { + phNxpNciHal_Sem_t* p_cb_data = (phNxpNciHal_Sem_t*)pContext; + UNUSED(pInfo); + if (NFCSTATUS_SUCCESS == status) { + NXPLOG_FWDNLD_D("phNxpNciHal_fw_dnld_reset_cb - Request Successful"); + } else { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_reset_cb - Request Failed!!"); + } + p_cb_data->status = status; + + SEM_POST(p_cb_data); + + return; +} + +/******************************************************************************* +** +** Function phNxpNciHal_fw_dnld_reset +** +** Description Download Reset +** +** Returns NFCSTATUS_SUCCESS if success +** +*******************************************************************************/ +static NFCSTATUS phNxpNciHal_fw_dnld_reset(void* pContext, NFCSTATUS status, + void* pInfo) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + phNxpNciHal_Sem_t cb_data; + UNUSED(pContext); + UNUSED(status); + UNUSED(pInfo); + if (((gphNxpNciHal_fw_IoctlCtx.bSkipSeq) == true) || + ((gphNxpNciHal_fw_IoctlCtx.bSkipReset) == true)) { + if ((gphNxpNciHal_fw_IoctlCtx.bSkipReset) == true) { + (gphNxpNciHal_fw_IoctlCtx.bSkipReset) = false; + } + return NFCSTATUS_SUCCESS; + } + + if (phNxpNciHal_init_cb_data(&cb_data, NULL) != NFCSTATUS_SUCCESS) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_reset Create dnld_cb_data failed"); + return NFCSTATUS_FAILED; + } + wStatus = phDnldNfc_Reset((pphDnldNfc_RspCb_t)&phNxpNciHal_fw_dnld_reset_cb, + (void*)&cb_data); + + if (wStatus != NFCSTATUS_PENDING) { + NXPLOG_FWDNLD_E("phDnldNfc_Reset failed"); + wStatus = NFCSTATUS_FAILED; + goto clean_and_return; + } + + /* Wait for callback response */ + if (SEM_WAIT(cb_data)) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_reset semaphore error"); + wStatus = NFCSTATUS_FAILED; + goto clean_and_return; + } + + if (cb_data.status != NFCSTATUS_SUCCESS) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_reset cb failed"); + wStatus = NFCSTATUS_FAILED; + goto clean_and_return; + } + + wStatus = NFCSTATUS_SUCCESS; + +clean_and_return: + phNxpNciHal_cleanup_cb_data(&cb_data); + + return wStatus; +} + +/******************************************************************************* +** +** Function phNxpNciHal_fw_dnld_normal_cb +** +** Description Download Normal callback +** +** Returns None +** +*******************************************************************************/ +static void phNxpNciHal_fw_dnld_normal_cb(void* pContext, NFCSTATUS status, + void* pInfo) { + phNxpNciHal_Sem_t* p_cb_data = (phNxpNciHal_Sem_t*)pContext; + UNUSED(pInfo); + if (NFCSTATUS_SUCCESS == status) { + NXPLOG_FWDNLD_D("phNxpNciHal_fw_dnld_normal_cb - Request Successful"); + } else { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_normal_cb - Request Failed!!"); + /* In this fail scenario trick the sequence handler to call next recover + * sequence */ + status = NFCSTATUS_SUCCESS; + } + p_cb_data->status = status; + + SEM_POST(p_cb_data); + usleep(1000 * 10); + + return; +} + +/******************************************************************************* +** +** Function phNxpNciHal_fw_dnld_force_cb +** +** Description Download Force callback +** +** Returns None +** +*******************************************************************************/ +static void phNxpNciHal_fw_dnld_force_cb(void* pContext, NFCSTATUS status, + void* pInfo) { + phNxpNciHal_Sem_t* p_cb_data = (phNxpNciHal_Sem_t*)pContext; + UNUSED(pInfo); + if (NFCSTATUS_SUCCESS == status) { + NXPLOG_FWDNLD_D("phLibNfc_DnldForceCb - Request Successful"); + (gphNxpNciHal_fw_IoctlCtx.bDnldRecovery) = false; + (gphNxpNciHal_fw_IoctlCtx.bRetryDnld) = true; + (gphNxpNciHal_fw_IoctlCtx.bSkipReset) = true; + } else { + /* In this fail scenario trick the sequence handler to call next recover + * sequence */ + status = NFCSTATUS_SUCCESS; + NXPLOG_FWDNLD_E("phLibNfc_DnldForceCb - Request Failed!!"); + } + p_cb_data->status = status; + + SEM_POST(p_cb_data); + usleep(1000 * 10); + + return; +} + +/******************************************************************************* +** +** Function phNxpNciHal_fw_dnld_normal +** +** Description Download Normal +** +** Returns NFCSTATUS_SUCCESS if success +** +*******************************************************************************/ +static NFCSTATUS phNxpNciHal_fw_dnld_normal(void* pContext, NFCSTATUS status, + void* pInfo) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + uint8_t bClkVal[2]; + phDnldNfc_Buff_t tData; + phNxpNciHal_Sem_t cb_data; + UNUSED(pContext); + UNUSED(status); + UNUSED(pInfo); + if ((gphNxpNciHal_fw_IoctlCtx.bSkipForce) == true) { + return NFCSTATUS_SUCCESS; + } else { + /* + bClkVal[0] = NXP_SYS_CLK_SRC_SEL; + bClkVal[1] = NXP_SYS_CLK_FREQ_SEL; + */ + bClkVal[0] = gphNxpNciHal_fw_IoctlCtx.bClkSrcVal; + bClkVal[1] = gphNxpNciHal_fw_IoctlCtx.bClkFreqVal; + + (tData.pBuff) = bClkVal; + (tData.wLen) = sizeof(bClkVal); + + if ((gphNxpNciHal_fw_IoctlCtx.bDnldRecovery) == true) { + (gphNxpNciHal_fw_IoctlCtx.bDnldAttempts)++; + } + + if (phNxpNciHal_init_cb_data(&cb_data, NULL) != NFCSTATUS_SUCCESS) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_reset Create dnld_cb_data failed"); + return NFCSTATUS_FAILED; + } + wStatus = phDnldNfc_Force( + &tData, (pphDnldNfc_RspCb_t)&phNxpNciHal_fw_dnld_normal_cb, + (void*)&cb_data); + + if (NFCSTATUS_PENDING != wStatus) { + NXPLOG_FWDNLD_E("phDnldNfc_Normal failed"); + (gphNxpNciHal_fw_IoctlCtx.bSkipForce) = false; + (gphNxpNciHal_fw_IoctlCtx.bRetryDnld) = false; + goto clean_and_return; + } + } + + /* Wait for callback response */ + if (SEM_WAIT(cb_data)) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_normal semaphore error"); + wStatus = NFCSTATUS_FAILED; + goto clean_and_return; + } + + if (cb_data.status != NFCSTATUS_SUCCESS) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_normal cb failed"); + wStatus = NFCSTATUS_FAILED; + goto clean_and_return; + } + + wStatus = NFCSTATUS_SUCCESS; + +clean_and_return: + phNxpNciHal_cleanup_cb_data(&cb_data); + + return wStatus; +} + +/******************************************************************************* +** +** Function phNxpNciHal_fw_dnld_force +** +** Description Download Force +** +** Returns NFCSTATUS_SUCCESS if success +** +*******************************************************************************/ +static NFCSTATUS phNxpNciHal_fw_dnld_force(void* pContext, NFCSTATUS status, + void* pInfo) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + uint8_t bClkVal[2]; + phDnldNfc_Buff_t tData; + phNxpNciHal_Sem_t cb_data; + UNUSED(pContext); + UNUSED(status); + UNUSED(pInfo); + if ((gphNxpNciHal_fw_IoctlCtx.bSkipForce) == true) { + return NFCSTATUS_SUCCESS; + } else { + /* + bClkVal[0] = NXP_SYS_CLK_SRC_SEL; + bClkVal[1] = NXP_SYS_CLK_FREQ_SEL; + */ + bClkVal[0] = gphNxpNciHal_fw_IoctlCtx.bClkSrcVal; + bClkVal[1] = gphNxpNciHal_fw_IoctlCtx.bClkFreqVal; + + (tData.pBuff) = bClkVal; + (tData.wLen) = sizeof(bClkVal); + + if ((gphNxpNciHal_fw_IoctlCtx.bDnldRecovery) == true) { + (gphNxpNciHal_fw_IoctlCtx.bDnldAttempts)++; + } + + if (phNxpNciHal_init_cb_data(&cb_data, NULL) != NFCSTATUS_SUCCESS) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_reset Create dnld_cb_data failed"); + return NFCSTATUS_FAILED; + } + wStatus = phDnldNfc_Force(&tData, + (pphDnldNfc_RspCb_t)&phNxpNciHal_fw_dnld_force_cb, + (void*)&cb_data); + + if (NFCSTATUS_PENDING != wStatus) { + NXPLOG_FWDNLD_E("phDnldNfc_Force failed"); + (gphNxpNciHal_fw_IoctlCtx.bSkipForce) = false; + (gphNxpNciHal_fw_IoctlCtx.bRetryDnld) = false; + goto clean_and_return; + } + } + + /* Wait for callback response */ + if (SEM_WAIT(cb_data)) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_force semaphore error"); + wStatus = NFCSTATUS_FAILED; + goto clean_and_return; + } + + if (cb_data.status != NFCSTATUS_SUCCESS) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_force cb failed"); + wStatus = NFCSTATUS_FAILED; + goto clean_and_return; + } + + wStatus = NFCSTATUS_SUCCESS; + +clean_and_return: + phNxpNciHal_cleanup_cb_data(&cb_data); + + return wStatus; +} + +/******************************************************************************* +** +** Function phNxpNciHal_fw_dnld_get_version_cb +** +** Description Download Get version callback +** +** Returns None +** +*******************************************************************************/ +static void phNxpNciHal_fw_dnld_get_version_cb(void* pContext, NFCSTATUS status, + void* pInfo) { + phNxpNciHal_Sem_t* p_cb_data = (phNxpNciHal_Sem_t*)pContext; + NFCSTATUS wStatus = status; + pphDnldNfc_Buff_t pRespBuff; + uint16_t wFwVern = 0; + uint16_t wMwVern = 0; + uint8_t bHwVer = 0; + uint8_t bExpectedLen = 0; + uint8_t bNewVer[2]; + uint8_t bCurrVer[2]; + + if ((NFCSTATUS_SUCCESS == wStatus) && (NULL != pInfo)) { + NXPLOG_FWDNLD_D("phNxpNciHal_fw_dnld_get_version_cb - Request Successful"); + + pRespBuff = (pphDnldNfc_Buff_t)pInfo; + + if ((0 != pRespBuff->wLen) && (NULL != pRespBuff->pBuff)) { + bHwVer = (pRespBuff->pBuff[0]); + bHwVer &= 0x0F; /* 0x0F is the mask to extract chip version */ + + if ((PHDNLDNFC_HWVER_MRA2_1 == bHwVer) || + (PHDNLDNFC_HWVER_MRA2_2 == bHwVer) +#if (NFC_NXP_CHIP_TYPE == PN551) + || (PHDNLDNFC_HWVER_PN551_MRA1_0 == bHwVer) +#elif (NFC_NXP_CHIP_TYPE == PN548C2) + || (PHDNLDNFC_HWVER_PN548AD_MRA1_0 == bHwVer) +#elif (NFC_NXP_CHIP_TYPE == PN553) + || (PHDNLDNFC_HWVER_PN553_MRA1_0 == bHwVer || + PHDNLDNFC_HWVER_PN553_MRA1_0_UPDATED & pRespBuff->pBuff[0]) +#endif + ) { + bExpectedLen = PHLIBNFC_IOCTL_DNLD_GETVERLEN_MRA2_1; + (gphNxpNciHal_fw_IoctlCtx.bChipVer) = bHwVer; +#if (NFC_NXP_CHIP_TYPE == PN553) + if (PHDNLDNFC_HWVER_PN553_MRA1_0_UPDATED & pRespBuff->pBuff[0]) { + (gphNxpNciHal_fw_IoctlCtx.bChipVer) = pRespBuff->pBuff[0]; + } +#endif + } else if ((bHwVer >= PHDNLDNFC_HWVER_MRA1_0) && + (bHwVer <= PHDNLDNFC_HWVER_MRA2_0)) { + bExpectedLen = PHLIBNFC_IOCTL_DNLD_GETVERLEN; + (gphNxpNciHal_fw_IoctlCtx.bChipVer) = bHwVer; + } else { + wStatus = NFCSTATUS_FAILED; + NXPLOG_FWDNLD_E( + "phNxpNciHal_fw_dnld_get_version_cb - Invalid ChipVersion!!"); + } + } else { + wStatus = NFCSTATUS_FAILED; + NXPLOG_FWDNLD_E( + "phNxpNciHal_fw_dnld_get_version_cb - Version Resp Buff " + "Invalid...\n"); + } + + if ((NFCSTATUS_SUCCESS == wStatus) && (bExpectedLen == pRespBuff->wLen) && + (NULL != pRespBuff->pBuff)) { + NXPLOG_FWDNLD_D( + "phNxpNciHal_fw_dnld_get_version_cb - Valid Version Resp " + "Buff!!...\n"); + + /* Validate version details to confirm if continue with the next sequence + * of Operations. */ + memcpy(bCurrVer, &(pRespBuff->pBuff[bExpectedLen - 2]), sizeof(bCurrVer)); + wFwVern = wFwVer; + wMwVern = wMwVer; + + memcpy(bNewVer, &wFwVern, sizeof(bNewVer)); + + /* check if the ROM code version and FW Major version is valid for the + * chip*/ + /* ES2.2 Rom Version - 0x7 and Valid FW Major Version - 0x1 */ + if ((pRespBuff->pBuff[1] == 0x07) && (bNewVer[1] != 0x01)) { + NXPLOG_FWDNLD_E( + "C1 FW on C2 chip is not allowed - FW Major Version!= 1 on ES2.2"); + wStatus = NFCSTATUS_NOT_ALLOWED; + } + /* Major Version number check */ + else if ((FALSE == (gphNxpNciHal_fw_IoctlCtx.bDnldInitiated)) && + (bNewVer[1] < bCurrVer[1])) { + NXPLOG_FWDNLD_E("Version Check Failed - MajorVerNum Mismatch\n"); + NXPLOG_FWDNLD_E("NewVer %d != CurrVer %d\n", bNewVer[1], bCurrVer[1]); + wStatus = NFCSTATUS_NOT_ALLOWED; + } + /* Minor Version number check - before download.*/ + else if ((FALSE == (gphNxpNciHal_fw_IoctlCtx.bDnldInitiated)) && + ((bNewVer[0] == bCurrVer[0]) && (bNewVer[1] == bCurrVer[1]))) { + wStatus = NFCSTATUS_SUCCESS; +#if (PH_LIBNFC_ENABLE_FORCE_DOWNLOAD == 0) + NXPLOG_FWDNLD_D("Version Already UpToDate!!\n"); + (gphNxpNciHal_fw_IoctlCtx.bSkipSeq) = TRUE; +#else + (gphNxpNciHal_fw_IoctlCtx.bForceDnld) = TRUE; +#endif + + } + /* Minor Version number check - after download + * after download, we should get the same version information.*/ + else if ((TRUE == (gphNxpNciHal_fw_IoctlCtx.bDnldInitiated)) && + ((bNewVer[0] != bCurrVer[0]) || (bNewVer[1] != bCurrVer[1]))) { + NXPLOG_FWDNLD_E("Version Not Updated After Download!!\n"); + wStatus = NFCSTATUS_FAILED; + } else { + NXPLOG_FWDNLD_D("Version Check Successful\n"); + /* Store the Mw & Fw Version for updating in EEPROM Log Area after + * successful download */ + if (TRUE == (gphNxpNciHal_fw_IoctlCtx.bDnldInitiated)) { + NXPLOG_FWDNLD_W("Updating Fw & Mw Versions.."); + (gphNxpNciHal_fw_IoctlCtx.tLogParams.wCurrMwVer) = wMwVern; + (gphNxpNciHal_fw_IoctlCtx.tLogParams.wCurrFwVer) = wFwVern; + } + } + } else { + NXPLOG_FWDNLD_E( + "phNxpNciHal_fw_dnld_get_version_cb - Version Resp Buff " + "Invalid...\n"); + } + } else { + wStatus = NFCSTATUS_FAILED; + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_get_version_cb - Request Failed!!"); + } + + p_cb_data->status = wStatus; + SEM_POST(p_cb_data); + return; +} + +/******************************************************************************* +** +** Function phNxpNciHal_fw_dnld_get_version +** +** Description Download Get version +** +** Returns NFCSTATUS_SUCCESS if success +** +*******************************************************************************/ +static NFCSTATUS phNxpNciHal_fw_dnld_get_version(void* pContext, + NFCSTATUS status, + void* pInfo) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + phNxpNciHal_Sem_t cb_data; + static uint8_t bGetVerRes[11]; + phDnldNfc_Buff_t tDnldBuff; + UNUSED(pContext); + UNUSED(status); + UNUSED(pInfo); + if (((gphNxpNciHal_fw_IoctlCtx.bSkipSeq) == true) || + ((gphNxpNciHal_fw_IoctlCtx.bPrevSessnOpen) == true)) { + return NFCSTATUS_SUCCESS; + } + + if (phNxpNciHal_init_cb_data(&cb_data, NULL) != NFCSTATUS_SUCCESS) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_get_version cb_data creation failed"); + return NFCSTATUS_FAILED; + } + + tDnldBuff.pBuff = bGetVerRes; + tDnldBuff.wLen = sizeof(bGetVerRes); + + wStatus = phDnldNfc_GetVersion( + &tDnldBuff, (pphDnldNfc_RspCb_t)&phNxpNciHal_fw_dnld_get_version_cb, + (void*)&cb_data); + if (wStatus != NFCSTATUS_PENDING) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_get_version failed"); + wStatus = NFCSTATUS_FAILED; + goto clean_and_return; + } + /* Wait for callback response */ + if (SEM_WAIT(cb_data)) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_get_version semaphore error"); + wStatus = NFCSTATUS_FAILED; + goto clean_and_return; + } + + if (cb_data.status != NFCSTATUS_SUCCESS) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_get_version cb failed"); + wStatus = NFCSTATUS_FAILED; + goto clean_and_return; + } + + wStatus = NFCSTATUS_SUCCESS; + +clean_and_return: + phNxpNciHal_cleanup_cb_data(&cb_data); + + return wStatus; +} + +/******************************************************************************* +** +** Function phNxpNciHal_fw_dnld_get_sessn_state_cb +** +** Description Download Get session state callback +** +** Returns None +** +*******************************************************************************/ +static void phNxpNciHal_fw_dnld_get_sessn_state_cb(void* pContext, + NFCSTATUS status, + void* pInfo) { + phNxpNciHal_Sem_t* p_cb_data = (phNxpNciHal_Sem_t*)pContext; + NFCSTATUS wStatus = status; + pphDnldNfc_Buff_t pRespBuff; + if ((NFCSTATUS_SUCCESS == wStatus) && (NULL != pInfo)) { + NXPLOG_FWDNLD_D( + "phNxpNciHal_fw_dnld_get_sessn_state_cb - Request Successful"); + + pRespBuff = (pphDnldNfc_Buff_t)pInfo; + + if ((3 == (pRespBuff->wLen)) && (NULL != (pRespBuff->pBuff))) { + NXPLOG_FWDNLD_D( + "phNxpNciHal_fw_dnld_get_sessn_state_cb - Valid Session State Resp " + "Buff!!..."); + + if (phDnldNfc_LCOper == pRespBuff->pBuff[2]) { + if (PHLIBNFC_FWDNLD_SESSNOPEN == pRespBuff->pBuff[0]) { + NXPLOG_FWDNLD_E("Prev Fw Upgrade Session still Open.."); + (gphNxpNciHal_fw_IoctlCtx.bPrevSessnOpen) = true; + if ((gphNxpNciHal_fw_IoctlCtx.bDnldInitiated) == true) { + NXPLOG_FWDNLD_D( + "Session still Open after Prev Fw Upgrade attempt!!"); + + if ((gphNxpNciHal_fw_IoctlCtx.bDnldAttempts) < + PHLIBNFC_IOCTL_DNLD_MAX_ATTEMPTS) { + NXPLOG_FWDNLD_W("Setting Dnld Retry .."); + (gphNxpNciHal_fw_IoctlCtx.bRetryDnld) = true; + } else { + NXPLOG_FWDNLD_E("Max Dnld Retry Counts Exceeded!!"); + (gphNxpNciHal_fw_IoctlCtx.bRetryDnld) = false; + } + wStatus = NFCSTATUS_FAILED; + } + } else { + gphNxpNciHal_fw_IoctlCtx.bPrevSessnOpen = false; + } + } else { + wStatus = NFCSTATUS_FAILED; + NXPLOG_FWDNLD_E( + "NFCC not in Operational State..Fw Upgrade not allowed!!"); + } + } else { + wStatus = NFCSTATUS_FAILED; + NXPLOG_FWDNLD_E( + "phNxpNciHal_fw_dnld_get_sessn_state_cb - Session State Resp Buff " + "Invalid..."); + } + } else { + wStatus = NFCSTATUS_FAILED; + NXPLOG_FWDNLD_E( + "phNxpNciHal_fw_dnld_get_sessn_state_cb - Request Failed!!"); + } + + p_cb_data->status = wStatus; + + SEM_POST(p_cb_data); + + return; +} + +/******************************************************************************* +** +** Function phNxpNciHal_fw_dnld_get_sessn_state +** +** Description Download Get session state +** +** Returns NFCSTATUS_SUCCESS if success +** +*******************************************************************************/ +static NFCSTATUS phNxpNciHal_fw_dnld_get_sessn_state(void* pContext, + NFCSTATUS status, + void* pInfo) { + phDnldNfc_Buff_t tDnldBuff; + static uint8_t bGSnStateRes[3]; + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + phNxpNciHal_Sem_t cb_data; + UNUSED(pContext); + UNUSED(status); + UNUSED(pInfo); + if (gphNxpNciHal_fw_IoctlCtx.bSkipSeq == true) { + return NFCSTATUS_SUCCESS; + } + + if (phNxpNciHal_init_cb_data(&cb_data, NULL) != NFCSTATUS_SUCCESS) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_get_version cb_data creation failed"); + return NFCSTATUS_FAILED; + } + + tDnldBuff.pBuff = bGSnStateRes; + tDnldBuff.wLen = sizeof(bGSnStateRes); + + wStatus = phDnldNfc_GetSessionState( + &tDnldBuff, &phNxpNciHal_fw_dnld_get_sessn_state_cb, (void*)&cb_data); + if (wStatus != NFCSTATUS_PENDING) { + NXPLOG_FWDNLD_E("phDnldNfc_GetSessionState failed"); + wStatus = NFCSTATUS_FAILED; + goto clean_and_return; + } + + /* Wait for callback response */ + if (SEM_WAIT(cb_data)) { + NXPLOG_FWDNLD_E("phDnldNfc_GetSessionState semaphore error"); + wStatus = NFCSTATUS_FAILED; + goto clean_and_return; + } + + if (cb_data.status != NFCSTATUS_SUCCESS) { + NXPLOG_FWDNLD_E("phDnldNfc_GetSessionState cb failed"); + wStatus = NFCSTATUS_FAILED; + goto clean_and_return; + } + + wStatus = NFCSTATUS_SUCCESS; + +clean_and_return: + phNxpNciHal_cleanup_cb_data(&cb_data); + + return wStatus; +} + +/******************************************************************************* +** +** Function phNxpNciHal_fw_dnld_log_read_cb +** +** Description Download Logread callback +** +** Returns None +** +*******************************************************************************/ +static void phNxpNciHal_fw_dnld_log_read_cb(void* pContext, NFCSTATUS status, + void* pInfo) { + phNxpNciHal_Sem_t* p_cb_data = (phNxpNciHal_Sem_t*)pContext; + + if ((NFCSTATUS_SUCCESS == status) && (NULL != pInfo)) { + NXPLOG_FWDNLD_D("phNxpNciHal_fw_dnld_log_read_cb - Request Successful"); + } else { + status = NFCSTATUS_FAILED; + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_log_read_cb - Request Failed!!"); + } + + p_cb_data->status = status; + SEM_POST(p_cb_data); + + return; +} + +/******************************************************************************* +** +** Function phNxpNciHal_fw_dnld_log_read +** +** Description Download Log Read +** +** Returns NFCSTATUS_SUCCESS if success +** +*******************************************************************************/ +static NFCSTATUS phNxpNciHal_fw_dnld_log_read(void* pContext, NFCSTATUS status, + void* pInfo) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + phNxpNciHal_Sem_t cb_data; + phDnldNfc_Buff_t Data; + UNUSED(pContext); + UNUSED(status); + UNUSED(pInfo); + if (((((gphNxpNciHal_fw_IoctlCtx.bSkipSeq) == true) || + ((gphNxpNciHal_fw_IoctlCtx.bForceDnld) == true)) && + ((gphNxpNciHal_fw_IoctlCtx.bPrevSessnOpen) == false)) || + ((((gphNxpNciHal_fw_IoctlCtx.bPrevSessnOpen) == true)) && + ((gphNxpNciHal_fw_IoctlCtx.bRetryDnld) == true))) + + { + return NFCSTATUS_SUCCESS; + } + + if (phNxpNciHal_init_cb_data(&cb_data, NULL) != NFCSTATUS_SUCCESS) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_log_read cb_data creation failed"); + return NFCSTATUS_FAILED; + } + + (Data.pBuff) = (void*)&(gphNxpNciHal_fw_IoctlCtx.tLogParams); + (Data.wLen) = sizeof(phLibNfc_EELogParams_t); + + wStatus = phDnldNfc_ReadLog( + &Data, (pphDnldNfc_RspCb_t)&phNxpNciHal_fw_dnld_log_read_cb, + (void*)&cb_data); + if (wStatus != NFCSTATUS_PENDING) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_log_read failed"); + wStatus = NFCSTATUS_FAILED; + goto clean_and_return; + } + + /* Wait for callback response */ + if (SEM_WAIT(cb_data)) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_log_read semaphore error"); + wStatus = NFCSTATUS_FAILED; + goto clean_and_return; + } + + if (cb_data.status != NFCSTATUS_SUCCESS) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_log_read cb failed"); + wStatus = NFCSTATUS_FAILED; + goto clean_and_return; + } + + wStatus = NFCSTATUS_SUCCESS; + +clean_and_return: + phNxpNciHal_cleanup_cb_data(&cb_data); + + return wStatus; +} + +/******************************************************************************* +** +** Function phNxpNciHal_fw_dnld_write_cb +** +** Description Download Write callback +** +** Returns None +** +*******************************************************************************/ +static void phNxpNciHal_fw_dnld_write_cb(void* pContext, NFCSTATUS status, + void* pInfo) { + phNxpNciHal_Sem_t* p_cb_data = (phNxpNciHal_Sem_t*)pContext; + UNUSED(pInfo); + if (NFCSTATUS_SUCCESS == status) { + NXPLOG_FWDNLD_D("phNxpNciHal_fw_dnld_write_cb - Request Successful"); + (gphNxpNciHal_fw_IoctlCtx.bDnldEepromWrite) = false; + if ((gphNxpNciHal_fw_IoctlCtx.bDnldInitiated) == true) { + (gphNxpNciHal_fw_IoctlCtx.tLogParams.wNumDnldSuccess) += 1; + + if ((gphNxpNciHal_fw_IoctlCtx.tLogParams.wDnldFailCnt) > 0) { + NXPLOG_FWDNLD_D("phNxpNciHal_fw_dnld_write_cb - Resetting DnldFailCnt"); + (gphNxpNciHal_fw_IoctlCtx.tLogParams.wDnldFailCnt) = 0; + } + + if ((gphNxpNciHal_fw_IoctlCtx.tLogParams.bConfig) == false) { + NXPLOG_FWDNLD_D( + "phNxpNciHal_fw_dnld_write_cb - Setting bConfig for use by NCI " + "mode"); + (gphNxpNciHal_fw_IoctlCtx.tLogParams.bConfig) = true; + } + } + + /* Reset the previously set DnldAttemptFailed flag */ + if ((gphNxpNciHal_fw_IoctlCtx.bDnldAttemptFailed) == true) { + (gphNxpNciHal_fw_IoctlCtx.bDnldAttemptFailed) = false; + } + } else { + if ((gphNxpNciHal_fw_IoctlCtx.bDnldInitiated) == true) { + (gphNxpNciHal_fw_IoctlCtx.tLogParams.wNumDnldFail) += 1; + (gphNxpNciHal_fw_IoctlCtx.tLogParams.wDnldFailCnt) += 1; + (gphNxpNciHal_fw_IoctlCtx.tLogParams.bConfig) = false; + } + if (NFCSTATUS_WRITE_FAILED == status) { + (gphNxpNciHal_fw_IoctlCtx.bSkipSeq) = true; + (gphNxpNciHal_fw_IoctlCtx.bDnldRecovery) = true; + } + // status = NFCSTATUS_FAILED; + + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_write_cb - Request Failed!!"); + } + + p_cb_data->status = status; + SEM_POST(p_cb_data); + + return; +} + +/******************************************************************************* +** +** Function phNxpNciHal_fw_dnld_write +** +** Description Download Write +** +** Returns NFCSTATUS_SUCCESS if success +** +*******************************************************************************/ +static NFCSTATUS phNxpNciHal_fw_dnld_write(void* pContext, NFCSTATUS status, + void* pInfo) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + phNxpNciHal_Sem_t cb_data; + UNUSED(pContext); + UNUSED(status); + UNUSED(pInfo); + if ((gphNxpNciHal_fw_IoctlCtx.bRetryDnld) == true) { + (gphNxpNciHal_fw_IoctlCtx.bRetryDnld) = false; + } + + if (((gphNxpNciHal_fw_IoctlCtx.bSkipSeq) == true) && + ((gphNxpNciHal_fw_IoctlCtx.bPrevSessnOpen) == false)) { + return NFCSTATUS_SUCCESS; + } + + if (phNxpNciHal_init_cb_data(&cb_data, NULL) != NFCSTATUS_SUCCESS) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_write cb_data creation failed"); + return NFCSTATUS_FAILED; + } + if ((gphNxpNciHal_fw_IoctlCtx.bForceDnld) == false) { + NXPLOG_FWDNLD_D("phNxpNciHal_fw_dnld_write - Incrementing NumDnldTrig.."); + (gphNxpNciHal_fw_IoctlCtx.bDnldInitiated) = true; + (gphNxpNciHal_fw_IoctlCtx.bDnldAttempts)++; + (gphNxpNciHal_fw_IoctlCtx.tLogParams.wNumDnldTrig) += 1; + } + wStatus = phDnldNfc_Write(false, NULL, + (pphDnldNfc_RspCb_t)&phNxpNciHal_fw_dnld_write_cb, + (void*)&cb_data); + if ((gphNxpNciHal_fw_IoctlCtx.bForceDnld) == false) { + if (wStatus != NFCSTATUS_PENDING) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_write failed"); + wStatus = NFCSTATUS_FAILED; + (gphNxpNciHal_fw_IoctlCtx.tLogParams.wNumDnldFail) += 1; + (gphNxpNciHal_fw_IoctlCtx.tLogParams.wDnldFailCnt) += 1; + (gphNxpNciHal_fw_IoctlCtx.tLogParams.bConfig) = false; + goto clean_and_return; + } + } + /* Wait for callback response */ + if (SEM_WAIT(cb_data)) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_write semaphore error"); + wStatus = NFCSTATUS_FAILED; + goto clean_and_return; + } + + if (cb_data.status != NFCSTATUS_SUCCESS) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_write cb failed"); + wStatus = cb_data.status; + goto clean_and_return; + } + + wStatus = NFCSTATUS_SUCCESS; + +clean_and_return: + phNxpNciHal_cleanup_cb_data(&cb_data); + + return wStatus; +} + +/******************************************************************************* +** +** Function phNxpNciHal_fw_dnld_chk_integrity_cb +** +** Description Download Check Integrity callback +** +** Returns None +** +*******************************************************************************/ +static void phNxpNciHal_fw_dnld_chk_integrity_cb(void* pContext, + NFCSTATUS status, + void* pInfo) { + phNxpNciHal_Sem_t* p_cb_data = (phNxpNciHal_Sem_t*)pContext; + NFCSTATUS wStatus = status; + pphDnldNfc_Buff_t pRespBuff; + // uint8_t bUserDataCrc[4]; + + if ((NFCSTATUS_SUCCESS == wStatus) && (NULL != pInfo)) { + NXPLOG_FWDNLD_D( + "phNxpNciHal_fw_dnld_chk_integrity_cb - Request Successful"); + pRespBuff = (pphDnldNfc_Buff_t)pInfo; + + if ((31 == (pRespBuff->wLen)) && (NULL != (pRespBuff->pBuff))) { + NXPLOG_FWDNLD_D( + "phNxpNciHal_fw_dnld_chk_integrity_cb - Valid Resp Buff!!...\n"); + wStatus = phLibNfc_VerifyCrcStatus(pRespBuff->pBuff[0]); + /* + memcpy(bUserDataCrc, &(pRespBuff->pBuff[27]), + sizeof(bUserDataCrc));*/ + } else { + NXPLOG_FWDNLD_E( + "phNxpNciHal_fw_dnld_chk_integrity_cb - Resp Buff Invalid...\n"); + } + } else { + wStatus = NFCSTATUS_FAILED; + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_chk_integrity_cb - Request Failed!!"); + } + + p_cb_data->status = wStatus; + + SEM_POST(p_cb_data); + + return; +} + +/******************************************************************************* +** +** Function phNxpNciHal_fw_dnld_chk_integrity +** +** Description Download Check Integrity +** +** Returns NFCSTATUS_SUCCESS if success +** +*******************************************************************************/ +static NFCSTATUS phNxpNciHal_fw_dnld_chk_integrity(void* pContext, + NFCSTATUS status, + void* pInfo) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + phNxpNciHal_Sem_t cb_data; + phDnldNfc_Buff_t tDnldBuff; + static uint8_t bChkIntgRes[31]; + UNUSED(pInfo); + UNUSED(pContext); + UNUSED(status); + if (gphNxpNciHal_fw_IoctlCtx.bPrevSessnOpen == true) { + NXPLOG_FWDNLD_D( + "Previous Upload session is open..Cannot issue ChkIntegrity Cmd!!"); + return NFCSTATUS_SUCCESS; + } + + if ((gphNxpNciHal_fw_IoctlCtx.bSkipSeq) == true) { + return NFCSTATUS_SUCCESS; + } else if (gphNxpNciHal_fw_IoctlCtx.bPrevSessnOpen == true) { + NXPLOG_FWDNLD_E( + "Previous Upload session is open..Cannot issue ChkIntegrity Cmd!!"); + return NFCSTATUS_SUCCESS; + } + + tDnldBuff.pBuff = bChkIntgRes; + tDnldBuff.wLen = sizeof(bChkIntgRes); + + if (phNxpNciHal_init_cb_data(&cb_data, NULL) != NFCSTATUS_SUCCESS) { + NXPLOG_FWDNLD_E( + "phNxpNciHal_fw_dnld_chk_integrity cb_data creation failed"); + return NFCSTATUS_FAILED; + } + + wStatus = phDnldNfc_CheckIntegrity( + (gphNxpNciHal_fw_IoctlCtx.bChipVer), &tDnldBuff, + &phNxpNciHal_fw_dnld_chk_integrity_cb, (void*)&cb_data); + if (wStatus != NFCSTATUS_PENDING) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_chk_integrity failed"); + wStatus = NFCSTATUS_FAILED; + goto clean_and_return; + } + + /* Wait for callback response */ + if (SEM_WAIT(cb_data)) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_chk_integrity semaphore error"); + wStatus = NFCSTATUS_FAILED; + goto clean_and_return; + } + + if (cb_data.status != NFCSTATUS_SUCCESS) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_chk_integrity cb failed"); + wStatus = NFCSTATUS_FAILED; + goto clean_and_return; + } + + wStatus = NFCSTATUS_SUCCESS; + +clean_and_return: + phNxpNciHal_cleanup_cb_data(&cb_data); + + return wStatus; +} + +/******************************************************************************* +** +** Function phNxpNciHal_fw_dnld_recover +** +** Description Download Recover +** +** Returns NFCSTATUS_SUCCESS if success +** +*******************************************************************************/ +static NFCSTATUS phNxpNciHal_fw_dnld_recover(void* pContext, NFCSTATUS status, + void* pInfo) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + phNxpNciHal_Sem_t cb_data; + + UNUSED(pInfo); + UNUSED(status); + UNUSED(pContext); + if ((gphNxpNciHal_fw_IoctlCtx.bDnldRecovery) == true) { + if (phNxpNciHal_init_cb_data(&cb_data, NULL) != NFCSTATUS_SUCCESS) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_recover cb_data creation failed"); + return NFCSTATUS_FAILED; + } + (gphNxpNciHal_fw_IoctlCtx.bDnldAttempts)++; + + /* resetting this flag to avoid cyclic issuance of recovery sequence in case + * of failure */ + (gphNxpNciHal_fw_IoctlCtx.bDnldRecovery) = false; + + wStatus = phDnldNfc_Write( + true, NULL, (pphDnldNfc_RspCb_t)&phNxpNciHal_fw_dnld_recover_cb, + (void*)&cb_data); + + if (NFCSTATUS_PENDING != wStatus) { + (gphNxpNciHal_fw_IoctlCtx.bSkipForce) = false; + (gphNxpNciHal_fw_IoctlCtx.bRetryDnld) = false; + goto clean_and_return; + } + /* Wait for callback response */ + if (SEM_WAIT(cb_data)) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_recover semaphore error"); + wStatus = NFCSTATUS_FAILED; + goto clean_and_return; + } + + if (cb_data.status != NFCSTATUS_SUCCESS) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_recover cb failed"); + wStatus = NFCSTATUS_FAILED; + goto clean_and_return; + } + wStatus = NFCSTATUS_SUCCESS; + + clean_and_return: + phNxpNciHal_cleanup_cb_data(&cb_data); + } + + return wStatus; +} + +/******************************************************************************* +** +** Function phNxpNciHal_fw_dnld_recover_cb +** +** Description Download Recover callback +** +** Returns None +** +*******************************************************************************/ +static void phNxpNciHal_fw_dnld_recover_cb(void* pContext, NFCSTATUS status, + void* pInfo) { + phNxpNciHal_Sem_t* p_cb_data = (phNxpNciHal_Sem_t*)pContext; + NFCSTATUS wStatus = status; + UNUSED(pContext); + UNUSED(pInfo); + + if (NFCSTATUS_SUCCESS == wStatus) { + if ((gphNxpNciHal_fw_IoctlCtx.bSkipForce) == false) { + NXPLOG_FWDNLD_D("phNxpNciHal_fw_dnld_recoverCb - Request Successful"); + (gphNxpNciHal_fw_IoctlCtx.bRetryDnld) = true; + } else { + NXPLOG_FWDNLD_D( + "phNxpNciHal_fw_dnld_recoverCb - Production key update Request " + "Successful"); + (gphNxpNciHal_fw_IoctlCtx.bSendNciCmd) = true; + } + } else { + wStatus = NFCSTATUS_FAILED; + NXPLOG_FWDNLD_D("phNxpNciHal_fw_dnld_recoverCb - Request Failed!!"); + } + + /* resetting this flag to avoid cyclic issuance of recovery sequence in case + * of failure */ + (gphNxpNciHal_fw_IoctlCtx.bDnldRecovery) = false; + + /* reset previously set SkipForce */ + (gphNxpNciHal_fw_IoctlCtx.bSkipForce) = false; + p_cb_data->status = wStatus; + + SEM_POST(p_cb_data); + + return; +} + +/******************************************************************************* +** +** Function phNxpNciHal_fw_dnld_send_ncicmd_cb +** +** Description Download Send NCI Command callback +** +** Returns None +** +*******************************************************************************/ +static void phNxpNciHal_fw_dnld_send_ncicmd_cb(void* pContext, NFCSTATUS status, + void* pInfo) { + phNxpNciHal_Sem_t* p_cb_data = (phNxpNciHal_Sem_t*)pContext; + NFCSTATUS wStatus = status; + pphDnldNfc_Buff_t pRespBuff; + UNUSED(pContext); + + if (NFCSTATUS_SUCCESS == wStatus) { + NXPLOG_FWDNLD_D("phNxpNciHal_fw_dnld_send_ncicmdCb - Request Successful"); + pRespBuff = (pphDnldNfc_Buff_t)pInfo; + + if ((0 != (pRespBuff->wLen)) && (NULL != (pRespBuff->pBuff))) { + if (0 == (pRespBuff->pBuff[3])) { + NXPLOG_FWDNLD_D("Successful Response received for Nci Reset Cmd"); + } else { + NXPLOG_FWDNLD_E("Nci Reset Request Failed!!"); + } + } else { + NXPLOG_FWDNLD_E("Invalid Response received for Nci Reset Request!!"); + } + /* Call Tml Ioctl to enable download mode */ + wStatus = phTmlNfc_IoCtl(phTmlNfc_e_EnableDownloadMode); + + if (NFCSTATUS_SUCCESS == wStatus) { + NXPLOG_FWDNLD_D("Switched Successfully to dnld mode.."); + (gphNxpNciHal_fw_IoctlCtx.bRetryDnld) = true; + } else { + NXPLOG_FWDNLD_E("Switching back to dnld mode Failed!!"); + (gphNxpNciHal_fw_IoctlCtx.bRetryDnld) = false; + wStatus = NFCSTATUS_FAILED; + } + } else { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_send_ncicmdCb - Request Failed!!"); + } + + (gphNxpNciHal_fw_IoctlCtx.bSendNciCmd) = false; + p_cb_data->status = wStatus; + + SEM_POST(p_cb_data); + + return; +} + +/******************************************************************************* +** +** Function phNxpNciHal_fw_dnld_send_ncicmd +** +** Description Download Send NCI Command +** +** Returns NFCSTATUS_SUCCESS if success +** +*******************************************************************************/ +static NFCSTATUS phNxpNciHal_fw_dnld_send_ncicmd(void* pContext, + NFCSTATUS status, + void* pInfo) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + static uint8_t bNciCmd[4] = {0x20, 0x00, 0x01, + 0x00}; /* Nci Reset Cmd with KeepConfig option */ + static uint8_t bNciResp[6]; + phDnldNfc_Buff_t tsData; + phDnldNfc_Buff_t trData; + phNxpNciHal_Sem_t cb_data; + + UNUSED(pInfo); + UNUSED(status); + UNUSED(pContext); + if ((gphNxpNciHal_fw_IoctlCtx.bSendNciCmd) == false) { + return NFCSTATUS_SUCCESS; + } else { + /* Call Tml Ioctl to enable/restore normal mode */ + wStatus = phTmlNfc_IoCtl(phTmlNfc_e_EnableNormalMode); + + if (NFCSTATUS_SUCCESS != wStatus) { + NXPLOG_FWDNLD_E("Switching to NormalMode Failed!!"); + (gphNxpNciHal_fw_IoctlCtx.bRetryDnld) = false; + (gphNxpNciHal_fw_IoctlCtx.bSendNciCmd) = false; + } else { + if (phNxpNciHal_init_cb_data(&cb_data, NULL) != NFCSTATUS_SUCCESS) { + NXPLOG_FWDNLD_E( + "phNxpNciHal_fw_dnld_send_ncicmd cb_data creation failed"); + return NFCSTATUS_FAILED; + } + (tsData.pBuff) = bNciCmd; + (tsData.wLen) = sizeof(bNciCmd); + (trData.pBuff) = bNciResp; + (trData.wLen) = sizeof(bNciResp); + + wStatus = phDnldNfc_RawReq( + &tsData, &trData, + (pphDnldNfc_RspCb_t)&phNxpNciHal_fw_dnld_send_ncicmd_cb, + (void*)&cb_data); + if (NFCSTATUS_PENDING != wStatus) { + goto clean_and_return; + } + /* Wait for callback response */ + if (SEM_WAIT(cb_data)) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_send_ncicmd semaphore error"); + wStatus = NFCSTATUS_FAILED; + goto clean_and_return; + } + + if (cb_data.status != NFCSTATUS_SUCCESS) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_send_ncicmd cb failed"); + wStatus = NFCSTATUS_FAILED; + goto clean_and_return; + } + wStatus = NFCSTATUS_SUCCESS; + + clean_and_return: + phNxpNciHal_cleanup_cb_data(&cb_data); + } + } + + return wStatus; +} + +/******************************************************************************* +** +** Function phNxpNciHal_fw_dnld_log_cb +** +** Description Download Log callback +** +** Returns None +** +*******************************************************************************/ +static void phNxpNciHal_fw_dnld_log_cb(void* pContext, NFCSTATUS status, + void* pInfo) { + phNxpNciHal_Sem_t* p_cb_data = (phNxpNciHal_Sem_t*)pContext; + NFCSTATUS wStatus = status; + UNUSED(pContext); + UNUSED(pInfo); + + if (NFCSTATUS_SUCCESS == wStatus) { + NXPLOG_FWDNLD_D("phLibNfc_DnldLogCb - Request Successful"); + (gphNxpNciHal_fw_IoctlCtx.bDnldInitiated) = false; + } else { + wStatus = NFCSTATUS_FAILED; + NXPLOG_FWDNLD_E("phLibNfc_DnldLogCb - Request Failed!!"); + } + p_cb_data->status = wStatus; + + SEM_POST(p_cb_data); + return; +} + +/******************************************************************************* +** +** Function phNxpNciHal_fw_dnld_log +** +** Description Download Log +** +** Returns NFCSTATUS_SUCCESS if success +** +*******************************************************************************/ +static NFCSTATUS phNxpNciHal_fw_dnld_log(void* pContext, NFCSTATUS status, + void* pInfo) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + phNxpNciHal_Sem_t cb_data; + phDnldNfc_Buff_t tData; + + UNUSED(pInfo); + UNUSED(status); + UNUSED(pContext); + if ((((gphNxpNciHal_fw_IoctlCtx.bSkipSeq) == true) || + ((gphNxpNciHal_fw_IoctlCtx.bForceDnld) == true)) && + ((gphNxpNciHal_fw_IoctlCtx.bDnldInitiated) == false)) { + return NFCSTATUS_SUCCESS; + } else { + if (phNxpNciHal_init_cb_data(&cb_data, NULL) != NFCSTATUS_SUCCESS) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_log cb_data creation failed"); + return NFCSTATUS_FAILED; + } + (tData.pBuff) = (void*)&(gphNxpNciHal_fw_IoctlCtx.tLogParams); + (tData.wLen) = sizeof(gphNxpNciHal_fw_IoctlCtx.tLogParams); + + wStatus = + phDnldNfc_Log(&tData, (pphDnldNfc_RspCb_t)&phNxpNciHal_fw_dnld_log_cb, + (void*)&cb_data); + + if (wStatus != NFCSTATUS_PENDING) { + NXPLOG_FWDNLD_E("phDnldNfc_Log failed"); + (gphNxpNciHal_fw_IoctlCtx.bDnldInitiated) = false; + wStatus = NFCSTATUS_FAILED; + goto clean_and_return; + } + /* Wait for callback response */ + if (SEM_WAIT(cb_data)) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_log semaphore error"); + wStatus = NFCSTATUS_FAILED; + goto clean_and_return; + } + + if (cb_data.status != NFCSTATUS_SUCCESS) { + NXPLOG_FWDNLD_E("phNxpNciHal_fw_dnld_log_cb failed"); + wStatus = NFCSTATUS_FAILED; + goto clean_and_return; + } + + wStatus = NFCSTATUS_SUCCESS; + + clean_and_return: + phNxpNciHal_cleanup_cb_data(&cb_data); + + return wStatus; + } +} + +/******************************************************************************* +** +** Function phNxpNciHal_fw_seq_handler +** +** Description Sequence Handler +** +** Returns NFCSTATUS_SUCCESS if sequence completed uninterrupted +** +*******************************************************************************/ +static NFCSTATUS phNxpNciHal_fw_seq_handler( + NFCSTATUS (*seq_handler[])(void* pContext, NFCSTATUS status, void* pInfo)) { + char* pContext = "FW-Download"; + int16_t seq_counter = 0; + phDnldNfc_Buff_t pInfo; + NFCSTATUS status = NFCSTATUS_FAILED; + + status = phTmlNfc_ReadAbort(); + if (NFCSTATUS_SUCCESS != status) { + NXPLOG_FWDNLD_E("Tml Read Abort failed!!"); + return status; + } + + while (seq_handler[seq_counter] != NULL) { + status = NFCSTATUS_FAILED; + status = (seq_handler[seq_counter])(pContext, status, &pInfo); + if (NFCSTATUS_SUCCESS != status) { + NXPLOG_FWDNLD_E(" phNxpNciHal_fw_seq_handler : FAILED"); + break; + } + seq_counter++; + } + return status; +} + +/******************************************************************************* +** +** Function phNxpNciHal_fw_dnld_complete +** +** Description Download Sequence Complete +** +** Returns NFCSTATUS_SUCCESS if success +** +*******************************************************************************/ +static NFCSTATUS phNxpNciHal_fw_dnld_complete(void* pContext, NFCSTATUS status, + void* pInfo) { + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + NFCSTATUS fStatus = status; + UNUSED(pInfo); + UNUSED(pContext); + + if (NFCSTATUS_WRITE_FAILED == status) { + if ((gphNxpNciHal_fw_IoctlCtx.bDnldAttempts) < + PHLIBNFC_IOCTL_DNLD_MAX_ATTEMPTS) { + (gphNxpNciHal_fw_IoctlCtx.bDnldRecovery) = true; + } else { + NXPLOG_FWDNLD_E("Max Dnld Retry Counts Exceeded!!"); + (gphNxpNciHal_fw_IoctlCtx.bDnldRecovery) = false; + (gphNxpNciHal_fw_IoctlCtx.bRetryDnld) = false; + } + } else if (NFCSTATUS_REJECTED == status) { + if ((gphNxpNciHal_fw_IoctlCtx.bDnldAttempts) < + PHLIBNFC_IOCTL_DNLD_MAX_ATTEMPTS) { + (gphNxpNciHal_fw_IoctlCtx.bDnldRecovery) = true; + + /* in case of signature error we need to try recover sequence directly + * bypassing the force cmd */ + (gphNxpNciHal_fw_IoctlCtx.bSkipForce) = true; + } else { + NXPLOG_FWDNLD_E("Max Dnld Retry Counts Exceeded!!"); + (gphNxpNciHal_fw_IoctlCtx.bDnldRecovery) = false; + (gphNxpNciHal_fw_IoctlCtx.bRetryDnld) = false; + } + } + + if ((gphNxpNciHal_fw_IoctlCtx.bDnldInitiated) == true) { + (gphNxpNciHal_fw_IoctlCtx.bLastStatus) = status; + (gphNxpNciHal_fw_IoctlCtx.bDnldAttemptFailed) = true; + + NXPLOG_FWDNLD_E("Invoking Pending Download Log Sequence.."); + (gphNxpNciHal_fw_IoctlCtx.bDnldInitiated) = false; + /* Perform the Logging sequence */ + wStatus = phNxpNciHal_fw_seq_handler(phNxpNciHal_dwnld_log_seqhandler); + if (NFCSTATUS_SUCCESS != gphNxpNciHal_fw_IoctlCtx.bLastStatus) { + /* update the previous Download Write status to upper layer and not the + * status of Log command */ + wStatus = gphNxpNciHal_fw_IoctlCtx.bLastStatus; + NXPLOG_FWDNLD_E( + "phNxpNciHal_fw_dnld_complete: Last Download Write Status before Log " + "command bLastStatus = 0x%x", + gphNxpNciHal_fw_IoctlCtx.bLastStatus); + } + status = phNxpNciHal_fw_dnld_complete(pContext, wStatus, &pInfo); + if (NFCSTATUS_SUCCESS == status) { + NXPLOG_FWDNLD_D(" phNxpNciHal_fw_dnld_complete : SUCCESS"); + } else { + NXPLOG_FWDNLD_E(" phNxpNciHal_fw_dnld_complete : FAILED"); + } + } else if ((gphNxpNciHal_fw_IoctlCtx.bDnldRecovery) == true) { + NXPLOG_FWDNLD_E("Invoking Download Recovery Sequence.."); + + if (NFCSTATUS_SUCCESS == wStatus) { + /* Perform the download Recovery sequence */ + wStatus = phNxpNciHal_fw_seq_handler(phNxpNciHal_dwnld_rec_seqhandler); + + status = phNxpNciHal_fw_dnld_complete(pContext, wStatus, &pInfo); + if (NFCSTATUS_SUCCESS == status) { + NXPLOG_FWDNLD_D(" phNxpNciHal_fw_dnld_complete : SUCCESS"); + } else { + NXPLOG_FWDNLD_E(" phNxpNciHal_fw_dnld_complete : FAILED"); + } + } + } else if ((gphNxpNciHal_fw_IoctlCtx.bRetryDnld) == true) { + (gphNxpNciHal_fw_IoctlCtx.bPrevSessnOpen) = false; + (gphNxpNciHal_fw_IoctlCtx.bDnldInitiated) = false; + (gphNxpNciHal_fw_IoctlCtx.bForceDnld) = false; + (gphNxpNciHal_fw_IoctlCtx.bSkipSeq) = false; + (gphNxpNciHal_fw_IoctlCtx.bSkipForce) = false; + (gphNxpNciHal_fw_IoctlCtx.bDnldRecovery) = false; + (gphNxpNciHal_fw_IoctlCtx.bSendNciCmd) = false; + + /* Perform the download sequence ... after successful recover attempt */ + wStatus = phNxpNciHal_fw_seq_handler(phNxpNciHal_dwnld_seqhandler); + + status = phNxpNciHal_fw_dnld_complete(pContext, wStatus, &pInfo); + if (NFCSTATUS_SUCCESS == status) { + NXPLOG_FWDNLD_D(" phNxpNciHal_fw_dnld_complete : SUCCESS"); + } else { + NXPLOG_FWDNLD_E(" phNxpNciHal_fw_dnld_complete : FAILED"); + } + } else { + NXPLOG_FWDNLD_D("phNxpNciHal_fw_dnld_complete: Download Status = 0x%x", + status); + if ((gphNxpNciHal_fw_IoctlCtx.bSkipSeq) == false) { + if (NFCSTATUS_SUCCESS == status) { + if (NFC_FW_DOWNLOAD == gphNxpNciHal_fw_IoctlCtx.IoctlCode) { + NXPLOG_FWDNLD_E("Fw Download success.. "); + } else if (PHLIBNFC_DNLD_MEM_READ == + gphNxpNciHal_fw_IoctlCtx.IoctlCode) { + NXPLOG_FWDNLD_E("Read Request success.. "); + } else if (PHLIBNFC_DNLD_MEM_WRITE == + gphNxpNciHal_fw_IoctlCtx.IoctlCode) { + NXPLOG_FWDNLD_E("Write Request success.. "); + } else if (PHLIBNFC_DNLD_READ_LOG == + gphNxpNciHal_fw_IoctlCtx.IoctlCode) { + NXPLOG_FWDNLD_E("ReadLog Request success.. "); + } else { + NXPLOG_FWDNLD_E("Invalid Request!!"); + } + } else { + if (NFC_FW_DOWNLOAD == gphNxpNciHal_fw_IoctlCtx.IoctlCode) { + NXPLOG_FWDNLD_E("Fw Download Failed!!"); + } else if (NFC_MEM_READ == gphNxpNciHal_fw_IoctlCtx.IoctlCode) { + NXPLOG_FWDNLD_E("Read Request Failed!!"); + } else if (NFC_MEM_WRITE == gphNxpNciHal_fw_IoctlCtx.IoctlCode) { + NXPLOG_FWDNLD_E("Write Request Failed!!"); + } else if (PHLIBNFC_DNLD_READ_LOG == + gphNxpNciHal_fw_IoctlCtx.IoctlCode) { + NXPLOG_FWDNLD_E("ReadLog Request Failed!!"); + } else { + NXPLOG_FWDNLD_E("Invalid Request!!"); + } + } + } + + if (gphNxpNciHal_fw_IoctlCtx.bSendNciCmd == false) { + /* Call Tml Ioctl to enable/restore normal mode */ + wStatus = phTmlNfc_IoCtl(phTmlNfc_e_EnableNormalMode); + + if (NFCSTATUS_SUCCESS != wStatus) { + NXPLOG_FWDNLD_E("Switching to NormalMode Failed!!"); + } else { + wStatus = fStatus; + } + } + + (gphNxpNciHal_fw_IoctlCtx.bPrevSessnOpen) = false; + (gphNxpNciHal_fw_IoctlCtx.bDnldInitiated) = false; + (gphNxpNciHal_fw_IoctlCtx.bChipVer) = 0; + (gphNxpNciHal_fw_IoctlCtx.bSkipSeq) = false; + (gphNxpNciHal_fw_IoctlCtx.bForceDnld) = false; + (gphNxpNciHal_fw_IoctlCtx.bDnldRecovery) = false; + (gphNxpNciHal_fw_IoctlCtx.bRetryDnld) = false; + (gphNxpNciHal_fw_IoctlCtx.bSkipReset) = false; + (gphNxpNciHal_fw_IoctlCtx.bSkipForce) = false; + (gphNxpNciHal_fw_IoctlCtx.bSendNciCmd) = false; + (gphNxpNciHal_fw_IoctlCtx.bDnldAttempts) = 0; + + if (gphNxpNciHal_fw_IoctlCtx.bDnldAttemptFailed == false) { + } else { + NXPLOG_FWDNLD_E("Returning Download Failed Status to Caller!!"); + + (gphNxpNciHal_fw_IoctlCtx.bLastStatus) = NFCSTATUS_SUCCESS; + (gphNxpNciHal_fw_IoctlCtx.bDnldAttemptFailed) = false; + } + phDnldNfc_CloseFwLibHandle(); + } + + return wStatus; +} + +/******************************************************************************* +** +** Function phNxpNciHal_fw_download_seq +** +** Description Download Sequence +** +** Returns NFCSTATUS_SUCCESS if success +** +*******************************************************************************/ +NFCSTATUS phNxpNciHal_fw_download_seq(uint8_t bClkSrcVal, uint8_t bClkFreqVal) { + NFCSTATUS status = NFCSTATUS_FAILED; + phDnldNfc_Buff_t pInfo; + char* pContext = "FW-Download"; + + /* reset the global flags */ + gphNxpNciHal_fw_IoctlCtx.IoctlCode = NFC_FW_DOWNLOAD; + (gphNxpNciHal_fw_IoctlCtx.bPrevSessnOpen) = false; + (gphNxpNciHal_fw_IoctlCtx.bDnldInitiated) = false; + (gphNxpNciHal_fw_IoctlCtx.bChipVer) = 0; + (gphNxpNciHal_fw_IoctlCtx.bSkipSeq) = false; + (gphNxpNciHal_fw_IoctlCtx.bForceDnld) = false; + (gphNxpNciHal_fw_IoctlCtx.bDnldRecovery) = false; + (gphNxpNciHal_fw_IoctlCtx.bRetryDnld) = false; + (gphNxpNciHal_fw_IoctlCtx.bSkipReset) = false; + (gphNxpNciHal_fw_IoctlCtx.bSkipForce) = false; + (gphNxpNciHal_fw_IoctlCtx.bSendNciCmd) = false; + (gphNxpNciHal_fw_IoctlCtx.bDnldAttempts) = 0; + (gphNxpNciHal_fw_IoctlCtx.bClkSrcVal) = bClkSrcVal; + (gphNxpNciHal_fw_IoctlCtx.bClkFreqVal) = bClkFreqVal; + /* Get firmware version */ + if (NFCSTATUS_SUCCESS == phDnldNfc_InitImgInfo()) { + NXPLOG_FWDNLD_D("phDnldNfc_InitImgInfo:SUCCESS"); +#if (NFC_NXP_CHIP_TYPE != PN547C2) + if (gRecFWDwnld == true) { + status = + phNxpNciHal_fw_seq_handler(phNxpNciHal_dummy_rec_dwnld_seqhandler); + } else +#endif + { + status = phNxpNciHal_fw_seq_handler(phNxpNciHal_dwnld_seqhandler); + } + } else { + NXPLOG_FWDNLD_E("phDnldNfc_InitImgInfo: FAILED"); + } + + /* Chage to normal mode */ + status = phNxpNciHal_fw_dnld_complete(pContext, status, &pInfo); + /*if (NFCSTATUS_SUCCESS == status) + { + NXPLOG_FWDNLD_D(" phNxpNciHal_fw_dnld_complete : SUCCESS"); + } + else + { + NXPLOG_FWDNLD_E(" phNxpNciHal_fw_dnld_complete : FAILED"); + }*/ + + return status; +} + +static NFCSTATUS phLibNfc_VerifyCrcStatus(uint8_t bCrcStatus) { +#if ((NFC_NXP_CHIP_TYPE == PN551) || (NFC_NXP_CHIP_TYPE == PN553)) + uint8_t bBitPos = 1; + uint8_t bShiftVal = 2; +#else + uint8_t bBitPos = 0; + uint8_t bShiftVal = 1; +#endif + NFCSTATUS wStatus = NFCSTATUS_SUCCESS; + while (bBitPos < 7) { + if (!(bCrcStatus & bShiftVal)) { + switch (bBitPos) { + case 0: { + NXPLOG_FWDNLD_E("User Data Crc is NOT OK!!"); + wStatus = NFCSTATUS_FAILED; + break; + } + case 1: { + NXPLOG_FWDNLD_E("Trim Data Crc is NOT OK!!"); + wStatus = NFCSTATUS_FAILED; + break; + } + case 2: { + NXPLOG_FWDNLD_E("Protected Data Crc is NOT OK!!"); + wStatus = NFCSTATUS_FAILED; + break; + } + case 3: { + NXPLOG_FWDNLD_E("Patch Code Crc is NOT OK!!"); + wStatus = NFCSTATUS_FAILED; + break; + } + case 4: { + NXPLOG_FWDNLD_E("Function Code Crc is NOT OK!!"); + wStatus = NFCSTATUS_FAILED; + break; + } + case 5: { + NXPLOG_FWDNLD_E("Patch Table Crc is NOT OK!!"); + wStatus = NFCSTATUS_FAILED; + break; + } + case 6: { + NXPLOG_FWDNLD_E("Function Table Crc is NOT OK!!"); + wStatus = NFCSTATUS_FAILED; + break; + } + default: { break; } + } + } + + bShiftVal <<= 1; + ++bBitPos; + } + + return wStatus; +} diff --git a/pn54x/dnld/phNxpNciHal_Dnld.h b/pn54x/dnld/phNxpNciHal_Dnld.h new file mode 100644 index 0000000..d32fead --- /dev/null +++ b/pn54x/dnld/phNxpNciHal_Dnld.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2012-2014 NXP Semiconductors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef _PHNXPNCIHAL_DNLD_H_ +#define _PHNXPNCIHAL_DNLD_H_ + +#include <phNfcStatus.h> +#include <phNfcTypes.h> + +NFCSTATUS phNxpNciHal_fw_download_seq(uint8_t bClkSrcVal, uint8_t bClkFreqVal); + +#endif /* _PHNXPNCIHAL_DNLD_H_ */ |