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