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