diff options
author | Nick Pelly <npelly@google.com> | 2010-09-23 12:47:58 -0700 |
---|---|---|
committer | Nick Pelly <npelly@google.com> | 2010-09-23 13:53:18 -0700 |
commit | 5d9927ba30ba449badb9f6df0fbeb4d6aedc6e2a (patch) | |
tree | 190f9251c6db03d3550ec7f30b51a2561c01d9cf /src/phFriNfc_TopazMap.c | |
parent | 4ff7c86a2c706b150078274455406f1b04966e1a (diff) | |
download | external_libnfc-nxp-5d9927ba30ba449badb9f6df0fbeb4d6aedc6e2a.zip external_libnfc-nxp-5d9927ba30ba449badb9f6df0fbeb4d6aedc6e2a.tar.gz external_libnfc-nxp-5d9927ba30ba449badb9f6df0fbeb4d6aedc6e2a.tar.bz2 |
Initial libnfc checkin
Source: Trusted_NFC_Device_Host_AA03.01e02_google.zip code drop (23-Sep-2010)
Change-Id: Ie47f18423f949a8d3e0815d13f55c814312add24
Signed-off-by: Nick Pelly <npelly@google.com>
Diffstat (limited to 'src/phFriNfc_TopazMap.c')
-rw-r--r-- | src/phFriNfc_TopazMap.c | 1859 |
1 files changed, 1859 insertions, 0 deletions
diff --git a/src/phFriNfc_TopazMap.c b/src/phFriNfc_TopazMap.c new file mode 100644 index 0000000..8901aa7 --- /dev/null +++ b/src/phFriNfc_TopazMap.c @@ -0,0 +1,1859 @@ +/* + * Copyright (C) 2010 NXP Semiconductors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*! +* \file phFriNfc_TopazMap.c +* \brief NFC Ndef Mapping For Remote Devices. +* +* Project: NFC-FRI +* +* $Date: Wed May 12 10:21:17 2010 $ +* $Author: ing02260 $ +* $Revision: 1.21 $ +* $Aliases: NFC_FRI1.1_WK1019_SDK,NFC_FRI1.1_WK1023_R35_1 $ +* +*/ + + + +#include <phFriNfc_NdefMap.h> +#include <phFriNfc_TopazMap.h> +#include <phFriNfc_MapTools.h> +#include <phFriNfc_OvrHal.h> + +#ifndef PH_FRINFC_MAP_TOPAZ_DISABLED +/*! \ingroup grp_file_attributes +* \name NDEF Mapping +* +* File: \ref phFriNfcNdefMap.c +* +*/ +/*@{*/ +#define PHFRINFCTOPAZMAP_FILEREVISION "$Revision: 1.21 $" +#define PHFRINFCTOPAZMAP_FILEALIASES "$Aliases: NFC_FRI1.1_WK1019_SDK,NFC_FRI1.1_WK1023_R35_1 $" +/*@}*/ +/****************** Start of macros ********************/ +/* Below MACRO is used for the WRITE error scenario, + in case PN544 returns error for any WRITE, then + read the written block and byte number, to check the data + written to the card is correct or not +*/ +/* #define TOPAZ_RF_ERROR_WORKAROUND */ + +#ifdef TOPAZ_RF_ERROR_WORKAROUND + + /* Below MACROs are added for the error returned from HAL, if the + below error has occured during the WRITE, then read the error + returned blocks to confirm */ + #define FRINFC_RF_TIMEOUT_89 (0x89U) + #define FRINFC_RF_TIMEOUT_90 (0x90U) + + /* State specific to read after the RF ERROR for the WRITE */ + #define PH_FRINFC_TOPAZ_STATE_RF_ERROR_READ (0x0FU) + +#endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */ + +/****************** End of macros ********************/ + +/*! +* \name Topaz Mapping - Helper Functions +* +*/ +/*@{*/ + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function shall read 8 bytes +* from the card. +*/ +static NFCSTATUS phFriNfc_Tpz_H_RdBytes(phFriNfc_NdefMap_t *NdefMap, + uint16_t BlockNo, + uint16_t ByteNo); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function shall process +* read id command +*/ +static NFCSTATUS phFriNfc_Tpz_H_ProReadID(phFriNfc_NdefMap_t *NdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function shall process +* read all command +*/ +static NFCSTATUS phFriNfc_Tpz_H_ProReadAll(phFriNfc_NdefMap_t *NdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function depends on +* function called by the user +*/ +static NFCSTATUS phFriNfc_Tpz_H_CallNxtOp(phFriNfc_NdefMap_t *NdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function checks the CC +* bytes +*/ +static NFCSTATUS phFriNfc_Tpz_H_ChkCCBytes(phFriNfc_NdefMap_t *NdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function finds +* NDEF TLV +*/ +static NFCSTATUS phFriNfc_Tpz_H_findNDEFTLV(phFriNfc_NdefMap_t *NdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function writes a +* byte into the card +*/ +static NFCSTATUS phFriNfc_Tpz_H_WrAByte(phFriNfc_NdefMap_t *NdefMap, + uint16_t BlockNo, + uint16_t ByteNo, + uint8_t ByteVal + ); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function shall process the +* NMN write +*/ +static NFCSTATUS phFriNfc_Tpz_H_ProWrNMN(phFriNfc_NdefMap_t *NdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function writes the length field of +* the NDEF TLV +*/ +static NFCSTATUS phFriNfc_Tpz_H_ProWrTLV(phFriNfc_NdefMap_t *NdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function updates length field +* of the NDEF TLV after complete write. +*/ +static NFCSTATUS phFriNfc_Tpz_H_WrLByte(phFriNfc_NdefMap_t *NdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function copies the card data +* to the user buffer +*/ +static NFCSTATUS phFriNfc_Tpz_H_CpDataToUsrBuf( phFriNfc_NdefMap_t *NdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function shall process the +* written data +*/ +static NFCSTATUS phFriNfc_Tpz_H_ProWrUsrData( phFriNfc_NdefMap_t *NdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function checks the block +* number is correct or not +*/ +static void phFriNfc_Tpz_H_BlkChk(phFriNfc_NdefMap_t *NdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function writes the 0th +* byte of block 1 has Zero +*/ +static NFCSTATUS phFriNfc_Tpz_H_WrByte0ValE1(phFriNfc_NdefMap_t *NdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function calls the +* completion routine +*/ +static void phFriNfc_Tpz_H_Complete(phFriNfc_NdefMap_t *NdefMap, + NFCSTATUS Status); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz check ndef. This function checks +* the CC byte in check ndef function +*/ +static NFCSTATUS phFriNfc_Tpz_H_ChkCCinChkNdef(phFriNfc_NdefMap_t *NdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz check ndef. This function checks +* the lock bits and set a card state +*/ +static void phFriNfc_Tpz_H_ChkLockBits(phFriNfc_NdefMap_t *NdefMap); + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function writes CC bytes or +* type of the TLV +*/ +static NFCSTATUS phFriNfc_Tpz_H_WrCCorTLV(phFriNfc_NdefMap_t *NdefMap); + +#ifdef TOPAZ_RF_ERROR_WORKAROUND + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function checks the written +* value after the +*/ +static +NFCSTATUS +phFriNfc_Tpz_H_CheckWrittenData ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t state_rf_error); + +#endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */ + +/*! +* \brief \copydoc page_ovr Helper function for Topaz. This function checks the written +* CC bytes are correct +*/ +static NFCSTATUS phFriNfc_Tpz_H_ProCCTLV(phFriNfc_NdefMap_t *NdefMap); +/*@}*/ +void phFriNfc_TopazMap_H_Reset(phFriNfc_NdefMap_t *NdefMap) +{ + /* Initialising the Topaz structure variable */ + NdefMap->TopazContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_INVALID_OPE; + NdefMap->TopazContainer.CurrentBlock = PH_FRINFC_TOPAZ_VAL1; + NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL0; + NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_VAL0; + (void)memset(NdefMap->TopazContainer.ReadBuffer, PH_FRINFC_TOPAZ_VAL0, + sizeof(NdefMap->TopazContainer.ReadBuffer)); + NdefMap->TopazContainer.ReadWriteCompleteFlag = PH_FRINFC_TOPAZ_FLAG0; + NdefMap->TopazContainer.RemainingSize = PH_FRINFC_TOPAZ_VAL0; + (void)memset(NdefMap->TopazContainer.UID, PH_FRINFC_TOPAZ_VAL0, + sizeof(NdefMap->TopazContainer.UID)); + NdefMap->TopazContainer.Cur_RW_Index=0; + NdefMap->TopazContainer.ByteRWFrmCard =0; +} + +/*! +* \brief Check whether a particular Remote Device is NDEF compliant. +* +* The function checks whether the peer device is NDEF compliant. +* +* \param[in] NdefMap Pointer to a valid instance of the \ref phFriNfc_NdefMap_t +* structure describing the component context. +* +* \retval NFCSTATUS_PENDING The action has been successfully triggered. +* \retval Others An error has occurred. +* +*/ + +NFCSTATUS phFriNfc_TopazMap_ChkNdef( phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_PARAMETER); + if ( NdefMap != NULL) + { + /* Update the previous operation */ + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_CHECK_OPE; + /* Update the CR index to know from which operation completion + routine has to be called */ + NdefMap->TopazContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_CHK_NDEF; + NdefMap->TopazContainer.CurrentBlock = PH_FRINFC_TOPAZ_VAL1; + NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL0; + + /* Set card state */ + NdefMap->CardType = PH_FRINFC_NDEFMAP_TOPAZ_CARD; + + /* Change the state to Check Ndef Compliant */ + NdefMap->State = PH_FRINFC_TOPAZ_STATE_READID; + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_CHECK_OPE; + +#ifdef TOPAZ_RAW_SUPPORT + NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw; + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READID; +#else +#ifdef PH_HAL4_ENABLE + NdefMap->Cmd.JewelCmd = phHal_eJewel_RID; +#else + NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRid; +#endif +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + Result = phFriNfc_Tpz_H_RdBytes(NdefMap, NdefMap->TopazContainer.CurrentBlock, + NdefMap->TopazContainer.ByteNumber); + } + return Result; +} + + +/*! +* \brief Initiates Reading of NDEF information from the Remote Device. +* +* The function initiates the reading of NDEF information from a Remote Device. +* It performs a reset of the state and starts the action (state machine). +* A periodic call of the \ref phFriNfcNdefMap_Process has to be done once the action +* has been triggered. +*/ +NFCSTATUS phFriNfc_TopazMap_RdNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + + /* Copy user buffer to the context */ + NdefMap->ApduBuffer = PacketData; + /* Copy user length to the context */ + NdefMap->ApduBufferSize = *PacketDataLength; + /* Update the user memory size to a context variable */ + NdefMap->NumOfBytesRead = PacketDataLength; + /* Number of bytes read from the card is zero. + This variable returns the number of bytes read + from the card. */ + *NdefMap->NumOfBytesRead = PH_FRINFC_TOPAZ_VAL0; + /* Index to know the length read */ + NdefMap->ApduBuffIndex = PH_FRINFC_TOPAZ_VAL0; + /* Store the offset in the context */ + NdefMap->Offset = Offset; + /* Update the CR index to know from which operation completion + routine has to be called */ + NdefMap->TopazContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_RD_NDEF; + + if( (Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN) || ( NdefMap->PrevOperation == + PH_FRINFC_NDEFMAP_WRITE_OPE)) + { + /* If previous operation is not read then the read shall + start from BEGIN */ + NdefMap->Offset = PH_FRINFC_NDEFMAP_SEEK_BEGIN; + /* Initialise current block and byte number */ + NdefMap->TopazContainer.CurrentBlock = PH_FRINFC_TOPAZ_VAL1; + NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL0; + /* State has to be changed */ + NdefMap->State = PH_FRINFC_TOPAZ_STATE_READALL; + NdefMap->TopazContainer.ReadWriteCompleteFlag = + PH_FRINFC_TOPAZ_FLAG0; + /* Topaz command = READALL */ +#ifdef TOPAZ_RAW_SUPPORT + NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw; + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READALL; +#else + +#ifdef PH_HAL4_ENABLE + NdefMap->Cmd.JewelCmd = phHal_eJewel_ReadAll; +#else + NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelReadAll; +#endif + +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + } + + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_READ_OPE; + /* Offset = Current, but the read has reached the End of Card */ + if( (Offset == PH_FRINFC_NDEFMAP_SEEK_CUR) && + (NdefMap->TopazContainer.ReadWriteCompleteFlag == + PH_FRINFC_TOPAZ_FLAG1)) + { + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_EOF_NDEF_CONTAINER_REACHED); + } + else + { + /* if the offset is begin then call READALL else copy the data + from the user buffer */ + Result = ((Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN)? + phFriNfc_Tpz_H_RdBytes(NdefMap, + NdefMap->TopazContainer.CurrentBlock, + NdefMap->TopazContainer.ByteNumber): + phFriNfc_Tpz_H_CpDataToUsrBuf(NdefMap)); + } + + return Result; +} + +/*! +* \brief Initiates Writing of NDEF information to the Remote Device. +* +* The function initiates the writing of NDEF information to a Remote Device. +* It performs a reset of the state and starts the action (state machine). +* A periodic call of the \ref phFriNfcNdefMap_Process has to be done once the action +* has been triggered. +*/ +NFCSTATUS phFriNfc_TopazMap_WrNdef( phFriNfc_NdefMap_t *NdefMap, + uint8_t *PacketData, + uint32_t *PacketDataLength, + uint8_t Offset) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint8_t TempByteVal = 0; + /* Copy user buffer to the context */ + NdefMap->ApduBuffer = PacketData; + /* Copy user length to the context */ + NdefMap->ApduBufferSize = *PacketDataLength; + /* Index to know the length written */ + NdefMap->ApduBuffIndex = PH_FRINFC_TOPAZ_VAL0; + /* Update the user memory size to a context variable */ + NdefMap->WrNdefPacketLength = PacketDataLength; + /* Number of bytes written to the card is zero. + This variable returns the number of bytes written + to the card. */ + *NdefMap->WrNdefPacketLength = PH_FRINFC_TOPAZ_VAL0; + /* Update the CR index to know from which operation completion + routine has to be called */ + NdefMap->TopazContainer.CRIndex = PH_FRINFC_NDEFMAP_CR_WR_NDEF; + /* Store the offset in the context */ + NdefMap->Offset = Offset; + + + if( (Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN) || + (NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_READ_OPE)) + { + NdefMap->Offset = PH_FRINFC_NDEFMAP_SEEK_BEGIN; + /* Initialise current block and byte number */ + NdefMap->TopazContainer.CurrentBlock = PH_FRINFC_TOPAZ_VAL1; + NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL0; + /* State has to be changed */ + NdefMap->State = PH_FRINFC_TOPAZ_STATE_READALL; + /* Topaz command = READALL */ + +#ifdef TOPAZ_RAW_SUPPORT + NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw; + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READALL; +#else +#ifdef PH_HAL4_ENABLE + NdefMap->Cmd.JewelCmd = phHal_eJewel_ReadAll; +#else + NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelReadAll; +#endif +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + NdefMap->TopazContainer.ReadWriteCompleteFlag = + PH_FRINFC_TOPAZ_FLAG0; + NdefMap->TopazContainer.RemainingSize = NdefMap->CardMemSize; + TempByteVal = NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1]; + } + else + { + /* State has to be changed */ + NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE; + /* copy the user data to write into the card */ + TempByteVal = NdefMap->ApduBuffer[NdefMap->ApduBuffIndex]; + } + + /* Update the previous operation to write operation */ + NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_WRITE_OPE; + if((Offset == PH_FRINFC_NDEFMAP_SEEK_CUR) && + (NdefMap->TopazContainer.ReadWriteCompleteFlag == + PH_FRINFC_TOPAZ_FLAG1)) + { + /* Offset = Current, but the read has reached the End of Card */ + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_EOF_NDEF_CONTAINER_REACHED); + } + else + { + /* Check the block */ + phFriNfc_Tpz_H_BlkChk(NdefMap); + /* if offset is begin then call READALL else start writing */ + Result = ((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN)? + phFriNfc_Tpz_H_RdBytes(NdefMap, NdefMap->TopazContainer.CurrentBlock, + NdefMap->TopazContainer.ByteNumber): + phFriNfc_Tpz_H_WrAByte(NdefMap, NdefMap->TopazContainer.CurrentBlock, + NdefMap->TopazContainer.ByteNumber,TempByteVal)); + } + + return Result; +} + + +/*! +* \brief Completion Routine, Processing function, needed to avoid long blocking. +* \note The lower (Overlapped HAL) layer must register a pointer to this function as a Completion +* Routine in order to be able to notify the component that an I/O has finished and data are +* ready to be processed. +* +*/ + +void phFriNfc_TopazMap_Process( void *Context, + NFCSTATUS Status) +{ + + phFriNfc_NdefMap_t *psNdefMap = NULL; + +#ifdef TOPAZ_RF_ERROR_WORKAROUND + + static uint8_t rf_error_state = 0; + +#endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */ + + psNdefMap = (phFriNfc_NdefMap_t *)Context; + + if ((Status & PHNFCSTBLOWER) == (NFCSTATUS_SUCCESS & PHNFCSTBLOWER)) + { + switch (psNdefMap->State) + { + case PH_FRINFC_TOPAZ_STATE_WRITE: + { + Status = phFriNfc_Tpz_H_ProWrUsrData (psNdefMap); + break; + } + + case PH_FRINFC_TOPAZ_STATE_READID: + { + Status = phFriNfc_Tpz_H_ProReadID (psNdefMap); + break; + } + + case PH_FRINFC_TOPAZ_STATE_READALL: + { + Status = phFriNfc_Tpz_H_ProReadAll (psNdefMap); + break; + } + + case PH_FRINFC_TOPAZ_STATE_WRITE_NMN: + { + Status = phFriNfc_Tpz_H_ProWrNMN (psNdefMap); + break; + } + + case PH_FRINFC_TOPAZ_STATE_WRITE_L_TLV: + { + Status = phFriNfc_Tpz_H_ProWrTLV (psNdefMap); + break; + } + + case PH_FRINFC_TOPAZ_STATE_WR_CC_OR_TLV: + { + Status = phFriNfc_Tpz_H_ProCCTLV (psNdefMap); + break; + } + +#ifdef TOPAZ_RF_ERROR_WORKAROUND + + case PH_FRINFC_TOPAZ_STATE_RF_ERROR_READ: + { + Status = phFriNfc_Tpz_H_CheckWrittenData (psNdefMap, + rf_error_state); + break; + } + +#endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */ + + default: + { + Status = PHNFCSTVAL (CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + break; + } + } + } + else + { +#ifdef TOPAZ_RF_ERROR_WORKAROUND + + if ((FRINFC_RF_TIMEOUT_89 == PHNFCSTATUS (Status)) || + (FRINFC_RF_TIMEOUT_90 == PHNFCSTATUS (Status)) || + (NFCSTATUS_RF_TIMEOUT == PHNFCSTATUS (Status))) + { + uint8_t byte_number = 0; + uint8_t block_number = 0; + + rf_error_state = psNdefMap->State; + +#ifdef TOPAZ_RAW_SUPPORT + + *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_READ; + +#else + +#ifdef PH_HAL4_ENABLE + + psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read1; + +#else + + psNdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead1; + +#endif /* #ifdef PH_HAL4_ENABLE */ + +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + /* Update the state variable to the new work around state*/ + psNdefMap->State = PH_FRINFC_TOPAZ_STATE_RF_ERROR_READ; + + /* Switch is used to know, if the error occured during WRITE or READ */ + switch (rf_error_state) + { + case PH_FRINFC_TOPAZ_STATE_WRITE_NMN: + { + /* Block and byte number is updated for NMN */ + byte_number = PH_FRINFC_TOPAZ_VAL0; + block_number = PH_FRINFC_TOPAZ_VAL1; + break; + } + + case PH_FRINFC_TOPAZ_STATE_WRITE_L_TLV: + { + /* Get the L field of the TLV block */ + block_number = (uint8_t)(((psNdefMap->TLVStruct.NdefTLVByte + + PH_FRINFC_TOPAZ_VAL1) > + PH_FRINFC_TOPAZ_VAL7)? + (psNdefMap->TLVStruct.NdefTLVBlock + + PH_FRINFC_TOPAZ_VAL1): + psNdefMap->TLVStruct.NdefTLVBlock); + /* Get the L byte */ + byte_number = (uint8_t)((psNdefMap->TLVStruct.NdefTLVByte + + PH_FRINFC_TOPAZ_VAL1) % + PH_FRINFC_TOPAZ_VAL8); + break; + } + + case PH_FRINFC_TOPAZ_STATE_WR_CC_OR_TLV: + { + switch (psNdefMap->TopazContainer.InternalState) + { + case PH_FRINFC_TOPAZ_WR_CC_BYTE0: + { + /* Block and byte number is updated for the CC byte 0 */ + block_number = (uint8_t)PH_FRINFC_TOPAZ_VAL1; + byte_number = (uint8_t)PH_FRINFC_TOPAZ_VAL0; + break; + } + + case PH_FRINFC_TOPAZ_WR_CC_BYTE1: + { + /* Block and byte number is updated for the CC byte 1 */ + block_number = (uint8_t)PH_FRINFC_TOPAZ_VAL1; + byte_number = (uint8_t)PH_FRINFC_TOPAZ_VAL1; + break; + } + + case PH_FRINFC_TOPAZ_WR_CC_BYTE2: + { + /* Block and byte number is updated for the CC byte 2 */ + block_number = (uint8_t)PH_FRINFC_TOPAZ_VAL1; + byte_number = (uint8_t)PH_FRINFC_TOPAZ_VAL2; + break; + } + + case PH_FRINFC_TOPAZ_WR_CC_BYTE3: + { + /* Block and byte number is updated for the CC byte 3 */ + block_number = (uint8_t)PH_FRINFC_TOPAZ_VAL1; + byte_number = (uint8_t)PH_FRINFC_TOPAZ_VAL3; + break; + } + + case PH_FRINFC_TOPAZ_WR_T_OF_TLV: + { + /* Block and byte number is updated for the Type field of the TLV */ + block_number = psNdefMap->TLVStruct.NdefTLVBlock; + byte_number = (uint8_t)psNdefMap->TLVStruct.NdefTLVByte; + break; + } + + default: + { + /* Do nothing */ + break; + } + } /* switch (psNdefMap->TopazContainer.InternalState) */ + break; + } + + case PH_FRINFC_TOPAZ_STATE_WRITE: + { + /* Block and byte number is updated for the written error data */ + block_number = psNdefMap->TopazContainer.CurrentBlock; + byte_number = psNdefMap->TopazContainer.ByteNumber; + break; + } + + default: + { + /* Error occured is not during WRITE, so update + state variable to the previous state */ + psNdefMap->State = rf_error_state; + break; + } + } /* switch (rf_error_state) */ + + /* The below check is added, to know if the error is for + the WRITE or READ scenario, + If the error is for READ, then state variable is not updated + If the error is for WRITE, then state variable is updated with + PH_FRINFC_TOPAZ_STATE_RF_ERROR_READ value */ + if (PH_FRINFC_TOPAZ_STATE_RF_ERROR_READ == psNdefMap->State) + { + /* Read the data with the updated block and byte number */ + Status = phFriNfc_Tpz_H_RdBytes (psNdefMap, block_number, + byte_number); + } + } + +#endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */ + } + + /* Call Completion Routine, if Status != PENDING */ + if (NFCSTATUS_PENDING != Status) + { + phFriNfc_Tpz_H_Complete(psNdefMap, Status); + } +} + + +#ifdef TOPAZ_RF_ERROR_WORKAROUND + +static +NFCSTATUS +phFriNfc_Tpz_H_CheckWrittenData ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t state_rf_error) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + + switch (state_rf_error) + { + case PH_FRINFC_TOPAZ_STATE_WRITE: + { + result = phFriNfc_Tpz_H_ProWrUsrData (psNdefMap); + break; + } + + case PH_FRINFC_TOPAZ_STATE_WRITE_NMN: + { + result = phFriNfc_Tpz_H_ProWrNMN (psNdefMap); + break; + } + + case PH_FRINFC_TOPAZ_STATE_WRITE_L_TLV: + { + result = phFriNfc_Tpz_H_ProWrTLV (psNdefMap); + break; + } + + case PH_FRINFC_TOPAZ_STATE_WR_CC_OR_TLV: + { + result = phFriNfc_Tpz_H_ProCCTLV (psNdefMap); + break; + } + + default: + { + break; + } + } + + return result; +} + + +#endif /* #ifdef TOPAZ_RF_ERROR_WORKAROUND */ + +static NFCSTATUS phFriNfc_Tpz_H_RdBytes(phFriNfc_NdefMap_t *NdefMap, + uint16_t BlockNo, + uint16_t ByteNo) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; +#ifdef TOPAZ_RAW_SUPPORT + uint8_t index = 0; +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + /* set the data for additional data exchange*/ + NdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = PH_FRINFC_TOPAZ_VAL0; + NdefMap->psDepAdditionalInfo.DepFlags.NADPresent = PH_FRINFC_TOPAZ_VAL0; + NdefMap->psDepAdditionalInfo.NAD = PH_FRINFC_TOPAZ_VAL0; + + NdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_TopazMap_Process; + NdefMap->MapCompletionInfo.Context = NdefMap; + + *NdefMap->SendRecvLength = NdefMap->TempReceiveLength; + + /* Depending on the jewel command, the send length is decided */ +#ifdef TOPAZ_RAW_SUPPORT + switch(NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0]) +#else + switch(NdefMap->Cmd.JewelCmd) +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + { + +#ifdef TOPAZ_RAW_SUPPORT + case PH_FRINFC_TOPAZ_CMD_READID: +#else +#ifdef PH_HAL4_ENABLE + case phHal_eJewel_RID: +#else + case phHal_eJewelCmdListJewelRid: +#endif +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + +#ifdef TOPAZ_RAW_SUPPORT + NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw; + /*Copy command to Send Buffer*/ + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READID; + index ++; + + /*Copy UID of the tag to Send Buffer*/ + (void)memset(&(NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1]), + 0x00,(0x06)); + index = index + 0x06; + + /* Update the length of the command buffer*/ + NdefMap->SendLength = index; +#else + /* For READ ID and READ ALL, send length is 0 */ + NdefMap->SendLength = PH_FRINFC_TOPAZ_VAL0; +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + break; + +#ifdef TOPAZ_RAW_SUPPORT + case PH_FRINFC_TOPAZ_CMD_READALL: +#else +#ifdef PH_HAL4_ENABLE + case phHal_eJewel_ReadAll: +#else + case phHal_eJewelCmdListJewelReadAll: +#endif +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + +#ifdef TOPAZ_RAW_SUPPORT + NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw; + /*Copy command to Send Buffer*/ + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READALL; + index ++; + + /*Copy 0x00 to Send Buffer*/ + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1] = 0x00; + index ++; + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2] = 0x00; + index ++; + + /*Copy UID of the tag to Send Buffer*/ + (void)memcpy(&(NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL3]), + &(NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid), + (NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.UidLength)); + + index = index + NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.UidLength; + + /* Update the length of the command buffer*/ + NdefMap->SendLength = index; +#else + /* For READ ID and READ ALL, send length is 0 */ + NdefMap->SendLength = PH_FRINFC_TOPAZ_VAL0; +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + break; + +#ifdef TOPAZ_RAW_SUPPORT + case PH_FRINFC_TOPAZ_CMD_READ: +#else +#ifdef PH_HAL4_ENABLE + case phHal_eJewel_Read1: +#else + case phHal_eJewelCmdListJewelRead1: +#endif + +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + +#ifdef TOPAZ_RAW_SUPPORT + NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw; + /*Copy command to Send Buffer*/ + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READ; + index ++; + + /*Copy Address to Send Buffer*/ + /* Calculate send length + 7 | 6 5 4 3 | 2 1 0 | + | block no | byte no | + */ + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1] = + (uint8_t)((BlockNo << PH_FRINFC_TOPAZ_SHIFT3) + + ByteNo); + index ++; + /*Copy 0x00 to Send Buffer*/ + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2] = 0x00; + index ++; + + /*Copy UID of the tag to Send Buffer*/ + (void)memcpy(&(NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL3]), + &(NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid), + (NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.UidLength)); + index = index + NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.UidLength; + + /* Update the length of the command buffer*/ + NdefMap->SendLength = index; +#else + /* Calculate send length + 7 | 6 5 4 3 | 2 1 0 | + | block no | byte no | + */ + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = + (uint8_t)((BlockNo << PH_FRINFC_TOPAZ_SHIFT3) + + ByteNo); + NdefMap->SendLength = PH_FRINFC_TOPAZ_VAL1; +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + break; +#ifdef TOPAZ_RAW_SUPPORT +#else +#ifdef PH_HAL4_ENABLE + case phHal_eJewel_Read: + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = 0x00; + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1] = 0x00; + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2] = 104; + NdefMap->SendLength = 3; + break; +#endif +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + default: + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + } + + if(Result == NFCSTATUS_SUCCESS) + { + /* Call the Overlapped HAL Transceive function */ + Result = phFriNfc_OvrHal_Transceive( NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo, + NdefMap->Cmd, + &NdefMap->psDepAdditionalInfo, + NdefMap->SendRecvBuf, + NdefMap->SendLength, + NdefMap->SendRecvBuf, + NdefMap->SendRecvLength); + } + return Result; +} + +static NFCSTATUS phFriNfc_Tpz_H_WrAByte(phFriNfc_NdefMap_t *NdefMap, + uint16_t BlockNo, + uint16_t ByteNo, + uint8_t ByteVal + ) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint8_t index = 0; + + + PHNFC_UNUSED_VARIABLE(ByteVal); + /* set the data for additional data exchange*/ + NdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = PH_FRINFC_TOPAZ_VAL0; + NdefMap->psDepAdditionalInfo.DepFlags.NADPresent = PH_FRINFC_TOPAZ_VAL0; + NdefMap->psDepAdditionalInfo.NAD = PH_FRINFC_TOPAZ_VAL0; + + NdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_TopazMap_Process; + NdefMap->MapCompletionInfo.Context = NdefMap; + + *NdefMap->SendRecvLength = NdefMap->TempReceiveLength; + /* Command used to write 1 byte */ +#ifdef TOPAZ_RAW_SUPPORT + NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw; +#else +#ifdef PH_HAL4_ENABLE + NdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E; +#else + NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelWriteErase1; +#endif +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + +#ifdef TOPAZ_RAW_SUPPORT + /*Copy command to Send Buffer*/ + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_WRITE_1E; + index ++; + + /*Copy Address to Send Buffer*/ + /* Calculate send length + 7 | 6 5 4 3 | 2 1 0 | + | block no | byte no | + */ + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL1] = + (uint8_t)((BlockNo << PH_FRINFC_TOPAZ_SHIFT3) + + ByteNo); + index ++; + /*Copy Data byte to Send Buffer*/ + NdefMap->SendRecvBuf[index] = ByteVal; + index ++; + + /*Copy UID of the tag to Send Buffer*/ + (void)memcpy(&(NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL3]), + &(NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid), + (NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.UidLength)); + index = index + NdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.UidLength; + + /* Update the length of the command buffer*/ + NdefMap->SendLength = index; + +#else + /* Depending on the jewel command, the send length is decided */ + /* Calculate send length + 7 | 6 5 4 3 | 2 1 0 | + | block no | byte no | + */ + NdefMap->SendRecvBuf[index] = + (uint8_t)((BlockNo << PH_FRINFC_TOPAZ_SHIFT3) + + ByteNo); + index ++; + NdefMap->SendRecvBuf[index] = ByteVal; + index ++; + NdefMap->SendLength = PH_FRINFC_TOPAZ_VAL2; + +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + /* Call the Overlapped HAL Transceive function */ + Result = phFriNfc_OvrHal_Transceive( NdefMap->LowerDevice, + &NdefMap->MapCompletionInfo, + NdefMap->psRemoteDevInfo, + NdefMap->Cmd, + &NdefMap->psDepAdditionalInfo, + NdefMap->SendRecvBuf, + NdefMap->SendLength, + NdefMap->SendRecvBuf, + NdefMap->SendRecvLength); + + return Result; +} + +static NFCSTATUS phFriNfc_Tpz_H_ProReadID(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + + if(((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] & + PH_FRINFC_TOPAZ_HEADROM0_CHK) == PH_FRINFC_TOPAZ_HEADROM0_VAL) && + (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL6)) + { + /* Copy UID to the context, Used when the READ ALL command is used */ + (void)memcpy(NdefMap->TopazContainer.UID, + &NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2], + PH_FRINFC_TOPAZ_VAL4); + + /* State has to be changed */ + NdefMap->State = PH_FRINFC_TOPAZ_STATE_READALL; + /* Topaz command = READALL */ +#ifdef TOPAZ_RAW_SUPPORT + NdefMap->Cmd.JewelCmd = phHal_eJewel_Raw; + NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] = PH_FRINFC_TOPAZ_CMD_READALL; +#else +#ifdef PH_HAL4_ENABLE + NdefMap->Cmd.JewelCmd = phHal_eJewel_ReadAll; +#else + NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelReadAll; +#endif +#endif /* #ifdef TOPAZ_RAW_SUPPORT */ + + /* Read all bytes from the card */ + Result = phFriNfc_Tpz_H_RdBytes(NdefMap, NdefMap->TopazContainer.CurrentBlock, + NdefMap->TopazContainer.ByteNumber); + } + + return Result; +} + +static NFCSTATUS phFriNfc_Tpz_H_ProReadAll(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + int32_t memcompare = PH_FRINFC_TOPAZ_VAL0; + + /* Compare the UID of READ ALL command with the stored UID */ +#ifdef PH_HAL4_ENABLE + if ((NdefMap->TopazContainer.UID[0] == NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2]) && + (NdefMap->TopazContainer.UID[1] == NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2 + 1]) && + (NdefMap->TopazContainer.UID[2] == NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2 + 2]) && + (NdefMap->TopazContainer.UID[3] == NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2 + 3])) + { + memcompare = PH_FRINFC_TOPAZ_VAL0; + } + else + { + memcompare = PH_FRINFC_TOPAZ_VAL1; + } +#else + memcompare = memcmp(NdefMap->TopazContainer.UID, + &NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2], + PH_FRINFC_TOPAZ_VAL4); +#endif /* #ifdef PH_HAL4_ENABLE */ + + if(((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] & + PH_FRINFC_TOPAZ_HEADROM0_CHK) == PH_FRINFC_TOPAZ_HEADROM0_VAL) && + (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_READALL_RESP) && + (memcompare == PH_FRINFC_TOPAZ_VAL0)) + { + /* Copy 96 bytes from the read/write memory space */ + (void)memcpy(NdefMap->TopazContainer.ReadBuffer, + &NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL10], + PH_FRINFC_TOPAZ_TOTAL_RWBYTES); + + /* Check the lock bits and set the card state */ + phFriNfc_Tpz_H_ChkLockBits(NdefMap); + + Result = phFriNfc_Tpz_H_CallNxtOp(NdefMap); + } + return Result; +} + +static NFCSTATUS phFriNfc_Tpz_H_CallNxtOp(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + /* Depending on the operation (check, read or write ndef), process the + read data */ + switch(NdefMap->PrevOperation) + { + case PH_FRINFC_NDEFMAP_CHECK_OPE: + /* Check the capabilty container values, according + to the spec */ + Result = phFriNfc_Tpz_H_ChkCCinChkNdef(NdefMap); + + if (NdefMap->CardState != PH_NDEFMAP_CARD_STATE_INVALID) + { + /* Check the spec version */ + Result = phFriNfc_Tpz_H_ChkSpcVer( NdefMap, + NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL1]); + /* Check the CC header size: Only valid ones are + 0x0C for 96 bytes. */ + if ((Result == NFCSTATUS_SUCCESS) && + ( NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL2] <= + PH_FRINFC_TOPAZ_CC_BYTE2_MAX)) + { + Result = phFriNfc_Tpz_H_findNDEFTLV(NdefMap); + /* As there is possibility of either having or not having TLV in + Topaz, no need to send the Actual status to the context*/ + Result = NFCSTATUS_SUCCESS; + } + } + else + { + Result = (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_FORMAT)); + } + break; + + case PH_FRINFC_NDEFMAP_READ_OPE: + /* Check the capabilty container values, according + to the spec */ + Result = phFriNfc_Tpz_H_ChkCCBytes(NdefMap); + + /* If success, find the ndef TLV */ + Result = ((Result != NFCSTATUS_SUCCESS)? + (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_FORMAT)): + phFriNfc_Tpz_H_findNDEFTLV(NdefMap)); + + if(Result == NFCSTATUS_SUCCESS) + { + NdefMap->TopazContainer.ByteNumber += PH_FRINFC_TOPAZ_VAL2; + /* If success, copy the read bytes to the user buffer */ + Result = phFriNfc_Tpz_H_CpDataToUsrBuf(NdefMap); + } + break; + + case PH_FRINFC_NDEFMAP_WRITE_OPE: + default: + if((NdefMap->CardState == PH_NDEFMAP_CARD_STATE_READ_WRITE) || + (NdefMap->CardState == PH_NDEFMAP_CARD_STATE_INITIALIZED)) + { + /* Check the capabilty container values, according + to the spec */ + Result = phFriNfc_Tpz_H_ChkCCBytes(NdefMap); + if(Result == NFCSTATUS_SUCCESS) + { + /* Find the NDEF TLV */ + Result = phFriNfc_Tpz_H_findNDEFTLV(NdefMap); + + /* Write the TLV */ + NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_T_OF_TLV; + } + else + { + NdefMap->TLVStruct.NdefTLVByte = PH_FRINFC_TOPAZ_VAL4; + NdefMap->TLVStruct.NdefTLVBlock = PH_FRINFC_TOPAZ_VAL1; + NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL4; + /* Write the TLV */ + NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_CC_BYTE0; + } + /* Write CC bytes */ + Result = phFriNfc_Tpz_H_WrCCorTLV(NdefMap); + } + break; + } + return Result; +} + +static NFCSTATUS phFriNfc_Tpz_H_ChkCCBytes(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + + if(NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL0] == + PH_FRINFC_TOPAZ_CC_BYTE0) + { + /* Check the spec version */ + Result = phFriNfc_Tpz_H_ChkSpcVer( NdefMap, + NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL1]); + /* Check the CC header size: Only valid ones are + 0x0C for 96 bytes. */ + Result = ((( NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL2] > + PH_FRINFC_TOPAZ_CC_BYTE2_MAX) || (Result != + NFCSTATUS_SUCCESS))? + (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_EOF_NDEF_CONTAINER_REACHED)): + Result); + + /* Get the read/write card memory size */ + NdefMap->TopazContainer.RemainingSize = + NdefMap->CardMemSize = ((Result == NFCSTATUS_SUCCESS)? + (PH_FRINFC_TOPAZ_MAX_CARD_SZ - PH_FRINFC_TOPAZ_VAL4): + NdefMap->CardMemSize); + + /* if the call is from write ndef then check for read write access */ + if(((NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_WRITE_OPE) && + (NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL3] != + PH_FRINFC_TOPAZ_CC_BYTE3_RW) && (Result == NFCSTATUS_SUCCESS))) + { + Result = (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_FORMAT)); + } + + /* if the call is from read ndef then check for read only or read write access */ + if(((NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_READ_OPE) && + ((NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL3] != + PH_FRINFC_TOPAZ_CC_BYTE3_RW) && + (NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL3] != + PH_FRINFC_TOPAZ_CC_BYTE3_RO))&& (Result == NFCSTATUS_SUCCESS))) + { + Result = (PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_FORMAT)); + } + } + return Result; +} + +extern NFCSTATUS phFriNfc_Tpz_H_ChkSpcVer( phFriNfc_NdefMap_t *NdefMap, + uint8_t VersionNo) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint8_t TagVerNo = VersionNo; + + /* To remove "warning (VS C4100) : unreferenced formal parameter" */ + PHNFC_UNUSED_VARIABLE(NdefMap); + + if ( TagVerNo == 0 ) + { + /*Return Status Error “ Invalid Format”*/ + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,NFCSTATUS_INVALID_FORMAT); + } + else + { + /* calculate the major and minor version number of T3VerNo */ + if( (( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM == + PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(TagVerNo ) )&& + ( PH_NFCFRI_NDEFMAP_NFCDEV_MINOR_VER_NUM >= + PH_NFCFRI_NDEFMAP_GET_MINOR_TAG_VERNO(TagVerNo))) || + (( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM == + PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(TagVerNo ) )&& + ( PH_NFCFRI_NDEFMAP_NFCDEV_MINOR_VER_NUM < + PH_NFCFRI_NDEFMAP_GET_MINOR_TAG_VERNO(TagVerNo) ))) + { + Result = PHNFCSTVAL(CID_NFC_NONE,NFCSTATUS_SUCCESS); + } + else + { + if (( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM < + PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(TagVerNo) ) || + ( PH_NFCFRI_NDEFMAP_NFCDEV_MAJOR_VER_NUM > + PH_NFCFRI_NDEFMAP_GET_MAJOR_TAG_VERNO(TagVerNo))) + { + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,NFCSTATUS_INVALID_FORMAT); + } + } + } + return Result; +} + +static NFCSTATUS phFriNfc_Tpz_H_findNDEFTLV(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + uint8_t index = PH_FRINFC_TOPAZ_VAL4; + + /* If remaining size is less than 3 then, there cant be any + TLV present in the card */ + while((index < PH_FRINFC_TOPAZ_TOTAL_RWBYTES) && + (NdefMap->TopazContainer.RemainingSize >= PH_FRINFC_TOPAZ_VAL3)) + { + switch(NdefMap->TopazContainer.ReadBuffer[index]) + { + case PH_FRINFC_TOPAZ_NDEF_T: + /* To get the length field of the TLV */ + index++; + /* Type and length are not data bytes, so to know the exact + remaining size in the card, the below operation is done */ + NdefMap->TopazContainer.RemainingSize -= PH_FRINFC_TOPAZ_VAL2; + /* Set the card state depending on the L value */ + Result = phFriNfc_MapTool_SetCardState(NdefMap, + (uint32_t)NdefMap->TopazContainer.ReadBuffer[index]); + /* Check the TLV is correct */ + if((NdefMap->TopazContainer.ReadBuffer[index] > + NdefMap->TopazContainer.RemainingSize) || + ((NdefMap->TopazContainer.ReadBuffer[index] == + PH_FRINFC_TOPAZ_VAL0) && (NdefMap->PrevOperation == + PH_FRINFC_NDEFMAP_READ_OPE)) || (Result != NFCSTATUS_SUCCESS)) + { + /* L field value cant be greater than the remaining size, so error */ + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + /* To break out of the loop */ + index = PH_FRINFC_TOPAZ_TOTAL_RWBYTES; + } + else + { + /* So remaining size also changes, according to the position of NDEF TLV */ + NdefMap->TLVStruct.BytesRemainLinTLV = + NdefMap->TopazContainer.ReadBuffer[index]; + + /* Get the byte number */ + NdefMap->TLVStruct.NdefTLVByte = (uint16_t)((index - PH_FRINFC_TOPAZ_VAL1) % + PH_FRINFC_TOPAZ_VAL8); + /* Get the block number */ + NdefMap->TLVStruct.NdefTLVBlock = (uint8_t)(((index - PH_FRINFC_TOPAZ_VAL1) / + PH_FRINFC_TOPAZ_VAL8) + + PH_FRINFC_TOPAZ_VAL1); + /* TLV found flag is set */ + NdefMap->TLVStruct.NdefTLVFoundFlag = PH_FRINFC_TOPAZ_FLAG1; + /* To know the position of V field in the TLV */ + NdefMap->TopazContainer.ByteNumber = (uint8_t)(((NdefMap->TLVStruct.NdefTLVBlock - 1) * 8) + + NdefMap->TLVStruct.NdefTLVByte); + /* To break out of the loop */ + index = PH_FRINFC_TOPAZ_TOTAL_RWBYTES; + Result = NFCSTATUS_SUCCESS; + } + break; + + case PH_FRINFC_TOPAZ_NULL_T: + /* Null TLV, Skip the TLV */ + NdefMap->TopazContainer.RemainingSize--; + index++; + break; + + case PH_FRINFC_TOPAZ_TERM_T: + /* No more TLV present in the card, so error */ + index = PH_FRINFC_TOPAZ_TOTAL_RWBYTES; + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + break; + + default: + /* Go till the length field of the TLV */ + index++; + /* Type and length is not the data, so to know the exact + remaining size in the card, the below operation is done */ + NdefMap->TopazContainer.RemainingSize -= PH_FRINFC_TOPAZ_VAL2; + if(NdefMap->TopazContainer.ReadBuffer[index] > + NdefMap->TopazContainer.RemainingSize) + { + /* L field value cant be greater than the remaining size, so error */ + index = PH_FRINFC_TOPAZ_TOTAL_RWBYTES; + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + else + { + /* Remaining size of the free space available in the card changes, + according to the position of NDEF TLV */ + NdefMap->TopazContainer.RemainingSize = + NdefMap->TopazContainer.RemainingSize - + NdefMap->TopazContainer.ReadBuffer[index]; + + /* Get the position of the next TLV */ + index = (uint8_t)(index + + (NdefMap->TopazContainer.ReadBuffer[index] + + PH_FRINFC_TOPAZ_VAL1)); + } + break; + } + } + + /* If no Ndef TLV found and operation done is read */ + if((NdefMap->TLVStruct.NdefTLVFoundFlag == PH_FRINFC_TOPAZ_FLAG0) && + (NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_READ_OPE)) + { + Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_EOF_NDEF_CONTAINER_REACHED); + } + if((NdefMap->TLVStruct.NdefTLVFoundFlag == PH_FRINFC_TOPAZ_FLAG0) && + ((NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_WRITE_OPE) || + (NdefMap->PrevOperation == PH_FRINFC_NDEFMAP_CHECK_OPE))) + { + NdefMap->TLVStruct.NdefTLVByte = PH_FRINFC_TOPAZ_VAL4; + NdefMap->TLVStruct.NdefTLVBlock = PH_FRINFC_TOPAZ_VAL1; + NdefMap->TopazContainer.ByteNumber = PH_FRINFC_TOPAZ_VAL4; + NdefMap->TopazContainer.RemainingSize = PH_FRINFC_TOPAZ_TOTAL_RWBYTES1; + } + return Result; +} + +static NFCSTATUS phFriNfc_Tpz_H_CpDataToUsrBuf(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + + /* Check the the TLV size and the user size */ + if(NdefMap->ApduBufferSize >= + NdefMap->TLVStruct.BytesRemainLinTLV) + { + /* Copy the read bytes to user buffer till the value (V) + of TLV ends */ + (void)memcpy(NdefMap->ApduBuffer, + &(NdefMap->TopazContainer.ReadBuffer[ + NdefMap->TopazContainer.ByteNumber]), + NdefMap->TLVStruct.BytesRemainLinTLV); + + /* Update the number of read bytes to the user */ + *(NdefMap->NumOfBytesRead) = + NdefMap->TLVStruct.BytesRemainLinTLV; + /* There is no byte to read */ + NdefMap->TopazContainer.ByteNumber = + PH_FRINFC_TOPAZ_VAL0; + /* No further read is possible */ + NdefMap->TopazContainer.ReadWriteCompleteFlag = + PH_FRINFC_TOPAZ_FLAG1; + /* Remaining size in the card can be greater than length field in + the TLV */ + NdefMap->TopazContainer.RemainingSize = + NdefMap->TopazContainer.RemainingSize - + NdefMap->TLVStruct.BytesRemainLinTLV; + /* TLV has been completely read, no more bytes to read */ + NdefMap->TLVStruct.BytesRemainLinTLV = + PH_FRINFC_TOPAZ_VAL0; + } + else + { + /* Copy read bytes till the user buffer size */ + (void)memcpy(NdefMap->ApduBuffer, + &(NdefMap->TopazContainer.ReadBuffer[ + NdefMap->TopazContainer.ByteNumber]), + NdefMap->ApduBufferSize); + + /* Update the number of read bytes to the user */ + *(NdefMap->NumOfBytesRead) = + NdefMap->ApduBufferSize; + /* Get the next byte number to read */ + NdefMap->TopazContainer.ByteNumber = + (uint8_t)(NdefMap->TopazContainer.ByteNumber + + NdefMap->ApduBufferSize); + /* Free space left in the card */ + NdefMap->TopazContainer.RemainingSize + = NdefMap->TopazContainer.RemainingSize + - (uint16_t)NdefMap->ApduBufferSize; + /* Bytes left in the TLV */ + NdefMap->TLVStruct.BytesRemainLinTLV = + NdefMap->TLVStruct.BytesRemainLinTLV - + (uint16_t)NdefMap->ApduBufferSize; + } + return Result; +} + +static NFCSTATUS phFriNfc_Tpz_H_ProWrNMN(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + uint8_t BlockNo = PH_FRINFC_TOPAZ_VAL0, + ByteNo = PH_FRINFC_TOPAZ_VAL0; + + if((NdefMap->TopazContainer.InternalState == + PH_FRINFC_TOPAZ_WR_NMN_0) && + (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == + PH_FRINFC_TOPAZ_VAL0) && + (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) + { + NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE_L_TLV; + /* Get the L field of the TLV block */ + BlockNo = (uint8_t)(((NdefMap->TLVStruct.NdefTLVByte + PH_FRINFC_TOPAZ_VAL1) > + PH_FRINFC_TOPAZ_VAL7)? + (NdefMap->TLVStruct.NdefTLVBlock + PH_FRINFC_TOPAZ_VAL1): + NdefMap->TLVStruct.NdefTLVBlock); + /* Get the L byte */ + ByteNo = (uint8_t)((NdefMap->TLVStruct.NdefTLVByte + PH_FRINFC_TOPAZ_VAL1) % + PH_FRINFC_TOPAZ_VAL8); + + + /* Here the NMN is written 0, so internal state is used */ + NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_L_TLV_0; + /* Write the length value = 0x00 , Write L field of TLV = 0 inside this*/ + Result = phFriNfc_Tpz_H_WrAByte( NdefMap, BlockNo, ByteNo, + PH_FRINFC_TOPAZ_VAL0); + } + else + { + if((NdefMap->TopazContainer.InternalState == + PH_FRINFC_TOPAZ_WR_NMN_E1) && + (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == + PH_FRINFC_TOPAZ_CC_BYTE0) && + (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) + { + /* Card state is initialised or invalid */ + NdefMap->CardState = (uint8_t)((NdefMap->CardState == + PH_NDEFMAP_CARD_STATE_INITIALIZED)? + PH_NDEFMAP_CARD_STATE_READ_WRITE: + NdefMap->CardState); + /* update the length to the user */ + *NdefMap->WrNdefPacketLength = NdefMap->ApduBuffIndex; + Result = NFCSTATUS_SUCCESS; + } + } + return Result; +} + +static NFCSTATUS phFriNfc_Tpz_H_ProWrTLV(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + if((NdefMap->TopazContainer.InternalState == + PH_FRINFC_TOPAZ_WR_L_TLV_0) && + (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == + PH_FRINFC_TOPAZ_VAL0) && + (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) + { + /* state is writing user data to the card */ + NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE; + + NdefMap->TopazContainer.ByteNumber++; + /* Check the byte number */ + phFriNfc_Tpz_H_BlkChk(NdefMap); + + /* Write data to the specified location */ + /* Write the data to the card from the user buffer */ + Result = phFriNfc_Tpz_H_WrAByte( NdefMap, + NdefMap->TopazContainer.CurrentBlock, + NdefMap->TopazContainer.ByteNumber, + NdefMap->ApduBuffer[NdefMap->ApduBuffIndex] + ); + } + else + { + if((NdefMap->TopazContainer.InternalState == + PH_FRINFC_TOPAZ_WR_L_TLV) && + (((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN) && + (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == + NdefMap->ApduBuffIndex)) || + ((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_CUR) && + (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == + (NdefMap->ApduBuffIndex + NdefMap->TLVStruct.BytesRemainLinTLV)))) && + (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) + { + /* Update the L value in the context */ + NdefMap->TLVStruct.BytesRemainLinTLV = + ((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN)? + NdefMap->ApduBuffIndex: + (NdefMap->TLVStruct.BytesRemainLinTLV + NdefMap->ApduBuffIndex)); + + /* Write 0xE1 in block number = 1 and byte number = 0 */ + Result = phFriNfc_Tpz_H_WrByte0ValE1(NdefMap); + } + } + return Result; +} + +static NFCSTATUS phFriNfc_Tpz_H_ProWrUsrData(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + /* send buffer should be equal to receive buffer */ + if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == + NdefMap->ApduBuffer[NdefMap->ApduBuffIndex]) && + (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) + { + /* Increment the index */ + NdefMap->ApduBuffIndex += PH_FRINFC_TOPAZ_VAL1; + + /* Remaining space left in the card is less by one */ + NdefMap->TopazContainer.RemainingSize -= PH_FRINFC_TOPAZ_VAL1; + + /* Increment the byte number */ + NdefMap->TopazContainer.ByteNumber++; + + /* Check the block number */ + phFriNfc_Tpz_H_BlkChk(NdefMap); + + /* check for the user space or the card size */ + if((NdefMap->ApduBufferSize == NdefMap->ApduBuffIndex) || + (NdefMap->TopazContainer.RemainingSize == PH_FRINFC_TOPAZ_VAL0)) + { + /* Set write complete, if the end of card is reached */ + NdefMap->TopazContainer.ReadWriteCompleteFlag = (uint8_t) + ((NdefMap->TopazContainer.RemainingSize == PH_FRINFC_TOPAZ_VAL0)? + PH_FRINFC_TOPAZ_FLAG1:PH_FRINFC_TOPAZ_FLAG0); + + Result = phFriNfc_Tpz_H_WrLByte(NdefMap); + } + else + { + /* State is continued to be in write */ + NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE; + + /* Write the byte to the specified location , and Byte to write */ + Result = phFriNfc_Tpz_H_WrAByte(NdefMap, NdefMap->TopazContainer.CurrentBlock, + NdefMap->TopazContainer.ByteNumber, + NdefMap->ApduBuffer[NdefMap->ApduBuffIndex] + ); + } + } + return Result; +} + +static NFCSTATUS phFriNfc_Tpz_H_WrLByte(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint8_t BlockNo = PH_FRINFC_TOPAZ_VAL0, + ByteNo = PH_FRINFC_TOPAZ_VAL0; + uint8_t TempByteVal = 0; + BlockNo = (uint8_t)(((NdefMap->TLVStruct.NdefTLVByte + + PH_FRINFC_TOPAZ_VAL1) > + PH_FRINFC_TOPAZ_VAL7)? + (NdefMap->TLVStruct.NdefTLVBlock + + PH_FRINFC_TOPAZ_VAL1): + NdefMap->TLVStruct.NdefTLVBlock); + + ByteNo = (uint8_t)((NdefMap->TLVStruct.NdefTLVByte + + PH_FRINFC_TOPAZ_VAL1) % PH_FRINFC_TOPAZ_VAL8); + /* Update L field */ + NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE_L_TLV; + /* Internal state for write */ + NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_L_TLV; + /* Update the length field depending on the offset */ + TempByteVal = (uint8_t) + ((NdefMap->Offset == PH_FRINFC_NDEFMAP_SEEK_BEGIN)? + NdefMap->ApduBuffIndex: + (NdefMap->ApduBuffIndex + + NdefMap->TLVStruct.BytesRemainLinTLV)); + /* Write the L field */ + Result = phFriNfc_Tpz_H_WrAByte(NdefMap, BlockNo, ByteNo,TempByteVal); + return Result; +} + +static NFCSTATUS phFriNfc_Tpz_H_WrByte0ValE1(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + + /* Update L field */ + NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE_NMN; + /* Internal state for writing 0xE1 */ + NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_NMN_E1; + /* Update the length field depending on the offset */ + /* Write the L field */ + Result = phFriNfc_Tpz_H_WrAByte(NdefMap, PH_FRINFC_TOPAZ_VAL1, + PH_FRINFC_TOPAZ_VAL0,PH_FRINFC_TOPAZ_CC_BYTE0); + return Result; +} + +static void phFriNfc_Tpz_H_Complete(phFriNfc_NdefMap_t *NdefMap, + NFCSTATUS Status) +{ + /* set the state back to the Reset_Init state*/ + NdefMap->State = PH_FRINFC_NDEFMAP_STATE_RESET_INIT; + + /* set the completion routine*/ + NdefMap->CompletionRoutine[NdefMap->TopazContainer.CRIndex]. + CompletionRoutine(NdefMap->CompletionRoutine->Context, Status); +} + +static void phFriNfc_Tpz_H_BlkChk(phFriNfc_NdefMap_t *NdefMap) +{ + NdefMap->TopazContainer.CurrentBlock = + (uint8_t)((NdefMap->TopazContainer.ByteNumber > + PH_FRINFC_TOPAZ_VAL7)? + (NdefMap->TopazContainer.CurrentBlock + + PH_FRINFC_TOPAZ_VAL1): + NdefMap->TopazContainer.CurrentBlock); + + NdefMap->TopazContainer.ByteNumber = (uint8_t)(NdefMap->TopazContainer.ByteNumber % + PH_FRINFC_TOPAZ_VAL8); +} + +static NFCSTATUS phFriNfc_Tpz_H_ChkCCinChkNdef(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + + if(NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL0] == + PH_FRINFC_TOPAZ_CC_BYTE0) + { + /* Check the most significant nibble of byte 3 (RWA) = 0 */ + Result = (((NdefMap->TopazContainer.ReadBuffer[PH_FRINFC_TOPAZ_VAL3] & + PH_FRINFC_TOPAZ_BYTE3_MSB)== PH_FRINFC_TOPAZ_VAL0)? + NFCSTATUS_SUCCESS: + Result); + + /* Card size is initialised */ + NdefMap->CardMemSize = NdefMap->TopazContainer.RemainingSize = + ((Result == NFCSTATUS_SUCCESS)? + (PH_FRINFC_TOPAZ_MAX_CARD_SZ - PH_FRINFC_TOPAZ_VAL4): + NdefMap->CardMemSize); + } + + if (NdefMap->CardState != PH_NDEFMAP_CARD_STATE_READ_ONLY) + { + NdefMap->CardState = (uint8_t)((Result == NFCSTATUS_SUCCESS)? + PH_NDEFMAP_CARD_STATE_INITIALIZED: + PH_NDEFMAP_CARD_STATE_INVALID); + } + + return Result; +} + +static void phFriNfc_Tpz_H_ChkLockBits(phFriNfc_NdefMap_t *NdefMap) +{ + /* Set the card state */ + NdefMap->CardState = (uint8_t) + (((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_LOCKBIT_BYTENO_0] == + PH_FRINFC_TOPAZ_LOCKBIT_BYTE114) && + ((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_LOCKBIT_BYTENO_1] == + PH_FRINFC_TOPAZ_LOCKBIT_BYTE115_1) || + (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_LOCKBIT_BYTENO_1] == + PH_FRINFC_TOPAZ_LOCKBIT_BYTE115_2)))? + PH_NDEFMAP_CARD_STATE_READ_WRITE: + PH_NDEFMAP_CARD_STATE_READ_ONLY); + + /* Set the card state from CC bytes */ + if (NdefMap->CardState == PH_NDEFMAP_CARD_STATE_READ_WRITE) + { + if (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_CC_BYTENO_3] == PH_FRINFC_TOPAZ_CC_READWRITE) + { + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_WRITE; + } + else if (NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_CC_BYTENO_3] == PH_FRINFC_TOPAZ_CC_READONLY) + { + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_ONLY; + } + else + { + NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INVALID; + } + } +} + +static NFCSTATUS phFriNfc_Tpz_H_WrCCorTLV(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = NFCSTATUS_SUCCESS; + uint8_t ByteNo = PH_FRINFC_TOPAZ_VAL0, + BlockNo = PH_FRINFC_TOPAZ_VAL0; + uint8_t TempByteVal = 0; + switch(NdefMap->TopazContainer.InternalState) + { + case PH_FRINFC_TOPAZ_WR_CC_BYTE0: + /* To write the CC bytes */ + TempByteVal = PH_FRINFC_TOPAZ_CC_BYTE0; + ByteNo = (uint8_t)PH_FRINFC_TOPAZ_VAL0; + BlockNo = PH_FRINFC_TOPAZ_VAL1; + break; + + case PH_FRINFC_TOPAZ_WR_CC_BYTE1: + /* To write the CC bytes */ + TempByteVal = PH_FRINFC_TOPAZ_CC_BYTE1; + ByteNo = (uint8_t)PH_FRINFC_TOPAZ_VAL1; + BlockNo = PH_FRINFC_TOPAZ_VAL1; + break; + + case PH_FRINFC_TOPAZ_WR_CC_BYTE2: + /* To write the CC bytes */ + TempByteVal = PH_FRINFC_TOPAZ_CC_BYTE2_MAX; + ByteNo = (uint8_t)PH_FRINFC_TOPAZ_VAL2; + BlockNo = PH_FRINFC_TOPAZ_VAL1; + break; + + case PH_FRINFC_TOPAZ_WR_CC_BYTE3: + /* To write the CC bytes */ + TempByteVal = PH_FRINFC_TOPAZ_CC_BYTE3_RW; + ByteNo = (uint8_t)PH_FRINFC_TOPAZ_VAL3; + BlockNo = PH_FRINFC_TOPAZ_VAL1; + break; + + case PH_FRINFC_TOPAZ_WR_T_OF_TLV: + default: + /* To write the NDEF TLV (if not present) */ + TempByteVal = PH_FRINFC_TOPAZ_NDEF_T; + ByteNo = (uint8_t)NdefMap->TLVStruct.NdefTLVByte; + BlockNo = NdefMap->TLVStruct.NdefTLVBlock; + break; + } + NdefMap->State = PH_FRINFC_TOPAZ_STATE_WR_CC_OR_TLV; + Result = phFriNfc_Tpz_H_WrAByte( NdefMap, BlockNo, ByteNo,TempByteVal); + return Result; +} + +static NFCSTATUS phFriNfc_Tpz_H_ProCCTLV(phFriNfc_NdefMap_t *NdefMap) +{ + NFCSTATUS Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + switch(NdefMap->TopazContainer.InternalState) + { + case PH_FRINFC_TOPAZ_WR_CC_BYTE0: + /* Process the CC byte */ + /* Check the response */ + if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == + PH_FRINFC_TOPAZ_CC_BYTE0) && + (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) + { + NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_CC_BYTE1; + Result = phFriNfc_Tpz_H_WrCCorTLV(NdefMap); + } + break; + + case PH_FRINFC_TOPAZ_WR_CC_BYTE1: + /* Process the CC byte */ + /* Check the response */ + if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == + PH_FRINFC_TOPAZ_CC_BYTE1) && + (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) + { + NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_CC_BYTE2; + Result = phFriNfc_Tpz_H_WrCCorTLV(NdefMap); + } + break; + + case PH_FRINFC_TOPAZ_WR_CC_BYTE2: + /* Process the CC byte */ + /* Check the response */ + if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == + PH_FRINFC_TOPAZ_CC_BYTE2_MAX) && + (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) + { + NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_CC_BYTE3; + Result = phFriNfc_Tpz_H_WrCCorTLV(NdefMap); + } + break; + + case PH_FRINFC_TOPAZ_WR_CC_BYTE3: + /* Process the CC byte */ + /* Check the response */ + if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == + PH_FRINFC_TOPAZ_CC_BYTE3_RW) && + (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) + { + NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_T_OF_TLV; + Result = phFriNfc_Tpz_H_WrCCorTLV(NdefMap); + } + break; + + case PH_FRINFC_TOPAZ_WR_T_OF_TLV: + default: + /* Check the response */ + if((NdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL0] == + PH_FRINFC_TOPAZ_NDEF_T) && + (*NdefMap->SendRecvLength == PH_FRINFC_TOPAZ_VAL1)) + { + /* Increment the Byte Number */ + NdefMap->TopazContainer.ByteNumber++; + /* Check the block and byte number */ + phFriNfc_Tpz_H_BlkChk(NdefMap); + /* Process the T of NDEF TLV */ + NdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE_NMN; + + /* Here the NMN is written 0, so internal state is used */ + NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_WR_NMN_0; + + /*Inside this call Write NMN (block number 1 and byte number 0) = 0 */ + Result = phFriNfc_Tpz_H_WrAByte( NdefMap, PH_FRINFC_TOPAZ_VAL1, + PH_FRINFC_TOPAZ_VAL0,PH_FRINFC_TOPAZ_VAL0); + } + break; + } + return Result; +} + +#ifdef UNIT_TEST +#include <phUnitTestNfc_Topaz_static.c> +#endif + +#endif /* PH_FRINFC_MAP_TOPAZ_DISABLED */ |