Convert files from C to C++

Removes compile time errors and warning as well.

Test: boots and NFC tag reading
Change-Id: I7e6540d607865b405cd18b8c23b2b390af59269f
diff --git a/src/nfc/tags/rw_i93.cc b/src/nfc/tags/rw_i93.cc
new file mode 100644
index 0000000..341c88c
--- /dev/null
+++ b/src/nfc/tags/rw_i93.cc
@@ -0,0 +1,3836 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2011-2014 Broadcom Corporation
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This file contains the implementation for ISO 15693 in Reader/Writer
+ *  mode.
+ *
+ ******************************************************************************/
+#include <string.h>
+#include "bt_types.h"
+#include "nfc_target.h"
+#include "trace_api.h"
+
+#include "nfc_api.h"
+#include "nfc_int.h"
+#include "rw_api.h"
+#include "rw_int.h"
+
+/* Response timeout     */
+#define RW_I93_TOUT_RESP 1000
+/* stay quiet timeout   */
+#define RW_I93_TOUT_STAY_QUIET 200
+/* max reading data if read multi block is supported */
+#define RW_I93_READ_MULTI_BLOCK_SIZE 128
+/* CC, zero length NDEF, Terminator TLV              */
+#define RW_I93_FORMAT_DATA_LEN 8
+/* max getting lock status if get multi block sec is supported */
+#define RW_I93_GET_MULTI_BLOCK_SEC_SIZE 253
+
+/* main state */
+enum {
+  RW_I93_STATE_NOT_ACTIVATED, /* ISO15693 is not activated            */
+  RW_I93_STATE_IDLE,          /* waiting for upper layer API          */
+  RW_I93_STATE_BUSY,          /* waiting for response from tag        */
+
+  RW_I93_STATE_DETECT_NDEF,   /* performing NDEF detection precedure  */
+  RW_I93_STATE_READ_NDEF,     /* performing read NDEF procedure       */
+  RW_I93_STATE_UPDATE_NDEF,   /* performing update NDEF procedure     */
+  RW_I93_STATE_FORMAT,        /* performing format procedure          */
+  RW_I93_STATE_SET_READ_ONLY, /* performing set read-only procedure   */
+
+  RW_I93_STATE_PRESENCE_CHECK /* checking presence of tag             */
+};
+
+/* sub state */
+enum {
+  RW_I93_SUBSTATE_WAIT_UID,          /* waiting for response of inventory    */
+  RW_I93_SUBSTATE_WAIT_SYS_INFO,     /* waiting for response of get sys info */
+  RW_I93_SUBSTATE_WAIT_CC,           /* waiting for reading CC               */
+  RW_I93_SUBSTATE_SEARCH_NDEF_TLV,   /* searching NDEF TLV                   */
+  RW_I93_SUBSTATE_CHECK_LOCK_STATUS, /* check if any NDEF TLV is locked      */
+
+  RW_I93_SUBSTATE_RESET_LEN,  /* set length to 0 to update NDEF TLV   */
+  RW_I93_SUBSTATE_WRITE_NDEF, /* writing NDEF and Terminator TLV      */
+  RW_I93_SUBSTATE_UPDATE_LEN, /* set length into NDEF TLV             */
+
+  RW_I93_SUBSTATE_WAIT_RESET_DSFID_AFI, /* reset DSFID and AFI */
+  RW_I93_SUBSTATE_CHECK_READ_ONLY,   /* check if any block is locked         */
+  RW_I93_SUBSTATE_WRITE_CC_NDEF_TLV, /* write CC and empty NDEF/Terminator TLV
+                                        */
+
+  RW_I93_SUBSTATE_WAIT_UPDATE_CC, /* updating CC as read-only             */
+  RW_I93_SUBSTATE_LOCK_NDEF_TLV,  /* lock blocks of NDEF TLV              */
+  RW_I93_SUBSTATE_WAIT_LOCK_CC    /* lock block of CC                     */
+};
+
+#if (BT_TRACE_VERBOSE == TRUE)
+static std::string rw_i93_get_state_name(uint8_t state);
+static std::string rw_i93_get_sub_state_name(uint8_t sub_state);
+static std::string rw_i93_get_tag_name(uint8_t product_version);
+#endif
+
+static void rw_i93_data_cback(uint8_t conn_id, tNFC_CONN_EVT event,
+                              tNFC_CONN* p_data);
+void rw_i93_handle_error(tNFC_STATUS status);
+tNFC_STATUS rw_i93_send_cmd_get_sys_info(uint8_t* p_uid, uint8_t extra_flag);
+
+/*******************************************************************************
+**
+** Function         rw_i93_get_product_version
+**
+** Description      Get product version from UID
+**
+** Returns          void
+**
+*******************************************************************************/
+void rw_i93_get_product_version(uint8_t* p_uid) {
+  tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
+
+  if (!memcmp(p_i93->uid, p_uid, I93_UID_BYTE_LEN)) {
+    return;
+  }
+
+  RW_TRACE_DEBUG0("rw_i93_get_product_version ()");
+
+  memcpy(p_i93->uid, p_uid, I93_UID_BYTE_LEN);
+
+  if (p_uid[1] == I93_UID_IC_MFG_CODE_NXP) {
+    if (p_uid[2] == I93_UID_ICODE_SLI)
+      p_i93->product_version = RW_I93_ICODE_SLI;
+    else if (p_uid[2] == I93_UID_ICODE_SLI_S)
+      p_i93->product_version = RW_I93_ICODE_SLI_S;
+    else if (p_uid[2] == I93_UID_ICODE_SLI_L)
+      p_i93->product_version = RW_I93_ICODE_SLI_L;
+    else
+      p_i93->product_version = RW_I93_UNKNOWN_PRODUCT;
+  } else if (p_uid[1] == I93_UID_IC_MFG_CODE_TI) {
+    if ((p_uid[2] & I93_UID_TAG_IT_HF_I_PRODUCT_ID_MASK) ==
+        I93_UID_TAG_IT_HF_I_PLUS_INLAY)
+      p_i93->product_version = RW_I93_TAG_IT_HF_I_PLUS_INLAY;
+    else if ((p_uid[2] & I93_UID_TAG_IT_HF_I_PRODUCT_ID_MASK) ==
+             I93_UID_TAG_IT_HF_I_PLUS_CHIP)
+      p_i93->product_version = RW_I93_TAG_IT_HF_I_PLUS_CHIP;
+    else if ((p_uid[2] & I93_UID_TAG_IT_HF_I_PRODUCT_ID_MASK) ==
+             I93_UID_TAG_IT_HF_I_STD_CHIP_INLAY)
+      p_i93->product_version = RW_I93_TAG_IT_HF_I_STD_CHIP_INLAY;
+    else if ((p_uid[2] & I93_UID_TAG_IT_HF_I_PRODUCT_ID_MASK) ==
+             I93_UID_TAG_IT_HF_I_PRO_CHIP_INLAY)
+      p_i93->product_version = RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY;
+    else
+      p_i93->product_version = RW_I93_UNKNOWN_PRODUCT;
+  } else if ((p_uid[1] == I93_UID_IC_MFG_CODE_STM) &&
+             (p_i93->info_flags & I93_INFO_FLAG_IC_REF)) {
+    if (p_i93->ic_reference == I93_IC_REF_STM_M24LR04E_R)
+      p_i93->product_version = RW_I93_STM_M24LR04E_R;
+    else if (p_i93->ic_reference == I93_IC_REF_STM_M24LR16E_R)
+      p_i93->product_version = RW_I93_STM_M24LR16E_R;
+    else if (p_i93->ic_reference == I93_IC_REF_STM_M24LR64E_R)
+      p_i93->product_version = RW_I93_STM_M24LR64E_R;
+    else {
+      switch (p_i93->ic_reference & I93_IC_REF_STM_MASK) {
+        case I93_IC_REF_STM_LRI1K:
+          p_i93->product_version = RW_I93_STM_LRI1K;
+          break;
+        case I93_IC_REF_STM_LRI2K:
+          p_i93->product_version = RW_I93_STM_LRI2K;
+          break;
+        case I93_IC_REF_STM_LRIS2K:
+          p_i93->product_version = RW_I93_STM_LRIS2K;
+          break;
+        case I93_IC_REF_STM_LRIS64K:
+          p_i93->product_version = RW_I93_STM_LRIS64K;
+          break;
+        case I93_IC_REF_STM_M24LR64_R:
+          p_i93->product_version = RW_I93_STM_M24LR64_R;
+          break;
+        default:
+          p_i93->product_version = RW_I93_UNKNOWN_PRODUCT;
+          break;
+      }
+    }
+  } else {
+    p_i93->product_version = RW_I93_UNKNOWN_PRODUCT;
+  }
+
+#if (BT_TRACE_VERBOSE == TRUE)
+  RW_TRACE_DEBUG1("product_version = <%s>",
+                  rw_i93_get_tag_name(p_i93->product_version).c_str());
+#else
+  RW_TRACE_DEBUG1("product_version = %d", p_i93->product_version);
+#endif
+
+  switch (p_i93->product_version) {
+    case RW_I93_TAG_IT_HF_I_STD_CHIP_INLAY:
+    case RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY:
+      /* these don't support Get System Information Command */
+      /* these support only Inventory, Stay Quiet, Read Single Block, Write
+       * Single Block, Lock Block */
+      p_i93->block_size = I93_TAG_IT_HF_I_STD_PRO_CHIP_INLAY_BLK_SIZE;
+      p_i93->num_block = I93_TAG_IT_HF_I_STD_PRO_CHIP_INLAY_NUM_USER_BLK;
+      break;
+    default:
+      break;
+  }
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_process_sys_info
+**
+** Description      Store system information of tag
+**
+** Returns          FALSE if retrying with protocol extension flag
+**
+*******************************************************************************/
+bool rw_i93_process_sys_info(uint8_t* p_data) {
+  uint8_t* p = p_data;
+  tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
+  uint8_t uid[I93_UID_BYTE_LEN], *p_uid;
+
+  RW_TRACE_DEBUG0("rw_i93_process_sys_info ()");
+
+  STREAM_TO_UINT8(p_i93->info_flags, p);
+
+  p_uid = uid;
+  STREAM_TO_ARRAY8(p_uid, p);
+
+  if (p_i93->info_flags & I93_INFO_FLAG_DSFID) {
+    STREAM_TO_UINT8(p_i93->dsfid, p);
+  }
+  if (p_i93->info_flags & I93_INFO_FLAG_AFI) {
+    STREAM_TO_UINT8(p_i93->afi, p);
+  }
+  if (p_i93->info_flags & I93_INFO_FLAG_MEM_SIZE) {
+    if (p_i93->intl_flags & RW_I93_FLAG_16BIT_NUM_BLOCK) {
+      STREAM_TO_UINT16(p_i93->num_block, p);
+    } else {
+      STREAM_TO_UINT8(p_i93->num_block, p);
+    }
+    /* it is one less than actual number of bytes */
+    p_i93->num_block += 1;
+
+    STREAM_TO_UINT8(p_i93->block_size, p);
+    /* it is one less than actual number of blocks */
+    p_i93->block_size = (p_i93->block_size & 0x1F) + 1;
+  }
+  if (p_i93->info_flags & I93_INFO_FLAG_IC_REF) {
+    STREAM_TO_UINT8(p_i93->ic_reference, p);
+
+    /* clear existing UID to set product version */
+    p_i93->uid[0] = 0x00;
+
+    /* store UID and get product version */
+    rw_i93_get_product_version(p_uid);
+
+    if (p_i93->uid[0] == I93_UID_FIRST_BYTE) {
+      if ((p_i93->uid[1] == I93_UID_IC_MFG_CODE_NXP) &&
+          (p_i93->ic_reference == I93_IC_REF_ICODE_SLI_L)) {
+        p_i93->num_block = 8;
+        p_i93->block_size = 4;
+      } else if (p_i93->uid[1] == I93_UID_IC_MFG_CODE_STM) {
+        /*
+        **  LRI1K:      010000xx(b), blockSize: 4, numberBlocks: 0x20
+        **  LRI2K:      001000xx(b), blockSize: 4, numberBlocks: 0x40
+        **  LRIS2K:     001010xx(b), blockSize: 4, numberBlocks: 0x40
+        **  LRIS64K:    010001xx(b), blockSize: 4, numberBlocks: 0x800
+        **  M24LR64-R:  001011xx(b), blockSize: 4, numberBlocks: 0x800
+        **  M24LR04E-R: 01011010(b), blockSize: 4, numberBlocks: 0x80
+        **  M24LR16E-R: 01001110(b), blockSize: 4, numberBlocks: 0x200
+        **  M24LR64E-R: 01011110(b), blockSize: 4, numberBlocks: 0x800
+        */
+        if ((p_i93->product_version == RW_I93_STM_M24LR16E_R) ||
+            (p_i93->product_version == RW_I93_STM_M24LR64E_R)) {
+          /*
+          ** M24LR16E-R or M24LR64E-R returns system information
+          ** without memory size, if option flag is not set.
+          ** LRIS64K and M24LR64-R return error if option flag is not
+          ** set.
+          */
+          if (!(p_i93->intl_flags & RW_I93_FLAG_16BIT_NUM_BLOCK)) {
+            /* get memory size with protocol extension flag */
+            if (rw_i93_send_cmd_get_sys_info(NULL, I93_FLAG_PROT_EXT_YES) ==
+                NFC_STATUS_OK) {
+              /* STM supports more than 2040 bytes */
+              p_i93->intl_flags |= RW_I93_FLAG_16BIT_NUM_BLOCK;
+
+              return false;
+            }
+          }
+          return true;
+        } else if ((p_i93->product_version == RW_I93_STM_LRI2K) &&
+                   (p_i93->ic_reference == 0x21)) {
+          /* workaround of byte order in memory size information */
+          p_i93->num_block = 64;
+          p_i93->block_size = 4;
+        }
+      }
+    }
+  }
+
+  return true;
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_check_sys_info_prot_ext
+**
+** Description      Check if need to set protocol extension flag to get system
+**                  info
+**
+** Returns          TRUE if sent Get System Info with protocol extension flag
+**
+*******************************************************************************/
+bool rw_i93_check_sys_info_prot_ext(uint8_t error_code) {
+  tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
+
+  RW_TRACE_DEBUG0("rw_i93_check_sys_info_prot_ext ()");
+
+  if ((p_i93->uid[1] == I93_UID_IC_MFG_CODE_STM) &&
+      (p_i93->sent_cmd == I93_CMD_GET_SYS_INFO) &&
+      (error_code == I93_ERROR_CODE_OPTION_NOT_SUPPORTED) &&
+      (rw_i93_send_cmd_get_sys_info(NULL, I93_FLAG_PROT_EXT_YES) ==
+       NFC_STATUS_OK)) {
+    return true;
+  } else {
+    return false;
+  }
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_send_to_upper
+**
+** Description      Send response to upper layer
+**
+** Returns          void
+**
+*******************************************************************************/
+void rw_i93_send_to_upper(NFC_HDR* p_resp) {
+  uint8_t *p = (uint8_t*)(p_resp + 1) + p_resp->offset, *p_uid;
+  uint16_t length = p_resp->len;
+  tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
+  tRW_DATA rw_data;
+  uint8_t event = RW_I93_MAX_EVT;
+  uint8_t flags;
+  NFC_HDR* p_buff;
+
+  RW_TRACE_DEBUG0("rw_i93_send_to_upper ()");
+
+  STREAM_TO_UINT8(flags, p);
+  length--;
+
+  if (flags & I93_FLAG_ERROR_DETECTED) {
+    if ((length) && (rw_i93_check_sys_info_prot_ext(*p))) {
+      /* getting system info with protocol extension flag */
+      /* This STM tag supports more than 2040 bytes */
+      p_i93->intl_flags |= RW_I93_FLAG_16BIT_NUM_BLOCK;
+      p_i93->state = RW_I93_STATE_BUSY;
+    } else {
+      /* notify error to upper layer */
+      rw_data.i93_cmd_cmpl.status = NFC_STATUS_FAILED;
+      rw_data.i93_cmd_cmpl.command = p_i93->sent_cmd;
+      STREAM_TO_UINT8(rw_data.i93_cmd_cmpl.error_code, p);
+
+      rw_cb.tcb.i93.sent_cmd = 0;
+      (*(rw_cb.p_cback))(RW_I93_CMD_CMPL_EVT, &rw_data);
+    }
+    return;
+  }
+
+  switch (p_i93->sent_cmd) {
+    case I93_CMD_INVENTORY:
+
+      /* forward inventory response */
+      rw_data.i93_inventory.status = NFC_STATUS_OK;
+      STREAM_TO_UINT8(rw_data.i93_inventory.dsfid, p);
+
+      p_uid = rw_data.i93_inventory.uid;
+      STREAM_TO_ARRAY8(p_uid, p);
+
+      /* store UID and get product version */
+      rw_i93_get_product_version(p_uid);
+
+      event = RW_I93_INVENTORY_EVT;
+      break;
+
+    case I93_CMD_READ_SINGLE_BLOCK:
+    case I93_CMD_READ_MULTI_BLOCK:
+    case I93_CMD_GET_MULTI_BLK_SEC:
+
+      /* forward tag data or security status */
+      p_buff = (NFC_HDR*)GKI_getbuf((uint16_t)(length + NFC_HDR_SIZE));
+
+      if (p_buff) {
+        p_buff->offset = 0;
+        p_buff->len = length;
+
+        memcpy((p_buff + 1), p, length);
+
+        rw_data.i93_data.status = NFC_STATUS_OK;
+        rw_data.i93_data.command = p_i93->sent_cmd;
+        rw_data.i93_data.p_data = p_buff;
+
+        event = RW_I93_DATA_EVT;
+      } else {
+        rw_data.i93_cmd_cmpl.status = NFC_STATUS_NO_BUFFERS;
+        rw_data.i93_cmd_cmpl.command = p_i93->sent_cmd;
+        rw_data.i93_cmd_cmpl.error_code = 0;
+
+        event = RW_I93_CMD_CMPL_EVT;
+      }
+      break;
+
+    case I93_CMD_WRITE_SINGLE_BLOCK:
+    case I93_CMD_LOCK_BLOCK:
+    case I93_CMD_WRITE_MULTI_BLOCK:
+    case I93_CMD_SELECT:
+    case I93_CMD_RESET_TO_READY:
+    case I93_CMD_WRITE_AFI:
+    case I93_CMD_LOCK_AFI:
+    case I93_CMD_WRITE_DSFID:
+    case I93_CMD_LOCK_DSFID:
+
+      /* notify the complete of command */
+      rw_data.i93_cmd_cmpl.status = NFC_STATUS_OK;
+      rw_data.i93_cmd_cmpl.command = p_i93->sent_cmd;
+      rw_data.i93_cmd_cmpl.error_code = 0;
+
+      event = RW_I93_CMD_CMPL_EVT;
+      break;
+
+    case I93_CMD_GET_SYS_INFO:
+
+      if (rw_i93_process_sys_info(p)) {
+        rw_data.i93_sys_info.status = NFC_STATUS_OK;
+        rw_data.i93_sys_info.info_flags = p_i93->info_flags;
+        rw_data.i93_sys_info.dsfid = p_i93->dsfid;
+        rw_data.i93_sys_info.afi = p_i93->afi;
+        rw_data.i93_sys_info.num_block = p_i93->num_block;
+        rw_data.i93_sys_info.block_size = p_i93->block_size;
+        rw_data.i93_sys_info.IC_reference = p_i93->ic_reference;
+
+        memcpy(rw_data.i93_sys_info.uid, p_i93->uid, I93_UID_BYTE_LEN);
+
+        event = RW_I93_SYS_INFO_EVT;
+      } else {
+        /* retrying with protocol extension flag */
+        p_i93->state = RW_I93_STATE_BUSY;
+        return;
+      }
+      break;
+
+    default:
+      break;
+  }
+
+  rw_cb.tcb.i93.sent_cmd = 0;
+  if (event != RW_I93_MAX_EVT) {
+    (*(rw_cb.p_cback))(event, &rw_data);
+  } else {
+    RW_TRACE_ERROR0("rw_i93_send_to_upper (): Invalid response");
+  }
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_send_to_lower
+**
+** Description      Send Request frame to lower layer
+**
+** Returns          TRUE if success
+**
+*******************************************************************************/
+bool rw_i93_send_to_lower(NFC_HDR* p_msg) {
+#if (BT_TRACE_PROTOCOL == TRUE)
+  DispRWI93Tag(p_msg, false, 0x00);
+#endif
+
+  /* store command for retransmitting */
+  if (rw_cb.tcb.i93.p_retry_cmd) {
+    GKI_freebuf(rw_cb.tcb.i93.p_retry_cmd);
+    rw_cb.tcb.i93.p_retry_cmd = NULL;
+  }
+
+  rw_cb.tcb.i93.p_retry_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
+
+  if (rw_cb.tcb.i93.p_retry_cmd) {
+    memcpy(rw_cb.tcb.i93.p_retry_cmd, p_msg,
+           sizeof(NFC_HDR) + p_msg->offset + p_msg->len);
+  }
+
+  if (NFC_SendData(NFC_RF_CONN_ID, p_msg) != NFC_STATUS_OK) {
+    RW_TRACE_ERROR0("rw_i93_send_to_lower (): NFC_SendData () failed");
+    return false;
+  }
+
+  nfc_start_quick_timer(&rw_cb.tcb.i93.timer, NFC_TTYPE_RW_I93_RESPONSE,
+                        (RW_I93_TOUT_RESP * QUICK_TIMER_TICKS_PER_SEC) / 1000);
+
+  return true;
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_send_cmd_inventory
+**
+** Description      Send Inventory Request to VICC
+**
+** Returns          tNFC_STATUS
+**
+*******************************************************************************/
+tNFC_STATUS rw_i93_send_cmd_inventory(uint8_t* p_uid, bool including_afi,
+                                      uint8_t afi) {
+  NFC_HDR* p_cmd;
+  uint8_t *p, flags;
+
+  RW_TRACE_DEBUG2("rw_i93_send_cmd_inventory () including_afi:%d, AFI:0x%02X",
+                  including_afi, afi);
+
+  p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
+
+  if (!p_cmd) {
+    RW_TRACE_ERROR0("rw_i93_send_cmd_inventory (): Cannot allocate buffer");
+    return NFC_STATUS_NO_BUFFERS;
+  }
+
+  p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
+  p_cmd->len = 3;
+  p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
+
+  /* Flags */
+  flags = (I93_FLAG_SLOT_ONE | I93_FLAG_INVENTORY_SET |
+           RW_I93_FLAG_SUB_CARRIER | RW_I93_FLAG_DATA_RATE);
+  if (including_afi) {
+    flags |= I93_FLAG_AFI_PRESENT;
+  }
+
+  UINT8_TO_STREAM(p, flags);
+
+  /* Command Code */
+  UINT8_TO_STREAM(p, I93_CMD_INVENTORY);
+
+  if (including_afi) {
+    /* Parameters */
+    UINT8_TO_STREAM(p, afi); /* Optional AFI */
+    p_cmd->len++;
+  }
+
+  if (p_uid) {
+    UINT8_TO_STREAM(p, I93_UID_BYTE_LEN * 8); /* Mask Length */
+    ARRAY8_TO_STREAM(p, p_uid);               /* UID */
+    p_cmd->len += I93_UID_BYTE_LEN;
+  } else {
+    UINT8_TO_STREAM(p, 0x00); /* Mask Length */
+  }
+
+  if (rw_i93_send_to_lower(p_cmd)) {
+    rw_cb.tcb.i93.sent_cmd = I93_CMD_INVENTORY;
+    return NFC_STATUS_OK;
+  } else {
+    return NFC_STATUS_FAILED;
+  }
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_send_cmd_stay_quiet
+**
+** Description      Send Stay Quiet Request to VICC
+**
+** Returns          tNFC_STATUS
+**
+*******************************************************************************/
+tNFC_STATUS rw_i93_send_cmd_stay_quiet(void) {
+  NFC_HDR* p_cmd;
+  uint8_t* p;
+
+  RW_TRACE_DEBUG0("rw_i93_send_cmd_stay_quiet ()");
+
+  p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
+
+  if (!p_cmd) {
+    RW_TRACE_ERROR0("rw_i93_send_cmd_stay_quiet (): Cannot allocate buffer");
+    return NFC_STATUS_NO_BUFFERS;
+  }
+
+  p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
+  p_cmd->len = 10;
+  p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
+
+  /* Flags */
+  UINT8_TO_STREAM(p, (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER |
+                      RW_I93_FLAG_DATA_RATE));
+
+  /* Command Code */
+  UINT8_TO_STREAM(p, I93_CMD_STAY_QUIET);
+
+  /* Parameters */
+  ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
+
+  if (rw_i93_send_to_lower(p_cmd)) {
+    rw_cb.tcb.i93.sent_cmd = I93_CMD_STAY_QUIET;
+
+    /* restart timer for stay quiet */
+    nfc_start_quick_timer(
+        &rw_cb.tcb.i93.timer, NFC_TTYPE_RW_I93_RESPONSE,
+        (RW_I93_TOUT_STAY_QUIET * QUICK_TIMER_TICKS_PER_SEC) / 1000);
+    return NFC_STATUS_OK;
+  } else {
+    return NFC_STATUS_FAILED;
+  }
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_send_cmd_read_single_block
+**
+** Description      Send Read Single Block Request to VICC
+**
+** Returns          tNFC_STATUS
+**
+*******************************************************************************/
+tNFC_STATUS rw_i93_send_cmd_read_single_block(uint16_t block_number,
+                                              bool read_security) {
+  NFC_HDR* p_cmd;
+  uint8_t *p, flags;
+
+  RW_TRACE_DEBUG0("rw_i93_send_cmd_read_single_block ()");
+
+  p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
+
+  if (!p_cmd) {
+    RW_TRACE_ERROR0(
+        "rw_i93_send_cmd_read_single_block (): Cannot allocate buffer");
+    return NFC_STATUS_NO_BUFFERS;
+  }
+
+  p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
+  p_cmd->len = 11;
+  p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
+
+  /* Flags */
+  flags =
+      (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER | RW_I93_FLAG_DATA_RATE);
+
+  if (read_security) flags |= I93_FLAG_OPTION_SET;
+
+  if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_16BIT_NUM_BLOCK)
+    flags |= I93_FLAG_PROT_EXT_YES;
+
+  UINT8_TO_STREAM(p, flags);
+
+  /* Command Code */
+  UINT8_TO_STREAM(p, I93_CMD_READ_SINGLE_BLOCK);
+
+  /* Parameters */
+  ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
+
+  if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_16BIT_NUM_BLOCK) {
+    UINT16_TO_STREAM(p, block_number); /* Block number */
+    p_cmd->len++;
+  } else {
+    UINT8_TO_STREAM(p, block_number); /* Block number */
+  }
+
+  if (rw_i93_send_to_lower(p_cmd)) {
+    rw_cb.tcb.i93.sent_cmd = I93_CMD_READ_SINGLE_BLOCK;
+    return NFC_STATUS_OK;
+  } else {
+    return NFC_STATUS_FAILED;
+  }
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_send_cmd_write_single_block
+**
+** Description      Send Write Single Block Request to VICC
+**
+** Returns          tNFC_STATUS
+**
+*******************************************************************************/
+tNFC_STATUS rw_i93_send_cmd_write_single_block(uint16_t block_number,
+                                               uint8_t* p_data) {
+  NFC_HDR* p_cmd;
+  uint8_t *p, flags;
+
+  RW_TRACE_DEBUG0("rw_i93_send_cmd_write_single_block ()");
+
+  p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
+
+  if (!p_cmd) {
+    RW_TRACE_ERROR0(
+        "rw_i93_send_cmd_write_single_block (): Cannot allocate buffer");
+    return NFC_STATUS_NO_BUFFERS;
+  }
+
+  p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
+  p_cmd->len = 11 + rw_cb.tcb.i93.block_size;
+  p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
+
+  /* Flags */
+  if ((rw_cb.tcb.i93.product_version == RW_I93_TAG_IT_HF_I_PLUS_INLAY) ||
+      (rw_cb.tcb.i93.product_version == RW_I93_TAG_IT_HF_I_PLUS_CHIP) ||
+      (rw_cb.tcb.i93.product_version == RW_I93_TAG_IT_HF_I_STD_CHIP_INLAY) ||
+      (rw_cb.tcb.i93.product_version == RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY)) {
+    /* Option must be set for TI tag */
+    flags = (I93_FLAG_ADDRESS_SET | I93_FLAG_OPTION_SET |
+             RW_I93_FLAG_SUB_CARRIER | RW_I93_FLAG_DATA_RATE);
+  } else {
+    flags = (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER |
+             RW_I93_FLAG_DATA_RATE);
+  }
+
+  if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_16BIT_NUM_BLOCK)
+    flags |= I93_FLAG_PROT_EXT_YES;
+
+  UINT8_TO_STREAM(p, flags);
+
+  /* Command Code */
+  UINT8_TO_STREAM(p, I93_CMD_WRITE_SINGLE_BLOCK);
+
+  /* Parameters */
+  ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
+
+  if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_16BIT_NUM_BLOCK) {
+    UINT16_TO_STREAM(p, block_number); /* Block number */
+    p_cmd->len++;
+  } else {
+    UINT8_TO_STREAM(p, block_number); /* Block number */
+  }
+
+  /* Data */
+  ARRAY_TO_STREAM(p, p_data, rw_cb.tcb.i93.block_size);
+
+  if (rw_i93_send_to_lower(p_cmd)) {
+    rw_cb.tcb.i93.sent_cmd = I93_CMD_WRITE_SINGLE_BLOCK;
+    return NFC_STATUS_OK;
+  } else {
+    return NFC_STATUS_FAILED;
+  }
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_send_cmd_lock_block
+**
+** Description      Send Lock Block Request to VICC
+**
+**                  STM LRIS64K, M24LR64-R, M24LR04E-R, M24LR16E-R, M24LR64E-R
+**                  do not support.
+**
+** Returns          tNFC_STATUS
+**
+*******************************************************************************/
+tNFC_STATUS rw_i93_send_cmd_lock_block(uint8_t block_number) {
+  NFC_HDR* p_cmd;
+  uint8_t* p;
+
+  RW_TRACE_DEBUG0("rw_i93_send_cmd_lock_block ()");
+
+  p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
+
+  if (!p_cmd) {
+    RW_TRACE_ERROR0("rw_i93_send_cmd_lock_block (): Cannot allocate buffer");
+    return NFC_STATUS_NO_BUFFERS;
+  }
+
+  p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
+  p_cmd->len = 11;
+  p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
+
+  /* Flags */
+  if ((rw_cb.tcb.i93.product_version == RW_I93_TAG_IT_HF_I_PLUS_INLAY) ||
+      (rw_cb.tcb.i93.product_version == RW_I93_TAG_IT_HF_I_PLUS_CHIP) ||
+      (rw_cb.tcb.i93.product_version == RW_I93_TAG_IT_HF_I_STD_CHIP_INLAY) ||
+      (rw_cb.tcb.i93.product_version == RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY)) {
+    /* Option must be set for TI tag */
+    UINT8_TO_STREAM(p, (I93_FLAG_ADDRESS_SET | I93_FLAG_OPTION_SET |
+                        RW_I93_FLAG_SUB_CARRIER | RW_I93_FLAG_DATA_RATE));
+  } else {
+    UINT8_TO_STREAM(p, (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER |
+                        RW_I93_FLAG_DATA_RATE));
+  }
+
+  /* Command Code */
+  UINT8_TO_STREAM(p, I93_CMD_LOCK_BLOCK);
+
+  /* Parameters */
+  ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
+  UINT8_TO_STREAM(p, block_number);       /* Block number */
+
+  if (rw_i93_send_to_lower(p_cmd)) {
+    rw_cb.tcb.i93.sent_cmd = I93_CMD_LOCK_BLOCK;
+    return NFC_STATUS_OK;
+  } else {
+    return NFC_STATUS_FAILED;
+  }
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_send_cmd_read_multi_blocks
+**
+** Description      Send Read Multiple Blocks Request to VICC
+**
+** Returns          tNFC_STATUS
+**
+*******************************************************************************/
+tNFC_STATUS rw_i93_send_cmd_read_multi_blocks(uint16_t first_block_number,
+                                              uint16_t number_blocks) {
+  NFC_HDR* p_cmd;
+  uint8_t *p, flags;
+
+  RW_TRACE_DEBUG0("rw_i93_send_cmd_read_multi_blocks ()");
+
+  p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
+
+  if (!p_cmd) {
+    RW_TRACE_ERROR0(
+        "rw_i93_send_cmd_read_multi_blocks (): Cannot allocate buffer");
+    return NFC_STATUS_NO_BUFFERS;
+  }
+
+  p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
+  p_cmd->len = 12;
+  p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
+
+  /* Flags */
+  flags =
+      (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER | RW_I93_FLAG_DATA_RATE);
+
+  if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_16BIT_NUM_BLOCK)
+    flags |= I93_FLAG_PROT_EXT_YES;
+
+  UINT8_TO_STREAM(p, flags);
+
+  /* Command Code */
+  UINT8_TO_STREAM(p, I93_CMD_READ_MULTI_BLOCK);
+
+  /* Parameters */
+  ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
+
+  if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_16BIT_NUM_BLOCK) {
+    UINT16_TO_STREAM(p, first_block_number); /* First block number */
+    p_cmd->len++;
+  } else {
+    UINT8_TO_STREAM(p, first_block_number); /* First block number */
+  }
+
+  UINT8_TO_STREAM(
+      p, number_blocks - 1); /* Number of blocks, 0x00 to read one block */
+
+  if (rw_i93_send_to_lower(p_cmd)) {
+    rw_cb.tcb.i93.sent_cmd = I93_CMD_READ_MULTI_BLOCK;
+    return NFC_STATUS_OK;
+  } else {
+    return NFC_STATUS_FAILED;
+  }
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_send_cmd_write_multi_blocks
+**
+** Description      Send Write Multiple Blocks Request to VICC
+**
+** Returns          tNFC_STATUS
+**
+*******************************************************************************/
+tNFC_STATUS rw_i93_send_cmd_write_multi_blocks(uint8_t first_block_number,
+                                               uint16_t number_blocks,
+                                               uint8_t* p_data) {
+  NFC_HDR* p_cmd;
+  uint8_t* p;
+
+  RW_TRACE_DEBUG0("rw_i93_send_cmd_write_multi_blocks ()");
+
+  p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
+
+  if (!p_cmd) {
+    RW_TRACE_ERROR0(
+        "rw_i93_send_cmd_write_multi_blocks (): Cannot allocate buffer");
+    return NFC_STATUS_NO_BUFFERS;
+  }
+
+  p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
+  p_cmd->len = 12 + number_blocks * rw_cb.tcb.i93.block_size;
+  p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
+
+  /* Flags */
+  UINT8_TO_STREAM(p, (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER |
+                      RW_I93_FLAG_DATA_RATE));
+
+  /* Command Code */
+  UINT8_TO_STREAM(p, I93_CMD_WRITE_MULTI_BLOCK);
+
+  /* Parameters */
+  ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
+  UINT8_TO_STREAM(p, first_block_number); /* First block number */
+  UINT8_TO_STREAM(
+      p, number_blocks - 1); /* Number of blocks, 0x00 to read one block */
+
+  /* Data */
+  ARRAY_TO_STREAM(p, p_data, number_blocks * rw_cb.tcb.i93.block_size);
+
+  if (rw_i93_send_to_lower(p_cmd)) {
+    rw_cb.tcb.i93.sent_cmd = I93_CMD_WRITE_MULTI_BLOCK;
+    return NFC_STATUS_OK;
+  } else {
+    return NFC_STATUS_FAILED;
+  }
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_send_cmd_select
+**
+** Description      Send Select Request to VICC
+**
+** Returns          tNFC_STATUS
+**
+*******************************************************************************/
+tNFC_STATUS rw_i93_send_cmd_select(uint8_t* p_uid) {
+  NFC_HDR* p_cmd;
+  uint8_t* p;
+
+  RW_TRACE_DEBUG0("rw_i93_send_cmd_select ()");
+
+  p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
+
+  if (!p_cmd) {
+    RW_TRACE_ERROR0("rw_i93_send_cmd_select (): Cannot allocate buffer");
+    return NFC_STATUS_NO_BUFFERS;
+  }
+
+  p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
+  p_cmd->len = 10;
+  p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
+
+  /* Flags */
+  UINT8_TO_STREAM(p, (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER |
+                      RW_I93_FLAG_DATA_RATE));
+
+  /* Command Code */
+  UINT8_TO_STREAM(p, I93_CMD_SELECT);
+
+  /* Parameters */
+  ARRAY8_TO_STREAM(p, p_uid); /* UID */
+
+  if (rw_i93_send_to_lower(p_cmd)) {
+    rw_cb.tcb.i93.sent_cmd = I93_CMD_SELECT;
+    return NFC_STATUS_OK;
+  } else {
+    return NFC_STATUS_FAILED;
+  }
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_send_cmd_reset_to_ready
+**
+** Description      Send Reset to Ready Request to VICC
+**
+** Returns          tNFC_STATUS
+**
+*******************************************************************************/
+tNFC_STATUS rw_i93_send_cmd_reset_to_ready(void) {
+  NFC_HDR* p_cmd;
+  uint8_t* p;
+
+  RW_TRACE_DEBUG0("rw_i93_send_cmd_reset_to_ready ()");
+
+  p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
+
+  if (!p_cmd) {
+    RW_TRACE_ERROR0(
+        "rw_i93_send_cmd_reset_to_ready (): Cannot allocate buffer");
+    return NFC_STATUS_NO_BUFFERS;
+  }
+
+  p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
+  p_cmd->len = 10;
+  p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
+
+  /* Flags */
+  UINT8_TO_STREAM(p, (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER |
+                      RW_I93_FLAG_DATA_RATE));
+
+  /* Command Code */
+  UINT8_TO_STREAM(p, I93_CMD_RESET_TO_READY);
+
+  /* Parameters */
+  ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
+
+  if (rw_i93_send_to_lower(p_cmd)) {
+    rw_cb.tcb.i93.sent_cmd = I93_CMD_RESET_TO_READY;
+    return NFC_STATUS_OK;
+  } else {
+    return NFC_STATUS_FAILED;
+  }
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_send_cmd_write_afi
+**
+** Description      Send Write AFI Request to VICC
+**
+** Returns          tNFC_STATUS
+**
+*******************************************************************************/
+tNFC_STATUS rw_i93_send_cmd_write_afi(uint8_t afi) {
+  NFC_HDR* p_cmd;
+  uint8_t* p;
+
+  RW_TRACE_DEBUG0("rw_i93_send_cmd_write_afi ()");
+
+  p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
+
+  if (!p_cmd) {
+    RW_TRACE_ERROR0("rw_i93_send_cmd_write_afi (): Cannot allocate buffer");
+    return NFC_STATUS_NO_BUFFERS;
+  }
+
+  p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
+  p_cmd->len = 11;
+  p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
+
+  /* Flags */
+  UINT8_TO_STREAM(p, (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER |
+                      RW_I93_FLAG_DATA_RATE));
+
+  /* Command Code */
+  UINT8_TO_STREAM(p, I93_CMD_WRITE_AFI);
+
+  /* Parameters */
+  ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
+  UINT8_TO_STREAM(p, afi);                /* AFI */
+
+  if (rw_i93_send_to_lower(p_cmd)) {
+    rw_cb.tcb.i93.sent_cmd = I93_CMD_WRITE_AFI;
+    return NFC_STATUS_OK;
+  } else {
+    return NFC_STATUS_FAILED;
+  }
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_send_cmd_lock_afi
+**
+** Description      Send Lock AFI Request to VICC
+**
+** Returns          tNFC_STATUS
+**
+*******************************************************************************/
+tNFC_STATUS rw_i93_send_cmd_lock_afi(void) {
+  NFC_HDR* p_cmd;
+  uint8_t* p;
+
+  RW_TRACE_DEBUG0("rw_i93_send_cmd_lock_afi ()");
+
+  p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
+
+  if (!p_cmd) {
+    RW_TRACE_ERROR0("rw_i93_send_cmd_lock_afi (): Cannot allocate buffer");
+    return NFC_STATUS_NO_BUFFERS;
+  }
+
+  p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
+  p_cmd->len = 10;
+  p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
+
+  /* Flags */
+  UINT8_TO_STREAM(p, (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER |
+                      RW_I93_FLAG_DATA_RATE));
+
+  /* Command Code */
+  UINT8_TO_STREAM(p, I93_CMD_LOCK_AFI);
+
+  /* Parameters */
+  ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
+
+  if (rw_i93_send_to_lower(p_cmd)) {
+    rw_cb.tcb.i93.sent_cmd = I93_CMD_LOCK_AFI;
+    return NFC_STATUS_OK;
+  } else {
+    return NFC_STATUS_FAILED;
+  }
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_send_cmd_write_dsfid
+**
+** Description      Send Write DSFID Request to VICC
+**
+** Returns          tNFC_STATUS
+**
+*******************************************************************************/
+tNFC_STATUS rw_i93_send_cmd_write_dsfid(uint8_t dsfid) {
+  NFC_HDR* p_cmd;
+  uint8_t* p;
+
+  RW_TRACE_DEBUG0("rw_i93_send_cmd_write_dsfid ()");
+
+  p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
+
+  if (!p_cmd) {
+    RW_TRACE_ERROR0("rw_i93_send_cmd_write_dsfid (): Cannot allocate buffer");
+    return NFC_STATUS_NO_BUFFERS;
+  }
+
+  p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
+  p_cmd->len = 11;
+  p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
+
+  /* Flags */
+  UINT8_TO_STREAM(p, (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER |
+                      RW_I93_FLAG_DATA_RATE));
+
+  /* Command Code */
+  UINT8_TO_STREAM(p, I93_CMD_WRITE_DSFID);
+
+  /* Parameters */
+  ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
+  UINT8_TO_STREAM(p, dsfid);              /* DSFID */
+
+  if (rw_i93_send_to_lower(p_cmd)) {
+    rw_cb.tcb.i93.sent_cmd = I93_CMD_WRITE_DSFID;
+    return NFC_STATUS_OK;
+  } else {
+    return NFC_STATUS_FAILED;
+  }
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_send_cmd_lock_dsfid
+**
+** Description      Send Lock DSFID Request to VICC
+**
+** Returns          tNFC_STATUS
+**
+*******************************************************************************/
+tNFC_STATUS rw_i93_send_cmd_lock_dsfid(void) {
+  NFC_HDR* p_cmd;
+  uint8_t* p;
+
+  RW_TRACE_DEBUG0("rw_i93_send_cmd_lock_dsfid ()");
+
+  p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
+
+  if (!p_cmd) {
+    RW_TRACE_ERROR0("rw_i93_send_cmd_lock_dsfid (): Cannot allocate buffer");
+    return NFC_STATUS_NO_BUFFERS;
+  }
+
+  p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
+  p_cmd->len = 10;
+  p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
+
+  /* Flags */
+  UINT8_TO_STREAM(p, (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER |
+                      RW_I93_FLAG_DATA_RATE));
+
+  /* Command Code */
+  UINT8_TO_STREAM(p, I93_CMD_LOCK_DSFID);
+
+  /* Parameters */
+  ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
+
+  if (rw_i93_send_to_lower(p_cmd)) {
+    rw_cb.tcb.i93.sent_cmd = I93_CMD_LOCK_DSFID;
+    return NFC_STATUS_OK;
+  } else {
+    return NFC_STATUS_FAILED;
+  }
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_send_cmd_get_sys_info
+**
+** Description      Send Get System Information Request to VICC
+**
+** Returns          tNFC_STATUS
+**
+*******************************************************************************/
+tNFC_STATUS rw_i93_send_cmd_get_sys_info(uint8_t* p_uid, uint8_t extra_flags) {
+  NFC_HDR* p_cmd;
+  uint8_t* p;
+
+  RW_TRACE_DEBUG0("rw_i93_send_cmd_get_sys_info ()");
+
+  p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
+
+  if (!p_cmd) {
+    RW_TRACE_ERROR0("rw_i93_send_cmd_get_sys_info (): Cannot allocate buffer");
+    return NFC_STATUS_NO_BUFFERS;
+  }
+
+  p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
+  p_cmd->len = 10;
+  p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
+
+  /* Flags */
+  UINT8_TO_STREAM(p, (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER |
+                      RW_I93_FLAG_DATA_RATE | extra_flags));
+
+  /* Command Code */
+  UINT8_TO_STREAM(p, I93_CMD_GET_SYS_INFO);
+
+  /* Parameters */
+  if (p_uid) {
+    ARRAY8_TO_STREAM(p, p_uid); /* UID */
+  } else {
+    ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
+  }
+
+  if (rw_i93_send_to_lower(p_cmd)) {
+    rw_cb.tcb.i93.sent_cmd = I93_CMD_GET_SYS_INFO;
+    return NFC_STATUS_OK;
+  } else {
+    return NFC_STATUS_FAILED;
+  }
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_send_cmd_get_multi_block_sec
+**
+** Description      Send Get Multiple Block Security Status Request to VICC
+**
+** Returns          tNFC_STATUS
+**
+*******************************************************************************/
+tNFC_STATUS rw_i93_send_cmd_get_multi_block_sec(uint16_t first_block_number,
+                                                uint16_t number_blocks) {
+  NFC_HDR* p_cmd;
+  uint8_t *p, flags;
+
+  RW_TRACE_DEBUG0("rw_i93_send_cmd_get_multi_block_sec ()");
+
+  p_cmd = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
+
+  if (!p_cmd) {
+    RW_TRACE_ERROR0(
+        "rw_i93_send_cmd_get_multi_block_sec (): Cannot allocate buffer");
+    return NFC_STATUS_NO_BUFFERS;
+  }
+
+  p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
+  p_cmd->len = 12;
+  p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
+
+  /* Flags */
+  flags =
+      (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER | RW_I93_FLAG_DATA_RATE);
+
+  if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_16BIT_NUM_BLOCK)
+    flags |= I93_FLAG_PROT_EXT_YES;
+
+  UINT8_TO_STREAM(p, flags);
+
+  /* Command Code */
+  UINT8_TO_STREAM(p, I93_CMD_GET_MULTI_BLK_SEC);
+
+  /* Parameters */
+  ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
+
+  if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_16BIT_NUM_BLOCK) {
+    UINT16_TO_STREAM(p, first_block_number); /* First block number */
+    UINT16_TO_STREAM(
+        p, number_blocks - 1); /* Number of blocks, 0x00 to read one block */
+    p_cmd->len += 2;
+  } else {
+    UINT8_TO_STREAM(p, first_block_number); /* First block number */
+    UINT8_TO_STREAM(
+        p, number_blocks - 1); /* Number of blocks, 0x00 to read one block */
+  }
+
+  if (rw_i93_send_to_lower(p_cmd)) {
+    rw_cb.tcb.i93.sent_cmd = I93_CMD_GET_MULTI_BLK_SEC;
+    return NFC_STATUS_OK;
+  } else {
+    return NFC_STATUS_FAILED;
+  }
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_get_next_blocks
+**
+** Description      Read as many blocks as possible (up to
+**                  RW_I93_READ_MULTI_BLOCK_SIZE)
+**
+** Returns          tNFC_STATUS
+**
+*******************************************************************************/
+tNFC_STATUS rw_i93_get_next_blocks(uint16_t offset) {
+  tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
+  uint16_t first_block;
+  uint16_t num_block;
+
+  RW_TRACE_DEBUG0("rw_i93_get_next_blocks ()");
+
+  first_block = offset / p_i93->block_size;
+
+  /* more blocks, more efficent but more error rate */
+
+  if (p_i93->intl_flags & RW_I93_FLAG_READ_MULTI_BLOCK) {
+    num_block = RW_I93_READ_MULTI_BLOCK_SIZE / p_i93->block_size;
+
+    if (num_block + first_block > p_i93->num_block)
+      num_block = p_i93->num_block - first_block;
+
+    if (p_i93->uid[1] == I93_UID_IC_MFG_CODE_STM) {
+      /* LRIS64K, M24LR64-R, M24LR04E-R, M24LR16E-R, M24LR64E-R requires
+      ** - The max number of blocks is 32 and they are all located in the
+      **   same sector.
+      ** - The sector is 32 blocks of 4 bytes.
+      */
+      if ((p_i93->product_version == RW_I93_STM_LRIS64K) ||
+          (p_i93->product_version == RW_I93_STM_M24LR64_R) ||
+          (p_i93->product_version == RW_I93_STM_M24LR04E_R) ||
+          (p_i93->product_version == RW_I93_STM_M24LR16E_R) ||
+          (p_i93->product_version == RW_I93_STM_M24LR64E_R)) {
+        if (num_block > I93_STM_MAX_BLOCKS_PER_READ)
+          num_block = I93_STM_MAX_BLOCKS_PER_READ;
+
+        if ((first_block / I93_STM_BLOCKS_PER_SECTOR) !=
+            ((first_block + num_block - 1) / I93_STM_BLOCKS_PER_SECTOR)) {
+          num_block = I93_STM_BLOCKS_PER_SECTOR -
+                      (first_block % I93_STM_BLOCKS_PER_SECTOR);
+        }
+      }
+    }
+
+    return rw_i93_send_cmd_read_multi_blocks(first_block, num_block);
+  } else {
+    return rw_i93_send_cmd_read_single_block(first_block, false);
+  }
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_get_next_block_sec
+**
+** Description      Get as many security of blocks as possible from
+**                  p_i93->rw_offset (up to RW_I93_GET_MULTI_BLOCK_SEC_SIZE)
+**
+** Returns          tNFC_STATUS
+**
+*******************************************************************************/
+tNFC_STATUS rw_i93_get_next_block_sec(void) {
+  tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
+  uint16_t num_blocks;
+
+  RW_TRACE_DEBUG0("rw_i93_get_next_block_sec ()");
+
+  if (p_i93->num_block <= p_i93->rw_offset) {
+    RW_TRACE_ERROR2("rw_offset(0x%x) must be less than num_block(0x%x)",
+                    p_i93->rw_offset, p_i93->num_block);
+    return NFC_STATUS_FAILED;
+  }
+
+  num_blocks = p_i93->num_block - p_i93->rw_offset;
+
+  if (num_blocks > RW_I93_GET_MULTI_BLOCK_SEC_SIZE)
+    num_blocks = RW_I93_GET_MULTI_BLOCK_SEC_SIZE;
+
+  return rw_i93_send_cmd_get_multi_block_sec(p_i93->rw_offset, num_blocks);
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_sm_detect_ndef
+**
+** Description      Process NDEF detection procedure
+**
+**                  1. Get UID if not having yet
+**                  2. Get System Info if not having yet
+**                  3. Read first block for CC
+**                  4. Search NDEF Type and length
+**                  5. Get block status to get max NDEF size and read-only
+**                     status
+**
+** Returns          void
+**
+*******************************************************************************/
+void rw_i93_sm_detect_ndef(NFC_HDR* p_resp) {
+  uint8_t *p = (uint8_t*)(p_resp + 1) + p_resp->offset, *p_uid;
+  uint8_t flags, u8 = 0, cc[4];
+  uint16_t length = p_resp->len, xx, block, first_block, last_block, num_blocks;
+  tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
+  tRW_DATA rw_data;
+  tNFC_STATUS status = NFC_STATUS_FAILED;
+
+#if (BT_TRACE_VERBOSE == TRUE)
+  RW_TRACE_DEBUG2("rw_i93_sm_detect_ndef () sub_state:%s (0x%x)",
+                  rw_i93_get_sub_state_name(p_i93->sub_state).c_str(),
+                  p_i93->sub_state);
+#else
+  RW_TRACE_DEBUG1("rw_i93_sm_detect_ndef () sub_state:0x%x", p_i93->sub_state);
+#endif
+
+  STREAM_TO_UINT8(flags, p);
+  length--;
+
+  if (flags & I93_FLAG_ERROR_DETECTED) {
+    if ((length) && (rw_i93_check_sys_info_prot_ext(*p))) {
+      /* getting system info with protocol extension flag */
+      /* This STM tag supports more than 2040 bytes */
+      p_i93->intl_flags |= RW_I93_FLAG_16BIT_NUM_BLOCK;
+    } else {
+      RW_TRACE_DEBUG1("Got error flags (0x%02x)", flags);
+      rw_i93_handle_error(NFC_STATUS_FAILED);
+    }
+    return;
+  }
+
+  switch (p_i93->sub_state) {
+    case RW_I93_SUBSTATE_WAIT_UID:
+
+      STREAM_TO_UINT8(u8, p); /* DSFID */
+      p_uid = p_i93->uid;
+      STREAM_TO_ARRAY8(p_uid, p);
+
+      if (u8 != I93_DFS_UNSUPPORTED) {
+        /* if Data Storage Format is unknown */
+        RW_TRACE_DEBUG1("Got unknown DSFID (0x%02x)", u8);
+        rw_i93_handle_error(NFC_STATUS_FAILED);
+      } else {
+        /* get system information to get memory size */
+        if (rw_i93_send_cmd_get_sys_info(NULL, I93_FLAG_PROT_EXT_NO) ==
+            NFC_STATUS_OK) {
+          p_i93->sub_state = RW_I93_SUBSTATE_WAIT_SYS_INFO;
+        } else {
+          rw_i93_handle_error(NFC_STATUS_FAILED);
+        }
+      }
+      break;
+
+    case RW_I93_SUBSTATE_WAIT_SYS_INFO:
+
+      p_i93->block_size = 0;
+      p_i93->num_block = 0;
+
+      if (!rw_i93_process_sys_info(p)) {
+        /* retrying with protocol extension flag */
+        break;
+      }
+
+      if ((p_i93->block_size == 0) || (p_i93->num_block == 0)) {
+        RW_TRACE_DEBUG0("Unable to get tag memory size");
+        rw_i93_handle_error(status);
+      } else {
+        /* read CC in the first block */
+        if (rw_i93_send_cmd_read_single_block(0x0000, false) == NFC_STATUS_OK) {
+          p_i93->sub_state = RW_I93_SUBSTATE_WAIT_CC;
+        } else {
+          rw_i93_handle_error(NFC_STATUS_FAILED);
+        }
+      }
+      break;
+
+    case RW_I93_SUBSTATE_WAIT_CC:
+
+      /* assume block size is more than 4 */
+      STREAM_TO_ARRAY(cc, p, 4);
+
+      status = NFC_STATUS_FAILED;
+
+      /*
+      ** Capability Container (CC)
+      **
+      ** CC[0] : magic number (0xE1)
+      ** CC[1] : Bit 7-6:Major version number
+      **       : Bit 5-4:Minor version number
+      **       : Bit 3-2:Read access condition (00b: read access granted
+      **         without any security)
+      **       : Bit 1-0:Write access condition (00b: write access granted
+      **         without any security)
+      ** CC[2] : Memory size in 8 bytes (Ex. 0x04 is 32 bytes) [STM, set to
+      **         0xFF if more than 2040bytes]
+      ** CC[3] : Bit 0:Read multiple blocks is supported [NXP, STM]
+      **       : Bit 1:Inventory page read is supported [NXP]
+      **       : Bit 2:More than 2040 bytes are supported [STM]
+      */
+
+      RW_TRACE_DEBUG4(
+          "rw_i93_sm_detect_ndef (): cc: 0x%02X 0x%02X 0x%02X 0x%02X", cc[0],
+          cc[1], cc[2], cc[3]);
+      RW_TRACE_DEBUG2(
+          "rw_i93_sm_detect_ndef (): Total blocks:0x%04X, Block size:0x%02X",
+          p_i93->num_block, p_i93->block_size);
+
+      if ((cc[0] == I93_ICODE_CC_MAGIC_NUMER) &&
+          ((cc[3] & I93_STM_CC_OVERFLOW_MASK) ||
+           (cc[2] * 8) == (p_i93->num_block * p_i93->block_size))) {
+        if ((cc[1] & I93_ICODE_CC_READ_ACCESS_MASK) ==
+            I93_ICODE_CC_READ_ACCESS_GRANTED) {
+          if ((cc[1] & I93_ICODE_CC_WRITE_ACCESS_MASK) !=
+              I93_ICODE_CC_WRITE_ACCESS_GRANTED) {
+            /* read-only or password required to write */
+            p_i93->intl_flags |= RW_I93_FLAG_READ_ONLY;
+          }
+          if (cc[3] & I93_ICODE_CC_MBREAD_MASK) {
+            /* tag supports read multi blocks command */
+            p_i93->intl_flags |= RW_I93_FLAG_READ_MULTI_BLOCK;
+          }
+          status = NFC_STATUS_OK;
+        }
+      }
+
+      if (status == NFC_STATUS_OK) {
+        /* seach NDEF TLV from offset 4 when CC file coded on 4 bytes NFC Forum
+         */
+        if (cc[2] != 0)
+          p_i93->rw_offset = 4;
+        else
+          p_i93->rw_offset = 8;
+
+        if (rw_i93_get_next_blocks(p_i93->rw_offset) == NFC_STATUS_OK) {
+          p_i93->sub_state = RW_I93_SUBSTATE_SEARCH_NDEF_TLV;
+          p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_TYPE;
+        } else {
+          rw_i93_handle_error(NFC_STATUS_FAILED);
+        }
+      } else {
+        rw_i93_handle_error(NFC_STATUS_FAILED);
+      }
+      break;
+
+    case RW_I93_SUBSTATE_SEARCH_NDEF_TLV:
+
+      /* search TLV within read blocks */
+      for (xx = 0; xx < length; xx++) {
+        /* if looking for type */
+        if (p_i93->tlv_detect_state == RW_I93_TLV_DETECT_STATE_TYPE) {
+          if (*(p + xx) == I93_ICODE_TLV_TYPE_NULL) {
+            continue;
+          } else if ((*(p + xx) == I93_ICODE_TLV_TYPE_NDEF) ||
+                     (*(p + xx) == I93_ICODE_TLV_TYPE_PROP)) {
+            /* store found type and get length field */
+            p_i93->tlv_type = *(p + xx);
+            p_i93->ndef_tlv_start_offset = p_i93->rw_offset + xx;
+
+            p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_LENGTH_1;
+          } else if (*(p + xx) == I93_ICODE_TLV_TYPE_TERM) {
+            /* no NDEF TLV found */
+            p_i93->tlv_type = I93_ICODE_TLV_TYPE_TERM;
+            break;
+          } else {
+            RW_TRACE_DEBUG1("Invalid type: 0x%02x", *(p + xx));
+            rw_i93_handle_error(NFC_STATUS_FAILED);
+            return;
+          }
+        } else if (p_i93->tlv_detect_state ==
+                   RW_I93_TLV_DETECT_STATE_LENGTH_1) {
+          /* if 3 bytes length field */
+          if (*(p + xx) == 0xFF) {
+            /* need 2 more bytes for length field */
+            p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_LENGTH_2;
+          } else {
+            p_i93->tlv_length = *(p + xx);
+            p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_VALUE;
+
+            if (p_i93->tlv_type == I93_ICODE_TLV_TYPE_NDEF) {
+              p_i93->ndef_tlv_last_offset =
+                  p_i93->ndef_tlv_start_offset + 1 + p_i93->tlv_length;
+              break;
+            }
+          }
+        } else if (p_i93->tlv_detect_state ==
+                   RW_I93_TLV_DETECT_STATE_LENGTH_2) {
+          /* the second byte of 3 bytes length field */
+          p_i93->tlv_length = *(p + xx);
+          p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_LENGTH_3;
+        } else if (p_i93->tlv_detect_state ==
+                   RW_I93_TLV_DETECT_STATE_LENGTH_3) {
+          /* the last byte of 3 bytes length field */
+          p_i93->tlv_length = (p_i93->tlv_length << 8) + *(p + xx);
+          p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_VALUE;
+
+          if (p_i93->tlv_type == I93_ICODE_TLV_TYPE_NDEF) {
+            p_i93->ndef_tlv_last_offset =
+                p_i93->ndef_tlv_start_offset + 3 + p_i93->tlv_length;
+            break;
+          }
+        } else if (p_i93->tlv_detect_state == RW_I93_TLV_DETECT_STATE_VALUE) {
+          /* this is other than NDEF TLV */
+          if (p_i93->tlv_length <= length - xx) {
+            /* skip value field */
+            xx += (uint8_t)p_i93->tlv_length;
+            p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_TYPE;
+          } else {
+            /* read more data */
+            p_i93->tlv_length -= (length - xx);
+            break;
+          }
+        }
+      }
+
+      /* found NDEF TLV and read length field */
+      if ((p_i93->tlv_type == I93_ICODE_TLV_TYPE_NDEF) &&
+          (p_i93->tlv_detect_state == RW_I93_TLV_DETECT_STATE_VALUE)) {
+        p_i93->ndef_length = p_i93->tlv_length;
+
+        /* get lock status to see if read-only */
+        if ((p_i93->product_version == RW_I93_TAG_IT_HF_I_STD_CHIP_INLAY) ||
+            (p_i93->product_version == RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY) ||
+            ((p_i93->uid[1] == I93_UID_IC_MFG_CODE_NXP) &&
+             (p_i93->ic_reference & I93_ICODE_IC_REF_MBREAD_MASK))) {
+          /* these doesn't support GetMultiBlockSecurityStatus */
+
+          p_i93->rw_offset = p_i93->ndef_tlv_start_offset;
+          first_block = p_i93->ndef_tlv_start_offset / p_i93->block_size;
+
+          /* read block to get lock status */
+          rw_i93_send_cmd_read_single_block(first_block, true);
+          p_i93->sub_state = RW_I93_SUBSTATE_CHECK_LOCK_STATUS;
+        } else {
+          /* block offset for read-only check */
+          p_i93->rw_offset = 0;
+
+          if (rw_i93_get_next_block_sec() == NFC_STATUS_OK) {
+            p_i93->sub_state = RW_I93_SUBSTATE_CHECK_LOCK_STATUS;
+          } else {
+            rw_i93_handle_error(NFC_STATUS_FAILED);
+          }
+        }
+      } else {
+        /* read more data */
+        p_i93->rw_offset += length;
+
+        if (p_i93->rw_offset >= p_i93->block_size * p_i93->num_block) {
+          rw_i93_handle_error(NFC_STATUS_FAILED);
+        } else if (rw_i93_get_next_blocks(p_i93->rw_offset) == NFC_STATUS_OK) {
+          p_i93->sub_state = RW_I93_SUBSTATE_SEARCH_NDEF_TLV;
+        } else {
+          rw_i93_handle_error(NFC_STATUS_FAILED);
+        }
+      }
+      break;
+
+    case RW_I93_SUBSTATE_CHECK_LOCK_STATUS:
+
+      if ((p_i93->product_version == RW_I93_TAG_IT_HF_I_STD_CHIP_INLAY) ||
+          (p_i93->product_version == RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY) ||
+          ((p_i93->uid[1] == I93_UID_IC_MFG_CODE_NXP) &&
+           (p_i93->ic_reference & I93_ICODE_IC_REF_MBREAD_MASK))) {
+        /* these doesn't support GetMultiBlockSecurityStatus */
+
+        block = (p_i93->rw_offset / p_i93->block_size);
+        last_block = (p_i93->ndef_tlv_last_offset / p_i93->block_size);
+
+        if ((*p) & I93_BLOCK_LOCKED) {
+          if (block <= last_block) {
+            p_i93->intl_flags |= RW_I93_FLAG_READ_ONLY;
+          }
+        } else {
+          /* if we need to check more user blocks */
+          if (block + 1 < p_i93->num_block) {
+            p_i93->rw_offset += p_i93->block_size;
+
+            /* read block to get lock status */
+            rw_i93_send_cmd_read_single_block(
+                (uint16_t)(p_i93->rw_offset / p_i93->block_size), true);
+            break;
+          }
+        }
+
+        p_i93->max_ndef_length =
+            p_i93->ndef_length
+            /* add available bytes including the last block of NDEF TLV */
+            + (p_i93->block_size * (block - last_block) + 1) -
+            (p_i93->ndef_tlv_last_offset % p_i93->block_size) - 1;
+      } else {
+        if (p_i93->rw_offset == 0) {
+          p_i93->max_ndef_length =
+              p_i93->ndef_length
+              /* add available bytes in the last block of NDEF TLV */
+              + p_i93->block_size -
+              (p_i93->ndef_tlv_last_offset % p_i93->block_size) - 1;
+
+          first_block = (p_i93->ndef_tlv_start_offset / p_i93->block_size);
+        } else {
+          first_block = 0;
+        }
+
+        last_block = (p_i93->ndef_tlv_last_offset / p_i93->block_size);
+        num_blocks = length;
+
+        for (block = first_block; block < num_blocks; block++) {
+          /* if any block of NDEF TLV is locked */
+          if ((block + p_i93->rw_offset) <= last_block) {
+            if (*(p + block) & I93_BLOCK_LOCKED) {
+              p_i93->intl_flags |= RW_I93_FLAG_READ_ONLY;
+              break;
+            }
+          } else {
+            if (*(p + block) & I93_BLOCK_LOCKED) {
+              /* no more consecutive unlocked block */
+              break;
+            } else {
+              /* add block size if not locked */
+              p_i93->max_ndef_length += p_i93->block_size;
+            }
+          }
+        }
+
+        /* update next security of block to check */
+        p_i93->rw_offset += num_blocks;
+
+        /* if need to check more */
+        if (p_i93->num_block > p_i93->rw_offset) {
+          if (rw_i93_get_next_block_sec() != NFC_STATUS_OK) {
+            rw_i93_handle_error(NFC_STATUS_FAILED);
+          }
+          break;
+        }
+      }
+
+      /* check if need to adjust max NDEF length */
+      if ((p_i93->ndef_length < 0xFF) && (p_i93->max_ndef_length >= 0xFF)) {
+        /* 3 bytes length field must be used */
+        p_i93->max_ndef_length -= 2;
+      }
+
+      rw_data.ndef.status = NFC_STATUS_OK;
+      rw_data.ndef.protocol = NFC_PROTOCOL_T5T;
+      rw_data.ndef.flags = 0;
+      rw_data.ndef.flags |= RW_NDEF_FL_SUPPORTED;
+      rw_data.ndef.flags |= RW_NDEF_FL_FORMATED;
+      rw_data.ndef.flags |= RW_NDEF_FL_FORMATABLE;
+      rw_data.ndef.cur_size = p_i93->ndef_length;
+
+      if (p_i93->intl_flags & RW_I93_FLAG_READ_ONLY) {
+        rw_data.ndef.flags |= RW_NDEF_FL_READ_ONLY;
+        rw_data.ndef.max_size = p_i93->ndef_length;
+      } else {
+        rw_data.ndef.flags |= RW_NDEF_FL_HARD_LOCKABLE;
+        rw_data.ndef.max_size = p_i93->max_ndef_length;
+      }
+
+      p_i93->state = RW_I93_STATE_IDLE;
+      p_i93->sent_cmd = 0;
+
+      RW_TRACE_DEBUG3("NDEF cur_size(%d),max_size (%d), flags (0x%x)",
+                      rw_data.ndef.cur_size, rw_data.ndef.max_size,
+                      rw_data.ndef.flags);
+
+      (*(rw_cb.p_cback))(RW_I93_NDEF_DETECT_EVT, &rw_data);
+      break;
+
+    default:
+      break;
+  }
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_sm_read_ndef
+**
+** Description      Process NDEF read procedure
+**
+** Returns          void
+**
+*******************************************************************************/
+void rw_i93_sm_read_ndef(NFC_HDR* p_resp) {
+  uint8_t* p = (uint8_t*)(p_resp + 1) + p_resp->offset;
+  uint8_t flags;
+  uint16_t offset, length = p_resp->len;
+  tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
+  tRW_DATA rw_data;
+
+  RW_TRACE_DEBUG0("rw_i93_sm_read_ndef ()");
+
+  STREAM_TO_UINT8(flags, p);
+  length--;
+
+  if (flags & I93_FLAG_ERROR_DETECTED) {
+    RW_TRACE_DEBUG1("Got error flags (0x%02x)", flags);
+    rw_i93_handle_error(NFC_STATUS_FAILED);
+    return;
+  }
+
+  /* if this is the first block */
+  if (p_i93->rw_length == 0) {
+    /* get start of NDEF in the first block */
+    offset = p_i93->ndef_tlv_start_offset % p_i93->block_size;
+
+    if (p_i93->ndef_length < 0xFF) {
+      offset += 2;
+    } else {
+      offset += 4;
+    }
+
+    /* adjust offset if read more blocks because the first block doesn't have
+     * NDEF */
+    offset -= (p_i93->rw_offset - p_i93->ndef_tlv_start_offset);
+  } else {
+    offset = 0;
+  }
+
+  /* if read enough data to skip type and length field for the beginning */
+  if (offset < length) {
+    offset++; /* flags */
+    p_resp->offset += offset;
+    p_resp->len -= offset;
+
+    rw_data.data.status = NFC_STATUS_OK;
+    rw_data.data.p_data = p_resp;
+
+    p_i93->rw_length += p_resp->len;
+  } else {
+    /* in case of no Ndef data included */
+    p_resp->len = 0;
+  }
+
+  /* if read all of NDEF data */
+  if (p_i93->rw_length >= p_i93->ndef_length) {
+    /* remove extra btyes in the last block */
+    p_resp->len -= (p_i93->rw_length - p_i93->ndef_length);
+
+    p_i93->state = RW_I93_STATE_IDLE;
+    p_i93->sent_cmd = 0;
+
+    RW_TRACE_DEBUG2("NDEF read complete read (%d)/total (%d)", p_resp->len,
+                    p_i93->ndef_length);
+
+    (*(rw_cb.p_cback))(RW_I93_NDEF_READ_CPLT_EVT, &rw_data);
+  } else {
+    RW_TRACE_DEBUG2("NDEF read segment read (%d)/total (%d)", p_resp->len,
+                    p_i93->ndef_length);
+
+    if (p_resp->len > 0) {
+      (*(rw_cb.p_cback))(RW_I93_NDEF_READ_EVT, &rw_data);
+    }
+
+    /* this will make read data from next block */
+    p_i93->rw_offset += length;
+
+    if (rw_i93_get_next_blocks(p_i93->rw_offset) != NFC_STATUS_OK) {
+      rw_i93_handle_error(NFC_STATUS_FAILED);
+    }
+  }
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_sm_update_ndef
+**
+** Description      Process NDEF update procedure
+**
+**                  1. Set length field to zero
+**                  2. Write NDEF and Terminator TLV
+**                  3. Set length field to NDEF length
+**
+** Returns          void
+**
+*******************************************************************************/
+void rw_i93_sm_update_ndef(NFC_HDR* p_resp) {
+  uint8_t* p = (uint8_t*)(p_resp + 1) + p_resp->offset;
+  uint8_t flags, xx, length_offset, buff[I93_MAX_BLOCK_LENGH];
+  uint16_t length = p_resp->len, block_number;
+  tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
+  tRW_DATA rw_data;
+
+#if (BT_TRACE_VERBOSE == TRUE)
+  RW_TRACE_DEBUG2("rw_i93_sm_update_ndef () sub_state:%s (0x%x)",
+                  rw_i93_get_sub_state_name(p_i93->sub_state).c_str(),
+                  p_i93->sub_state);
+#else
+  RW_TRACE_DEBUG1("rw_i93_sm_update_ndef () sub_state:0x%x", p_i93->sub_state);
+#endif
+
+  STREAM_TO_UINT8(flags, p);
+  length--;
+
+  if (flags & I93_FLAG_ERROR_DETECTED) {
+    if (((p_i93->product_version == RW_I93_TAG_IT_HF_I_PLUS_INLAY) ||
+         (p_i93->product_version == RW_I93_TAG_IT_HF_I_PLUS_CHIP) ||
+         (p_i93->product_version == RW_I93_TAG_IT_HF_I_STD_CHIP_INLAY) ||
+         (p_i93->product_version == RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY)) &&
+        (*p == I93_ERROR_CODE_BLOCK_FAIL_TO_WRITE)) {
+      /* ignore error */
+    } else {
+      RW_TRACE_DEBUG1("Got error flags (0x%02x)", flags);
+      rw_i93_handle_error(NFC_STATUS_FAILED);
+      return;
+    }
+  }
+
+  switch (p_i93->sub_state) {
+    case RW_I93_SUBSTATE_RESET_LEN:
+
+      /* get offset of length field */
+      length_offset = (p_i93->ndef_tlv_start_offset + 1) % p_i93->block_size;
+
+      /* set length to zero */
+      *(p + length_offset) = 0x00;
+
+      if (p_i93->ndef_length > 0) {
+        /* if 3 bytes length field is needed */
+        if (p_i93->ndef_length >= 0xFF) {
+          xx = length_offset + 3;
+        } else {
+          xx = length_offset + 1;
+        }
+
+        /* write the first part of NDEF in the same block */
+        for (; xx < p_i93->block_size; xx++) {
+          if (p_i93->rw_length < p_i93->ndef_length) {
+            *(p + xx) = *(p_i93->p_update_data + p_i93->rw_length++);
+          } else {
+            *(p + xx) = I93_ICODE_TLV_TYPE_NULL;
+          }
+        }
+      }
+
+      block_number = (p_i93->ndef_tlv_start_offset + 1) / p_i93->block_size;
+
+      if (rw_i93_send_cmd_write_single_block(block_number, p) ==
+          NFC_STATUS_OK) {
+        /* update next writing offset */
+        p_i93->rw_offset = (block_number + 1) * p_i93->block_size;
+        p_i93->sub_state = RW_I93_SUBSTATE_WRITE_NDEF;
+      } else {
+        rw_i93_handle_error(NFC_STATUS_FAILED);
+      }
+      break;
+
+    case RW_I93_SUBSTATE_WRITE_NDEF:
+
+      /* if it's not the end of tag memory */
+      if (p_i93->rw_offset < p_i93->block_size * p_i93->num_block) {
+        block_number = p_i93->rw_offset / p_i93->block_size;
+
+        /* if we have more data to write */
+        if (p_i93->rw_length < p_i93->ndef_length) {
+          p = p_i93->p_update_data + p_i93->rw_length;
+
+          p_i93->rw_offset += p_i93->block_size;
+          p_i93->rw_length += p_i93->block_size;
+
+          /* if this is the last block of NDEF TLV */
+          if (p_i93->rw_length > p_i93->ndef_length) {
+            /* length of NDEF TLV in the block */
+            xx = (uint8_t)(p_i93->block_size -
+                           (p_i93->rw_length - p_i93->ndef_length));
+
+            /* set NULL TLV in the unused part of block */
+            memset(buff, I93_ICODE_TLV_TYPE_NULL, p_i93->block_size);
+            memcpy(buff, p, xx);
+            p = buff;
+
+            /* if it's the end of tag memory */
+            if ((p_i93->rw_offset >= p_i93->block_size * p_i93->num_block) &&
+                (xx < p_i93->block_size)) {
+              buff[xx] = I93_ICODE_TLV_TYPE_TERM;
+            }
+
+            p_i93->ndef_tlv_last_offset =
+                p_i93->rw_offset - p_i93->block_size + xx - 1;
+          }
+
+          if (rw_i93_send_cmd_write_single_block(block_number, p) !=
+              NFC_STATUS_OK) {
+            rw_i93_handle_error(NFC_STATUS_FAILED);
+          }
+        } else {
+          /* if this is the very next block of NDEF TLV */
+          if (block_number ==
+              (p_i93->ndef_tlv_last_offset / p_i93->block_size) + 1) {
+            p_i93->rw_offset += p_i93->block_size;
+
+            /* write Terminator TLV and NULL TLV */
+            memset(buff, I93_ICODE_TLV_TYPE_NULL, p_i93->block_size);
+            buff[0] = I93_ICODE_TLV_TYPE_TERM;
+            p = buff;
+
+            if (rw_i93_send_cmd_write_single_block(block_number, p) !=
+                NFC_STATUS_OK) {
+              rw_i93_handle_error(NFC_STATUS_FAILED);
+            }
+          } else {
+            /* finished writing NDEF and Terminator TLV */
+            /* read length field to update length       */
+            block_number =
+                (p_i93->ndef_tlv_start_offset + 1) / p_i93->block_size;
+
+            if (rw_i93_send_cmd_read_single_block(block_number, false) ==
+                NFC_STATUS_OK) {
+              /* set offset to length field */
+              p_i93->rw_offset = p_i93->ndef_tlv_start_offset + 1;
+
+              /* get size of length field */
+              if (p_i93->ndef_length >= 0xFF) {
+                p_i93->rw_length = 3;
+              } else if (p_i93->ndef_length > 0) {
+                p_i93->rw_length = 1;
+              } else {
+                p_i93->rw_length = 0;
+              }
+
+              p_i93->sub_state = RW_I93_SUBSTATE_UPDATE_LEN;
+            } else {
+              rw_i93_handle_error(NFC_STATUS_FAILED);
+            }
+          }
+        }
+      } else {
+        /* if we have no more data to write */
+        if (p_i93->rw_length >= p_i93->ndef_length) {
+          /* finished writing NDEF and Terminator TLV */
+          /* read length field to update length       */
+          block_number = (p_i93->ndef_tlv_start_offset + 1) / p_i93->block_size;
+
+          if (rw_i93_send_cmd_read_single_block(block_number, false) ==
+              NFC_STATUS_OK) {
+            /* set offset to length field */
+            p_i93->rw_offset = p_i93->ndef_tlv_start_offset + 1;
+
+            /* get size of length field */
+            if (p_i93->ndef_length >= 0xFF) {
+              p_i93->rw_length = 3;
+            } else if (p_i93->ndef_length > 0) {
+              p_i93->rw_length = 1;
+            } else {
+              p_i93->rw_length = 0;
+            }
+
+            p_i93->sub_state = RW_I93_SUBSTATE_UPDATE_LEN;
+            break;
+          }
+        }
+        rw_i93_handle_error(NFC_STATUS_FAILED);
+      }
+      break;
+
+    case RW_I93_SUBSTATE_UPDATE_LEN:
+
+      /* if we have more length field to write */
+      if (p_i93->rw_length > 0) {
+        /* if we got ack for writing, read next block to update rest of length
+         * field */
+        if (length == 0) {
+          block_number = p_i93->rw_offset / p_i93->block_size;
+
+          if (rw_i93_send_cmd_read_single_block(block_number, false) !=
+              NFC_STATUS_OK) {
+            rw_i93_handle_error(NFC_STATUS_FAILED);
+          }
+        } else {
+          length_offset = p_i93->rw_offset % p_i93->block_size;
+
+          /* update length field within the read block */
+          for (xx = length_offset; xx < p_i93->block_size; xx++) {
+            if (p_i93->rw_length == 3)
+              *(p + xx) = 0xFF;
+            else if (p_i93->rw_length == 2)
+              *(p + xx) = (uint8_t)((p_i93->ndef_length >> 8) & 0xFF);
+            else if (p_i93->rw_length == 1)
+              *(p + xx) = (uint8_t)(p_i93->ndef_length & 0xFF);
+
+            p_i93->rw_length--;
+            if (p_i93->rw_length == 0) break;
+          }
+
+          block_number = (p_i93->rw_offset / p_i93->block_size);
+
+          if (rw_i93_send_cmd_write_single_block(block_number, p) ==
+              NFC_STATUS_OK) {
+            /* set offset to the beginning of next block */
+            p_i93->rw_offset +=
+                p_i93->block_size - (p_i93->rw_offset % p_i93->block_size);
+          } else {
+            rw_i93_handle_error(NFC_STATUS_FAILED);
+          }
+        }
+      } else {
+        RW_TRACE_DEBUG3("NDEF update complete, %d bytes, (%d-%d)",
+                        p_i93->ndef_length, p_i93->ndef_tlv_start_offset,
+                        p_i93->ndef_tlv_last_offset);
+
+        p_i93->state = RW_I93_STATE_IDLE;
+        p_i93->sent_cmd = 0;
+        p_i93->p_update_data = NULL;
+
+        rw_data.status = NFC_STATUS_OK;
+        (*(rw_cb.p_cback))(RW_I93_NDEF_UPDATE_CPLT_EVT, &rw_data);
+      }
+      break;
+
+    default:
+      break;
+  }
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_sm_format
+**
+** Description      Process format procedure
+**
+**                  1. Get UID
+**                  2. Get sys info for memory size (reset AFI/DSFID)
+**                  3. Get block status to get read-only status
+**                  4. Write CC and empty NDEF
+**
+** Returns          void
+**
+*******************************************************************************/
+void rw_i93_sm_format(NFC_HDR* p_resp) {
+  uint8_t *p = (uint8_t*)(p_resp + 1) + p_resp->offset, *p_uid;
+  uint8_t flags;
+  uint16_t length = p_resp->len, xx, block_number;
+  tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
+  tRW_DATA rw_data;
+  tNFC_STATUS status = NFC_STATUS_FAILED;
+
+#if (BT_TRACE_VERBOSE == TRUE)
+  RW_TRACE_DEBUG2("rw_i93_sm_format () sub_state:%s (0x%x)",
+                  rw_i93_get_sub_state_name(p_i93->sub_state).c_str(),
+                  p_i93->sub_state);
+#else
+  RW_TRACE_DEBUG1("rw_i93_sm_format () sub_state:0x%x", p_i93->sub_state);
+#endif
+
+  STREAM_TO_UINT8(flags, p);
+  length--;
+
+  if (flags & I93_FLAG_ERROR_DETECTED) {
+    if (((p_i93->product_version == RW_I93_TAG_IT_HF_I_PLUS_INLAY) ||
+         (p_i93->product_version == RW_I93_TAG_IT_HF_I_PLUS_CHIP) ||
+         (p_i93->product_version == RW_I93_TAG_IT_HF_I_STD_CHIP_INLAY) ||
+         (p_i93->product_version == RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY)) &&
+        (*p == I93_ERROR_CODE_BLOCK_FAIL_TO_WRITE)) {
+      /* ignore error */
+    } else if ((length) && (rw_i93_check_sys_info_prot_ext(*p))) {
+      /* getting system info with protocol extension flag */
+      /* This STM tag supports more than 2040 bytes */
+      p_i93->intl_flags |= RW_I93_FLAG_16BIT_NUM_BLOCK;
+      return;
+    } else {
+      RW_TRACE_DEBUG1("Got error flags (0x%02x)", flags);
+      rw_i93_handle_error(NFC_STATUS_FAILED);
+      return;
+    }
+  }
+
+  switch (p_i93->sub_state) {
+    case RW_I93_SUBSTATE_WAIT_UID:
+
+      p++; /* skip DSFID */
+      p_uid = p_i93->uid;
+      STREAM_TO_ARRAY8(p_uid, p); /* store UID */
+
+      /* get system information to get memory size */
+      if (rw_i93_send_cmd_get_sys_info(NULL, I93_FLAG_PROT_EXT_NO) ==
+          NFC_STATUS_OK) {
+        p_i93->sub_state = RW_I93_SUBSTATE_WAIT_SYS_INFO;
+      } else {
+        rw_i93_handle_error(NFC_STATUS_FAILED);
+      }
+      break;
+
+    case RW_I93_SUBSTATE_WAIT_SYS_INFO:
+
+      p_i93->block_size = 0;
+      p_i93->num_block = 0;
+
+      if (!rw_i93_process_sys_info(p)) {
+        /* retrying with protocol extension flag */
+        break;
+      }
+
+      if (p_i93->info_flags & I93_INFO_FLAG_DSFID) {
+        /* DSFID, if any DSFID then reset */
+        if (p_i93->dsfid != I93_DFS_UNSUPPORTED) {
+          p_i93->intl_flags |= RW_I93_FLAG_RESET_DSFID;
+        }
+      }
+      if (p_i93->info_flags & I93_INFO_FLAG_AFI) {
+        /* AFI, reset to 0 */
+        if (p_i93->afi != 0x00) {
+          p_i93->intl_flags |= RW_I93_FLAG_RESET_AFI;
+        }
+      }
+
+      if ((p_i93->block_size == 0) || (p_i93->num_block == 0)) {
+        RW_TRACE_DEBUG0("Unable to get tag memory size");
+        rw_i93_handle_error(status);
+      } else if (p_i93->intl_flags & RW_I93_FLAG_RESET_DSFID) {
+        if (rw_i93_send_cmd_write_dsfid(I93_DFS_UNSUPPORTED) == NFC_STATUS_OK) {
+          p_i93->sub_state = RW_I93_SUBSTATE_WAIT_RESET_DSFID_AFI;
+        } else {
+          rw_i93_handle_error(NFC_STATUS_FAILED);
+        }
+      } else if (p_i93->intl_flags & RW_I93_FLAG_RESET_AFI) {
+        if (rw_i93_send_cmd_write_afi(0x00) == NFC_STATUS_OK) {
+          p_i93->sub_state = RW_I93_SUBSTATE_WAIT_RESET_DSFID_AFI;
+        } else {
+          rw_i93_handle_error(NFC_STATUS_FAILED);
+        }
+      } else {
+        /* get lock status to see if read-only */
+        if ((p_i93->uid[1] == I93_UID_IC_MFG_CODE_NXP) &&
+            (p_i93->ic_reference & I93_ICODE_IC_REF_MBREAD_MASK)) {
+          /* these doesn't support GetMultiBlockSecurityStatus */
+
+          rw_cb.tcb.i93.rw_offset = 0;
+
+          /* read blocks with option flag to get block security status */
+          if (rw_i93_send_cmd_read_single_block(0x0000, true) ==
+              NFC_STATUS_OK) {
+            p_i93->sub_state = RW_I93_SUBSTATE_CHECK_READ_ONLY;
+          } else {
+            rw_i93_handle_error(NFC_STATUS_FAILED);
+          }
+        } else {
+          /* block offset for read-only check */
+          p_i93->rw_offset = 0;
+
+          if (rw_i93_get_next_block_sec() == NFC_STATUS_OK) {
+            p_i93->sub_state = RW_I93_SUBSTATE_CHECK_READ_ONLY;
+          } else {
+            rw_i93_handle_error(NFC_STATUS_FAILED);
+          }
+        }
+      }
+
+      break;
+
+    case RW_I93_SUBSTATE_WAIT_RESET_DSFID_AFI:
+
+      if (p_i93->sent_cmd == I93_CMD_WRITE_DSFID) {
+        p_i93->intl_flags &= ~RW_I93_FLAG_RESET_DSFID;
+      } else if (p_i93->sent_cmd == I93_CMD_WRITE_AFI) {
+        p_i93->intl_flags &= ~RW_I93_FLAG_RESET_AFI;
+      }
+
+      if (p_i93->intl_flags & RW_I93_FLAG_RESET_DSFID) {
+        if (rw_i93_send_cmd_write_dsfid(I93_DFS_UNSUPPORTED) == NFC_STATUS_OK) {
+          p_i93->sub_state = RW_I93_SUBSTATE_WAIT_RESET_DSFID_AFI;
+        } else {
+          rw_i93_handle_error(NFC_STATUS_FAILED);
+        }
+      } else if (p_i93->intl_flags & RW_I93_FLAG_RESET_AFI) {
+        if (rw_i93_send_cmd_write_afi(0x00) == NFC_STATUS_OK) {
+          p_i93->sub_state = RW_I93_SUBSTATE_WAIT_RESET_DSFID_AFI;
+        } else {
+          rw_i93_handle_error(NFC_STATUS_FAILED);
+        }
+      } else {
+        /* get lock status to see if read-only */
+        if ((p_i93->uid[1] == I93_UID_IC_MFG_CODE_NXP) &&
+            (p_i93->ic_reference & I93_ICODE_IC_REF_MBREAD_MASK)) {
+          /* these doesn't support GetMultiBlockSecurityStatus */
+
+          rw_cb.tcb.i93.rw_offset = 0;
+
+          /* read blocks with option flag to get block security status */
+          if (rw_i93_send_cmd_read_single_block(0x0000, true) ==
+              NFC_STATUS_OK) {
+            p_i93->sub_state = RW_I93_SUBSTATE_CHECK_READ_ONLY;
+          } else {
+            rw_i93_handle_error(NFC_STATUS_FAILED);
+          }
+        } else {
+          /* block offset for read-only check */
+          p_i93->rw_offset = 0;
+
+          if (rw_i93_get_next_block_sec() == NFC_STATUS_OK) {
+            p_i93->sub_state = RW_I93_SUBSTATE_CHECK_READ_ONLY;
+          } else {
+            rw_i93_handle_error(NFC_STATUS_FAILED);
+          }
+        }
+      }
+      break;
+
+    case RW_I93_SUBSTATE_CHECK_READ_ONLY:
+
+      if ((p_i93->product_version == RW_I93_TAG_IT_HF_I_STD_CHIP_INLAY) ||
+          (p_i93->product_version == RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY) ||
+          ((p_i93->uid[1] == I93_UID_IC_MFG_CODE_NXP) &&
+           (p_i93->ic_reference & I93_ICODE_IC_REF_MBREAD_MASK))) {
+        if ((*p) & I93_BLOCK_LOCKED) {
+          rw_i93_handle_error(NFC_STATUS_FAILED);
+          break;
+        }
+
+        /* if we checked all of user blocks */
+        if ((p_i93->rw_offset / p_i93->block_size) + 1 == p_i93->num_block) {
+          if ((p_i93->product_version == RW_I93_TAG_IT_HF_I_STD_CHIP_INLAY) ||
+              (p_i93->product_version == RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY)) {
+            /* read the block which has AFI */
+            p_i93->rw_offset = I93_TAG_IT_HF_I_STD_PRO_CHIP_INLAY_AFI_LOCATION;
+            rw_i93_send_cmd_read_single_block(
+                (uint16_t)(p_i93->rw_offset / p_i93->block_size), true);
+            break;
+          }
+        } else if (p_i93->rw_offset ==
+                   I93_TAG_IT_HF_I_STD_PRO_CHIP_INLAY_AFI_LOCATION) {
+          /* no block is locked */
+        } else {
+          p_i93->rw_offset += p_i93->block_size;
+          rw_i93_send_cmd_read_single_block(
+              (uint16_t)(p_i93->rw_offset / p_i93->block_size), true);
+          break;
+        }
+      } else {
+        /* if any block is locked, we cannot format it */
+        for (xx = 0; xx < length; xx++) {
+          if (*(p + xx) & I93_BLOCK_LOCKED) {
+            rw_i93_handle_error(NFC_STATUS_FAILED);
+            break;
+          }
+        }
+
+        /* update block offset for read-only check */
+        p_i93->rw_offset += length;
+
+        /* if need to get more lock status of blocks */
+        if (p_i93->num_block > p_i93->rw_offset) {
+          if (rw_i93_get_next_block_sec() != NFC_STATUS_OK) {
+            rw_i93_handle_error(NFC_STATUS_FAILED);
+          }
+          break;
+        }
+      }
+
+      /* get buffer to store CC, zero length NDEF TLV and Terminator TLV */
+      p_i93->p_update_data = (uint8_t*)GKI_getbuf(RW_I93_FORMAT_DATA_LEN);
+
+      if (!p_i93->p_update_data) {
+        RW_TRACE_ERROR0("rw_i93_sm_format (): Cannot allocate buffer");
+        rw_i93_handle_error(NFC_STATUS_FAILED);
+        break;
+      }
+
+      p = p_i93->p_update_data;
+
+      /* Capability Container */
+      *(p++) = I93_ICODE_CC_MAGIC_NUMER; /* magic number */
+      *(p++) = 0x40;                     /* version 1.0, read/write */
+
+      /* if memory size is less than 2048 bytes */
+      if (((p_i93->num_block * p_i93->block_size) / 8) < 0x100)
+        *(p++) = (uint8_t)((p_i93->num_block * p_i93->block_size) /
+                           8); /* memory size */
+      else
+        *(p++) = 0xFF;
+
+      if ((p_i93->product_version == RW_I93_ICODE_SLI) ||
+          (p_i93->product_version == RW_I93_ICODE_SLI_S) ||
+          (p_i93->product_version == RW_I93_ICODE_SLI_L)) {
+        if (p_i93->ic_reference & I93_ICODE_IC_REF_MBREAD_MASK)
+          *(p++) = I93_ICODE_CC_IPREAD_MASK; /* IPREAD */
+        else
+          *(p++) = I93_ICODE_CC_MBREAD_MASK; /* MBREAD, read multi block command
+                                                supported */
+      } else if ((p_i93->product_version == RW_I93_TAG_IT_HF_I_PLUS_INLAY) ||
+                 (p_i93->product_version == RW_I93_TAG_IT_HF_I_PLUS_CHIP)) {
+        *(p++) = I93_ICODE_CC_MBREAD_MASK; /* MBREAD, read multi block command
+                                              supported */
+      } else if ((p_i93->product_version ==
+                  RW_I93_TAG_IT_HF_I_STD_CHIP_INLAY) ||
+                 (p_i93->product_version ==
+                  RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY)) {
+        *(p++) = 0;
+      } else {
+        /* STM except LRIS2K, Broadcom supports read multi block command */
+
+        /* if memory size is more than 2040 bytes (which is not LRIS2K) */
+        if (((p_i93->num_block * p_i93->block_size) / 8) > 0xFF)
+          *(p++) = (I93_ICODE_CC_MBREAD_MASK | I93_STM_CC_OVERFLOW_MASK);
+        else if (p_i93->product_version == RW_I93_STM_LRIS2K)
+          *(p++) = 0x00;
+        else
+          *(p++) = I93_ICODE_CC_MBREAD_MASK;
+      }
+
+      /* zero length NDEF and Terminator TLV */
+      *(p++) = I93_ICODE_TLV_TYPE_NDEF;
+      *(p++) = 0x00;
+      *(p++) = I93_ICODE_TLV_TYPE_TERM;
+      *(p++) = I93_ICODE_TLV_TYPE_NULL;
+
+      /* start from block 0 */
+      p_i93->rw_offset = 0;
+
+      if (rw_i93_send_cmd_write_single_block(0, p_i93->p_update_data) ==
+          NFC_STATUS_OK) {
+        p_i93->sub_state = RW_I93_SUBSTATE_WRITE_CC_NDEF_TLV;
+        p_i93->rw_offset += p_i93->block_size;
+      } else {
+        rw_i93_handle_error(NFC_STATUS_FAILED);
+      }
+      break;
+
+    case RW_I93_SUBSTATE_WRITE_CC_NDEF_TLV:
+
+      /* if we have more data to write */
+      if (p_i93->rw_offset < RW_I93_FORMAT_DATA_LEN) {
+        block_number = (p_i93->rw_offset / p_i93->block_size);
+        p = p_i93->p_update_data + p_i93->rw_offset;
+
+        if (rw_i93_send_cmd_write_single_block(block_number, p) ==
+            NFC_STATUS_OK) {
+          p_i93->sub_state = RW_I93_SUBSTATE_WRITE_CC_NDEF_TLV;
+          p_i93->rw_offset += p_i93->block_size;
+        } else {
+          rw_i93_handle_error(NFC_STATUS_FAILED);
+        }
+      } else {
+        GKI_freebuf(p_i93->p_update_data);
+        p_i93->p_update_data = NULL;
+
+        p_i93->state = RW_I93_STATE_IDLE;
+        p_i93->sent_cmd = 0;
+
+        rw_data.status = NFC_STATUS_OK;
+        (*(rw_cb.p_cback))(RW_I93_FORMAT_CPLT_EVT, &rw_data);
+      }
+      break;
+
+    default:
+      break;
+  }
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_sm_set_read_only
+**
+** Description      Process read-only procedure
+**
+**                  1. Update CC as read-only
+**                  2. Lock all block of NDEF TLV
+**                  3. Lock block of CC
+**
+** Returns          void
+**
+*******************************************************************************/
+void rw_i93_sm_set_read_only(NFC_HDR* p_resp) {
+  uint8_t* p = (uint8_t*)(p_resp + 1) + p_resp->offset;
+  uint8_t flags, block_number;
+  uint16_t length = p_resp->len;
+  tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
+  tRW_DATA rw_data;
+
+#if (BT_TRACE_VERBOSE == TRUE)
+  RW_TRACE_DEBUG2("rw_i93_sm_set_read_only () sub_state:%s (0x%x)",
+                  rw_i93_get_sub_state_name(p_i93->sub_state).c_str(),
+                  p_i93->sub_state);
+#else
+  RW_TRACE_DEBUG1("rw_i93_sm_set_read_only () sub_state:0x%x",
+                  p_i93->sub_state);
+#endif
+
+  STREAM_TO_UINT8(flags, p);
+  length--;
+
+  if (flags & I93_FLAG_ERROR_DETECTED) {
+    if (((p_i93->product_version == RW_I93_TAG_IT_HF_I_PLUS_INLAY) ||
+         (p_i93->product_version == RW_I93_TAG_IT_HF_I_PLUS_CHIP) ||
+         (p_i93->product_version == RW_I93_TAG_IT_HF_I_STD_CHIP_INLAY) ||
+         (p_i93->product_version == RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY)) &&
+        (*p == I93_ERROR_CODE_BLOCK_FAIL_TO_WRITE)) {
+      /* ignore error */
+    } else {
+      RW_TRACE_DEBUG1("Got error flags (0x%02x)", flags);
+      rw_i93_handle_error(NFC_STATUS_FAILED);
+      return;
+    }
+  }
+
+  switch (p_i93->sub_state) {
+    case RW_I93_SUBSTATE_WAIT_CC:
+
+      /* mark CC as read-only */
+      *(p + 1) |= I93_ICODE_CC_READ_ONLY;
+
+      if (rw_i93_send_cmd_write_single_block(0, p) == NFC_STATUS_OK) {
+        p_i93->sub_state = RW_I93_SUBSTATE_WAIT_UPDATE_CC;
+      } else {
+        rw_i93_handle_error(NFC_STATUS_FAILED);
+      }
+      break;
+
+    case RW_I93_SUBSTATE_WAIT_UPDATE_CC:
+
+      /* successfully write CC then lock all blocks of NDEF TLV */
+      p_i93->rw_offset = p_i93->ndef_tlv_start_offset;
+      block_number = (uint8_t)(p_i93->rw_offset / p_i93->block_size);
+
+      if (rw_i93_send_cmd_lock_block(block_number) == NFC_STATUS_OK) {
+        p_i93->rw_offset += p_i93->block_size;
+        p_i93->sub_state = RW_I93_SUBSTATE_LOCK_NDEF_TLV;
+      } else {
+        rw_i93_handle_error(NFC_STATUS_FAILED);
+      }
+      break;
+
+    case RW_I93_SUBSTATE_LOCK_NDEF_TLV:
+
+      /* if we need to lock more blocks */
+      if (p_i93->rw_offset < p_i93->ndef_tlv_last_offset) {
+        /* get the next block of NDEF TLV */
+        block_number = (uint8_t)(p_i93->rw_offset / p_i93->block_size);
+
+        if (rw_i93_send_cmd_lock_block(block_number) == NFC_STATUS_OK) {
+          p_i93->rw_offset += p_i93->block_size;
+        } else {
+          rw_i93_handle_error(NFC_STATUS_FAILED);
+        }
+      }
+      /* if the first block of NDEF TLV is different from block of CC */
+      else if (p_i93->ndef_tlv_start_offset / p_i93->block_size != 0) {
+        /* lock block of CC */
+        if (rw_i93_send_cmd_lock_block(0) == NFC_STATUS_OK) {
+          p_i93->sub_state = RW_I93_SUBSTATE_WAIT_LOCK_CC;
+        } else {
+          rw_i93_handle_error(NFC_STATUS_FAILED);
+        }
+      } else {
+        p_i93->intl_flags |= RW_I93_FLAG_READ_ONLY;
+        p_i93->state = RW_I93_STATE_IDLE;
+        p_i93->sent_cmd = 0;
+
+        rw_data.status = NFC_STATUS_OK;
+        (*(rw_cb.p_cback))(RW_I93_SET_TAG_RO_EVT, &rw_data);
+      }
+      break;
+
+    case RW_I93_SUBSTATE_WAIT_LOCK_CC:
+
+      p_i93->intl_flags |= RW_I93_FLAG_READ_ONLY;
+      p_i93->state = RW_I93_STATE_IDLE;
+      p_i93->sent_cmd = 0;
+
+      rw_data.status = NFC_STATUS_OK;
+      (*(rw_cb.p_cback))(RW_I93_SET_TAG_RO_EVT, &rw_data);
+      break;
+
+    default:
+      break;
+  }
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_handle_error
+**
+** Description      notify error to application and clean up
+**
+** Returns          none
+**
+*******************************************************************************/
+void rw_i93_handle_error(tNFC_STATUS status) {
+  tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
+  tRW_DATA rw_data;
+  tRW_EVENT event;
+
+  RW_TRACE_DEBUG2("rw_i93_handle_error (): status:0x%02X, state:0x%X", status,
+                  p_i93->state);
+
+  nfc_stop_quick_timer(&p_i93->timer);
+
+  if (rw_cb.p_cback) {
+    rw_data.status = status;
+
+    switch (p_i93->state) {
+      case RW_I93_STATE_IDLE: /* in case of RawFrame */
+        event = RW_I93_INTF_ERROR_EVT;
+        break;
+
+      case RW_I93_STATE_BUSY:
+        if (p_i93->sent_cmd == I93_CMD_STAY_QUIET) {
+          /* There is no response to Stay Quiet command */
+          rw_data.i93_cmd_cmpl.status = NFC_STATUS_OK;
+          rw_data.i93_cmd_cmpl.command = I93_CMD_STAY_QUIET;
+          rw_data.i93_cmd_cmpl.error_code = 0;
+          event = RW_I93_CMD_CMPL_EVT;
+        } else {
+          event = RW_I93_INTF_ERROR_EVT;
+        }
+        break;
+
+      case RW_I93_STATE_DETECT_NDEF:
+        rw_data.ndef.protocol = NFC_PROTOCOL_T5T;
+        rw_data.ndef.cur_size = 0;
+        rw_data.ndef.max_size = 0;
+        rw_data.ndef.flags = 0;
+        rw_data.ndef.flags |= RW_NDEF_FL_FORMATABLE;
+        rw_data.ndef.flags |= RW_NDEF_FL_UNKNOWN;
+        event = RW_I93_NDEF_DETECT_EVT;
+        break;
+
+      case RW_I93_STATE_READ_NDEF:
+        event = RW_I93_NDEF_READ_FAIL_EVT;
+        break;
+
+      case RW_I93_STATE_UPDATE_NDEF:
+        p_i93->p_update_data = NULL;
+        event = RW_I93_NDEF_UPDATE_FAIL_EVT;
+        break;
+
+      case RW_I93_STATE_FORMAT:
+        if (p_i93->p_update_data) {
+          GKI_freebuf(p_i93->p_update_data);
+          p_i93->p_update_data = NULL;
+        }
+        event = RW_I93_FORMAT_CPLT_EVT;
+        break;
+
+      case RW_I93_STATE_SET_READ_ONLY:
+        event = RW_I93_SET_TAG_RO_EVT;
+        break;
+
+      case RW_I93_STATE_PRESENCE_CHECK:
+        event = RW_I93_PRESENCE_CHECK_EVT;
+        break;
+
+      default:
+        event = RW_I93_MAX_EVT;
+        break;
+    }
+
+    p_i93->state = RW_I93_STATE_IDLE;
+    p_i93->sent_cmd = 0;
+
+    if (event != RW_I93_MAX_EVT) {
+      (*(rw_cb.p_cback))(event, &rw_data);
+    }
+  } else {
+    p_i93->state = RW_I93_STATE_IDLE;
+  }
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_process_timeout
+**
+** Description      process timeout event
+**
+** Returns          none
+**
+*******************************************************************************/
+void rw_i93_process_timeout(TIMER_LIST_ENT* p_tle) {
+  NFC_HDR* p_buf;
+
+  RW_TRACE_DEBUG1("rw_i93_process_timeout () event=%d", p_tle->event);
+
+  if (p_tle->event == NFC_TTYPE_RW_I93_RESPONSE) {
+    if ((rw_cb.tcb.i93.retry_count < RW_MAX_RETRIES) &&
+        (rw_cb.tcb.i93.p_retry_cmd) &&
+        (rw_cb.tcb.i93.sent_cmd != I93_CMD_STAY_QUIET)) {
+      rw_cb.tcb.i93.retry_count++;
+      RW_TRACE_ERROR1("rw_i93_process_timeout (): retry_count = %d",
+                      rw_cb.tcb.i93.retry_count);
+
+      p_buf = rw_cb.tcb.i93.p_retry_cmd;
+      rw_cb.tcb.i93.p_retry_cmd = NULL;
+
+      if (rw_i93_send_to_lower(p_buf)) {
+        return;
+      }
+    }
+
+    /* all retrial is done or failed to send command to lower layer */
+    if (rw_cb.tcb.i93.p_retry_cmd) {
+      GKI_freebuf(rw_cb.tcb.i93.p_retry_cmd);
+      rw_cb.tcb.i93.p_retry_cmd = NULL;
+      rw_cb.tcb.i93.retry_count = 0;
+    }
+    rw_i93_handle_error(NFC_STATUS_TIMEOUT);
+  } else {
+    RW_TRACE_ERROR1("rw_i93_process_timeout () unknown event=%d", p_tle->event);
+  }
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_data_cback
+**
+** Description      This callback function receives the data from NFCC.
+**
+** Returns          none
+**
+*******************************************************************************/
+static void rw_i93_data_cback(uint8_t conn_id, tNFC_CONN_EVT event,
+                              tNFC_CONN* p_data) {
+  tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
+  NFC_HDR* p_resp;
+  tRW_DATA rw_data;
+
+#if (BT_TRACE_VERBOSE == TRUE)
+  uint8_t begin_state = p_i93->state;
+#endif
+
+  RW_TRACE_DEBUG1("rw_i93_data_cback () event = 0x%X", event);
+
+  if ((event == NFC_DEACTIVATE_CEVT) || (event == NFC_ERROR_CEVT) ||
+      ((event == NFC_DATA_CEVT) && (p_data->status != NFC_STATUS_OK))) {
+    nfc_stop_quick_timer(&p_i93->timer);
+
+    if (event == NFC_ERROR_CEVT) {
+      if ((p_i93->retry_count < RW_MAX_RETRIES) && (p_i93->p_retry_cmd)) {
+        p_i93->retry_count++;
+
+        RW_TRACE_ERROR1("rw_i93_data_cback (): retry_count = %d",
+                        p_i93->retry_count);
+
+        p_resp = p_i93->p_retry_cmd;
+        p_i93->p_retry_cmd = NULL;
+        if (rw_i93_send_to_lower(p_resp)) {
+          return;
+        }
+      }
+
+      /* all retrial is done or failed to send command to lower layer */
+      if (p_i93->p_retry_cmd) {
+        GKI_freebuf(p_i93->p_retry_cmd);
+        p_i93->p_retry_cmd = NULL;
+        p_i93->retry_count = 0;
+      }
+
+      rw_i93_handle_error((tNFC_STATUS)(*(uint8_t*)p_data));
+    } else {
+      /* free retry buffer */
+      if (p_i93->p_retry_cmd) {
+        GKI_freebuf(p_i93->p_retry_cmd);
+        p_i93->p_retry_cmd = NULL;
+        p_i93->retry_count = 0;
+      }
+      NFC_SetStaticRfCback(NULL);
+      p_i93->state = RW_I93_STATE_NOT_ACTIVATED;
+    }
+    return;
+  }
+
+  if (event != NFC_DATA_CEVT) {
+    return;
+  }
+
+  p_resp = (NFC_HDR*)p_data->data.p_data;
+
+  nfc_stop_quick_timer(&p_i93->timer);
+
+  /* free retry buffer */
+  if (p_i93->p_retry_cmd) {
+    GKI_freebuf(p_i93->p_retry_cmd);
+    p_i93->p_retry_cmd = NULL;
+    p_i93->retry_count = 0;
+  }
+
+#if (BT_TRACE_PROTOCOL == TRUE)
+  DispRWI93Tag(p_resp, true, p_i93->sent_cmd);
+#endif
+
+#if (BT_TRACE_VERBOSE == TRUE)
+  RW_TRACE_DEBUG2("RW I93 state: <%s (%d)>",
+                  rw_i93_get_state_name(p_i93->state).c_str(), p_i93->state);
+#else
+  RW_TRACE_DEBUG1("RW I93 state: %d", p_i93->state);
+#endif
+
+  switch (p_i93->state) {
+    case RW_I93_STATE_IDLE:
+      /* Unexpected Response from VICC, it should be raw frame response */
+      /* forward to upper layer without parsing */
+      p_i93->sent_cmd = 0;
+      if (rw_cb.p_cback) {
+        rw_data.raw_frame.status = p_data->data.status;
+        rw_data.raw_frame.p_data = p_resp;
+        (*(rw_cb.p_cback))(RW_I93_RAW_FRAME_EVT, &rw_data);
+        p_resp = NULL;
+      } else {
+        GKI_freebuf(p_resp);
+      }
+      break;
+    case RW_I93_STATE_BUSY:
+      p_i93->state = RW_I93_STATE_IDLE;
+      rw_i93_send_to_upper(p_resp);
+      GKI_freebuf(p_resp);
+      break;
+
+    case RW_I93_STATE_DETECT_NDEF:
+      rw_i93_sm_detect_ndef(p_resp);
+      GKI_freebuf(p_resp);
+      break;
+
+    case RW_I93_STATE_READ_NDEF:
+      rw_i93_sm_read_ndef(p_resp);
+      /* p_resp may send upper lyaer */
+      break;
+
+    case RW_I93_STATE_UPDATE_NDEF:
+      rw_i93_sm_update_ndef(p_resp);
+      GKI_freebuf(p_resp);
+      break;
+
+    case RW_I93_STATE_FORMAT:
+      rw_i93_sm_format(p_resp);
+      GKI_freebuf(p_resp);
+      break;
+
+    case RW_I93_STATE_SET_READ_ONLY:
+      rw_i93_sm_set_read_only(p_resp);
+      GKI_freebuf(p_resp);
+      break;
+
+    case RW_I93_STATE_PRESENCE_CHECK:
+      p_i93->state = RW_I93_STATE_IDLE;
+      p_i93->sent_cmd = 0;
+
+      /* if any response, send presence check with ok */
+      rw_data.status = NFC_STATUS_OK;
+      (*(rw_cb.p_cback))(RW_I93_PRESENCE_CHECK_EVT, &rw_data);
+      GKI_freebuf(p_resp);
+      break;
+
+    default:
+      RW_TRACE_ERROR1("rw_i93_data_cback (): invalid state=%d", p_i93->state);
+      GKI_freebuf(p_resp);
+      break;
+  }
+
+#if (BT_TRACE_VERBOSE == TRUE)
+  if (begin_state != p_i93->state) {
+    RW_TRACE_DEBUG2("RW I93 state changed:<%s> -> <%s>",
+                    rw_i93_get_state_name(begin_state).c_str(),
+                    rw_i93_get_state_name(p_i93->state).c_str());
+  }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_select
+**
+** Description      Initialise ISO 15693 / T5T RW
+**
+** Returns          NFC_STATUS_OK if success
+**
+*******************************************************************************/
+tNFC_STATUS rw_i93_select(uint8_t* p_uid) {
+  tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
+  uint8_t uid[I93_UID_BYTE_LEN], *p;
+
+  RW_TRACE_DEBUG0("rw_i93_select ()");
+
+  NFC_SetStaticRfCback(rw_i93_data_cback);
+
+  p_i93->state = RW_I93_STATE_IDLE;
+
+  /* convert UID to big endian format - MSB(0xE0) in first byte */
+  p = uid;
+  STREAM_TO_ARRAY8(p, p_uid);
+
+  rw_i93_get_product_version(uid);
+
+  return NFC_STATUS_OK;
+}
+
+/*******************************************************************************
+**
+** Function         RW_I93Inventory
+**
+** Description      This function send Inventory command with/without AFI
+**                  If UID is provided then set UID[0]:MSB, ... UID[7]:LSB
+**
+**                  RW_I93_RESPONSE_EVT will be returned
+**
+** Returns          NFC_STATUS_OK if success
+**                  NFC_STATUS_NO_BUFFERS if out of buffer
+**                  NFC_STATUS_BUSY if busy
+**                  NFC_STATUS_FAILED if other error
+**
+*******************************************************************************/
+tNFC_STATUS RW_I93Inventory(bool including_afi, uint8_t afi, uint8_t* p_uid) {
+  tNFC_STATUS status;
+
+  RW_TRACE_API2("RW_I93Inventory (), including_afi:%d, AFI:0x%02X",
+                including_afi, afi);
+
+  if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
+    RW_TRACE_ERROR1(
+        "RW_I93Inventory ():Unable to start command at state (0x%X)",
+        rw_cb.tcb.i93.state);
+    return NFC_STATUS_BUSY;
+  }
+
+  status = rw_i93_send_cmd_inventory(p_uid, including_afi, afi);
+
+  if (status == NFC_STATUS_OK) {
+    rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
+  }
+
+  return (status);
+}
+
+/*******************************************************************************
+**
+** Function         RW_I93StayQuiet
+**
+** Description      This function send Inventory command
+**
+**                  RW_I93_CMD_CMPL_EVT will be returned
+**
+** Returns          NFC_STATUS_OK if success
+**                  NFC_STATUS_NO_BUFFERS if out of buffer
+**                  NFC_STATUS_BUSY if busy
+**                  NFC_STATUS_FAILED if other error
+**
+*******************************************************************************/
+tNFC_STATUS RW_I93StayQuiet(void) {
+  tNFC_STATUS status;
+
+  RW_TRACE_API0("RW_I93StayQuiet ()");
+
+  if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
+    RW_TRACE_ERROR1(
+        "RW_I93StayQuiet ():Unable to start command at state (0x%X)",
+        rw_cb.tcb.i93.state);
+    return NFC_STATUS_BUSY;
+  }
+
+  status = rw_i93_send_cmd_stay_quiet();
+  if (status == NFC_STATUS_OK) {
+    rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
+  }
+
+  return status;
+}
+
+/*******************************************************************************
+**
+** Function         RW_I93ReadSingleBlock
+**
+** Description      This function send Read Single Block command
+**
+**                  RW_I93_RESPONSE_EVT will be returned
+**
+** Returns          NFC_STATUS_OK if success
+**                  NFC_STATUS_NO_BUFFERS if out of buffer
+**                  NFC_STATUS_BUSY if busy
+**                  NFC_STATUS_FAILED if other error
+**
+*******************************************************************************/
+tNFC_STATUS RW_I93ReadSingleBlock(uint16_t block_number) {
+  tNFC_STATUS status;
+
+  RW_TRACE_API1("RW_I93ReadSingleBlock () block_number:0x%02X", block_number);
+
+  if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
+    RW_TRACE_ERROR1(
+        "RW_I93ReadSingleBlock ():Unable to start command at state (0x%X)",
+        rw_cb.tcb.i93.state);
+    return NFC_STATUS_BUSY;
+  }
+
+  status = rw_i93_send_cmd_read_single_block(block_number, false);
+  if (status == NFC_STATUS_OK) {
+    rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
+  }
+
+  return status;
+}
+
+/*******************************************************************************
+**
+** Function         RW_I93WriteSingleBlock
+**
+** Description      This function send Write Single Block command
+**                  Application must get block size first by calling
+**                  RW_I93GetSysInfo().
+**
+**                  RW_I93_CMD_CMPL_EVT will be returned
+**
+** Returns          NFC_STATUS_OK if success
+**                  NFC_STATUS_NO_BUFFERS if out of buffer
+**                  NFC_STATUS_BUSY if busy
+**                  NFC_STATUS_FAILED if other error
+**
+*******************************************************************************/
+tNFC_STATUS RW_I93WriteSingleBlock(uint16_t block_number, uint8_t* p_data) {
+  tNFC_STATUS status;
+
+  RW_TRACE_API0("RW_I93WriteSingleBlock ()");
+
+  if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
+    RW_TRACE_ERROR1(
+        "RW_I93WriteSingleBlock ():Unable to start command at state (0x%X)",
+        rw_cb.tcb.i93.state);
+    return NFC_STATUS_BUSY;
+  }
+
+  if (rw_cb.tcb.i93.block_size == 0) {
+    RW_TRACE_ERROR0("RW_I93WriteSingleBlock ():Block size is unknown");
+    return NFC_STATUS_FAILED;
+  }
+
+  status = rw_i93_send_cmd_write_single_block(block_number, p_data);
+  if (status == NFC_STATUS_OK) {
+    rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
+  }
+
+  return status;
+}
+
+/*******************************************************************************
+**
+** Function         RW_I93LockBlock
+**
+** Description      This function send Lock Block command
+**
+**                  RW_I93_CMD_CMPL_EVT will be returned
+**
+** Returns          NFC_STATUS_OK if success
+**                  NFC_STATUS_NO_BUFFERS if out of buffer
+**                  NFC_STATUS_BUSY if busy
+**                  NFC_STATUS_FAILED if other error
+**
+*******************************************************************************/
+tNFC_STATUS RW_I93LockBlock(uint8_t block_number) {
+  tNFC_STATUS status;
+
+  RW_TRACE_API0("RW_I93LockBlock ()");
+
+  if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
+    RW_TRACE_ERROR1(
+        "RW_I93LockBlock ():Unable to start command at state (0x%X)",
+        rw_cb.tcb.i93.state);
+    return NFC_STATUS_BUSY;
+  }
+
+  status = rw_i93_send_cmd_lock_block(block_number);
+  if (status == NFC_STATUS_OK) {
+    rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
+  }
+
+  return status;
+}
+
+/*******************************************************************************
+**
+** Function         RW_I93ReadMultipleBlocks
+**
+** Description      This function send Read Multiple Blocks command
+**
+**                  RW_I93_RESPONSE_EVT will be returned
+**
+** Returns          NFC_STATUS_OK if success
+**                  NFC_STATUS_NO_BUFFERS if out of buffer
+**                  NFC_STATUS_BUSY if busy
+**                  NFC_STATUS_FAILED if other error
+**
+*******************************************************************************/
+tNFC_STATUS RW_I93ReadMultipleBlocks(uint16_t first_block_number,
+                                     uint16_t number_blocks) {
+  tNFC_STATUS status;
+
+  RW_TRACE_API0("RW_I93ReadMultipleBlocks ()");
+
+  if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
+    RW_TRACE_ERROR1(
+        "RW_I93ReadMultipleBlocks ():Unable to start command at state (0x%X)",
+        rw_cb.tcb.i93.state);
+    return NFC_STATUS_BUSY;
+  }
+
+  status = rw_i93_send_cmd_read_multi_blocks(first_block_number, number_blocks);
+  if (status == NFC_STATUS_OK) {
+    rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
+  }
+
+  return status;
+}
+
+/*******************************************************************************
+**
+** Function         RW_I93WriteMultipleBlocks
+**
+** Description      This function send Write Multiple Blocks command
+**
+**                  RW_I93_CMD_CMPL_EVT will be returned
+**
+** Returns          NFC_STATUS_OK if success
+**                  NFC_STATUS_NO_BUFFERS if out of buffer
+**                  NFC_STATUS_BUSY if busy
+**                  NFC_STATUS_FAILED if other error
+**
+*******************************************************************************/
+tNFC_STATUS RW_I93WriteMultipleBlocks(uint8_t first_block_number,
+                                      uint16_t number_blocks, uint8_t* p_data) {
+  tNFC_STATUS status;
+
+  RW_TRACE_API0("RW_I93WriteMultipleBlocks ()");
+
+  if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
+    RW_TRACE_ERROR1(
+        "RW_I93WriteMultipleBlocks ():Unable to start command at state (0x%X)",
+        rw_cb.tcb.i93.state);
+    return NFC_STATUS_BUSY;
+  }
+
+  if (rw_cb.tcb.i93.block_size == 0) {
+    RW_TRACE_ERROR0("RW_I93WriteSingleBlock ():Block size is unknown");
+    return NFC_STATUS_FAILED;
+  }
+
+  status = rw_i93_send_cmd_write_multi_blocks(first_block_number, number_blocks,
+                                              p_data);
+  if (status == NFC_STATUS_OK) {
+    rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
+  }
+
+  return status;
+}
+
+/*******************************************************************************
+**
+** Function         RW_I93Select
+**
+** Description      This function send Select command
+**
+**                  UID[0]: 0xE0, MSB
+**                  UID[1]: IC Mfg Code
+**                  ...
+**                  UID[7]: LSB
+**
+**                  RW_I93_CMD_CMPL_EVT will be returned
+**
+** Returns          NFC_STATUS_OK if success
+**                  NFC_STATUS_NO_BUFFERS if out of buffer
+**                  NFC_STATUS_BUSY if busy
+**                  NFC_STATUS_FAILED if other error
+**
+*******************************************************************************/
+tNFC_STATUS RW_I93Select(uint8_t* p_uid) {
+  tNFC_STATUS status;
+
+  RW_TRACE_API0("RW_I93Select ()");
+
+  if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
+    RW_TRACE_ERROR1("RW_I93Select ():Unable to start command at state (0x%X)",
+                    rw_cb.tcb.i93.state);
+    return NFC_STATUS_BUSY;
+  }
+
+  if (p_uid) {
+    status = rw_i93_send_cmd_select(p_uid);
+    if (status == NFC_STATUS_OK) {
+      rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
+    }
+  } else {
+    RW_TRACE_ERROR0("RW_I93Select ():UID shall be provided");
+    status = NFC_STATUS_FAILED;
+  }
+
+  return status;
+}
+
+/*******************************************************************************
+**
+** Function         RW_I93ResetToReady
+**
+** Description      This function send Reset To Ready command
+**
+**                  RW_I93_CMD_CMPL_EVT will be returned
+**
+** Returns          NFC_STATUS_OK if success
+**                  NFC_STATUS_NO_BUFFERS if out of buffer
+**                  NFC_STATUS_BUSY if busy
+**                  NFC_STATUS_FAILED if other error
+**
+*******************************************************************************/
+tNFC_STATUS RW_I93ResetToReady(void) {
+  tNFC_STATUS status;
+
+  RW_TRACE_API0("RW_I93ResetToReady ()");
+
+  if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
+    RW_TRACE_ERROR1(
+        "RW_I93ResetToReady ():Unable to start command at state (0x%X)",
+        rw_cb.tcb.i93.state);
+    return NFC_STATUS_BUSY;
+  }
+
+  status = rw_i93_send_cmd_reset_to_ready();
+  if (status == NFC_STATUS_OK) {
+    rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
+  }
+
+  return status;
+}
+
+/*******************************************************************************
+**
+** Function         RW_I93WriteAFI
+**
+** Description      This function send Write AFI command
+**
+**                  RW_I93_CMD_CMPL_EVT will be returned
+**
+** Returns          NFC_STATUS_OK if success
+**                  NFC_STATUS_NO_BUFFERS if out of buffer
+**                  NFC_STATUS_BUSY if busy
+**                  NFC_STATUS_FAILED if other error
+**
+*******************************************************************************/
+tNFC_STATUS RW_I93WriteAFI(uint8_t afi) {
+  tNFC_STATUS status;
+
+  RW_TRACE_API0("RW_I93WriteAFI ()");
+
+  if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
+    RW_TRACE_ERROR1("RW_I93WriteAFI ():Unable to start command at state (0x%X)",
+                    rw_cb.tcb.i93.state);
+    return NFC_STATUS_BUSY;
+  }
+
+  status = rw_i93_send_cmd_write_afi(afi);
+  if (status == NFC_STATUS_OK) {
+    rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
+  }
+
+  return status;
+}
+
+/*******************************************************************************
+**
+** Function         RW_I93LockAFI
+**
+** Description      This function send Lock AFI command
+**
+**                  RW_I93_CMD_CMPL_EVT will be returned
+**
+** Returns          NFC_STATUS_OK if success
+**                  NFC_STATUS_NO_BUFFERS if out of buffer
+**                  NFC_STATUS_BUSY if busy
+**                  NFC_STATUS_FAILED if other error
+**
+*******************************************************************************/
+tNFC_STATUS RW_I93LockAFI(void) {
+  tNFC_STATUS status;
+
+  RW_TRACE_API0("RW_I93LockAFI ()");
+
+  if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
+    RW_TRACE_ERROR1("RW_I93LockAFI ():Unable to start command at state (0x%X)",
+                    rw_cb.tcb.i93.state);
+    return NFC_STATUS_BUSY;
+  }
+
+  status = rw_i93_send_cmd_lock_afi();
+  if (status == NFC_STATUS_OK) {
+    rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
+  }
+
+  return status;
+}
+
+/*******************************************************************************
+**
+** Function         RW_I93WriteDSFID
+**
+** Description      This function send Write DSFID command
+**
+**                  RW_I93_CMD_CMPL_EVT will be returned
+**
+** Returns          NFC_STATUS_OK if success
+**                  NFC_STATUS_NO_BUFFERS if out of buffer
+**                  NFC_STATUS_BUSY if busy
+**                  NFC_STATUS_FAILED if other error
+**
+*******************************************************************************/
+tNFC_STATUS RW_I93WriteDSFID(uint8_t dsfid) {
+  tNFC_STATUS status;
+
+  RW_TRACE_API0("RW_I93WriteDSFID ()");
+
+  if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
+    RW_TRACE_ERROR1(
+        "RW_I93WriteDSFID ():Unable to start command at state (0x%X)",
+        rw_cb.tcb.i93.state);
+    return NFC_STATUS_BUSY;
+  }
+
+  status = rw_i93_send_cmd_write_dsfid(dsfid);
+  if (status == NFC_STATUS_OK) {
+    rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
+  }
+
+  return status;
+}
+
+/*******************************************************************************
+**
+** Function         RW_I93LockDSFID
+**
+** Description      This function send Lock DSFID command
+**
+**                  RW_I93_CMD_CMPL_EVT will be returned
+**
+** Returns          NFC_STATUS_OK if success
+**                  NFC_STATUS_NO_BUFFERS if out of buffer
+**                  NFC_STATUS_BUSY if busy
+**                  NFC_STATUS_FAILED if other error
+**
+*******************************************************************************/
+tNFC_STATUS RW_I93LockDSFID(void) {
+  tNFC_STATUS status;
+
+  RW_TRACE_API0("RW_I93LockDSFID ()");
+
+  if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
+    RW_TRACE_ERROR1(
+        "RW_I93LockDSFID ():Unable to start command at state (0x%X)",
+        rw_cb.tcb.i93.state);
+    return NFC_STATUS_BUSY;
+  }
+
+  status = rw_i93_send_cmd_lock_dsfid();
+  if (status == NFC_STATUS_OK) {
+    rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
+  }
+
+  return status;
+}
+
+/*******************************************************************************
+**
+** Function         RW_I93GetSysInfo
+**
+** Description      This function send Get System Information command
+**
+**                  RW_I93_RESPONSE_EVT will be returned
+**
+** Returns          NFC_STATUS_OK if success
+**                  NFC_STATUS_NO_BUFFERS if out of buffer
+**                  NFC_STATUS_BUSY if busy
+**                  NFC_STATUS_FAILED if other error
+**
+*******************************************************************************/
+tNFC_STATUS RW_I93GetSysInfo(uint8_t* p_uid) {
+  tNFC_STATUS status;
+
+  RW_TRACE_API0("RW_I93GetSysInfo ()");
+
+  if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
+    RW_TRACE_ERROR1(
+        "RW_I93GetSysInfo ():Unable to start command at state (0x%X)",
+        rw_cb.tcb.i93.state);
+    return NFC_STATUS_BUSY;
+  }
+
+  if (p_uid) {
+    status = rw_i93_send_cmd_get_sys_info(p_uid, I93_FLAG_PROT_EXT_NO);
+  } else {
+    status = rw_i93_send_cmd_get_sys_info(NULL, I93_FLAG_PROT_EXT_NO);
+  }
+
+  if (status == NFC_STATUS_OK) {
+    rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
+  }
+
+  return status;
+}
+
+/*******************************************************************************
+**
+** Function         RW_I93GetMultiBlockSecurityStatus
+**
+** Description      This function send Get Multiple Block Security Status
+**                  command
+**
+**                  RW_I93_RESPONSE_EVT will be returned
+**
+** Returns          NFC_STATUS_OK if success
+**                  NFC_STATUS_NO_BUFFERS if out of buffer
+**                  NFC_STATUS_BUSY if busy
+**                  NFC_STATUS_FAILED if other error
+**
+*******************************************************************************/
+tNFC_STATUS RW_I93GetMultiBlockSecurityStatus(uint16_t first_block_number,
+                                              uint16_t number_blocks) {
+  tNFC_STATUS status;
+
+  RW_TRACE_API0("RW_I93GetMultiBlockSecurityStatus ()");
+
+  if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
+    RW_TRACE_ERROR1(
+        "RW_I93GetMultiBlockSecurityStatus ():Unable to start command at state "
+        "(0x%X)",
+        rw_cb.tcb.i93.state);
+    return NFC_STATUS_BUSY;
+  }
+
+  status =
+      rw_i93_send_cmd_get_multi_block_sec(first_block_number, number_blocks);
+  if (status == NFC_STATUS_OK) {
+    rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
+  }
+
+  return status;
+}
+
+/*******************************************************************************
+**
+** Function         RW_I93DetectNDef
+**
+** Description      This function performs NDEF detection procedure
+**
+**                  RW_I93_NDEF_DETECT_EVT will be returned
+**
+** Returns          NFC_STATUS_OK if success
+**                  NFC_STATUS_FAILED if busy or other error
+**
+*******************************************************************************/
+tNFC_STATUS RW_I93DetectNDef(void) {
+  tNFC_STATUS status;
+  tRW_I93_RW_SUBSTATE sub_state;
+
+  RW_TRACE_API0("RW_I93DetectNDef ()");
+
+  if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
+    RW_TRACE_ERROR1(
+        "RW_I93DetectNDef ():Unable to start command at state (0x%X)",
+        rw_cb.tcb.i93.state);
+    return NFC_STATUS_FAILED;
+  }
+
+  if (rw_cb.tcb.i93.uid[0] != I93_UID_FIRST_BYTE) {
+    status = rw_i93_send_cmd_inventory(NULL, false, 0x00);
+    sub_state = RW_I93_SUBSTATE_WAIT_UID;
+  } else if ((rw_cb.tcb.i93.num_block == 0) ||
+             (rw_cb.tcb.i93.block_size == 0)) {
+    status =
+        rw_i93_send_cmd_get_sys_info(rw_cb.tcb.i93.uid, I93_FLAG_PROT_EXT_NO);
+    sub_state = RW_I93_SUBSTATE_WAIT_SYS_INFO;
+
+    /* clear all flags */
+    rw_cb.tcb.i93.intl_flags = 0;
+  } else {
+    /* read CC in the first block */
+    status = rw_i93_send_cmd_read_single_block(0x0000, false);
+    sub_state = RW_I93_SUBSTATE_WAIT_CC;
+  }
+
+  if (status == NFC_STATUS_OK) {
+    rw_cb.tcb.i93.state = RW_I93_STATE_DETECT_NDEF;
+    rw_cb.tcb.i93.sub_state = sub_state;
+
+    /* clear flags except flag for 2 bytes of number of blocks */
+    rw_cb.tcb.i93.intl_flags &= RW_I93_FLAG_16BIT_NUM_BLOCK;
+  }
+
+  return (status);
+}
+
+/*******************************************************************************
+**
+** Function         RW_I93ReadNDef
+**
+** Description      This function performs NDEF read procedure
+**                  Note: RW_I93DetectNDef () must be called before using this
+**
+**                  The following event will be returned
+**                      RW_I93_NDEF_READ_EVT for each segmented NDEF message
+**                      RW_I93_NDEF_READ_CPLT_EVT for the last segment or
+**                      complete NDEF
+**                      RW_I93_NDEF_READ_FAIL_EVT for failure
+**
+** Returns          NFC_STATUS_OK if success
+**                  NFC_STATUS_FAILED if I93 is busy or other error
+**
+*******************************************************************************/
+tNFC_STATUS RW_I93ReadNDef(void) {
+  RW_TRACE_API0("RW_I93ReadNDef ()");
+
+  if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
+    RW_TRACE_ERROR1("RW_I93ReadNDef ():Unable to start command at state (0x%X)",
+                    rw_cb.tcb.i93.state);
+    return NFC_STATUS_FAILED;
+  }
+
+  if ((rw_cb.tcb.i93.tlv_type == I93_ICODE_TLV_TYPE_NDEF) &&
+      (rw_cb.tcb.i93.ndef_length > 0)) {
+    rw_cb.tcb.i93.rw_offset = rw_cb.tcb.i93.ndef_tlv_start_offset;
+    rw_cb.tcb.i93.rw_length = 0;
+
+    if (rw_i93_get_next_blocks(rw_cb.tcb.i93.rw_offset) == NFC_STATUS_OK) {
+      rw_cb.tcb.i93.state = RW_I93_STATE_READ_NDEF;
+    } else {
+      return NFC_STATUS_FAILED;
+    }
+  } else {
+    RW_TRACE_ERROR0("RW_I93ReadNDef ():No NDEF detected");
+    return NFC_STATUS_FAILED;
+  }
+
+  return NFC_STATUS_OK;
+}
+
+/*******************************************************************************
+**
+** Function         RW_I93UpdateNDef
+**
+** Description      This function performs NDEF update procedure
+**                  Note: RW_I93DetectNDef () must be called before using this
+**                        Updating data must not be removed until returning
+**                        event
+**
+**                  The following event will be returned
+**                      RW_I93_NDEF_UPDATE_CPLT_EVT for complete
+**                      RW_I93_NDEF_UPDATE_FAIL_EVT for failure
+**
+** Returns          NFC_STATUS_OK if success
+**                  NFC_STATUS_FAILED if I93 is busy or other error
+**
+*******************************************************************************/
+tNFC_STATUS RW_I93UpdateNDef(uint16_t length, uint8_t* p_data) {
+  uint16_t block_number;
+
+  RW_TRACE_API1("RW_I93UpdateNDef () length:%d", length);
+
+  if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
+    RW_TRACE_ERROR1(
+        "RW_I93UpdateNDef ():Unable to start command at state (0x%X)",
+        rw_cb.tcb.i93.state);
+    return NFC_STATUS_FAILED;
+  }
+
+  if (rw_cb.tcb.i93.tlv_type == I93_ICODE_TLV_TYPE_NDEF) {
+    if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_READ_ONLY) {
+      RW_TRACE_ERROR0("RW_I93UpdateNDef ():NDEF is read-only");
+      return NFC_STATUS_FAILED;
+    }
+    if (rw_cb.tcb.i93.max_ndef_length < length) {
+      RW_TRACE_ERROR2(
+          "RW_I93UpdateNDef ():data (%d bytes) is more than max NDEF length "
+          "(%d)",
+          length, rw_cb.tcb.i93.max_ndef_length);
+      return NFC_STATUS_FAILED;
+    }
+
+    rw_cb.tcb.i93.ndef_length = length;
+    rw_cb.tcb.i93.p_update_data = p_data;
+
+    /* read length field */
+    rw_cb.tcb.i93.rw_offset = rw_cb.tcb.i93.ndef_tlv_start_offset + 1;
+    rw_cb.tcb.i93.rw_length = 0;
+
+    block_number = rw_cb.tcb.i93.rw_offset / rw_cb.tcb.i93.block_size;
+
+    if (rw_i93_send_cmd_read_single_block(block_number, false) ==
+        NFC_STATUS_OK) {
+      rw_cb.tcb.i93.state = RW_I93_STATE_UPDATE_NDEF;
+      rw_cb.tcb.i93.sub_state = RW_I93_SUBSTATE_RESET_LEN;
+    } else {
+      return NFC_STATUS_FAILED;
+    }
+  } else {
+    RW_TRACE_ERROR0("RW_I93ReadNDef ():No NDEF detected");
+    return NFC_STATUS_FAILED;
+  }
+
+  return NFC_STATUS_OK;
+}
+
+/*******************************************************************************
+**
+** Function         RW_I93FormatNDef
+**
+** Description      This function performs formatting procedure
+**
+**                  RW_I93_FORMAT_CPLT_EVT will be returned
+**
+** Returns          NFC_STATUS_OK if success
+**                  NFC_STATUS_FAILED if busy or other error
+**
+*******************************************************************************/
+tNFC_STATUS RW_I93FormatNDef(void) {
+  tNFC_STATUS status;
+  tRW_I93_RW_SUBSTATE sub_state;
+
+  RW_TRACE_API0("RW_I93FormatNDef ()");
+
+  if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
+    RW_TRACE_ERROR1(
+        "RW_I93FormatNDef ():Unable to start command at state (0x%X)",
+        rw_cb.tcb.i93.state);
+    return NFC_STATUS_FAILED;
+  }
+
+  if ((rw_cb.tcb.i93.product_version == RW_I93_TAG_IT_HF_I_STD_CHIP_INLAY) ||
+      (rw_cb.tcb.i93.product_version == RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY)) {
+    /* These don't support GetSystemInformation and GetMultiBlockSecurityStatus
+     */
+    rw_cb.tcb.i93.rw_offset = 0;
+
+    /* read blocks with option flag to get block security status */
+    status = rw_i93_send_cmd_read_single_block(0x0000, true);
+    sub_state = RW_I93_SUBSTATE_CHECK_READ_ONLY;
+  } else {
+    status = rw_i93_send_cmd_inventory(rw_cb.tcb.i93.uid, false, 0x00);
+    sub_state = RW_I93_SUBSTATE_WAIT_UID;
+  }
+
+  if (status == NFC_STATUS_OK) {
+    rw_cb.tcb.i93.state = RW_I93_STATE_FORMAT;
+    rw_cb.tcb.i93.sub_state = sub_state;
+    rw_cb.tcb.i93.intl_flags = 0;
+  }
+
+  return (status);
+}
+
+/*******************************************************************************
+**
+** Function         RW_I93SetTagReadOnly
+**
+** Description      This function performs NDEF read-only procedure
+**                  Note: RW_I93DetectNDef () must be called before using this
+**                        Updating data must not be removed until returning
+**                        event
+**
+**                  The RW_I93_SET_TAG_RO_EVT event will be returned.
+**
+** Returns          NFC_STATUS_OK if success
+**                  NFC_STATUS_FAILED if I93 is busy or other error
+**
+*******************************************************************************/
+tNFC_STATUS RW_I93SetTagReadOnly(void) {
+  RW_TRACE_API0("RW_I93SetTagReadOnly ()");
+
+  if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
+    RW_TRACE_ERROR1(
+        "RW_I93SetTagReadOnly ():Unable to start command at state (0x%X)",
+        rw_cb.tcb.i93.state);
+    return NFC_STATUS_FAILED;
+  }
+
+  if (rw_cb.tcb.i93.tlv_type == I93_ICODE_TLV_TYPE_NDEF) {
+    if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_READ_ONLY) {
+      RW_TRACE_ERROR0("RW_I93SetTagReadOnly ():NDEF is already read-only");
+      return NFC_STATUS_FAILED;
+    }
+
+    /* get CC in the first block */
+    if (rw_i93_send_cmd_read_single_block(0, false) == NFC_STATUS_OK) {
+      rw_cb.tcb.i93.state = RW_I93_STATE_SET_READ_ONLY;
+      rw_cb.tcb.i93.sub_state = RW_I93_SUBSTATE_WAIT_CC;
+    } else {
+      return NFC_STATUS_FAILED;
+    }
+  } else {
+    RW_TRACE_ERROR0("RW_I93SetTagReadOnly ():No NDEF detected");
+    return NFC_STATUS_FAILED;
+  }
+
+  return NFC_STATUS_OK;
+}
+
+/*****************************************************************************
+**
+** Function         RW_I93PresenceCheck
+**
+** Description      Check if the tag is still in the field.
+**
+**                  The RW_I93_PRESENCE_CHECK_EVT w/ status is used to indicate
+**                  presence or non-presence.
+**
+** Returns          NFC_STATUS_OK, if raw data frame sent
+**                  NFC_STATUS_NO_BUFFERS: unable to allocate a buffer for this
+**                  operation
+**                  NFC_STATUS_FAILED: other error
+**
+*****************************************************************************/
+tNFC_STATUS RW_I93PresenceCheck(void) {
+  tNFC_STATUS status;
+  tRW_DATA evt_data;
+
+  RW_TRACE_API0("RW_I93PresenceCheck ()");
+
+  if (!rw_cb.p_cback) {
+    return NFC_STATUS_FAILED;
+  } else if (rw_cb.tcb.i93.state == RW_I93_STATE_NOT_ACTIVATED) {
+    evt_data.status = NFC_STATUS_FAILED;
+    (*rw_cb.p_cback)(RW_T4T_PRESENCE_CHECK_EVT, &evt_data);
+
+    return NFC_STATUS_OK;
+  } else if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
+    return NFC_STATUS_BUSY;
+  } else {
+    /* The support of AFI by the VICC is optional, so do not include AFI */
+    status = rw_i93_send_cmd_inventory(rw_cb.tcb.i93.uid, false, 0x00);
+
+    if (status == NFC_STATUS_OK) {
+      /* do not retry during presence check */
+      rw_cb.tcb.i93.retry_count = RW_MAX_RETRIES;
+      rw_cb.tcb.i93.state = RW_I93_STATE_PRESENCE_CHECK;
+    }
+  }
+
+  return (status);
+}
+
+#if (BT_TRACE_VERBOSE == TRUE)
+/*******************************************************************************
+**
+** Function         rw_i93_get_state_name
+**
+** Description      This function returns the state name.
+**
+** NOTE             conditionally compiled to save memory.
+**
+** Returns          pointer to the name
+**
+*******************************************************************************/
+static std::string rw_i93_get_state_name(uint8_t state) {
+  switch (state) {
+    case RW_I93_STATE_NOT_ACTIVATED:
+      return "NOT_ACTIVATED";
+    case RW_I93_STATE_IDLE:
+      return "IDLE";
+    case RW_I93_STATE_BUSY:
+      return "BUSY";
+    case RW_I93_STATE_DETECT_NDEF:
+      return "NDEF_DETECTION";
+    case RW_I93_STATE_READ_NDEF:
+      return "READ_NDEF";
+    case RW_I93_STATE_UPDATE_NDEF:
+      return "UPDATE_NDEF";
+    case RW_I93_STATE_FORMAT:
+      return "FORMAT";
+    case RW_I93_STATE_SET_READ_ONLY:
+      return "SET_READ_ONLY";
+    case RW_I93_STATE_PRESENCE_CHECK:
+      return "PRESENCE_CHECK";
+    default:
+      return "???? UNKNOWN STATE";
+  }
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_get_sub_state_name
+**
+** Description      This function returns the sub_state name.
+**
+** NOTE             conditionally compiled to save memory.
+**
+** Returns          pointer to the name
+**
+*******************************************************************************/
+static std::string rw_i93_get_sub_state_name(uint8_t sub_state) {
+  switch (sub_state) {
+    case RW_I93_SUBSTATE_WAIT_UID:
+      return "WAIT_UID";
+    case RW_I93_SUBSTATE_WAIT_SYS_INFO:
+      return "WAIT_SYS_INFO";
+    case RW_I93_SUBSTATE_WAIT_CC:
+      return "WAIT_CC";
+    case RW_I93_SUBSTATE_SEARCH_NDEF_TLV:
+      return "SEARCH_NDEF_TLV";
+    case RW_I93_SUBSTATE_CHECK_LOCK_STATUS:
+      return "CHECK_LOCK_STATUS";
+    case RW_I93_SUBSTATE_RESET_LEN:
+      return "RESET_LEN";
+    case RW_I93_SUBSTATE_WRITE_NDEF:
+      return "WRITE_NDEF";
+    case RW_I93_SUBSTATE_UPDATE_LEN:
+      return "UPDATE_LEN";
+    case RW_I93_SUBSTATE_WAIT_RESET_DSFID_AFI:
+      return "WAIT_RESET_DSFID_AFI";
+    case RW_I93_SUBSTATE_CHECK_READ_ONLY:
+      return "CHECK_READ_ONLY";
+    case RW_I93_SUBSTATE_WRITE_CC_NDEF_TLV:
+      return "WRITE_CC_NDEF_TLV";
+    case RW_I93_SUBSTATE_WAIT_UPDATE_CC:
+      return "WAIT_UPDATE_CC";
+    case RW_I93_SUBSTATE_LOCK_NDEF_TLV:
+      return "LOCK_NDEF_TLV";
+    case RW_I93_SUBSTATE_WAIT_LOCK_CC:
+      return "WAIT_LOCK_CC";
+    default:
+      return "???? UNKNOWN SUBSTATE";
+  }
+}
+
+/*******************************************************************************
+**
+** Function         rw_i93_get_tag_name
+**
+** Description      This function returns the tag name.
+**
+** NOTE             conditionally compiled to save memory.
+**
+** Returns          pointer to the name
+**
+*******************************************************************************/
+static std::string rw_i93_get_tag_name(uint8_t product_version) {
+  switch (product_version) {
+    case RW_I93_ICODE_SLI:
+      return "SLI/SLIX";
+    case RW_I93_ICODE_SLI_S:
+      return "SLI-S/SLIX-S";
+    case RW_I93_ICODE_SLI_L:
+      return "SLI-L/SLIX-L";
+    case RW_I93_TAG_IT_HF_I_PLUS_INLAY:
+      return "Tag-it HF-I Plus Inlay";
+    case RW_I93_TAG_IT_HF_I_PLUS_CHIP:
+      return "Tag-it HF-I Plus Chip";
+    case RW_I93_TAG_IT_HF_I_STD_CHIP_INLAY:
+      return "Tag-it HF-I Standard Chip/Inlyas";
+    case RW_I93_TAG_IT_HF_I_PRO_CHIP_INLAY:
+      return "Tag-it HF-I Pro Chip/Inlays";
+    case RW_I93_STM_LRI1K:
+      return "LRi1K";
+    case RW_I93_STM_LRI2K:
+      return "LRi2K";
+    case RW_I93_STM_LRIS2K:
+      return "LRiS2K";
+    case RW_I93_STM_LRIS64K:
+      return "LRiS64K";
+    case RW_I93_STM_M24LR64_R:
+      return "M24LR64";
+    case RW_I93_STM_M24LR04E_R:
+      return "M24LR04E";
+    case RW_I93_STM_M24LR16E_R:
+      return "M24LR16E";
+    case RW_I93_STM_M24LR64E_R:
+      return "M24LR64E";
+    case RW_I93_UNKNOWN_PRODUCT:
+    default:
+      return "UNKNOWN";
+  }
+}
+
+#endif