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