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