summaryrefslogtreecommitdiffstats
path: root/src/phFriNfc_ISO15693Map.c
diff options
context:
space:
mode:
authorMartijn Coenen <martijn.coenen@nxp.com>2011-01-13 23:24:24 +0100
committerJeff Hamilton <jham@android.com>2011-02-25 06:44:34 +0900
commita6e012a748e70ab203655d4e1c0d0a77b6515fad (patch)
treea3aeefc1f4816c58a4e943d85fca89678432f159 /src/phFriNfc_ISO15693Map.c
parent29e144ebf81b0f09b3fe4c26b67485ce836909c6 (diff)
downloadexternal_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.c1668
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 */