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