Home | History | Annotate | Download | only in dnld
      1 /*
      2  * Copyright (C) 2010-2014 NXP Semiconductors
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /*
     18  * Internal Download Management routines
     19  * Download Component
     20  */
     21 
     22 #include <phDnldNfc_Internal.h>
     23 #include <phDnldNfc_Utils.h>
     24 #include <phNxpLog.h>
     25 #include <phNxpNciHal_utils.h>
     26 #include <phTmlNfc.h>
     27 
     28 /* Minimum length of payload including 1 byte CmdId */
     29 #define PHDNLDNFC_MIN_PLD_LEN (0x04U)
     30 
     31 /* Offset of Length byte within the frame */
     32 #define PHDNLDNFC_FRAME_HDR_OFFSET (0x00)
     33 /* Offset of FrameId within the frame */
     34 #define PHDNLDNFC_FRAMEID_OFFSET (PHDNLDNFC_FRAME_HDR_LEN)
     35 /* Offset of status byte within the frame */
     36 #define PHDNLDNFC_FRAMESTATUS_OFFSET PHDNLDNFC_FRAMEID_OFFSET
     37 /* Offset within frame where payload starts*/
     38 #define PHDNLDNFC_PLD_OFFSET (PHDNLDNFC_MIN_PLD_LEN - 1)
     39 
     40 #define PHDNLDNFC_FRAME_RDDATA_OFFSET \
     41   ((PHDNLDNFC_FRAME_HDR_LEN) +        \
     42    (PHDNLDNFC_MIN_PLD_LEN)) /* recvd frame offset where data starts */
     43 
     44 /* Size of first secure write frame Signature */
     45 #define PHDNLDNFC_FRAME_SIGNATURE_SIZE (0xC0U)
     46 /* Size of first secure write frame payload */
     47 #define PHDNLDNFC_FIRST_FRAME_PLD_SIZE (0xE4U)
     48 
     49 /* Status response for first fragmented write frame */
     50 #define PHDNLDNFC_FIRST_FRAGFRAME_RESP (0x2DU)
     51 /* Status response for subsequent fragmented write frame */
     52 #define PHDNLDNFC_NEXT_FRAGFRAME_RESP (0x2EU)
     53 
     54 #define PHDNLDNFC_SET_HDR_FRAGBIT(n) \
     55   ((n) | (1 << 10)) /* Header chunk bit set macro */
     56 #define PHDNLDNFC_CLR_HDR_FRAGBIT(n) \
     57   ((n) & ~(1U << 10)) /* Header chunk bit clear macro */
     58 #define PHDNLDNFC_CHK_HDR_FRAGBIT(n) \
     59   ((n)&0x04) /* macro to check if frag bit is set in Hdr */
     60 
     61 /* Timeout value to wait for response from NFCC */
     62 #define PHDNLDNFC_RSP_TIMEOUT (2500)
     63 /* Timeout value to wait before resending the last frame */
     64 #define PHDNLDNFC_RETRY_FRAME_WRITE (50)
     65 
     66 /* size of EEPROM user data length */
     67 #define PHDNLDNFC_USERDATA_EEPROM_LENSIZE (0x02U)
     68 /* size of EEPROM offset */
     69 #define PHDNLDNFC_USERDATA_EEPROM_OFFSIZE (0x02U)
     70 
     71 #ifdef NXP_PN547C1_DOWNLOAD
     72 /* EEPROM offset and length value for PN547C1 */
     73 /* 16 bits offset indicating user data area start location */
     74 #define PHDNLDNFC_USERDATA_EEPROM_OFFSET (0x003CU)
     75 /* 16 bits length of user data area */
     76 #define PHDNLDNFC_USERDATA_EEPROM_LEN (0x0DC0U)
     77 #else
     78 
     79 #if (NFC_NXP_CHIP_TYPE == PN548C2)
     80 /* EEPROM offset and length value for PN548AD */
     81 /* 16 bits offset indicating user data area start location */
     82 #define PHDNLDNFC_USERDATA_EEPROM_OFFSET (0x02BCU)
     83 /* 16 bits length of user data area */
     84 #define PHDNLDNFC_USERDATA_EEPROM_LEN (0x0C00U)
     85 #elif (NFC_NXP_CHIP_TYPE == PN551)
     86 /* EEPROM offset and length value for PN551 */
     87 /* 16 bits offset indicating user data area start location */
     88 #define PHDNLDNFC_USERDATA_EEPROM_OFFSET (0x02BCU)
     89 /* 16 bits length of user data area */
     90 #define PHDNLDNFC_USERDATA_EEPROM_LEN (0x0C00U)
     91 #else
     92 /* EEPROM offset and length value for PN547C2 */
     93 /* 16 bits offset indicating user data area start location */
     94 #define PHDNLDNFC_USERDATA_EEPROM_OFFSET (0x023CU)
     95 /* 16 bits length of user data area */
     96 #define PHDNLDNFC_USERDATA_EEPROM_LEN (0x0C80U)
     97 #endif
     98 
     99 #endif
    100 #define PH_LIBNFC_VEN_RESET_ON_DOWNLOAD_TIMEOUT (1)
    101 
    102 /* Function prototype declarations */
    103 static void phDnldNfc_ProcessSeqState(void* pContext,
    104                                       phTmlNfc_TransactInfo_t* pInfo);
    105 static void phDnldNfc_ProcessRWSeqState(void* pContext,
    106                                         phTmlNfc_TransactInfo_t* pInfo);
    107 static NFCSTATUS phDnldNfc_ProcessFrame(void* pContext,
    108                                         phTmlNfc_TransactInfo_t* pInfo);
    109 static NFCSTATUS phDnldNfc_ProcessRecvInfo(void* pContext,
    110                                            phTmlNfc_TransactInfo_t* pInfo);
    111 static NFCSTATUS phDnldNfc_BuildFramePkt(pphDnldNfc_DlContext_t pDlContext);
    112 static NFCSTATUS phDnldNfc_CreateFramePld(pphDnldNfc_DlContext_t pDlContext);
    113 static NFCSTATUS phDnldNfc_SetupResendTimer(pphDnldNfc_DlContext_t pDlContext);
    114 static NFCSTATUS phDnldNfc_UpdateRsp(pphDnldNfc_DlContext_t pDlContext,
    115                                      phTmlNfc_TransactInfo_t* pInfo,
    116                                      uint16_t wPldLen);
    117 static void phDnldNfc_RspTimeOutCb(uint32_t TimerId, void* pContext);
    118 static void phDnldNfc_ResendTimeOutCb(uint32_t TimerId, void* pContext);
    119 
    120 /*
    121 *************************** Function Definitions ***************************
    122 */
    123 
    124 /*******************************************************************************
    125 **
    126 ** Function         phDnldNfc_CmdHandler
    127 **
    128 ** Description      Download Command Handler Mechanism
    129 **                  - holds the sub states for each command processing
    130 **                  - coordinates with TML download thread to complete a
    131 **                    download command request
    132 **                  - calls the user callback on completion of a cmd
    133 **
    134 ** Parameters       pContext  - pointer to the download context structure
    135 **                  TrigEvent - event requested by user
    136 **
    137 ** Returns          NFC status:
    138 **                  NFCSTATUS_PENDING - download request sent to NFCC
    139 **                                      successfully,response pending
    140 **                  NFCSTATUS_BUSY - handler is busy processing a download
    141 **                                   request
    142 **                  NFCSTATUS_INVALID_PARAMETER - one or more of the supplied
    143 **                                                parameters could not be
    144 **                                                interpreted properly
    145 **                  Other errors
    146 **
    147 *******************************************************************************/
    148 NFCSTATUS phDnldNfc_CmdHandler(void* pContext, phDnldNfc_Event_t TrigEvent) {
    149   NFCSTATUS status = NFCSTATUS_SUCCESS;
    150   pphDnldNfc_DlContext_t pDlCtxt = (pphDnldNfc_DlContext_t)pContext;
    151 
    152   if (NULL == pDlCtxt) {
    153     NXPLOG_FWDNLD_E("Invalid Input Parameter!!");
    154     status = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER);
    155   } else {
    156     switch (TrigEvent) {
    157       case phDnldNfc_EventReset:
    158       case phDnldNfc_EventGetVer:
    159       case phDnldNfc_EventIntegChk:
    160       case phDnldNfc_EventGetSesnSt:
    161       case phDnldNfc_EventRaw: {
    162         if (phDnldNfc_EventInvalid == (pDlCtxt->tCurrEvent)) {
    163           NXPLOG_FWDNLD_D("Processing Normal Sequence..");
    164           pDlCtxt->tCurrEvent = TrigEvent;
    165           pDlCtxt->tDnldInProgress = phDnldNfc_TransitionBusy;
    166 
    167           phDnldNfc_ProcessSeqState(pDlCtxt, NULL);
    168 
    169           status = pDlCtxt->wCmdSendStatus;
    170         } else {
    171           NXPLOG_FWDNLD_E("Prev Norml Sequence not completed/restored!!");
    172           status = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED);
    173         }
    174         break;
    175       }
    176       case phDnldNfc_EventWrite:
    177       case phDnldNfc_EventRead:
    178       case phDnldNfc_EventLog:
    179       case phDnldNfc_EventForce: {
    180         if (phDnldNfc_EventInvalid == (pDlCtxt->tCurrEvent)) {
    181           NXPLOG_FWDNLD_D("Processing R/W Sequence..");
    182           pDlCtxt->tCurrEvent = TrigEvent;
    183           pDlCtxt->tDnldInProgress = phDnldNfc_TransitionBusy;
    184 
    185           phDnldNfc_ProcessRWSeqState(pDlCtxt, NULL);
    186 
    187           status = pDlCtxt->wCmdSendStatus;
    188         } else {
    189           NXPLOG_FWDNLD_E("Prev R/W Sequence not completed/restored!!");
    190           status = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED);
    191         }
    192         break;
    193       }
    194       default: {
    195         /* Unknown Event */
    196         NXPLOG_FWDNLD_E("Unknown Event Parameter!!");
    197         status = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER);
    198         break;
    199       }
    200     }
    201   }
    202 
    203   return status;
    204 }
    205 
    206 /*******************************************************************************
    207 **
    208 ** Function         phDnldNfc_ProcessSeqState
    209 **
    210 ** Description      Processes all cmd/resp sequences except read & write
    211 **
    212 ** Parameters       pContext - pointer to the download context structure
    213 **                  pInfo - pointer to the Transaction buffer updated by TML
    214 **                          Thread
    215 **
    216 ** Returns          None
    217 **
    218 *******************************************************************************/
    219 static void phDnldNfc_ProcessSeqState(void* pContext,
    220                                       phTmlNfc_TransactInfo_t* pInfo) {
    221   NFCSTATUS wStatus = NFCSTATUS_SUCCESS;
    222   NFCSTATUS wIntStatus;
    223   uint32_t TimerId;
    224   pphDnldNfc_DlContext_t pDlCtxt = (pphDnldNfc_DlContext_t)pContext;
    225 
    226   if (NULL == pDlCtxt) {
    227     NXPLOG_FWDNLD_E("Invalid Input Parameter!!");
    228     wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER);
    229   } else {
    230     switch (pDlCtxt->tCurrState) {
    231       case phDnldNfc_StateInit: {
    232         NXPLOG_FWDNLD_D("Initializing Sequence..");
    233 
    234         if (0 == (pDlCtxt->TimerInfo.dwRspTimerId)) {
    235           TimerId = phOsalNfc_Timer_Create();
    236 
    237           if (0 == TimerId) {
    238             NXPLOG_FWDNLD_W("Response Timer Create failed!!");
    239             wStatus = NFCSTATUS_INSUFFICIENT_RESOURCES;
    240             pDlCtxt->wCmdSendStatus = wStatus;
    241             break;
    242           } else {
    243             NXPLOG_FWDNLD_D("Response Timer Created Successfully");
    244             (pDlCtxt->TimerInfo.dwRspTimerId) = TimerId;
    245             (pDlCtxt->TimerInfo.TimerStatus) = 0;
    246             (pDlCtxt->TimerInfo.wTimerExpStatus) = 0;
    247           }
    248         }
    249         pDlCtxt->tCurrState = phDnldNfc_StateSend;
    250       }
    251       case phDnldNfc_StateSend: {
    252         wStatus = phDnldNfc_BuildFramePkt(pDlCtxt);
    253 
    254         if (NFCSTATUS_SUCCESS == wStatus) {
    255           pDlCtxt->tCurrState = phDnldNfc_StateRecv;
    256 
    257           wStatus = phTmlNfc_Write(
    258               (pDlCtxt->tCmdRspFrameInfo.aFrameBuff),
    259               (uint16_t)(pDlCtxt->tCmdRspFrameInfo.dwSendlength),
    260               (pphTmlNfc_TransactCompletionCb_t)&phDnldNfc_ProcessSeqState,
    261               pDlCtxt);
    262         }
    263         pDlCtxt->wCmdSendStatus = wStatus;
    264         break;
    265       }
    266       case phDnldNfc_StateRecv: {
    267         wStatus = phDnldNfc_ProcessRecvInfo(pContext, pInfo);
    268 
    269         if (NFCSTATUS_SUCCESS == wStatus) {
    270           wStatus = phOsalNfc_Timer_Start((pDlCtxt->TimerInfo.dwRspTimerId),
    271                                           PHDNLDNFC_RSP_TIMEOUT,
    272                                           &phDnldNfc_RspTimeOutCb, pDlCtxt);
    273 
    274           if (NFCSTATUS_SUCCESS == wStatus) {
    275             NXPLOG_FWDNLD_D("Response timer started");
    276             pDlCtxt->TimerInfo.TimerStatus = 1;
    277             pDlCtxt->tCurrState = phDnldNfc_StateTimer;
    278           } else {
    279             NXPLOG_FWDNLD_W("Response timer not started");
    280             pDlCtxt->tCurrState = phDnldNfc_StateResponse;
    281           }
    282           /* Call TML_Read function and register the call back function */
    283           wStatus = phTmlNfc_Read(
    284               pDlCtxt->tCmdRspFrameInfo.aFrameBuff,
    285               (uint16_t)PHDNLDNFC_CMDRESP_MAX_BUFF_SIZE,
    286               (pphTmlNfc_TransactCompletionCb_t)&phDnldNfc_ProcessSeqState,
    287               (void*)pDlCtxt);
    288 
    289           /* set read status to pDlCtxt->wCmdSendStatus to enable callback */
    290           pDlCtxt->wCmdSendStatus = wStatus;
    291           break;
    292         } else {
    293           /* Setting TimerExpStatus below to avoid frame processing in response
    294            * state */
    295           (pDlCtxt->TimerInfo.wTimerExpStatus) = NFCSTATUS_RF_TIMEOUT;
    296           pDlCtxt->tCurrState = phDnldNfc_StateResponse;
    297         }
    298       }
    299       case phDnldNfc_StateTimer: {
    300         if (1 == (pDlCtxt->TimerInfo.TimerStatus)) /*Is Timer Running*/
    301         {
    302           /*Stop Timer*/
    303           (void)phOsalNfc_Timer_Stop(pDlCtxt->TimerInfo.dwRspTimerId);
    304           (pDlCtxt->TimerInfo.TimerStatus) = 0; /*timer stopped*/
    305         }
    306         pDlCtxt->tCurrState = phDnldNfc_StateResponse;
    307       }
    308       case phDnldNfc_StateResponse: {
    309         if (NFCSTATUS_RF_TIMEOUT != (pDlCtxt->TimerInfo.wTimerExpStatus)) {
    310           /* Process response */
    311           wStatus = phDnldNfc_ProcessFrame(pContext, pInfo);
    312         } else {
    313           if (phDnldNfc_EventReset != pDlCtxt->tCurrEvent) {
    314             wStatus = (pDlCtxt->TimerInfo.wTimerExpStatus);
    315           } else {
    316             wStatus = NFCSTATUS_SUCCESS;
    317           }
    318           (pDlCtxt->TimerInfo.wTimerExpStatus) = 0;
    319         }
    320 
    321         /* Abort TML read operation which is always kept open */
    322         wIntStatus = phTmlNfc_ReadAbort();
    323 
    324         if (NFCSTATUS_SUCCESS != wIntStatus) {
    325           /* TODO:-Action to take in this case:-Tml read abort failed!? */
    326           NXPLOG_FWDNLD_W("Tml Read Abort failed!!");
    327         }
    328 
    329         pDlCtxt->tCurrEvent = phDnldNfc_EventInvalid;
    330         pDlCtxt->tDnldInProgress = phDnldNfc_TransitionIdle;
    331         pDlCtxt->tCurrState = phDnldNfc_StateInit;
    332 
    333         /* Delete the timer & reset timer primitives in context */
    334         (void)phOsalNfc_Timer_Delete(pDlCtxt->TimerInfo.dwRspTimerId);
    335         (pDlCtxt->TimerInfo.dwRspTimerId) = 0;
    336         (pDlCtxt->TimerInfo.TimerStatus) = 0;
    337         (pDlCtxt->TimerInfo.wTimerExpStatus) = 0;
    338 
    339         if ((NULL != (pDlCtxt->UserCb)) && (NULL != (pDlCtxt->UserCtxt))) {
    340           pDlCtxt->UserCb((pDlCtxt->UserCtxt), wStatus,
    341                           &(pDlCtxt->tRspBuffInfo));
    342         }
    343         break;
    344       }
    345       default: {
    346         pDlCtxt->tCurrEvent = phDnldNfc_EventInvalid;
    347         pDlCtxt->tDnldInProgress = phDnldNfc_TransitionIdle;
    348         break;
    349       }
    350     }
    351   }
    352 
    353   return;
    354 }
    355 
    356 /*******************************************************************************
    357 **
    358 ** Function         phDnldNfc_ProcessRWSeqState
    359 **
    360 ** Description      Processes read/write cmd/rsp sequence
    361 **
    362 ** Parameters       pContext - pointer to the download context structure
    363 **                  pInfo - pointer to the Transaction buffer updated by TML
    364 **                             Thread
    365 **
    366 ** Returns          None
    367 **
    368 *******************************************************************************/
    369 static void phDnldNfc_ProcessRWSeqState(void* pContext,
    370                                         phTmlNfc_TransactInfo_t* pInfo) {
    371   NFCSTATUS wStatus = NFCSTATUS_SUCCESS;
    372   NFCSTATUS wIntStatus = wStatus;
    373   uint32_t TimerId;
    374   pphDnldNfc_DlContext_t pDlCtxt = (pphDnldNfc_DlContext_t)pContext;
    375 
    376   if (NULL == pDlCtxt) {
    377     NXPLOG_FWDNLD_E("Invalid Input Parameter!!");
    378     wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER);
    379   } else {
    380     switch (pDlCtxt->tCurrState) {
    381       case phDnldNfc_StateInit: {
    382         if (0 == (pDlCtxt->TimerInfo.dwRspTimerId)) {
    383           TimerId = phOsalNfc_Timer_Create();
    384 
    385           if (0 == TimerId) {
    386             NXPLOG_FWDNLD_E("Response Timer Create failed!!");
    387             wStatus = NFCSTATUS_INSUFFICIENT_RESOURCES;
    388           } else {
    389             NXPLOG_FWDNLD_D("Response Timer Created Successfully");
    390             (pDlCtxt->TimerInfo.dwRspTimerId) = TimerId;
    391             (pDlCtxt->TimerInfo.TimerStatus) = 0;
    392             (pDlCtxt->TimerInfo.wTimerExpStatus) = 0;
    393           }
    394         }
    395         pDlCtxt->tCurrState = phDnldNfc_StateSend;
    396       }
    397       case phDnldNfc_StateSend: {
    398         if (pDlCtxt->bResendLastFrame == false) {
    399           wStatus = phDnldNfc_BuildFramePkt(pDlCtxt);
    400         } else {
    401           pDlCtxt->bResendLastFrame = false;
    402         }
    403 
    404         if (NFCSTATUS_SUCCESS == wStatus) {
    405           pDlCtxt->tCurrState = phDnldNfc_StateRecv;
    406 
    407           wStatus = phTmlNfc_Write(
    408               (pDlCtxt->tCmdRspFrameInfo.aFrameBuff),
    409               (uint16_t)(pDlCtxt->tCmdRspFrameInfo.dwSendlength),
    410               (pphTmlNfc_TransactCompletionCb_t)&phDnldNfc_ProcessRWSeqState,
    411               pDlCtxt);
    412         }
    413         pDlCtxt->wCmdSendStatus = wStatus;
    414         break;
    415       }
    416       case phDnldNfc_StateRecv: {
    417         wStatus = phDnldNfc_ProcessRecvInfo(pContext, pInfo);
    418 
    419         if (NFCSTATUS_SUCCESS == wStatus) {
    420           /* processing For Pipelined write before calling timer below */
    421           wStatus = phOsalNfc_Timer_Start((pDlCtxt->TimerInfo.dwRspTimerId),
    422                                           PHDNLDNFC_RSP_TIMEOUT,
    423                                           &phDnldNfc_RspTimeOutCb, pDlCtxt);
    424 
    425           if (NFCSTATUS_SUCCESS == wStatus) {
    426             NXPLOG_FWDNLD_D("Response timer started");
    427             pDlCtxt->TimerInfo.TimerStatus = 1;
    428             pDlCtxt->tCurrState = phDnldNfc_StateTimer;
    429           } else {
    430             NXPLOG_FWDNLD_W("Response timer not started");
    431             pDlCtxt->tCurrState = phDnldNfc_StateResponse;
    432             /* Todo:- diagnostic in this case */
    433           }
    434           /* Call TML_Read function and register the call back function */
    435           wStatus = phTmlNfc_Read(
    436               pDlCtxt->tCmdRspFrameInfo.aFrameBuff,
    437               (uint16_t)PHDNLDNFC_CMDRESP_MAX_BUFF_SIZE,
    438               (pphTmlNfc_TransactCompletionCb_t)&phDnldNfc_ProcessRWSeqState,
    439               (void*)pDlCtxt);
    440 
    441           /* set read status to pDlCtxt->wCmdSendStatus to enable callback */
    442           pDlCtxt->wCmdSendStatus = wStatus;
    443           break;
    444         } else {
    445           /* Setting TimerExpStatus below to avoid frame processing in reponse
    446            * state */
    447           (pDlCtxt->TimerInfo.wTimerExpStatus) = NFCSTATUS_RF_TIMEOUT;
    448           pDlCtxt->tCurrState = phDnldNfc_StateResponse;
    449         }
    450       }
    451       case phDnldNfc_StateTimer: {
    452         if (1 == (pDlCtxt->TimerInfo.TimerStatus)) /*Is Timer Running*/
    453         {
    454           /* Stop Timer */
    455           (void)phOsalNfc_Timer_Stop(pDlCtxt->TimerInfo.dwRspTimerId);
    456           (pDlCtxt->TimerInfo.TimerStatus) = 0; /*timer stopped*/
    457         }
    458         pDlCtxt->tCurrState = phDnldNfc_StateResponse;
    459       }
    460       case phDnldNfc_StateResponse: {
    461         if (NFCSTATUS_RF_TIMEOUT != (pDlCtxt->TimerInfo.wTimerExpStatus)) {
    462           /* Process response */
    463           wStatus = phDnldNfc_ProcessFrame(pContext, pInfo);
    464 
    465           if (NFCSTATUS_BUSY == wStatus) {
    466             /* store the status for use in subsequent processing */
    467             wIntStatus = wStatus;
    468 
    469             /* setup the resend wait timer */
    470             wStatus = phDnldNfc_SetupResendTimer(pDlCtxt);
    471 
    472             if (NFCSTATUS_SUCCESS == wStatus) {
    473               /* restore the last mem_bsy status to avoid re-building frame
    474                * below */
    475               wStatus = wIntStatus;
    476             }
    477           }
    478         } else {
    479           wStatus = (pDlCtxt->TimerInfo.wTimerExpStatus);
    480           (pDlCtxt->TimerInfo.wTimerExpStatus) = 0;
    481         }
    482 
    483         if ((0 != (pDlCtxt->tRWInfo.wRemBytes)) &&
    484             (NFCSTATUS_SUCCESS == wStatus)) {
    485           /* Abort TML read operation which is always kept open */
    486           wIntStatus = phTmlNfc_ReadAbort();
    487 
    488           if (NFCSTATUS_SUCCESS != wIntStatus) {
    489             NXPLOG_FWDNLD_W("Tml read abort failed!");
    490           }
    491 
    492           wStatus = phDnldNfc_BuildFramePkt(pDlCtxt);
    493 
    494           if (NFCSTATUS_SUCCESS == wStatus) {
    495             pDlCtxt->tCurrState = phDnldNfc_StateRecv;
    496             wStatus = phTmlNfc_Write(
    497                 (pDlCtxt->tCmdRspFrameInfo.aFrameBuff),
    498                 (uint16_t)(pDlCtxt->tCmdRspFrameInfo.dwSendlength),
    499                 (pphTmlNfc_TransactCompletionCb_t)&phDnldNfc_ProcessRWSeqState,
    500                 pDlCtxt);
    501 
    502             /* TODO:- Verify here if TML_Write returned NFC_PENDING status &
    503                take appropriate
    504                   action otherwise ?? */
    505           }
    506         } else if (NFCSTATUS_BUSY == wStatus) {
    507           /* No processing to be done,since resend wait timer should have
    508            * already been started */
    509         } else {
    510           (pDlCtxt->tRWInfo.bFramesSegmented) = false;
    511           /* Abort TML read operation which is always kept open */
    512           wIntStatus = phTmlNfc_ReadAbort();
    513 
    514           if (NFCSTATUS_SUCCESS != wIntStatus) {
    515             NXPLOG_FWDNLD_W("Tml read abort failed!");
    516           }
    517 
    518           pDlCtxt->tCurrEvent = phDnldNfc_EventInvalid;
    519           pDlCtxt->tDnldInProgress = phDnldNfc_TransitionIdle;
    520           pDlCtxt->tCurrState = phDnldNfc_StateInit;
    521           pDlCtxt->bResendLastFrame = false;
    522 
    523           /* Delete the timer & reset timer primitives in context */
    524           (void)phOsalNfc_Timer_Delete(pDlCtxt->TimerInfo.dwRspTimerId);
    525           (pDlCtxt->TimerInfo.dwRspTimerId) = 0;
    526           (pDlCtxt->TimerInfo.TimerStatus) = 0;
    527           (pDlCtxt->TimerInfo.wTimerExpStatus) = 0;
    528 
    529           if ((NULL != (pDlCtxt->UserCb)) && (NULL != (pDlCtxt->UserCtxt))) {
    530             pDlCtxt->UserCb((pDlCtxt->UserCtxt), wStatus,
    531                             &(pDlCtxt->tRspBuffInfo));
    532           }
    533         }
    534         break;
    535       }
    536       default: {
    537         pDlCtxt->tCurrEvent = phDnldNfc_EventInvalid;
    538         pDlCtxt->tDnldInProgress = phDnldNfc_TransitionIdle;
    539         break;
    540       }
    541     }
    542   }
    543 
    544   return;
    545 }
    546 
    547 /*******************************************************************************
    548 **
    549 ** Function         phDnldNfc_BuildFramePkt
    550 **
    551 ** Description      Forms the frame packet
    552 **
    553 ** Parameters       pDlContext - pointer to the download context structure
    554 **
    555 ** Returns          NFC status
    556 **
    557 *******************************************************************************/
    558 static NFCSTATUS phDnldNfc_BuildFramePkt(pphDnldNfc_DlContext_t pDlContext) {
    559   NFCSTATUS wStatus = NFCSTATUS_SUCCESS;
    560   uint16_t wFrameLen = 0;
    561   uint16_t wCrcVal;
    562   uint8_t* pFrameByte;
    563 
    564   if (NULL == pDlContext) {
    565     NXPLOG_FWDNLD_E("Invalid Input Parameter!!");
    566     wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER);
    567   } else {
    568     if (phDnldNfc_FTWrite == (pDlContext->FrameInp.Type)) {
    569       if ((0 == (pDlContext->tUserData.wLen)) ||
    570           (NULL == (pDlContext->tUserData.pBuff))) {
    571         NXPLOG_FWDNLD_E("Invalid Input Parameter(s) for Write!!");
    572         wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER);
    573       } else {
    574         if ((pDlContext->tRWInfo.bFirstWrReq) == true) {
    575           (pDlContext->tRWInfo.wRemBytes) = (pDlContext->tUserData.wLen);
    576           (pDlContext->tRWInfo.wOffset) = 0;
    577         }
    578       }
    579     } else if (phDnldNfc_FTRead == (pDlContext->FrameInp.Type)) {
    580       if ((0 == (pDlContext->tRspBuffInfo.wLen)) ||
    581           (NULL == (pDlContext->tRspBuffInfo.pBuff))) {
    582         NXPLOG_FWDNLD_E("Invalid Input Parameter(s) for Read!!");
    583         wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER);
    584       } else {
    585         if ((pDlContext->tRWInfo.bFramesSegmented) == false) {
    586           NXPLOG_FWDNLD_D("Verifying RspBuffInfo for Read Request..");
    587           wFrameLen = (pDlContext->tRspBuffInfo.wLen) + PHDNLDNFC_MIN_PLD_LEN;
    588 
    589           (pDlContext->tRWInfo.wRWPldSize) =
    590               (PHDNLDNFC_CMDRESP_MAX_PLD_SIZE - PHDNLDNFC_MIN_PLD_LEN);
    591           (pDlContext->tRWInfo.wRemBytes) = (pDlContext->tRspBuffInfo.wLen);
    592           (pDlContext->tRWInfo.dwAddr) = (pDlContext->FrameInp.dwAddr);
    593           (pDlContext->tRWInfo.wOffset) = 0;
    594           (pDlContext->tRWInfo.wBytesRead) = 0;
    595 
    596           if (PHDNLDNFC_CMDRESP_MAX_PLD_SIZE < wFrameLen) {
    597             (pDlContext->tRWInfo.bFramesSegmented) = true;
    598           }
    599         }
    600       }
    601     } else if (phDnldNfc_FTLog == (pDlContext->FrameInp.Type)) {
    602       if ((0 == (pDlContext->tUserData.wLen)) ||
    603           (NULL == (pDlContext->tUserData.pBuff))) {
    604         NXPLOG_FWDNLD_E("Invalid Input Parameter(s) for Log!!");
    605         wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER);
    606       }
    607     } else {
    608     }
    609 
    610     if (NFCSTATUS_SUCCESS == wStatus) {
    611       wStatus = phDnldNfc_CreateFramePld(pDlContext);
    612     }
    613 
    614     if (NFCSTATUS_SUCCESS == wStatus) {
    615       wFrameLen = 0;
    616       wFrameLen = (pDlContext->tCmdRspFrameInfo.dwSendlength);
    617 
    618       if (phDnldNfc_FTRaw != (pDlContext->FrameInp.Type)) {
    619         if (phDnldNfc_FTWrite != (pDlContext->FrameInp.Type)) {
    620           pFrameByte = (uint8_t*)&wFrameLen;
    621 
    622           pDlContext->tCmdRspFrameInfo.aFrameBuff[PHDNLDNFC_FRAME_HDR_OFFSET] =
    623               pFrameByte[1];
    624           pDlContext->tCmdRspFrameInfo
    625               .aFrameBuff[PHDNLDNFC_FRAME_HDR_OFFSET + 1] = pFrameByte[0];
    626 
    627           NXPLOG_FWDNLD_D("Inserting FrameId ..");
    628           pDlContext->tCmdRspFrameInfo.aFrameBuff[PHDNLDNFC_FRAMEID_OFFSET] =
    629               (pDlContext->tCmdId);
    630 
    631           wFrameLen += PHDNLDNFC_FRAME_HDR_LEN;
    632         } else {
    633           if (0 != (pDlContext->tRWInfo.wRWPldSize)) {
    634             if ((pDlContext->tRWInfo.bFramesSegmented) == true) {
    635               /* Turning ON the Fragmentation bit in FrameLen */
    636               wFrameLen = PHDNLDNFC_SET_HDR_FRAGBIT(wFrameLen);
    637             }
    638 
    639             pFrameByte = (uint8_t*)&wFrameLen;
    640 
    641             pDlContext->tCmdRspFrameInfo
    642                 .aFrameBuff[PHDNLDNFC_FRAME_HDR_OFFSET] = pFrameByte[1];
    643             pDlContext->tCmdRspFrameInfo
    644                 .aFrameBuff[PHDNLDNFC_FRAME_HDR_OFFSET + 1] = pFrameByte[0];
    645 
    646             /* To ensure we have no frag bit set for crc calculation */
    647             wFrameLen = PHDNLDNFC_CLR_HDR_FRAGBIT(wFrameLen);
    648 
    649             wFrameLen += PHDNLDNFC_FRAME_HDR_LEN;
    650           }
    651         }
    652         if (wFrameLen > PHDNLDNFC_CMDRESP_MAX_BUFF_SIZE) {
    653           NXPLOG_FWDNLD_D("wFrameLen exceeds the limit");
    654           return NFCSTATUS_FAILED;
    655         }
    656         /* calculate CRC16 */
    657         wCrcVal = phDnldNfc_CalcCrc16((pDlContext->tCmdRspFrameInfo.aFrameBuff),
    658                                       wFrameLen);
    659 
    660         pFrameByte = (uint8_t*)&wCrcVal;
    661 
    662         /* Insert the computed Crc value */
    663         pDlContext->tCmdRspFrameInfo.aFrameBuff[wFrameLen] = pFrameByte[1];
    664         pDlContext->tCmdRspFrameInfo.aFrameBuff[wFrameLen + 1] = pFrameByte[0];
    665 
    666         wFrameLen += PHDNLDNFC_FRAME_CRC_LEN;
    667       }
    668 
    669       (pDlContext->tCmdRspFrameInfo.dwSendlength) = wFrameLen;
    670       NXPLOG_FWDNLD_D("Frame created successfully");
    671     } else {
    672       NXPLOG_FWDNLD_E("Frame creation failed!!");
    673       wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED);
    674     }
    675   }
    676 
    677   return wStatus;
    678 }
    679 
    680 /*******************************************************************************
    681 **
    682 ** Function         phDnldNfc_CreateFramePld
    683 **
    684 ** Description      Forms the frame payload
    685 **
    686 ** Parameters       pDlContext - pointer to the download context structure
    687 **
    688 ** Returns          NFC status
    689 **
    690 *******************************************************************************/
    691 static NFCSTATUS phDnldNfc_CreateFramePld(pphDnldNfc_DlContext_t pDlContext) {
    692   NFCSTATUS wStatus = NFCSTATUS_SUCCESS;
    693   uint16_t wBuffIdx = 0;
    694   uint16_t wChkIntgVal = 0;
    695   uint16_t wFrameLen = 0;
    696 
    697   if (NULL == pDlContext) {
    698     NXPLOG_FWDNLD_E("Invalid Input Parameter!!");
    699     wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER);
    700   } else {
    701     memset((pDlContext->tCmdRspFrameInfo.aFrameBuff), 0,
    702            PHDNLDNFC_CMDRESP_MAX_BUFF_SIZE);
    703     (pDlContext->tCmdRspFrameInfo.dwSendlength) = 0;
    704 
    705     if (phDnldNfc_FTNone == (pDlContext->FrameInp.Type)) {
    706       (pDlContext->tCmdRspFrameInfo.dwSendlength) += PHDNLDNFC_MIN_PLD_LEN;
    707     } else if (phDnldNfc_ChkIntg == (pDlContext->FrameInp.Type)) {
    708       (pDlContext->tCmdRspFrameInfo.dwSendlength) += PHDNLDNFC_MIN_PLD_LEN;
    709 
    710       wChkIntgVal = PHDNLDNFC_USERDATA_EEPROM_OFFSET;
    711       memcpy(&(pDlContext->tCmdRspFrameInfo
    712                    .aFrameBuff[PHDNLDNFC_FRAME_RDDATA_OFFSET]),
    713              &wChkIntgVal, sizeof(wChkIntgVal));
    714 
    715       wChkIntgVal = PHDNLDNFC_USERDATA_EEPROM_LEN;
    716       memcpy(&(pDlContext->tCmdRspFrameInfo
    717                    .aFrameBuff[PHDNLDNFC_FRAME_RDDATA_OFFSET +
    718                                PHDNLDNFC_USERDATA_EEPROM_OFFSIZE]),
    719              &wChkIntgVal, sizeof(wChkIntgVal));
    720 
    721       (pDlContext->tCmdRspFrameInfo.dwSendlength) +=
    722           PHDNLDNFC_USERDATA_EEPROM_LENSIZE;
    723       (pDlContext->tCmdRspFrameInfo.dwSendlength) +=
    724           PHDNLDNFC_USERDATA_EEPROM_OFFSIZE;
    725     } else if (phDnldNfc_FTWrite == (pDlContext->FrameInp.Type)) {
    726       wBuffIdx = (pDlContext->tRWInfo.wOffset);
    727 
    728       if ((pDlContext->tRWInfo.bFramesSegmented) == false) {
    729         wFrameLen = (pDlContext->tUserData.pBuff[wBuffIdx]);
    730         wFrameLen <<= 8;
    731         wFrameLen |= (pDlContext->tUserData.pBuff[wBuffIdx + 1]);
    732 
    733         (pDlContext->tRWInfo.wRWPldSize) = wFrameLen;
    734       }
    735 
    736       if ((pDlContext->tRWInfo.wRWPldSize) > PHDNLDNFC_CMDRESP_MAX_PLD_SIZE) {
    737         if ((pDlContext->tRWInfo.bFirstChunkResp) == false) {
    738           (pDlContext->tRWInfo.wRemChunkBytes) = wFrameLen;
    739           (pDlContext->tRWInfo.wOffset) += PHDNLDNFC_FRAME_HDR_LEN;
    740           wBuffIdx = (pDlContext->tRWInfo.wOffset);
    741         }
    742 
    743         if (PHDNLDNFC_CMDRESP_MAX_PLD_SIZE <
    744             (pDlContext->tRWInfo.wRemChunkBytes)) {
    745           (pDlContext->tRWInfo.wBytesToSendRecv) =
    746               PHDNLDNFC_CMDRESP_MAX_PLD_SIZE;
    747           (pDlContext->tRWInfo.bFramesSegmented) = true;
    748         } else {
    749           (pDlContext->tRWInfo.wBytesToSendRecv) =
    750               (pDlContext->tRWInfo.wRemChunkBytes);
    751           (pDlContext->tRWInfo.bFramesSegmented) = false;
    752         }
    753 
    754         memcpy(&(pDlContext->tCmdRspFrameInfo
    755                      .aFrameBuff[PHDNLDNFC_FRAMEID_OFFSET]),
    756                &(pDlContext->tUserData.pBuff[wBuffIdx]),
    757                (pDlContext->tRWInfo.wBytesToSendRecv));
    758       } else {
    759         (pDlContext->tRWInfo.wRWPldSize) = 0;
    760         (pDlContext->tRWInfo.wBytesToSendRecv) =
    761             (wFrameLen + PHDNLDNFC_FRAME_HDR_LEN);
    762 
    763         memcpy(&(pDlContext->tCmdRspFrameInfo.aFrameBuff[0]),
    764                &(pDlContext->tUserData.pBuff[wBuffIdx]),
    765                (pDlContext->tRWInfo.wBytesToSendRecv));
    766       }
    767       (pDlContext->tCmdRspFrameInfo.dwSendlength) +=
    768           (pDlContext->tRWInfo.wBytesToSendRecv);
    769     } else if (phDnldNfc_FTRead == (pDlContext->FrameInp.Type)) {
    770       (pDlContext->tRWInfo.wBytesToSendRecv) =
    771           ((pDlContext->tRWInfo.wRemBytes) > (pDlContext->tRWInfo.wRWPldSize))
    772               ? (pDlContext->tRWInfo.wRWPldSize)
    773               : (pDlContext->tRWInfo.wRemBytes);
    774 
    775       wBuffIdx = (PHDNLDNFC_PLD_OFFSET +
    776                   ((sizeof(pDlContext->tRWInfo.wBytesToSendRecv)) %
    777                    PHDNLDNFC_MIN_PLD_LEN) -
    778                   1);
    779 
    780       memcpy(&(pDlContext->tCmdRspFrameInfo.aFrameBuff[wBuffIdx]),
    781              &(pDlContext->tRWInfo.wBytesToSendRecv),
    782              (sizeof(pDlContext->tRWInfo.wBytesToSendRecv)));
    783 
    784       wBuffIdx += sizeof(pDlContext->tRWInfo.wBytesToSendRecv);
    785 
    786       memcpy(&(pDlContext->tCmdRspFrameInfo.aFrameBuff[wBuffIdx]),
    787              &(pDlContext->tRWInfo.dwAddr), sizeof(pDlContext->tRWInfo.dwAddr));
    788 
    789       (pDlContext->tCmdRspFrameInfo.dwSendlength) +=
    790           (PHDNLDNFC_MIN_PLD_LEN + (sizeof(pDlContext->tRWInfo.dwAddr)));
    791     } else if (phDnldNfc_FTLog == (pDlContext->FrameInp.Type)) {
    792       (pDlContext->tCmdRspFrameInfo.dwSendlength) += PHDNLDNFC_MIN_PLD_LEN;
    793 
    794       wBuffIdx = (PHDNLDNFC_MIN_PLD_LEN + PHDNLDNFC_FRAME_HDR_LEN);
    795 
    796       memcpy(&(pDlContext->tCmdRspFrameInfo.aFrameBuff[wBuffIdx]),
    797              (pDlContext->tUserData.pBuff), (pDlContext->tUserData.wLen));
    798 
    799       (pDlContext->tCmdRspFrameInfo.dwSendlength) +=
    800           (pDlContext->tUserData.wLen);
    801     } else if (phDnldNfc_FTForce == (pDlContext->FrameInp.Type)) {
    802       (pDlContext->tCmdRspFrameInfo.dwSendlength) += PHDNLDNFC_MIN_PLD_LEN;
    803 
    804       wBuffIdx = PHDNLDNFC_PLD_OFFSET;
    805 
    806       memcpy(&(pDlContext->tCmdRspFrameInfo.aFrameBuff[wBuffIdx]),
    807              (pDlContext->tUserData.pBuff), (pDlContext->tUserData.wLen));
    808     } else if (phDnldNfc_FTRaw == (pDlContext->FrameInp.Type)) {
    809       if ((0 == (pDlContext->tUserData.wLen)) ||
    810           (NULL == (pDlContext->tUserData.pBuff))) {
    811         NXPLOG_FWDNLD_E("Invalid Input Parameter(s) for Raw Request!!");
    812         wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER);
    813       } else {
    814         memcpy(&(pDlContext->tCmdRspFrameInfo.aFrameBuff[wBuffIdx]),
    815                (pDlContext->tUserData.pBuff), (pDlContext->tUserData.wLen));
    816 
    817         (pDlContext->tCmdRspFrameInfo.dwSendlength) +=
    818             (pDlContext->tUserData.wLen);
    819       }
    820     } else {
    821     }
    822   }
    823 
    824   return wStatus;
    825 }
    826 
    827 /*******************************************************************************
    828 **
    829 ** Function         phDnldNfc_ProcessFrame
    830 **
    831 ** Description      Processes response frame received
    832 **
    833 ** Parameters       pContext - pointer to the download context structure
    834 **                  pInfo - pointer to the Transaction buffer updated by TML
    835 **                          Thread
    836 **
    837 ** Returns          NFCSTATUS_SUCCESS - parameters successfully validated
    838 **                  NFCSTATUS_INVALID_PARAMETER - invalid parameters
    839 **
    840 *******************************************************************************/
    841 static NFCSTATUS phDnldNfc_ProcessFrame(void* pContext,
    842                                         phTmlNfc_TransactInfo_t* pInfo) {
    843   NFCSTATUS wStatus = NFCSTATUS_SUCCESS;
    844   uint16_t wCrcVal, wRecvdCrc, wRecvdLen, wPldLen;
    845   pphDnldNfc_DlContext_t pDlCtxt = (pphDnldNfc_DlContext_t)pContext;
    846 
    847   if ((NULL == pDlCtxt) || (NULL == pInfo)) {
    848     NXPLOG_FWDNLD_E("Invalid Input Parameters!!");
    849     wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER);
    850   } else {
    851     if ((PH_DL_STATUS_OK != pInfo->wStatus) || (0 == pInfo->wLength) ||
    852         (NULL == pInfo->pBuff)) {
    853       NXPLOG_FWDNLD_E("Dnld Cmd Request Failed!!");
    854       wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED);
    855     } else {
    856       if (phDnldNfc_FTRaw == (pDlCtxt->FrameInp.Type)) {
    857         if ((0 != (pDlCtxt->tRspBuffInfo.wLen)) &&
    858             (NULL != (pDlCtxt->tRspBuffInfo.pBuff))) {
    859           memcpy((pDlCtxt->tRspBuffInfo.pBuff), (pInfo->pBuff),
    860                  (pInfo->wLength));
    861 
    862           (pDlCtxt->tRspBuffInfo.wLen) = (pInfo->wLength);
    863         } else {
    864           NXPLOG_FWDNLD_E("Cannot update Response buff with received data!!");
    865         }
    866       } else {
    867         /* calculate CRC16 */
    868         wCrcVal = phDnldNfc_CalcCrc16(
    869             (pInfo->pBuff), ((pInfo->wLength) - PHDNLDNFC_FRAME_CRC_LEN));
    870 
    871         wRecvdCrc = 0;
    872         wRecvdCrc = (((uint16_t)(pInfo->pBuff[(pInfo->wLength) - 2]) << 8U) |
    873                      (pInfo->pBuff[(pInfo->wLength) - 1]));
    874 
    875         if (wRecvdCrc == wCrcVal) {
    876           wRecvdLen =
    877               (((uint16_t)(pInfo->pBuff[PHDNLDNFC_FRAME_HDR_OFFSET]) << 8U) |
    878                (pInfo->pBuff[PHDNLDNFC_FRAME_HDR_OFFSET + 1]));
    879 
    880           wPldLen = ((pInfo->wLength) -
    881                      (PHDNLDNFC_FRAME_HDR_LEN + PHDNLDNFC_FRAME_CRC_LEN));
    882 
    883           if (wRecvdLen != wPldLen) {
    884             NXPLOG_FWDNLD_E("Invalid frame payload length received");
    885             wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED);
    886           } else {
    887             wStatus = phDnldNfc_UpdateRsp(pDlCtxt, pInfo, (wPldLen - 1));
    888           }
    889         } else {
    890           NXPLOG_FWDNLD_E("Invalid frame received");
    891           wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED);
    892         }
    893       }
    894     }
    895   }
    896 
    897   return wStatus;
    898 }
    899 
    900 /*******************************************************************************
    901 **
    902 ** Function         phDnldNfc_ProcessRecvInfo
    903 **
    904 ** Description      Processes the response during the state phDnldNfc_StateRecv
    905 **
    906 ** Parameters       pContext - pointer to the download context structure
    907 **                  pInfo - pointer to the Transaction buffer updated by TML
    908 **                          Thread
    909 **
    910 ** Returns          NFCSTATUS_SUCCESS - parameters successfully validated
    911 **                  NFCSTATUS_INVALID_PARAMETER - invalid parameters
    912 **
    913 *******************************************************************************/
    914 static NFCSTATUS phDnldNfc_ProcessRecvInfo(void* pContext,
    915                                            phTmlNfc_TransactInfo_t* pInfo) {
    916   NFCSTATUS wStatus = NFCSTATUS_SUCCESS;
    917 
    918   if (NULL != pContext) {
    919     if (NULL == pInfo) {
    920       NXPLOG_FWDNLD_E("Invalid pInfo received from TML!!");
    921       wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED);
    922     } else {
    923       wStatus = PHNFCSTATUS(pInfo->wStatus);
    924 
    925       if (NFCSTATUS_SUCCESS == wStatus) {
    926         NXPLOG_FWDNLD_D("Send Success");
    927       } else {
    928         NXPLOG_FWDNLD_E("Tml Write error!!");
    929         wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED);
    930       }
    931     }
    932   } else {
    933     NXPLOG_FWDNLD_E("Invalid context received from TML!!");
    934     wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED);
    935   }
    936 
    937   return wStatus;
    938 }
    939 
    940 /*******************************************************************************
    941 **
    942 ** Function         phDnldNfc_SetupResendTimer
    943 **
    944 ** Description      Sets up the timer for resending the previous write frame
    945 **
    946 ** Parameters       pDlContext - pointer to the download context structure
    947 **
    948 ** Returns          NFC status
    949 **
    950 *******************************************************************************/
    951 static NFCSTATUS phDnldNfc_SetupResendTimer(pphDnldNfc_DlContext_t pDlContext) {
    952   NFCSTATUS wStatus = NFCSTATUS_SUCCESS;
    953 
    954   wStatus = phOsalNfc_Timer_Start((pDlContext->TimerInfo.dwRspTimerId),
    955                                   PHDNLDNFC_RETRY_FRAME_WRITE,
    956                                   &phDnldNfc_ResendTimeOutCb, pDlContext);
    957 
    958   if (NFCSTATUS_SUCCESS == wStatus) {
    959     NXPLOG_FWDNLD_D("Frame Resend wait timer started");
    960     (pDlContext->TimerInfo.TimerStatus) = 1;
    961     pDlContext->tCurrState = phDnldNfc_StateTimer;
    962   } else {
    963     NXPLOG_FWDNLD_W("Frame Resend wait timer not started");
    964     (pDlContext->TimerInfo.TimerStatus) = 0; /*timer stopped*/
    965     pDlContext->tCurrState = phDnldNfc_StateResponse;
    966     /* Todo:- diagnostic in this case */
    967   }
    968 
    969   return wStatus;
    970 }
    971 
    972 #if !defined(PH_LIBNFC_VEN_RESET_ON_DOWNLOAD_TIMEOUT)
    973 #error PH_LIBNFC_VEN_RESET_ON_DOWNLOAD_TIMEOUT has to be defined
    974 #endif
    975 
    976 /*******************************************************************************
    977 **
    978 ** Function         phDnldNfc_RspTimeOutCb
    979 **
    980 ** Description      Callback function in case of timer expiration
    981 **
    982 ** Parameters       TimerId  - expired timer id
    983 **                  pContext - pointer to the download context structure
    984 **
    985 ** Returns          None
    986 **
    987 *******************************************************************************/
    988 static void phDnldNfc_RspTimeOutCb(uint32_t TimerId, void* pContext) {
    989   pphDnldNfc_DlContext_t pDlCtxt = (pphDnldNfc_DlContext_t)pContext;
    990 
    991   if (NULL != pDlCtxt) {
    992     UNUSED(TimerId);
    993 
    994     if (1 == pDlCtxt->TimerInfo.TimerStatus) {
    995       /* No response received and the timer expired */
    996       pDlCtxt->TimerInfo.TimerStatus = 0; /* Reset timer status flag */
    997 
    998       NXPLOG_FWDNLD_D("%x", pDlCtxt->tLastStatus);
    999 
   1000 #if (PH_LIBNFC_VEN_RESET_ON_DOWNLOAD_TIMEOUT == TRUE)
   1001       if (PH_DL_STATUS_SIGNATURE_ERROR == pDlCtxt->tLastStatus) {
   1002         /* Do a VEN Reset of the chip. */
   1003         NXPLOG_FWDNLD_E("Performing a VEN Reset");
   1004         phTmlNfc_IoCtl(phTmlNfc_e_EnableNormalMode);
   1005         phTmlNfc_IoCtl(phTmlNfc_e_EnableDownloadMode);
   1006         NXPLOG_FWDNLD_E("VEN Reset Done");
   1007       }
   1008 #endif
   1009 
   1010       (pDlCtxt->TimerInfo.wTimerExpStatus) = NFCSTATUS_RF_TIMEOUT;
   1011 
   1012       if ((phDnldNfc_EventRead == pDlCtxt->tCurrEvent) ||
   1013           (phDnldNfc_EventWrite == pDlCtxt->tCurrEvent)) {
   1014         phDnldNfc_ProcessRWSeqState(pDlCtxt, NULL);
   1015       } else {
   1016         phDnldNfc_ProcessSeqState(pDlCtxt, NULL);
   1017       }
   1018     }
   1019   }
   1020 
   1021   return;
   1022 }
   1023 
   1024 /*******************************************************************************
   1025 **
   1026 ** Function         phDnldNfc_ResendTimeOutCb
   1027 **
   1028 ** Description      Callback function in case of Frame Resend Wait timer
   1029 **                  expiration
   1030 **
   1031 ** Parameters       TimerId  - expired timer id
   1032 **                  pContext - pointer to the download context structure
   1033 **
   1034 ** Returns          None
   1035 **
   1036 *******************************************************************************/
   1037 static void phDnldNfc_ResendTimeOutCb(uint32_t TimerId, void* pContext) {
   1038   pphDnldNfc_DlContext_t pDlCtxt = (pphDnldNfc_DlContext_t)pContext;
   1039 
   1040   if (NULL != pDlCtxt) {
   1041     UNUSED(TimerId);
   1042 
   1043     if (1 == pDlCtxt->TimerInfo.TimerStatus) {
   1044       /* No response received and the timer expired */
   1045       pDlCtxt->TimerInfo.TimerStatus = 0; /* Reset timer status flag */
   1046 
   1047       (pDlCtxt->TimerInfo.wTimerExpStatus) = 0;
   1048 
   1049       pDlCtxt->tCurrState = phDnldNfc_StateSend;
   1050 
   1051       /* set the flag to trigger last frame re-transmission */
   1052       pDlCtxt->bResendLastFrame = true;
   1053 
   1054       phDnldNfc_ProcessRWSeqState(pDlCtxt, NULL);
   1055     }
   1056   }
   1057 
   1058   return;
   1059 }
   1060 
   1061 /*******************************************************************************
   1062 **
   1063 ** Function         phDnldNfc_UpdateRsp
   1064 **
   1065 ** Description      verifies the payload status byte and copies data
   1066 **                  to response buffer if successful
   1067 **
   1068 ** Parameters       pDlContext - pointer to the download context structure
   1069 **                  pInfo - pointer to the Transaction buffer updated by TML
   1070 **                          Thread
   1071 **                  wPldLen - Length of the payload bytes to copy to response
   1072 **                            buffer
   1073 **
   1074 ** Returns          NFC status
   1075 **
   1076 *******************************************************************************/
   1077 static NFCSTATUS phDnldNfc_UpdateRsp(pphDnldNfc_DlContext_t pDlContext,
   1078                                      phTmlNfc_TransactInfo_t* pInfo,
   1079                                      uint16_t wPldLen) {
   1080   NFCSTATUS wStatus = NFCSTATUS_SUCCESS;
   1081   uint16_t wReadLen = 0;
   1082 
   1083   if ((NULL == pDlContext) || (NULL == pInfo)) {
   1084     NXPLOG_FWDNLD_E("Invalid Input Parameters!!");
   1085     wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER);
   1086   } else {
   1087     if (PH_DL_CMD_WRITE == (pDlContext->tCmdId)) {
   1088       if (PH_DL_STATUS_OK == (pInfo->pBuff[PHDNLDNFC_FRAMESTATUS_OFFSET])) {
   1089         /* first write frame response received case */
   1090         if ((pDlContext->tRWInfo.bFirstWrReq) == true) {
   1091           NXPLOG_FWDNLD_D("First Write Frame Success Status received!!");
   1092           (pDlContext->tRWInfo.bFirstWrReq) = false;
   1093         }
   1094 
   1095         if ((pDlContext->tRWInfo.bFirstChunkResp) == true) {
   1096           if ((pDlContext->tRWInfo.bFramesSegmented) == false) {
   1097             NXPLOG_FWDNLD_D("Chunked Write Frame Success Status received!!");
   1098             (pDlContext->tRWInfo.wRemChunkBytes) -=
   1099                 (pDlContext->tRWInfo.wBytesToSendRecv);
   1100             (pDlContext->tRWInfo.bFirstChunkResp) = false;
   1101           } else {
   1102             NXPLOG_FWDNLD_E("UnExpected Status received!!");
   1103             wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED);
   1104           }
   1105         }
   1106 
   1107         if (NFCSTATUS_SUCCESS == wStatus) {
   1108           (pDlContext->tRWInfo.wRemBytes) -=
   1109               (pDlContext->tRWInfo.wBytesToSendRecv);
   1110           (pDlContext->tRWInfo.wOffset) +=
   1111               (pDlContext->tRWInfo.wBytesToSendRecv);
   1112         }
   1113       } else if (((pDlContext->tRWInfo.bFirstChunkResp) == false) &&
   1114                  ((pDlContext->tRWInfo.bFramesSegmented) == true) &&
   1115                  (PHDNLDNFC_FIRST_FRAGFRAME_RESP ==
   1116                   (pInfo->pBuff[PHDNLDNFC_FRAMESTATUS_OFFSET]))) {
   1117         (pDlContext->tRWInfo.bFirstChunkResp) = true;
   1118         (pDlContext->tRWInfo.wRemChunkBytes) -=
   1119             (pDlContext->tRWInfo.wBytesToSendRecv);
   1120         (pDlContext->tRWInfo.wRemBytes) -=
   1121             ((pDlContext->tRWInfo.wBytesToSendRecv) + PHDNLDNFC_FRAME_HDR_LEN);
   1122         (pDlContext->tRWInfo.wOffset) += (pDlContext->tRWInfo.wBytesToSendRecv);
   1123 
   1124         /* first write frame response received case */
   1125         if ((pDlContext->tRWInfo.bFirstWrReq) == true) {
   1126           NXPLOG_FWDNLD_D("First Write Frame Success Status received!!");
   1127           (pDlContext->tRWInfo.bFirstWrReq) = false;
   1128         }
   1129       } else if (((pDlContext->tRWInfo.bFirstChunkResp) == true) &&
   1130                  ((pDlContext->tRWInfo.bFramesSegmented) == true) &&
   1131                  (PHDNLDNFC_NEXT_FRAGFRAME_RESP ==
   1132                   (pInfo->pBuff[PHDNLDNFC_FRAMESTATUS_OFFSET]))) {
   1133         (pDlContext->tRWInfo.wRemChunkBytes) -=
   1134             (pDlContext->tRWInfo.wBytesToSendRecv);
   1135         (pDlContext->tRWInfo.wRemBytes) -=
   1136             (pDlContext->tRWInfo.wBytesToSendRecv);
   1137         (pDlContext->tRWInfo.wOffset) += (pDlContext->tRWInfo.wBytesToSendRecv);
   1138       } else if (PH_DL_STATUS_FIRMWARE_VERSION_ERROR ==
   1139                  (pInfo->pBuff[PHDNLDNFC_FRAMESTATUS_OFFSET])) {
   1140         NXPLOG_FWDNLD_E(
   1141             "FW version Error !!!could be either due to FW major version "
   1142             "mismatch or Firmware Already Up To Date !!");
   1143         (pDlContext->tRWInfo.bFirstWrReq) = false;
   1144         /* resetting wRemBytes to 0 to avoid any further write frames send */
   1145         (pDlContext->tRWInfo.wRemBytes) = 0;
   1146         (pDlContext->tRWInfo.wOffset) = 0;
   1147         wStatus = NFCSTATUS_FW_VERSION_ERROR;
   1148       } else if (PH_DL_STATUS_PLL_ERROR ==
   1149                  (pInfo->pBuff[PHDNLDNFC_FRAMESTATUS_OFFSET])) {
   1150         NXPLOG_FWDNLD_E("PLL Error Status received!!");
   1151         (pDlContext->tLastStatus) = PH_DL_STATUS_PLL_ERROR;
   1152         wStatus = NFCSTATUS_WRITE_FAILED;
   1153       } else if (PH_DL_STATUS_SIGNATURE_ERROR ==
   1154                  (pInfo->pBuff[PHDNLDNFC_FRAMESTATUS_OFFSET])) {
   1155         NXPLOG_FWDNLD_E("Signature Mismatch Error received!!");
   1156         /* save the status for use in loading the relevant recovery image
   1157          * (either signature or platform) */
   1158         (pDlContext->tLastStatus) = PH_DL_STATUS_SIGNATURE_ERROR;
   1159         wStatus = NFCSTATUS_REJECTED;
   1160       } else if (PH_DL_STATUS_MEM_BSY ==
   1161                  (pInfo->pBuff[PHDNLDNFC_FRAMESTATUS_OFFSET])) {
   1162         NXPLOG_FWDNLD_E("Mem Busy Status received!!");
   1163         (pDlContext->tLastStatus) = PH_DL_STATUS_MEM_BSY;
   1164         wStatus = NFCSTATUS_BUSY;
   1165       } else {
   1166         NXPLOG_FWDNLD_E("Unsuccessful Status received!!");
   1167         wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED);
   1168       }
   1169     } else if (PH_DL_CMD_READ == (pDlContext->tCmdId)) {
   1170       if (PH_DL_STATUS_OK == (pInfo->pBuff[PHDNLDNFC_FRAMESTATUS_OFFSET])) {
   1171         wReadLen = (((uint16_t)(pInfo->pBuff[PHDNLDNFC_FRAMESTATUS_OFFSET + 3])
   1172                      << 8U) |
   1173                     (pInfo->pBuff[PHDNLDNFC_FRAMESTATUS_OFFSET + 2]));
   1174 
   1175         if (wReadLen != (pDlContext->tRWInfo.wBytesToSendRecv)) {
   1176           NXPLOG_FWDNLD_E("Desired Length bytes not received!!");
   1177           wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED);
   1178         } else {
   1179           memcpy(
   1180               &(pDlContext->tRspBuffInfo.pBuff[(pDlContext->tRWInfo.wOffset)]),
   1181               &(pInfo->pBuff[PHDNLDNFC_FRAME_RDDATA_OFFSET]), wReadLen);
   1182 
   1183           (pDlContext->tRWInfo.wBytesRead) += wReadLen;
   1184 
   1185           (pDlContext->tRspBuffInfo.wLen) = (pDlContext->tRWInfo.wBytesRead);
   1186 
   1187           (pDlContext->tRWInfo.wRemBytes) -=
   1188               (pDlContext->tRWInfo.wBytesToSendRecv);
   1189           (pDlContext->tRWInfo.dwAddr) +=
   1190               (pDlContext->tRWInfo.wBytesToSendRecv);
   1191           (pDlContext->tRWInfo.wOffset) +=
   1192               (pDlContext->tRWInfo.wBytesToSendRecv);
   1193         }
   1194       } else {
   1195         NXPLOG_FWDNLD_E("Unsuccessful Status received!!");
   1196         wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED);
   1197       }
   1198     } else {
   1199       if (PH_DL_STATUS_OK == (pInfo->pBuff[PHDNLDNFC_FRAMESTATUS_OFFSET])) {
   1200         if ((0 != (pDlContext->tRspBuffInfo.wLen)) &&
   1201             (NULL != (pDlContext->tRspBuffInfo.pBuff))) {
   1202           memcpy((pDlContext->tRspBuffInfo.pBuff),
   1203                  &(pInfo->pBuff[PHDNLDNFC_FRAMESTATUS_OFFSET + 1]), wPldLen);
   1204 
   1205           (pDlContext->tRspBuffInfo.wLen) = wPldLen;
   1206         }
   1207       } else {
   1208         NXPLOG_FWDNLD_E("Unsuccessful Status received!!");
   1209         wStatus = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED);
   1210       }
   1211     }
   1212   }
   1213 
   1214   return wStatus;
   1215 }
   1216