diff options
Diffstat (limited to 'src/phFriNfc_TopazDynamicMap.c')
-rw-r--r-- | src/phFriNfc_TopazDynamicMap.c | 3800 |
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 ))*/ + + + |