summaryrefslogtreecommitdiffstats
path: root/src/phFriNfc_TopazMap.c
diff options
context:
space:
mode:
authorNick Pelly <npelly@google.com>2010-09-23 12:47:58 -0700
committerNick Pelly <npelly@google.com>2010-09-23 13:53:18 -0700
commit5d9927ba30ba449badb9f6df0fbeb4d6aedc6e2a (patch)
tree190f9251c6db03d3550ec7f30b51a2561c01d9cf /src/phFriNfc_TopazMap.c
parent4ff7c86a2c706b150078274455406f1b04966e1a (diff)
downloadexternal_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.c1859
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 */