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