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