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