aboutsummaryrefslogtreecommitdiff
path: root/pn54x/dnld/phDnldNfc_Internal.c
diff options
context:
space:
mode:
Diffstat (limited to 'pn54x/dnld/phDnldNfc_Internal.c')
-rw-r--r--pn54x/dnld/phDnldNfc_Internal.c1215
1 files changed, 1215 insertions, 0 deletions
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;
+}