1 /* 2 * Copyright (C) 2010 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 * \file phFriNfc_TopazMap.c 19 * \brief NFC Ndef Mapping For Remote Devices. 20 * 21 * Project: NFC-FRI 22 * 23 * $Date: Wed May 12 10:21:17 2010 $ 24 * $Author: ing02260 $ 25 * $Revision: 1.21 $ 26 * $Aliases: NFC_FRI1.1_WK1019_SDK,NFC_FRI1.1_WK1023_R35_1 $ 27 * 28 */ 29 30 31 32 #include <phFriNfc_NdefMap.h> 33 #include <phFriNfc_TopazMap.h> 34 #include <phFriNfc_MapTools.h> 35 #include <phFriNfc_OvrHal.h> 36 37 #ifndef PH_FRINFC_MAP_TOPAZ_DISABLED 38 /*! \ingroup grp_file_attributes 39 * \name NDEF Mapping 40 * 41 * File: \ref phFriNfcNdefMap.c 42 * 43 */ 44 /*@{*/ 45 #define PHFRINFCTOPAZMAP_FILEREVISION "$Revision: 1.21 $" 46 #define PHFRINFCTOPAZMAP_FILEALIASES "$Aliases: NFC_FRI1.1_WK1019_SDK,NFC_FRI1.1_WK1023_R35_1 $" 47 /*@}*/ 48 /****************** Start of macros ********************/ 49 /* Below MACRO is used for the WRITE error scenario, 50 in case PN544 returns error for any WRITE, then 51 read the written block and byte number, to check the data 52 written to the card is correct or not 53 */ 54 /* #define TOPAZ_RF_ERROR_WORKAROUND */ 55 56 #ifdef TOPAZ_RF_ERROR_WORKAROUND 57 58 /* Below MACROs are added for the error returned from HAL, if the 59 below error has occured during the WRITE, then read the error 60 returned blocks to confirm */ 61 #define FRINFC_RF_TIMEOUT_89 (0x89U) 62 #define FRINFC_RF_TIMEOUT_90 (0x90U) 63 64 /* State specific to read after the RF ERROR for the WRITE */ 65 #define PH_FRINFC_TOPAZ_STATE_RF_ERROR_READ (0x0FU) 66 67 #endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */ 68 69 /****************** End of macros ********************/ 70 71 /*! 72 * \name Topaz Mapping - Helper Functions 73 * 74 */ 75 /*@{*/ 76 77 /*! 78 * \brief \copydoc page_ovr Helper function for Topaz. This function shall read 8 bytes 79 * from the card. 80 */ 81 static NFCSTATUS phFriNfc_Tpz_H_RdBytes(phFriNfc_NdefMap_t *NdefMap, 82 uint16_t BlockNo, 83 uint16_t ByteNo); 84 85 /*! 86 * \brief \copydoc page_ovr Helper function for Topaz. This function shall process 87 * read id command 88 */ 89 static NFCSTATUS phFriNfc_Tpz_H_ProReadID(phFriNfc_NdefMap_t *NdefMap); 90 91 /*! 92 * \brief \copydoc page_ovr Helper function for Topaz. This function shall process 93 * read all command 94 */ 95 static NFCSTATUS phFriNfc_Tpz_H_ProReadAll(phFriNfc_NdefMap_t *NdefMap); 96 97 /*! 98 * \brief \copydoc page_ovr Helper function for Topaz. This function depends on 99 * function called by the user 100 */ 101 static NFCSTATUS phFriNfc_Tpz_H_CallNxtOp(phFriNfc_NdefMap_t *NdefMap); 102 103 /*! 104 * \brief \copydoc page_ovr Helper function for Topaz. This function checks the CC 105 * bytes 106 */ 107 static NFCSTATUS phFriNfc_Tpz_H_ChkCCBytes(phFriNfc_NdefMap_t *NdefMap); 108 109 /*! 110 * \brief \copydoc page_ovr Helper function for Topaz. This function finds 111 * NDEF TLV 112 */ 113 static NFCSTATUS phFriNfc_Tpz_H_findNDEFTLV(phFriNfc_NdefMap_t *NdefMap); 114 115 /*! 116 * \brief \copydoc page_ovr Helper function for Topaz. This function writes a 117 * byte into the card 118 */ 119 static NFCSTATUS phFriNfc_Tpz_H_WrAByte(phFriNfc_NdefMap_t *NdefMap, 120 uint16_t BlockNo, 121 uint16_t ByteNo, 122 uint8_t ByteVal 123 ); 124 125 /*! 126 * \brief \copydoc page_ovr Helper function for Topaz. This function shall process the 127 * NMN write 128 */ 129 static NFCSTATUS phFriNfc_Tpz_H_ProWrNMN(phFriNfc_NdefMap_t *NdefMap); 130 131 /*! 132 * \brief \copydoc page_ovr Helper function for Topaz. This function writes the length field of 133 * the NDEF TLV 134 */ 135 static NFCSTATUS phFriNfc_Tpz_H_ProWrTLV(phFriNfc_NdefMap_t *NdefMap); 136 137 /*! 138 * \brief \copydoc page_ovr Helper function for Topaz. This function updates length field 139 * of the NDEF TLV after complete write. 140 */ 141 static NFCSTATUS phFriNfc_Tpz_H_WrLByte(phFriNfc_NdefMap_t *NdefMap); 142 143 /*! 144 * \brief \copydoc page_ovr Helper function for Topaz. This function copies the card data 145 * to the user buffer 146 */ 147 static NFCSTATUS phFriNfc_Tpz_H_CpDataToUsrBuf( phFriNfc_NdefMap_t *NdefMap); 148 149 /*! 150 * \brief \copydoc page_ovr Helper function for Topaz. This function shall process the 151 * written data 152 */ 153 static NFCSTATUS phFriNfc_Tpz_H_ProWrUsrData( phFriNfc_NdefMap_t *NdefMap); 154 155 /*! 156 * \brief \copydoc page_ovr Helper function for Topaz. This function checks the block 157 * number is correct or not 158 */ 159 static void phFriNfc_Tpz_H_BlkChk(phFriNfc_NdefMap_t *NdefMap); 160 161 /*! 162 * \brief \copydoc page_ovr Helper function for Topaz. This function writes the 0th 163 * byte of block 1 has Zero 164 */ 165 static NFCSTATUS phFriNfc_Tpz_H_WrByte0ValE1(phFriNfc_NdefMap_t *NdefMap); 166 167 /*! 168 * \brief \copydoc page_ovr Helper function for Topaz. This function calls the 169 * completion routine 170 */ 171 static void phFriNfc_Tpz_H_Complete(phFriNfc_NdefMap_t *NdefMap, 172 NFCSTATUS Status); 173 174 /*! 175 * \brief \copydoc page_ovr Helper function for Topaz check ndef. This function checks 176 * the CC byte in check ndef function 177 */ 178 static NFCSTATUS phFriNfc_Tpz_H_ChkCCinChkNdef(phFriNfc_NdefMap_t *NdefMap); 179 180 /*! 181 * \brief \copydoc page_ovr Helper function for Topaz check ndef. This function checks 182 * the lock bits and set a card state 183 */ 184 static void phFriNfc_Tpz_H_ChkLockBits(phFriNfc_NdefMap_t *NdefMap); 185 186 /*! 187 * \brief \copydoc page_ovr Helper function for Topaz. This function writes CC bytes or 188 * type of the TLV 189 */ 190 static NFCSTATUS phFriNfc_Tpz_H_WrCCorTLV(phFriNfc_NdefMap_t *NdefMap); 191 192 #ifdef TOPAZ_RF_ERROR_WORKAROUND 193 194 /*! 195 * \brief \copydoc page_ovr Helper function for Topaz. This function checks the written 196 * value after the 197 */ 198 static 199 NFCSTATUS 200 phFriNfc_Tpz_H_CheckWrittenData ( 201 phFriNfc_NdefMap_t *psNdefMap, 202 uint8_t state_rf_error); 203 204 #endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */ 205 206 /*! 207 * \brief \copydoc page_ovr Helper function for Topaz. This function checks the written 208 * CC bytes are correct 209 */ 210 static NFCSTATUS phFriNfc_Tpz_H_ProCCTLV(phFriNfc_NdefMap_t *NdefMap); 211 /*@}*/ 212 void phFriNfc_TopazMap_H_Reset(phFriNfc_NdefMap_t *NdefMap) 213 { 214 /* Initialising the Topaz structure variable */ 215 NdefMap->TopazContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_INVALID_OPE; 216 NdefMap->TopazContainer.CurrentBlock = PH_FRINFC_TOPAZ_VAL1; 217 NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL0; 218 NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_VAL0; 219 (void)memset(NdefMap->TopazContainer.ReadBuffer, PH_FRINFC_TOPAZ_VAL0, 220 sizeof(NdefMap->TopazContainer.ReadBuffer)); 221 NdefMap->TopazContainer.ReadWriteCompleteFlag = PH_FRINFC_TOPAZ_FLAG0; 222 NdefMap->TopazContainer.RemainingSize = PH_FRINFC_TOPAZ_VAL0; 223 (void)memset(NdefMap->TopazContainer.UID, PH_FRINFC_TOPAZ_VAL0, 224 sizeof(NdefMap->TopazContainer.UID)); 225 NdefMap->TopazContainer.Cur_RW_Index=0; 226 NdefMap->TopazContainer.ByteRWFrmCard =0; 227 } 228 229 /*! 230 * \brief Check whether a particular Remote Device is NDEF compliant. 231 * 232 * The function checks whether the peer device is NDEF compliant. 233 * 234 * \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t 235 * structure describing the component context. 236 * 237 * \retval NFCSTATUS_PENDING The action has been successfully triggered. 238 * \retval Others An error has occurred. 239 * 240 */ 241 242 NFCSTATUS phFriNfc_TopazMap_ChkNdef( phFriNfc_NdefMap_t *NdefMap) 243 { 244 NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, 245 NFCSTATUS_INVALID_PARAMETER); 246 if ( NdefMap != NULL) 247 { 248 /* Update the previous operation */ 249 NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_CHECK_OPE; 250 /* Update the CR index to know from which operation completion 251 routine has to be called */ 252 NdefMap->TopazContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_CHK_NDEF; 253 NdefMap->TopazContainer.CurrentBlock = PH_FRINFC_TOPAZ_VAL1; 254 NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL0; 255 256 /* Set card state */ 257 NdefMap->CardType = PH_FRINFC_NDEFMAP_TOPAZ_CARD; 258 259 /* Change the state to Check Ndef Compliant */ 260 NdefMap->State = PH_FRINFC_TOPAZ_STATE_READID; 261 NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_CHECK_OPE; 262 263 #ifdef TOPAZ_RAW_SUPPORT 264 NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw; 265 NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READID; 266 #else 267 #ifdef PH_HAL4_ENABLE 268 NdefMap->Cmd.JewelCmd = phHal_eJewel_RID; 269 #else 270 NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRid; 271 #endif 272 #endif /* #ifdef TOPAZ_RAW_SUPPORT */ 273 274 Result = phFriNfc_Tpz_H_RdBytes(NdefMap, NdefMap->TopazContainer.CurrentBlock, 275 NdefMap->TopazContainer.ByteNumber); 276 } 277 return Result; 278 } 279 280 281 /*! 282 * \brief Initiates Reading of NDEF information from the Remote Device. 283 * 284 * The function initiates the reading of NDEF information from a Remote Device. 285 * It performs a reset of the state and starts the action (state machine). 286 * A periodic call of the \ref phFriNfcNdefMap_Process has to be done once the action 287 * has been triggered. 288 */ 289 NFCSTATUS phFriNfc_TopazMap_RdNdef( phFriNfc_NdefMap_t *NdefMap, 290 uint8_t *PacketData, 291 uint32_t *PacketDataLength, 292 uint8_t Offset) 293 { 294 NFCSTATUS Result = NFCSTATUS_SUCCESS; 295 296 /* Copy user buffer to the context */ 297 NdefMap->ApduBuffer = PacketData; 298 /* Copy user length to the context */ 299 NdefMap->ApduBufferSize = *PacketDataLength; 300 /* Update the user memory size to a context variable */ 301 NdefMap->NumOfBytesRead = PacketDataLength; 302 /* Number of bytes read from the card is zero. 303 This variable returns the number of bytes read 304 from the card. */ 305 *NdefMap->NumOfBytesRead = PH_FRINFC_TOPAZ_VAL0; 306 /* Index to know the length read */ 307 NdefMap->ApduBuffIndex = PH_FRINFC_TOPAZ_VAL0; 308 /* Store the offset in the context */ 309 NdefMap->Offset = Offset; 310 /* Update the CR index to know from which operation completion 311 routine has to be called */ 312 NdefMap->TopazContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_RD_NDEF; 313 314 if( (Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN) || ( NdefMap->PrevOperation == 315 PH_FRINFC_NDEFMAP_WRITE_OPE)) 316 { 317 /* If previous operation is not read then the read shall 318 start from BEGIN */ 319 NdefMap->Offset = PH_FRINFC_NDEFMAP_SEEK_BEGIN; 320 /* Initialise current block and byte number */ 321 NdefMap->TopazContainer.CurrentBlock = PH_FRINFC_TOPAZ_VAL1; 322 NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL0; 323 /* State has to be changed */ 324 NdefMap->State = PH_FRINFC_TOPAZ_STATE_READALL; 325 NdefMap->TopazContainer.ReadWriteCompleteFlag = 326 PH_FRINFC_TOPAZ_FLAG0; 327 /* Topaz command = READALL */ 328 #ifdef TOPAZ_RAW_SUPPORT 329 NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw; 330 NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READALL; 331 #else 332 333 #ifdef PH_HAL4_ENABLE 334 NdefMap->Cmd.JewelCmd = phHal_eJewel_ReadAll; 335 #else 336 NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelReadAll; 337 #endif 338 339 #endif /* #ifdef TOPAZ_RAW_SUPPORT */ 340 } 341 342 NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_READ_OPE; 343 /* Offset = Current, but the read has reached the End of Card */ 344 if( (Offset == PH_FRINFC_NDEFMAP_SEEK_CUR) && 345 (NdefMap->TopazContainer.ReadWriteCompleteFlag == 346 PH_FRINFC_TOPAZ_FLAG1)) 347 { 348 Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, 349 NFCSTATUS_EOF_NDEF_CONTAINER_REACHED); 350 } 351 else 352 { 353 /* if the offset is begin then call READALL else copy the data 354 from the user buffer */ 355 Result = ((Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN)? 356 phFriNfc_Tpz_H_RdBytes(NdefMap, 357 NdefMap->TopazContainer.CurrentBlock, 358 NdefMap->TopazContainer.ByteNumber): 359 phFriNfc_Tpz_H_CpDataToUsrBuf(NdefMap)); 360 } 361 362 return Result; 363 } 364 365 /*! 366 * \brief Initiates Writing of NDEF information to the Remote Device. 367 * 368 * The function initiates the writing of NDEF information to a Remote Device. 369 * It performs a reset of the state and starts the action (state machine). 370 * A periodic call of the \ref phFriNfcNdefMap_Process has to be done once the action 371 * has been triggered. 372 */ 373 NFCSTATUS phFriNfc_TopazMap_WrNdef( phFriNfc_NdefMap_t *NdefMap, 374 uint8_t *PacketData, 375 uint32_t *PacketDataLength, 376 uint8_t Offset) 377 { 378 NFCSTATUS Result = NFCSTATUS_SUCCESS; 379 uint8_t TempByteVal = 0; 380 /* Copy user buffer to the context */ 381 NdefMap->ApduBuffer = PacketData; 382 /* Copy user length to the context */ 383 NdefMap->ApduBufferSize = *PacketDataLength; 384 /* Index to know the length written */ 385 NdefMap->ApduBuffIndex = PH_FRINFC_TOPAZ_VAL0; 386 /* Update the user memory size to a context variable */ 387 NdefMap->WrNdefPacketLength = PacketDataLength; 388 /* Number of bytes written to the card is zero. 389 This variable returns the number of bytes written 390 to the card. */ 391 *NdefMap->WrNdefPacketLength = PH_FRINFC_TOPAZ_VAL0; 392 /* Update the CR index to know from which operation completion 393 routine has to be called */ 394 NdefMap->TopazContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_WR_NDEF; 395 /* Store the offset in the context */ 396 NdefMap->Offset = Offset; 397 398 399 if( (Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN) || 400 (NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_READ_OPE)) 401 { 402 NdefMap->Offset = PH_FRINFC_NDEFMAP_SEEK_BEGIN; 403 /* Initialise current block and byte number */ 404 NdefMap->TopazContainer.CurrentBlock = PH_FRINFC_TOPAZ_VAL1; 405 NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL0; 406 /* State has to be changed */ 407 NdefMap->State = PH_FRINFC_TOPAZ_STATE_READALL; 408 /* Topaz command = READALL */ 409 410 #ifdef TOPAZ_RAW_SUPPORT 411 NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw; 412 NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READALL; 413 #else 414 #ifdef PH_HAL4_ENABLE 415 NdefMap->Cmd.JewelCmd = phHal_eJewel_ReadAll; 416 #else 417 NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelReadAll; 418 #endif 419 #endif /* #ifdef TOPAZ_RAW_SUPPORT */ 420 NdefMap->TopazContainer.ReadWriteCompleteFlag = 421 PH_FRINFC_TOPAZ_FLAG0; 422 NdefMap->TopazContainer.RemainingSize = NdefMap->CardMemSize; 423 TempByteVal = NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1]; 424 } 425 else 426 { 427 /* State has to be changed */ 428 NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE; 429 /* copy the user data to write into the card */ 430 TempByteVal = NdefMap->ApduBuffer[NdefMap->ApduBuffIndex]; 431 } 432 433 /* Update the previous operation to write operation */ 434 NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_WRITE_OPE; 435 if((Offset == PH_FRINFC_NDEFMAP_SEEK_CUR) && 436 (NdefMap->TopazContainer.ReadWriteCompleteFlag == 437 PH_FRINFC_TOPAZ_FLAG1)) 438 { 439 /* Offset = Current, but the read has reached the End of Card */ 440 Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, 441 NFCSTATUS_EOF_NDEF_CONTAINER_REACHED); 442 } 443 else 444 { 445 /* Check the block */ 446 phFriNfc_Tpz_H_BlkChk(NdefMap); 447 /* if offset is begin then call READALL else start writing */ 448 Result = ((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN)? 449 phFriNfc_Tpz_H_RdBytes(NdefMap, NdefMap->TopazContainer.CurrentBlock, 450 NdefMap->TopazContainer.ByteNumber): 451 phFriNfc_Tpz_H_WrAByte(NdefMap, NdefMap->TopazContainer.CurrentBlock, 452 NdefMap->TopazContainer.ByteNumber,TempByteVal)); 453 } 454 455 return Result; 456 } 457 458 459 /*! 460 * \brief Completion Routine, Processing function, needed to avoid long blocking. 461 * \note The lower (Overlapped HAL) layer must register a pointer to this function as a Completion 462 * Routine in order to be able to notify the component that an I/O has finished and data are 463 * ready to be processed. 464 * 465 */ 466 467 void phFriNfc_TopazMap_Process( void *Context, 468 NFCSTATUS Status) 469 { 470 471 phFriNfc_NdefMap_t *psNdefMap = NULL; 472 473 #ifdef TOPAZ_RF_ERROR_WORKAROUND 474 475 static uint8_t rf_error_state = 0; 476 477 #endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */ 478 479 psNdefMap = (phFriNfc_NdefMap_t *)Context; 480 481 if ((Status & PHNFCSTBLOWER) == (NFCSTATUS_SUCCESS & PHNFCSTBLOWER)) 482 { 483 switch (psNdefMap->State) 484 { 485 case PH_FRINFC_TOPAZ_STATE_WRITE: 486 { 487 Status = phFriNfc_Tpz_H_ProWrUsrData (psNdefMap); 488 break; 489 } 490 491 case PH_FRINFC_TOPAZ_STATE_READID: 492 { 493 Status = phFriNfc_Tpz_H_ProReadID (psNdefMap); 494 break; 495 } 496 497 case PH_FRINFC_TOPAZ_STATE_READALL: 498 { 499 Status = phFriNfc_Tpz_H_ProReadAll (psNdefMap); 500 break; 501 } 502 503 case PH_FRINFC_TOPAZ_STATE_WRITE_NMN: 504 { 505 Status = phFriNfc_Tpz_H_ProWrNMN (psNdefMap); 506 break; 507 } 508 509 case PH_FRINFC_TOPAZ_STATE_WRITE_L_TLV: 510 { 511 Status = phFriNfc_Tpz_H_ProWrTLV (psNdefMap); 512 break; 513 } 514 515 case PH_FRINFC_TOPAZ_STATE_WR_CC_OR_TLV: 516 { 517 Status = phFriNfc_Tpz_H_ProCCTLV (psNdefMap); 518 break; 519 } 520 521 #ifdef TOPAZ_RF_ERROR_WORKAROUND 522 523 case PH_FRINFC_TOPAZ_STATE_RF_ERROR_READ: 524 { 525 Status = phFriNfc_Tpz_H_CheckWrittenData (psNdefMap, 526 rf_error_state); 527 break; 528 } 529 530 #endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */ 531 532 default: 533 { 534 Status = PHNFCSTVAL (CID_FRI_NFC_NDEF_MAP, 535 NFCSTATUS_INVALID_DEVICE_REQUEST); 536 break; 537 } 538 } 539 } 540 else 541 { 542 #ifdef TOPAZ_RF_ERROR_WORKAROUND 543 544 if ((FRINFC_RF_TIMEOUT_89 == PHNFCSTATUS (Status)) || 545 (FRINFC_RF_TIMEOUT_90 == PHNFCSTATUS (Status)) || 546 (NFCSTATUS_RF_TIMEOUT == PHNFCSTATUS (Status))) 547 { 548 uint8_t byte_number = 0; 549 uint8_t block_number = 0; 550 551 rf_error_state = psNdefMap->State; 552 553 #ifdef TOPAZ_RAW_SUPPORT 554 555 *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_READ; 556 557 #else 558 559 #ifdef PH_HAL4_ENABLE 560 561 psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read1; 562 563 #else 564 565 psNdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead1; 566 567 #endif /* #ifdef PH_HAL4_ENABLE */ 568 569 #endif /* #ifdef TOPAZ_RAW_SUPPORT */ 570 571 /* Update the state variable to the new work around state*/ 572 psNdefMap->State = PH_FRINFC_TOPAZ_STATE_RF_ERROR_READ; 573 574 /* Switch is used to know, if the error occured during WRITE or READ */ 575 switch (rf_error_state) 576 { 577 case PH_FRINFC_TOPAZ_STATE_WRITE_NMN: 578 { 579 /* Block and byte number is updated for NMN */ 580 byte_number = PH_FRINFC_TOPAZ_VAL0; 581 block_number = PH_FRINFC_TOPAZ_VAL1; 582 break; 583 } 584 585 case PH_FRINFC_TOPAZ_STATE_WRITE_L_TLV: 586 { 587 /* Get the L field of the TLV block */ 588 block_number = (uint8_t)(((psNdefMap->TLVStruct.NdefTLVByte + 589 PH_FRINFC_TOPAZ_VAL1) > 590 PH_FRINFC_TOPAZ_VAL7)? 591 (psNdefMap->TLVStruct.NdefTLVBlock + 592 PH_FRINFC_TOPAZ_VAL1): 593 psNdefMap->TLVStruct.NdefTLVBlock); 594 /* Get the L byte */ 595 byte_number = (uint8_t)((psNdefMap->TLVStruct.NdefTLVByte + 596 PH_FRINFC_TOPAZ_VAL1) % 597 PH_FRINFC_TOPAZ_VAL8); 598 break; 599 } 600 601 case PH_FRINFC_TOPAZ_STATE_WR_CC_OR_TLV: 602 { 603 switch (psNdefMap->TopazContainer.InternalState) 604 { 605 case PH_FRINFC_TOPAZ_WR_CC_BYTE0: 606 { 607 /* Block and byte number is updated for the CC byte 0 */ 608 block_number = (uint8_t)PH_FRINFC_TOPAZ_VAL1; 609 byte_number = (uint8_t)PH_FRINFC_TOPAZ_VAL0; 610 break; 611 } 612 613 case PH_FRINFC_TOPAZ_WR_CC_BYTE1: 614 { 615 /* Block and byte number is updated for the CC byte 1 */ 616 block_number = (uint8_t)PH_FRINFC_TOPAZ_VAL1; 617 byte_number = (uint8_t)PH_FRINFC_TOPAZ_VAL1; 618 break; 619 } 620 621 case PH_FRINFC_TOPAZ_WR_CC_BYTE2: 622 { 623 /* Block and byte number is updated for the CC byte 2 */ 624 block_number = (uint8_t)PH_FRINFC_TOPAZ_VAL1; 625 byte_number = (uint8_t)PH_FRINFC_TOPAZ_VAL2; 626 break; 627 } 628 629 case PH_FRINFC_TOPAZ_WR_CC_BYTE3: 630 { 631 /* Block and byte number is updated for the CC byte 3 */ 632 block_number = (uint8_t)PH_FRINFC_TOPAZ_VAL1; 633 byte_number = (uint8_t)PH_FRINFC_TOPAZ_VAL3; 634 break; 635 } 636 637 case PH_FRINFC_TOPAZ_WR_T_OF_TLV: 638 { 639 /* Block and byte number is updated for the Type field of the TLV */ 640 block_number = psNdefMap->TLVStruct.NdefTLVBlock; 641 byte_number = (uint8_t)psNdefMap->TLVStruct.NdefTLVByte; 642 break; 643 } 644 645 default: 646 { 647 /* Do nothing */ 648 break; 649 } 650 } /* switch (psNdefMap->TopazContainer.InternalState) */ 651 break; 652 } 653 654 case PH_FRINFC_TOPAZ_STATE_WRITE: 655 { 656 /* Block and byte number is updated for the written error data */ 657 block_number = psNdefMap->TopazContainer.CurrentBlock; 658 byte_number = psNdefMap->TopazContainer.ByteNumber; 659 break; 660 } 661 662 default: 663 { 664 /* Error occured is not during WRITE, so update 665 state variable to the previous state */ 666 psNdefMap->State = rf_error_state; 667 break; 668 } 669 } /* switch (rf_error_state) */ 670 671 /* The below check is added, to know if the error is for 672 the WRITE or READ scenario, 673 If the error is for READ, then state variable is not updated 674 If the error is for WRITE, then state variable is updated with 675 PH_FRINFC_TOPAZ_STATE_RF_ERROR_READ value */ 676 if (PH_FRINFC_TOPAZ_STATE_RF_ERROR_READ == psNdefMap->State) 677 { 678 /* Read the data with the updated block and byte number */ 679 Status = phFriNfc_Tpz_H_RdBytes (psNdefMap, block_number, 680 byte_number); 681 } 682 } 683 684 #endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */ 685 } 686 687 /* Call Completion Routine, if Status != PENDING */ 688 if (NFCSTATUS_PENDING != Status) 689 { 690 phFriNfc_Tpz_H_Complete(psNdefMap, Status); 691 } 692 } 693 694 695 #ifdef TOPAZ_RF_ERROR_WORKAROUND 696 697 static 698 NFCSTATUS 699 phFriNfc_Tpz_H_CheckWrittenData ( 700 phFriNfc_NdefMap_t *psNdefMap, 701 uint8_t state_rf_error) 702 { 703 NFCSTATUS result = NFCSTATUS_SUCCESS; 704 705 switch (state_rf_error) 706 { 707 case PH_FRINFC_TOPAZ_STATE_WRITE: 708 { 709 result = phFriNfc_Tpz_H_ProWrUsrData (psNdefMap); 710 break; 711 } 712 713 case PH_FRINFC_TOPAZ_STATE_WRITE_NMN: 714 { 715 result = phFriNfc_Tpz_H_ProWrNMN (psNdefMap); 716 break; 717 } 718 719 case PH_FRINFC_TOPAZ_STATE_WRITE_L_TLV: 720 { 721 result = phFriNfc_Tpz_H_ProWrTLV (psNdefMap); 722 break; 723 } 724 725 case PH_FRINFC_TOPAZ_STATE_WR_CC_OR_TLV: 726 { 727 result = phFriNfc_Tpz_H_ProCCTLV (psNdefMap); 728 break; 729 } 730 731 default: 732 { 733 break; 734 } 735 } 736 737 return result; 738 } 739 740 741 #endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */ 742 743 static NFCSTATUS phFriNfc_Tpz_H_RdBytes(phFriNfc_NdefMap_t *NdefMap, 744 uint16_t BlockNo, 745 uint16_t ByteNo) 746 { 747 NFCSTATUS Result = NFCSTATUS_SUCCESS; 748 #ifdef TOPAZ_RAW_SUPPORT 749 uint8_t index = 0; 750 #endif /* #ifdef TOPAZ_RAW_SUPPORT */ 751 752 /* set the data for additional data exchange*/ 753 NdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = PH_FRINFC_TOPAZ_VAL0; 754 NdefMap->psDepAdditionalInfo.DepFlags.NADPresent = PH_FRINFC_TOPAZ_VAL0; 755 NdefMap->psDepAdditionalInfo.NAD = PH_FRINFC_TOPAZ_VAL0; 756 757 NdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_TopazMap_Process; 758 NdefMap->MapCompletionInfo.Context = NdefMap; 759 760 *NdefMap->SendRecvLength = NdefMap->TempReceiveLength; 761 762 /* Depending on the jewel command, the send length is decided */ 763 #ifdef TOPAZ_RAW_SUPPORT 764 switch(NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0]) 765 #else 766 switch(NdefMap->Cmd.JewelCmd) 767 #endif /* #ifdef TOPAZ_RAW_SUPPORT */ 768 { 769 770 #ifdef TOPAZ_RAW_SUPPORT 771 case PH_FRINFC_TOPAZ_CMD_READID: 772 #else 773 #ifdef PH_HAL4_ENABLE 774 case phHal_eJewel_RID: 775 #else 776 case phHal_eJewelCmdListJewelRid: 777 #endif 778 #endif /* #ifdef TOPAZ_RAW_SUPPORT */ 779 780 #ifdef TOPAZ_RAW_SUPPORT 781 NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw; 782 /*Copy command to Send Buffer*/ 783 NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READID; 784 index ++; 785 786 /*Copy UID of the tag to Send Buffer*/ 787 (void)memset(&(NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1]), 788 0x00,(0x06)); 789 index = index + 0x06; 790 791 /* Update the length of the command buffer*/ 792 NdefMap->SendLength = index; 793 #else 794 /* For READ ID and READ ALL, send length is 0 */ 795 NdefMap->SendLength = PH_FRINFC_TOPAZ_VAL0; 796 #endif /* #ifdef TOPAZ_RAW_SUPPORT */ 797 break; 798 799 #ifdef TOPAZ_RAW_SUPPORT 800 case PH_FRINFC_TOPAZ_CMD_READALL: 801 #else 802 #ifdef PH_HAL4_ENABLE 803 case phHal_eJewel_ReadAll: 804 #else 805 case phHal_eJewelCmdListJewelReadAll: 806 #endif 807 #endif /* #ifdef TOPAZ_RAW_SUPPORT */ 808 809 #ifdef TOPAZ_RAW_SUPPORT 810 NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw; 811 /*Copy command to Send Buffer*/ 812 NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READALL; 813 index ++; 814 815 /*Copy 0x00 to Send Buffer*/ 816 NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1] = 0x00; 817 index ++; 818 NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2] = 0x00; 819 index ++; 820 821 /*Copy UID of the tag to Send Buffer*/ 822 (void)memcpy(&(NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL3]), 823 &(NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid), 824 (NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.UidLength)); 825 826 index = index + NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.UidLength; 827 828 /* Update the length of the command buffer*/ 829 NdefMap->SendLength = index; 830 #else 831 /* For READ ID and READ ALL, send length is 0 */ 832 NdefMap->SendLength = PH_FRINFC_TOPAZ_VAL0; 833 #endif /* #ifdef TOPAZ_RAW_SUPPORT */ 834 break; 835 836 #ifdef TOPAZ_RAW_SUPPORT 837 case PH_FRINFC_TOPAZ_CMD_READ: 838 #else 839 #ifdef PH_HAL4_ENABLE 840 case phHal_eJewel_Read1: 841 #else 842 case phHal_eJewelCmdListJewelRead1: 843 #endif 844 845 #endif /* #ifdef TOPAZ_RAW_SUPPORT */ 846 847 #ifdef TOPAZ_RAW_SUPPORT 848 NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw; 849 /*Copy command to Send Buffer*/ 850 NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READ; 851 index ++; 852 853 /*Copy Address to Send Buffer*/ 854 /* Calculate send length 855 7 | 6 5 4 3 | 2 1 0 | 856 | block no | byte no | 857 */ 858 NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1] = 859 (uint8_t)((BlockNo << PH_FRINFC_TOPAZ_SHIFT3) + 860 ByteNo); 861 index ++; 862 /*Copy 0x00 to Send Buffer*/ 863 NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2] = 0x00; 864 index ++; 865 866 /*Copy UID of the tag to Send Buffer*/ 867 (void)memcpy(&(NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL3]), 868 &(NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid), 869 (NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.UidLength)); 870 index = index + NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.UidLength; 871 872 /* Update the length of the command buffer*/ 873 NdefMap->SendLength = index; 874 #else 875 /* Calculate send length 876 7 | 6 5 4 3 | 2 1 0 | 877 | block no | byte no | 878 */ 879 NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = 880 (uint8_t)((BlockNo << PH_FRINFC_TOPAZ_SHIFT3) + 881 ByteNo); 882 NdefMap->SendLength = PH_FRINFC_TOPAZ_VAL1; 883 #endif /* #ifdef TOPAZ_RAW_SUPPORT */ 884 885 break; 886 #ifdef TOPAZ_RAW_SUPPORT 887 #else 888 #ifdef PH_HAL4_ENABLE 889 case phHal_eJewel_Read: 890 NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = 0x00; 891 NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1] = 0x00; 892 NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2] = 104; 893 NdefMap->SendLength = 3; 894 break; 895 #endif 896 #endif /* #ifdef TOPAZ_RAW_SUPPORT */ 897 898 default: 899 Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, 900 NFCSTATUS_INVALID_DEVICE_REQUEST); 901 } 902 903 if(Result == NFCSTATUS_SUCCESS) 904 { 905 /* Call the Overlapped HAL Transceive function */ 906 Result = phFriNfc_OvrHal_Transceive( NdefMap->LowerDevice, 907 &NdefMap->MapCompletionInfo, 908 NdefMap->psRemoteDevInfo, 909 NdefMap->Cmd, 910 &NdefMap->psDepAdditionalInfo, 911 NdefMap->SendRecvBuf, 912 NdefMap->SendLength, 913 NdefMap->SendRecvBuf, 914 NdefMap->SendRecvLength); 915 } 916 return Result; 917 } 918 919 static NFCSTATUS phFriNfc_Tpz_H_WrAByte(phFriNfc_NdefMap_t *NdefMap, 920 uint16_t BlockNo, 921 uint16_t ByteNo, 922 uint8_t ByteVal 923 ) 924 { 925 NFCSTATUS Result = NFCSTATUS_SUCCESS; 926 uint8_t index = 0; 927 928 929 PHNFC_UNUSED_VARIABLE(ByteVal); 930 /* set the data for additional data exchange*/ 931 NdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = PH_FRINFC_TOPAZ_VAL0; 932 NdefMap->psDepAdditionalInfo.DepFlags.NADPresent = PH_FRINFC_TOPAZ_VAL0; 933 NdefMap->psDepAdditionalInfo.NAD = PH_FRINFC_TOPAZ_VAL0; 934 935 NdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_TopazMap_Process; 936 NdefMap->MapCompletionInfo.Context = NdefMap; 937 938 *NdefMap->SendRecvLength = NdefMap->TempReceiveLength; 939 /* Command used to write 1 byte */ 940 #ifdef TOPAZ_RAW_SUPPORT 941 NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw; 942 #else 943 #ifdef PH_HAL4_ENABLE 944 NdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E; 945 #else 946 NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelWriteErase1; 947 #endif 948 #endif /* #ifdef TOPAZ_RAW_SUPPORT */ 949 950 #ifdef TOPAZ_RAW_SUPPORT 951 /*Copy command to Send Buffer*/ 952 NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_WRITE_1E; 953 index ++; 954 955 /*Copy Address to Send Buffer*/ 956 /* Calculate send length 957 7 | 6 5 4 3 | 2 1 0 | 958 | block no | byte no | 959 */ 960 NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1] = 961 (uint8_t)((BlockNo << PH_FRINFC_TOPAZ_SHIFT3) + 962 ByteNo); 963 index ++; 964 /*Copy Data byte to Send Buffer*/ 965 NdefMap->SendRecvBuf[index] = ByteVal; 966 index ++; 967 968 /*Copy UID of the tag to Send Buffer*/ 969 (void)memcpy(&(NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL3]), 970 &(NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid), 971 (NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.UidLength)); 972 index = index + NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.UidLength; 973 974 /* Update the length of the command buffer*/ 975 NdefMap->SendLength = index; 976 977 #else 978 /* Depending on the jewel command, the send length is decided */ 979 /* Calculate send length 980 7 | 6 5 4 3 | 2 1 0 | 981 | block no | byte no | 982 */ 983 NdefMap->SendRecvBuf[index] = 984 (uint8_t)((BlockNo << PH_FRINFC_TOPAZ_SHIFT3) + 985 ByteNo); 986 index ++; 987 NdefMap->SendRecvBuf[index] = ByteVal; 988 index ++; 989 NdefMap->SendLength = PH_FRINFC_TOPAZ_VAL2; 990 991 #endif /* #ifdef TOPAZ_RAW_SUPPORT */ 992 993 /* Call the Overlapped HAL Transceive function */ 994 Result = phFriNfc_OvrHal_Transceive( NdefMap->LowerDevice, 995 &NdefMap->MapCompletionInfo, 996 NdefMap->psRemoteDevInfo, 997 NdefMap->Cmd, 998 &NdefMap->psDepAdditionalInfo, 999 NdefMap->SendRecvBuf, 1000 NdefMap->SendLength, 1001 NdefMap->SendRecvBuf, 1002 NdefMap->SendRecvLength); 1003 1004 return Result; 1005 } 1006 1007 static NFCSTATUS phFriNfc_Tpz_H_ProReadID(phFriNfc_NdefMap_t *NdefMap) 1008 { 1009 NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, 1010 NFCSTATUS_INVALID_RECEIVE_LENGTH); 1011 1012 if(((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] & 1013 PH_FRINFC_TOPAZ_HEADROM0_CHK) == PH_FRINFC_TOPAZ_HEADROM0_VAL) && 1014 (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL6)) 1015 { 1016 /* Copy UID to the context, Used when the READ ALL command is used */ 1017 (void)memcpy(NdefMap->TopazContainer.UID, 1018 &NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2], 1019 PH_FRINFC_TOPAZ_VAL4); 1020 1021 /* State has to be changed */ 1022 NdefMap->State = PH_FRINFC_TOPAZ_STATE_READALL; 1023 /* Topaz command = READALL */ 1024 #ifdef TOPAZ_RAW_SUPPORT 1025 NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw; 1026 NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READALL; 1027 #else 1028 #ifdef PH_HAL4_ENABLE 1029 NdefMap->Cmd.JewelCmd = phHal_eJewel_ReadAll; 1030 #else 1031 NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelReadAll; 1032 #endif 1033 #endif /* #ifdef TOPAZ_RAW_SUPPORT */ 1034 1035 /* Read all bytes from the card */ 1036 Result = phFriNfc_Tpz_H_RdBytes(NdefMap, NdefMap->TopazContainer.CurrentBlock, 1037 NdefMap->TopazContainer.ByteNumber); 1038 } 1039 1040 return Result; 1041 } 1042 1043 static NFCSTATUS phFriNfc_Tpz_H_ProReadAll(phFriNfc_NdefMap_t *NdefMap) 1044 { 1045 NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, 1046 NFCSTATUS_INVALID_RECEIVE_LENGTH); 1047 int32_t memcompare = PH_FRINFC_TOPAZ_VAL0; 1048 1049 /* Compare the UID of READ ALL command with the stored UID */ 1050 #ifdef PH_HAL4_ENABLE 1051 if ((NdefMap->TopazContainer.UID[0] == NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2]) && 1052 (NdefMap->TopazContainer.UID[1] == NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2 + 1]) && 1053 (NdefMap->TopazContainer.UID[2] == NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2 + 2]) && 1054 (NdefMap->TopazContainer.UID[3] == NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2 + 3])) 1055 { 1056 memcompare = PH_FRINFC_TOPAZ_VAL0; 1057 } 1058 else 1059 { 1060 memcompare = PH_FRINFC_TOPAZ_VAL1; 1061 } 1062 #else 1063 memcompare = memcmp(NdefMap->TopazContainer.UID, 1064 &NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2], 1065 PH_FRINFC_TOPAZ_VAL4); 1066 #endif /* #ifdef PH_HAL4_ENABLE */ 1067 1068 if(((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] & 1069 PH_FRINFC_TOPAZ_HEADROM0_CHK) == PH_FRINFC_TOPAZ_HEADROM0_VAL) && 1070 (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_READALL_RESP) && 1071 (memcompare == PH_FRINFC_TOPAZ_VAL0)) 1072 { 1073 /* Copy 96 bytes from the read/write memory space */ 1074 (void)memcpy(NdefMap->TopazContainer.ReadBuffer, 1075 &NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL10], 1076 PH_FRINFC_TOPAZ_TOTAL_RWBYTES); 1077 1078 /* Check the lock bits and set the card state */ 1079 phFriNfc_Tpz_H_ChkLockBits(NdefMap); 1080 1081 Result = phFriNfc_Tpz_H_CallNxtOp(NdefMap); 1082 } 1083 return Result; 1084 } 1085 1086 static NFCSTATUS phFriNfc_Tpz_H_CallNxtOp(phFriNfc_NdefMap_t *NdefMap) 1087 { 1088 NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, 1089 NFCSTATUS_INVALID_RECEIVE_LENGTH); 1090 /* Depending on the operation (check, read or write ndef), process the 1091 read data */ 1092 switch(NdefMap->PrevOperation) 1093 { 1094 case PH_FRINFC_NDEFMAP_CHECK_OPE: 1095 /* Check the capabilty container values, according 1096 to the spec */ 1097 Result = phFriNfc_Tpz_H_ChkCCinChkNdef(NdefMap); 1098 1099 if (NdefMap->CardState != PH_NDEFMAP_CARD_STATE_INVALID) 1100 { 1101 /* Check the spec version */ 1102 Result = phFriNfc_Tpz_H_ChkSpcVer( NdefMap, 1103 NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL1]); 1104 /* Check the CC header size: Only valid ones are 1105 0x0C for 96 bytes. */ 1106 if ((Result == NFCSTATUS_SUCCESS) && 1107 ( NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL2] <= 1108 PH_FRINFC_TOPAZ_CC_BYTE2_MAX)) 1109 { 1110 Result = phFriNfc_Tpz_H_findNDEFTLV(NdefMap); 1111 /* As there is possibility of either having or not having TLV in 1112 Topaz, no need to send the Actual status to the context*/ 1113 Result = NFCSTATUS_SUCCESS; 1114 } 1115 } 1116 else 1117 { 1118 Result = (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, 1119 NFCSTATUS_INVALID_FORMAT)); 1120 } 1121 break; 1122 1123 case PH_FRINFC_NDEFMAP_READ_OPE: 1124 /* Check the capabilty container values, according 1125 to the spec */ 1126 Result = phFriNfc_Tpz_H_ChkCCBytes(NdefMap); 1127 1128 /* If success, find the ndef TLV */ 1129 Result = ((Result != NFCSTATUS_SUCCESS)? 1130 (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, 1131 NFCSTATUS_INVALID_FORMAT)): 1132 phFriNfc_Tpz_H_findNDEFTLV(NdefMap)); 1133 1134 if(Result == NFCSTATUS_SUCCESS) 1135 { 1136 NdefMap->TopazContainer.ByteNumber += PH_FRINFC_TOPAZ_VAL2; 1137 /* If success, copy the read bytes to the user buffer */ 1138 Result = phFriNfc_Tpz_H_CpDataToUsrBuf(NdefMap); 1139 } 1140 break; 1141 1142 case PH_FRINFC_NDEFMAP_WRITE_OPE: 1143 default: 1144 if((NdefMap->CardState == PH_NDEFMAP_CARD_STATE_READ_WRITE) || 1145 (NdefMap->CardState == PH_NDEFMAP_CARD_STATE_INITIALIZED)) 1146 { 1147 /* Check the capabilty container values, according 1148 to the spec */ 1149 Result = phFriNfc_Tpz_H_ChkCCBytes(NdefMap); 1150 if(Result == NFCSTATUS_SUCCESS) 1151 { 1152 /* Find the NDEF TLV */ 1153 Result = phFriNfc_Tpz_H_findNDEFTLV(NdefMap); 1154 1155 /* Write the TLV */ 1156 NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_T_OF_TLV; 1157 } 1158 else 1159 { 1160 NdefMap->TLVStruct.NdefTLVByte = PH_FRINFC_TOPAZ_VAL4; 1161 NdefMap->TLVStruct.NdefTLVBlock = PH_FRINFC_TOPAZ_VAL1; 1162 NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL4; 1163 /* Write the TLV */ 1164 NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_CC_BYTE0; 1165 } 1166 /* Write CC bytes */ 1167 Result = phFriNfc_Tpz_H_WrCCorTLV(NdefMap); 1168 } 1169 break; 1170 } 1171 return Result; 1172 } 1173 1174 static NFCSTATUS phFriNfc_Tpz_H_ChkCCBytes(phFriNfc_NdefMap_t *NdefMap) 1175 { 1176 NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, 1177 NFCSTATUS_NO_NDEF_SUPPORT); 1178 1179 if(NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL0] == 1180 PH_FRINFC_TOPAZ_CC_BYTE0) 1181 { 1182 /* Check the spec version */ 1183 Result = phFriNfc_Tpz_H_ChkSpcVer( NdefMap, 1184 NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL1]); 1185 /* Check the CC header size: Only valid ones are 1186 0x0C for 96 bytes. */ 1187 Result = ((( NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL2] > 1188 PH_FRINFC_TOPAZ_CC_BYTE2_MAX) || (Result != 1189 NFCSTATUS_SUCCESS))? 1190 (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, 1191 NFCSTATUS_EOF_NDEF_CONTAINER_REACHED)): 1192 Result); 1193 1194 /* Get the read/write card memory size */ 1195 NdefMap->TopazContainer.RemainingSize = 1196 NdefMap->CardMemSize = ((Result == NFCSTATUS_SUCCESS)? 1197 (PH_FRINFC_TOPAZ_MAX_CARD_SZ - PH_FRINFC_TOPAZ_VAL4): 1198 NdefMap->CardMemSize); 1199 1200 /* if the call is from write ndef then check for read write access */ 1201 if(((NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_WRITE_OPE) && 1202 (NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL3] != 1203 PH_FRINFC_TOPAZ_CC_BYTE3_RW) && (Result == NFCSTATUS_SUCCESS))) 1204 { 1205 Result = (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, 1206 NFCSTATUS_INVALID_FORMAT)); 1207 } 1208 1209 /* if the call is from read ndef then check for read only or read write access */ 1210 if(((NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_READ_OPE) && 1211 ((NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL3] != 1212 PH_FRINFC_TOPAZ_CC_BYTE3_RW) && 1213 (NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL3] != 1214 PH_FRINFC_TOPAZ_CC_BYTE3_RO))&& (Result == NFCSTATUS_SUCCESS))) 1215 { 1216 Result = (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, 1217 NFCSTATUS_INVALID_FORMAT)); 1218 } 1219 } 1220 return Result; 1221 } 1222 1223 extern NFCSTATUS phFriNfc_Tpz_H_ChkSpcVer( phFriNfc_NdefMap_t *NdefMap, 1224 uint8_t VersionNo) 1225 { 1226 NFCSTATUS Result = NFCSTATUS_SUCCESS; 1227 uint8_t TagVerNo = VersionNo; 1228 1229 /* To remove "warning (VS C4100) : unreferenced formal parameter" */ 1230 PHNFC_UNUSED_VARIABLE(NdefMap); 1231 1232 if ( TagVerNo == 0 ) 1233 { 1234 /*Return Status Error Invalid Format*/ 1235 Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,NFCSTATUS_INVALID_FORMAT); 1236 } 1237 else 1238 { 1239 /* calculate the major and minor version number of T3VerNo */ 1240 if( (( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM == 1241 PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(TagVerNo ) )&& 1242 ( PH_NFCFRI_NDEFMAP_NFCDEV_MINOR_VER_NUM >= 1243 PH_NFCFRI_NDEFMAP_GET_MINOR_TAG_VERNO(TagVerNo))) || 1244 (( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM == 1245 PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(TagVerNo ) )&& 1246 ( PH_NFCFRI_NDEFMAP_NFCDEV_MINOR_VER_NUM < 1247 PH_NFCFRI_NDEFMAP_GET_MINOR_TAG_VERNO(TagVerNo) ))) 1248 { 1249 Result = PHNFCSTVAL(CID_NFC_NONE,NFCSTATUS_SUCCESS); 1250 } 1251 else 1252 { 1253 if (( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM < 1254 PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(TagVerNo) ) || 1255 ( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM > 1256 PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(TagVerNo))) 1257 { 1258 Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,NFCSTATUS_INVALID_FORMAT); 1259 } 1260 } 1261 } 1262 return Result; 1263 } 1264 1265 static NFCSTATUS phFriNfc_Tpz_H_findNDEFTLV(phFriNfc_NdefMap_t *NdefMap) 1266 { 1267 NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, 1268 NFCSTATUS_NO_NDEF_SUPPORT); 1269 uint8_t index = PH_FRINFC_TOPAZ_VAL4; 1270 1271 /* If remaining size is less than 3 then, there cant be any 1272 TLV present in the card */ 1273 while((index < PH_FRINFC_TOPAZ_TOTAL_RWBYTES) && 1274 (NdefMap->TopazContainer.RemainingSize >= PH_FRINFC_TOPAZ_VAL3)) 1275 { 1276 switch(NdefMap->TopazContainer.ReadBuffer[index]) 1277 { 1278 case PH_FRINFC_TOPAZ_NDEF_T: 1279 /* To get the length field of the TLV */ 1280 index++; 1281 /* Type and length are not data bytes, so to know the exact 1282 remaining size in the card, the below operation is done */ 1283 NdefMap->TopazContainer.RemainingSize -= PH_FRINFC_TOPAZ_VAL2; 1284 /* Set the card state depending on the L value */ 1285 Result = phFriNfc_MapTool_SetCardState(NdefMap, 1286 (uint32_t)NdefMap->TopazContainer.ReadBuffer[index]); 1287 /* Check the TLV is correct */ 1288 if((NdefMap->TopazContainer.ReadBuffer[index] > 1289 NdefMap->TopazContainer.RemainingSize) || 1290 ((NdefMap->TopazContainer.ReadBuffer[index] == 1291 PH_FRINFC_TOPAZ_VAL0) && (NdefMap->PrevOperation == 1292 PH_FRINFC_NDEFMAP_READ_OPE)) || (Result != NFCSTATUS_SUCCESS)) 1293 { 1294 /* L field value cant be greater than the remaining size, so error */ 1295 Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, 1296 NFCSTATUS_NO_NDEF_SUPPORT); 1297 /* To break out of the loop */ 1298 index = PH_FRINFC_TOPAZ_TOTAL_RWBYTES; 1299 } 1300 else 1301 { 1302 /* So remaining size also changes, according to the position of NDEF TLV */ 1303 NdefMap->TLVStruct.BytesRemainLinTLV = 1304 NdefMap->TopazContainer.ReadBuffer[index]; 1305 1306 /* Get the byte number */ 1307 NdefMap->TLVStruct.NdefTLVByte = (uint16_t)((index - PH_FRINFC_TOPAZ_VAL1) % 1308 PH_FRINFC_TOPAZ_VAL8); 1309 /* Get the block number */ 1310 NdefMap->TLVStruct.NdefTLVBlock = (uint8_t)(((index - PH_FRINFC_TOPAZ_VAL1) / 1311 PH_FRINFC_TOPAZ_VAL8) + 1312 PH_FRINFC_TOPAZ_VAL1); 1313 /* TLV found flag is set */ 1314 NdefMap->TLVStruct.NdefTLVFoundFlag = PH_FRINFC_TOPAZ_FLAG1; 1315 /* To know the position of V field in the TLV */ 1316 NdefMap->TopazContainer.ByteNumber = (uint8_t)(((NdefMap->TLVStruct.NdefTLVBlock - 1) * 8) + 1317 NdefMap->TLVStruct.NdefTLVByte); 1318 /* To break out of the loop */ 1319 index = PH_FRINFC_TOPAZ_TOTAL_RWBYTES; 1320 Result = NFCSTATUS_SUCCESS; 1321 } 1322 break; 1323 1324 case PH_FRINFC_TOPAZ_NULL_T: 1325 /* Null TLV, Skip the TLV */ 1326 NdefMap->TopazContainer.RemainingSize--; 1327 index++; 1328 break; 1329 1330 case PH_FRINFC_TOPAZ_TERM_T: 1331 /* No more TLV present in the card, so error */ 1332 index = PH_FRINFC_TOPAZ_TOTAL_RWBYTES; 1333 Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, 1334 NFCSTATUS_NO_NDEF_SUPPORT); 1335 break; 1336 1337 default: 1338 /* Go till the length field of the TLV */ 1339 index++; 1340 /* Type and length is not the data, so to know the exact 1341 remaining size in the card, the below operation is done */ 1342 NdefMap->TopazContainer.RemainingSize -= PH_FRINFC_TOPAZ_VAL2; 1343 if(NdefMap->TopazContainer.ReadBuffer[index] > 1344 NdefMap->TopazContainer.RemainingSize) 1345 { 1346 /* L field value cant be greater than the remaining size, so error */ 1347 index = PH_FRINFC_TOPAZ_TOTAL_RWBYTES; 1348 Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, 1349 NFCSTATUS_NO_NDEF_SUPPORT); 1350 } 1351 else 1352 { 1353 /* Remaining size of the free space available in the card changes, 1354 according to the position of NDEF TLV */ 1355 NdefMap->TopazContainer.RemainingSize = 1356 NdefMap->TopazContainer.RemainingSize - 1357 NdefMap->TopazContainer.ReadBuffer[index]; 1358 1359 /* Get the position of the next TLV */ 1360 index = (uint8_t)(index + 1361 (NdefMap->TopazContainer.ReadBuffer[index] + 1362 PH_FRINFC_TOPAZ_VAL1)); 1363 } 1364 break; 1365 } 1366 } 1367 1368 /* If no Ndef TLV found and operation done is read */ 1369 if((NdefMap->TLVStruct.NdefTLVFoundFlag == PH_FRINFC_TOPAZ_FLAG0) && 1370 (NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_READ_OPE)) 1371 { 1372 Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, 1373 NFCSTATUS_EOF_NDEF_CONTAINER_REACHED); 1374 } 1375 if((NdefMap->TLVStruct.NdefTLVFoundFlag == PH_FRINFC_TOPAZ_FLAG0) && 1376 ((NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_WRITE_OPE) || 1377 (NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_CHECK_OPE))) 1378 { 1379 NdefMap->TLVStruct.NdefTLVByte = PH_FRINFC_TOPAZ_VAL4; 1380 NdefMap->TLVStruct.NdefTLVBlock = PH_FRINFC_TOPAZ_VAL1; 1381 NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL4; 1382 NdefMap->TopazContainer.RemainingSize = PH_FRINFC_TOPAZ_TOTAL_RWBYTES1; 1383 } 1384 return Result; 1385 } 1386 1387 static NFCSTATUS phFriNfc_Tpz_H_CpDataToUsrBuf(phFriNfc_NdefMap_t *NdefMap) 1388 { 1389 NFCSTATUS Result = NFCSTATUS_SUCCESS; 1390 1391 /* Check the the TLV size and the user size */ 1392 if(NdefMap->ApduBufferSize >= 1393 NdefMap->TLVStruct.BytesRemainLinTLV) 1394 { 1395 /* Copy the read bytes to user buffer till the value (V) 1396 of TLV ends */ 1397 (void)memcpy(NdefMap->ApduBuffer, 1398 &(NdefMap->TopazContainer.ReadBuffer[ 1399 NdefMap->TopazContainer.ByteNumber]), 1400 NdefMap->TLVStruct.BytesRemainLinTLV); 1401 1402 /* Update the number of read bytes to the user */ 1403 *(NdefMap->NumOfBytesRead) = 1404 NdefMap->TLVStruct.BytesRemainLinTLV; 1405 /* There is no byte to read */ 1406 NdefMap->TopazContainer.ByteNumber = 1407 PH_FRINFC_TOPAZ_VAL0; 1408 /* No further read is possible */ 1409 NdefMap->TopazContainer.ReadWriteCompleteFlag = 1410 PH_FRINFC_TOPAZ_FLAG1; 1411 /* Remaining size in the card can be greater than length field in 1412 the TLV */ 1413 NdefMap->TopazContainer.RemainingSize = 1414 NdefMap->TopazContainer.RemainingSize - 1415 NdefMap->TLVStruct.BytesRemainLinTLV; 1416 /* TLV has been completely read, no more bytes to read */ 1417 NdefMap->TLVStruct.BytesRemainLinTLV = 1418 PH_FRINFC_TOPAZ_VAL0; 1419 } 1420 else 1421 { 1422 /* Copy read bytes till the user buffer size */ 1423 (void)memcpy(NdefMap->ApduBuffer, 1424 &(NdefMap->TopazContainer.ReadBuffer[ 1425 NdefMap->TopazContainer.ByteNumber]), 1426 NdefMap->ApduBufferSize); 1427 1428 /* Update the number of read bytes to the user */ 1429 *(NdefMap->NumOfBytesRead) = 1430 NdefMap->ApduBufferSize; 1431 /* Get the next byte number to read */ 1432 NdefMap->TopazContainer.ByteNumber = 1433 (uint8_t)(NdefMap->TopazContainer.ByteNumber + 1434 NdefMap->ApduBufferSize); 1435 /* Free space left in the card */ 1436 NdefMap->TopazContainer.RemainingSize 1437 = NdefMap->TopazContainer.RemainingSize 1438 - (uint16_t)NdefMap->ApduBufferSize; 1439 /* Bytes left in the TLV */ 1440 NdefMap->TLVStruct.BytesRemainLinTLV = 1441 NdefMap->TLVStruct.BytesRemainLinTLV - 1442 (uint16_t)NdefMap->ApduBufferSize; 1443 } 1444 return Result; 1445 } 1446 1447 static NFCSTATUS phFriNfc_Tpz_H_ProWrNMN(phFriNfc_NdefMap_t *NdefMap) 1448 { 1449 NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, 1450 NFCSTATUS_INVALID_RECEIVE_LENGTH); 1451 uint8_t BlockNo = PH_FRINFC_TOPAZ_VAL0, 1452 ByteNo = PH_FRINFC_TOPAZ_VAL0; 1453 1454 if((NdefMap->TopazContainer.InternalState == 1455 PH_FRINFC_TOPAZ_WR_NMN_0) && 1456 (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == 1457 PH_FRINFC_TOPAZ_VAL0) && 1458 (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) 1459 { 1460 NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE_L_TLV; 1461 /* Get the L field of the TLV block */ 1462 BlockNo = (uint8_t)(((NdefMap->TLVStruct.NdefTLVByte + PH_FRINFC_TOPAZ_VAL1) > 1463 PH_FRINFC_TOPAZ_VAL7)? 1464 (NdefMap->TLVStruct.NdefTLVBlock + PH_FRINFC_TOPAZ_VAL1): 1465 NdefMap->TLVStruct.NdefTLVBlock); 1466 /* Get the L byte */ 1467 ByteNo = (uint8_t)((NdefMap->TLVStruct.NdefTLVByte + PH_FRINFC_TOPAZ_VAL1) % 1468 PH_FRINFC_TOPAZ_VAL8); 1469 1470 1471 /* Here the NMN is written 0, so internal state is used */ 1472 NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_L_TLV_0; 1473 /* Write the length value = 0x00 , Write L field of TLV = 0 inside this*/ 1474 Result = phFriNfc_Tpz_H_WrAByte( NdefMap, BlockNo, ByteNo, 1475 PH_FRINFC_TOPAZ_VAL0); 1476 } 1477 else 1478 { 1479 if((NdefMap->TopazContainer.InternalState == 1480 PH_FRINFC_TOPAZ_WR_NMN_E1) && 1481 (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == 1482 PH_FRINFC_TOPAZ_CC_BYTE0) && 1483 (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) 1484 { 1485 /* Card state is initialised or invalid */ 1486 NdefMap->CardState = (uint8_t)((NdefMap->CardState == 1487 PH_NDEFMAP_CARD_STATE_INITIALIZED)? 1488 PH_NDEFMAP_CARD_STATE_READ_WRITE: 1489 NdefMap->CardState); 1490 /* update the length to the user */ 1491 *NdefMap->WrNdefPacketLength = NdefMap->ApduBuffIndex; 1492 Result = NFCSTATUS_SUCCESS; 1493 } 1494 } 1495 return Result; 1496 } 1497 1498 static NFCSTATUS phFriNfc_Tpz_H_ProWrTLV(phFriNfc_NdefMap_t *NdefMap) 1499 { 1500 NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, 1501 NFCSTATUS_INVALID_RECEIVE_LENGTH); 1502 if((NdefMap->TopazContainer.InternalState == 1503 PH_FRINFC_TOPAZ_WR_L_TLV_0) && 1504 (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == 1505 PH_FRINFC_TOPAZ_VAL0) && 1506 (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) 1507 { 1508 /* state is writing user data to the card */ 1509 NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE; 1510 1511 NdefMap->TopazContainer.ByteNumber++; 1512 /* Check the byte number */ 1513 phFriNfc_Tpz_H_BlkChk(NdefMap); 1514 1515 /* Write data to the specified location */ 1516 /* Write the data to the card from the user buffer */ 1517 Result = phFriNfc_Tpz_H_WrAByte( NdefMap, 1518 NdefMap->TopazContainer.CurrentBlock, 1519 NdefMap->TopazContainer.ByteNumber, 1520 NdefMap->ApduBuffer[NdefMap->ApduBuffIndex] 1521 ); 1522 } 1523 else 1524 { 1525 if((NdefMap->TopazContainer.InternalState == 1526 PH_FRINFC_TOPAZ_WR_L_TLV) && 1527 (((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN) && 1528 (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == 1529 NdefMap->ApduBuffIndex)) || 1530 ((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_CUR) && 1531 (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == 1532 (NdefMap->ApduBuffIndex + NdefMap->TLVStruct.BytesRemainLinTLV)))) && 1533 (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) 1534 { 1535 /* Update the L value in the context */ 1536 NdefMap->TLVStruct.BytesRemainLinTLV = 1537 ((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN)? 1538 NdefMap->ApduBuffIndex: 1539 (NdefMap->TLVStruct.BytesRemainLinTLV + NdefMap->ApduBuffIndex)); 1540 1541 /* Write 0xE1 in block number = 1 and byte number = 0 */ 1542 Result = phFriNfc_Tpz_H_WrByte0ValE1(NdefMap); 1543 } 1544 } 1545 return Result; 1546 } 1547 1548 static NFCSTATUS phFriNfc_Tpz_H_ProWrUsrData(phFriNfc_NdefMap_t *NdefMap) 1549 { 1550 NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, 1551 NFCSTATUS_INVALID_RECEIVE_LENGTH); 1552 /* send buffer should be equal to receive buffer */ 1553 if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == 1554 NdefMap->ApduBuffer[NdefMap->ApduBuffIndex]) && 1555 (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) 1556 { 1557 /* Increment the index */ 1558 NdefMap->ApduBuffIndex += PH_FRINFC_TOPAZ_VAL1; 1559 1560 /* Remaining space left in the card is less by one */ 1561 NdefMap->TopazContainer.RemainingSize -= PH_FRINFC_TOPAZ_VAL1; 1562 1563 /* Increment the byte number */ 1564 NdefMap->TopazContainer.ByteNumber++; 1565 1566 /* Check the block number */ 1567 phFriNfc_Tpz_H_BlkChk(NdefMap); 1568 1569 /* check for the user space or the card size */ 1570 if((NdefMap->ApduBufferSize == NdefMap->ApduBuffIndex) || 1571 (NdefMap->TopazContainer.RemainingSize == PH_FRINFC_TOPAZ_VAL0)) 1572 { 1573 /* Set write complete, if the end of card is reached */ 1574 NdefMap->TopazContainer.ReadWriteCompleteFlag = (uint8_t) 1575 ((NdefMap->TopazContainer.RemainingSize == PH_FRINFC_TOPAZ_VAL0)? 1576 PH_FRINFC_TOPAZ_FLAG1:PH_FRINFC_TOPAZ_FLAG0); 1577 1578 Result = phFriNfc_Tpz_H_WrLByte(NdefMap); 1579 } 1580 else 1581 { 1582 /* State is continued to be in write */ 1583 NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE; 1584 1585 /* Write the byte to the specified location , and Byte to write */ 1586 Result = phFriNfc_Tpz_H_WrAByte(NdefMap, NdefMap->TopazContainer.CurrentBlock, 1587 NdefMap->TopazContainer.ByteNumber, 1588 NdefMap->ApduBuffer[NdefMap->ApduBuffIndex] 1589 ); 1590 } 1591 } 1592 return Result; 1593 } 1594 1595 static NFCSTATUS phFriNfc_Tpz_H_WrLByte(phFriNfc_NdefMap_t *NdefMap) 1596 { 1597 NFCSTATUS Result = NFCSTATUS_SUCCESS; 1598 uint8_t BlockNo = PH_FRINFC_TOPAZ_VAL0, 1599 ByteNo = PH_FRINFC_TOPAZ_VAL0; 1600 uint8_t TempByteVal = 0; 1601 BlockNo = (uint8_t)(((NdefMap->TLVStruct.NdefTLVByte + 1602 PH_FRINFC_TOPAZ_VAL1) > 1603 PH_FRINFC_TOPAZ_VAL7)? 1604 (NdefMap->TLVStruct.NdefTLVBlock + 1605 PH_FRINFC_TOPAZ_VAL1): 1606 NdefMap->TLVStruct.NdefTLVBlock); 1607 1608 ByteNo = (uint8_t)((NdefMap->TLVStruct.NdefTLVByte + 1609 PH_FRINFC_TOPAZ_VAL1) % PH_FRINFC_TOPAZ_VAL8); 1610 /* Update L field */ 1611 NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE_L_TLV; 1612 /* Internal state for write */ 1613 NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_L_TLV; 1614 /* Update the length field depending on the offset */ 1615 TempByteVal = (uint8_t) 1616 ((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN)? 1617 NdefMap->ApduBuffIndex: 1618 (NdefMap->ApduBuffIndex + 1619 NdefMap->TLVStruct.BytesRemainLinTLV)); 1620 /* Write the L field */ 1621 Result = phFriNfc_Tpz_H_WrAByte(NdefMap, BlockNo, ByteNo,TempByteVal); 1622 return Result; 1623 } 1624 1625 static NFCSTATUS phFriNfc_Tpz_H_WrByte0ValE1(phFriNfc_NdefMap_t *NdefMap) 1626 { 1627 NFCSTATUS Result = NFCSTATUS_SUCCESS; 1628 1629 /* Update L field */ 1630 NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE_NMN; 1631 /* Internal state for writing 0xE1 */ 1632 NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_NMN_E1; 1633 /* Update the length field depending on the offset */ 1634 /* Write the L field */ 1635 Result = phFriNfc_Tpz_H_WrAByte(NdefMap, PH_FRINFC_TOPAZ_VAL1, 1636 PH_FRINFC_TOPAZ_VAL0,PH_FRINFC_TOPAZ_CC_BYTE0); 1637 return Result; 1638 } 1639 1640 static void phFriNfc_Tpz_H_Complete(phFriNfc_NdefMap_t *NdefMap, 1641 NFCSTATUS Status) 1642 { 1643 /* set the state back to the Reset_Init state*/ 1644 NdefMap->State = PH_FRINFC_NDEFMAP_STATE_RESET_INIT; 1645 1646 /* set the completion routine*/ 1647 NdefMap->CompletionRoutine[NdefMap->TopazContainer.CRIndex]. 1648 CompletionRoutine(NdefMap->CompletionRoutine->Context, Status); 1649 } 1650 1651 static void phFriNfc_Tpz_H_BlkChk(phFriNfc_NdefMap_t *NdefMap) 1652 { 1653 NdefMap->TopazContainer.CurrentBlock = 1654 (uint8_t)((NdefMap->TopazContainer.ByteNumber > 1655 PH_FRINFC_TOPAZ_VAL7)? 1656 (NdefMap->TopazContainer.CurrentBlock + 1657 PH_FRINFC_TOPAZ_VAL1): 1658 NdefMap->TopazContainer.CurrentBlock); 1659 1660 NdefMap->TopazContainer.ByteNumber = (uint8_t)(NdefMap->TopazContainer.ByteNumber % 1661 PH_FRINFC_TOPAZ_VAL8); 1662 } 1663 1664 static NFCSTATUS phFriNfc_Tpz_H_ChkCCinChkNdef(phFriNfc_NdefMap_t *NdefMap) 1665 { 1666 NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, 1667 NFCSTATUS_NO_NDEF_SUPPORT); 1668 1669 if(NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL0] == 1670 PH_FRINFC_TOPAZ_CC_BYTE0) 1671 { 1672 /* Check the most significant nibble of byte 3 (RWA) = 0 */ 1673 Result = (((NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL3] & 1674 PH_FRINFC_TOPAZ_BYTE3_MSB)== PH_FRINFC_TOPAZ_VAL0)? 1675 NFCSTATUS_SUCCESS: 1676 Result); 1677 1678 /* Card size is initialised */ 1679 NdefMap->CardMemSize = NdefMap->TopazContainer.RemainingSize = 1680 ((Result == NFCSTATUS_SUCCESS)? 1681 (PH_FRINFC_TOPAZ_MAX_CARD_SZ - PH_FRINFC_TOPAZ_VAL4): 1682 NdefMap->CardMemSize); 1683 } 1684 1685 if (NdefMap->CardState != PH_NDEFMAP_CARD_STATE_READ_ONLY) 1686 { 1687 NdefMap->CardState = (uint8_t)((Result == NFCSTATUS_SUCCESS)? 1688 PH_NDEFMAP_CARD_STATE_INITIALIZED: 1689 PH_NDEFMAP_CARD_STATE_INVALID); 1690 } 1691 1692 return Result; 1693 } 1694 1695 static void phFriNfc_Tpz_H_ChkLockBits(phFriNfc_NdefMap_t *NdefMap) 1696 { 1697 /* Set the card state */ 1698 NdefMap->CardState = (uint8_t) 1699 (((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_LOCKBIT_BYTENO_0] == 1700 PH_FRINFC_TOPAZ_LOCKBIT_BYTE114) && 1701 ((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_LOCKBIT_BYTENO_1] == 1702 PH_FRINFC_TOPAZ_LOCKBIT_BYTE115_1) || 1703 (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_LOCKBIT_BYTENO_1] == 1704 PH_FRINFC_TOPAZ_LOCKBIT_BYTE115_2)))? 1705 PH_NDEFMAP_CARD_STATE_READ_WRITE: 1706 PH_NDEFMAP_CARD_STATE_READ_ONLY); 1707 1708 /* Set the card state from CC bytes */ 1709 if (NdefMap->CardState == PH_NDEFMAP_CARD_STATE_READ_WRITE) 1710 { 1711 if (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_CC_BYTENO_3] == PH_FRINFC_TOPAZ_CC_READWRITE) 1712 { 1713 NdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_WRITE; 1714 } 1715 else if (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_CC_BYTENO_3] == PH_FRINFC_TOPAZ_CC_READONLY) 1716 { 1717 NdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_ONLY; 1718 } 1719 else 1720 { 1721 NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INVALID; 1722 } 1723 } 1724 } 1725 1726 static NFCSTATUS phFriNfc_Tpz_H_WrCCorTLV(phFriNfc_NdefMap_t *NdefMap) 1727 { 1728 NFCSTATUS Result = NFCSTATUS_SUCCESS; 1729 uint8_t ByteNo = PH_FRINFC_TOPAZ_VAL0, 1730 BlockNo = PH_FRINFC_TOPAZ_VAL0; 1731 uint8_t TempByteVal = 0; 1732 switch(NdefMap->TopazContainer.InternalState) 1733 { 1734 case PH_FRINFC_TOPAZ_WR_CC_BYTE0: 1735 /* To write the CC bytes */ 1736 TempByteVal = PH_FRINFC_TOPAZ_CC_BYTE0; 1737 ByteNo = (uint8_t)PH_FRINFC_TOPAZ_VAL0; 1738 BlockNo = PH_FRINFC_TOPAZ_VAL1; 1739 break; 1740 1741 case PH_FRINFC_TOPAZ_WR_CC_BYTE1: 1742 /* To write the CC bytes */ 1743 TempByteVal = PH_FRINFC_TOPAZ_CC_BYTE1; 1744 ByteNo = (uint8_t)PH_FRINFC_TOPAZ_VAL1; 1745 BlockNo = PH_FRINFC_TOPAZ_VAL1; 1746 break; 1747 1748 case PH_FRINFC_TOPAZ_WR_CC_BYTE2: 1749 /* To write the CC bytes */ 1750 TempByteVal = PH_FRINFC_TOPAZ_CC_BYTE2_MAX; 1751 ByteNo = (uint8_t)PH_FRINFC_TOPAZ_VAL2; 1752 BlockNo = PH_FRINFC_TOPAZ_VAL1; 1753 break; 1754 1755 case PH_FRINFC_TOPAZ_WR_CC_BYTE3: 1756 /* To write the CC bytes */ 1757 TempByteVal = PH_FRINFC_TOPAZ_CC_BYTE3_RW; 1758 ByteNo = (uint8_t)PH_FRINFC_TOPAZ_VAL3; 1759 BlockNo = PH_FRINFC_TOPAZ_VAL1; 1760 break; 1761 1762 case PH_FRINFC_TOPAZ_WR_T_OF_TLV: 1763 default: 1764 /* To write the NDEF TLV (if not present) */ 1765 TempByteVal = PH_FRINFC_TOPAZ_NDEF_T; 1766 ByteNo = (uint8_t)NdefMap->TLVStruct.NdefTLVByte; 1767 BlockNo = NdefMap->TLVStruct.NdefTLVBlock; 1768 break; 1769 } 1770 NdefMap->State = PH_FRINFC_TOPAZ_STATE_WR_CC_OR_TLV; 1771 Result = phFriNfc_Tpz_H_WrAByte( NdefMap, BlockNo, ByteNo,TempByteVal); 1772 return Result; 1773 } 1774 1775 static NFCSTATUS phFriNfc_Tpz_H_ProCCTLV(phFriNfc_NdefMap_t *NdefMap) 1776 { 1777 NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, 1778 NFCSTATUS_INVALID_RECEIVE_LENGTH); 1779 switch(NdefMap->TopazContainer.InternalState) 1780 { 1781 case PH_FRINFC_TOPAZ_WR_CC_BYTE0: 1782 /* Process the CC byte */ 1783 /* Check the response */ 1784 if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == 1785 PH_FRINFC_TOPAZ_CC_BYTE0) && 1786 (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) 1787 { 1788 NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_CC_BYTE1; 1789 Result = phFriNfc_Tpz_H_WrCCorTLV(NdefMap); 1790 } 1791 break; 1792 1793 case PH_FRINFC_TOPAZ_WR_CC_BYTE1: 1794 /* Process the CC byte */ 1795 /* Check the response */ 1796 if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == 1797 PH_FRINFC_TOPAZ_CC_BYTE1) && 1798 (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) 1799 { 1800 NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_CC_BYTE2; 1801 Result = phFriNfc_Tpz_H_WrCCorTLV(NdefMap); 1802 } 1803 break; 1804 1805 case PH_FRINFC_TOPAZ_WR_CC_BYTE2: 1806 /* Process the CC byte */ 1807 /* Check the response */ 1808 if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == 1809 PH_FRINFC_TOPAZ_CC_BYTE2_MAX) && 1810 (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) 1811 { 1812 NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_CC_BYTE3; 1813 Result = phFriNfc_Tpz_H_WrCCorTLV(NdefMap); 1814 } 1815 break; 1816 1817 case PH_FRINFC_TOPAZ_WR_CC_BYTE3: 1818 /* Process the CC byte */ 1819 /* Check the response */ 1820 if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == 1821 PH_FRINFC_TOPAZ_CC_BYTE3_RW) && 1822 (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) 1823 { 1824 NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_T_OF_TLV; 1825 Result = phFriNfc_Tpz_H_WrCCorTLV(NdefMap); 1826 } 1827 break; 1828 1829 case PH_FRINFC_TOPAZ_WR_T_OF_TLV: 1830 default: 1831 /* Check the response */ 1832 if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == 1833 PH_FRINFC_TOPAZ_NDEF_T) && 1834 (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) 1835 { 1836 /* Increment the Byte Number */ 1837 NdefMap->TopazContainer.ByteNumber++; 1838 /* Check the block and byte number */ 1839 phFriNfc_Tpz_H_BlkChk(NdefMap); 1840 /* Process the T of NDEF TLV */ 1841 NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE_NMN; 1842 1843 /* Here the NMN is written 0, so internal state is used */ 1844 NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_NMN_0; 1845 1846 /*Inside this call Write NMN (block number 1 and byte number 0) = 0 */ 1847 Result = phFriNfc_Tpz_H_WrAByte( NdefMap, PH_FRINFC_TOPAZ_VAL1, 1848 PH_FRINFC_TOPAZ_VAL0,PH_FRINFC_TOPAZ_VAL0); 1849 } 1850 break; 1851 } 1852 return Result; 1853 } 1854 1855 #ifdef UNIT_TEST 1856 #include <phUnitTestNfc_Topaz_static.c> 1857 #endif 1858 1859 #endif /* PH_FRINFC_MAP_TOPAZ_DISABLED */ 1860