blob: 2a66af11951356ac11aff91931459dbceb55e48b [file] [log] [blame]
/*
* 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;
}