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 */
103static void phDnldNfc_ProcessSeqState(void* pContext,
104                                      phTmlNfc_TransactInfo_t* pInfo);
105static void phDnldNfc_ProcessRWSeqState(void* pContext,
106                                        phTmlNfc_TransactInfo_t* pInfo);
107static NFCSTATUS phDnldNfc_ProcessFrame(void* pContext,
108                                        phTmlNfc_TransactInfo_t* pInfo);
109static NFCSTATUS phDnldNfc_ProcessRecvInfo(void* pContext,
110                                           phTmlNfc_TransactInfo_t* pInfo);
111static NFCSTATUS phDnldNfc_BuildFramePkt(pphDnldNfc_DlContext_t pDlContext);
112static NFCSTATUS phDnldNfc_CreateFramePld(pphDnldNfc_DlContext_t pDlContext);
113static NFCSTATUS phDnldNfc_SetupResendTimer(pphDnldNfc_DlContext_t pDlContext);
114static NFCSTATUS phDnldNfc_UpdateRsp(pphDnldNfc_DlContext_t pDlContext,
115                                     phTmlNfc_TransactInfo_t* pInfo,
116                                     uint16_t wPldLen);
117static void phDnldNfc_RspTimeOutCb(uint32_t TimerId, void* pContext);
118static 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*******************************************************************************/
148NFCSTATUS 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*******************************************************************************/
219static 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*******************************************************************************/
369static 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*******************************************************************************/
558static 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*******************************************************************************/
691static 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*******************************************************************************/
841static 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*******************************************************************************/
914static 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*******************************************************************************/
951static 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*******************************************************************************/
988static 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*******************************************************************************/
1037static 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*******************************************************************************/
1077static 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