/* * 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 <phTmlNfc.h> #include <phDnldNfc.h> #include <phNxpNciHal_Dnld.h> #include <phNxpNciHal_utils.h> #include <phNxpLog.h> #include <phNxpConfig.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((TRUE == (gphNxpNciHal_fw_IoctlCtx.bSkipSeq)) || (TRUE == (gphNxpNciHal_fw_IoctlCtx.bSkipReset))) { if(TRUE == (gphNxpNciHal_fw_IoctlCtx.bSkipReset)) { (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(TRUE == (gphNxpNciHal_fw_IoctlCtx.bSkipForce)) { 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(TRUE == (gphNxpNciHal_fw_IoctlCtx.bDnldRecovery)) { (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(TRUE == (gphNxpNciHal_fw_IoctlCtx.bSkipForce)) { 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(TRUE == (gphNxpNciHal_fw_IoctlCtx.bDnldRecovery)) { (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) #endif ) { bExpectedLen = PHLIBNFC_IOCTL_DNLD_GETVERLEN_MRA2_1; (gphNxpNciHal_fw_IoctlCtx.bChipVer) = bHwVer; } 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"); 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((TRUE == (gphNxpNciHal_fw_IoctlCtx.bSkipSeq)) || (TRUE == (gphNxpNciHal_fw_IoctlCtx.bPrevSessnOpen))) { 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(TRUE == (gphNxpNciHal_fw_IoctlCtx.bDnldInitiated)) { 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 (TRUE == gphNxpNciHal_fw_IoctlCtx.bSkipSeq) { 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((((TRUE == (gphNxpNciHal_fw_IoctlCtx.bSkipSeq)) || (TRUE == (gphNxpNciHal_fw_IoctlCtx.bForceDnld))) && (FALSE == (gphNxpNciHal_fw_IoctlCtx.bPrevSessnOpen))) || (((TRUE == (gphNxpNciHal_fw_IoctlCtx.bPrevSessnOpen))) && (TRUE == (gphNxpNciHal_fw_IoctlCtx.bRetryDnld)))) { 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(TRUE == (gphNxpNciHal_fw_IoctlCtx.bDnldInitiated)) { (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(FALSE == (gphNxpNciHal_fw_IoctlCtx.tLogParams.bConfig)) { 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(TRUE == (gphNxpNciHal_fw_IoctlCtx.bDnldAttemptFailed)) { (gphNxpNciHal_fw_IoctlCtx.bDnldAttemptFailed) = FALSE; } } else { if(TRUE == (gphNxpNciHal_fw_IoctlCtx.bDnldInitiated)) { (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(TRUE == (gphNxpNciHal_fw_IoctlCtx.bRetryDnld)) { (gphNxpNciHal_fw_IoctlCtx.bRetryDnld) = FALSE; } if((TRUE == (gphNxpNciHal_fw_IoctlCtx.bSkipSeq)) && (FALSE == (gphNxpNciHal_fw_IoctlCtx.bPrevSessnOpen))) { 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(FALSE == (gphNxpNciHal_fw_IoctlCtx.bForceDnld)) { 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(FALSE == (gphNxpNciHal_fw_IoctlCtx.bForceDnld)) { 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(TRUE == gphNxpNciHal_fw_IoctlCtx.bPrevSessnOpen) { NXPLOG_FWDNLD_D("Previous Upload session is open..Cannot issue ChkIntegrity Cmd!!"); return NFCSTATUS_SUCCESS; } if(TRUE == (gphNxpNciHal_fw_IoctlCtx.bSkipSeq)) { return NFCSTATUS_SUCCESS; } else if(TRUE == gphNxpNciHal_fw_IoctlCtx.bPrevSessnOpen) { 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(TRUE == (gphNxpNciHal_fw_IoctlCtx.bDnldRecovery)) { 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(FALSE == (gphNxpNciHal_fw_IoctlCtx.bSkipForce)) { 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(FALSE == (gphNxpNciHal_fw_IoctlCtx.bSendNciCmd)) { 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(((TRUE == (gphNxpNciHal_fw_IoctlCtx.bSkipSeq)) || (TRUE == (gphNxpNciHal_fw_IoctlCtx.bForceDnld))) && (FALSE == (gphNxpNciHal_fw_IoctlCtx.bDnldInitiated))) { 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(TRUE == (gphNxpNciHal_fw_IoctlCtx.bDnldInitiated)) { (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(TRUE == (gphNxpNciHal_fw_IoctlCtx.bDnldRecovery)) { 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(TRUE == (gphNxpNciHal_fw_IoctlCtx.bRetryDnld)) { (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(FALSE == (gphNxpNciHal_fw_IoctlCtx.bSkipSeq)) { 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(FALSE == gphNxpNciHal_fw_IoctlCtx.bSendNciCmd) { /* 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(FALSE == gphNxpNciHal_fw_IoctlCtx.bDnldAttemptFailed) { } 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) 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; }