diff options
author | Martijn Coenen <martijn.coenen@nxp.com> | 2011-01-13 23:24:24 +0100 |
---|---|---|
committer | Jeff Hamilton <jham@android.com> | 2011-02-25 06:44:34 +0900 |
commit | a6e012a748e70ab203655d4e1c0d0a77b6515fad (patch) | |
tree | a3aeefc1f4816c58a4e943d85fca89678432f159 /src/phFriNfc_ISO15693Map.c | |
parent | 29e144ebf81b0f09b3fe4c26b67485ce836909c6 (diff) | |
download | external_libnfc-nxp-a6e012a748e70ab203655d4e1c0d0a77b6515fad.zip external_libnfc-nxp-a6e012a748e70ab203655d4e1c0d0a77b6515fad.tar.gz external_libnfc-nxp-a6e012a748e70ab203655d4e1c0d0a77b6515fad.tar.bz2 |
Added support for NDEF on ICODE.
This patch allows reading and writing of NDEF messages on ICODE tags.
Change-Id: I43b4845c898c2bf268f609a5a81e991460059ff6
Diffstat (limited to 'src/phFriNfc_ISO15693Map.c')
-rw-r--r-- | src/phFriNfc_ISO15693Map.c | 1668 |
1 files changed, 1668 insertions, 0 deletions
diff --git a/src/phFriNfc_ISO15693Map.c b/src/phFriNfc_ISO15693Map.c new file mode 100644 index 0000000..8b6d1f1 --- /dev/null +++ b/src/phFriNfc_ISO15693Map.c @@ -0,0 +1,1668 @@ +/* +/* + * 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_ISO15693Map.c +* \brief This component encapsulates read/write/check ndef/process functionalities, +* for the ISO-15693 Card. +* +* Project: NFC-FRI +* +* $Date: $ +* $Author: ing02260 $ +* $Revision: $ +* $Aliases: $ +* +*/ + +#ifndef PH_FRINFC_MAP_ISO15693_DISABLED + +#include <phNfcTypes.h> +#include <phNfcConfig.h> +#include <phNfcInterface.h> +#include <phNfcHalTypes.h> +#include <phFriNfc.h> +#include <phFriNfc_NdefMap.h> +#include <phFriNfc_OvrHal.h> +#include <phFriNfc_MapTools.h> +#include <phFriNfc_ISO15693Map.h> + +/************************** START DATA STRUCTURE *********************/ + +typedef enum phFriNfc_eChkNdefSeq +{ + ISO15693_NDEF_TLV_T, + ISO15693_NDEF_TLV_L, + ISO15693_NDEF_TLV_V, + ISO15693_PROP_TLV_L, + ISO15693_PROP_TLV_V + +}phFriNfc_eChkNdefSeq_t; + +typedef enum phFriNfc_eWrNdefSeq +{ + ISO15693_RD_BEFORE_WR_NDEF_L_0, + ISO15693_WRITE_DATA, + ISO15693_RD_BEFORE_WR_NDEF_L, + ISO15693_WRITE_NDEF_TLV_L + +}phFriNfc_eWrNdefSeq_t; + +#ifdef FRINFC_READONLY_NDEF + +typedef enum phFriNfc_eRONdefSeq +{ + ISO15693_RD_BEFORE_WR_CC, + ISO15693_WRITE_CC, + ISO15693_LOCK_BLOCK + +}phFriNfc_eRONdefSeq_t; + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + +/************************** END DATA STRUCTURE *********************/ + +/************************** START MACROS definition *********************/ + + + + +/* UID bytes to differentiate ICODE cards */ +#define ISO15693_UID_BYTE_4 0x04U +#define ISO15693_UID_BYTE_5 0x05U + +/* UID value for + SL2 ICS20 + SL2S2002 + */ +#define ISO15693_UIDBYTE_5_VALUE_SLI_X 0x01U +/* Card size SL2 ICS20 / SL2S2002 */ +#define ISO15693_SL2_S2002_ICS20 112U + +/* UID value for + SL2 ICS53, + SL2 ICS54 + SL2S5302 +*/ +#define ISO15693_UIDBYTE_5_VALUE_SLI_X_S 0x02U +#define ISO15693_UIDBYTE_4_VALUE_SLI_X_S 0x00U +#define ISO15693_UIDBYTE_4_VALUE_SLI_X_SHC 0x80U +#define ISO15693_UIDBYTE_4_VALUE_SLI_X_SY 0x40U +/* SL2 ICS53, SL2 ICS54 and SL2S5302 */ +#define ISO15693_SL2_S5302_ICS53_ICS54 160U + +/* UID value for + SL2 ICS50 + SL2 ICS51 + SL2S5002 +*/ +#define ISO15693_UIDBYTE_5_VALUE_SLI_X_L 0x03U +#define ISO15693_UIDBYTE_4_VALUE_SLI_X_L 0x00U +#define ISO15693_UIDBYTE_4_VALUE_SLI_X_LHC 0x80U +/* SL2 ICS50, SL2 ICS51 and SL2S5002 */ +#define ISO15693_SL2_S5002_ICS50_ICS51 32U + + +/* State Machine declaration +CHECK NDEF state */ +#define ISO15693_CHECK_NDEF 0x01U +/* READ NDEF state */ +#define ISO15693_READ_NDEF 0x02U +/* WRITE NDEF state */ +#define ISO15693_WRITE_NDEF 0x03U +#ifdef FRINFC_READONLY_NDEF + + /* READ ONLY NDEF state */ + #define ISO15693_READ_ONLY_NDEF 0x04U + + /* READ ONLY MASK byte for CC */ + #define ISO15693_CC_READ_ONLY_MASK 0x03U + + /* CC READ WRITE index */ + #define ISO15693_RW_BTYE_INDEX 0x01U + + /* LOCK BLOCK command */ + #define ISO15693_LOCK_BLOCK_CMD 0x22U + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + +/* CC Bytes +Magic number */ +#define ISO15693_CC_MAGIC_BYTE 0xE1U +/* Expected mapping version */ +#define ISO15693_MAPPING_VERSION 0x01U +/* Major version is in upper 2 bits */ +#define ISO15693_MAJOR_VERSION_MASK 0xC0U + +/* CC indicating tag is capable of multi-block read */ +#define ISO15693_CC_USE_MBR 0x01U +/* CC indicating tag is capable of inventory page read */ +#define ISO15693_CC_USE_IPR 0x02U +/* EXTRA byte in the response */ +#define ISO15693_EXTRA_RESP_BYTE 0x01U + +/* Maximum card size multiplication factor */ +#define ISO15693_MULT_FACTOR 0x08U +/* NIBBLE mask for READ WRITE access */ +#define ISO15693_LSB_NIBBLE_MASK 0x0FU +#define ISO15693_MSB_NIBBLE_MASK 0xF0U + +#define ISO15693_RD_WR_PERMISSION 0x00U +#define ISO15693_RD_ONLY_PERMISSION 0x03U + +/* READ command identifier */ +#define ISO15693_READ_COMMAND 0x20U + +/* READ multiple command identifier */ +#define ISO15693_READ_MULTIPLE_COMMAND 0x23U + +/* INVENTORY pageread command identifier */ +#define ICODE_INVENTORY_PAGEREAD_COMMAND 0xB0U +#define INVENTORY_PAGEREAD_FLAGS 0x24U +#define NXP_MANUFACTURING_CODE 0x04U + +/* WRITE command identifier */ +#define ISO15693_WRITE_COMMAND 0x21U +/* FLAG option */ +#define ISO15693_FLAGS 0x20U + +/* RESPONSE length expected for single block READ */ +#define ISO15693_SINGLE_BLK_RD_RESP_LEN 0x04U +/* NULL TLV identifier */ +#define ISO15693_NULL_TLV_ID 0x00U +/* NDEF TLV, TYPE identifier */ +#define ISO15693_NDEF_TLV_TYPE_ID 0x03U + +/* 8 BIT shift */ +#define ISO15693_BTYE_SHIFT 0x08U + +/* Proprietary TLV TYPE identifier */ +#define ISO15693_PROP_TLV_ID 0xFDU + +/* CC SIZE in BYTES */ +#define ISO15693_CC_SIZE 0x04U + +/* To get the remaining size in the card. +Inputs are +1. maximum data size +2. block number +3. index of the block number */ +#define ISO15693_GET_REMAINING_SIZE(max_data_size, blk, index) \ + (max_data_size - ((blk * ISO15693_BYTES_PER_BLOCK) + index)) + +#define ISO15693_GET_LEN_FIELD_BLOCK_NO(blk, byte_addr, ndef_size) \ + (((byte_addr + ((ndef_size >= ISO15693_THREE_BYTE_LENGTH_ID) ? 3 : 1)) >= \ + (ISO15693_BYTES_PER_BLOCK - 1)) ? (blk + 1) : blk) + +#define ISO15693_GET_LEN_FIELD_BYTE_NO(blk, byte_addr, ndef_size) \ + (((byte_addr + ((ndef_size >= ISO15693_THREE_BYTE_LENGTH_ID) ? 3 : 1)) % \ + ISO15693_BYTES_PER_BLOCK)) + + + +/************************** END MACROS definition *********************/ + +/************************** START static functions declaration *********************/ +static +NFCSTATUS +phFriNfc_ISO15693_H_ProcessReadOnly ( + phFriNfc_NdefMap_t *psNdefMap); + +static +NFCSTATUS +phFriNfc_ISO15693_H_ProcessWriteNdef ( + phFriNfc_NdefMap_t *psNdefMap); + +static +NFCSTATUS +phFriNfc_ISO15693_H_ProcessReadNdef ( + phFriNfc_NdefMap_t *psNdefMap); + +static +NFCSTATUS +phFriNfc_ISO15693_H_ProcessCheckNdef ( + phFriNfc_NdefMap_t *psNdefMap); + +static +void +phFriNfc_ISO15693_H_Complete ( + phFriNfc_NdefMap_t *psNdefMap, + NFCSTATUS Status); + +static +NFCSTATUS +phFriNfc_ISO15693_H_ReadWrite ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t command, + uint8_t *p_data, + uint8_t data_length); + +static +NFCSTATUS +phFriNfc_ReadRemainingInMultiple ( + phFriNfc_NdefMap_t *psNdefMap, + uint32_t startBlock); + +/************************** END static functions declaration *********************/ + +/************************** START static functions definition *********************/ + +static +NFCSTATUS +phFriNfc_ISO15693_H_ProcessWriteNdef ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_ISO15693Cont_t *ps_iso_15693_con = + &(psNdefMap->ISO15693Container); + phFriNfc_eWrNdefSeq_t e_wr_ndef_seq = (phFriNfc_eWrNdefSeq_t) + psNdefMap->ISO15693Container.ndef_seq; + uint8_t *p_recv_buf = NULL; + uint8_t recv_length = 0; + uint8_t write_flag = FALSE; + uint8_t a_write_buf[ISO15693_BYTES_PER_BLOCK] = {0}; + uint8_t remaining_size = 0; + + switch (e_wr_ndef_seq) + { + case ISO15693_RD_BEFORE_WR_NDEF_L_0: + { + p_recv_buf = (psNdefMap->SendRecvBuf + + ISO15693_EXTRA_RESP_BYTE); + recv_length = (uint8_t) + (*psNdefMap->SendRecvLength - ISO15693_EXTRA_RESP_BYTE); + + if (ISO15693_SINGLE_BLK_RD_RESP_LEN == recv_length) + { + uint8_t byte_index = 0; + + (void)memcpy ((void *)a_write_buf, (void *)p_recv_buf, + recv_length); + + byte_index = ISO15693_GET_LEN_FIELD_BYTE_NO( + ps_iso_15693_con->ndef_tlv_type_blk, + ps_iso_15693_con->ndef_tlv_type_byte, + psNdefMap->ApduBufferSize); + + /* Writing length field to 0 */ + *(a_write_buf + byte_index) = 0x00; + + if ((ISO15693_BYTES_PER_BLOCK - 1) != byte_index) + { + byte_index = (uint8_t)(byte_index + 1); + remaining_size = (ISO15693_BYTES_PER_BLOCK - byte_index); + + if ((psNdefMap->ApduBufferSize - psNdefMap->ApduBuffIndex) + < remaining_size) + { + remaining_size = (uint8_t)(psNdefMap->ApduBufferSize - + psNdefMap->ApduBuffIndex); + } + + /* Go to next byte to fill the write buffer */ + + (void)memcpy ((void *)(a_write_buf + byte_index), + (void *)(psNdefMap->ApduBuffer + + psNdefMap->ApduBuffIndex), remaining_size); + + psNdefMap->ApduBuffIndex = (uint8_t)(psNdefMap->ApduBuffIndex + + remaining_size); + } + + e_wr_ndef_seq = ISO15693_WRITE_DATA; + write_flag = TRUE; + } /* if (ISO15693_SINGLE_BLK_RD_RESP_LEN == recv_length) */ + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } /* case ISO15693_RD_BEFORE_WR_NDEF_L_0: */ + + case ISO15693_RD_BEFORE_WR_NDEF_L: + { + p_recv_buf = (psNdefMap->SendRecvBuf + ISO15693_EXTRA_RESP_BYTE); + recv_length = (uint8_t)(*psNdefMap->SendRecvLength - + ISO15693_EXTRA_RESP_BYTE); + + if (ISO15693_SINGLE_BLK_RD_RESP_LEN == recv_length) + { + uint8_t byte_index = 0; + + (void)memcpy ((void *)a_write_buf, (void *)p_recv_buf, + recv_length); + + byte_index = ISO15693_GET_LEN_FIELD_BYTE_NO( + ps_iso_15693_con->ndef_tlv_type_blk, + ps_iso_15693_con->ndef_tlv_type_byte, + psNdefMap->ApduBuffIndex); + + *(a_write_buf + byte_index) = (uint8_t)psNdefMap->ApduBuffIndex; + e_wr_ndef_seq = ISO15693_WRITE_NDEF_TLV_L; + write_flag = TRUE; + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_RECEIVE_LENGTH); + } + break; + } + + case ISO15693_WRITE_DATA: + { + if ((psNdefMap->ApduBufferSize == psNdefMap->ApduBuffIndex) + || (ps_iso_15693_con->current_block == + (ps_iso_15693_con->max_data_size / ISO15693_BYTES_PER_BLOCK))) + { + ps_iso_15693_con->current_block = + ISO15693_GET_LEN_FIELD_BLOCK_NO( + ps_iso_15693_con->ndef_tlv_type_blk, + ps_iso_15693_con->ndef_tlv_type_byte, + psNdefMap->ApduBuffIndex); + e_wr_ndef_seq = ISO15693_RD_BEFORE_WR_NDEF_L; + } + else + { + remaining_size = ISO15693_BYTES_PER_BLOCK; + + ps_iso_15693_con->current_block = (uint16_t) + (ps_iso_15693_con->current_block + 1); + + if ((psNdefMap->ApduBufferSize - psNdefMap->ApduBuffIndex) + < remaining_size) + { + remaining_size = (uint8_t)(psNdefMap->ApduBufferSize - + psNdefMap->ApduBuffIndex); + } + + (void)memcpy ((void *)a_write_buf, (void *) + (psNdefMap->ApduBuffer + + psNdefMap->ApduBuffIndex), remaining_size); + + psNdefMap->ApduBuffIndex = (uint8_t)(psNdefMap->ApduBuffIndex + + remaining_size); + write_flag = TRUE; + } + break; + } /* case ISO15693_WRITE_DATA: */ + + case ISO15693_WRITE_NDEF_TLV_L: + { + *psNdefMap->WrNdefPacketLength = psNdefMap->ApduBuffIndex; + ps_iso_15693_con->actual_ndef_size = psNdefMap->ApduBuffIndex; + break; + } + + default: + { + break; + } + } /* switch (e_wr_ndef_seq) */ + + if (*psNdefMap->WrNdefPacketLength != psNdefMap->ApduBuffIndex) + { + if (FALSE == write_flag) + { + result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, + ISO15693_READ_COMMAND, NULL, 0); + } + else + { + result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, + ISO15693_WRITE_COMMAND, + a_write_buf, sizeof (a_write_buf)); + } + } + + psNdefMap->ISO15693Container.ndef_seq = (uint8_t)e_wr_ndef_seq; + return result; +} + +static +NFCSTATUS +phFriNfc_ISO15693_H_ReadWrite ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t command, + uint8_t *p_data, + uint8_t data_length) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + uint8_t send_index = 0; + + /* set the data for additional data exchange*/ + psNdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = 0; + psNdefMap->psDepAdditionalInfo.DepFlags.NADPresent = 0; + psNdefMap->psDepAdditionalInfo.NAD = 0; + + psNdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_ISO15693_Process; + psNdefMap->MapCompletionInfo.Context = psNdefMap; + + *psNdefMap->SendRecvLength = psNdefMap->TempReceiveLength; + + psNdefMap->Cmd.Iso15693Cmd = phHal_eIso15693_Cmd; + + *(psNdefMap->SendRecvBuf + send_index) = (uint8_t)ISO15693_FLAGS; + send_index = (uint8_t)(send_index + 1); + + *(psNdefMap->SendRecvBuf + send_index) = (uint8_t)command; + send_index = (uint8_t)(send_index + 1); + + (void)memcpy ((void *)(psNdefMap->SendRecvBuf + send_index), + (void *)psNdefMap->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Uid, + psNdefMap->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.UidLength); + send_index = (uint8_t)(send_index + + psNdefMap->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.UidLength); + + *(psNdefMap->SendRecvBuf + send_index) = (uint8_t) + psNdefMap->ISO15693Container.current_block; + send_index = (uint8_t)(send_index + 1); + + if ((ISO15693_WRITE_COMMAND == command) || + (ISO15693_READ_MULTIPLE_COMMAND == command)) + { + (void)memcpy ((void *)(psNdefMap->SendRecvBuf + send_index), + (void *)p_data, data_length); + send_index = (uint8_t)(send_index + data_length); + } + + psNdefMap->SendLength = send_index; + 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_ISO15693_H_Inventory_Page_Read ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t command, + uint8_t page, + uint8_t numPages) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + uint8_t send_index = 0; + + /* set the data for additional data exchange*/ + psNdefMap->psDepAdditionalInfo.DepFlags.MetaChaining = 0; + psNdefMap->psDepAdditionalInfo.DepFlags.NADPresent = 0; + psNdefMap->psDepAdditionalInfo.NAD = 0; + + psNdefMap->MapCompletionInfo.CompletionRoutine = phFriNfc_ISO15693_Process; + psNdefMap->MapCompletionInfo.Context = psNdefMap; + + *psNdefMap->SendRecvLength = psNdefMap->TempReceiveLength; + + psNdefMap->Cmd.Iso15693Cmd = phHal_eIso15693_Cmd; + + *(psNdefMap->SendRecvBuf + send_index) = INVENTORY_PAGEREAD_FLAGS; + send_index = (uint8_t)(send_index + 1); + + *(psNdefMap->SendRecvBuf + send_index) = (uint8_t)command; + send_index = (uint8_t)(send_index + 1); + + *(psNdefMap->SendRecvBuf + send_index) = NXP_MANUFACTURING_CODE; + send_index = (uint8_t)(send_index + 1); + + *(psNdefMap->SendRecvBuf + send_index) = 0x40; + send_index = (uint8_t)(send_index + 1); + + (void)memcpy ((void *)(psNdefMap->SendRecvBuf + send_index), + (void *)psNdefMap->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.Uid, + psNdefMap->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.UidLength); + send_index = (uint8_t)(send_index + + psNdefMap->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info.UidLength); + + *(psNdefMap->SendRecvBuf + send_index) = (uint8_t) + page; + send_index = (uint8_t)(send_index + 1); + + *(psNdefMap->SendRecvBuf + send_index) = (uint8_t) + numPages; + send_index = (uint8_t)(send_index + 1); + + psNdefMap->SendLength = send_index; + + 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_ISO15693_Reformat_Pageread_Buffer ( + uint8_t *p_recv_buf, + uint8_t recv_length, + uint8_t *p_dst_buf, + uint8_t dst_length) +{ + // Inventory page reads return an extra security byte per page + // So we need to reformat the returned buffer in memory + uint32_t i = 0; + uint32_t reformatted_index = 0; + while (i < recv_length) { + // Going for another page of 16 bytes, check for space in dst buffer + if (reformatted_index + 16 > dst_length) { + break; + } + if (p_recv_buf[i] == 0x0F) { + // Security, insert 16 0 bytes + memset(&(p_dst_buf[reformatted_index]), 0, 16); + reformatted_index += 16; + i++; + } else { + // Skip security byte + i++; + if (i + 16 <= recv_length) { + memcpy(&(p_dst_buf[reformatted_index]), &(p_recv_buf[i]), 16); + reformatted_index += 16; + } else { + break; + } + i+=16; + } + } + return reformatted_index; +} + +static +NFCSTATUS +phFriNfc_ISO15693_H_ProcessReadNdef ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_ISO15693Cont_t *ps_iso_15693_con = + &(psNdefMap->ISO15693Container); + uint16_t remaining_data_size = 0; + uint8_t *p_recv_buf = + (psNdefMap->SendRecvBuf + ISO15693_EXTRA_RESP_BYTE); + uint8_t recv_length = (uint8_t) + (*psNdefMap->SendRecvLength - ISO15693_EXTRA_RESP_BYTE); + + uint8_t *reformatted_buf = (uint8_t*) phOsalNfc_GetMemory(ps_iso_15693_con->max_data_size); + + if (ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_IPR) + { + uint8_t reformatted_size = phFriNfc_ISO15693_Reformat_Pageread_Buffer(p_recv_buf, recv_length, + reformatted_buf, ps_iso_15693_con->max_data_size); + p_recv_buf = reformatted_buf + (ps_iso_15693_con->current_block * ISO15693_BYTES_PER_BLOCK); + recv_length = reformatted_size - (ps_iso_15693_con->current_block * ISO15693_BYTES_PER_BLOCK); + } + if (ps_iso_15693_con->store_length) + { + /* Continue read option selected + So stored data already existing, + copy the information to the user buffer + */ + if (ps_iso_15693_con->store_length + <= (psNdefMap->ApduBufferSize - psNdefMap->ApduBuffIndex)) + { + /* Stored data length is less than or equal + to the user expected size */ + (void)memcpy ((void *)(psNdefMap->ApduBuffer + + psNdefMap->ApduBuffIndex), + (void *)p_recv_buf, + ps_iso_15693_con->store_length); + + psNdefMap->ApduBuffIndex = (uint16_t)(psNdefMap->ApduBuffIndex + + ps_iso_15693_con->store_length); + + remaining_data_size = ps_iso_15693_con->store_length; + + ps_iso_15693_con->store_length = 0; + } + else + { + /* stored length is more than the user expected size */ + remaining_data_size = (uint16_t)(ps_iso_15693_con->store_length - + (psNdefMap->ApduBufferSize - psNdefMap->ApduBuffIndex)); + + (void)memcpy ((void *)(psNdefMap->ApduBuffer + + psNdefMap->ApduBuffIndex), + (void *)ps_iso_15693_con->store_read_data, + remaining_data_size); + + (void)memcpy ((void *)ps_iso_15693_con->store_read_data, + (void *)(ps_iso_15693_con->store_read_data + + remaining_data_size), + (ps_iso_15693_con->store_length - remaining_data_size)); + + psNdefMap->ApduBuffIndex = (uint16_t)(psNdefMap->ApduBuffIndex + + remaining_data_size); + } + } /* if (ps_iso_15693_con->store_length) */ + else + { + uint8_t byte_index = 0; + + remaining_data_size = ps_iso_15693_con->remaining_size_to_read; + if (ISO15693_GET_VALUE_FIELD_BLOCK_NO(ps_iso_15693_con->ndef_tlv_type_blk, + ps_iso_15693_con->ndef_tlv_type_byte, + ps_iso_15693_con->actual_ndef_size) + == ps_iso_15693_con->current_block) + { + /* Read from the beginning option selected, + BYTE number may start from the middle */ + byte_index = (uint8_t)ISO15693_GET_VALUE_FIELD_BYTE_NO( + ps_iso_15693_con->ndef_tlv_type_blk, + ps_iso_15693_con->ndef_tlv_type_byte, + ps_iso_15693_con->actual_ndef_size); + } + + if ((psNdefMap->ApduBufferSize - psNdefMap->ApduBuffIndex) + < remaining_data_size) + { + if ((psNdefMap->ApduBufferSize - psNdefMap->ApduBuffIndex) + < (uint16_t)(recv_length - byte_index)) + { + remaining_data_size = (uint8_t)(psNdefMap->ApduBufferSize - + psNdefMap->ApduBuffIndex); + /* Store the data for the continue read option */ + (void)memcpy ((void *)ps_iso_15693_con->store_read_data, + (void *)(p_recv_buf + byte_index + + remaining_data_size), + ((recv_length - byte_index) - + remaining_data_size)); + + ps_iso_15693_con->store_length = (uint8_t) + ((recv_length - byte_index) - remaining_data_size); + } + else + { + remaining_data_size = (uint8_t) + (recv_length - byte_index); + } + } + else + { + if (remaining_data_size > (recv_length - byte_index)) + { + remaining_data_size = (uint8_t) + (recv_length - byte_index); + } + } + (void)memcpy ((void *)(psNdefMap->ApduBuffer + + psNdefMap->ApduBuffIndex), + (void *)(p_recv_buf + byte_index), + remaining_data_size); + + psNdefMap->ApduBuffIndex = (uint16_t)(psNdefMap->ApduBuffIndex + + remaining_data_size); + + } /* if (ps_iso_15693_con->store_length) */ + + /* Remaining size is decremented */ + ps_iso_15693_con->remaining_size_to_read = (uint8_t) + (ps_iso_15693_con->remaining_size_to_read - + remaining_data_size); + + if ((psNdefMap->ApduBuffIndex != psNdefMap->ApduBufferSize) + && (0 != ps_iso_15693_con->remaining_size_to_read)) + { + ps_iso_15693_con->current_block = (uint16_t) + (ps_iso_15693_con->current_block + 1); + /* READ again */ + if ((ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_MBR) || + (ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_IPR)) { + result = phFriNfc_ReadRemainingInMultiple(psNdefMap, ps_iso_15693_con->current_block); + } + else { + result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, ISO15693_READ_COMMAND, + NULL, 0); + } + } + else + { + /* Read completed */ + *psNdefMap->NumOfBytesRead = psNdefMap->ApduBuffIndex; + } + if (reformatted_buf != NULL) { + phOsalNfc_FreeMemory(reformatted_buf); + } + return result; +} + +static +NFCSTATUS +phFriNfc_ISO15693_H_CheckCCBytes ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_ISO15693Cont_t *ps_iso_15693_con = + &(psNdefMap->ISO15693Container); + uint8_t recv_index = 0; + uint8_t *p_recv_buf = (psNdefMap->SendRecvBuf + 1); + + if (ISO15693_CC_MAGIC_BYTE == *p_recv_buf) + { + recv_index = (uint8_t)(recv_index + 1); + uint8_t tag_major_version = (*(p_recv_buf + recv_index) & ISO15693_MAJOR_VERSION_MASK) >> 6; + if (ISO15693_MAPPING_VERSION >= tag_major_version) + { + switch (*(p_recv_buf + recv_index) & ISO15693_LSB_NIBBLE_MASK) + { + case ISO15693_RD_WR_PERMISSION: + { + psNdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_WRITE; + break; + } + + case ISO15693_RD_ONLY_PERMISSION: + { + psNdefMap->CardState = PH_NDEFMAP_CARD_STATE_READ_ONLY; + break; + } + + default: + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + break; + } + } + recv_index = (uint8_t)(recv_index + 1); + + if (!result) + { + ps_iso_15693_con->max_data_size = (uint16_t) + (*(p_recv_buf + recv_index) * + ISO15693_MULT_FACTOR); + recv_index = (uint8_t)(recv_index + 1); + ps_iso_15693_con->read_capabilities = (*(p_recv_buf + recv_index)); + + + } + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + } + else + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + return result; +} + +static +NFCSTATUS +phFriNfc_ISO15693_H_ProcessCheckNdef ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_ISO15693Cont_t *ps_iso_15693_con = + &(psNdefMap->ISO15693Container); + phFriNfc_eChkNdefSeq_t e_chk_ndef_seq = (phFriNfc_eChkNdefSeq_t) + psNdefMap->ISO15693Container.ndef_seq; + + uint8_t *p_recv_buf = + (psNdefMap->SendRecvBuf + ISO15693_EXTRA_RESP_BYTE); + uint8_t recv_length = (uint8_t) + (*psNdefMap->SendRecvLength - ISO15693_EXTRA_RESP_BYTE); + uint8_t parse_index = 0; + static uint16_t prop_ndef_index = 0; + uint8_t *reformatted_buf = (uint8_t*) phOsalNfc_GetMemory(ps_iso_15693_con->max_data_size); + + if (0 == ps_iso_15693_con->current_block) + { + /* Check CC byte */ + result = phFriNfc_ISO15693_H_CheckCCBytes (psNdefMap); + parse_index = (uint8_t)(parse_index + recv_length); + } + else if (1 == ps_iso_15693_con->current_block && + (ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_IPR)) + { + + uint8_t reformatted_size = phFriNfc_ISO15693_Reformat_Pageread_Buffer(p_recv_buf, recv_length, + reformatted_buf, ps_iso_15693_con->max_data_size); + // Skip initial CC bytes + p_recv_buf = reformatted_buf + (ps_iso_15693_con->current_block * ISO15693_BYTES_PER_BLOCK); + recv_length = reformatted_size - (ps_iso_15693_con->current_block * ISO15693_BYTES_PER_BLOCK); + } + else + { + /* Propreitary TLVs VALUE can end in between a block, + so when that block is read, dont read the proprietary data */ + if (ISO15693_PROP_TLV_V == e_chk_ndef_seq) + { + parse_index = ps_iso_15693_con->ndef_tlv_type_byte; + e_chk_ndef_seq = ISO15693_NDEF_TLV_T; + } + } + + while ((parse_index < recv_length) + && (NFCSTATUS_SUCCESS == result) + && (ISO15693_NDEF_TLV_V != e_chk_ndef_seq)) + { + switch (e_chk_ndef_seq) + { + case ISO15693_NDEF_TLV_T: + { + prop_ndef_index = 0; + switch (*(p_recv_buf + parse_index)) + { + case ISO15693_NDEF_TLV_TYPE_ID: + { + ps_iso_15693_con->ndef_tlv_type_byte = parse_index; + ps_iso_15693_con->ndef_tlv_type_blk = + ps_iso_15693_con->current_block; + e_chk_ndef_seq = ISO15693_NDEF_TLV_L; + /* Update the block number */ + + break; + } + + case ISO15693_NULL_TLV_ID: + { + /* Dont do any thing, go to next byte */ + break; + } + + case ISO15693_PROP_TLV_ID: + { + /* Move the sequence to find the length + of the proprietary TLV */ + e_chk_ndef_seq = ISO15693_PROP_TLV_L; + break; + } + + default: + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + break; + } + } /* switch (*(p_recv_buf + parse_index)) */ + break; + } + + case ISO15693_PROP_TLV_L: + { + switch (prop_ndef_index) + { + case 0: + { + if (0 == *(p_recv_buf + parse_index)) + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + e_chk_ndef_seq = ISO15693_NDEF_TLV_T; + } + else + { + prop_ndef_index = (uint8_t)(prop_ndef_index + 1); + + if (ISO15693_THREE_BYTE_LENGTH_ID == + *(p_recv_buf + parse_index)) + { + prop_ndef_index = (uint8_t)(prop_ndef_index + 1); + } + else + { + ps_iso_15693_con->actual_ndef_size = + *(p_recv_buf + parse_index); + e_chk_ndef_seq = ISO15693_PROP_TLV_V; + prop_ndef_index = 0; + } + } + break; + } + + case 1: + { + ps_iso_15693_con->actual_ndef_size = (uint16_t) + (*(p_recv_buf + parse_index) << + ISO15693_BTYE_SHIFT); + prop_ndef_index = (uint8_t)(prop_ndef_index + 1); + break; + } + + case 2: + { + ps_iso_15693_con->actual_ndef_size = (uint16_t) + (ps_iso_15693_con->actual_ndef_size | + *(p_recv_buf + parse_index)); + + e_chk_ndef_seq = ISO15693_PROP_TLV_V; + prop_ndef_index = 0; + break; + } + + default: + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + break; + } + } /* switch (prop_ndef_index) */ + + if ((ISO15693_PROP_TLV_V == e_chk_ndef_seq) + && (ISO15693_GET_REMAINING_SIZE(ps_iso_15693_con->max_data_size, + ps_iso_15693_con->current_block, parse_index) + <= ps_iso_15693_con->actual_ndef_size)) + { + /* Check for the length field value has not exceeded the card size, + if size is exceeded or then return error */ + e_chk_ndef_seq = ISO15693_NDEF_TLV_T; + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + else + { + uint16_t prop_byte_addr = 0; + /* skip the proprietary TLVs value field */ + prop_byte_addr = (uint16_t) + ((ps_iso_15693_con->current_block * ISO15693_BYTES_PER_BLOCK) + + parse_index + ps_iso_15693_con->actual_ndef_size); + + ps_iso_15693_con->ndef_tlv_type_byte = (uint8_t)(prop_byte_addr % + ISO15693_BYTES_PER_BLOCK); + ps_iso_15693_con->ndef_tlv_type_blk = (uint16_t)(prop_byte_addr / + ISO15693_BYTES_PER_BLOCK); + if (parse_index + ps_iso_15693_con->actual_ndef_size >= + recv_length) + { + parse_index = (uint8_t)recv_length; + } + else + { + parse_index = (uint8_t)(parse_index + + ps_iso_15693_con->actual_ndef_size); + } + + } + break; + } /* case ISO15693_PROP_TLV_L: */ + + case ISO15693_PROP_TLV_V: + { + uint8_t remaining_length = (uint8_t)(recv_length - + parse_index); + + if ((ps_iso_15693_con->actual_ndef_size - prop_ndef_index) + > remaining_length) + { + parse_index = (uint8_t)(parse_index + remaining_length); + prop_ndef_index = (uint8_t)(prop_ndef_index + remaining_length); + } + else if ((ps_iso_15693_con->actual_ndef_size - prop_ndef_index) + == remaining_length) + { + parse_index = (uint8_t)(parse_index + remaining_length); + e_chk_ndef_seq = ISO15693_NDEF_TLV_T; + prop_ndef_index = 0; + } + else + { + parse_index = (uint8_t)(parse_index + + (ps_iso_15693_con->actual_ndef_size - + prop_ndef_index)); + e_chk_ndef_seq = ISO15693_NDEF_TLV_T; + prop_ndef_index = 0; + } + break; + } /* case ISO15693_PROP_TLV_V: */ + + case ISO15693_NDEF_TLV_L: + { + switch (prop_ndef_index) + { + case 0: + { + if (0 == *(p_recv_buf + parse_index)) + { + e_chk_ndef_seq = ISO15693_NDEF_TLV_V; + ps_iso_15693_con->actual_ndef_size = 0; + } + else + { + prop_ndef_index = (uint8_t)(prop_ndef_index + 1); + + if (ISO15693_THREE_BYTE_LENGTH_ID == + *(p_recv_buf + parse_index)) + { + prop_ndef_index = (uint8_t)(prop_ndef_index + 1); + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + prop_ndef_index = 0; + } + else + { + ps_iso_15693_con->actual_ndef_size = + *(p_recv_buf + parse_index); + e_chk_ndef_seq = ISO15693_NDEF_TLV_V; + prop_ndef_index = 0; + } + } + break; + } + + case 1: + { + ps_iso_15693_con->actual_ndef_size = (uint16_t) + (*(p_recv_buf + parse_index) << + ISO15693_BTYE_SHIFT); + prop_ndef_index = (uint8_t)(prop_ndef_index + 1); + break; + } + + case 2: + { + ps_iso_15693_con->actual_ndef_size = (uint16_t) + (ps_iso_15693_con->actual_ndef_size | + *(p_recv_buf + parse_index)); + + e_chk_ndef_seq = ISO15693_NDEF_TLV_V; + prop_ndef_index = 0; + break; + } + + default: + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + break; + } + } /* switch (prop_ndef_index) */ + + if ((ISO15693_NDEF_TLV_V == e_chk_ndef_seq) + && (ISO15693_GET_REMAINING_SIZE(ps_iso_15693_con->max_data_size, + /* parse_index + 1 is done because the data starts from the next index. + MOD operation is used to know that parse_index > + ISO15693_BYTES_PER_BLOCK, then block shall be incremented + */ + (((parse_index + 1) % ISO15693_BYTES_PER_BLOCK) ? + ps_iso_15693_con->current_block : + ps_iso_15693_con->current_block + 1), ((parse_index + 1) % + ISO15693_BYTES_PER_BLOCK)) + < ps_iso_15693_con->actual_ndef_size)) + { + /* Check for the length field value has not exceeded the card size */ + e_chk_ndef_seq = ISO15693_NDEF_TLV_T; + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + else + { + psNdefMap->CardState = (uint8_t) + ((PH_NDEFMAP_CARD_STATE_READ_ONLY + == psNdefMap->CardState) ? + PH_NDEFMAP_CARD_STATE_READ_ONLY : + ((ps_iso_15693_con->actual_ndef_size) ? + PH_NDEFMAP_CARD_STATE_READ_WRITE : + PH_NDEFMAP_CARD_STATE_INITIALIZED)); + } + break; + } /* case ISO15693_NDEF_TLV_L: */ + + case ISO15693_NDEF_TLV_V: + { + break; + } + + default: + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + break; + } + } /* switch (e_chk_ndef_seq) */ + parse_index = (uint8_t)(parse_index + 1); + } /* while ((parse_index < recv_length) + && (NFCSTATUS_SUCCESS == result) + && (ISO15693_NDEF_TLV_V != e_chk_ndef_seq)) */ + + if (result) + { + /* Error returned while parsing, so STOP read */ + e_chk_ndef_seq = ISO15693_NDEF_TLV_T; + prop_ndef_index = 0; + } + else if (ISO15693_NDEF_TLV_V != e_chk_ndef_seq) + { + /* READ again */ + if (ISO15693_PROP_TLV_V != e_chk_ndef_seq) + { + ps_iso_15693_con->current_block = (uint16_t) + (ps_iso_15693_con->current_block + 1); + } + else + { + ps_iso_15693_con->current_block = ps_iso_15693_con->ndef_tlv_type_blk; + } + + uint32_t remaining_size = ISO15693_GET_REMAINING_SIZE(ps_iso_15693_con->max_data_size, + ps_iso_15693_con->current_block, 0); + if (remaining_size > 0) + { + if ((ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_MBR) || + (ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_IPR)) { + result = phFriNfc_ReadRemainingInMultiple(psNdefMap, ps_iso_15693_con->current_block); + } else { + result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, ISO15693_READ_COMMAND, + NULL, 0); + } + } + else + { + e_chk_ndef_seq = ISO15693_NDEF_TLV_T; + prop_ndef_index = 0; + /* Error, no size to parse */ + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_NO_NDEF_SUPPORT); + } + + } + else + { + /* Successful read with proper NDEF information updated */ + prop_ndef_index = 0; + e_chk_ndef_seq = ISO15693_NDEF_TLV_T; + psNdefMap->CardType = (uint8_t)PH_FRINFC_NDEFMAP_ISO15693_CARD; + } + + psNdefMap->ISO15693Container.ndef_seq = (uint8_t)e_chk_ndef_seq; + + if (reformatted_buf != NULL) { + phOsalNfc_FreeMemory(reformatted_buf); + } + return result; +} + +static +void +phFriNfc_ISO15693_H_Complete ( + phFriNfc_NdefMap_t *psNdefMap, + NFCSTATUS Status) +{ + /* set the state back to the RESET_INIT state*/ + psNdefMap->State = PH_FRINFC_NDEFMAP_STATE_RESET_INIT; + + /* set the completion routine*/ + psNdefMap->CompletionRoutine[psNdefMap->ISO15693Container.cr_index]. + CompletionRoutine (psNdefMap->CompletionRoutine->Context, Status); +} + +#ifdef FRINFC_READONLY_NDEF + +static +NFCSTATUS +phFriNfc_ISO15693_H_ProcessReadOnly ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_ISO15693Cont_t *ps_iso_15693_con = + &(psNdefMap->ISO15693Container); + phFriNfc_eRONdefSeq_t e_ro_ndef_seq = (phFriNfc_eRONdefSeq_t) + ps_iso_15693_con->ndef_seq; + uint8_t *p_recv_buf = (psNdefMap->SendRecvBuf + + ISO15693_EXTRA_RESP_BYTE); + uint8_t recv_length = (uint8_t)(*psNdefMap->SendRecvLength - + ISO15693_EXTRA_RESP_BYTE); + uint8_t a_write_buf[ISO15693_BYTES_PER_BLOCK] = {0}; + + switch (e_ro_ndef_seq) + { + case ISO15693_RD_BEFORE_WR_CC: + { + if (ISO15693_SINGLE_BLK_RD_RESP_LEN == recv_length) + { + (void)memcpy ((void *)a_write_buf, (void *)p_recv_buf, + sizeof (a_write_buf)); + + *(a_write_buf + ISO15693_RW_BTYE_INDEX) = (uint8_t) + (*(a_write_buf + ISO15693_RW_BTYE_INDEX) | + ISO15693_CC_READ_ONLY_MASK); + + result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, + ISO15693_WRITE_DATA, a_write_buf, + sizeof (a_write_buf)); + + e_ro_ndef_seq = ISO15693_WRITE_CC; + } + break; + } + + case ISO15693_WRITE_CC: + { + e_ro_ndef_seq = ISO15693_LOCK_BLOCK; + result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, + ISO15693_LOCK_BLOCK_CMD, NULL, 0); + break; + } + + case ISO15693_LOCK_BLOCK: + { + if (ps_iso_15693_con->current_block == + (ps_iso_15693_con->max_data_size / ISO15693_BYTES_PER_BLOCK)) + { + /* READ ONLY successful */ + } + else + { + ps_iso_15693_con->current_block = (uint16_t) + (ps_iso_15693_con->current_block + 1); + result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, + ISO15693_LOCK_BLOCK_CMD, NULL, 0); + } + break; + } + + default: + { + break; + } + } + + ps_iso_15693_con->ndef_seq = (uint8_t)e_ro_ndef_seq; + return result; +} + +#endif /* #ifdef FRINFC_READONLY_NDEF */ +/************************** END static functions definition *********************/ + +/************************** START external functions *********************/ + +NFCSTATUS +phFriNfc_ISO15693_ChkNdef ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phHal_sIso15693Info_t *ps_iso_15693_info = + &(psNdefMap->psRemoteDevInfo->RemoteDevInfo.Iso15693_Info); + + /* Update the previous operation with current operation. + This becomes the previous operation after this execution */ + psNdefMap->PrevOperation = PH_FRINFC_NDEFMAP_CHECK_OPE; + /* Update the CR index to know from which operation completion + routine has to be called */ + psNdefMap->ISO15693Container.cr_index = PH_FRINFC_NDEFMAP_CR_CHK_NDEF; + /* State update */ + psNdefMap->State = ISO15693_CHECK_NDEF; + /* Reset the NDEF sequence */ + psNdefMap->ISO15693Container.ndef_seq = 0; + psNdefMap->ISO15693Container.current_block = 0; + psNdefMap->ISO15693Container.actual_ndef_size = 0; + psNdefMap->ISO15693Container.ndef_tlv_type_blk = 0; + psNdefMap->ISO15693Container.ndef_tlv_type_byte = 0; + psNdefMap->ISO15693Container.store_length = 0; + psNdefMap->ISO15693Container.remaining_size_to_read = 0; + psNdefMap->ISO15693Container.read_capabilities = 0; + + switch (ps_iso_15693_info->Uid[ISO15693_UID_BYTE_5]) + { + case ISO15693_UIDBYTE_5_VALUE_SLI_X: + { + psNdefMap->ISO15693Container.max_data_size = + ISO15693_SL2_S2002_ICS20; + break; + } + + case ISO15693_UIDBYTE_5_VALUE_SLI_X_S: + { + switch (ps_iso_15693_info->Uid[ISO15693_UID_BYTE_4]) + { + case ISO15693_UIDBYTE_4_VALUE_SLI_X_S: + case ISO15693_UIDBYTE_4_VALUE_SLI_X_SHC: + case ISO15693_UIDBYTE_4_VALUE_SLI_X_SY: + { + psNdefMap->ISO15693Container.max_data_size = + ISO15693_SL2_S5302_ICS53_ICS54; + break; + } + + default: + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + break; + } + } + break; + } + + case ISO15693_UIDBYTE_5_VALUE_SLI_X_L: + { + switch (ps_iso_15693_info->Uid[ISO15693_UID_BYTE_4]) + { + case ISO15693_UIDBYTE_4_VALUE_SLI_X_L: + case ISO15693_UIDBYTE_4_VALUE_SLI_X_LHC: + { + psNdefMap->ISO15693Container.max_data_size = + ISO15693_SL2_S5002_ICS50_ICS51; + break; + } + + default: + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + break; + } + } + break; + } + + default: + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_INVALID_DEVICE_REQUEST); + break; + } + } + + if (!result) + { + result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, ISO15693_READ_COMMAND, + NULL, 0); + } + + + return result; +} + +NFCSTATUS +phFriNfc_ISO15693_RdNdef ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t *pPacketData, + uint32_t *pPacketDataLength, + uint8_t Offset) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_ISO15693Cont_t *ps_iso_15693_con = + &(psNdefMap->ISO15693Container); + + /* Update the previous operation with current operation. + This becomes the previous operation after this execution */ + psNdefMap->PrevOperation = PH_FRINFC_NDEFMAP_READ_OPE; + /* Update the CR index to know from which operation completion + routine has to be called */ + psNdefMap->ISO15693Container.cr_index = PH_FRINFC_NDEFMAP_CR_RD_NDEF; + /* State update */ + psNdefMap->State = ISO15693_READ_NDEF; + /* Copy user buffer to the context */ + psNdefMap->ApduBuffer = pPacketData; + /* Copy user length to the context */ + psNdefMap->ApduBufferSize = *pPacketDataLength; + /* Update the user memory size to a context variable */ + psNdefMap->NumOfBytesRead = pPacketDataLength; + /* Number of bytes read from the card is zero. + This variable returns the number of bytes read + from the card. */ + *psNdefMap->NumOfBytesRead = 0; + /* Index to know the length read */ + psNdefMap->ApduBuffIndex = 0; + /* Store the offset in the context */ + psNdefMap->Offset = Offset; + + if ((!ps_iso_15693_con->remaining_size_to_read) + && (!psNdefMap->Offset)) + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_EOF_NDEF_CONTAINER_REACHED); + } + else if (0 == ps_iso_15693_con->actual_ndef_size) + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_READ_FAILED); + } + else if (PH_NDEFMAP_CARD_STATE_INITIALIZED == psNdefMap->CardState) + { + result = PHNFCSTVAL(CID_FRI_NFC_NDEF_MAP, + NFCSTATUS_READ_FAILED); + } + else if (psNdefMap->Offset) + { + ps_iso_15693_con->remaining_size_to_read = + ps_iso_15693_con->actual_ndef_size; + ps_iso_15693_con->current_block = + ISO15693_GET_VALUE_FIELD_BLOCK_NO( + ps_iso_15693_con->ndef_tlv_type_blk, + ps_iso_15693_con->ndef_tlv_type_byte, + ps_iso_15693_con->actual_ndef_size); + + // Check capabilities + if ((ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_MBR) || + (ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_IPR)) { + result = phFriNfc_ReadRemainingInMultiple(psNdefMap, ps_iso_15693_con->current_block); + } else { + result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, ISO15693_READ_COMMAND, + NULL, 0); + } + } + else + { + if (ps_iso_15693_con->store_length > 0) + { + result = phFriNfc_ISO15693_H_ProcessReadNdef (psNdefMap); + } + else + { + ps_iso_15693_con->current_block = (uint16_t) + (ps_iso_15693_con->current_block + 1); + result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, ISO15693_READ_COMMAND, + NULL, 0); + } + } + + return result; +} + +static +NFCSTATUS +phFriNfc_ReadRemainingInMultiple ( + phFriNfc_NdefMap_t *psNdefMap, + uint32_t startBlock) +{ + NFCSTATUS result = NFCSTATUS_FAILED; + phFriNfc_ISO15693Cont_t *ps_iso_15693_con = &(psNdefMap->ISO15693Container); + + uint32_t remaining_size = ISO15693_GET_REMAINING_SIZE(ps_iso_15693_con->max_data_size, + startBlock, 0); + // Check capabilities + if (ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_MBR) { + // Multi-page read command + uint8_t mbread[1]; + mbread[0] = (remaining_size / ISO15693_BYTES_PER_BLOCK) - 1; + result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, ISO15693_READ_MULTIPLE_COMMAND, + mbread, 1); + } else if (ps_iso_15693_con->read_capabilities & ISO15693_CC_USE_IPR) { + uint32_t page = 0; + uint32_t pagesToRead = (remaining_size / ISO15693_BYTES_PER_BLOCK / 4) - 1; + if ((remaining_size % (ISO15693_BYTES_PER_BLOCK * ISO15693_BLOCKS_PER_PAGE)) != 0) { + pagesToRead++; + } + result = phFriNfc_ISO15693_H_Inventory_Page_Read (psNdefMap, ICODE_INVENTORY_PAGEREAD_COMMAND, + page, pagesToRead); + // Inventory + } else { + result = NFCSTATUS_FAILED; + } + return result; +} + +NFCSTATUS +phFriNfc_ISO15693_WrNdef ( + phFriNfc_NdefMap_t *psNdefMap, + uint8_t *pPacketData, + uint32_t *pPacketDataLength, + uint8_t Offset) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_ISO15693Cont_t *ps_iso_15693_con = + &(psNdefMap->ISO15693Container); + uint8_t a_write_buf[ISO15693_BYTES_PER_BLOCK] = {0}; + + /* Update the previous operation with current operation. + This becomes the previous operation after this execution */ + psNdefMap->PrevOperation = PH_FRINFC_NDEFMAP_WRITE_OPE; + /* Update the CR index to know from which operation completion + routine has to be called */ + psNdefMap->ISO15693Container.cr_index = PH_FRINFC_NDEFMAP_CR_WR_NDEF; + /* State update */ + psNdefMap->State = ISO15693_WRITE_NDEF; + /* Copy user buffer to the context */ + psNdefMap->ApduBuffer = pPacketData; + /* Copy user length to the context */ + psNdefMap->ApduBufferSize = *pPacketDataLength; + /* Update the user memory size to a context variable */ + psNdefMap->NumOfBytesRead = pPacketDataLength; + /* Number of bytes written to the card is zero. + This variable returns the number of bytes written + to the card. */ + *psNdefMap->WrNdefPacketLength = 0; + /* Index to know the length read */ + psNdefMap->ApduBuffIndex = 0; + /* Store the offset in the context */ + psNdefMap->Offset = Offset; + + ps_iso_15693_con->current_block = + ISO15693_GET_LEN_FIELD_BLOCK_NO( + ps_iso_15693_con->ndef_tlv_type_blk, + ps_iso_15693_con->ndef_tlv_type_byte, + *pPacketDataLength); + + if (ISO15693_GET_LEN_FIELD_BYTE_NO( + ps_iso_15693_con->ndef_tlv_type_blk, + ps_iso_15693_con->ndef_tlv_type_byte, + *pPacketDataLength)) + { + ps_iso_15693_con->ndef_seq = (uint8_t)ISO15693_RD_BEFORE_WR_NDEF_L_0; + result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, + ISO15693_READ_COMMAND, NULL, 0); + } + else + { + ps_iso_15693_con->ndef_seq = (uint8_t)ISO15693_WRITE_DATA; + + /* Length is made 0x00 */ + *a_write_buf = 0x00; + + /* Write remaining data */ + (void)memcpy ((void *)(a_write_buf + 1), + (void *)psNdefMap->ApduBuffer, + (ISO15693_BYTES_PER_BLOCK - 1)); + + result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, + ISO15693_WRITE_COMMAND, + a_write_buf, ISO15693_BYTES_PER_BLOCK); + + psNdefMap->ApduBuffIndex = (uint16_t)(psNdefMap->ApduBuffIndex + + (ISO15693_BYTES_PER_BLOCK - 1)); + } + + return result; +} + +#ifdef FRINFC_READONLY_NDEF + +NFCSTATUS +phFriNfc_ISO15693_ConvertToReadOnly ( + phFriNfc_NdefMap_t *psNdefMap) +{ + NFCSTATUS result = NFCSTATUS_SUCCESS; + phFriNfc_ISO15693Cont_t *ps_iso_15693_con = + &(psNdefMap->ISO15693Container); + + psNdefMap->State = ISO15693_READ_ONLY_NDEF; + ps_iso_15693_con->ndef_seq = (uint8_t)ISO15693_RD_BEFORE_WR_CC; + ps_iso_15693_con->current_block = 0; + + result = phFriNfc_ISO15693_H_ReadWrite (psNdefMap, + ISO15693_READ_COMMAND, NULL, 0); + + return result; +} + +#endif /* #ifdef FRINFC_READONLY_NDEF */ + + +void +phFriNfc_ISO15693_Process ( + void *pContext, + NFCSTATUS Status) +{ + phFriNfc_NdefMap_t *psNdefMap = + (phFriNfc_NdefMap_t *)pContext; + + if ((NFCSTATUS_SUCCESS & PHNFCSTBLOWER) == (Status & PHNFCSTBLOWER)) + { + switch (psNdefMap->State) + { + case ISO15693_CHECK_NDEF: + { + Status = phFriNfc_ISO15693_H_ProcessCheckNdef (psNdefMap); + break; + } + + case ISO15693_READ_NDEF: + { + Status = phFriNfc_ISO15693_H_ProcessReadNdef (psNdefMap); + break; + } + + case ISO15693_WRITE_NDEF: + { + Status = phFriNfc_ISO15693_H_ProcessWriteNdef (psNdefMap); + break; + } + +#ifdef FRINFC_READONLY_NDEF + case ISO15693_READ_ONLY_NDEF: + { + Status = phFriNfc_ISO15693_H_ProcessReadOnly (psNdefMap); + break; + } +#endif /* #ifdef FRINFC_READONLY_NDEF */ + + default: + { + break; + } + } + } + + /* Call for the Completion Routine*/ + if (NFCSTATUS_PENDING != Status) + { + phFriNfc_ISO15693_H_Complete(psNdefMap, Status); + } +} + +/************************** END external functions *********************/ + +#endif /* #ifndef PH_FRINFC_MAP_ISO15693_DISABLED */ |