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