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