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