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