aboutsummaryrefslogtreecommitdiff
path: root/pn54x/dnld
diff options
context:
space:
mode:
Diffstat (limited to 'pn54x/dnld')
-rw-r--r--pn54x/dnld/phDnldNfc.c1294
-rw-r--r--pn54x/dnld/phDnldNfc.h141
-rw-r--r--pn54x/dnld/phDnldNfc_Cmd.h41
-rw-r--r--pn54x/dnld/phDnldNfc_Internal.c1215
-rw-r--r--pn54x/dnld/phDnldNfc_Internal.h209
-rw-r--r--pn54x/dnld/phDnldNfc_Status.h68
-rw-r--r--pn54x/dnld/phDnldNfc_Utils.c87
-rw-r--r--pn54x/dnld/phDnldNfc_Utils.h27
-rw-r--r--pn54x/dnld/phNxpNciHal_Dnld.c1808
-rw-r--r--pn54x/dnld/phNxpNciHal_Dnld.h24
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_ */