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 */
78static void phDnldNfc_ProcessSeqState(void *pContext, phTmlNfc_TransactInfo_t *pInfo);
79static void phDnldNfc_ProcessRWSeqState(void *pContext, phTmlNfc_TransactInfo_t *pInfo);
80static NFCSTATUS phDnldNfc_ProcessFrame(void *pContext, phTmlNfc_TransactInfo_t *pInfo);
81static NFCSTATUS phDnldNfc_ProcessRecvInfo(void *pContext, phTmlNfc_TransactInfo_t *pInfo);
82static NFCSTATUS phDnldNfc_BuildFramePkt(pphDnldNfc_DlContext_t pDlContext);
83static NFCSTATUS phDnldNfc_CreateFramePld(pphDnldNfc_DlContext_t pDlContext);
84static NFCSTATUS phDnldNfc_SetupResendTimer(pphDnldNfc_DlContext_t pDlContext);
85static NFCSTATUS phDnldNfc_UpdateRsp(pphDnldNfc_DlContext_t   pDlContext, phTmlNfc_TransactInfo_t  *pInfo, uint16_t wPldLen);
86static void phDnldNfc_RspTimeOutCb(uint32_t TimerId, void *pContext);
87static 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*******************************************************************************/
112NFCSTATUS 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*******************************************************************************/
196static 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*******************************************************************************/
372static 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*******************************************************************************/
592static 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*******************************************************************************/
748static 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*******************************************************************************/
906static 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*******************************************************************************/
995static 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*******************************************************************************/
1040static 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*******************************************************************************/
1082static 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*******************************************************************************/
1136static 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*******************************************************************************/
1177static 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