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