summaryrefslogtreecommitdiffstats
path: root/src/phFriNfc_TopazDynamicMap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/phFriNfc_TopazDynamicMap.c')
-rw-r--r--src/phFriNfc_TopazDynamicMap.c3800
1 files changed, 3800 insertions, 0 deletions
diff --git a/src/phFriNfc_TopazDynamicMap.c b/src/phFriNfc_TopazDynamicMap.c
new file mode 100644
index 0000000..dc99a43
--- /dev/null
+++ b/src/phFriNfc_TopazDynamicMap.c
@@ -0,0 +1,3800 @@
+/*
+ * 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_TopazDynamicMap.c
+* \brief NFC Ndef Mapping For Remote Devices.
+*
+* Project: NFC-FRI
+*
+* $Date: Tue Jun 8 17:19:18 2010 $
+* $Author: ing02260 $
+* $Revision: 1.38 $
+* $Aliases: NFC_FRI1.1_WK1023_R35_1 $
+*
+*/
+
+
+
+#include <phFriNfc_NdefMap.h>
+#include <phFriNfc_TopazMap.h>
+#include <phFriNfc_MapTools.h>
+#include <phFriNfc_OvrHal.h>
+
+#if !(defined(PH_FRINFC_MAP_TOPAZ_DISABLED ) || defined (PH_FRINFC_MAP_TOPAZ_DYNAMIC_DISABLED ))
+
+/*! \ingroup grp_file_attributes
+* \name NDEF Mapping
+*
+* File: \ref phFriNfcNdefMap.c
+*
+*/
+/*@{*/
+#define PHFRINFCTOPAZMAP_FILEREVISION "$Revision: 1.38 $"
+#define PHFRINFCTOPAZMAP_FILEALIASES "$Aliases: NFC_FRI1.1_WK1023_R35_1 $"
+/*@}*/
+/*!
+* \name Topaz Mapping - Helper data structures and macros
+*
+*/
+/*@{*/
+
+/********************************** Start of data structures *********************************/
+
+
+/*!
+* \brief \copydoc page_ovr enum for the topaz sequence of execution.
+*/
+typedef enum phFriNfc_Tpz_ParseSeq
+{
+ LOCK_T_TLV,
+ LOCK_L_TLV,
+ LOCK_V_TLV,
+ MEM_T_TLV,
+ MEM_L_TLV,
+ MEM_V_TLV,
+ NDEF_T_TLV,
+ NDEF_L_TLV,
+ NDEF_V_TLV
+}phFriNfc_Tpz_ParseSeq_t;
+
+typedef enum phFriNfc_Tpz_WrSeq
+{
+ WR_NDEF_T_TLV,
+ WR_NMN_0,
+ WR_LEN_1_0,
+ WR_LEN_2_0,
+ WR_LEN_3_0,
+ WR_DATA,
+ WR_DATA_READ_REQD,
+ WR_LEN_1_VALUE,
+ WR_LEN_2_VALUE,
+ WR_LEN_3_VALUE,
+ WR_NMN_E1
+}phFriNfc_Tpz_WrSeq_t;
+
+/********************************** End of data structures *********************************/
+
+/********************************** Start of Macros *********************************/
+/* New state for TOPAZ dynamic card*/
+#define PH_FRINFC_TOPAZ_STATE_RD_FOR_WR_NDEF (0x10U)
+
+#define NIBBLE_SIZE (0x04U)
+/* Byte shifting for the topaz */
+#define TOPAZ_BYTE_SHIFT (0x08U)
+/* Lock and memory control TLV length. Always 3 bytes */
+#define TOPAZ_MEM_LOCK_TLV_LENGTH (0x03U)
+/* UID byte length */
+#define TOPAZ_UID_BYTES_LENGTH (0x08U)
+
+/* Number os static lock and reserved bytes */
+#define TOPAZ_STATIC_LOCK_RES_BYTES (0x18U)
+/* Number of static lock and reserved memory. This value is 3 (because
+ block number D, E and F are lock and reserved blocks */
+#define TOPAZ_STATIC_LOCK_BLOCK_AREAS (0x03U)
+/* First lock or reserved block in the static area of the card */
+#define TOPAZ_STATIC_LOCK_FIRST_BLOCK_NO (0x0DU)
+/* First lock or reserved byte number in the static area of the card */
+#define TOPAZ_STATIC_LOCK_RES_START (0x68U)
+/* End lock or reserved byte number in the static area of the card */
+#define TOPAZ_STATIC_LOCK_RES_END (0x80U)
+
+/* CC byte length */
+#define TOPAZ_CC_BYTES_LENGTH (0x04U)
+
+/* In TOPAZ card each block has 8 bytes */
+#define TOPAZ_BYTES_PER_BLOCK (0x08U)
+/* Each byte has 8 bites */
+#define TOPAZ_BYTE_SIZE_IN_BITS (0x08U)
+
+/* This mask is to get the least significant NIBBLE from a BYTE */
+#define TOPAZ_NIBBLE_MASK (0x0FU)
+/* This is used to mask the least significant BYTE from a TWO BYTE value */
+#define TOPAZ_BYTE_LENGTH_MASK (0x00FFU)
+
+/* Total segments in TOPAZ 512 bytes card. Each segment = 128 bytes,
+so there are 4 segements in the card */
+#define TOPAZ_TOTAL_SEG_TO_READ (0x04U)
+/* SPEC version value shall be 0x10 as per the TYPE 1 specification */
+#define TOPAZ_SPEC_VERSION (0x10U)
+
+/* Response length for READ SEGMENT command is 128 bytes */
+#define TOPAZ_SEGMENT_READ_LENGTH (0x80U)
+/* Response length for WRITE-1E command is 1 byte */
+#define TOPAZ_WRITE_1_RESPONSE (0x01U)
+/* Response length for WRITE-8E command is 8 bytes */
+#define TOPAZ_WRITE_8_RESPONSE (0x08U)
+/* Response length for READ-8 command is 8 bytes */
+#define TOPAZ_READ_8_RESPONSE (0x08U)
+
+/* Data bytes that can be written for the WRITE-8E command is 8 bytes */
+#define TOPAZ_WRITE_8_DATA_LENGTH (0x08U)
+
+/* Get the exact byte address of the card from the segment number
+ and the parse index of each segment */
+#define TOPAZ_BYTE_ADR_FROM_SEG(seg, parse_index) \
+ (((seg) * TOPAZ_SEGMENT_READ_LENGTH) + (parse_index))
+
+/* Get the segment number of the card from the byte address */
+#define TOPAZ_SEG_FROM_BYTE_ADR(byte_addr) \
+ ((byte_addr) / TOPAZ_SEGMENT_READ_LENGTH)
+/* Get the block number of the card from the byte address */
+#define TOPAZ_BLK_FROM_BYTE_ADR(byte_addr) \
+ ((byte_addr) / TOPAZ_BYTES_PER_BLOCK)
+/* Get the block offset of a block number of the card from the byte address */
+#define TOPAZ_BYTE_OFFSET_FROM_BYTE_ADR(byte_addr) \
+ ((byte_addr) % TOPAZ_BYTES_PER_BLOCK)
+/* Get the exact byte address of the card from the block number
+ and the byte offset of the block number */
+#define TOPAZ_BYTE_ADR_FROM_BLK(block_no, byte_offset) \
+ (((block_no) * TOPAZ_BYTES_PER_BLOCK) + (byte_offset))
+/* To increment the block number and if block number overlaps with the
+ static lock and reserved blocks, then skip the blocks */
+#define TOPAZ_INCREMENT_SKIP_STATIC_BLOCK(block_no) \
+ ((((block_no) + 1) == TOPAZ_STATIC_LOCK_FIRST_BLOCK_NO) ? \
+ (((block_no) + 1) + TOPAZ_STATIC_LOCK_BLOCK_AREAS) : \
+ ((block_no) + 1))
+
+/********************************** End of Macros *********************************/
+
+/*@}*/
+
+
+/*!
+* \name Topaz Mapping - Helper Functions
+*
+*/
+/*@{*/
+
+/*!
+* \brief \copydoc page_ovr Helper function for Topaz. This function shall read defined
+* bytes from the card.
+*/
+static
+NFCSTATUS
+phFriNfc_Tpz_H_NxpRead (
+ phFriNfc_NdefMap_t *psNdefMap);
+
+/*!
+* \brief \copydoc page_ovr Helper function for Topaz. This function shall process
+* received read id command.
+*/
+static
+NFCSTATUS
+phFriNfc_Tpz_H_ChkReadID (
+ phFriNfc_NdefMap_t *psNdefMap);
+
+
+/*!
+* \brief \copydoc page_ovr Helper function for Topaz. This function shall process
+* read response.
+*/
+static
+NFCSTATUS
+phFriNfc_Tpz_H_ProReadResp (
+ phFriNfc_NdefMap_t *psNdefMap);
+
+/*!
+* \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 lock bits and set a card state
+*/
+static
+NFCSTATUS
+phFriNfc_Tpz_H_ChkLockBits (
+ phFriNfc_NdefMap_t *psNdefMap);
+
+/*!
+* \brief \copydoc page_ovr Helper function for Topaz. This function writes defined
+* bytes into the card
+*/
+static
+NFCSTATUS
+phFriNfc_Tpz_H_NxpWrite (
+ phFriNfc_NdefMap_t *psNdefMap,
+ uint8_t *p_write_data,
+ uint8_t wr_data_len);
+
+
+/*!
+* \brief \copydoc page_ovr Helper function for Topaz. This function parses the read bytes
+* till the NDEF TLV is found. Also, it returns error if it founds wrong TLVs.
+*/
+static
+NFCSTATUS
+phFriNfc_Tpz_H_ParseTLVs (
+ phFriNfc_NdefMap_t *psNdefMap);
+
+/*!
+ * \brief \copydoc page_ovr Helper function for Topaz. This function parses the read bytes
+ * till the TYPE of the LOCK control TLV is found.
+ * Also, it returns error if it founds wrong TYPE.
+ */
+static
+NFCSTATUS
+phFriNfc_Tpz_H_ParseLockTLVType (
+ phFriNfc_NdefMap_t *psNdefMap,
+ uint8_t *p_parse_data,
+ uint16_t *p_parse_index,
+ uint16_t total_len_to_parse,
+ phFriNfc_Tpz_ParseSeq_t *seq_to_execute);
+
+/*!
+ * \brief \copydoc page_ovr Helper function for Topaz. This function parses the read bytes
+ * till the TYPE of the MEMORY control TLV is found.
+ * Also, it returns error if it founds wrong TYPE.
+ */
+static
+NFCSTATUS
+phFriNfc_Tpz_H_ParseMemTLVType (
+ phFriNfc_NdefMap_t *psNdefMap,
+ uint8_t *p_parse_data,
+ uint16_t *p_parse_index,
+ uint16_t total_len_to_parse,
+ phFriNfc_Tpz_ParseSeq_t *seq_to_execute);
+
+/*!
+ * \brief \copydoc page_ovr Helper function for Topaz. This function parses the read bytes
+ * till the TYPE of the NDEF control TLV is found.
+ * Also, it returns error if it founds wrong TYPE.
+ */
+static
+NFCSTATUS
+phFriNfc_Tpz_H_ParseNdefTLVType (
+ phFriNfc_NdefMap_t *psNdefMap,
+ uint8_t *p_parse_data,
+ uint16_t *p_parse_index,
+ uint16_t total_len_to_parse,
+ phFriNfc_Tpz_ParseSeq_t *seq_to_execute);
+
+/*!
+ * \brief \copydoc page_ovr Helper function for Topaz. This function gets the lock bytes
+ * information.
+ */
+static
+NFCSTATUS
+phFriNfc_Tpz_H_GetLockBytesInfo (
+ phFriNfc_NdefMap_t *psNdefMap,
+ uint8_t *p_lock_info);
+
+/*!
+ * \brief \copydoc page_ovr Helper function for Topaz. This function gets the reserved bytes
+ * information.
+ */
+static
+NFCSTATUS
+phFriNfc_Tpz_H_GetMemBytesInfo (
+ phFriNfc_NdefMap_t *psNdefMap,
+ uint8_t *p_mem_info);
+
+/*!
+ * \brief \copydoc page_ovr Helper function for Topaz. This function copies and checks the CC bytes.
+ * This function checks for the lock bytes value and card state also.
+ */
+static
+NFCSTATUS
+phFriNfc_Tpz_H_CheckCCBytes (
+ phFriNfc_NdefMap_t *psNdefMap);
+
+/*!
+ * \brief \copydoc page_ovr Helper function for Topaz. This function checks the CC bytes.
+ * If .
+ */
+static
+NFCSTATUS
+phFriNfc_Tpz_H_CheckCCBytesForWrite (
+ phFriNfc_NdefMap_t *psNdefMap);
+
+
+/*!
+ * \brief \copydoc page_ovr Helper function for Topaz. This function copies the read bytes.
+ * This function also checks for the lock and reserved bytes and skips the bytes before copying it
+ * in the buffer.
+ */
+static
+NFCSTATUS
+phFriNfc_Tpz_H_CopyReadData (
+ phFriNfc_NdefMap_t *psNdefMap);
+
+/*!
+ * \brief \copydoc page_ovr Helper function for Topaz. This function copies the stored read bytes.
+ * This function is used only for the offset " PH_FRINFC_NDEFMAP_SEEK_CUR ".
+ */
+static
+NFCSTATUS
+phFriNfc_Tpz_H_RemainingReadDataCopy (
+ phFriNfc_NdefMap_t *psNdefMap);
+
+/*!
+ * \brief \copydoc page_ovr Helper function for Topaz. This function gives the exact byte address
+ * of the value field after the NDEF TYPE field
+ */
+static
+uint16_t
+phFriNfc_Tpz_H_GetNDEFValueFieldAddrForRead (
+ phFriNfc_NdefMap_t *psNdefMap);
+
+/*!
+ * \brief \copydoc page_ovr Helper function for Topaz. This function gives the exact byte address
+ * of the value field after the NDEF TYPE field
+ */
+static
+uint16_t
+phFriNfc_Tpz_H_GetNDEFValueFieldAddrForWrite (
+ phFriNfc_NdefMap_t *psNdefMap,
+ uint16_t size_to_write);
+
+/*!
+ * \brief \copydoc page_ovr Helper function for Topaz. This function gives the number of bytes to skip.
+ * This function checks the input byte address and checks if any lock or reserved bytes matches with the
+ * given address. if yes, then it will return number od bytes to skip.
+ */
+static
+uint16_t
+phFriNfc_Tpz_H_GetSkipSize (
+ phFriNfc_NdefMap_t *psNdefMap,
+ uint16_t byte_adr_card);
+
+/*!
+ * \brief \copydoc page_ovr Helper function for Topaz. This function gives the actual data that can
+ * be read and written in the card.
+ * This function checks for the lock and reserved bytes and subtracts the remaining size to give the
+ * actual size.
+ */
+static
+NFCSTATUS
+phFriNfc_Tpz_H_ActualCardSize (
+ phFriNfc_NdefMap_t *psNdefMap);
+
+/*!
+ * \brief \copydoc page_ovr Helper function for Topaz. This function processes the response for
+ * the write data
+ */
+static
+NFCSTATUS
+phFriNfc_Tpz_H_ProWrResp (
+ phFriNfc_NdefMap_t *psNdefMap);
+
+/*!
+ * \brief \copydoc page_ovr Helper function for Topaz. This function processes the read 8 commands,
+ * that is required for writing the data
+ */
+static
+NFCSTATUS
+phFriNfc_Tpz_H_ProRdForWrResp (
+ phFriNfc_NdefMap_t *psNdefMap);
+
+/*!
+ * \brief \copydoc page_ovr Helper function for Topaz. This function copies the user data to the
+ * write buffer and writes the data to the card. If the lock or memory blocks are in between the
+ * write data, then read the current block
+ */
+static
+NFCSTATUS
+phFriNfc_Tpz_H_CopySendWrData (
+ phFriNfc_NdefMap_t *psNdefMap);
+
+/*!
+ * \brief \copydoc page_ovr Helper function for Topaz. This function compares the input block
+ * number with lock bytes block number and returns the p_skip_size which is the lock bytes
+ * size
+ */
+static
+uint16_t
+phFriNfc_Tpz_H_CompareLockBlocks (
+ phFriNfc_NdefMap_t *psNdefMap,
+ uint8_t block_no,
+ uint16_t *p_skip_size);
+
+/*!
+ * \brief \copydoc page_ovr Helper function for Topaz. This function compares the input block
+ * number with reserved bytes block number and returns the p_skip_size which is the reserved bytes
+ * size
+ */
+static
+uint16_t
+phFriNfc_Tpz_H_CompareMemBlocks (
+ phFriNfc_NdefMap_t *psNdefMap,
+ uint8_t block_no,
+ uint16_t *p_skip_size);
+
+/*!
+ * \brief \copydoc page_ovr Helper function for Topaz. This function copies the read data and update
+ * the user bytes by skipping lock or memory control areas. Also, used while updating the value field
+ * skips the initial bytes and to start at the proper value field byte offset of the block
+ */
+static
+NFCSTATUS
+phFriNfc_Tpz_H_CopyReadDataAndWrite (
+ phFriNfc_NdefMap_t *psNdefMap);
+
+
+/*!
+ * \brief \copydoc page_ovr Helper function for Topaz. This function reads the required block for writing,
+ * as some of the bytes shall not be overwritten
+ */
+static
+NFCSTATUS
+phFriNfc_Tpz_H_RdForWrite (
+ phFriNfc_NdefMap_t *psNdefMap);
+
+/*!
+ * \brief \copydoc page_ovr Helper function for Topaz. This function reads the length block for writing,
+ * updates the length bytes with 0
+ */
+static
+NFCSTATUS
+phFriNfc_Tpz_H_UpdateLenFieldZeroAfterRead (
+ phFriNfc_NdefMap_t *psNdefMap);
+
+/*!
+ * \brief \copydoc page_ovr Helper function for Topaz. This function reads the length block for writing,
+ * updates the length bytes with exact bytes that was written in the card
+ */
+static
+NFCSTATUS
+phFriNfc_Tpz_H_UpdateLenFieldValuesAfterRead (
+ phFriNfc_NdefMap_t *psNdefMap);
+
+/*!
+ * \brief \copydoc page_ovr Helper function for Topaz. This function writes the NDEF TYPE of the
+ * NDEF TLV to the specific byte address. This function is called only if the previous write is
+ * failed or there is no NDEF TLV with correct CC bytes
+ */
+static
+NFCSTATUS
+phFriNfc_Tpz_H_UpdateNdefTypeField (
+ phFriNfc_NdefMap_t *psNdefMap);
+
+
+/*!
+* \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_TopazDynamicMap_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.Cur_RW_Index = PH_FRINFC_TOPAZ_VAL0;
+ NdefMap->TopazContainer.CurrentSeg = 0;
+ NdefMap->TopazContainer.NdefTLVByteAddress = 0;
+ NdefMap->CardState = PH_NDEFMAP_CARD_STATE_INVALID;
+
+ NdefMap->TopazContainer.CurrentBlock = 0;
+ NdefMap->TopazContainer.WriteSeq = 0;
+ NdefMap->TopazContainer.ExpectedSeq = 0;
+
+ /* Set card state */
+ NdefMap->CardType = PH_FRINFC_NDEFMAP_TOPAZ_DYNAMIC_CARD;
+
+ /* Change the state to Read */
+ NdefMap->State = PH_FRINFC_TOPAZ_STATE_READ;
+
+ NdefMap->TopazContainer.InternalState = PH_FRINFC_TOPAZ_DYNAMIC_INIT_CHK_NDEF;
+#ifdef TOPAZ_RAW_SUPPORT
+
+ *NdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_RSEG;
+
+#else
+
+#ifdef PH_HAL4_ENABLE
+ NdefMap->Cmd.JewelCmd = phHal_eJewel_ReadSeg;
+#else
+ NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead;
+#endif
+
+#endif /* #ifdef TOPAZ_RAW_SUPPORT */
+
+ Result = phFriNfc_Tpz_H_NxpRead(NdefMap);
+
+ }
+ 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_TopazDynamicMap_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 = 0;
+ /* 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;
+ NdefMap->TopazContainer.SkipLockBlkFlag = 0;
+
+ NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_READ_OPE;
+ if ((PH_FRINFC_NDEFMAP_SEEK_CUR == Offset) &&
+ (TRUE == NdefMap->TopazContainer.ReadWriteCompleteFlag))
+ {
+ Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_EOF_NDEF_CONTAINER_REACHED);
+ }
+ else if ((PH_NDEFMAP_CARD_STATE_INITIALIZED ==
+ NdefMap->CardState) ||
+ (0 == NdefMap->TopazContainer.ActualNDEFMsgSize))
+ {
+ /* Length field of NDEF TLV is 0, so read cannot proceed */
+ Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_READ_FAILED);
+ }
+ else if ((PH_FRINFC_NDEFMAP_SEEK_BEGIN == Offset) ||
+ (PH_FRINFC_NDEFMAP_READ_OPE != NdefMap->PrevOperation))
+ {
+ /* If previous operation is not read then the read shall
+ start from BEGIN */
+ NdefMap->Offset = PH_FRINFC_NDEFMAP_SEEK_BEGIN;
+ /* Initialise byte number */
+ NdefMap->TopazContainer.Cur_RW_Index = PH_FRINFC_TOPAZ_VAL0;
+
+ NdefMap->TopazContainer.RemainingReadSize = 0;
+ NdefMap->TopazContainer.ReadBufferSize = 0;
+ NdefMap->TopazContainer.ReadWriteCompleteFlag = FALSE;
+ NdefMap->TopazContainer.CurrentBlock = 0;
+ NdefMap->TopazContainer.WriteSeq = 0;
+
+ NdefMap->TopazContainer.CurrentSeg = (uint8_t)TOPAZ_SEG_FROM_BYTE_ADR (
+ phFriNfc_Tpz_H_GetNDEFValueFieldAddrForRead (NdefMap));
+
+ /* Change the state to Read ID */
+ NdefMap->State = PH_FRINFC_TOPAZ_STATE_READID;
+ /*Change the state to Read ID*/
+ NdefMap->TopazContainer.ReadWriteCompleteFlag = 0;
+#ifdef TOPAZ_RAW_SUPPORT
+
+ NdefMap->SendRecvBuf[0] = 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_NxpRead(NdefMap);
+
+ }
+ else
+ {
+ /* Change the state to Read */
+ NdefMap->State = PH_FRINFC_TOPAZ_STATE_READ;
+ Result = phFriNfc_Tpz_H_RemainingReadDataCopy (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_TopazDynamicMap_WrNdef( 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;
+ /* Index to know the length written */
+ NdefMap->ApduBuffIndex = 0;
+ /* 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 = 0;
+ /* 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;
+
+ /* Update the previous operation to write operation */
+ NdefMap->PrevOperation = PH_FRINFC_NDEFMAP_WRITE_OPE;
+
+ if (PH_NDEFMAP_CARD_STATE_READ_ONLY == NdefMap->CardState)
+ {
+ Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_WRITE_FAILED);
+ }
+ else if ((PH_FRINFC_NDEFMAP_SEEK_CUR == Offset) &&
+ (TRUE == NdefMap->TopazContainer.ReadWriteCompleteFlag))
+ {
+ /* Offset = Current, but the read has reached the End of Card */
+ Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_EOF_NDEF_CONTAINER_REACHED);
+ }
+ else if (0 == NdefMap->TopazContainer.NdefTLVByteAddress)
+ {
+ /* No NDEF TLV found in the card, so write not possible */
+ Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_NO_NDEF_SUPPORT);
+ }
+ else if ((PH_FRINFC_NDEFMAP_SEEK_BEGIN == Offset) ||
+ (PH_FRINFC_NDEFMAP_WRITE_OPE != NdefMap->PrevOperation))
+ {
+ NdefMap->Offset = PH_FRINFC_NDEFMAP_SEEK_BEGIN;
+ /* Initialise byte number */
+ NdefMap->TopazContainer.Cur_RW_Index = PH_FRINFC_TOPAZ_VAL0;
+ /* State has to be changed */
+ NdefMap->State = PH_FRINFC_TOPAZ_STATE_READ;
+ NdefMap->TopazContainer.ReadWriteCompleteFlag = FALSE;
+
+ NdefMap->TopazContainer.CurrentSeg = 0;
+ NdefMap->TopazContainer.CurrentBlock = 1;
+ NdefMap->TopazContainer.WriteSeq = 0;
+
+#ifdef TOPAZ_RAW_SUPPORT
+
+ *NdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_READ8;
+
+#else
+
+ /* Topaz command = Jewel Nxp Read */
+#ifdef PH_HAL4_ENABLE
+ NdefMap->Cmd.JewelCmd = phHal_eJewel_Read;
+#else
+ NdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead;
+#endif
+
+ NdefMap->Cmd.JewelCmd = phHal_eJewel_Read8;
+
+#endif /* #ifdef TOPAZ_RAW_SUPPORT */
+ /* Call read segment */
+ Result = phFriNfc_Tpz_H_NxpRead (NdefMap);
+ }
+ else
+ {
+#if 0
+ /* This part is to handle the Current offset,
+ Current offset is not yet validated */
+ Result = phFriNfc_Tpz_H_NxpWrite(NdefMap);
+#endif /* #if 0 */
+ }
+
+ 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_TopazDynamicMap_Process( void *Context,
+ NFCSTATUS Status)
+{
+
+ phFriNfc_NdefMap_t *NdefMap;
+
+ NdefMap = (phFriNfc_NdefMap_t *)Context;
+
+
+ if((NFCSTATUS_SUCCESS & PHNFCSTBLOWER) == (Status & PHNFCSTBLOWER))
+ {
+ switch(NdefMap->State)
+ {
+ case PH_FRINFC_TOPAZ_STATE_READ:
+ {
+ Status = phFriNfc_Tpz_H_ProReadResp (NdefMap);
+ break;
+ }
+
+ case PH_FRINFC_TOPAZ_STATE_WRITE:
+ {
+ Status = phFriNfc_Tpz_H_ProWrResp (NdefMap);
+ break;
+ }
+
+ case PH_FRINFC_TOPAZ_STATE_RD_FOR_WR_NDEF:
+ {
+ Status = phFriNfc_Tpz_H_ProRdForWrResp (NdefMap);
+ break;
+ }
+
+ case PH_FRINFC_TOPAZ_STATE_READID:
+ {
+ Status = phFriNfc_Tpz_H_ChkReadID(NdefMap);
+ break;
+ }
+
+ default:
+ {
+ Status = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_INVALID_DEVICE_REQUEST);
+ break;
+ }
+ }
+ }
+
+ /* Call for the Completion Routine*/
+ if(Status != NFCSTATUS_PENDING)
+ {
+ phFriNfc_Tpz_H_Complete(NdefMap, Status);
+ }
+}
+
+static
+NFCSTATUS
+phFriNfc_Tpz_H_ProWrResp (
+ phFriNfc_NdefMap_t *psNdefMap)
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ phFriNfc_TopazCont_t *ps_tpz_info = NULL;
+ phFriNfc_Tpz_WrSeq_t write_seq;
+ uint8_t write_buf[] = {0x00};
+ uint8_t write_index = 0;
+ uint16_t write_len = 0;
+ uint16_t len_byte_addr = 0;
+
+ ps_tpz_info = &(psNdefMap->TopazContainer);
+ write_seq = (phFriNfc_Tpz_WrSeq_t)(ps_tpz_info->WriteSeq);
+ write_len = (uint16_t)((psNdefMap->ApduBufferSize < ps_tpz_info->NDEFRWSize) ?
+ psNdefMap->ApduBufferSize : ps_tpz_info->NDEFRWSize);
+
+ switch (write_seq)
+ {
+ case WR_NDEF_T_TLV:
+ {
+ /* TYPE field of the NDEF TLV write is complete */
+ if (TOPAZ_WRITE_8_RESPONSE == *psNdefMap->SendRecvLength)
+ {
+ psNdefMap->State = (uint8_t)
+ PH_FRINFC_TOPAZ_STATE_WRITE;
+
+ /* Now, Write 0 to the magic number byte */
+ ps_tpz_info->WriteSeq = (uint8_t)WR_NMN_0;
+ write_seq = WR_NMN_0;
+ ps_tpz_info->CurrentBlock = 1;
+ ps_tpz_info->ByteNumber = 0;
+
+#ifdef TOPAZ_RAW_SUPPORT
+ *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_1E;
+#else
+ psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E;
+#endif /* #ifdef TOPAZ_RAW_SUPPORT */
+ result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, write_buf,
+ sizeof (write_buf));
+ }
+ else
+ {
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_INVALID_RECEIVE_LENGTH);
+ }
+ break;
+ }
+
+ case WR_NMN_0:
+ {
+ /* Magic number set to 0 write is complete */
+ if (TOPAZ_WRITE_1_RESPONSE == *psNdefMap->SendRecvLength)
+ {
+ ps_tpz_info->WriteSeq = (uint8_t)(write_seq + 1);
+ write_seq = (phFriNfc_Tpz_WrSeq_t)(write_seq + 1);
+ /* Now the sequence = WR_LEN_1_0, so Length block is read,
+ and only length bytes are made 0, before writing data to 0
+ */
+ result = phFriNfc_Tpz_H_RdForWrite (psNdefMap);
+ }
+ else
+ {
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_INVALID_RECEIVE_LENGTH);
+ }
+ break;
+ }
+
+ case WR_LEN_1_0:
+ {
+ /* Length field is updated with the value 0 */
+ if (TOPAZ_WRITE_8_RESPONSE != *psNdefMap->SendRecvLength)
+ {
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_INVALID_RECEIVE_LENGTH);
+ }
+ else if (write_len >= 0xFF)
+ {
+ ps_tpz_info->ByteNumber = 0;
+
+ ps_tpz_info->CurrentBlock = (uint8_t)
+ TOPAZ_INCREMENT_SKIP_STATIC_BLOCK (
+ ps_tpz_info->CurrentBlock);
+
+ ps_tpz_info->WriteSeq = (uint8_t)(write_seq + 1);
+ write_seq = (phFriNfc_Tpz_WrSeq_t)(write_seq + 1);
+ /* Now the sequence = WR_LEN_1_1, so Length block is read,
+ and only length bytes are made 0, before writing data to 0
+ */
+ result = phFriNfc_Tpz_H_RdForWrite (psNdefMap);
+ }
+ else
+ {
+ /* NDEF data length < 0xFF */
+ len_byte_addr = phFriNfc_Tpz_H_GetNDEFValueFieldAddrForWrite
+ (psNdefMap, write_len);
+ ps_tpz_info->CurrentBlock = (uint8_t)
+ TOPAZ_BLK_FROM_BYTE_ADR (len_byte_addr);
+ ps_tpz_info->ByteNumber = (uint8_t)
+ TOPAZ_BYTE_OFFSET_FROM_BYTE_ADR (len_byte_addr);
+
+
+ ps_tpz_info->WriteSeq = (uint8_t)WR_DATA;
+ write_seq = WR_DATA;
+
+ if (0 != ps_tpz_info->ByteNumber)
+ {
+ /* If data starts in between the block then read
+ the data */
+ result = phFriNfc_Tpz_H_RdForWrite (psNdefMap);
+ }
+ else
+ {
+ /* Data starts at the beginning of the block, so start
+ writing the user data */
+ result = phFriNfc_Tpz_H_CopySendWrData (psNdefMap);
+ }
+ }
+ break;
+ }
+
+ case WR_LEN_2_0:
+ case WR_LEN_2_VALUE:
+ {
+ /* 2nd length field is updated with the value 0 or the correct
+ written value */
+ if (TOPAZ_WRITE_8_RESPONSE != *psNdefMap->SendRecvLength)
+ {
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_INVALID_RECEIVE_LENGTH);
+ }
+ else
+ {
+ ps_tpz_info->ByteNumber = 0;
+ ps_tpz_info->CurrentBlock = (uint8_t)
+ TOPAZ_INCREMENT_SKIP_STATIC_BLOCK (
+ ps_tpz_info->CurrentBlock);
+ ps_tpz_info->WriteSeq = (uint8_t)(write_seq + 1);
+ write_seq = (phFriNfc_Tpz_WrSeq_t)(write_seq + 1);
+ /* If length byte starts in between the block then read
+ the length block */
+ result = phFriNfc_Tpz_H_RdForWrite (psNdefMap);
+ }
+ break;
+ }
+
+ case WR_LEN_3_0:
+ {
+ /* 3rd length field is updated with the value 0 */
+ if (TOPAZ_WRITE_8_RESPONSE != *psNdefMap->SendRecvLength)
+ {
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_INVALID_RECEIVE_LENGTH);
+ }
+ else
+ {
+ len_byte_addr = phFriNfc_Tpz_H_GetNDEFValueFieldAddrForWrite
+ (psNdefMap, write_len);
+ ps_tpz_info->CurrentBlock = (uint8_t)
+ TOPAZ_BLK_FROM_BYTE_ADR (len_byte_addr);
+ ps_tpz_info->ByteNumber = (uint8_t)
+ TOPAZ_BYTE_OFFSET_FROM_BYTE_ADR (len_byte_addr);
+
+ ps_tpz_info->WriteSeq = (uint8_t)(write_seq + 1);
+ write_seq = (phFriNfc_Tpz_WrSeq_t)(write_seq + 1);
+
+ if (0 != ps_tpz_info->ByteNumber)
+ {
+ /* If data starts in between the block then read
+ the data */
+ result = phFriNfc_Tpz_H_RdForWrite (psNdefMap);
+ }
+ else
+ {
+ /* Data starts at the beginning of the block, so start
+ writing the user data */
+ result = phFriNfc_Tpz_H_CopySendWrData (psNdefMap);
+ }
+ }
+ break;
+ }
+
+ case WR_DATA:
+ {
+ /* Data is written from the input buffer */
+ if (TOPAZ_WRITE_8_RESPONSE != *psNdefMap->SendRecvLength)
+ {
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_INVALID_RECEIVE_LENGTH);
+ }
+ else if (write_len == psNdefMap->ApduBuffIndex)
+ {
+ /* Data to be written is completely written to the card */
+ *psNdefMap->WrNdefPacketLength = psNdefMap->ApduBuffIndex;
+ ps_tpz_info->WriteSeq = (uint8_t)WR_LEN_1_VALUE;
+ write_seq = WR_LEN_1_VALUE;
+ /* To write the first length byte, it has to be read and then
+ the length has to be updated */
+ result = phFriNfc_Tpz_H_RdForWrite (psNdefMap);
+ }
+ else
+ {
+ ps_tpz_info->ByteNumber = 0;
+ /* Go to the next block */
+ ps_tpz_info->CurrentBlock = (uint8_t)
+ TOPAZ_INCREMENT_SKIP_STATIC_BLOCK (
+ ps_tpz_info->CurrentBlock);
+ /* Copy and write the user data */
+ result = phFriNfc_Tpz_H_CopySendWrData (psNdefMap);
+ }
+ break;
+ }
+
+ case WR_DATA_READ_REQD:
+ {
+ /* This sequence is executed, if the first read has some
+ lock or reserved blocks bytes and the lock or reserved
+ blocks are extended to the next block */
+ if (TOPAZ_WRITE_8_RESPONSE != *psNdefMap->SendRecvLength)
+ {
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_INVALID_RECEIVE_LENGTH);
+ }
+ else
+ {
+ ps_tpz_info->ByteNumber = 0;
+ /* Go to the next block */
+ ps_tpz_info->CurrentBlock = (uint8_t)
+ TOPAZ_INCREMENT_SKIP_STATIC_BLOCK (
+ ps_tpz_info->CurrentBlock);
+ /* Write is complete for one block, now because lock bytes are
+ shifted to next blocks, the next block is read and update
+ the written data by skipping the lock or reserved memory bytes */
+ result = phFriNfc_Tpz_H_RdForWrite (psNdefMap);
+ }
+ break;
+ }
+
+ case WR_LEN_3_VALUE:
+ {
+ /* 3rd LENGTH field byte is updated with correct written value */
+ if (TOPAZ_WRITE_8_RESPONSE != *psNdefMap->SendRecvLength)
+ {
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_INVALID_RECEIVE_LENGTH);
+ }
+ else
+ {
+#ifdef TOPAZ_RAW_SUPPORT
+ *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_1E;
+#else
+ psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E;
+#endif /* #ifdef TOPAZ_RAW_SUPPORT */
+
+ psNdefMap->State = (uint8_t)PH_FRINFC_TOPAZ_STATE_WRITE;
+
+ write_buf[write_index] = PH_FRINFC_TOPAZ_CC_BYTE0;
+ write_index = (uint8_t)(write_index + 1);
+
+ ps_tpz_info->ByteNumber = 0;
+ ps_tpz_info->CurrentBlock = 1;
+
+ ps_tpz_info->WriteSeq = (uint8_t)WR_NMN_E1;
+ write_seq = WR_NMN_E1;
+
+ /* Length byte write is complete, so now update the magic
+ number byte with value 0xE1 */
+ result = phFriNfc_Tpz_H_NxpWrite(psNdefMap, write_buf,
+ write_index);
+ }
+ break;
+ }
+
+ case WR_LEN_1_VALUE:
+ {
+ /* 1st LENGTH field byte is updated */
+ if (TOPAZ_WRITE_8_RESPONSE != *psNdefMap->SendRecvLength)
+ {
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_INVALID_RECEIVE_LENGTH);
+ }
+ else if (write_len < 0xFF)
+ {
+ /* Total length to write is less than 0xFF, so LENGTH field has
+ only one byte, then update the magic number byte with
+ value 0xE1 */
+#ifdef TOPAZ_RAW_SUPPORT
+ *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_1E;
+#else
+ psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E;
+#endif /* #ifdef TOPAZ_RAW_SUPPORT */
+ psNdefMap->State = (uint8_t)PH_FRINFC_TOPAZ_STATE_WRITE;
+
+ write_buf[write_index] = PH_FRINFC_TOPAZ_CC_BYTE0;
+ write_index = (uint8_t)(write_index + 1);
+
+ ps_tpz_info->ByteNumber = 0;
+ ps_tpz_info->CurrentBlock = 1;
+
+ ps_tpz_info->WriteSeq = (uint8_t)WR_NMN_E1;
+ write_seq = WR_NMN_E1;
+ result = phFriNfc_Tpz_H_NxpWrite(psNdefMap, write_buf,
+ write_index);
+ }
+ else
+ {
+ /* 2nd byte of the LENGTH field has to be updated so,
+ read the block, before updating it */
+ ps_tpz_info->ByteNumber = 0;
+ ps_tpz_info->CurrentBlock = (uint8_t)
+ TOPAZ_INCREMENT_SKIP_STATIC_BLOCK (
+ ps_tpz_info->CurrentBlock);
+ ps_tpz_info->WriteSeq = (uint8_t)WR_LEN_2_VALUE;
+ write_seq = WR_LEN_2_VALUE;
+ result = phFriNfc_Tpz_H_RdForWrite (psNdefMap);
+ }
+ break;
+ }
+
+ case WR_NMN_E1:
+ {
+ /* Magic number is written, so update the actual ndef length. */
+ if (TOPAZ_WRITE_1_RESPONSE == *psNdefMap->SendRecvLength)
+ {
+ *psNdefMap->WrNdefPacketLength = (uint32_t)
+ psNdefMap->ApduBuffIndex;
+ ps_tpz_info->ActualNDEFMsgSize = (uint16_t)
+ psNdefMap->ApduBuffIndex;
+ }
+ else
+ {
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_INVALID_RECEIVE_LENGTH);
+ }
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+
+ return result;
+}
+
+static
+NFCSTATUS
+phFriNfc_Tpz_H_UpdateNdefTypeField (
+ phFriNfc_NdefMap_t *psNdefMap)
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ phFriNfc_TopazCont_t *ps_tpz_info = NULL;
+ uint8_t write_buf[TOPAZ_WRITE_8_DATA_LENGTH];
+
+ ps_tpz_info = &(psNdefMap->TopazContainer);
+
+ (void)memcpy ((void *)write_buf, (void *)
+ psNdefMap->SendRecvBuf, TOPAZ_WRITE_8_DATA_LENGTH);
+
+ /* Update the TYPE field of the NDEF TLV */
+ write_buf[ps_tpz_info->ByteNumber] = PH_FRINFC_TOPAZ_NDEF_T;
+
+ psNdefMap->State = (uint8_t)PH_FRINFC_TOPAZ_STATE_WRITE;
+
+#ifdef TOPAZ_RAW_SUPPORT
+ *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_E8;
+#else
+ psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write8E;
+#endif /* #ifdef TOPAZ_RAW_SUPPORT */
+ result = phFriNfc_Tpz_H_NxpWrite(psNdefMap, write_buf,
+ sizeof (write_buf));
+
+ return result;
+}
+
+static
+NFCSTATUS
+phFriNfc_Tpz_H_ProRdForWrResp (
+ phFriNfc_NdefMap_t *psNdefMap)
+{
+ /* This function is used during the write operation */
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ phFriNfc_TopazCont_t *ps_tpz_info = NULL;
+
+ ps_tpz_info = &(psNdefMap->TopazContainer);
+
+ psNdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE;
+
+ if (TOPAZ_READ_8_RESPONSE == *psNdefMap->SendRecvLength)
+ {
+ switch ((phFriNfc_Tpz_WrSeq_t)ps_tpz_info->WriteSeq)
+ {
+ case WR_NDEF_T_TLV:
+ {
+ /* Read bytes are for updating the TYPE field of the NDEF TLV */
+ result = phFriNfc_Tpz_H_UpdateNdefTypeField (psNdefMap);
+ break;
+ }
+
+ case WR_LEN_1_0:
+ case WR_LEN_2_0:
+ case WR_LEN_3_0:
+ {
+ /* Read bytes are for updating the LENGTH field to 0 of the NDEF TLV and
+ also to update the data from the user buffer */
+ result = phFriNfc_Tpz_H_UpdateLenFieldZeroAfterRead (psNdefMap);
+ break;
+ }
+
+ case WR_DATA:
+ case WR_DATA_READ_REQD:
+ {
+ /* Read bytes are for skipping the lock and reserved bytes */
+ result = phFriNfc_Tpz_H_CopyReadDataAndWrite (psNdefMap);
+ break;
+ }
+
+ case WR_LEN_1_VALUE:
+ case WR_LEN_2_VALUE:
+ case WR_LEN_3_VALUE:
+ {
+ /* Read bytes are for updating the LENGTH field to the correct values
+ of the NDEF TLV */
+ result = phFriNfc_Tpz_H_UpdateLenFieldValuesAfterRead (psNdefMap);
+ break;
+ }
+
+ default:
+ {
+ /* Code must not come come here */
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* Error in the length, wither the HW has sent wrong response length or
+ the response length byte is corrupted */
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_INVALID_RECEIVE_LENGTH);
+ }
+
+
+ return result;
+}
+
+static
+NFCSTATUS
+phFriNfc_Tpz_H_ChkReadID(
+ phFriNfc_NdefMap_t *psNdefMap)
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ int compare_result = 0;
+ uint8_t recv_index = 0;
+
+
+ if (PH_FRINFC_TOPAZ_VAL6 == *psNdefMap->SendRecvLength)
+ {
+ if (((psNdefMap->SendRecvBuf[recv_index] &
+ PH_FRINFC_TOPAZ_HEADROM0_CHK) == PH_FRINFC_TOPAZ_DYNAMIC_HEADROM0_VAL))
+ {
+ /* Copy UID to the context*/
+ compare_result = phOsalNfc_MemCompare (
+ psNdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid,
+ &psNdefMap->SendRecvBuf[PH_FRINFC_TOPAZ_VAL2],
+ psNdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.UidLength);
+ if (0 == compare_result)
+ {
+ /* State has to be changed */
+ psNdefMap->State = PH_FRINFC_TOPAZ_STATE_READ;
+
+ /* Topaz command = READSEG */
+#ifdef TOPAZ_RAW_SUPPORT
+
+ *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_RSEG;
+
+#else
+
+#ifdef PH_HAL4_ENABLE
+ psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read;
+#else
+ psNdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead;
+#endif
+ psNdefMap->Cmd.JewelCmd = phHal_eJewel_ReadSeg;
+
+#endif /* #ifdef TOPAZ_RAW_SUPPORT */
+ /* Read bytes from the card */
+ result = phFriNfc_Tpz_H_NxpRead (psNdefMap);
+ }
+ else
+ {
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_NO_NDEF_SUPPORT);
+
+ }
+ }
+ }
+ else
+ {
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_INVALID_RECEIVE_LENGTH);
+ }
+
+ return result;
+}
+
+#define TOPAZ_READ_ID_ZERO_LENGTH (0x06U)
+static
+NFCSTATUS
+phFriNfc_Tpz_H_NxpRead (
+ phFriNfc_NdefMap_t *psNdefMap)
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ uint8_t send_index = 0;
+#ifdef TOPAZ_RAW_SUPPORT
+ uint8_t read_append[] = { 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00};
+#endif /* #ifdef TOPAZ_RAW_SUPPORT */
+
+ /* set the data for additional data exchange*/
+ psNdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = PH_FRINFC_TOPAZ_VAL0;
+ psNdefMap->psDepAdditionalInfo.DepFlags.NADPresent = PH_FRINFC_TOPAZ_VAL0;
+ psNdefMap->psDepAdditionalInfo.NAD = PH_FRINFC_TOPAZ_VAL0;
+
+ psNdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_TopazDynamicMap_Process;
+ psNdefMap->MapCompletionInfo.Context = psNdefMap;
+
+ *psNdefMap->SendRecvLength = psNdefMap->TempReceiveLength;
+
+ /* Depending on the jewel command, the send length is decided */
+#ifdef TOPAZ_RAW_SUPPORT
+
+ psNdefMap->Cmd.JewelCmd = phHal_eJewel_Raw;
+ /* " send_index " is incremented because already received buffer is filled with
+ TOPAZ command */
+ send_index = (uint8_t)(send_index + 1);
+
+ switch (*psNdefMap->SendRecvBuf)
+#else
+ switch(psNdefMap->Cmd.JewelCmd)
+#endif /* #ifdef TOPAZ_RAW_SUPPORT */
+ {
+#ifdef TOPAZ_RAW_SUPPORT
+
+ case PH_FRINFC_TOPAZ_CMD_READID:
+ {
+ (void)memcpy ((void *)(psNdefMap->SendRecvBuf + send_index),
+ (void *)read_append, TOPAZ_READ_ID_ZERO_LENGTH);
+ send_index = (uint8_t)(send_index + TOPAZ_READ_ID_ZERO_LENGTH);
+ break;
+ }
+
+ case PH_FRINFC_TOPAZ_CMD_READ8:
+ {
+ psNdefMap->SendRecvBuf[send_index] =
+ psNdefMap->TopazContainer.CurrentBlock;
+ send_index = (uint8_t)(send_index + 1);
+ break;
+ }
+
+ case PH_FRINFC_TOPAZ_CMD_RSEG:
+ {
+ psNdefMap->SendRecvBuf[send_index] = (uint8_t)
+ (psNdefMap->TopazContainer.CurrentSeg
+ << NIBBLE_SIZE);
+ send_index = (uint8_t)(send_index + 1);
+ break;
+ }
+
+#else /* #ifdef TOPAZ_RAW_SUPPORT */
+
+#ifdef PH_HAL4_ENABLE
+ case phHal_eJewel_RID:
+ case phHal_eJewel_ReadAll:
+#else
+ case phHal_eJewelCmdListJewelRid:
+ case phHal_eJewelCmdListJewelReadAll:
+#endif
+ {
+ /* For READ ID and READ ALL, send length is 0 */
+ psNdefMap->SendLength = PH_FRINFC_TOPAZ_VAL0;
+ break;
+ }
+
+#ifdef PH_HAL4_ENABLE
+ case phHal_eJewel_Read:
+#else
+ case phHal_eJewelCmdListJewelRead:
+#endif
+ {
+ /* Need to check the User data size request*/
+
+ psNdefMap->SendLength = PH_FRINFC_TOPAZ_VAL3;
+ break;
+ }
+
+ case phHal_eJewel_ReadSeg:
+ {
+ psNdefMap->SendRecvBuf[send_index] = (uint8_t)
+ (psNdefMap->TopazContainer.CurrentSeg
+ << NIBBLE_SIZE);
+ send_index = (uint8_t)(send_index + 1);
+ psNdefMap->SendLength = send_index;
+ break;
+ }
+
+ case phHal_eJewel_Read8:
+ {
+ psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read4;
+ psNdefMap->SendRecvBuf[send_index] = psNdefMap->TopazContainer.CurrentBlock;
+ send_index = (uint8_t)(send_index + 1);
+ psNdefMap->SendLength = send_index;
+ break;
+ }
+
+#endif /* #ifdef TOPAZ_RAW_SUPPORT */
+
+ default:
+ {
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_INVALID_DEVICE_REQUEST);
+ break;
+ }
+ }
+ if(result == NFCSTATUS_SUCCESS)
+ {
+#ifdef TOPAZ_RAW_SUPPORT
+
+ if (PH_FRINFC_TOPAZ_CMD_READID != *psNdefMap->SendRecvBuf)
+ {
+ (void)memcpy ((void *)(psNdefMap->SendRecvBuf + send_index),
+ (void *)read_append, sizeof (read_append));
+ send_index = (uint8_t)(send_index + sizeof (read_append));
+
+ (void)memcpy ((void *)(psNdefMap->SendRecvBuf + send_index),
+ (void *)psNdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid,
+ psNdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.UidLength);
+ send_index = (uint8_t)(send_index +
+ psNdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.UidLength);
+ }
+
+ psNdefMap->SendLength = send_index;
+
+#endif /* #ifdef TOPAZ_RAW_SUPPORT */
+ /* Call the Overlapped HAL Transceive function */
+ result = phFriNfc_OvrHal_Transceive( psNdefMap->LowerDevice,
+ &psNdefMap->MapCompletionInfo,
+ psNdefMap->psRemoteDevInfo,
+ psNdefMap->Cmd,
+ &psNdefMap->psDepAdditionalInfo,
+ psNdefMap->SendRecvBuf,
+ psNdefMap->SendLength,
+ psNdefMap->SendRecvBuf,
+ psNdefMap->SendRecvLength);
+ }
+ return result;
+}
+
+
+static
+NFCSTATUS
+phFriNfc_Tpz_H_NxpWrite(
+ phFriNfc_NdefMap_t *psNdefMap,
+ uint8_t *p_write_data,
+ uint8_t wr_data_len)
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ phFriNfc_TopazCont_t *ps_tpz_info = NULL;
+ uint8_t send_index = 0;
+
+ ps_tpz_info = &(psNdefMap->TopazContainer);
+
+ /* set the data for additional data exchange*/
+ psNdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = PH_FRINFC_TOPAZ_VAL0;
+ psNdefMap->psDepAdditionalInfo.DepFlags.NADPresent = PH_FRINFC_TOPAZ_VAL0;
+ psNdefMap->psDepAdditionalInfo.NAD = PH_FRINFC_TOPAZ_VAL0;
+
+ psNdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_TopazDynamicMap_Process;
+ psNdefMap->MapCompletionInfo.Context = psNdefMap;
+
+ *psNdefMap->SendRecvLength = psNdefMap->TempReceiveLength;
+
+#ifdef TOPAZ_RAW_SUPPORT
+ /* " send_index " is incremented because already received buffer is filled with
+ TOPAZ command */
+ send_index = (uint8_t)(send_index + 1);
+ psNdefMap->Cmd.JewelCmd = phHal_eJewel_Raw;
+
+ switch (*psNdefMap->SendRecvBuf)
+
+#else /* #ifdef TOPAZ_RAW_SUPPORT */
+
+ switch (psNdefMap->Cmd.JewelCmd)
+
+#endif /* #ifdef TOPAZ_RAW_SUPPORT */
+ {
+#ifdef TOPAZ_RAW_SUPPORT
+
+ case PH_FRINFC_TOPAZ_CMD_WRITE_1E:
+ {
+ psNdefMap->SendRecvBuf[send_index] = (uint8_t)((ps_tpz_info->CurrentBlock
+ << (NIBBLE_SIZE - 1)) |
+ ps_tpz_info->ByteNumber);
+ send_index = (uint8_t)(send_index + 1);
+ break;
+ }
+
+ case PH_FRINFC_TOPAZ_CMD_WRITE_E8:
+ {
+ psNdefMap->SendRecvBuf[send_index] = ps_tpz_info->CurrentBlock;
+ send_index = (uint8_t)(send_index + 1);
+ break;
+ }
+
+#else /* #ifdef TOPAZ_RAW_SUPPORT */
+
+ case phHal_eJewel_Write1E:
+ {
+ psNdefMap->SendRecvBuf[send_index] = (uint8_t)((ps_tpz_info->CurrentBlock
+ << (NIBBLE_SIZE - 1)) |
+ ps_tpz_info->ByteNumber);
+ send_index = (uint8_t)(send_index + 1);
+
+
+ break;
+ }
+
+ case phHal_eJewel_Write8E:
+ {
+ psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write4E;
+ psNdefMap->SendRecvBuf[send_index] = ps_tpz_info->CurrentBlock;
+ send_index = (uint8_t)(send_index + 1);
+ break;
+ }
+
+#endif /* #ifdef TOPAZ_RAW_SUPPORT */
+
+ default:
+ {
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_INVALID_DEVICE_REQUEST);
+ break;
+ }
+ }
+
+
+ if (NFCSTATUS_SUCCESS == result)
+ {
+ (void)memcpy ((void *)(psNdefMap->SendRecvBuf + send_index),
+ (void *)p_write_data, wr_data_len);
+
+ send_index = (uint8_t)(send_index + wr_data_len);
+
+#ifdef TOPAZ_RAW_SUPPORT
+
+ (void)memcpy ((void *)(psNdefMap->SendRecvBuf + send_index),
+ (void *)psNdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.Uid,
+ psNdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.UidLength);
+ send_index = (uint8_t)(send_index +
+ psNdefMap->psRemoteDevInfo->RemoteDevInfo.Jewel_Info.UidLength);
+
+#endif /* #ifdef TOPAZ_RAW_SUPPORT */
+
+ psNdefMap->SendLength = send_index;
+
+ /* Call the Overlapped HAL Transceive function */
+ result = phFriNfc_OvrHal_Transceive( psNdefMap->LowerDevice,
+ &psNdefMap->MapCompletionInfo,
+ psNdefMap->psRemoteDevInfo,
+ psNdefMap->Cmd,
+ &psNdefMap->psDepAdditionalInfo,
+ psNdefMap->SendRecvBuf,
+ psNdefMap->SendLength,
+ psNdefMap->SendRecvBuf,
+ psNdefMap->SendRecvLength);
+ }
+ return result;
+}
+
+static
+NFCSTATUS
+phFriNfc_Tpz_H_ProReadResp(
+ phFriNfc_NdefMap_t *psNdefMap)
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ phFriNfc_TopazCont_t *ps_tpz_info = NULL;
+ uint8_t write_buffer[] = {0x00};
+
+ ps_tpz_info = &(psNdefMap->TopazContainer);
+
+ switch (psNdefMap->PrevOperation)
+ {
+ case PH_FRINFC_NDEFMAP_CHECK_OPE:
+ {
+ if (PH_FRINFC_TOPAZ_DYNAMIC_READSEG_RESP ==
+ *psNdefMap->SendRecvLength)
+ {
+ if (0 == ps_tpz_info->CurrentSeg)
+ {
+ result = phFriNfc_Tpz_H_CheckCCBytes (psNdefMap);
+ }
+
+ if (NFCSTATUS_SUCCESS == result)
+ {
+ result = phFriNfc_Tpz_H_ParseTLVs (psNdefMap);
+ }
+ }
+ else
+ {
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_INVALID_RECEIVE_LENGTH);
+ }
+ break;
+ }
+
+ case PH_FRINFC_NDEFMAP_READ_OPE:
+ {
+ if (PH_FRINFC_TOPAZ_DYNAMIC_READSEG_RESP ==
+ *psNdefMap->SendRecvLength)
+ {
+ /* call the data bytes to internal buffer*/
+ result = phFriNfc_Tpz_H_CopyReadData (psNdefMap);
+ }
+ else
+ {
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_INVALID_RECEIVE_LENGTH);
+ }
+ break;
+ }
+
+ case PH_FRINFC_NDEFMAP_WRITE_OPE:
+ {
+ /* read the bytes for cheking the CC bytes and lock bit status*/
+ if(TOPAZ_READ_8_RESPONSE == *psNdefMap->SendRecvLength)
+ {
+ (void)memcpy ((void *)ps_tpz_info->CCByteBuf,
+ (void *)(psNdefMap->SendRecvBuf),
+ TOPAZ_CC_BYTES_LENGTH);
+
+ result = phFriNfc_Tpz_H_CheckCCBytesForWrite (psNdefMap);
+ if (NFCSTATUS_SUCCESS == result)
+ {
+ if ((0x00 == *ps_tpz_info->CCByteBuf) ||
+ (NDEF_T_TLV == ps_tpz_info->ExpectedSeq))
+ {
+ /* This statement is for getting the new
+ NDEF TLV byte address, because 1st CC byte is
+ corrupted or no NDEF TLV in the card
+
+ If the 1st CC byte (NDEF magic number) in the
+ card is 0, means that previous write has failed,
+ so to write the exact file
+ OR
+ The NDEF TLV is not present in the entire card, and
+ the sequence is NDEF_T_TLV (this means, that lock and
+ memory control TLV is found in the card)
+ */
+ psNdefMap->State = (uint8_t)
+ PH_FRINFC_TOPAZ_STATE_RD_FOR_WR_NDEF;
+ ps_tpz_info->WriteSeq = (uint8_t)WR_NDEF_T_TLV;
+
+ ps_tpz_info->CurrentBlock = (uint8_t)
+ TOPAZ_BLK_FROM_BYTE_ADR (
+ ps_tpz_info->NdefTLVByteAddress);
+
+ ps_tpz_info->ByteNumber = (uint8_t)
+ TOPAZ_BYTE_OFFSET_FROM_BYTE_ADR (
+ ps_tpz_info->NdefTLVByteAddress);
+
+#ifdef TOPAZ_RAW_SUPPORT
+ *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_READ8;
+#else
+ psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read8;
+#endif /* #ifdef TOPAZ_RAW_SUPPORT */
+
+ result = phFriNfc_Tpz_H_NxpRead (psNdefMap);
+ }
+ else
+ {
+ ps_tpz_info->WriteSeq = (uint8_t)WR_NMN_0;
+ ps_tpz_info->CurrentBlock = 1;
+ ps_tpz_info->ByteNumber = 0;
+ psNdefMap->State = (uint8_t)
+ PH_FRINFC_TOPAZ_STATE_WRITE;
+#ifdef TOPAZ_RAW_SUPPORT
+ *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_1E;
+#else
+ psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E;
+#endif /* #ifdef TOPAZ_RAW_SUPPORT */
+
+ /* Call read 8 */
+ result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, write_buffer,
+ sizeof (write_buffer));
+ }
+
+ }
+ }
+ else
+ {
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_INVALID_RECEIVE_LENGTH);
+ }
+ break;
+ }
+
+ default:
+ {
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_INVALID_DEVICE_REQUEST);
+ break;
+ }
+ }
+
+ 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
+NFCSTATUS
+phFriNfc_Tpz_H_ChkLockBits(
+ phFriNfc_NdefMap_t *psNdefMap)
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+#ifdef ENABLE_LOCK_BITS_CHECK
+ uint8_t *p_recv_buf = psNdefMap->SendRecvBuf;
+#endif /* #ifdef ENABLE_LOCK_BITS_CHECK */
+ psNdefMap->CardState = PH_NDEFMAP_CARD_STATE_INITIALIZED;
+
+#ifdef ENABLE_LOCK_BITS_CHECK
+
+ /* Set the card state */
+ psNdefMap->CardState = (uint8_t)
+ (((p_recv_buf[PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_0] ==
+ PH_FRINFC_TOPAZ_DYNAMIC_LOCKBYTE_0) &&
+ ((p_recv_buf[PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_1] ==
+ PH_FRINFC_TOPAZ_DYNAMIC_LOCKBYTE_1)) &&
+ ((p_recv_buf[PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_2] ==
+ PH_FRINFC_TOPAZ_DYNAMIC_LOCKBYTE_2TO7)) &&
+ ((p_recv_buf[PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_3] ==
+ PH_FRINFC_TOPAZ_DYNAMIC_LOCKBYTE_2TO7)) &&
+ ((p_recv_buf[PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_4] ==
+ PH_FRINFC_TOPAZ_DYNAMIC_LOCKBYTE_2TO7)) &&
+ ((p_recv_buf[PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_5] ==
+ PH_FRINFC_TOPAZ_DYNAMIC_LOCKBYTE_2TO7)) &&
+ ((p_recv_buf[PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_6] ==
+ PH_FRINFC_TOPAZ_DYNAMIC_LOCKBYTE_2TO7))) &&
+ ((p_recv_buf[PH_FRINFC_TOPAZ_DYNAMIC_LOCKBIT_BYTENO_7] ==
+ PH_FRINFC_TOPAZ_DYNAMIC_LOCKBYTE_2TO7)) ?
+ PH_NDEFMAP_CARD_STATE_INITIALIZED :
+ PH_NDEFMAP_CARD_STATE_READ_ONLY);
+
+#endif /* #ifdef ENABLE_LOCK_BITS_CHECK */
+
+ /* Set the card state from CC bytes */
+ if (PH_NDEFMAP_CARD_STATE_INITIALIZED == psNdefMap->CardState)
+ {
+ switch ((psNdefMap->TopazContainer.CCByteBuf[3] & 0xFF))
+ {
+ case PH_FRINFC_TOPAZ_CC_READWRITE:
+ {
+ psNdefMap->CardState = PH_NDEFMAP_CARD_STATE_INITIALIZED;
+ break;
+ }
+
+ case PH_FRINFC_TOPAZ_CC_READONLY:
+ {
+ psNdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_ONLY;
+ break;
+ }
+
+ default:
+ {
+ psNdefMap->CardState = PH_NDEFMAP_CARD_STATE_INVALID;
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_NO_NDEF_SUPPORT);
+ break;
+ }
+ }
+ }
+
+ return result;
+}
+
+static
+NFCSTATUS
+phFriNfc_Tpz_H_CheckCCBytes (
+ phFriNfc_NdefMap_t *psNdefMap)
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ phFriNfc_TopazCont_t *ps_tpz_info = &(psNdefMap->TopazContainer);
+ uint8_t *p_recv_buf = psNdefMap->SendRecvBuf;
+ uint16_t parse_index = 0;
+
+ parse_index = (uint16_t)(parse_index + TOPAZ_UID_BYTES_LENGTH);
+
+ (void)memcpy ((void *)ps_tpz_info->CCByteBuf,
+ (void *)(p_recv_buf + parse_index),
+ TOPAZ_CC_BYTES_LENGTH);
+
+ p_recv_buf = ps_tpz_info->CCByteBuf;
+ parse_index = 0;
+
+#ifdef TOPAZ_MAGIC_NO_CHK_ENABLE
+ /* 1st CC byte value = 0 or 0xE1 */
+ if ((PH_FRINFC_TOPAZ_CC_BYTE0 == p_recv_buf[parse_index])
+#ifdef TOPAZ_MAGIC_NO_0_CHK_ENABLE
+ || (0 == p_recv_buf[parse_index])
+#endif /* #if TOPAZ_MAGIC_NO_0_CHK_ENABLE */
+ )
+#endif /* #ifdef TOPAZ_MAGIC_NO_CHK_ENABLE */
+ {
+ parse_index = (uint16_t)(parse_index + 1);
+ /* 2nd CC byte value = 0x10 */
+ result = phFriNfc_Tpz_H_ChkSpcVer (psNdefMap, p_recv_buf[parse_index]);
+ }
+#ifdef TOPAZ_MAGIC_NO_CHK_ENABLE
+ else
+ {
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_NO_NDEF_SUPPORT);
+ }
+#endif /* #ifdef TOPAZ_MAGIC_NO_CHK_ENABLE */
+
+ if (NFCSTATUS_SUCCESS == result)
+ {
+ parse_index = (uint16_t)(parse_index + 1);
+ /* 3rd CC byte value = 0x3F for 512 card */
+ if (PH_FRINFC_TOPAZ_DYNAMIC_CC_BYTE2_MMSIZE == p_recv_buf[parse_index])
+ {
+ /* Card size calculated as ((3rd CC byte * 8) - 4 CC bytes) */
+ psNdefMap->CardMemSize = (uint16_t)((p_recv_buf[parse_index] *
+ TOPAZ_BYTES_PER_BLOCK) -
+ TOPAZ_CC_BYTES_LENGTH);
+ ps_tpz_info->RemainingSize = (uint16_t)(psNdefMap->CardMemSize +
+ TOPAZ_UID_BYTES_LENGTH +
+ TOPAZ_CC_BYTES_LENGTH);
+ result = phFriNfc_Tpz_H_ChkLockBits (psNdefMap);
+ }
+ else
+ {
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_NO_NDEF_SUPPORT);
+ }
+ }
+
+ if (NFCSTATUS_SUCCESS != result)
+ {
+ psNdefMap->CardState = PH_NDEFMAP_CARD_STATE_INVALID;
+ }
+
+ return result;
+}
+
+static
+NFCSTATUS
+phFriNfc_Tpz_H_CheckCCBytesForWrite (
+ phFriNfc_NdefMap_t *psNdefMap)
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ phFriNfc_TopazCont_t *ps_tpz_info = NULL;
+ uint8_t check_cc_rw[] = {TOPAZ_SPEC_VERSION,
+ PH_FRINFC_TOPAZ_DYNAMIC_CC_BYTE2_MMSIZE,
+ PH_FRINFC_TOPAZ_CC_READWRITE};
+ uint8_t check_index = 0;
+
+ ps_tpz_info = &(psNdefMap->TopazContainer);
+
+#ifdef TOPAZ_MAGIC_NO_CHK_ENABLE
+ if (
+ (PH_FRINFC_TOPAZ_CC_BYTE0 == ps_tpz_info->CCByteBuf[check_index])
+#if TOPAZ_MAGIC_NO_0_CHK_ENABLE
+ || (0 == ps_tpz_info->CCByteBuf[check_index])
+#endif /* #if TOPAZ_MAGIC_NO_0_CHK_ENABLE */
+ )
+#endif /* #ifdef TOPAZ_MAGIC_NO_CHK_ENABLE */
+ {
+ check_index = (uint8_t)(check_index + 1);
+
+ if ((check_cc_rw[0] != ps_tpz_info->CCByteBuf[1]) ||
+ (check_cc_rw[1] != ps_tpz_info->CCByteBuf[2]) ||
+ (check_cc_rw[2] != ps_tpz_info->CCByteBuf[3]))
+ {
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_NO_NDEF_SUPPORT);
+ }
+ }
+#ifdef TOPAZ_MAGIC_NO_CHK_ENABLE
+ else
+ {
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_NO_NDEF_SUPPORT);
+ }
+#endif /* #ifdef TOPAZ_MAGIC_NO_CHK_ENABLE */
+ return result;
+}
+
+static
+uint16_t
+phFriNfc_Tpz_H_GetNDEFValueFieldAddrForRead (
+ phFriNfc_NdefMap_t *psNdefMap)
+{
+ phFriNfc_TopazCont_t *ps_tpz_info = &(psNdefMap->TopazContainer);
+ uint16_t skip_size = 0;
+ uint16_t byte_addr = 0;
+ uint8_t exit_index = 0;
+
+ byte_addr = ps_tpz_info->NdefTLVByteAddress;
+
+ while (exit_index < ((ps_tpz_info->ActualNDEFMsgSize >= 0xFF) ? 3 : 1))
+ {
+ byte_addr = (uint16_t)(byte_addr + 1);
+ if (TOPAZ_STATIC_LOCK_RES_START == byte_addr)
+ {
+ byte_addr = (uint16_t)(byte_addr + TOPAZ_STATIC_LOCK_RES_BYTES);
+ }
+ skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, byte_addr);
+
+ byte_addr = (uint16_t)(byte_addr + skip_size);
+ exit_index = (uint8_t)(exit_index + 1);
+ }
+
+ byte_addr = (uint16_t)(byte_addr + 1);
+ if (TOPAZ_STATIC_LOCK_RES_START == byte_addr)
+ {
+ byte_addr = (uint16_t)(byte_addr + TOPAZ_STATIC_LOCK_RES_BYTES);
+ }
+ skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, byte_addr);
+
+ byte_addr = (uint16_t)(byte_addr + skip_size);
+
+ return byte_addr;
+}
+
+static
+uint16_t
+phFriNfc_Tpz_H_GetNDEFValueFieldAddrForWrite (
+ phFriNfc_NdefMap_t *psNdefMap,
+ uint16_t size_to_write)
+{
+ phFriNfc_TopazCont_t *ps_tpz_info = &(psNdefMap->TopazContainer);
+ uint16_t skip_size = 0;
+ uint16_t byte_addr = 0;
+ uint8_t exit_index = 0;
+
+ byte_addr = ps_tpz_info->NdefTLVByteAddress;
+
+ while (exit_index < ((size_to_write >= 0xFF) ? 3 : 1))
+ {
+ byte_addr = (uint16_t)(byte_addr + 1);
+ if (TOPAZ_STATIC_LOCK_RES_START == byte_addr)
+ {
+ byte_addr = (uint16_t)(byte_addr + TOPAZ_STATIC_LOCK_RES_BYTES);
+ }
+ skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, byte_addr);
+
+ byte_addr = (uint16_t)(byte_addr + skip_size);
+ exit_index = (uint8_t)(exit_index + 1);
+ }
+
+ byte_addr = (uint16_t)(byte_addr + 1);
+ if (TOPAZ_STATIC_LOCK_RES_START == byte_addr)
+ {
+ byte_addr = (uint16_t)(byte_addr + TOPAZ_STATIC_LOCK_RES_BYTES);
+ }
+ skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, byte_addr);
+
+ byte_addr = (uint16_t)(byte_addr + skip_size);
+
+ return byte_addr;
+}
+
+
+static
+NFCSTATUS
+phFriNfc_Tpz_H_RemainingReadDataCopy (
+ phFriNfc_NdefMap_t *psNdefMap)
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ phFriNfc_TopazCont_t *ps_tpz_info = &(psNdefMap->TopazContainer);
+ uint8_t copy_temp_buf[PH_FRINFC_NDEFMAP_TOPAZ_MAX_SIZE];
+ uint16_t copy_length = 0;
+ uint16_t read_copy_length = 0;
+
+
+ if (0 != ps_tpz_info->ReadBufferSize)
+ {
+ /* Data is already copied, so give it from the stored buffer */
+ if ((psNdefMap->ApduBufferSize - psNdefMap->ApduBuffIndex) >=
+ ps_tpz_info->ReadBufferSize)
+ {
+ read_copy_length = ps_tpz_info->ReadBufferSize;
+ (void)memcpy ((void *)(psNdefMap->ApduBuffer + psNdefMap->ApduBuffIndex),
+ (void *)ps_tpz_info->ReadBuffer, ps_tpz_info->ReadBufferSize);
+ }
+ else
+ {
+ read_copy_length = (uint16_t)(psNdefMap->ApduBufferSize -
+ psNdefMap->ApduBuffIndex);
+
+ copy_length = (uint16_t)(ps_tpz_info->ReadBufferSize -
+ read_copy_length);
+
+ /* Copy data to user buffer */
+ (void)memcpy ((void *)(psNdefMap->ApduBuffer + psNdefMap->ApduBuffIndex),
+ (void *)ps_tpz_info->ReadBuffer, read_copy_length);
+
+ /* Copy data from " ReadBuffer " to temporary buffer */
+ (void)memcpy ((void *)copy_temp_buf,
+ (void *)(ps_tpz_info->ReadBuffer + read_copy_length),
+ copy_length);
+
+ /* Copy data from temporary buffer to " ReadBuffer " */
+ (void)memcpy ((void *)ps_tpz_info->ReadBuffer,
+ (void *)copy_temp_buf, copy_length);
+
+ }
+
+ psNdefMap->ApduBuffIndex = (uint16_t)(psNdefMap->ApduBuffIndex +
+ read_copy_length);
+ ps_tpz_info->ReadBufferSize = (uint8_t)
+ (ps_tpz_info->ReadBufferSize -
+ read_copy_length);
+ ps_tpz_info->RemainingReadSize = (uint16_t)(
+ ps_tpz_info->RemainingReadSize - read_copy_length);
+ }
+
+ if (0 == ps_tpz_info->RemainingReadSize)
+ {
+ /* No data to read, so return */
+ *psNdefMap->NumOfBytesRead = psNdefMap->ApduBuffIndex;
+ ps_tpz_info->ReadBufferSize = 0;
+ ps_tpz_info->ReadWriteCompleteFlag = TRUE;
+ }
+ else if (psNdefMap->ApduBuffIndex == psNdefMap->ApduBufferSize)
+ {
+ /* User data length is read completely */
+ *psNdefMap->NumOfBytesRead = psNdefMap->ApduBuffIndex;
+ }
+ else
+ {
+ /* Stored data is not enough, so continue reading the next segment */
+ ps_tpz_info->CurrentSeg = (uint8_t)
+ (ps_tpz_info->CurrentSeg + 1);
+#ifdef TOPAZ_RAW_SUPPORT
+
+ *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_RSEG;
+
+#else
+
+ psNdefMap->Cmd.JewelCmd = phHal_eJewel_ReadSeg;
+
+#endif /* #ifdef TOPAZ_RAW_SUPPORT */
+ result = phFriNfc_Tpz_H_NxpRead (psNdefMap);
+ }
+
+ return result;
+}
+
+static
+NFCSTATUS
+phFriNfc_Tpz_H_CopyReadData (
+ phFriNfc_NdefMap_t *psNdefMap)
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ phFriNfc_TopazCont_t *ps_tpz_info = &(psNdefMap->TopazContainer);
+ phFriNfc_LockCntrlTLVCont_t *ps_locktlv_info = NULL;
+ phFriNfc_ResMemCntrlTLVCont_t *ps_memtlv_info = NULL;
+ uint16_t copy_index = 0;
+ uint16_t copy_length = 0;
+ uint16_t recv_length = 0;
+ static uint16_t skip_size = 0;
+ /* byte address read */
+ uint16_t copy_till_address = 0;
+ uint16_t exact_copy_length = 0;
+ uint16_t actual_ndef_length = 0;
+
+
+ recv_length = *(psNdefMap->SendRecvLength);
+
+ actual_ndef_length = ps_tpz_info->ActualNDEFMsgSize;
+ if (PH_FRINFC_NDEFMAP_SEEK_CUR == psNdefMap->Offset)
+ {
+ actual_ndef_length = (uint16_t)(
+ ps_tpz_info->RemainingReadSize +
+ psNdefMap->ApduBuffIndex);
+ }
+
+ exact_copy_length = (uint16_t)((psNdefMap->ApduBufferSize >
+ actual_ndef_length) ? actual_ndef_length :
+ psNdefMap->ApduBufferSize);
+
+ if (0 == ps_tpz_info->CurrentSeg)
+ {
+ /* Skip copying the UID bytes, CC bytes, and lock and reserved memory bytes
+ */
+ recv_length = (*(psNdefMap->SendRecvLength) - TOPAZ_STATIC_LOCK_RES_BYTES);
+ }
+
+ if (TOPAZ_SEG_FROM_BYTE_ADR (
+ phFriNfc_Tpz_H_GetNDEFValueFieldAddrForRead (psNdefMap)) ==
+ ps_tpz_info->CurrentSeg)
+ {
+ copy_index = (uint16_t)(
+ phFriNfc_Tpz_H_GetNDEFValueFieldAddrForRead (
+ psNdefMap) % TOPAZ_SEGMENT_READ_LENGTH);
+ skip_size = 0;
+ }
+
+ if (0 != skip_size)
+ {
+ copy_index = (copy_index + skip_size);
+ skip_size = 0;
+ }
+
+ while (copy_index < recv_length)
+ {
+ copy_length = (uint16_t)(recv_length - copy_index);
+ copy_till_address = 0;
+ /* IF MORE THAN ONE TLV EXISTS THEN ADD A WHILE LOOP HERE, AND PLACE THE
+ IF STATEMENT INSIDE THE WHILE LOOP. ALSO,
+ ps_locktlv_info = &(psNdefMap->LockTlv) change this to
+ ps_locktlv_info = &(psNdefMap->LockTlv[index])
+ */
+ ps_locktlv_info = &(psNdefMap->LockTlv);
+ if (
+ /* Check the lock bytes belong to this segment */
+ (ps_tpz_info->CurrentSeg ==
+ (ps_locktlv_info->ByteAddr / TOPAZ_SEGMENT_READ_LENGTH)) &&
+ /* Now to check if the copy_index has surpassed the lock byte address */
+ (TOPAZ_BYTE_ADR_FROM_SEG(ps_tpz_info->CurrentSeg, copy_index)
+ <= ps_locktlv_info->ByteAddr)
+ )
+ {
+ copy_till_address = ps_locktlv_info->ByteAddr;
+ skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap,
+ ps_locktlv_info->ByteAddr);
+ }
+
+ /* IF MORE THAN ONE TLV EXISTS THEN ADD A WHILE LOOP HERE, AND PLACE THE
+ IF STATEMENT INSIDE THE WHILE LOOP. ALSO,
+ ps_memtlv_info = &(psNdefMap->MemTlv) change this to
+ ps_memtlv_info = &(psNdefMap->MemTlv[index])
+ */
+ ps_memtlv_info = &(psNdefMap->MemTlv);
+ if (
+ /* Check the reserved bytes belong to this segment */
+ (ps_tpz_info->CurrentSeg ==
+ (ps_memtlv_info->ByteAddr / TOPAZ_SEGMENT_READ_LENGTH)) &&
+ /* Now to check if the copy_index has surpassed the reserved byte address */
+ (TOPAZ_BYTE_ADR_FROM_SEG(ps_tpz_info->CurrentSeg, copy_index)
+ <= ps_memtlv_info->ByteAddr)
+ )
+ {
+ copy_till_address = (uint16_t)
+ (((ps_memtlv_info->ByteAddr < copy_till_address) ||
+ (0 == copy_till_address))?
+ ps_memtlv_info->ByteAddr : copy_till_address);
+
+ if (copy_till_address == ps_memtlv_info->ByteAddr)
+ {
+ skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap,
+ ps_memtlv_info->ByteAddr);
+ }
+ }
+
+
+ copy_length = (uint16_t) ((copy_till_address == 0) ? copy_length :
+ ((copy_till_address % TOPAZ_SEGMENT_READ_LENGTH) -
+ copy_index));
+
+ /* After lock bytes, there are immediate reserved bytes, so " copy_length "
+ can be 0 */
+ if (0 != copy_length)
+ {
+ /* If complete user buffer is not filled and the
+ read data is greater than the user data buffer, then get the
+ remaining size that should be copied.
+ The below " if " statement is used for the above scenario */
+ if ((copy_length > (uint16_t)
+ (exact_copy_length - psNdefMap->ApduBuffIndex)) &&
+ (exact_copy_length != psNdefMap->ApduBuffIndex))
+ {
+ copy_length = (uint16_t)(exact_copy_length -
+ psNdefMap->ApduBuffIndex);
+ }
+
+ if (exact_copy_length != psNdefMap->ApduBuffIndex)
+ {
+ (void)memcpy ((void *)(psNdefMap->ApduBuffer +
+ psNdefMap->ApduBuffIndex),
+ (void *)(psNdefMap->SendRecvBuf + copy_index),
+ copy_length);
+#if 0
+ if (((copy_till_address == 0) ? copy_length :
+ ((copy_till_address % TOPAZ_SEGMENT_READ_LENGTH) -
+ copy_index)) > (uint16_t)
+ (exact_copy_length - psNdefMap->ApduBuffIndex))
+ {
+ /* Copy remaining buffer in the static memory */
+ (void)memcpy ((void *)(ps_tpz_info->ReadBuffer +
+ ps_tpz_info->ReadBufferSize),
+ (void *)(psNdefMap->SendRecvBuf + copy_index),
+ (((copy_till_address % TOPAZ_SEGMENT_READ_LENGTH) -
+ copy_index) - copy_length));
+
+ ps_tpz_info->ReadBufferSize = (uint16_t)(((copy_till_address %
+ TOPAZ_SEGMENT_READ_LENGTH) -
+ copy_index) - copy_length);
+
+ /* Copy the data in the user buffer */
+ copy_index = (uint16_t)(copy_index +
+ ((copy_till_address % TOPAZ_SEGMENT_READ_LENGTH) -
+ copy_index));
+ }
+ else
+#endif /* #if 0 */
+ {
+ /* Copy the data in the user buffer */
+ copy_index = (uint16_t)(copy_index + copy_length);
+ }
+
+ psNdefMap->ApduBuffIndex = (uint16_t)(psNdefMap->ApduBuffIndex +
+ copy_length);
+
+
+ }
+ else
+ {
+ copy_length = (uint16_t) ((copy_till_address == 0) ? copy_length :
+ ((copy_till_address % TOPAZ_SEGMENT_READ_LENGTH) -
+ copy_index));
+
+ /* Actual NDEF message size is greater than the last index copied in
+ the user buffer */
+ if (actual_ndef_length > (psNdefMap->ApduBuffIndex +
+ ps_tpz_info->ReadBufferSize))
+ {
+ /* The statement is correct, check the remaining length */
+ copy_length = ((copy_length > (actual_ndef_length -
+ psNdefMap->ApduBuffIndex)) ?
+ (actual_ndef_length -
+ psNdefMap->ApduBuffIndex) :
+ copy_length);
+
+ /* Copy remaining buffer in the static memory */
+ (void)memcpy ((void *)(ps_tpz_info->ReadBuffer +
+ ps_tpz_info->ReadBufferSize),
+ (void *)(psNdefMap->SendRecvBuf + copy_index),
+ copy_length);
+
+ ps_tpz_info->ReadBufferSize = (uint8_t)(
+ ps_tpz_info->ReadBufferSize +
+ copy_length);
+ }
+
+ /* Copy the data in the user buffer */
+ copy_index = (uint16_t)(copy_index + copy_length);
+ }
+ }
+
+ if ((copy_index + skip_size) <= recv_length)
+ {
+ copy_index = (uint16_t)(copy_index + skip_size);
+ skip_size = 0;
+ }
+ else
+ {
+ skip_size = (uint16_t)((skip_size > 0) ?
+ (recv_length - copy_index) : 0);
+ copy_index = (uint16_t)recv_length;
+ }
+ }
+
+ if (exact_copy_length != psNdefMap->ApduBuffIndex)
+ {
+ ps_tpz_info->CurrentSeg = (uint8_t)
+ (ps_tpz_info->CurrentSeg + 1);
+#ifdef TOPAZ_RAW_SUPPORT
+
+ *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_RSEG;
+
+#else
+
+ psNdefMap->Cmd.JewelCmd = phHal_eJewel_ReadSeg;
+
+#endif /* #ifdef TOPAZ_RAW_SUPPORT */
+ result = phFriNfc_Tpz_H_NxpRead (psNdefMap);
+ }
+ else
+ {
+ *psNdefMap->NumOfBytesRead = psNdefMap->ApduBuffIndex;
+ if (psNdefMap->ApduBuffIndex == actual_ndef_length)
+ {
+ ps_tpz_info->ReadBufferSize = 0;
+ ps_tpz_info->ReadWriteCompleteFlag = TRUE;
+ }
+ else
+ {
+ ps_tpz_info->RemainingReadSize = (actual_ndef_length -
+ psNdefMap->ApduBuffIndex);
+ }
+ }
+ return result;
+}
+
+
+static
+NFCSTATUS
+phFriNfc_Tpz_H_ParseTLVs (
+ phFriNfc_NdefMap_t *psNdefMap)
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ phFriNfc_TopazCont_t *ps_tpz_info = &(psNdefMap->TopazContainer);
+ uint8_t *p_recv_buf = NULL;
+ uint16_t recv_length = 0;
+ uint16_t parse_index = 0;
+ phFriNfc_Tpz_ParseSeq_t expected_seq = (phFriNfc_Tpz_ParseSeq_t)
+ ps_tpz_info->ExpectedSeq;
+ uint16_t byte_addr = 0;
+ /* This variable is kept static because if the size to skip LOCK or RESERVED
+ bytes extends to next read then it shall be stored and used to skip the next
+ read the bytes
+ */
+ static uint16_t skip_size = 0;
+ /* This variable is kept static because if the bytes extends from the read segment,
+ then the index shall be stored
+ This is to store index copied from the
+ 1. lock memory VALUE field bytes in the LOCK and MEMORY CONTROL TLV.
+ 2. Also, LENGTH field of the NDEF TLV */
+ static uint8_t lock_mem_ndef_index = 0;
+ /* This variable is kept static because if the bytes extends from the read segment,
+ then it has to stored
+ This is to store the
+ 1. lock memory VALUE field bytes in the LOCK and MEMORY CONTROL TLV.
+ 2. Also, LENGTH field of the NDEF TLV */
+ static uint8_t lock_mem_buf[TOPAZ_MEM_LOCK_TLV_LENGTH] = {0};
+ /* This is used in case if there is no MAGIC NUMBER found
+ OR
+ TYPE field is not found after reading entire card */
+ static uint16_t ndef_tlv_byte_addr = 0;
+
+ p_recv_buf = psNdefMap->SendRecvBuf;
+ recv_length = *psNdefMap->SendRecvLength;
+
+ if (0 == ps_tpz_info->CurrentSeg)
+ {
+ /* First read, so reset all the static variables */
+ lock_mem_ndef_index = 0;
+ skip_size = 0;
+ ndef_tlv_byte_addr = 0;
+
+ /* Skip copying the UID bytes and CC bytes, which is first 12 bytes */
+ parse_index = (uint16_t)(TOPAZ_UID_BYTES_LENGTH +
+ TOPAZ_CC_BYTES_LENGTH);
+ /* Delete the lock and reserved memory bytes
+ (which are the last 24 bytes in the card) */
+ recv_length = (uint16_t)(*(psNdefMap->SendRecvLength) -
+ TOPAZ_STATIC_LOCK_RES_BYTES);
+ }
+
+ while ((parse_index < recv_length) && (NFCSTATUS_SUCCESS == result) &&
+ (NDEF_V_TLV != expected_seq))
+ {
+ if (0 == skip_size)
+ {
+ /* Macro used to get the exact byte address of the card.
+ This is done by using the current segment and the parse index */
+ byte_addr = TOPAZ_BYTE_ADR_FROM_SEG (ps_tpz_info->CurrentSeg, parse_index);
+ /* Skip size is to skip the lock or memory reserved bytes */
+ skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, byte_addr);
+ }
+
+ if (0 != skip_size)
+ {
+ if ((recv_length - parse_index) >= skip_size)
+ {
+ parse_index = (uint16_t)(parse_index + skip_size);
+ skip_size = 0;
+ }
+ else
+ {
+ parse_index = (uint16_t)(parse_index + (recv_length -
+ parse_index));
+ skip_size = (uint16_t)(skip_size - (recv_length -
+ parse_index));
+ }
+ }
+ else
+ {
+ switch (expected_seq)
+ {
+ case LOCK_T_TLV:
+ {
+ /* Parse the bytes till TYPE field of LOCK TLV is found, Once the
+ TYPE field is found then change the sequence to LOCK_L_TLV */
+ result = phFriNfc_Tpz_H_ParseLockTLVType (psNdefMap, p_recv_buf,
+ &parse_index, recv_length, &expected_seq);
+
+ break;
+ }
+
+ case LOCK_L_TLV:
+ {
+ /* Parse the length field of LOCK TLV. Length field value of the
+ LOCK TLV is always 3 */
+ if (TOPAZ_MEM_LOCK_TLV_LENGTH != p_recv_buf[parse_index])
+ {
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_NO_NDEF_SUPPORT);
+ }
+ else
+ {
+ parse_index = (uint16_t)(parse_index + 1);
+ expected_seq = LOCK_V_TLV;
+ }
+ break;
+ }
+
+ case LOCK_V_TLV:
+ {
+ /* Parse the VALUE field of the LOCK TLV */
+ lock_mem_buf[lock_mem_ndef_index] = p_recv_buf[parse_index];
+ parse_index = (uint16_t)(parse_index + 1);
+ lock_mem_ndef_index = (uint8_t)(lock_mem_ndef_index + 1);
+
+
+ /* All the 3 bytes are copied in the local buffer */
+ if (TOPAZ_MEM_LOCK_TLV_LENGTH == lock_mem_ndef_index)
+ {
+ /* Calculate the byte address and size of the lock bytes */
+ result = phFriNfc_Tpz_H_GetLockBytesInfo (psNdefMap, lock_mem_buf);
+ lock_mem_ndef_index = 0;
+ expected_seq = MEM_T_TLV;
+ }
+ break;
+ }
+
+ case MEM_T_TLV:
+ {
+ /* Parse the bytes till TYPE field of MEMORY TLV is found, Once the
+ TYPE field is found then change the sequence to MEM_L_TLV */
+ result = phFriNfc_Tpz_H_ParseMemTLVType (psNdefMap, p_recv_buf,
+ &parse_index, recv_length, &expected_seq);
+ break;
+ }
+
+ case MEM_L_TLV:
+ {
+ /* Parse the length field of MEMORY TLV. Length field value of the
+ MEMORY TLV is always 3 */
+ if (TOPAZ_MEM_LOCK_TLV_LENGTH != p_recv_buf[parse_index])
+ {
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_NO_NDEF_SUPPORT);
+ }
+ else
+ {
+ parse_index = (uint16_t)(parse_index + 1);
+ expected_seq = MEM_V_TLV;
+ }
+
+ break;
+ }
+
+ case MEM_V_TLV:
+ {
+ /* Parse the VALUE field of the MEMORY TLV */
+ lock_mem_buf[lock_mem_ndef_index] = p_recv_buf[parse_index];
+ parse_index = (uint16_t)(parse_index + 1);
+ lock_mem_ndef_index = (uint8_t)(lock_mem_ndef_index + 1);
+
+ /* All the 3 bytes are copied in the local buffer */
+ if (TOPAZ_MEM_LOCK_TLV_LENGTH == lock_mem_ndef_index)
+ {
+ /* Calculate the byte address and size of the lock bytes */
+ ndef_tlv_byte_addr = TOPAZ_BYTE_ADR_FROM_SEG (
+ ps_tpz_info->CurrentSeg , parse_index);
+ result = phFriNfc_Tpz_H_GetMemBytesInfo (psNdefMap, lock_mem_buf);
+ lock_mem_ndef_index = 0;
+ expected_seq = NDEF_T_TLV;
+ }
+
+ break;
+ }
+
+ case NDEF_T_TLV:
+ {
+ /* Parse the bytes till TYPE field of NDEF TLV is found, Once the
+ TYPE field is found then change the sequence to NDEF_L_TLV */
+ result = phFriNfc_Tpz_H_ParseNdefTLVType (psNdefMap, p_recv_buf,
+ &parse_index, recv_length, &expected_seq);
+
+ break;
+ }
+
+ case NDEF_L_TLV:
+ {
+ /* Length field of the NDEF TLV */
+ if (0 == lock_mem_ndef_index)
+ {
+ /* This is the 1st time, the loop has entered this case,
+ means that the NDEF byte address has to be updated */
+ ps_tpz_info->NdefTLVByteAddress = (uint16_t)
+ TOPAZ_BYTE_ADR_FROM_SEG (ps_tpz_info->CurrentSeg,
+ (parse_index - 1));
+ }
+
+ if (0 != lock_mem_ndef_index)
+ {
+ /* There is already index has been updated, update remaining
+ buffer */
+ lock_mem_buf[lock_mem_ndef_index] = p_recv_buf[parse_index];
+ parse_index = (uint16_t)(parse_index + 1);
+ lock_mem_ndef_index = (uint8_t)(lock_mem_ndef_index + 1);
+
+ if (TOPAZ_MEM_LOCK_TLV_LENGTH == lock_mem_ndef_index)
+ {
+ lock_mem_ndef_index = 0;
+ ps_tpz_info->ActualNDEFMsgSize = (uint16_t)((lock_mem_buf[1] <<
+ TOPAZ_BYTE_SHIFT) | lock_mem_buf[2]);
+ expected_seq = NDEF_V_TLV;
+ }
+ }
+ /* Check for remaining size in the card and the actual ndef length */
+ else if (p_recv_buf[parse_index] <=
+ (ps_tpz_info->RemainingSize - (parse_index + 1)))
+ {
+ /* This check is added to see that length field in the TLV is
+ greater than the 1 byte */
+ if (0xFF == p_recv_buf[parse_index])
+ {
+ lock_mem_buf[lock_mem_ndef_index] =
+ p_recv_buf[parse_index];
+ lock_mem_ndef_index = (uint8_t)(lock_mem_ndef_index + 1);
+ }
+ else
+ {
+ /* Length field of the TLV is ONE byte, so update the
+ actual ndef size */
+ lock_mem_ndef_index = 0;
+ ps_tpz_info->ActualNDEFMsgSize = (uint16_t)
+ p_recv_buf[parse_index];
+
+ expected_seq = NDEF_V_TLV;
+ }
+ parse_index = (uint16_t)(parse_index + 1);
+ }
+ else
+ {
+ /* Wrong length, remaining size in the card is lesser than the actual
+ ndef message length */
+ lock_mem_ndef_index = 0;
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_NO_NDEF_SUPPORT);
+ }
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }/* end of switch (expected_seq) */
+ } /* end of if (0 != skip_size) */
+ } /* while ((parse_index < recv_length) && (NFCSTATUS_SUCCESS != result) &&
+ (NDEF_V_TLV != expected_seq)) */
+
+ ps_tpz_info->ExpectedSeq = (uint8_t)expected_seq;
+
+ if (0 == ps_tpz_info->CurrentSeg)
+ {
+ /* First segment has the STATIC lock and reserved bytes, so delete it from
+ the remaining size */
+ ps_tpz_info->RemainingSize = (uint16_t)(ps_tpz_info->RemainingSize -
+ (parse_index + TOPAZ_STATIC_LOCK_RES_BYTES));
+
+ }
+ else
+ {
+ ps_tpz_info->RemainingSize = (uint16_t)(ps_tpz_info->RemainingSize -
+ parse_index);
+ }
+
+ if ((NDEF_V_TLV == expected_seq) && (NFCSTATUS_SUCCESS == result))
+ {
+ /* NDEF TLV found */
+ result = phFriNfc_Tpz_H_ActualCardSize (psNdefMap);
+
+ if ((PH_NDEFMAP_CARD_STATE_READ_ONLY != psNdefMap->CardState) &&
+ (0 != ps_tpz_info->ActualNDEFMsgSize))
+ {
+ /* Check if the card state is READ ONLY or the actual NDEF size is 0
+ if actual NDEF size is 0, then card state is INITIALISED
+ */
+ psNdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_WRITE;
+ }
+ }
+
+ if ((NFCSTATUS_SUCCESS == result) && (NDEF_V_TLV != expected_seq))
+ {
+ ps_tpz_info->CurrentSeg = (uint8_t)(ps_tpz_info->CurrentSeg + 1);
+ if (TOPAZ_TOTAL_SEG_TO_READ == ps_tpz_info->CurrentSeg)
+ {
+ /* Max segment to read reached, so no more read can be done */
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_NO_NDEF_SUPPORT);
+ }
+ else
+ {
+#ifdef TOPAZ_RAW_SUPPORT
+
+ *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_RSEG;
+
+#else
+
+ psNdefMap->Cmd.JewelCmd = phHal_eJewel_ReadSeg;
+
+#endif /* #ifdef TOPAZ_RAW_SUPPORT */
+ result = phFriNfc_Tpz_H_NxpRead(psNdefMap);
+ }
+ }
+
+ if ((NFCSTATUS_SUCCESS != result) && (NFCSTATUS_PENDING != result))
+ {
+ /* Error scenario */
+ ps_tpz_info->NdefTLVByteAddress = 0;
+ ps_tpz_info->ActualNDEFMsgSize = 0;
+ }
+
+ if (NFCSTATUS_PENDING != result)
+ {
+ /* Exit scenario */
+ if ((0x00 == *ps_tpz_info->CCByteBuf) ||
+ ((NDEF_T_TLV == expected_seq) &&
+ (TOPAZ_TOTAL_SEG_TO_READ == ps_tpz_info->CurrentSeg)))
+ {
+ /* This statement is for getting the new
+ NDEF TLV byte address, because 1st CC byte is corrupted or
+ no NDEF TLV in the card
+
+ If the 1st CC byte (NDEF magic number) in the card is 0, means
+ that previous write has failed, so to write the exact TLV,
+ calculate the byte number
+ OR
+ The NDEF TLV is not present in the entire card, and the sequence is
+ NDEF_T_TLV (this means, that lock and memory control TLV is found
+ in the card)
+ */
+ uint16_t size_to_skip = 0;
+ ps_tpz_info->ActualNDEFMsgSize = 0;
+
+ if (0 != ndef_tlv_byte_addr)
+ {
+ /* ndef_tlv_byte_addr is updated, only after complete parsing the
+ memory control TLV so the value shall not be 0 */
+ do
+ {
+ /* This loop is added to make sure the lock and reserved bytes are not
+ overwritten */
+ size_to_skip = 0;
+ size_to_skip = phFriNfc_Tpz_H_GetSkipSize (psNdefMap,
+ ndef_tlv_byte_addr);
+
+ ndef_tlv_byte_addr = (uint16_t)(ndef_tlv_byte_addr +
+ size_to_skip);
+ }while (0 != size_to_skip);
+
+ /* Update the TLV byte address */
+ ps_tpz_info->NdefTLVByteAddress = ndef_tlv_byte_addr;
+
+ /* Update the remaining size */
+ ps_tpz_info->RemainingSize = (uint16_t)(psNdefMap->CardMemSize +
+ TOPAZ_UID_BYTES_LENGTH +
+ TOPAZ_CC_BYTES_LENGTH);
+
+ ps_tpz_info->RemainingSize = (uint16_t)
+ (ps_tpz_info->RemainingSize -
+ (ndef_tlv_byte_addr +
+ TOPAZ_STATIC_LOCK_RES_BYTES));
+ (void)phFriNfc_Tpz_H_ActualCardSize (psNdefMap);
+
+ /* Length byte is subtracted here to get the actual NDEF
+ read and write size */
+ ps_tpz_info->NDEFRWSize = (uint16_t)
+ (ps_tpz_info->NDEFRWSize - 2);
+ ndef_tlv_byte_addr = 0;
+ }
+ }
+ }
+
+ return result;
+}
+
+static
+NFCSTATUS
+phFriNfc_Tpz_H_CopyReadDataAndWrite (
+ phFriNfc_NdefMap_t *psNdefMap)
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ phFriNfc_TopazCont_t *ps_tpz_info = NULL;
+ uint8_t write_buf[TOPAZ_WRITE_8_DATA_LENGTH];
+ uint16_t write_index = 0;
+ uint16_t write_len = 0;
+ uint16_t byte_addr = 0;
+ static uint16_t skip_size = 0;
+
+ ps_tpz_info = &(psNdefMap->TopazContainer);
+
+ write_len = (uint16_t)((psNdefMap->ApduBufferSize < ps_tpz_info->NDEFRWSize) ?
+ psNdefMap->ApduBufferSize : ps_tpz_info->NDEFRWSize);
+
+ (void)memcpy ((void *)write_buf, (void *)psNdefMap->SendRecvBuf,
+ TOPAZ_WRITE_8_DATA_LENGTH);
+
+ if (ps_tpz_info->CurrentBlock == TOPAZ_BLK_FROM_BYTE_ADR (
+ phFriNfc_Tpz_H_GetNDEFValueFieldAddrForWrite (psNdefMap, write_len)))
+ {
+ skip_size = 0;
+ }
+
+ /* Byte Number != 0 menas that the VALUE field of the TLV is in between the
+ block, so the first few bytes shall be copied and then user data has to
+ be copied
+ */
+ if (0 != ps_tpz_info->ByteNumber)
+ {
+ write_index = (uint16_t)(write_index + ps_tpz_info->ByteNumber);
+ }
+
+
+ if (0 != skip_size)
+ {
+ write_index = (uint16_t)(write_index + skip_size);
+ }
+
+ while ((write_index < TOPAZ_WRITE_8_DATA_LENGTH) &&
+ (write_len != psNdefMap->ApduBuffIndex))
+ {
+ skip_size = 0;
+ byte_addr = TOPAZ_BYTE_ADR_FROM_BLK (ps_tpz_info->CurrentBlock,
+ ps_tpz_info->ByteNumber);
+ skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, byte_addr);
+
+ if (0 == skip_size)
+ {
+ write_buf[write_index] =
+ psNdefMap->ApduBuffer[psNdefMap->ApduBuffIndex];
+
+ write_index = (uint16_t)(write_index + 1);
+ psNdefMap->ApduBuffIndex = (uint16_t)
+ (psNdefMap->ApduBuffIndex + 1);
+ ps_tpz_info->ByteNumber = (uint8_t)
+ (ps_tpz_info->ByteNumber + 1);
+ }
+ else
+ {
+
+ if (skip_size >= (TOPAZ_WRITE_8_DATA_LENGTH - write_index))
+ {
+ skip_size = (uint16_t)(skip_size - (TOPAZ_WRITE_8_DATA_LENGTH
+ - write_index));
+ write_index = (uint16_t)TOPAZ_WRITE_8_DATA_LENGTH;
+ }
+ else
+ {
+ ps_tpz_info->ByteNumber = (uint8_t)
+ (ps_tpz_info->ByteNumber + skip_size);
+ write_index = (uint16_t)(write_index + skip_size);
+ skip_size = 0;
+ }
+ }
+ }
+
+ if (psNdefMap->ApduBuffIndex == write_len)
+ {
+ ps_tpz_info->WriteSeq = (uint8_t)WR_DATA;
+ }
+ else
+ {
+ if (0 != skip_size)
+ {
+ ps_tpz_info->WriteSeq = (uint8_t)WR_DATA_READ_REQD;
+
+ }
+ else
+ {
+ ps_tpz_info->WriteSeq = (uint8_t)WR_DATA;
+ }
+ }
+
+#ifdef TOPAZ_RAW_SUPPORT
+ *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_E8;
+#else
+ psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write8E;
+#endif /* #ifdef TOPAZ_RAW_SUPPORT */
+ result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, write_buf,
+ sizeof (write_buf));
+
+ return result;
+
+}
+
+static
+NFCSTATUS
+phFriNfc_Tpz_H_UpdateLenFieldValuesAfterRead (
+ phFriNfc_NdefMap_t *psNdefMap)
+{
+ /* This function is called, only when the LENGTH field has to be updated
+ with the correct value */
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ phFriNfc_TopazCont_t *ps_tpz_info = NULL;
+ uint16_t write_len = 0;
+ uint16_t write_index = 0;
+ uint16_t byte_addr = 0;
+ phFriNfc_Tpz_WrSeq_t write_seq;
+ /* This variable is kept static because if the size to skip LOCK or RESERVED
+ bytes extends to next read then it shall be stored and used to skip the next
+ read the bytes
+ */
+ static uint16_t skip_size = 0;
+ uint8_t write_buf[TOPAZ_WRITE_8_DATA_LENGTH];
+ uint8_t exit_while = FALSE;
+
+ ps_tpz_info = &(psNdefMap->TopazContainer);
+ write_len = (uint16_t)((psNdefMap->ApduBufferSize < ps_tpz_info->NDEFRWSize) ?
+ psNdefMap->ApduBufferSize : ps_tpz_info->NDEFRWSize);
+
+ psNdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE;
+
+ (void)memcpy ((void *)write_buf, (void *)psNdefMap->SendRecvBuf,
+ TOPAZ_WRITE_8_DATA_LENGTH);
+
+ write_seq = (phFriNfc_Tpz_WrSeq_t)ps_tpz_info->WriteSeq;
+
+ if (WR_LEN_1_VALUE == write_seq)
+ {
+ /* First LENGTH field is geting updated, so the skip size
+ reset is done */
+ skip_size = 0;
+ }
+
+ if (0 != ps_tpz_info->ByteNumber)
+ {
+ /* Byte Number is not 0, means that some data shall not be overwriteen till
+ that position in the block */
+ write_index = (uint16_t)(write_index + ps_tpz_info->ByteNumber);
+ }
+
+ if (0 != skip_size)
+ {
+ /* This is possible after updating the FIRST length field
+ skip size is skipped because of the pending LOCK or
+ RESERVED bytes
+ */
+ write_index = (uint16_t)(write_index + skip_size);
+ }
+
+ while ((write_index < TOPAZ_WRITE_8_DATA_LENGTH) &&
+ (FALSE == exit_while))
+ {
+ skip_size = 0;
+ /* Get the exact byte address from the block number and
+ byte number */
+ byte_addr = TOPAZ_BYTE_ADR_FROM_BLK (ps_tpz_info->CurrentBlock,
+ ps_tpz_info->ByteNumber);
+ /* Get the skip size */
+ skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, byte_addr);
+
+ if (0 == skip_size)
+ {
+ switch (write_seq)
+ {
+ case WR_LEN_1_VALUE:
+ {
+ /* First sequenc is always to update 1st LENGTH field of the TLV */
+ if (write_len < 0xFF)
+ {
+ /* This means the LENGTH field is only one BYTE */
+ write_buf[write_index] = (uint8_t)
+ psNdefMap->ApduBuffIndex;
+ /* Exit the loop */
+ exit_while = TRUE;
+ }
+ else
+ {
+ /* Update the 1st LENGTH field */
+ write_buf[write_index] = (uint8_t)0xFF;
+ }
+ break;
+ }
+
+ case WR_LEN_2_VALUE:
+ {
+ /* Update the 2nd LENGTH field */
+ write_buf[write_index] = (uint8_t)
+ (psNdefMap->ApduBuffIndex >> BYTE_SIZE);
+ break;
+ }
+
+ case WR_LEN_3_VALUE:
+ {
+ /* Update the 3rd LENGTH field */
+ write_buf[write_index] = (uint8_t)
+ (psNdefMap->ApduBuffIndex &
+ TOPAZ_BYTE_LENGTH_MASK);
+ /* Exit the loop */
+ exit_while = TRUE;
+ break;
+ }
+
+ default:
+ {
+ /* Invalid case */
+ break;
+ }
+ }
+ write_index = (uint16_t)(write_index + 1);
+ if (
+ /* As the write is done for 8 bytes, the write index cant
+ go for more than or equal to 8 bytes, if it reaches 8 bytes
+ then sequence shall not be incrmented */
+ (TOPAZ_WRITE_8_DATA_LENGTH != write_index) &&
+ /* If the last length field byte is updated then the
+ write sequence shall not be incremented */
+ (WR_LEN_3_VALUE != write_seq) &&
+ /* Check added if the write length is less than 0xFF.
+ If length is less than 0xFF, then write sequence
+ shall not be incremented */
+ (write_len >= 0xFF)
+ )
+ {
+ /* Sequence is incremented to the next level */
+ write_seq = (phFriNfc_Tpz_WrSeq_t)(write_seq + 1);
+ }
+ /* Byte number is incremented */
+ ps_tpz_info->ByteNumber = (uint8_t)
+ (ps_tpz_info->ByteNumber + 1);
+ }
+ else
+ {
+
+ if (skip_size >= (TOPAZ_WRITE_8_DATA_LENGTH - write_index))
+ {
+ skip_size = (uint16_t)(skip_size - (TOPAZ_WRITE_8_DATA_LENGTH
+ - write_index));
+ write_index = (uint16_t)TOPAZ_WRITE_8_DATA_LENGTH;
+ }
+ else
+ {
+ ps_tpz_info->ByteNumber = (uint8_t)
+ (ps_tpz_info->ByteNumber + skip_size);
+ write_index = (uint16_t)(write_index + skip_size);
+ skip_size = 0;
+ }
+
+ }
+ }
+
+ ps_tpz_info->WriteSeq = (uint8_t)write_seq;
+
+#ifdef TOPAZ_RAW_SUPPORT
+ *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_E8;
+#else
+ psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write8E;
+#endif /* #ifdef TOPAZ_RAW_SUPPORT */
+
+ result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, write_buf,
+ sizeof (write_buf));
+ return result;
+}
+
+
+
+static
+NFCSTATUS
+phFriNfc_Tpz_H_UpdateLenFieldZeroAfterRead (
+ phFriNfc_NdefMap_t *psNdefMap)
+{
+ /* This function is called, only when the LENGTH field has to be updated
+ with the 0 */
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ phFriNfc_TopazCont_t *ps_tpz_info = NULL;
+ uint16_t write_len = 0;
+ uint16_t write_index = 0;
+ uint16_t prev_apdu_index = 0;
+ uint16_t byte_addr = 0;
+ phFriNfc_Tpz_WrSeq_t write_seq;
+ /* This variable is kept static because if the size to skip LOCK or RESERVED
+ bytes extends to next read then it shall be stored and used to skip the next
+ read bytes
+ */
+ static uint16_t skip_size = 0;
+ uint8_t write_buf[TOPAZ_WRITE_8_DATA_LENGTH];
+
+ ps_tpz_info = &(psNdefMap->TopazContainer);
+ write_len = (uint16_t)((psNdefMap->ApduBufferSize < ps_tpz_info->NDEFRWSize) ?
+ psNdefMap->ApduBufferSize : ps_tpz_info->NDEFRWSize);
+
+ psNdefMap->State = PH_FRINFC_TOPAZ_STATE_WRITE;
+
+ (void)memcpy ((void *)write_buf, (void *)psNdefMap->SendRecvBuf,
+ TOPAZ_WRITE_8_DATA_LENGTH);
+
+ prev_apdu_index = psNdefMap->ApduBuffIndex;
+ write_seq = (phFriNfc_Tpz_WrSeq_t)ps_tpz_info->WriteSeq;
+
+ if (WR_LEN_1_0 == write_seq)
+ {
+ /* First LENGTH field is geting updated, so the skip size
+ reset is done */
+ skip_size = 0;
+ }
+
+ if (0 != ps_tpz_info->ByteNumber)
+ {
+ /* Byte Number is not 0, means that some data shall not be overwriteen till
+ that position in the block */
+ write_index = (uint16_t)(write_index + ps_tpz_info->ByteNumber);
+ ps_tpz_info->ByteNumber = 0;
+ }
+
+ if (0 != skip_size)
+ {
+ /* This is possible after updating the FIRST length field
+ skip size is skipped because of the pending LOCK or
+ RESERVED bytes
+ */
+ write_index = (uint16_t)(write_index + skip_size);
+ }
+
+ while ((write_index < TOPAZ_WRITE_8_DATA_LENGTH) &&
+ (write_len != psNdefMap->ApduBuffIndex))
+ {
+ skip_size = 0;
+ byte_addr = TOPAZ_BYTE_ADR_FROM_BLK (ps_tpz_info->CurrentBlock,
+ ps_tpz_info->ByteNumber);
+ skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap, byte_addr);
+
+ if (0 == skip_size)
+ {
+ switch (write_seq)
+ {
+ case WR_LEN_1_0:
+ {
+ /* First sequence is always to update 1st LENGTH field
+ of the TLV */
+ write_buf[write_index] = 0x00;
+ write_index = (uint16_t)(write_index + 1);
+ if (write_len < 0xFF)
+ {
+ /* LENGTH field is only 1 byte, so update change the sequence to
+ update user data */
+ write_seq = WR_DATA;
+ }
+ else
+ {
+ /* Go to the next LENGTH field to update */
+ write_seq = (phFriNfc_Tpz_WrSeq_t)((TOPAZ_WRITE_8_DATA_LENGTH !=
+ write_index) ?
+ (write_seq + 1) : write_seq);
+ }
+ break;
+ }
+
+ case WR_LEN_2_0:
+ case WR_LEN_3_0:
+ {
+ /* Update 2nd and 3rd LEGNTH field */
+ write_buf[write_index] = 0x00;
+ write_index = (uint16_t)(write_index + 1);
+ write_seq = (phFriNfc_Tpz_WrSeq_t)((TOPAZ_WRITE_8_DATA_LENGTH !=
+ write_index) ?
+ (write_seq + 1) : write_seq);
+ break;
+ }
+
+ case WR_DATA:
+ default:
+ {
+ /* Update the buffer by the user data */
+ write_buf[write_index] =
+ psNdefMap->ApduBuffer[psNdefMap->ApduBuffIndex];
+
+ write_index = (uint16_t)(write_index + 1);
+ psNdefMap->ApduBuffIndex = (uint16_t)
+ (psNdefMap->ApduBuffIndex + 1);
+ break;
+ }
+
+ }
+
+ ps_tpz_info->ByteNumber = (uint8_t)
+ (ps_tpz_info->ByteNumber + 1);
+ }
+ else
+ {
+ /* LOCK and MEMORY bytes are found */
+ if (skip_size >= (TOPAZ_WRITE_8_DATA_LENGTH - write_index))
+ {
+ /* skip size has exceeded the block number, so calculate the
+ remaining skip size */
+ skip_size = (uint16_t)(skip_size - (TOPAZ_WRITE_8_DATA_LENGTH
+ - write_index));
+ write_index = (uint16_t)TOPAZ_WRITE_8_DATA_LENGTH;
+ }
+ else
+ {
+ /* skip the LOCK and MEMORY bytes size */
+ ps_tpz_info->ByteNumber = (uint8_t)
+ (ps_tpz_info->ByteNumber + skip_size);
+ write_index = (uint16_t)(write_index + skip_size);
+ skip_size = 0;
+ }
+ }
+ }
+
+ if (psNdefMap->ApduBuffIndex == write_len)
+ {
+ /* User data has been completely copied and it is ready to write, so
+ change the sequence */
+ ps_tpz_info->WriteSeq = (uint8_t)WR_DATA;
+ }
+ else if ((WR_DATA == write_seq) && (prev_apdu_index ==
+ psNdefMap->ApduBuffIndex))
+ {
+ /* The user data has not been written, only the LENGTH field is
+ updated */
+ ps_tpz_info->WriteSeq = (uint8_t)((write_len < 0xFF) ?
+ WR_LEN_1_0 : WR_LEN_3_0);
+ }
+ else
+ {
+ /* Update the sequence in the context */
+ ps_tpz_info->WriteSeq = (uint8_t)write_seq;
+ }
+
+ ps_tpz_info->ByteNumber = 0;
+
+#ifdef TOPAZ_RAW_SUPPORT
+ *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_E8;
+#else
+ psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write8E;
+#endif /* #ifdef TOPAZ_RAW_SUPPORT */
+
+ result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, write_buf,
+ sizeof (write_buf));
+ return result;
+}
+
+static
+NFCSTATUS
+phFriNfc_Tpz_H_RdForWrite (
+ phFriNfc_NdefMap_t *psNdefMap)
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ phFriNfc_TopazCont_t *ps_tpz_info = NULL;
+ phFriNfc_Tpz_WrSeq_t write_seq;
+ uint16_t byte_addr = 0;
+ uint8_t exit_while = FALSE;
+ uint16_t skip_size = 0;
+
+ ps_tpz_info = &(psNdefMap->TopazContainer);
+ write_seq = (phFriNfc_Tpz_WrSeq_t)(ps_tpz_info->WriteSeq);
+
+#ifdef TOPAZ_RAW_SUPPORT
+
+ *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_READ8;
+
+#else
+
+ psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read8;
+
+#endif /* #ifdef TOPAZ_RAW_SUPPORT */
+
+ psNdefMap->State = PH_FRINFC_TOPAZ_STATE_RD_FOR_WR_NDEF;
+
+ switch (write_seq)
+ {
+ case WR_LEN_1_0:
+ case WR_LEN_1_VALUE:
+ {
+ byte_addr = (ps_tpz_info->NdefTLVByteAddress + 1);
+
+ /* This loop is to skip the lock amd reserved bytes */
+ while (FALSE == exit_while)
+ {
+ if (TOPAZ_STATIC_LOCK_FIRST_BLOCK_NO ==
+ TOPAZ_BLK_FROM_BYTE_ADR (byte_addr))
+ {
+ byte_addr = (uint16_t)(byte_addr +
+ TOPAZ_STATIC_LOCK_RES_BYTES);
+ }
+ skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap,
+ byte_addr);
+ if (0 != skip_size)
+ {
+ byte_addr = (uint16_t)(byte_addr + skip_size);
+
+
+ }
+ else
+ {
+ exit_while = TRUE;
+ }
+ }
+ break;
+ }
+
+ case WR_LEN_2_0:
+ case WR_LEN_3_0:
+ case WR_LEN_2_VALUE:
+ case WR_LEN_3_VALUE:
+ {
+ byte_addr = (uint16_t)TOPAZ_BYTE_ADR_FROM_BLK (ps_tpz_info->CurrentBlock,
+ ps_tpz_info->ByteNumber);
+ /* This loop is for to skip the lock amd reserved bytes */
+ while (FALSE == exit_while)
+ {
+ skip_size = phFriNfc_Tpz_H_GetSkipSize (psNdefMap,
+ byte_addr);
+ if (0 != skip_size)
+ {
+ byte_addr = (uint16_t)(byte_addr + skip_size);
+ }
+ else
+ {
+ exit_while = TRUE;
+ }
+ }
+ break;
+ }
+
+ case WR_DATA_READ_REQD:
+ {
+ /* Lock or reserved bytes found bytes */
+ byte_addr = (uint16_t)TOPAZ_BYTE_ADR_FROM_BLK (ps_tpz_info->CurrentBlock,
+ ps_tpz_info->ByteNumber);
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+
+ ps_tpz_info->CurrentBlock = (uint8_t)
+ TOPAZ_BLK_FROM_BYTE_ADR (byte_addr);
+ ps_tpz_info->ByteNumber = (uint8_t)
+ TOPAZ_BYTE_OFFSET_FROM_BYTE_ADR (byte_addr);
+
+ result = phFriNfc_Tpz_H_NxpRead (psNdefMap);
+
+ return result;
+}
+
+static
+uint16_t
+phFriNfc_Tpz_H_CompareLockBlocks (
+ phFriNfc_NdefMap_t *psNdefMap,
+ uint8_t block_no,
+ uint16_t *p_skip_size)
+{
+ uint16_t return_addr = 0;
+ phFriNfc_LockCntrlTLVCont_t *ps_locktlv_info = NULL;
+
+ ps_locktlv_info = &(psNdefMap->LockTlv);
+
+ if (block_no == ps_locktlv_info->BlkNum)
+ {
+ /* ps_tpz_info->ByteNumber = (uint8_t)ps_locktlv_info->ByteNum; */
+ *p_skip_size = ps_locktlv_info->Size;
+ return_addr = ps_locktlv_info->ByteAddr;
+ }
+
+ return return_addr;
+}
+
+static
+uint16_t
+phFriNfc_Tpz_H_CompareMemBlocks (
+ phFriNfc_NdefMap_t *psNdefMap,
+ uint8_t block_no,
+ uint16_t *p_skip_size)
+{
+ uint16_t return_addr = 0;
+ phFriNfc_ResMemCntrlTLVCont_t *ps_memtlv_info = NULL;
+
+ ps_memtlv_info = &(psNdefMap->MemTlv);
+
+ if (block_no == ps_memtlv_info->BlkNum)
+ {
+ /* ps_tpz_info->ByteNumber = (uint8_t)ps_memtlv_info->ByteNum; */
+ *p_skip_size = ps_memtlv_info->Size;
+ return_addr = ps_memtlv_info->ByteAddr;
+ }
+
+ return return_addr;
+}
+
+
+static
+NFCSTATUS
+phFriNfc_Tpz_H_CopySendWrData (
+ phFriNfc_NdefMap_t *psNdefMap)
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ phFriNfc_TopazCont_t *ps_tpz_info = NULL;
+ uint8_t write_buf[TOPAZ_WRITE_8_DATA_LENGTH];
+ uint16_t write_len;
+ uint8_t copy_length;
+ uint16_t skip_size = 0;
+
+ ps_tpz_info = &(psNdefMap->TopazContainer);
+ write_len = (uint16_t)((psNdefMap->ApduBufferSize < ps_tpz_info->NDEFRWSize) ?
+ psNdefMap->ApduBufferSize : ps_tpz_info->NDEFRWSize);
+
+ if (0 != phFriNfc_Tpz_H_CompareLockBlocks (psNdefMap,
+ ps_tpz_info->CurrentBlock, &skip_size))
+ {
+ ps_tpz_info->WriteSeq = (uint8_t)WR_DATA_READ_REQD;
+ ps_tpz_info->ByteNumber = 0;
+ result = phFriNfc_Tpz_H_RdForWrite (psNdefMap);
+ }
+ else if (0 != phFriNfc_Tpz_H_CompareMemBlocks (psNdefMap,
+ ps_tpz_info->CurrentBlock, &skip_size))
+ {
+ ps_tpz_info->WriteSeq = (uint8_t)WR_DATA_READ_REQD;
+ ps_tpz_info->ByteNumber = 0;
+ result = phFriNfc_Tpz_H_RdForWrite (psNdefMap);
+ }
+ else
+ {
+#ifdef TOPAZ_RAW_SUPPORT
+ *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_E8;
+#else
+ psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write8E;
+#endif /* #ifdef TOPAZ_RAW_SUPPORT */
+ psNdefMap->State = (uint8_t)PH_FRINFC_TOPAZ_STATE_WRITE;
+
+ if ((write_len - psNdefMap->ApduBuffIndex) >= TOPAZ_WRITE_8_DATA_LENGTH)
+ {
+ copy_length = (uint8_t)TOPAZ_WRITE_8_DATA_LENGTH;
+ (void)memcpy ((void *)write_buf,
+ (void *)(psNdefMap->ApduBuffer + psNdefMap->ApduBuffIndex),
+ copy_length);
+
+ psNdefMap->ApduBuffIndex = (uint16_t)(psNdefMap->ApduBuffIndex +
+ copy_length);
+ }
+ else
+ {
+ copy_length = (uint8_t)(write_len - psNdefMap->ApduBuffIndex);
+
+ (void)memcpy ((void *)write_buf,
+ (void *)(psNdefMap->ApduBuffer + psNdefMap->ApduBuffIndex),
+ TOPAZ_WRITE_8_DATA_LENGTH);
+
+ psNdefMap->ApduBuffIndex = (uint16_t)(psNdefMap->ApduBuffIndex +
+ copy_length);
+
+ (void)memset ((void *)(write_buf + copy_length), 0x00,
+ (TOPAZ_WRITE_8_DATA_LENGTH - copy_length));
+ }
+
+#ifdef TOPAZ_RAW_SUPPORT
+ *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_WRITE_E8;
+#else
+ psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write8E;
+#endif /* #ifdef TOPAZ_RAW_SUPPORT */
+
+ result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, write_buf,
+ sizeof (write_buf));
+ }
+
+
+ return result;
+}
+
+
+static
+NFCSTATUS
+phFriNfc_Tpz_H_ActualCardSize (
+ phFriNfc_NdefMap_t *psNdefMap)
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ phFriNfc_TopazCont_t *ps_tpz_info = NULL;
+ phFriNfc_LockCntrlTLVCont_t *ps_locktlv_info = NULL;
+ phFriNfc_ResMemCntrlTLVCont_t *ps_memtlv_info = NULL;
+ uint16_t ndef_value_byte_addr = 0;
+ uint16_t ndef_read_write_size = 0;
+
+ ps_tpz_info = &(psNdefMap->TopazContainer);
+ if (ps_tpz_info->ActualNDEFMsgSize > ps_tpz_info->RemainingSize)
+ {
+ ps_tpz_info->ActualNDEFMsgSize = 0;
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_NO_NDEF_SUPPORT);
+ }
+ else
+ {
+ ndef_read_write_size = ps_tpz_info->RemainingSize;
+ ndef_value_byte_addr = phFriNfc_Tpz_H_GetNDEFValueFieldAddrForRead
+ (psNdefMap);
+
+ ps_locktlv_info = &(psNdefMap->LockTlv);
+ if (ps_locktlv_info->ByteAddr > ndef_value_byte_addr)
+ {
+ ndef_read_write_size = (ndef_read_write_size -
+ ps_locktlv_info->Size);
+ }
+
+ ps_memtlv_info = &(psNdefMap->MemTlv);
+ if (ps_memtlv_info->ByteAddr > ndef_value_byte_addr)
+ {
+ ndef_read_write_size = (ndef_read_write_size -
+ ps_memtlv_info->Size);
+ }
+
+ if (ps_tpz_info->ActualNDEFMsgSize > ndef_read_write_size)
+ {
+ ps_tpz_info->ActualNDEFMsgSize = 0;
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_NO_NDEF_SUPPORT);
+ }
+ else
+ {
+ ps_tpz_info->NDEFRWSize = (uint16_t)
+ ((ps_tpz_info->ActualNDEFMsgSize < 0xFF) ?
+ (ndef_read_write_size - 2) :
+ ndef_read_write_size);
+ }
+ }
+
+ return result;
+}
+
+static
+NFCSTATUS
+phFriNfc_Tpz_H_ParseLockTLVType (
+ phFriNfc_NdefMap_t *psNdefMap,
+ uint8_t *p_parse_data,
+ uint16_t *p_parse_index,
+ uint16_t total_len_to_parse,
+ phFriNfc_Tpz_ParseSeq_t *seq_to_execute)
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ uint16_t parse_index = *p_parse_index;
+ phFriNfc_Tpz_ParseSeq_t expected_seq = *seq_to_execute;
+
+ PHNFC_UNUSED_VARIABLE(psNdefMap);
+ PHNFC_UNUSED_VARIABLE(total_len_to_parse);
+
+ switch (p_parse_data[parse_index])
+ {
+ case PH_FRINFC_TOPAZ_LOCK_CTRL_T:
+ {
+ expected_seq = LOCK_L_TLV;
+ parse_index = (parse_index + 1);
+ break;
+ }
+
+ case PH_FRINFC_TOPAZ_NULL_T:
+ {
+ expected_seq = LOCK_T_TLV;
+ parse_index = (parse_index + 1);
+ break;
+ }
+
+ default:
+ {
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_NO_NDEF_SUPPORT);
+ break;
+ }
+ }
+
+
+ *seq_to_execute = expected_seq;
+ *p_parse_index = parse_index;
+ return result;
+}
+
+static
+NFCSTATUS
+phFriNfc_Tpz_H_ParseMemTLVType (
+ phFriNfc_NdefMap_t *psNdefMap,
+ uint8_t *p_parse_data,
+ uint16_t *p_parse_index,
+ uint16_t total_len_to_parse,
+ phFriNfc_Tpz_ParseSeq_t *seq_to_execute)
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ uint16_t parse_index = *p_parse_index;
+ phFriNfc_Tpz_ParseSeq_t expected_seq = *seq_to_execute;
+
+ PHNFC_UNUSED_VARIABLE(psNdefMap);
+ PHNFC_UNUSED_VARIABLE(total_len_to_parse);
+
+ switch (p_parse_data[parse_index])
+ {
+ case PH_FRINFC_TOPAZ_LOCK_CTRL_T:
+ {
+ expected_seq = LOCK_L_TLV;
+ parse_index = (parse_index + 1);
+ break;
+ }
+
+ case PH_FRINFC_TOPAZ_NULL_T:
+ {
+ expected_seq = MEM_T_TLV;
+ parse_index = (parse_index + 1);
+ break;
+ }
+
+ case PH_FRINFC_TOPAZ_MEM_CTRL_T:
+ {
+ expected_seq = MEM_L_TLV;
+ parse_index = (parse_index + 1);
+ break;
+ }
+
+ default:
+ {
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_NO_NDEF_SUPPORT);
+ break;
+ }
+ }
+
+ *seq_to_execute = expected_seq;
+ *p_parse_index = parse_index;
+ return result;
+}
+
+static
+NFCSTATUS
+phFriNfc_Tpz_H_ParseNdefTLVType (
+ phFriNfc_NdefMap_t *psNdefMap,
+ uint8_t *p_parse_data,
+ uint16_t *p_parse_index,
+ uint16_t total_len_to_parse,
+ phFriNfc_Tpz_ParseSeq_t *seq_to_execute)
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ uint16_t parse_index = *p_parse_index;
+ phFriNfc_Tpz_ParseSeq_t expected_seq = *seq_to_execute;
+
+ PHNFC_UNUSED_VARIABLE(psNdefMap);
+ PHNFC_UNUSED_VARIABLE(total_len_to_parse);
+
+ switch (p_parse_data[parse_index])
+ {
+ case PH_FRINFC_TOPAZ_MEM_CTRL_T:
+ {
+ /* TYPE field of Memory control TLV is found.
+ This means that more than one memory control
+ TLV exists */
+ expected_seq = MEM_L_TLV;
+ parse_index = (parse_index + 1);
+ break;
+ }
+
+ case PH_FRINFC_TOPAZ_NULL_T:
+ {
+ /* Skip the NULL TLV */
+ expected_seq = NDEF_T_TLV;
+ parse_index = (parse_index + 1);
+ break;
+ }
+
+ case PH_FRINFC_TOPAZ_NDEF_T:
+ {
+ /* TYPE field of NDEF TLV found, so next expected
+ sequence is LENGTH field */
+ expected_seq = NDEF_L_TLV;
+ parse_index = (parse_index + 1);
+ break;
+ }
+
+ default:
+ {
+ /* Reset the sequence */
+ expected_seq = LOCK_T_TLV;
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_NO_NDEF_SUPPORT);
+ break;
+ }
+ }
+
+ *seq_to_execute = expected_seq;
+ *p_parse_index = parse_index;
+ return result;
+}
+
+static
+uint16_t
+phFriNfc_Tpz_H_GetSkipSize (
+ phFriNfc_NdefMap_t *psNdefMap,
+ uint16_t byte_adr_card)
+{
+ uint16_t return_size = 0;
+ phFriNfc_LockCntrlTLVCont_t *ps_locktlv_info = NULL;
+ phFriNfc_ResMemCntrlTLVCont_t *ps_memtlv_info = NULL;
+
+ ps_locktlv_info = &(psNdefMap->LockTlv);
+ ps_memtlv_info = &(psNdefMap->MemTlv);
+
+ /* If there are more than one LOCK CONTROL TLV, then
+ ADD A LOOP HERE OF THE NUMBER OF TLVs FOUND */
+ if (byte_adr_card == ps_locktlv_info->ByteAddr)
+ {
+ return_size = ps_locktlv_info->Size;
+ }
+
+ /* If there are more than one MEMORY CONTROL TLV, then
+ ADD A LOOP HERE OF THE NUMBER OF TLVs FOUND */
+ if (byte_adr_card == ps_memtlv_info->ByteAddr)
+ {
+ return_size = ps_memtlv_info->Size;
+ }
+ return return_size;
+}
+
+static
+NFCSTATUS
+phFriNfc_Tpz_H_GetLockBytesInfo (
+ phFriNfc_NdefMap_t *psNdefMap,
+ uint8_t *p_lock_info)
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ phFriNfc_LockCntrlTLVCont_t *ps_locktlv_info = NULL;
+ uint8_t page_address = 0;
+ uint8_t bytes_offset = 0;
+ uint8_t lock_index = 0;
+
+ ps_locktlv_info = &(psNdefMap->LockTlv);
+
+ page_address = (uint8_t)(p_lock_info[lock_index] >> NIBBLE_SIZE);
+ bytes_offset = (uint8_t)(p_lock_info[lock_index] & TOPAZ_NIBBLE_MASK);
+
+ lock_index = (lock_index + 1);
+ ps_locktlv_info->Size = (uint16_t)
+ (((p_lock_info[lock_index] % TOPAZ_BYTE_SIZE_IN_BITS) > 0)?
+ ((p_lock_info[lock_index] / TOPAZ_BYTE_SIZE_IN_BITS) + 1) :
+ (p_lock_info[lock_index] / TOPAZ_BYTE_SIZE_IN_BITS));
+
+ lock_index = (lock_index + 1);
+ ps_locktlv_info->BytesPerPage =
+ (p_lock_info[lock_index] & TOPAZ_NIBBLE_MASK);
+ ps_locktlv_info->BytesLockedPerLockBit =
+ (p_lock_info[lock_index] >> NIBBLE_SIZE);
+
+ /* Apply the formula to calculate byte address
+ ByteAddr = PageAddr*2^BytesPerPage + ByteOffset
+ */
+ ps_locktlv_info->ByteAddr = (uint16_t)((page_address
+ * (2 << ps_locktlv_info->BytesPerPage))
+ + bytes_offset);
+
+
+ if (
+ /* Out of bound memory check */
+ ((ps_locktlv_info->ByteAddr + ps_locktlv_info->Size) >
+ (uint16_t)(psNdefMap->TopazContainer.CCByteBuf[2] *
+ TOPAZ_BYTES_PER_BLOCK)) ||
+
+ /* Check the static lock and reserved areas memory blocks */
+ ((ps_locktlv_info->ByteAddr >= TOPAZ_STATIC_LOCK_RES_START) &&
+ (ps_locktlv_info->ByteAddr < TOPAZ_STATIC_LOCK_RES_END)) ||
+ (((ps_locktlv_info->ByteAddr + ps_locktlv_info->Size - 1) >=
+ TOPAZ_STATIC_LOCK_RES_START) &&
+ ((ps_locktlv_info->ByteAddr + ps_locktlv_info->Size - 1) <
+ TOPAZ_STATIC_LOCK_RES_END))
+ )
+ {
+ ps_locktlv_info->ByteAddr = 0;
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_NO_NDEF_SUPPORT);
+ }
+ else
+ {
+ ps_locktlv_info->BlkNum = (ps_locktlv_info->ByteAddr /
+ TOPAZ_BYTES_PER_BLOCK);
+ ps_locktlv_info->ByteNum = (ps_locktlv_info->ByteAddr %
+ TOPAZ_BYTES_PER_BLOCK);
+ }
+
+ return result;
+}
+
+static
+NFCSTATUS
+phFriNfc_Tpz_H_GetMemBytesInfo (
+ phFriNfc_NdefMap_t *psNdefMap,
+ uint8_t *p_mem_info)
+{
+ NFCSTATUS result = NFCSTATUS_SUCCESS;
+ phFriNfc_ResMemCntrlTLVCont_t *ps_memtlv_info = NULL;
+ phFriNfc_LockCntrlTLVCont_t *ps_locktlv_info = NULL;
+ uint8_t page_address = 0;
+ uint8_t bytes_offset = 0;
+ uint8_t mem_index = 0;
+
+ ps_memtlv_info = &(psNdefMap->MemTlv);
+ ps_locktlv_info = &(psNdefMap->LockTlv);
+ page_address = (uint8_t)(p_mem_info[mem_index] >> NIBBLE_SIZE);
+ bytes_offset = (uint8_t)(p_mem_info[mem_index] & TOPAZ_NIBBLE_MASK);
+
+ mem_index = (mem_index + 1);
+ ps_memtlv_info->Size = (uint16_t)p_mem_info[mem_index];
+
+ mem_index = (mem_index + 1);
+ ps_memtlv_info->BytesPerPage =
+ (p_mem_info[mem_index] & TOPAZ_NIBBLE_MASK);
+
+ /* Apply the formula to calculate byte address
+ ByteAddr = PageAddr * 2^BytesPerPage + ByteOffset
+ */
+ ps_memtlv_info->ByteAddr = (uint16_t)((page_address
+ * (2 << ps_memtlv_info->BytesPerPage))
+ + bytes_offset);
+
+
+ if (
+ /* Check if the lock and memory bytes are overlapped */
+ ((ps_memtlv_info->ByteAddr >= ps_locktlv_info->ByteAddr) &&
+ (ps_memtlv_info->ByteAddr <=
+ (ps_locktlv_info->ByteAddr + ps_locktlv_info->Size - 1))) ||
+
+ (((ps_memtlv_info->ByteAddr + ps_memtlv_info->Size - 1) >=
+ ps_locktlv_info->ByteAddr) &&
+ ((ps_memtlv_info->ByteAddr + ps_memtlv_info->Size - 1) <=
+ (ps_locktlv_info->ByteAddr + ps_locktlv_info->Size - 1))) ||
+
+ /* Check the static lock and reserved areas memory blocks */
+ ((ps_memtlv_info->ByteAddr >= TOPAZ_STATIC_LOCK_RES_START) &&
+ (ps_memtlv_info->ByteAddr < TOPAZ_STATIC_LOCK_RES_END)) ||
+ (((ps_memtlv_info->ByteAddr + ps_memtlv_info->Size - 1) >=
+ TOPAZ_STATIC_LOCK_RES_START) &&
+ ((ps_memtlv_info->ByteAddr + ps_memtlv_info->Size - 1) <
+ TOPAZ_STATIC_LOCK_RES_END)) ||
+
+ /* Check if the memory address is out bound */
+ ((ps_locktlv_info->ByteAddr + ps_locktlv_info->Size) >
+ (uint16_t)(psNdefMap->TopazContainer.CCByteBuf[2] *
+ TOPAZ_BYTES_PER_BLOCK))
+ )
+ {
+ ps_memtlv_info->ByteAddr = 0;
+ result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP,
+ NFCSTATUS_NO_NDEF_SUPPORT);
+ }
+ else
+ {
+ ps_memtlv_info->BlkNum = (ps_memtlv_info->ByteAddr /
+ TOPAZ_BYTES_PER_BLOCK);
+ ps_memtlv_info->ByteNum = (ps_memtlv_info->ByteAddr %
+ TOPAZ_BYTES_PER_BLOCK);
+ }
+
+ return result;
+}
+
+#ifdef UNIT_TEST
+#include <phUnitTestNfc_TopazDynamic_static.c>
+#endif
+
+#endif /*#if !(defined(PH_FRINFC_MAP_TOPAZ_DISABLED ) || defined (PH_FRINFC_MAP_TOPAZ_DYNAMIC_DISABLED ))*/
+
+
+