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