| /* |
| * 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: Wed Oct 27 10:21:29 2010 $ |
| * $Author: ing02260 $ |
| * $Revision: 1.41 $ |
| * $Aliases: $ |
| * |
| */ |
| |
| |
| |
| #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.41 $" |
| #define PHFRINFCTOPAZMAP_FILEALIASES "$Aliases: $" |
| /*@}*/ |
| /*! |
| * \name Topaz Mapping - Helper data structures and macros |
| * |
| */ |
| /*@{*/ |
| |
| /********************************** Start of data structures *********************************/ |
| #ifdef FRINFC_READONLY_NDEF |
| |
| #define DYN_CC_BLOCK_NUMBER (0x01U) |
| #define DYN_STATIC_LOCK_BLOCK_NUM (0x0EU) |
| |
| #define DYN_STATIC_LOCK0_BYTE_NUM (0x00U) |
| #define DYN_STATIC_LOCK0_BYTE_VALUE (0xFFU) |
| |
| #define DYN_STATIC_LOCK1_BYTE_NUM (0x01U) |
| #define DYN_STATIC_LOCK1_BYTE_VALUE (0x7FU) |
| |
| #define DYN_CC_RWA_BYTE_NUMBER (0x03U) |
| #define DYN_CC_READ_ONLY_VALUE (0x0FU) |
| |
| #endif /* #ifdef FRINFC_READONLY_NDEF */ |
| |
| /*! |
| * \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; |
| |
| #ifdef FRINFC_READONLY_NDEF |
| |
| typedef enum phFriNfc_Tpz_RO_Seq |
| { |
| WR_READONLY_CC, |
| RD_LOCK_BYTES, |
| WR_LOCK_BYTES, |
| RD_STATIC_LOCK_BYTE0, |
| WR_STATIC_LOCK_BYTE0, |
| WR_STATIC_LOCK_BYTE1 |
| }phFriNfc_Tpz_RO_Seq_t; |
| |
| #endif /* #ifdef FRINFC_READONLY_NDEF */ |
| |
| /********************************** End of data structures *********************************/ |
| |
| /********************************** Start of Macros *********************************/ |
| /* New state for TOPAZ dynamic card*/ |
| #define PH_FRINFC_TOPAZ_STATE_RD_FOR_WR_NDEF (0x10U) |
| |
| #ifdef FRINFC_READONLY_NDEF |
| #define PH_FRINFC_TOPAZ_STATE_READ_ONLY (0x11U) |
| #endif /* #ifdef FRINFC_READONLY_NDEF */ |
| |
| #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 (0x78U) |
| |
| /* 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)) |
| |
| #ifdef FRINFC_READONLY_NDEF |
| |
| #define TOPAZ_CONVERT_BITS_TO_BYTES(bits_to_bytes) \ |
| (((bits_to_bytes % TOPAZ_BYTE_SIZE_IN_BITS) > 0) ? \ |
| ((bits_to_bytes / TOPAZ_BYTE_SIZE_IN_BITS) + 1) : \ |
| (bits_to_bytes / TOPAZ_BYTE_SIZE_IN_BITS)) |
| |
| #endif /* #ifdef FRINFC_READONLY_NDEF */ |
| /********************************** 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); |
| |
| #ifdef FRINFC_READONLY_NDEF |
| |
| static |
| NFCSTATUS |
| phFriNfc_Tpz_H_ProcessReadOnly ( |
| phFriNfc_NdefMap_t *psNdefMap); |
| |
| static |
| NFCSTATUS |
| phFriNfc_Tpz_H_UpdateAndWriteLockBits ( |
| phFriNfc_NdefMap_t *psNdefMap); |
| |
| |
| #endif /* #ifdef FRINFC_READONLY_NDEF */ |
| |
| |
| /*! |
| * \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; |
| |
| (void)memset ((void *)&(NdefMap->LockTlv), 0, |
| sizeof (phFriNfc_LockCntrlTLVCont_t)); |
| |
| (void)memset ((void *)&(NdefMap->MemTlv), 0, |
| sizeof (phFriNfc_ResMemCntrlTLVCont_t)); |
| |
| /* 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; |
| } |
| |
| #ifdef FRINFC_READONLY_NDEF |
| |
| NFCSTATUS |
| phFriNfc_TopazDynamicMap_ConvertToReadOnly ( |
| phFriNfc_NdefMap_t *psNdefMap) |
| { |
| NFCSTATUS result = NFCSTATUS_SUCCESS; |
| uint8_t cc_read_only_byte = 0x0FU; |
| |
| psNdefMap->State = PH_FRINFC_TOPAZ_STATE_READ_ONLY; |
| |
| psNdefMap->TopazContainer.read_only_seq = 0; |
| |
| |
| |
| psNdefMap->TopazContainer.CurrentBlock = 0x01U; |
| psNdefMap->TopazContainer.ByteNumber = 0x03U; |
| |
| #ifdef TOPAZ_RAW_SUPPORT |
| *psNdefMap->SendRecvBuf = (uint8_t)PH_FRINFC_TOPAZ_CMD_WRITE_1E; |
| #else |
| psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E; |
| #endif /* #ifdef TOPAZ_RAW_SUPPORT */ |
| |
| result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, &cc_read_only_byte, |
| 1); |
| |
| if (NFCSTATUS_PENDING == result) |
| { |
| psNdefMap->TopazContainer.read_only_seq = (uint8_t)WR_READONLY_CC; |
| } |
| |
| |
| return result; |
| } |
| |
| #endif /* #ifdef FRINFC_READONLY_NDEF */ |
| |
| /*! |
| * \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; |
| } |
| |
| #ifdef FRINFC_READONLY_NDEF |
| case PH_FRINFC_TOPAZ_STATE_READ_ONLY: |
| { |
| Status = phFriNfc_Tpz_H_ProcessReadOnly (NdefMap); |
| break; |
| } |
| #endif /* #ifdef FRINFC_READONLY_NDEF */ |
| |
| 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); |
| } |
| } |
| |
| #ifdef FRINFC_READONLY_NDEF |
| |
| static |
| NFCSTATUS |
| phFriNfc_Tpz_H_UpdateAndWriteLockBits ( |
| phFriNfc_NdefMap_t *psNdefMap) |
| { |
| NFCSTATUS result = NFCSTATUS_SUCCESS; |
| phFriNfc_TopazCont_t *ps_tpz_info = NULL; |
| phFriNfc_LockCntrlTLVCont_t *ps_locktlv_info = NULL; |
| uint8_t remaining_lock_bits = 0; |
| uint8_t byte_index = 0; |
| uint8_t lock_bytes_value[TOPAZ_BYTES_PER_BLOCK] = {0}; |
| uint8_t lock_byte_index = 0; |
| uint8_t no_of_bits_left_in_block = 0; |
| |
| ps_tpz_info = &(psNdefMap->TopazContainer); |
| ps_locktlv_info = &(psNdefMap->LockTlv); |
| |
| (void)memcpy ((void *)lock_bytes_value, (void *)psNdefMap->SendRecvBuf, |
| TOPAZ_BYTES_PER_BLOCK); |
| |
| if (ps_tpz_info->CurrentBlock == ps_locktlv_info->BlkNum) |
| { |
| /* Get the lock bits that has to locked */ |
| remaining_lock_bits = ps_locktlv_info->LockTlvBuff[1]; |
| byte_index = (uint8_t)ps_locktlv_info->ByteNum; |
| } |
| else |
| { |
| /* This condition applies only for the lock bits not ending with |
| " ps_locktlv_info->BlkNum ". |
| Calculate the remaining lock bits */ |
| remaining_lock_bits = (uint8_t)(ps_locktlv_info->LockTlvBuff[1] - |
| ps_tpz_info->lock_bytes_written); |
| } |
| |
| no_of_bits_left_in_block = (uint8_t)((TOPAZ_BYTES_PER_BLOCK - byte_index) * |
| TOPAZ_BYTE_SIZE_IN_BITS); |
| |
| if (no_of_bits_left_in_block >= remaining_lock_bits) |
| { |
| /* Entire lock bits can be written */ |
| uint8_t mod_value = 0; |
| |
| mod_value = (uint8_t)(remaining_lock_bits % TOPAZ_BYTES_PER_BLOCK); |
| |
| if (mod_value) |
| { |
| /* The lock bits ends in between of a byte */ |
| /* lock bits to write is greater than 8 bits */ |
| if (mod_value > TOPAZ_BYTE_SIZE_IN_BITS) |
| { |
| while (lock_byte_index < |
| (TOPAZ_CONVERT_BITS_TO_BYTES(remaining_lock_bits) - 1)) |
| { |
| /* Set 1b to all bits left in the block */ |
| lock_bytes_value[byte_index] = 0xFF; |
| lock_byte_index = (uint8_t)(lock_byte_index + 1); |
| byte_index = (uint8_t)(byte_index + 1); |
| } |
| /* Last byte of the lock bits shall be filled partially, |
| Set only the remaining lock bits and dont change |
| the other bit value */ |
| lock_bytes_value[byte_index] = 0; |
| lock_bytes_value[byte_index] = (uint8_t) |
| SET_BITS8 (lock_bytes_value[byte_index], 0, |
| mod_value, 1); |
| } |
| else |
| { |
| /* lock bits to write is less than 8 bits, so |
| there is only one byte to write. |
| Set only the remaining lock bits and dont change |
| the other bit value */ |
| lock_bytes_value[0] = (uint8_t) |
| SET_BITS8 (lock_bytes_value[0], 0, |
| mod_value, 1); |
| } |
| } /* if (mod_value) */ |
| else |
| { |
| /* The lock bits exactly ends at a byte |
| MOD operation is 00, that means entire byte value shall be 0xFF, means |
| every bit shall be to 1 */ |
| |
| while (lock_byte_index < TOPAZ_CONVERT_BITS_TO_BYTES(remaining_lock_bits)) |
| { |
| /* Set 1b to all bits left in the block */ |
| lock_bytes_value[byte_index] = 0xFF; |
| lock_byte_index = (uint8_t)(lock_byte_index + 1); |
| byte_index = (uint8_t)(byte_index + 1); |
| } |
| } /* else of if (mod_value) */ |
| ps_tpz_info->lock_bytes_written = remaining_lock_bits; |
| } |
| else /* if (no_of_bits_left_in_block >= remaining_lock_bits) */ |
| { |
| /* Partial lock bits can be written. use next read to write |
| the remaining lock bits */ |
| while (lock_byte_index < (no_of_bits_left_in_block / |
| TOPAZ_BYTES_PER_BLOCK)) |
| { |
| /* Set 1b to all bits left in the block */ |
| lock_bytes_value[byte_index] = 0xFF; |
| lock_byte_index = (uint8_t)(lock_byte_index + 1); |
| byte_index = (uint8_t)(byte_index + 1); |
| } |
| ps_tpz_info->lock_bytes_written = (uint8_t)(no_of_bits_left_in_block / |
| TOPAZ_BYTES_PER_BLOCK); |
| } /* else of if (no_of_bits_left_in_block >= remaining_lock_bits) */ |
| |
| #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, lock_bytes_value, |
| sizeof (lock_bytes_value)); |
| return result; |
| } |
| |
| static |
| NFCSTATUS |
| phFriNfc_Tpz_H_ProcessReadOnly ( |
| phFriNfc_NdefMap_t *psNdefMap) |
| { |
| NFCSTATUS result = NFCSTATUS_SUCCESS; |
| phFriNfc_Tpz_RO_Seq_t e_readonly_seq = RD_LOCK_BYTES; |
| phFriNfc_TopazCont_t *ps_tpz_info = NULL; |
| phFriNfc_LockCntrlTLVCont_t *ps_locktlv_info = NULL; |
| static uint8_t static_lock_bytes[2] = {0}; |
| |
| ps_tpz_info = &(psNdefMap->TopazContainer); |
| ps_locktlv_info = &(psNdefMap->LockTlv); |
| e_readonly_seq = (phFriNfc_Tpz_RO_Seq_t)psNdefMap->TopazContainer.read_only_seq; |
| |
| switch (e_readonly_seq) |
| { |
| case WR_READONLY_CC: |
| { |
| if (TOPAZ_WRITE_1_RESPONSE == *psNdefMap->SendRecvLength) |
| { |
| psNdefMap->TopazContainer.CurrentBlock = (uint8_t) |
| psNdefMap->LockTlv.BlkNum; |
| |
| e_readonly_seq = RD_LOCK_BYTES; |
| #ifdef TOPAZ_RAW_SUPPORT |
| |
| *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_READ8; |
| |
| #else |
| |
| /* Topaz command = Jewel Nxp Read */ |
| #ifdef PH_HAL4_ENABLE |
| psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read; |
| #else |
| psNdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead; |
| #endif |
| |
| psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read8; |
| |
| #endif /* #ifdef TOPAZ_RAW_SUPPORT */ |
| /* Call read segment */ |
| result = phFriNfc_Tpz_H_NxpRead (psNdefMap); |
| } |
| else |
| { |
| result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, |
| NFCSTATUS_INVALID_RECEIVE_LENGTH); |
| } |
| break; |
| } |
| |
| case RD_LOCK_BYTES: |
| { |
| if (TOPAZ_READ_8_RESPONSE == *psNdefMap->SendRecvLength) |
| { |
| result = phFriNfc_Tpz_H_UpdateAndWriteLockBits (psNdefMap); |
| |
| if (NFCSTATUS_PENDING == result) |
| { |
| e_readonly_seq = WR_LOCK_BYTES; |
| } |
| } |
| else |
| { |
| result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, |
| NFCSTATUS_INVALID_RECEIVE_LENGTH); |
| } |
| break; |
| } |
| |
| case WR_LOCK_BYTES: |
| { |
| if (TOPAZ_WRITE_8_RESPONSE == *psNdefMap->SendRecvLength) |
| { |
| ps_tpz_info->CurrentBlock = (uint8_t) |
| (ps_tpz_info->CurrentBlock + 1); |
| if (ps_locktlv_info->LockTlvBuff[1] - |
| ps_tpz_info->lock_bytes_written) |
| { |
| #ifdef TOPAZ_RAW_SUPPORT |
| |
| *psNdefMap->SendRecvBuf = PH_FRINFC_TOPAZ_CMD_READ8; |
| |
| #else |
| |
| /* Topaz command = Jewel Nxp Read */ |
| #ifdef PH_HAL4_ENABLE |
| psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read; |
| #else |
| psNdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead; |
| #endif |
| |
| psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read8; |
| |
| #endif /* #ifdef TOPAZ_RAW_SUPPORT */ |
| /* Call read segment */ |
| result = phFriNfc_Tpz_H_NxpRead (psNdefMap); |
| e_readonly_seq = RD_LOCK_BYTES; |
| } |
| else |
| { |
| ps_tpz_info->CurrentBlock = (uint8_t) |
| DYN_STATIC_LOCK_BLOCK_NUM; |
| ps_tpz_info->ByteNumber = (uint8_t) |
| DYN_STATIC_LOCK0_BYTE_NUM; |
| #ifdef TOPAZ_RAW_SUPPORT |
| |
| *psNdefMap->SendRecvBuf = (uint8_t)PH_FRINFC_TOPAZ_CMD_READ8; |
| |
| #else |
| |
| /* Topaz command = Jewel Nxp Read */ |
| #ifdef PH_HAL4_ENABLE |
| psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read; |
| #else |
| psNdefMap->Cmd.JewelCmd = phHal_eJewelCmdListJewelRead; |
| #endif |
| |
| psNdefMap->Cmd.JewelCmd = phHal_eJewel_Read8; |
| |
| #endif /* #ifdef TOPAZ_RAW_SUPPORT */ |
| /* Call read segment */ |
| result = phFriNfc_Tpz_H_NxpRead (psNdefMap); |
| e_readonly_seq = RD_STATIC_LOCK_BYTE0; |
| |
| } |
| } |
| else |
| { |
| result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, |
| NFCSTATUS_INVALID_RECEIVE_LENGTH); |
| } |
| break; |
| } |
| |
| case RD_STATIC_LOCK_BYTE0: |
| { |
| if (TOPAZ_READ_8_RESPONSE == *psNdefMap->SendRecvLength) |
| { |
| uint8_t lock_byte_value = 0; |
| |
| (void)memcpy ((void *)static_lock_bytes, |
| (void *)(psNdefMap->SendRecvBuf + |
| ps_tpz_info->ByteNumber), |
| sizeof (static_lock_bytes)); |
| |
| |
| lock_byte_value = (uint8_t)(static_lock_bytes[0] | |
| DYN_STATIC_LOCK0_BYTE_VALUE); |
| |
| #ifdef TOPAZ_RAW_SUPPORT |
| *psNdefMap->SendRecvBuf = (uint8_t)PH_FRINFC_TOPAZ_CMD_WRITE_1E; |
| #else |
| psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E; |
| #endif /* #ifdef TOPAZ_RAW_SUPPORT */ |
| |
| result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, &lock_byte_value, |
| 1); |
| |
| if (NFCSTATUS_PENDING == result) |
| { |
| e_readonly_seq = (uint8_t)WR_STATIC_LOCK_BYTE0; |
| } |
| } |
| else |
| { |
| result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, |
| NFCSTATUS_INVALID_RECEIVE_LENGTH); |
| } |
| break; |
| } |
| |
| case WR_STATIC_LOCK_BYTE0: |
| { |
| if (TOPAZ_WRITE_1_RESPONSE == *psNdefMap->SendRecvLength) |
| { |
| uint8_t lock_byte_value = |
| (static_lock_bytes[1] | |
| DYN_STATIC_LOCK1_BYTE_VALUE); |
| |
| ps_tpz_info->CurrentBlock = (uint8_t) |
| DYN_STATIC_LOCK_BLOCK_NUM; |
| ps_tpz_info->ByteNumber = (uint8_t) |
| DYN_STATIC_LOCK1_BYTE_NUM; |
| #ifdef TOPAZ_RAW_SUPPORT |
| *psNdefMap->SendRecvBuf = (uint8_t)PH_FRINFC_TOPAZ_CMD_WRITE_1E; |
| #else |
| psNdefMap->Cmd.JewelCmd = phHal_eJewel_Write1E; |
| #endif /* #ifdef TOPAZ_RAW_SUPPORT */ |
| |
| result = phFriNfc_Tpz_H_NxpWrite (psNdefMap, &lock_byte_value, |
| 1); |
| |
| if (NFCSTATUS_PENDING == result) |
| { |
| e_readonly_seq = (uint8_t)WR_STATIC_LOCK_BYTE1; |
| } |
| } |
| else |
| { |
| result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, |
| NFCSTATUS_INVALID_RECEIVE_LENGTH); |
| } |
| break; |
| } |
| |
| case WR_STATIC_LOCK_BYTE1: |
| { |
| if (TOPAZ_WRITE_1_RESPONSE == *psNdefMap->SendRecvLength) |
| { |
| /* READ ONLY successful */ |
| } |
| else |
| { |
| result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, |
| NFCSTATUS_INVALID_RECEIVE_LENGTH); |
| } |
| break; |
| } |
| |
| default: |
| { |
| result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, |
| NFCSTATUS_INVALID_RECEIVE_LENGTH); |
| break; |
| } |
| } |
| |
| psNdefMap->TopazContainer.read_only_seq = (uint8_t)e_readonly_seq; |
| return result; |
| } |
| |
| #endif /* #ifdef FRINFC_READONLY_NDEF */ |
| |
| 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], |
| TOPAZ_UID_LENGTH_FOR_READ_WRITE); |
| 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, |
| TOPAZ_UID_LENGTH_FOR_READ_WRITE); |
| send_index = (uint8_t)(send_index + |
| TOPAZ_UID_LENGTH_FOR_READ_WRITE); |
| } |
| |
| 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, |
| TOPAZ_UID_LENGTH_FOR_READ_WRITE); |
| send_index = (uint8_t)(send_index + TOPAZ_UID_LENGTH_FOR_READ_WRITE); |
| |
| #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)(copy_index + ( |
| 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) |
| ) |
| { |
| if ((ps_locktlv_info->ByteAddr < TOPAZ_STATIC_LOCK_RES_START) || |
| (ps_locktlv_info->ByteAddr >= (TOPAZ_STATIC_LOCK_RES_END + 8))) |
| { |
| 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) |
| ) |
| { |
| if ((ps_memtlv_info->ByteAddr < TOPAZ_STATIC_LOCK_RES_START) || |
| (ps_memtlv_info->ByteAddr >= (TOPAZ_STATIC_LOCK_RES_END + 8))) |
| { |
| 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 != copy_till_address) |
| { |
| skip_size = 0; |
| } |
| |
| 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) |
| { |
| #ifdef FRINFC_READONLY_NDEF |
| (void)memcpy ((void *)psNdefMap->LockTlv.LockTlvBuff, |
| (void *)lock_mem_buf, sizeof (lock_mem_buf)); |
| #endif /* #ifdef FRINFC_READONLY_NDEF */ |
| /* 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; |
| result = NFCSTATUS_SUCCESS; |
| } |
| } |
| } |
| |
| 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) >= (uint16_t)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 |
| * (1 << 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 |
| * (1 << 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 ))*/ |
| |
| |
| |