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