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