The length of a packet should be non-zero am: 396ac0e081 am: 6e2338cb88 am: 653f2de33b am: 84c29af749
Original change: https://googleplex-android-review.googlesource.com/c/platform/system/nfc/+/19504916
Change-Id: I78ca4d415392e039dd4f1f72416d319094433b39
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Android.bp b/Android.bp
index 9679a81..1576d1d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1 +1,18 @@
+package {
+ default_applicable_licenses: ["system_nfc_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "system_nfc_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
subdirs = ["src", "utils"]
diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29..0000000
--- a/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/conf/Android.bp b/conf/Android.bp
new file mode 100644
index 0000000..1f62fe0
--- /dev/null
+++ b/conf/Android.bp
@@ -0,0 +1,28 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// 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.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "system_nfc_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["system_nfc_license"],
+}
+
+prebuilt_etc {
+ name: "libnfc-nci.conf-default",
+ src: "libnfc-nci.conf",
+ filename: "libnfc-nci.conf",
+}
diff --git a/conf/libnfc-nci.conf b/conf/libnfc-nci.conf
new file mode 100644
index 0000000..f07f0ed
--- /dev/null
+++ b/conf/libnfc-nci.conf
@@ -0,0 +1,82 @@
+###############################################################################
+# Debug options
+NFC_DEBUG_ENABLED=0
+
+###############################################################################
+# File used for NFA storage
+NFA_STORAGE="/data/nfc"
+PRESERVE_STORAGE=0x01
+
+###############################################################################
+# When screen is turned off, specify the desired power state of the controller.
+# 0: power-off-sleep state; DEFAULT
+# 1: full-power state
+# 2: screen-off card-emulation (CE4/CE3/CE1 modes are used)
+SCREEN_OFF_POWER_STATE=1
+
+###############################################################################
+# Default poll duration (in ms)
+# Default is 500ms if not set (see nfc_target.h)
+#NFA_DM_DISC_DURATION_POLL=333
+
+###############################################################################
+# Force tag polling for the following technology(s).
+# The bits are defined as tNFA_TECHNOLOGY_MASK in nfa_api.h.
+# Default is NFA_TECHNOLOGY_MASK_A | NFA_TECHNOLOGY_MASK_B |
+# NFA_TECHNOLOGY_MASK_F | NFA_TECHNOLOGY_MASK_ISO15693 |
+# NFA_TECHNOLOGY_MASK_B_PRIME | NFA_TECHNOLOGY_MASK_KOVIO |
+# NFA_TECHNOLOGY_MASK_A_ACTIVE | NFA_TECHNOLOGY_MASK_F_ACTIVE.
+#
+# Notable bits:
+# NFA_TECHNOLOGY_MASK_A 0x01 /* NFC Technology A */
+# NFA_TECHNOLOGY_MASK_B 0x02 /* NFC Technology B */
+# NFA_TECHNOLOGY_MASK_F 0x04 /* NFC Technology F */
+# NFA_TECHNOLOGY_MASK_ISO15693 0x08 /* Proprietary Technology */
+# NFA_TECHNOLOGY_MASK_KOVIO 0x20 /* Proprietary Technology */
+# NFA_TECHNOLOGY_MASK_A_ACTIVE 0x40 /* NFC Technology A active mode */
+# NFA_TECHNOLOGY_MASK_F_ACTIVE 0x80 /* NFC Technology F active mode */
+POLLING_TECH_MASK=0x2F
+
+###############################################################################
+# Force P2P to only listen for the following technology(s).
+# The bits are defined as tNFA_TECHNOLOGY_MASK in nfa_api.h.
+# Default is NFA_TECHNOLOGY_MASK_A | NFA_TECHNOLOGY_MASK_F |
+# NFA_TECHNOLOGY_MASK_A_ACTIVE | NFA_TECHNOLOGY_MASK_F_ACTIVE
+#
+# Notable bits:
+# NFA_TECHNOLOGY_MASK_A 0x01 /* NFC Technology A */
+# NFA_TECHNOLOGY_MASK_F 0x04 /* NFC Technology F */
+# NFA_TECHNOLOGY_MASK_A_ACTIVE 0x40 /* NFC Technology A active mode */
+# NFA_TECHNOLOGY_MASK_F_ACTIVE 0x80 /* NFC Technology F active mode */
+P2P_LISTEN_TECH_MASK=0x00
+
+###############################################################################
+# Force UICC to only listen to the following technology(s).
+# The bits are defined as tNFA_TECHNOLOGY_MASK in nfa_api.h.
+# Default is NFA_TECHNOLOGY_MASK_A | NFA_TECHNOLOGY_MASK_B | NFA_TECHNOLOGY_MASK_F
+UICC_LISTEN_TECH_MASK=0x07
+
+###############################################################################
+# Override the stack default for NFA_EE_MAX_EE_SUPPORTED set in nfc_target.h.
+# The value is set to 3 by default as it assumes we will discover 0xF2,
+# 0xF3, and 0xF4. If a platform will exclude and SE, this value can be reduced
+# so that the stack will not wait any longer than necessary.
+# Maximum EE supported number
+# NXP PN547C2 0x02
+# NXP PN65T 0x03
+# NXP PN548C2 0x02
+# NXP PN66T 0x03
+NFA_MAX_EE_SUPPORTED=0x02
+
+###############################################################################
+# AID for Empty Select command
+# If specified, this AID will be substituted when an Empty SELECT command is
+# detected. The first byte is the length of the AID. Maximum length is 16.
+AID_FOR_EMPTY_SELECT={08:A0:00:00:01:51:00:00:00}
+
+###############################################################################
+# AID_MATCHING constants
+# AID_MATCHING_EXACT_ONLY 0x00
+# AID_MATCHING_EXACT_OR_PREFIX 0x01
+# AID_MATCHING_PREFIX_ONLY 0x02
+AID_MATCHING_MODE=0x01
diff --git a/src/Android.bp b/src/Android.bp
index 9075cf6..f691c4a 100644
--- a/src/Android.bp
+++ b/src/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "system_nfc_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["system_nfc_license"],
+}
+
cc_library_shared {
arch: {
arm: {
@@ -26,6 +35,7 @@
"libnfcutils",
],
cflags: [
+ "-DDYN_ALLOC=1",
"-DBUILDCFG=1",
"-Wall",
"-Werror",
@@ -55,6 +65,11 @@
"gki/common/*.cc",
"gki/ulinux/*.cc",
],
+ required: [
+ // Provide a default libnfc-nci.conf in /system/etc for devices that
+ // does not ship one in /product
+ "libnfc-nci.conf-default",
+ ],
product_variables: {
debuggable: {
cflags: [
@@ -65,6 +80,7 @@
sanitize: {
misc_undefined: ["bounds"],
integer_overflow: true,
+ scs: true,
},
}
@@ -169,4 +185,3 @@
"fuzzers/llcp/*.cc",
],
}
-
diff --git a/src/adaptation/NfcAdaptation.cc b/src/adaptation/NfcAdaptation.cc
index 2af25cf..7c6a857 100644
--- a/src/adaptation/NfcAdaptation.cc
+++ b/src/adaptation/NfcAdaptation.cc
@@ -736,7 +736,7 @@
**
*******************************************************************************/
uint8_t NfcAdaptation::HalGetMaxNfcee() {
- const char* func = "NfcAdaptation::HalPowerCycle";
+ const char* func = "NfcAdaptation::HalGetMaxNfcee";
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s", func);
return nfa_ee_max_ee_cfg;
diff --git a/src/adaptation/debug_nfcsnoop.cc b/src/adaptation/debug_nfcsnoop.cc
index cd655cd..ce283c1 100644
--- a/src/adaptation/debug_nfcsnoop.cc
+++ b/src/adaptation/debug_nfcsnoop.cc
@@ -17,23 +17,33 @@
******************************************************************************/
#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
#include <resolv.h>
#include <zlib.h>
#include <mutex>
#include <ringbuffer.h>
+#include <cutils/properties.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
#include "bt_types.h"
#include "include/debug_nfcsnoop.h"
#include "nfc_int.h"
#define USEC_PER_SEC 1000000ULL
+#define DEFAULT_NFCSNOOP_PATH "/data/misc/nfc/logs/nfcsnoop_nci_logs"
+#define DEFAULT_NFCSNOOP_FILE_SIZE 32 * 1024 * 1024
+
// Total nfcsnoop memory log buffer size
#ifndef NFCSNOOP_MEM_BUFFER_SIZE
static const size_t NFCSNOOP_MEM_BUFFER_SIZE = (256 * 1024);
#endif
+#define NFCSNOOP_MEM_BUFFER_THRESHOLD 1024
+
// Block size for copying buffers (for compression/encoding etc.)
static const size_t BLOCK_SIZE = 16384;
@@ -43,6 +53,9 @@
static std::mutex buffer_mutex;
static ringbuffer_t* buffer = nullptr;
static uint64_t last_timestamp_ms = 0;
+static bool isDebuggable = false;
+
+using android::base::StringPrintf;
static void nfcsnoop_cb(const uint8_t* data, const size_t length,
bool is_received, const uint64_t timestamp_us) {
@@ -85,28 +98,27 @@
if (deflateInit(&zs, Z_DEFAULT_COMPRESSION) != Z_OK) return false;
bool rc = true;
- uint8_t block_src[BLOCK_SIZE];
- uint8_t block_dst[BLOCK_SIZE];
+ std::unique_ptr<uint8_t> block_src(new uint8_t[BLOCK_SIZE]);
+ std::unique_ptr<uint8_t> block_dst(new uint8_t[BLOCK_SIZE]);
const size_t num_blocks =
(ringbuffer_size(rb_src) + BLOCK_SIZE - 1) / BLOCK_SIZE;
for (size_t i = 0; i < num_blocks; ++i) {
zs.avail_in =
- ringbuffer_peek(rb_src, i * BLOCK_SIZE, block_src, BLOCK_SIZE);
- zs.next_in = block_src;
+ ringbuffer_peek(rb_src, i * BLOCK_SIZE, block_src.get(), BLOCK_SIZE);
+ zs.next_in = block_src.get();
do {
zs.avail_out = BLOCK_SIZE;
- zs.next_out = block_dst;
+ zs.next_out = block_dst.get();
int err = deflate(&zs, (i == num_blocks - 1) ? Z_FINISH : Z_NO_FLUSH);
if (err == Z_STREAM_ERROR) {
rc = false;
break;
}
-
const size_t length = BLOCK_SIZE - zs.avail_out;
- ringbuffer_insert(rb_dst, block_dst, length);
+ ringbuffer_insert(rb_dst, block_dst.get(), length);
} while (zs.avail_out == 0);
}
@@ -121,7 +133,17 @@
static_cast<uint64_t>(tv.tv_usec);
uint8_t* p = (uint8_t*)(packet + 1) + packet->offset;
uint8_t mt = (*(p)&NCI_MT_MASK) >> NCI_MT_SHIFT;
-
+ if (isDebuggable &&
+ ringbuffer_available(buffer) < NFCSNOOP_MEM_BUFFER_THRESHOLD) {
+ if (storeNfcSnoopLogs(DEFAULT_NFCSNOOP_PATH, DEFAULT_NFCSNOOP_FILE_SIZE)) {
+ std::lock_guard<std::mutex> lock(buffer_mutex);
+ // Free the buffer after the content is stored in log file
+ ringbuffer_free(buffer);
+ buffer = nullptr;
+ // Allocate new buffer to store new NCI logs
+ debug_nfcsnoop_init();
+ }
+ }
if (mt == NCI_MT_DATA) {
nfcsnoop_cb(p, NCI_DATA_HDR_SIZE, is_received, timestamp);
} else if (packet->len > 2) {
@@ -131,6 +153,7 @@
void debug_nfcsnoop_init(void) {
if (buffer == nullptr) buffer = ringbuffer_init(NFCSNOOP_MEM_BUFFER_SIZE);
+ isDebuggable = property_get_int32("ro.debuggable", 0);
}
void debug_nfcsnoop_dump(int fd) {
@@ -189,3 +212,35 @@
error:
ringbuffer_free(ringbuffer);
}
+
+bool storeNfcSnoopLogs(std::string filepath, off_t maxFileSize) {
+ int fileStream;
+ off_t fileSize;
+ // check file size
+ struct stat st;
+ if (stat(filepath.c_str(), &st) == 0) {
+ fileSize = st.st_size;
+ } else {
+ fileSize = 0;
+ }
+
+ mode_t prevmask = umask(0);
+ if (fileSize >= maxFileSize) {
+ fileStream = open(filepath.c_str(), O_RDWR | O_CREAT | O_TRUNC,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
+ } else {
+ fileStream = open(filepath.c_str(), O_RDWR | O_CREAT | O_APPEND,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
+ }
+ umask(prevmask);
+
+ if (fileStream >= 0) {
+ debug_nfcsnoop_dump(fileStream);
+ close(fileStream);
+ return true;
+ } else {
+ LOG(ERROR) << StringPrintf("%s: fail to create, error = %d", __func__,
+ errno);
+ return false;
+ }
+}
diff --git a/src/fuzzers/ce/t3t.cc b/src/fuzzers/ce/t3t.cc
index 490f6b7..e774df7 100644
--- a/src/fuzzers/ce/t3t.cc
+++ b/src/fuzzers/ce/t3t.cc
@@ -93,13 +93,13 @@
for (auto it = ctx.Data.cbegin(); it != ctx.Data.cend(); ++it) {
NFC_HDR* p_msg;
p_msg = (NFC_HDR*)GKI_getbuf(sizeof(NFC_HDR) + it->size());
- if (p_msg == nullptr) {
+ if (p_msg == nullptr || it->size() < 1) {
FUZZLOG(MODULE_NAME ": GKI_getbuf returns null, size=%zu", it->size());
return;
}
/* Initialize NFC_HDR */
- p_msg->len = it->size();
+ p_msg->len = it->size() - 1;
p_msg->offset = 0;
uint8_t* p = (uint8_t*)(p_msg + 1) + p_msg->offset;
diff --git a/src/fuzzers/fuzz.sh b/src/fuzzers/fuzz.sh
index c8fc235..1cba253 100755
--- a/src/fuzzers/fuzz.sh
+++ b/src/fuzzers/fuzz.sh
@@ -102,7 +102,7 @@
SANITIZE_HOST="address" \
SANITIZE_TARGET="hwaddress fuzzer" \
NATIVE_COVERAGE="true" \
- COVERAGE_PATHS="system/nfc/src" \
+ NATIVE_COVERAGE_PATHS="system/nfc/src" \
make -j $FUZZER_NAME
popd
adb shell mkdir -p /$FUZZ_DIR
diff --git a/src/fuzzers/fuzz_cmn.cc b/src/fuzzers/fuzz_cmn.cc
index 43433bd..930026c 100644
--- a/src/fuzzers/fuzz_cmn.cc
+++ b/src/fuzzers/fuzz_cmn.cc
@@ -4,6 +4,7 @@
void delete_stack_non_volatile_store(bool){};
void debug_nfcsnoop_dump(int){};
std::string nfc_storage_path;
+bool storeNfcSnoopLogs(std::string, off_t) { return true; };
uint8_t appl_dta_mode_flag = 0;
bool nfc_debug_enabled = true;
diff --git a/src/fuzzers/rw/t1t.cc b/src/fuzzers/rw/t1t.cc
index 94670fd..f2c4f80 100644
--- a/src/fuzzers/rw/t1t.cc
+++ b/src/fuzzers/rw/t1t.cc
@@ -213,13 +213,13 @@
for (auto it = ctx.Data.cbegin() + 1; it != ctx.Data.cend(); ++it) {
NFC_HDR* p_msg;
p_msg = (NFC_HDR*)GKI_getbuf(sizeof(NFC_HDR) + it->size());
- if (p_msg == nullptr) {
+ if (p_msg == nullptr || it->size() < 1) {
FUZZLOG(MODULE_NAME ": GKI_getbuf returns null, size=%zu", it->size());
return;
}
/* Initialize NFC_HDR */
- p_msg->len = it->size();
+ p_msg->len = it->size() - 1;
p_msg->offset = 0;
uint8_t* p = (uint8_t*)(p_msg + 1) + p_msg->offset;
diff --git a/src/fuzzers/rw/t2t.cc b/src/fuzzers/rw/t2t.cc
index 57ddb0f..f829e35 100644
--- a/src/fuzzers/rw/t2t.cc
+++ b/src/fuzzers/rw/t2t.cc
@@ -172,13 +172,13 @@
for (auto it = ctx.Data.cbegin() + 1; it != ctx.Data.cend(); ++it) {
NFC_HDR* p_msg;
p_msg = (NFC_HDR*)GKI_getbuf(sizeof(NFC_HDR) + it->size());
- if (p_msg == nullptr) {
+ if (p_msg == nullptr || it->size() < 1) {
FUZZLOG(MODULE_NAME ": GKI_getbuf returns null, size=%zu", it->size());
return;
}
/* Initialize NFC_HDR */
- p_msg->len = it->size();
+ p_msg->len = it->size() - 1;
p_msg->offset = 0;
uint8_t* p = (uint8_t*)(p_msg + 1) + p_msg->offset;
diff --git a/src/fuzzers/rw/t3t.cc b/src/fuzzers/rw/t3t.cc
index b64ffc5..8853cf7 100644
--- a/src/fuzzers/rw/t3t.cc
+++ b/src/fuzzers/rw/t3t.cc
@@ -251,6 +251,11 @@
.status = NFC_STATUS_OK,
.p_data = p_msg,
}};
+ if (p_msg->len < 1) {
+ FUZZLOG(MODULE_NAME ": Ivalid message length=%hu", p_msg->len);
+ return;
+ }
+ p_msg->len--;
rf_cback(NFC_RF_CONN_ID, NFC_DATA_CEVT, &conn);
}
diff --git a/src/fuzzers/rw/t5t.cc b/src/fuzzers/rw/t5t.cc
index 9ddcca6..bd61f66 100644
--- a/src/fuzzers/rw/t5t.cc
+++ b/src/fuzzers/rw/t5t.cc
@@ -72,7 +72,8 @@
}
static bool Init_StayQuiet(Fuzz_Context& /*ctx*/) {
- return NFC_STATUS_OK == RW_I93StayQuiet();
+ uint8_t uid[] = TEST_UID_VALUE;
+ return NFC_STATUS_OK == RW_I93StayQuiet(uid);
}
static bool Init_ReadSingleBlock(Fuzz_Context& /*ctx*/) {
@@ -289,13 +290,13 @@
for (auto it = ctx.Data.cbegin() + 1; it != ctx.Data.cend(); ++it) {
NFC_HDR* p_msg;
p_msg = (NFC_HDR*)GKI_getbuf(sizeof(NFC_HDR) + it->size());
- if (p_msg == nullptr) {
+ if (p_msg == nullptr || it->size() < 1) {
FUZZLOG(MODULE_NAME ": GKI_getbuf returns null, size=%zu", it->size());
return;
}
/* Initialize NFC_HDR */
- p_msg->len = it->size();
+ p_msg->len = it->size() - 1;
p_msg->offset = 0;
uint8_t* p = (uint8_t*)(p_msg + 1) + p_msg->offset;
diff --git a/src/gki/common/gki_buffer.cc b/src/gki/common/gki_buffer.cc
index 72e02c6..858fe90 100644
--- a/src/gki/common/gki_buffer.cc
+++ b/src/gki/common/gki_buffer.cc
@@ -17,6 +17,7 @@
******************************************************************************/
#include <android-base/stringprintf.h>
#include <base/logging.h>
+#include <log/log.h>
#include "gki_int.h"
#if (GKI_NUM_TOTAL_BUF_POOLS > 16)
@@ -28,6 +29,8 @@
static void gki_remove_from_pool_list(uint8_t pool_id);
#endif /* BTU_STACK_LITE_ENABLED == FALSE */
+extern bool nfc_debug_enabled;
+
using android::base::StringPrintf;
/*******************************************************************************
@@ -253,22 +256,41 @@
*******************************************************************************/
void* GKI_getbuf(uint16_t size) {
BUFFER_HDR_T* p_hdr;
+ FREE_QUEUE_T* Q;
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- if (size == 0) {
- LOG(ERROR) << StringPrintf("getbuf: Size is zero");
+#if defined(DYN_ALLOC) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+ if (size == 0 || size > (USHRT_MAX - 3)) {
+ LOG(ERROR) << StringPrintf("getbuf: Requested size(%d) is invalid", size);
+ android_errorWriteLog(0x534e4554, "205729183");
+#ifndef DYN_ALLOC
abort();
+#else
+ return (nullptr);
+#endif
}
- size_t total_sz = size + sizeof(BUFFER_HDR_T);
+ size = ALIGN_POOL(size);
+ size_t total_sz = size + sizeof(BUFFER_HDR_T)
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ + sizeof(uint32_t);
+#else
+ ;
+#endif
p_hdr = (BUFFER_HDR_T*)GKI_os_malloc(total_sz);
if (!p_hdr) {
LOG(ERROR) << StringPrintf("unable to allocate buffer!!!!!");
+#ifndef DYN_ALLOC
abort();
+#else
+ return (nullptr);
+#endif
}
memset(p_hdr, 0, total_sz);
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ *(uint32_t*)((uint8_t*)p_hdr + BUFFER_HDR_SIZE + size) = MAGIC_NO;
+#endif
p_hdr->task_id = GKI_get_taskid();
p_hdr->status = BUF_STATUS_UNLINKED;
p_hdr->p_next = nullptr;
@@ -277,12 +299,18 @@
p_hdr->q_id = 0;
p_hdr->size = size;
- UNUSED(gki_alloc_free_queue);
+ GKI_disable();
+ Q = &gki_cb.com.freeq[p_hdr->q_id];
+ if (++Q->cur_cnt > Q->max_cnt) Q->max_cnt = Q->cur_cnt;
+ GKI_enable();
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s %p %d:%d", __func__, ((uint8_t*)p_hdr + BUFFER_HDR_SIZE), Q->cur_cnt,
+ Q->max_cnt);
+ UNUSED(gki_alloc_free_queue);
return (void*)((uint8_t*)p_hdr + BUFFER_HDR_SIZE);
#else
uint8_t i;
- FREE_QUEUE_T* Q;
tGKI_COM_CB* p_cb = &gki_cb.com;
if (size == 0) {
@@ -367,7 +395,7 @@
**
*******************************************************************************/
void* GKI_getpoolbuf(uint8_t pool_id) {
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+#if defined(DYN_ALLOC) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
uint16_t size = 0;
switch (pool_id) {
// NFC_NCI_POOL_ID, NFC_RW_POOL_ID and NFC_CE_POOL_ID are all redefined to
@@ -383,7 +411,11 @@
default:
LOG(ERROR) << StringPrintf("Unknown pool ID: %d", pool_id);
+#ifndef DYN_ALLOC
abort();
+#else
+ return (nullptr);
+#endif
break;
}
@@ -448,22 +480,6 @@
*******************************************************************************/
void GKI_freebuf(void* p_buf) {
BUFFER_HDR_T* p_hdr;
-
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- p_hdr = (BUFFER_HDR_T*)((uint8_t*)p_buf - BUFFER_HDR_SIZE);
-
- if (p_hdr->status != BUF_STATUS_UNLINKED) {
- GKI_exception(GKI_ERROR_FREEBUF_BUF_LINKED, "Freeing Linked Buf");
- return;
- }
-
- if (p_hdr->q_id >= GKI_NUM_TOTAL_BUF_POOLS) {
- GKI_exception(GKI_ERROR_FREEBUF_BAD_QID, "Bad Buf QId");
- return;
- }
-
- GKI_os_free(p_hdr);
-#else
FREE_QUEUE_T* Q;
#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
@@ -485,6 +501,14 @@
return;
}
+#if defined(DYN_ALLOC) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+ GKI_disable();
+ Q = &gki_cb.com.freeq[p_hdr->q_id];
+ if (Q->cur_cnt > 0) Q->cur_cnt--;
+ GKI_enable();
+
+ GKI_os_free(p_hdr);
+#else
GKI_disable();
/*
@@ -522,7 +546,7 @@
p_hdr = (BUFFER_HDR_T*)((uint8_t*)p_buf - BUFFER_HDR_SIZE);
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+#if defined(DYN_ALLOC) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
return p_hdr->size;
#else
if ((uintptr_t)p_hdr & 1) return (0);
@@ -554,6 +578,7 @@
if (*magic == MAGIC_NO) return false;
+ LOG(ERROR) << StringPrintf("%s 0x%x %p", __func__, *magic, p_buf);
return true;
#else
@@ -1283,10 +1308,35 @@
**
*******************************************************************************/
uint16_t GKI_get_pool_bufsize(uint8_t pool_id) {
+#if defined(DYN_ALLOC) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+ uint16_t size = 0;
+ switch (pool_id) {
+ case GKI_POOL_ID_0:
+ size = GKI_BUF0_SIZE;
+ break;
+ case GKI_POOL_ID_1:
+ size = GKI_BUF1_SIZE;
+ break;
+ case GKI_POOL_ID_2:
+ size = GKI_BUF2_SIZE;
+ break;
+ case GKI_POOL_ID_3:
+ size = GKI_BUF3_SIZE;
+ break;
+ /* Here could be more pool ids, but they are not used in the current
+ * implementation */
+ default:
+ LOG(ERROR) << StringPrintf("Unknown pool ID: %d", pool_id);
+ return (0);
+ break;
+ }
+ return (size);
+#else
if (pool_id < GKI_NUM_TOTAL_BUF_POOLS)
return (gki_cb.com.freeq[pool_id].size);
return (0);
+#endif
}
/*******************************************************************************
diff --git a/src/gki/common/gki_common.h b/src/gki/common/gki_common.h
index d814f07..701d23b 100644
--- a/src/gki/common/gki_common.h
+++ b/src/gki/common/gki_common.h
@@ -54,7 +54,7 @@
uint8_t task_id; /* task which allocated the buffer*/
uint8_t status; /* FREE, UNLINKED or QUEUED */
uint8_t Type;
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+#if defined(DYN_ALLOC) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
uint16_t size;
#endif
} BUFFER_HDR_T;
diff --git a/src/gki/ulinux/gki_ulinux.cc b/src/gki/ulinux/gki_ulinux.cc
index 093b58d..7262b5f 100644
--- a/src/gki/ulinux/gki_ulinux.cc
+++ b/src/gki/ulinux/gki_ulinux.cc
@@ -95,8 +95,8 @@
/* Call the actual thread entry point */
(p_pthread_info->task_entry)(p_pthread_info->params);
- LOG(ERROR) << StringPrintf("gki_task task_id=%i terminating",
- p_pthread_info->task_id);
+ LOG(WARNING) << StringPrintf("gki_task task_id=%i terminating",
+ p_pthread_info->task_id);
gki_cb.os.thread_id[p_pthread_info->task_id] = 0;
return nullptr;
@@ -338,9 +338,9 @@
/*******************************************************************************
**
- ** Function GKI_run
+ ** Function gki_system_tick_start_stop_cback
**
- ** Description This function runs a task
+ ** Description This function starts or stops timer
**
** Parameters: start: TRUE start system tick (again), FALSE stop
**
@@ -634,8 +634,8 @@
/* unlock thread_evt_mutex as pthread_cond_wait() does auto lock when cond
* is met */
pthread_mutex_unlock(&gki_cb.os.thread_evt_mutex[rtask]);
- LOG(ERROR) << StringPrintf("GKI TASK_DEAD received. exit thread %d...",
- rtask);
+ LOG(WARNING) << StringPrintf("GKI TASK_DEAD received. exit thread %d...",
+ rtask);
gki_cb.os.thread_id[rtask] = 0;
return (EVENT_MASK(GKI_SHUTDOWN_EVT));
diff --git a/src/include/buildcfg.h b/src/include/buildcfg.h
index b66695b..d69ed55 100644
--- a/src/include/buildcfg.h
+++ b/src/include/buildcfg.h
@@ -43,6 +43,10 @@
#define GKI_BUF0_SIZE 268
#define GKI_BUF0_MAX 40
+#ifdef DYN_ALLOC
+#define GKI_NUM_FIXED_BUF_POOLS 0
+#else
#define GKI_NUM_FIXED_BUF_POOLS 4
+#endif
#endif
diff --git a/src/include/debug_nfcsnoop.h b/src/include/debug_nfcsnoop.h
index 2dd7b6b..b846d69 100644
--- a/src/include/debug_nfcsnoop.h
+++ b/src/include/debug_nfcsnoop.h
@@ -47,4 +47,6 @@
// capture the packet
void nfcsnoop_capture(const NFC_HDR* packet, bool is_received);
+// store NCI log to file
+bool storeNfcSnoopLogs(std::string filepath, off_t maxFileSize);
#endif /* _DEBUG_NFCSNOOP_ */
diff --git a/src/include/nci_defs.h b/src/include/nci_defs.h
index b43cb1c..c23c39e 100644
--- a/src/include/nci_defs.h
+++ b/src/include/nci_defs.h
@@ -155,6 +155,7 @@
#define NCI_STATUS_ACTIVATION_FAILED 0xA1
#define NCI_STATUS_TEAR_DOWN 0xA2
/* RF Interface */
+#define NCI_STATUS_RF_FRAME_CORRUPTED 0x02
#define NCI_STATUS_RF_TRANSMISSION_ERR 0xB0
#define NCI_STATUS_RF_PROTOCOL_ERR 0xB1
#define NCI_STATUS_TIMEOUT 0xB2
@@ -428,17 +429,22 @@
#define NCI_PARAM_ID_CON_DEVICES_LIMIT 0x01
#define NCI_PARAM_ID_CON_DISCOVERY_PARAM 0x02
#define NCI_PARAM_ID_PA_BAILOUT 0x08
+#define NCI_PARAM_ID_PA_DEVICES_LIMIT 0x09
#define NCI_PARAM_ID_PB_AFI 0x10
#define NCI_PARAM_ID_PB_BAILOUT 0x11
#define NCI_PARAM_ID_PB_ATTRIB_PARAM1 0x12
+#define NCI_PARAM_ID_PB_DEVICES_LIMIT 0x14
#define NCI_PARAM_ID_PF_BIT_RATE 0x18
#define NCI_PARAM_ID_PF_RC 0x19
+#define NCI_PARAM_ID_PF_BAILOUT 0x19
+#define NCI_PARAM_ID_PF_DEVICES_LIMIT 0x1A
#define NCI_PARAM_ID_PB_H_INFO 0x20
#define NCI_PARAM_ID_PI_BIT_RATE 0x21
#define NCI_PARAM_ID_BITR_NFC_DEP 0x28
#define NCI_PARAM_ID_ATR_REQ_GEN_BYTES 0x29
#define NCI_PARAM_ID_ATR_REQ_CONFIG 0x2A
+#define NCI_PARAM_ID_PV_DEVICES_LIMIT 0x2F
#define NCI_PARAM_ID_LA_BIT_FRAME_SDD 0x30
#define NCI_PARAM_ID_LA_PLATFORM_CONFIG 0x31
@@ -485,6 +491,7 @@
#define NCI_PARAM_ID_WT 0x60
#define NCI_PARAM_ID_ATR_RES_GEN_BYTES 0x61
#define NCI_PARAM_ID_ATR_RSP_CONFIG 0x62
+#define NCI_PARAM_ID_PACM_BIT_RATE 0x68
#define NCI_PARAM_ID_RF_FIELD_INFO 0x80
#define NCI_PARAM_ID_NFC_DEP_OP 0x82
diff --git a/src/include/nfc_config.h b/src/include/nfc_config.h
index dda4260..aa7ac66 100644
--- a/src/include/nfc_config.h
+++ b/src/include/nfc_config.h
@@ -38,6 +38,9 @@
#define NAME_AID_MATCHING_MODE "AID_MATCHING_MODE"
#define NAME_OFFHOST_AID_ROUTE_PWR_STATE "OFFHOST_AID_ROUTE_PWR_STATE"
#define NAME_LEGACY_MIFARE_READER "LEGACY_MIFARE_READER"
+#define NAME_RECOVERY_OPTION "RECOVERY_OPTION"
+#define NAME_ALWAYS_ON_SET_EE_POWER_AND_LINK_CONF \
+ "ALWAYS_ON_SET_EE_POWER_AND_LINK_CONF"
/* Configs from vendor interface */
#define NAME_NFA_POLL_BAIL_OUT_MODE "NFA_POLL_BAIL_OUT_MODE"
diff --git a/src/nfa/dm/nfa_dm_act.cc b/src/nfa/dm/nfa_dm_act.cc
index aa494fb..51c841d 100644
--- a/src/nfa/dm/nfa_dm_act.cc
+++ b/src/nfa/dm/nfa_dm_act.cc
@@ -36,9 +36,10 @@
#if (NFC_NFCEE_INCLUDED == TRUE)
#include "nfa_ee_int.h"
-
#endif
+#include "nfc_int.h"
+
#if (NFA_SNEP_INCLUDED == TRUE)
#include "nfa_snep_int.h"
#endif
@@ -336,12 +337,13 @@
break;
#if (NFC_NFCEE_INCLUDED == TRUE)
- case NFC_NFCEE_DISCOVER_REVT: /* NFCEE Discover response */
- case NFC_NFCEE_INFO_REVT: /* NFCEE Discover Notification */
- case NFC_EE_ACTION_REVT: /* EE Action notification */
- case NFC_NFCEE_MODE_SET_REVT: /* NFCEE Mode Set response */
- case NFC_NFCEE_STATUS_REVT: /* NFCEE Status notification*/
- case NFC_SET_ROUTING_REVT: /* Configure Routing response */
+ case NFC_NFCEE_DISCOVER_REVT: /* NFCEE Discover response */
+ case NFC_NFCEE_INFO_REVT: /* NFCEE Discover Notification */
+ case NFC_EE_ACTION_REVT: /* EE Action notification */
+ case NFC_NFCEE_MODE_SET_REVT: /* NFCEE Mode Set response */
+ case NFC_NFCEE_STATUS_REVT: /* NFCEE Status notification*/
+ case NFC_SET_ROUTING_REVT: /* Configure Routing response */
+ case NFC_NFCEE_PL_CONTROL_REVT: /* NFCEE pwr and link ctrl response */
nfa_ee_proc_evt(event, p_data);
break;
@@ -949,6 +951,14 @@
poll_disc_mask |= NFA_DM_DISC_MASK_P_KOVIO;
}
+ if (!(nfc_cb.nci_interfaces & (1 << NCI_INTERFACE_NFC_DEP))) {
+ /* Remove NFC-DEP related Discovery mask, if NFC_DEP interface is not
+ * supported */
+ poll_disc_mask &=
+ ~(NFA_DM_DISC_MASK_PACM_NFC_DEP | NFA_DM_DISC_MASK_PAA_NFC_DEP |
+ NFA_DM_DISC_MASK_PFA_NFC_DEP | NFA_DM_DISC_MASK_PF_NFC_DEP);
+ }
+
nfa_dm_cb.poll_disc_handle = nfa_dm_add_rf_discover(
poll_disc_mask, NFA_DM_DISC_HOST_ID_DH, nfa_dm_poll_disc_cback);
@@ -1436,6 +1446,18 @@
} else if (event == NFC_DEACTIVATE_CEVT) {
NFC_SetStaticRfCback(nullptr);
}
+ /* needed if CLF reports timeout, transmission or protocol error to notify DTA
+ * that may need to resume discovery if DH stays in POLL_ACTIVE state */
+ else if (appl_dta_mode_flag && (event == NFC_ERROR_CEVT)) {
+ if (p_data) {
+ evt_data.data.status = p_data->data.status;
+ nfa_dm_conn_cback_event_notify(NFA_RW_INTF_ERROR_EVT, &evt_data);
+ } else {
+ LOG(ERROR) << StringPrintf(
+ "received NFC_ERROR_CEVT with NULL data "
+ "pointer");
+ }
+ }
}
/*******************************************************************************
@@ -1836,6 +1858,8 @@
return "NFC_NFCEE_INFO_REVT";
case NFC_NFCEE_MODE_SET_REVT:
return "NFC_NFCEE_MODE_SET_REVT";
+ case NFC_NFCEE_PL_CONTROL_REVT:
+ return "NFC_NFCEE_PL_CONTROL_REVT";
case NFC_RF_FIELD_REVT:
return "NFC_RF_FIELD_REVT";
case NFC_EE_ACTION_REVT:
diff --git a/src/nfa/dm/nfa_dm_api.cc b/src/nfa/dm/nfa_dm_api.cc
index 20b1730..87f6e80 100644
--- a/src/nfa/dm/nfa_dm_api.cc
+++ b/src/nfa/dm/nfa_dm_api.cc
@@ -760,7 +760,8 @@
DLOG_IF(INFO, nfc_debug_enabled) << __func__;
/* Post the API message */
- p_msg = (tNFA_DM_API_SET_RF_DISC_DUR*)GKI_getbuf(sizeof(NFC_HDR));
+ p_msg = (tNFA_DM_API_SET_RF_DISC_DUR*)GKI_getbuf(
+ sizeof(tNFA_DM_API_SET_RF_DISC_DUR));
if (p_msg != nullptr) {
p_msg->hdr.event = NFA_DM_API_SET_RF_DISC_DURATION_EVT;
diff --git a/src/nfa/dm/nfa_dm_main.cc b/src/nfa/dm/nfa_dm_main.cc
index 18ca93c..a65fbcd 100644
--- a/src/nfa/dm/nfa_dm_main.cc
+++ b/src/nfa/dm/nfa_dm_main.cc
@@ -446,6 +446,9 @@
/* Increment setcfg_pending counter */
nfa_dm_cb.setcfg_pending_num++;
}
+ if ((nfa_dm_cb.eDtaMode & NFA_DTA_HCEF_MODE) == NFA_DTA_HCEF_MODE) {
+ nfa_dm_cb.eDtaMode &= ~NFA_DTA_HCEF_MODE;
+ }
return (nfc_status);
} else {
diff --git a/src/nfa/ee/nfa_ee_act.cc b/src/nfa/ee/nfa_ee_act.cc
index 9fad48c..8b637d6 100644
--- a/src/nfa/ee/nfa_ee_act.cc
+++ b/src/nfa/ee/nfa_ee_act.cc
@@ -30,6 +30,7 @@
#include "nfa_dm_int.h"
#include "nfa_ee_int.h"
#include "nfa_hci_int.h"
+#include "nfc_int.h"
#include <statslog.h>
#include "metrics.h"
@@ -383,11 +384,16 @@
}
if (p_cb->nfcee_id == NFC_DH_ID &&
nfa_ee_proto_mask_list[xx] == NFA_PROTOCOL_MASK_NFC_DEP) {
- /* add NFC-DEP routing to HOST */
- add_route_tech_proto_tlv(&pp, NFC_ROUTE_TAG_PROTO, NFC_DH_ID,
- NCI_ROUTE_PWR_STATE_ON, NFC_PROTOCOL_NFC_DEP);
- DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf("%s - NFC DEP added for DH!!!", __func__);
+ /* add NFC-DEP routing to HOST if NFC_DEP interface is supported */
+ if (nfc_cb.nci_interfaces & (1 << NCI_INTERFACE_NFC_DEP)) {
+ add_route_tech_proto_tlv(&pp, NFC_ROUTE_TAG_PROTO, NFC_DH_ID,
+ NCI_ROUTE_PWR_STATE_ON,
+ NFC_PROTOCOL_NFC_DEP);
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - NFC DEP added for DH!!!", __func__);
+ } else {
+ continue;
+ }
} else {
add_route_tech_proto_tlv(&pp, proto_tag, p_cb->nfcee_id, power_cfg,
nfa_ee_proto_list[xx]);
@@ -1310,7 +1316,7 @@
/* report NFA_EE_REMOVE_AID_EVT to the callback associated the NFCEE */
p_cback = p_cb->p_ee_cback;
} else {
- LOG(ERROR) << StringPrintf(
+ LOG(WARNING) << StringPrintf(
"nfa_ee_api_remove_aid The AID entry is not in the database");
evt_data.status = NFA_STATUS_INVALID_PARAM;
}
@@ -1643,6 +1649,20 @@
/*******************************************************************************
**
+** Function nfa_ee_api_pwr_and_link_ctrl
+**
+** Description Initiates closing of the connection to the given NFCEE
+**
+** Returns void
+**
+*******************************************************************************/
+void nfa_ee_api_pwr_and_link_ctrl(tNFA_EE_MSG* p_data) {
+ NFC_NfceePLConfig(p_data->pwr_and_link_ctrl.nfcee_id,
+ p_data->pwr_and_link_ctrl.config);
+}
+
+/*******************************************************************************
+**
** Function nfa_ee_report_disc_done
**
** Description Process the callback for NFCEE discovery response
@@ -2078,7 +2098,7 @@
for (xx = 0; xx < nfa_ee_cb.cur_ee; xx++, p_cb++) {
if ((p_cb->ee_status & NFA_EE_STATUS_INT_MASK) ||
- (p_cb->ee_status != NFA_EE_STATUS_ACTIVE)) {
+ (p_cb->ee_status != NFA_EE_STATUS_ACTIVE) ) {
continue;
}
p_info->ee_handle = (tNFA_HANDLE)p_cb->nfcee_id | NFA_HANDLE_GROUP_EE;
@@ -2151,8 +2171,8 @@
/* Start routing table update debounce timer */
nfa_ee_start_timer();
}
- LOG(ERROR) << StringPrintf("%s p_rsp->status:0x%02x", __func__,
- p_rsp->status);
+ LOG(WARNING) << StringPrintf("%s p_rsp->status:0x%02x", __func__,
+ p_rsp->status);
if (p_rsp->status == NFA_STATUS_OK) {
if (p_rsp->mode == NFA_EE_MD_ACTIVATE) {
p_cb->ee_status = NFC_NFCEE_STATUS_ACTIVE;
@@ -2261,6 +2281,23 @@
/*******************************************************************************
**
+** Function nfa_ee_pwr_and_link_ctrl_rsp
+**
+** Description Process the result for NCI response
+**
+** Returns void
+**
+*******************************************************************************/
+void nfa_ee_pwr_and_link_ctrl_rsp(tNFA_EE_MSG* p_data) {
+ tNFA_EE_CBACK_DATA evt_data;
+ if (p_data != nullptr) {
+ evt_data.status = NFA_STATUS_OK;
+ nfa_ee_report_event(nullptr, NFA_EE_PWR_AND_LINK_CTRL_EVT, &evt_data);
+ }
+}
+
+/*******************************************************************************
+**
** Function nfa_ee_nci_conn
**
** Description process the connection callback events
diff --git a/src/nfa/ee/nfa_ee_api.cc b/src/nfa/ee/nfa_ee_api.cc
index bb6005a..4881261 100644
--- a/src/nfa/ee/nfa_ee_api.cc
+++ b/src/nfa/ee/nfa_ee_api.cc
@@ -953,3 +953,46 @@
return status;
}
+
+/*******************************************************************************
+**
+** Function NFA_EePowerAndLinkCtrl
+**
+** Description This Control Message is used by the DH to constrain the way
+** the NFCC manages the power supply and communication links
+** between the NFCC and its connected NFCEEs.
+**
+** Returns NFA_STATUS_OK if successfully initiated
+** NFA_STATUS_FAILED otherwise
+** NFA_STATUS_INVALID_PARAM If bad parameter
+**
+*******************************************************************************/
+tNFA_STATUS NFA_EePowerAndLinkCtrl(tNFA_HANDLE ee_handle, uint8_t config) {
+ tNFA_EE_API_PWR_AND_LINK_CTRL* p_msg;
+ tNFA_STATUS status = NFA_STATUS_FAILED;
+ uint8_t nfcee_id = (uint8_t)(ee_handle & 0xFF);
+ tNFA_EE_ECB* p_cb;
+
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("handle:<0x%x>, config:<0x%x>", ee_handle, config);
+ p_cb = nfa_ee_find_ecb(nfcee_id);
+
+ if ((p_cb == nullptr) || (p_cb->ee_status != NFA_EE_STATUS_ACTIVE)) {
+ LOG(ERROR) << StringPrintf("Bad ee_handle");
+ status = NFA_STATUS_INVALID_PARAM;
+ } else {
+ p_msg = (tNFA_EE_API_PWR_AND_LINK_CTRL*)GKI_getbuf(
+ sizeof(tNFA_EE_API_PWR_AND_LINK_CTRL));
+ if (p_msg != nullptr) {
+ p_msg->hdr.event = NFA_EE_API_PWR_AND_LINK_CTRL_EVT;
+ p_msg->nfcee_id = nfcee_id;
+ p_msg->config = config;
+
+ nfa_sys_sendmsg(p_msg);
+
+ status = NFA_STATUS_OK;
+ }
+ }
+
+ return status;
+}
diff --git a/src/nfa/ee/nfa_ee_main.cc b/src/nfa/ee/nfa_ee_main.cc
index 69a70d0..6331771 100644
--- a/src/nfa/ee/nfa_ee_main.cc
+++ b/src/nfa/ee/nfa_ee_main.cc
@@ -52,35 +52,37 @@
const tNFA_EE_SM_ACT nfa_ee_actions[] = {
/* NFA-EE action function/ internal events */
- nfa_ee_api_discover, /* NFA_EE_API_DISCOVER_EVT */
- nfa_ee_api_register, /* NFA_EE_API_REGISTER_EVT */
- nfa_ee_api_deregister, /* NFA_EE_API_DEREGISTER_EVT */
- nfa_ee_api_mode_set, /* NFA_EE_API_MODE_SET_EVT */
- nfa_ee_api_set_tech_cfg, /* NFA_EE_API_SET_TECH_CFG_EVT */
- nfa_ee_api_clear_tech_cfg, /*NFA_EE_API_CLEAR_TECH_CFG_EVT */
- nfa_ee_api_set_proto_cfg, /* NFA_EE_API_SET_PROTO_CFG_EVT */
- nfa_ee_api_clear_proto_cfg, /*NFA_EE_API_CLEAR_PROTO_CFG_EVT*/
- nfa_ee_api_add_aid, /* NFA_EE_API_ADD_AID_EVT */
- nfa_ee_api_remove_aid, /* NFA_EE_API_REMOVE_AID_EVT */
- nfa_ee_api_add_sys_code, /* NFA_EE_API_ADD_SYSCODE_EVT */
- nfa_ee_api_remove_sys_code, /* NFA_EE_API_REMOVE_SYSCODE_EVT*/
- nfa_ee_api_lmrt_size, /* NFA_EE_API_LMRT_SIZE_EVT */
- nfa_ee_api_update_now, /* NFA_EE_API_UPDATE_NOW_EVT */
- nfa_ee_api_connect, /* NFA_EE_API_CONNECT_EVT */
- nfa_ee_api_send_data, /* NFA_EE_API_SEND_DATA_EVT */
- nfa_ee_api_disconnect, /* NFA_EE_API_DISCONNECT_EVT */
- nfa_ee_nci_disc_rsp, /* NFA_EE_NCI_DISC_RSP_EVT */
- nfa_ee_nci_disc_ntf, /* NFA_EE_NCI_DISC_NTF_EVT */
- nfa_ee_nci_mode_set_rsp, /* NFA_EE_NCI_MODE_SET_RSP_EVT */
- nfa_ee_nci_conn, /* NFA_EE_NCI_CONN_EVT */
- nfa_ee_nci_conn, /* NFA_EE_NCI_DATA_EVT */
- nfa_ee_nci_action_ntf, /* NFA_EE_NCI_ACTION_NTF_EVT */
- nfa_ee_nci_disc_req_ntf, /* NFA_EE_NCI_DISC_REQ_NTF_EVT */
- nfa_ee_nci_wait_rsp, /* NFA_EE_NCI_WAIT_RSP_EVT */
- nfa_ee_rout_timeout, /* NFA_EE_ROUT_TIMEOUT_EVT */
- nfa_ee_discv_timeout, /* NFA_EE_DISCV_TIMEOUT_EVT */
- nfa_ee_lmrt_to_nfcc, /* NFA_EE_CFG_TO_NFCC_EVT */
- nfa_ee_nci_nfcee_status_ntf /*NFA_EE_NCI_NFCEE_STATUS_NTF_EVT*/
+ nfa_ee_api_discover, /* NFA_EE_API_DISCOVER_EVT */
+ nfa_ee_api_register, /* NFA_EE_API_REGISTER_EVT */
+ nfa_ee_api_deregister, /* NFA_EE_API_DEREGISTER_EVT */
+ nfa_ee_api_mode_set, /* NFA_EE_API_MODE_SET_EVT */
+ nfa_ee_api_set_tech_cfg, /* NFA_EE_API_SET_TECH_CFG_EVT */
+ nfa_ee_api_clear_tech_cfg, /*NFA_EE_API_CLEAR_TECH_CFG_EVT */
+ nfa_ee_api_set_proto_cfg, /* NFA_EE_API_SET_PROTO_CFG_EVT */
+ nfa_ee_api_clear_proto_cfg, /*NFA_EE_API_CLEAR_PROTO_CFG_EVT*/
+ nfa_ee_api_add_aid, /* NFA_EE_API_ADD_AID_EVT */
+ nfa_ee_api_remove_aid, /* NFA_EE_API_REMOVE_AID_EVT */
+ nfa_ee_api_add_sys_code, /* NFA_EE_API_ADD_SYSCODE_EVT */
+ nfa_ee_api_remove_sys_code, /* NFA_EE_API_REMOVE_SYSCODE_EVT*/
+ nfa_ee_api_lmrt_size, /* NFA_EE_API_LMRT_SIZE_EVT */
+ nfa_ee_api_update_now, /* NFA_EE_API_UPDATE_NOW_EVT */
+ nfa_ee_api_connect, /* NFA_EE_API_CONNECT_EVT */
+ nfa_ee_api_send_data, /* NFA_EE_API_SEND_DATA_EVT */
+ nfa_ee_api_disconnect, /* NFA_EE_API_DISCONNECT_EVT */
+ nfa_ee_api_pwr_and_link_ctrl, /* NFA_EE_API_PWR_AND_LINK_CTRL_EVT */
+ nfa_ee_nci_disc_rsp, /* NFA_EE_NCI_DISC_RSP_EVT */
+ nfa_ee_nci_disc_ntf, /* NFA_EE_NCI_DISC_NTF_EVT */
+ nfa_ee_nci_mode_set_rsp, /* NFA_EE_NCI_MODE_SET_RSP_EVT */
+ nfa_ee_nci_conn, /* NFA_EE_NCI_CONN_EVT */
+ nfa_ee_nci_conn, /* NFA_EE_NCI_DATA_EVT */
+ nfa_ee_nci_action_ntf, /* NFA_EE_NCI_ACTION_NTF_EVT */
+ nfa_ee_nci_disc_req_ntf, /* NFA_EE_NCI_DISC_REQ_NTF_EVT */
+ nfa_ee_nci_wait_rsp, /* NFA_EE_NCI_WAIT_RSP_EVT */
+ nfa_ee_rout_timeout, /* NFA_EE_ROUT_TIMEOUT_EVT */
+ nfa_ee_discv_timeout, /* NFA_EE_DISCV_TIMEOUT_EVT */
+ nfa_ee_lmrt_to_nfcc, /* NFA_EE_CFG_TO_NFCC_EVT */
+ nfa_ee_nci_nfcee_status_ntf, /*NFA_EE_NCI_NFCEE_STATUS_NTF_EVT*/
+ nfa_ee_pwr_and_link_ctrl_rsp /* NFA_EE_PWR_CONTROL_EVT */
};
/*******************************************************************************
@@ -354,6 +356,10 @@
case NFC_NFCEE_STATUS_REVT:
int_event = NFA_EE_NCI_NFCEE_STATUS_NTF_EVT;
break;
+
+ case NFC_NFCEE_PL_CONTROL_REVT:
+ int_event = NFA_EE_PWR_CONTROL_EVT;
+ break;
}
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
@@ -598,6 +604,8 @@
return "API_SEND_DATA";
case NFA_EE_API_DISCONNECT_EVT:
return "API_DISCONNECT";
+ case NFA_EE_API_PWR_AND_LINK_CTRL_EVT:
+ return "NFA_EE_API_PWR_AND_LINK_CTRL_EVT";
case NFA_EE_NCI_DISC_RSP_EVT:
return "NCI_DISC_RSP";
case NFA_EE_NCI_DISC_NTF_EVT:
@@ -620,6 +628,8 @@
return "NFA_EE_DISCV_TIMEOUT_EVT";
case NFA_EE_CFG_TO_NFCC_EVT:
return "CFG_TO_NFCC";
+ case NFA_EE_PWR_CONTROL_EVT:
+ return "NFA_EE_PWR_CONTROL_EVT";
default:
return "Unknown";
}
diff --git a/src/nfa/include/nfa_api.h b/src/nfa/include/nfa_api.h
index d139966..d89c6f3 100755
--- a/src/nfa/include/nfa_api.h
+++ b/src/nfa/include/nfa_api.h
@@ -59,9 +59,14 @@
#define NFA_STATUS_INVALID_PARAM NCI_STATUS_INVALID_PARAM
/* Already started */
#define NFA_STATUS_ALREADY_STARTED NCI_STATUS_ALREADY_STARTED
+/* RF frame error */
+#define NFA_STATUS_RF_FRAME_CORRUPTED NCI_STATUS_RF_FRAME_CORRUPTED
+/* RF protocol error */
+#define NFA_STATUS_RF_PROTOCOL_ERR NCI_STATUS_RF_PROTOCOL_ERR
/* RF Timeout */
#define NFA_STATUS_TIMEOUT NCI_STATUS_TIMEOUT
+#define NFA_STATUS_CONTINUE NFC_STATUS_CONTINUE
/* Out of GKI buffers */
#define NFA_STATUS_NO_BUFFERS NFC_STATUS_NO_BUFFERS
/* Protocol mismatch between API and activated one */
@@ -331,6 +336,8 @@
#define NFA_P2P_PAUSED_EVT 38
/* P2P services resumed event */
#define NFA_P2P_RESUMED_EVT 39
+/* T2T command completed */
+#define NFA_T2T_CMD_CPLT_EVT 40
/* NFC deactivation type */
#define NFA_DEACTIVATE_TYPE_IDLE NFC_DEACTIVATE_TYPE_IDLE
diff --git a/src/nfa/include/nfa_ee_api.h b/src/nfa/include/nfa_ee_api.h
index 8a60dcf..30a0867 100644
--- a/src/nfa/include/nfa_ee_api.h
+++ b/src/nfa/include/nfa_ee_api.h
@@ -67,6 +67,7 @@
NFA_EE_NEW_EE_EVT, /* A new NFCEE is discovered */
NFA_EE_ACTION_EVT, /* An action happened in NFCEE */
NFA_EE_DISCOVER_REQ_EVT, /* NFCEE Discover Request Notification */
+ NFA_EE_PWR_AND_LINK_CTRL_EVT, /* NFCEE power and link ctrl */
NFA_EE_NO_MEM_ERR_EVT, /* Error - out of GKI buffers */
NFA_EE_NO_CB_ERR_EVT /* Error - Can not find control block or wrong state */
};
@@ -584,4 +585,20 @@
*******************************************************************************/
extern tNFA_STATUS NFA_EeDisconnect(tNFA_HANDLE ee_handle);
+/*******************************************************************************
+**
+** Function NFA_EePowerAndLinkCtrl
+**
+** Description This Control Message is used by the DH to constrain the way
+** the NFCC manages the power supply and communication links
+** between the NFCC and its connected NFCEEs.
+**
+** Returns NFA_STATUS_OK if successfully initiated
+** NFA_STATUS_FAILED otherwise
+** NFA_STATUS_INVALID_PARAM If bad parameter
+**
+*******************************************************************************/
+extern tNFA_STATUS NFA_EePowerAndLinkCtrl(tNFA_HANDLE ee_handle,
+ uint8_t config);
+
#endif /* NFA_EE_API_H */
diff --git a/src/nfa/include/nfa_ee_int.h b/src/nfa/include/nfa_ee_int.h
index bf9a864..cf1781a 100644
--- a/src/nfa/include/nfa_ee_int.h
+++ b/src/nfa/include/nfa_ee_int.h
@@ -62,6 +62,7 @@
NFA_EE_API_CONNECT_EVT,
NFA_EE_API_SEND_DATA_EVT,
NFA_EE_API_DISCONNECT_EVT,
+ NFA_EE_API_PWR_AND_LINK_CTRL_EVT,
NFA_EE_NCI_DISC_RSP_EVT,
NFA_EE_NCI_DISC_NTF_EVT,
@@ -76,8 +77,8 @@
NFA_EE_DISCV_TIMEOUT_EVT,
NFA_EE_CFG_TO_NFCC_EVT,
NFA_EE_NCI_NFCEE_STATUS_NTF_EVT,
+ NFA_EE_PWR_CONTROL_EVT,
NFA_EE_MAX_EVT
-
};
typedef uint16_t tNFA_EE_INT_EVT;
@@ -129,7 +130,7 @@
/* AID routing changed */
#define NFA_EE_ECB_FLAGS_AID 0x08
/* System Code routing changed */
-#define NFA_EE_ECB_FLAGS_SYSCODE 0xE0
+#define NFA_EE_ECB_FLAGS_SYSCODE 0x01
/* VS changed */
#define NFA_EE_ECB_FLAGS_VS 0x10
/* Restore related */
@@ -335,6 +336,14 @@
uint8_t nfcee_id;
} tNFA_EE_API_DISCONNECT;
+/* data type for NFA_EE_API_PWR_AND_LINK_CTRL_EVT */
+typedef struct {
+ NFC_HDR hdr;
+ tNFA_EE_ECB* p_cb;
+ uint8_t nfcee_id;
+ uint8_t config;
+} tNFA_EE_API_PWR_AND_LINK_CTRL;
+
/* common data type for internal events with nfa_ee_use_cfg_cb[] as TRUE */
typedef struct {
NFC_HDR hdr;
@@ -393,6 +402,12 @@
tNFC_NFCEE_STATUS_REVT* p_data;
} tNFA_EE_NCI_NFCEE_STATUS_NTF;
+/* data type for NFA_EE_NCI_NFCEE_STATUS_EVT */
+typedef struct {
+ NFC_HDR hdr;
+ tNFC_NFCEE_PL_CONTROL_REVT* p_data;
+} tNFA_EE_NCI_PWR_AND_LINK_CTRL_RSP;
+
/* union of all event data types */
typedef union {
NFC_HDR hdr;
@@ -413,6 +428,7 @@
tNFA_EE_API_CONNECT connect;
tNFA_EE_API_SEND_DATA send_data;
tNFA_EE_API_DISCONNECT disconnect;
+ tNFA_EE_API_PWR_AND_LINK_CTRL pwr_and_link_ctrl;
tNFA_EE_NCI_DISC_RSP disc_rsp;
tNFA_EE_NCI_DISC_NTF disc_ntf;
tNFA_EE_NCI_MODE_SET mode_set_rsp;
@@ -421,6 +437,7 @@
tNFA_EE_NCI_ACTION act;
tNFA_EE_NCI_DISC_REQ disc_req;
tNFA_EE_NCI_NFCEE_STATUS_NTF nfcee_status_ntf;
+ tNFA_EE_NCI_PWR_AND_LINK_CTRL_RSP ncfee_pwr_and_link_ctrl_rsp;
} tNFA_EE_MSG;
/* type for State Machine (SM) action functions */
@@ -545,11 +562,13 @@
void nfa_ee_api_connect(tNFA_EE_MSG* p_data);
void nfa_ee_api_send_data(tNFA_EE_MSG* p_data);
void nfa_ee_api_disconnect(tNFA_EE_MSG* p_data);
+void nfa_ee_api_pwr_and_link_ctrl(tNFA_EE_MSG* p_data);
void nfa_ee_report_disc_done(bool notify_sys);
void nfa_ee_nci_disc_rsp(tNFA_EE_MSG* p_data);
void nfa_ee_nci_disc_ntf(tNFA_EE_MSG* p_data);
void nfa_ee_nci_mode_set_rsp(tNFA_EE_MSG* p_data);
void nfa_ee_nci_nfcee_status_ntf(tNFA_EE_MSG* p_data);
+void nfa_ee_pwr_and_link_ctrl_rsp(tNFA_EE_MSG* p_data);
void nfa_ee_nci_wait_rsp(tNFA_EE_MSG* p_data);
void nfa_ee_nci_conn(tNFA_EE_MSG* p_data);
void nfa_ee_nci_action_ntf(tNFA_EE_MSG* p_data);
diff --git a/src/nfa/include/nfa_rw_api.h b/src/nfa/include/nfa_rw_api.h
index ee9bec7..c9ba23c 100644
--- a/src/nfa/include/nfa_rw_api.h
+++ b/src/nfa/include/nfa_rw_api.h
@@ -417,6 +417,24 @@
/*******************************************************************************
**
+** Function NFA_RwT2tReadDynLockBytes
+**
+** Description:
+** Configure NFA skip_dyn_locks flag to send or not READ commands to the
+** activated Type 2 tag to read the DynLock_Area contents.
+**
+** When the operation has completed (or if an error occurs), the app will
+** be notified with NFA_T2T_CMD_CPLT_EVT.
+**
+** Returns:
+** NFA_STATUS_OK if successfully initiated
+** NFA_STATUS_FAILED otherwise
+**
+*******************************************************************************/
+extern tNFA_STATUS NFA_RwT2tReadDynLockBytes(bool read_dyn_locks);
+
+/*******************************************************************************
+**
** Function NFA_RwT3tRead
**
** Description:
@@ -491,7 +509,7 @@
** NFA_STATUS_FAILED otherwise
**
*******************************************************************************/
-extern tNFA_STATUS NFA_RwI93StayQuiet(void);
+extern tNFA_STATUS NFA_RwI93StayQuiet(uint8_t* p_uid);
/*******************************************************************************
**
@@ -742,4 +760,21 @@
extern tNFA_STATUS NFA_RwI93GetMultiBlockSecurityStatus(
uint8_t first_block_number, uint16_t number_blocks);
+/*******************************************************************************
+**
+** Function NFA_RwI93SetAddressingMode
+**
+** Description:
+** Set addressing mode to use to communicate with T5T tag.
+** mode = true: addressed (default if API not called)
+** mode = false: non-addressed
+**
+** Returns:
+** NFA_STATUS_OK if successfully initiated
+** NFA_STATUS_WRONG_PROTOCOL: T5T tag not activated
+** NFA_STATUS_FAILED otherwise
+**
+*******************************************************************************/
+extern tNFA_STATUS NFA_RwI93SetAddressingMode(bool mode);
+
#endif /* NFA_RW_API_H */
diff --git a/src/nfa/include/nfa_rw_int.h b/src/nfa/include/nfa_rw_int.h
index f9a53c2..38101d7 100644
--- a/src/nfa/include/nfa_rw_int.h
+++ b/src/nfa/include/nfa_rw_int.h
@@ -95,6 +95,7 @@
NFA_RW_OP_T2T_READ,
NFA_RW_OP_T2T_WRITE,
NFA_RW_OP_T2T_SECTOR_SELECT,
+ NFA_RW_OP_T2T_READ_DYN_LOCKS,
/* Exclusive Type-3 tag operations */
NFA_RW_OP_T3T_READ,
@@ -117,7 +118,7 @@
NFA_RW_OP_I93_LOCK_DSFID,
NFA_RW_OP_I93_GET_SYS_INFO,
NFA_RW_OP_I93_GET_MULTI_BLOCK_STATUS,
-
+ NFA_RW_OP_I93_SET_ADDR_MODE,
NFA_RW_OP_MAX
};
typedef uint8_t tNFA_RW_OP;
@@ -164,6 +165,11 @@
/* NFA_RW_OP_T2T_SECTOR_SELECT params */
typedef struct { uint8_t sector_number; } tNFA_RW_OP_PARAMS_T2T_SECTOR_SELECT;
+/* NFA_RW_OP_T2T_READ_DYN_LOCKS params */
+typedef struct {
+ bool read_dyn_locks;
+} tNFA_RW_OP_PARAMS_T2T_READ_DYN_LOCKS;
+
/* NFA_RW_OP_T3T_READ params */
typedef struct {
uint8_t num_blocks;
@@ -184,6 +190,7 @@
bool afi_present;
uint8_t afi;
uint8_t dsfid;
+ bool addr_mode;
uint16_t first_block_number;
uint16_t number_blocks;
uint8_t* p_data;
@@ -209,6 +216,7 @@
tNFA_RW_OP_PARAMS_T2T_READ t2t_read;
tNFA_RW_OP_PARAMS_T2T_WRITE t2t_write;
tNFA_RW_OP_PARAMS_T2T_SECTOR_SELECT t2t_sector_select;
+ tNFA_RW_OP_PARAMS_T2T_READ_DYN_LOCKS t2t_read_dyn_locks;
/* params for NFA_RW_OP_T3T_READ and NFA_RW_OP_T3T_WRITE */
tNFA_RW_OP_PARAMS_T3T_READ t3t_read;
@@ -315,6 +323,7 @@
uint8_t i93_block_size;
uint16_t i93_num_block;
uint8_t i93_uid[I93_UID_BYTE_LEN];
+ uint8_t i93_addr_mode;
} tNFA_RW_CB;
extern tNFA_RW_CB nfa_rw_cb;
diff --git a/src/nfa/rw/nfa_rw_act.cc b/src/nfa/rw/nfa_rw_act.cc
index 0c0e608..4721b68 100644
--- a/src/nfa/rw/nfa_rw_act.cc
+++ b/src/nfa/rw/nfa_rw_act.cc
@@ -776,7 +776,7 @@
break;
case RW_T2T_TLV_DETECT_EVT: /* Lock control/Mem/Prop tlv detection complete
- */
+ */
nfa_rw_handle_tlv_detect(p_rw_data);
break;
@@ -966,6 +966,9 @@
break;
case RW_T3T_INTF_ERROR_EVT:
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s; send deactivate", __func__);
+ nfa_dm_rf_deactivate(NFA_DEACTIVATE_TYPE_DISCOVERY);
conn_evt_data.status = p_rw_data->status;
nfa_dm_act_conn_cback_notify(NFA_RW_INTF_ERROR_EVT, &conn_evt_data);
break;
@@ -1696,8 +1699,7 @@
status = RW_T3tUpdateNDef(nfa_rw_cb.ndef_wr_len, nfa_rw_cb.p_ndef_wr_buf);
} else if (NFC_PROTOCOL_ISO_DEP == protocol) {
/* ISODEP/4A,4B- NFC-A or NFC-B */
- status = RW_T4tUpdateNDef((uint16_t)nfa_rw_cb.ndef_wr_len,
- nfa_rw_cb.p_ndef_wr_buf);
+ status = RW_T4tUpdateNDef(nfa_rw_cb.ndef_wr_len, nfa_rw_cb.p_ndef_wr_buf);
} else if (NFC_PROTOCOL_T5T == protocol) {
/* ISO 15693 */
status = RW_I93UpdateNDef((uint16_t)nfa_rw_cb.ndef_wr_len,
@@ -1790,8 +1792,8 @@
} else if (nfa_rw_cb.ndef_st == NFA_RW_NDEF_ST_FALSE) {
if (nfa_rw_cb.protocol == NFC_PROTOCOL_T1T) {
/* For Type 1 tag, NDEF can be written on Initialized tag
- * Perform ndef detection first to check if tag is in Initialized state to
- * Write NDEF */
+ * Perform ndef detection first to check if tag is in Initialized state
+ * to Write NDEF */
write_status = nfa_rw_start_ndef_detection();
} else {
/* Tag is not NDEF */
@@ -2366,7 +2368,7 @@
case NFA_RW_OP_I93_STAY_QUIET:
i93_command = I93_CMD_STAY_QUIET;
- status = RW_I93StayQuiet();
+ status = RW_I93StayQuiet(p_data->op_req.params.i93_cmd.p_data);
break;
case NFA_RW_OP_I93_READ_SINGLE_BLOCK:
@@ -2449,6 +2451,25 @@
p_data->op_req.params.i93_cmd.number_blocks);
break;
+ case NFA_RW_OP_I93_SET_ADDR_MODE:
+ i93_command = I93_CMD_SET_ADDR_MODE;
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - T5T addressing mode (0: addressed, "
+ "1: non-addressed) is %d",
+ __func__, p_data->op_req.params.i93_cmd.addr_mode);
+
+ status = RW_I93SetAddressingMode(p_data->op_req.params.i93_cmd.addr_mode);
+ if (status != NFC_STATUS_OK) {
+ break;
+ }
+
+ /* Command complete - perform cleanup, notify app */
+ nfa_rw_command_complete();
+ conn_evt_data.i93_cmd_cplt.status = NFA_STATUS_OK;
+ conn_evt_data.i93_cmd_cplt.sent_command = i93_command;
+ nfa_dm_act_conn_cback_notify(NFA_I93_CMD_CPLT_EVT, &conn_evt_data);
+ break;
+
default:
break;
}
@@ -2634,22 +2655,16 @@
memcpy(tag_params.t2t.uid, p_activate_params->rf_tech_param.param.pa.nfcid1,
p_activate_params->rf_tech_param.param.pa.nfcid1_len);
} else if (NFC_PROTOCOL_T3T == nfa_rw_cb.protocol) {
- if (appl_dta_mode_flag) {
- /* Incase of DTA mode Dont send commands to get system code. Just notify
- * activation */
- activate_notify = true;
- } else {
- /* Delay notifying upper layer of NFA_ACTIVATED_EVT until system codes
- * are retrieved */
- activate_notify = false;
+ /* Delay notifying upper layer of NFA_ACTIVATED_EVT until system codes
+ * are retrieved */
+ activate_notify = false;
- /* Issue command to get Felica system codes */
- tNFA_RW_MSG msg;
- msg.op_req.op = NFA_RW_OP_T3T_GET_SYSTEM_CODES;
- bool free_buf = nfa_rw_handle_op_req(&msg);
- CHECK(free_buf)
- << "nfa_rw_handle_op_req is holding on to soon-garbage stack memory.";
- }
+ /* Issue command to get Felica system codes */
+ tNFA_RW_MSG msg;
+ msg.op_req.op = NFA_RW_OP_T3T_GET_SYSTEM_CODES;
+ bool free_buf = nfa_rw_handle_op_req(&msg);
+ CHECK(free_buf)
+ << "nfa_rw_handle_op_req is holding on to soon-garbage stack memory.";
} else if (NFA_PROTOCOL_T5T == nfa_rw_cb.protocol) {
/* Delay notifying upper layer of NFA_ACTIVATED_EVT to retrieve additional
* tag infomation */
@@ -2699,8 +2714,23 @@
/* Tag-it HF-I Plus Chip/Inlay supports Get System Information Command */
/* just try for others */
- if (RW_I93GetSysInfo(nfa_rw_cb.i93_uid) != NFC_STATUS_OK) {
- /* notify activation without AFI/MEM size/IC-Ref */
+ if (!appl_dta_mode_flag) {
+ if (RW_I93GetSysInfo(nfa_rw_cb.i93_uid) != NFC_STATUS_OK) {
+ /* notify activation without AFI/MEM size/IC-Ref */
+ nfa_rw_cb.flags &= ~NFA_RW_FL_ACTIVATION_NTF_PENDING;
+ activate_notify = true;
+
+ tag_params.i93.info_flags = I93_INFO_FLAG_DSFID;
+ tag_params.i93.dsfid = nfa_rw_cb.i93_dsfid;
+ tag_params.i93.block_size = 0;
+ tag_params.i93.num_block = 0;
+ memcpy(tag_params.i93.uid, nfa_rw_cb.i93_uid, I93_UID_BYTE_LEN);
+ } else {
+ /* reset memory size */
+ nfa_rw_cb.i93_block_size = 0;
+ nfa_rw_cb.i93_num_block = 0;
+ }
+ } else {
nfa_rw_cb.flags &= ~NFA_RW_FL_ACTIVATION_NTF_PENDING;
activate_notify = true;
@@ -2709,10 +2739,6 @@
tag_params.i93.block_size = 0;
tag_params.i93.num_block = 0;
memcpy(tag_params.i93.uid, nfa_rw_cb.i93_uid, I93_UID_BYTE_LEN);
- } else {
- /* reset memory size */
- nfa_rw_cb.i93_block_size = 0;
- nfa_rw_cb.i93_num_block = 0;
}
}
}
@@ -2779,6 +2805,7 @@
**
*******************************************************************************/
bool nfa_rw_handle_op_req(tNFA_RW_MSG* p_data) {
+ tNFA_CONN_EVT_DATA conn_evt_data;
bool freebuf = true;
uint16_t presence_check_start_delay = 0;
@@ -2817,7 +2844,6 @@
/* Call appropriate handler for requested operation */
switch (p_data->op_req.op) {
case NFA_RW_OP_DETECT_NDEF:
- nfa_rw_cb.skip_dyn_locks = false;
nfa_rw_detect_ndef();
break;
@@ -2904,6 +2930,22 @@
nfa_rw_t2t_sector_select(p_data);
break;
+ case NFA_RW_OP_T2T_READ_DYN_LOCKS:
+ if (p_data->op_req.params.t2t_read_dyn_locks.read_dyn_locks == true) {
+ nfa_rw_cb.skip_dyn_locks = false;
+ } else {
+ nfa_rw_cb.skip_dyn_locks = true;
+ }
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - Skip reading of dynamic lock bytes: %d",
+ __func__, nfa_rw_cb.skip_dyn_locks);
+
+ /* Command complete - perform cleanup, notify app */
+ nfa_rw_command_complete();
+ conn_evt_data.status = NFA_STATUS_OK;
+ nfa_dm_act_conn_cback_notify(NFA_T2T_CMD_CPLT_EVT, &conn_evt_data);
+ break;
+
/* Type-3 tag commands */
case NFA_RW_OP_T3T_READ:
nfa_rw_t3t_read(p_data);
@@ -2933,6 +2975,7 @@
case NFA_RW_OP_I93_LOCK_DSFID:
case NFA_RW_OP_I93_GET_SYS_INFO:
case NFA_RW_OP_I93_GET_MULTI_BLOCK_STATUS:
+ case NFA_RW_OP_I93_SET_ADDR_MODE:
nfa_rw_i93_command(p_data);
break;
diff --git a/src/nfa/rw/nfa_rw_api.cc b/src/nfa/rw/nfa_rw_api.cc
index 1c130f7..0e7a98e 100644
--- a/src/nfa/rw/nfa_rw_api.cc
+++ b/src/nfa/rw/nfa_rw_api.cc
@@ -699,6 +699,48 @@
/*******************************************************************************
**
+** Function NFA_RwT2tReadDynLockBytes
+**
+** Description:
+** Configure NFA skip_dyn_locks flag.
+**
+** This API must be called after activation but before NFA_RwDetectNDef()
+** or NFA_RwReadNDef() and NFA_RwWriteNDef() in case NDEF Detection is
+** triggered internally. It overwrites skip_dyn_locks default setting
+** set to false at activation. If not called, at the end of the NDEF
+** Detection, the DynLock_Area will be read and its content used to define
+** max_ndef_msg_len.
+**
+** When the operation has completed (or if an error occurs), the app will
+** be notified with NFA_T2T_CMD_CPLT_EVT.
+**
+** Returns:
+** NFA_STATUS_OK if successfully initiated
+** NFA_STATUS_FAILED otherwise
+**
+*******************************************************************************/
+tNFA_STATUS NFA_RwT2tReadDynLockBytes(bool read_dyn_locks) {
+ tNFA_RW_OPERATION* p_msg;
+
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - read DynLock_Area bytes: %d", __func__, read_dyn_locks);
+
+ p_msg = (tNFA_RW_OPERATION*)GKI_getbuf((uint16_t)(sizeof(tNFA_RW_OPERATION)));
+ if (p_msg != nullptr) {
+ /* Fill in tNFA_RW_OPERATION struct */
+ p_msg->hdr.event = NFA_RW_OP_REQUEST_EVT;
+ p_msg->op = NFA_RW_OP_T2T_READ_DYN_LOCKS;
+
+ p_msg->params.t2t_read_dyn_locks.read_dyn_locks = read_dyn_locks;
+
+ nfa_sys_sendmsg(p_msg);
+ return (NFA_STATUS_OK);
+ }
+ return (NFA_STATUS_FAILED);
+}
+
+/*******************************************************************************
+**
** Function NFA_RwT3tRead
**
** Description:
@@ -874,7 +916,7 @@
** NFA_STATUS_FAILED otherwise
**
*******************************************************************************/
-tNFA_STATUS NFA_RwI93StayQuiet(void) {
+tNFA_STATUS NFA_RwI93StayQuiet(uint8_t* p_uid) {
tNFA_RW_OPERATION* p_msg;
DLOG_IF(INFO, nfc_debug_enabled) << __func__;
@@ -888,6 +930,8 @@
/* Fill in tNFA_RW_OPERATION struct */
p_msg->hdr.event = NFA_RW_OP_REQUEST_EVT;
p_msg->op = NFA_RW_OP_I93_STAY_QUIET;
+ p_msg->params.i93_cmd.p_data = (uint8_t*)(p_msg + 1);
+ memcpy(p_msg->params.i93_cmd.p_data, p_uid, I93_UID_BYTE_LEN);
nfa_sys_sendmsg(p_msg);
@@ -1480,3 +1524,43 @@
return (NFA_STATUS_FAILED);
}
+
+/*******************************************************************************
+**
+** Function NFA_RwI93SetAddressingMode
+**
+** Description:
+** Set addressing mode to use to communicate with T5T tag.
+** mode = true: addressed (default if API not called)
+** mode = false: non-addressed
+**
+** Returns:
+** NFA_STATUS_OK if successfully initiated
+** NFA_STATUS_WRONG_PROTOCOL: T5T tag not activated
+** NFA_STATUS_FAILED otherwise
+**
+*******************************************************************************/
+tNFA_STATUS NFA_RwI93SetAddressingMode(bool mode) {
+ tNFA_RW_OPERATION* p_msg;
+
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s - %d", __func__, mode);
+
+ if (nfa_rw_cb.protocol != NFC_PROTOCOL_T5T) {
+ return (NFA_STATUS_WRONG_PROTOCOL);
+ }
+
+ p_msg = (tNFA_RW_OPERATION*)GKI_getbuf((uint16_t)(sizeof(tNFA_RW_OPERATION)));
+ if (p_msg != nullptr) {
+ /* Fill in tNFA_RW_OPERATION struct */
+ p_msg->hdr.event = NFA_RW_OP_REQUEST_EVT;
+ p_msg->op = NFA_RW_OP_I93_SET_ADDR_MODE;
+
+ p_msg->params.i93_cmd.addr_mode = mode;
+
+ nfa_sys_sendmsg(p_msg);
+
+ return (NFA_STATUS_OK);
+ }
+
+ return (NFA_STATUS_FAILED);
+}
diff --git a/src/nfc/include/nfc_api.h b/src/nfc/include/nfc_api.h
index 5e4d6ca..145bbf0 100644
--- a/src/nfc/include/nfc_api.h
+++ b/src/nfc/include/nfc_api.h
@@ -113,8 +113,14 @@
* NFC Config Parameter IDs defined by NCI
**********************************************/
#define NFC_PMID_TOTAL_DURATION NCI_PARAM_ID_TOTAL_DURATION
+#define NFC_PMID_PA_BAILOUT NCI_PARAM_ID_PA_BAILOUT
#define NFC_PMID_PF_RC NCI_PARAM_ID_PF_RC
+#define NFC_PMID_PB_BAILOUT NCI_PARAM_ID_PB_BAILOUT
+#define NFC_PMID_PF_BIT_RATE NCI_PARAM_ID_PF_BIT_RATE
+#define NFC_PMID_PF_BAILOUT NCI_PARAM_ID_PF_BAILOUT
+#define NFC_PMID_PF_DEVICES_LIMIT NCI_PARAM_ID_PF_DEVICES_LIMIT
#define NFC_PMID_ATR_REQ_GEN_BYTES NCI_PARAM_ID_ATR_REQ_GEN_BYTES
+#define NFC_PMID_ATR_REQ_CONFIG NCI_PARAM_ID_ATR_REQ_CONFIG
#define NFC_PMID_LA_HIST_BY NCI_PARAM_ID_LA_HIST_BY
#define NFC_PMID_LA_NFCID1 NCI_PARAM_ID_LA_NFCID1
#define NFC_PMID_LA_BIT_FRAME_SDD NCI_PARAM_ID_LA_BIT_FRAME_SDD
@@ -135,6 +141,7 @@
#define NFC_PMID_WT NCI_PARAM_ID_WT
#define NFC_PMID_ATR_RES_GEN_BYTES NCI_PARAM_ID_ATR_RES_GEN_BYTES
#define NFC_PMID_ATR_RSP_CONFIG NCI_PARAM_ID_ATR_RSP_CONFIG
+#define NFC_PMID_PACM_BIT_RATE NCI_PARAM_ID_PACM_BIT_RATE
#define NFC_PMID_RF_FIELD_INFO NCI_PARAM_ID_RF_FIELD_INFO
/* Technology based routing */
diff --git a/src/nfc/include/rw_api.h b/src/nfc/include/rw_api.h
index ea9c1cf..242b568 100644
--- a/src/nfc/include/rw_api.h
+++ b/src/nfc/include/rw_api.h
@@ -169,6 +169,9 @@
#define RW_T4T_CHK_EMPTY_I_BLOCK 1
#define RW_T4T_CHK_ISO_DEP_NAK_PRES_CHK 5
+#define RW_I93_MODE_ADDRESSED 0
+#define RW_I93_MODE_NON_ADDRESSED 1
+
typedef struct {
tNFC_STATUS status;
uint16_t msg_len; /* Length of the NDEF message */
@@ -933,7 +936,7 @@
** NFC_STATUS_FAILED if T4T is busy or other error
**
*******************************************************************************/
-extern tNFC_STATUS RW_T4tUpdateNDef(uint16_t length, uint8_t* p_data);
+extern tNFC_STATUS RW_T4tUpdateNDef(uint32_t length, uint8_t* p_data);
/*****************************************************************************
**
@@ -1002,7 +1005,7 @@
** NFC_STATUS_FAILED if other error
**
*******************************************************************************/
-extern tNFC_STATUS RW_I93StayQuiet(void);
+extern tNFC_STATUS RW_I93StayQuiet(uint8_t* p_uid);
/*******************************************************************************
**
@@ -1326,6 +1329,22 @@
*****************************************************************************/
extern tNFC_STATUS RW_I93PresenceCheck(void);
+/*****************************************************************************
+**
+** Function RW_I93SetAddressingMode
+**
+** Description Set if the tag must be addressed with UID or not.
+**
+** The addressing mode (addressed or non-addressed) must be
+** done at the module initialization prior to the Tag
+** activation.
+**
+** Returns NFC_STATUS_OK, if mode is stored
+** NFC_STATUS_FAILED: other error
+**
+*****************************************************************************/
+extern tNFC_STATUS RW_I93SetAddressingMode(bool mode);
+
/*******************************************************************************
**
** Function RW_SendRawFrame
diff --git a/src/nfc/include/rw_int.h b/src/nfc/include/rw_int.h
index 5c95e76..e25f48e 100644
--- a/src/nfc/include/rw_int.h
+++ b/src/nfc/include/rw_int.h
@@ -254,7 +254,7 @@
/* Maximum supported Lock control TLVS in the tag */
#define RW_T2T_MAX_LOCK_TLVS 0x05
/* Maximum supported dynamic lock bytes */
-#define RW_T2T_MAX_LOCK_BYTES 0x1E
+#define RW_T2T_MAX_LOCK_BYTES 0x20
#define RW_T2T_SEGMENT_BYTES 128
#define RW_T2T_SEGMENT_SIZE 16
@@ -361,19 +361,17 @@
#define RW_T2T_SUBSTATE_WAIT_READ_DYN_LOCK_BYTE_BLOCK 0x1A
/* waiting for response to set dynamic lock bits */
#define RW_T2T_SUBSTATE_WAIT_SET_DYN_LOCK_BITS 0x1B
-/* waiting for response to set static lock bits */
-#define RW_T2T_SUBSTATE_WAIT_SET_ST_LOCK_BITS 0x1C
typedef struct {
uint16_t offset; /* Offset of the lock byte in the Tag */
- uint8_t num_bits; /* Number of lock bits in the lock byte */
- uint8_t bytes_locked_per_bit; /* No. of tag bytes gets locked by a bit in this
- byte */
+ uint16_t num_bits; /* Number of lock bits in the lock byte */
+ uint16_t bytes_locked_per_bit; /* No. of tag bytes gets locked by a bit
+ in this byte */
} tRW_T2T_LOCK_INFO;
typedef struct {
uint16_t offset; /* Reserved bytes offset taken from Memory control TLV */
- uint8_t num_bytes; /* Number of reserved bytes as per the TLV */
+ uint16_t num_bytes; /* Number of reserved bytes as per the TLV */
} tRW_T2T_RES_INFO;
typedef struct {
@@ -527,6 +525,8 @@
uint8_t cur_poll_rc; /* RC used in current POLL command */
uint8_t flags; /* Flags see RW_T3T_FL_* */
+ /* Recall System Code used in last T3T polling command */
+ int32_t cur_active_sc;
} tRW_T3T_CB;
/*
@@ -540,16 +540,34 @@
/* Max data size using a single UpdateBinary. 6 bytes are for CLA, INS, P1, P2,
* Lc */
+/* Use worst case where Extended Field Coding and ODO format are used */
#define RW_T4T_MAX_DATA_PER_WRITE \
(NFC_RW_POOL_BUF_SIZE - NFC_HDR_SIZE - NCI_MSG_OFFSET_SIZE - \
- NCI_DATA_HDR_SIZE - T4T_CMD_MAX_HDR_SIZE)
+ NCI_DATA_HDR_SIZE - T4T_CMD_MAX_EXT_HDR_SIZE)
+#define RW_T4T_EXT_FIELD_CODING 0x01
+#define RW_T4T_DDO_LC_FIELD_CODING 0x02
+
+#define RW_T4T_BER_TLV_LENGTH_1_BYTE 0x01
+#define RW_T4T_BER_TLV_LENGTH_2_BYTES 0x02
+#define RW_T4T_BER_TLV_LENGTH_3_BYTES 0x03
+
+/* Minimum data header in command APDU data:
+ * ODO: 54 00 xxyyzz: tag '54' with 3-byte offset xxyyzz
+ * DDO: 53 Ld {data to be written to the ENDEF File}
+ * Ld (data length) can be 1, 2 or 3 bytes
+ */
+#define RW_T4T_ODO_DDO_HEADER_MIN_LENGTH 0x06 /* ODO + tag '53' */
+/* Ld encoded on two bytes with '81' tag and N=0 to 255
+ * for data field length coded on one byte */
+#define RW_T4T_ODO_DDO_HEADER_2BYTES_LENGTH 8 /* ODO + tag '53' + '81' + N */
/* Mandatory NDEF file control */
typedef struct {
uint16_t file_id; /* File Identifier */
- uint16_t max_file_size; /* Max NDEF file size */
+ uint32_t max_file_size; /* Max NDEF file size */
uint8_t read_access; /* read access condition */
uint8_t write_access; /* write access condition */
+ uint8_t nlen_size; /* (E)NLEN size (2 or 4 bytes) */
} tRW_T4T_NDEF_FC;
/* Capability Container */
@@ -571,10 +589,11 @@
uint8_t version; /* currently effective version */
TIMER_LIST_ENT timer; /* timeout for each API call */
- uint16_t ndef_length; /* length of NDEF data */
- uint8_t* p_update_data; /* pointer of data to update */
- uint16_t rw_length; /* remaining bytes to read/write */
- uint16_t rw_offset; /* remaining offset to read/write */
+ uint32_t ndef_length; /* length of NDEF data */
+ uint8_t* p_update_data; /* pointer of data to update */
+ uint32_t rw_length; /* remaining bytes to read/write */
+ uint32_t rw_offset; /* remaining offset to read/write */
+
NFC_HDR* p_data_to_free; /* GKI buffet to delete after done */
tRW_T4T_CC cc_file; /* Capability Container File */
@@ -591,6 +610,7 @@
uint16_t max_update_size; /* max updating size per a command */
uint16_t card_size;
uint8_t card_type;
+ uint8_t intl_flags; /* flags for internal information */
} tRW_T4T_CB;
/* RW retransmission statistics */
@@ -665,6 +685,10 @@
#define RW_I93_FLAG_16BIT_NUM_BLOCK 0x10
/* use extended commands */
#define RW_I93_FLAG_EXT_COMMANDS 0x20
+/* use Special Frame in Write-Alike commands */
+#define RW_I93_FLAG_SPECIAL_FRAME 0x40
+/* use SMS bit in Selected state */
+#define RW_I93_FLAG_SELECTED_STATE 0x80
/* searching for type */
#define RW_I93_TLV_DETECT_STATE_TYPE 0x01
@@ -676,6 +700,50 @@
#define RW_I93_TLV_DETECT_STATE_LENGTH_3 0x04
/* reading value field */
#define RW_I93_TLV_DETECT_STATE_VALUE 0x05
+#define RW_I93_GET_SYS_INFO_MEM_INFO 1
+#define RW_T5T_CC_READ_MEM_INFO 0
+
+/* capability Container CC Size */
+#define RW_I93_CC_SIZE 4
+
+/* 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_WAIT_CC_EXT, /* waiting for reading CC second byte */
+ 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 */
+ RW_I93_SUBSTATE_LOCK_T5T_AREA /* lock blocks of T5T_Area */
+};
enum {
RW_I93_ICODE_SLI, /* ICODE SLI, SLIX */
@@ -692,6 +760,7 @@
RW_I93_STM_M24LR64_R, /* STM M24LR64-R */
RW_I93_STM_M24LR04E_R, /* STM M24LR04E-R */
RW_I93_STM_M24LR16E_R, /* STM M24LR16E-R */
+ RW_I93_STM_M24LR16D_W, /* STM M24LR16D-W */
RW_I93_STM_M24LR64E_R, /* STM M24LR64E-R */
RW_I93_STM_ST25DV04K, /* STM ST25DV04K */
RW_I93_STM_ST25DVHIK, /* STM ST25DV 16K OR 64K */
@@ -726,6 +795,16 @@
uint8_t tlv_detect_state; /* TLV detecting state */
uint8_t tlv_type; /* currently detected type */
+ uint8_t addr_mode;
+ uint8_t i93_t5t_mode;
+ uint8_t t5t_area_start_block; /* offset of first block of T5T_Area */
+ uint16_t t5t_area_last_offset; /* offset of last byte of T5T_Area */
+
+ /* Greedy collection with NDEF Detection data */
+ uint8_t gre_validity;
+ uint8_t gre_cc_content[8];
+ uint16_t gre_ndef_tlv_pos;
+ uint16_t gre_ndef_tlv_length;
uint16_t tlv_length; /* currently detected length */
uint16_t ndef_tlv_start_offset; /* offset of first byte of NDEF TLV */
@@ -825,6 +904,12 @@
extern tNFC_STATUS rw_i93_select(uint8_t* p_uid);
extern void rw_i93_process_timeout(TIMER_LIST_ENT* p_tle);
+extern std::string rw_i93_get_state_name(uint8_t state);
+extern std::string rw_i93_get_sub_state_name(uint8_t sub_state);
+extern void rw_t5t_sm_detect_ndef(NFC_HDR*);
+extern void rw_t5t_sm_update_ndef(NFC_HDR*);
+extern void rw_t5t_sm_set_read_only(NFC_HDR*);
+
extern void rw_t4t_handle_isodep_nak_rsp(uint8_t status, bool is_ntf);
extern tNFC_STATUS rw_mfc_select(uint8_t selres, uint8_t uid[T1T_CMD_UID_LEN]);
diff --git a/src/nfc/include/tags_defs.h b/src/nfc/include/tags_defs.h
index 0e73c36..9572286 100644
--- a/src/nfc/include/tags_defs.h
+++ b/src/nfc/include/tags_defs.h
@@ -366,15 +366,24 @@
#define T4T_CMD_MIN_HDR_SIZE 4 /* CLA, INS, P1, P2 */
#define T4T_CMD_MAX_HDR_SIZE 5 /* CLA, INS, P1, P2, Lc */
+/* CLA, INS, P1, P2, Data ODO */
+#define T4T_CMD_MIN_EXT_HDR_SIZE 9
+/* CLA, INS, P1, P2, Lc, Data ODO, Le
+ * with Lc and Le coded using Extended Field Coding */
+#define T4T_CMD_MAX_EXT_HDR_SIZE 15
+
+#define T4T_VERSION_3_0 0x30 /* version 3.0 */
#define T4T_VERSION_2_0 0x20 /* version 2.0 */
#define T4T_VERSION_1_0 0x10 /* version 1.0 */
-#define T4T_MY_VERSION T4T_VERSION_2_0
+#define T4T_MY_VERSION T4T_VERSION_3_0
#define T4T_GET_MAJOR_VERSION(x) ((x) >> 4)
#define T4T_CMD_CLASS 0x00
#define T4T_CMD_INS_SELECT 0xA4
#define T4T_CMD_INS_READ_BINARY 0xB0
#define T4T_CMD_INS_UPDATE_BINARY 0xD6
+#define T4T_CMD_INS_READ_BINARY_ODO 0xB1
+#define T4T_CMD_INS_UPDATE_BINARY_ODO 0xD7
#define T4T_CMD_DES_CLASS 0x90
#define T4T_CMD_INS_GET_HW_VERSION 0x60
#define T4T_CMD_CREATE_AID 0xCA
@@ -415,6 +424,8 @@
#define T4T_VERSION_OFFSET_IN_CC 0x02
#define T4T_FC_TLV_OFFSET_IN_CC 0x07
+/* size of T(1),L(1),V(8) for extended NDEF file control */
+#define T4T_ENDEF_FC_V_FIELD_OFFSET 0x09
/* Offset of Write access byte from type field in CC */
#define T4T_FC_WRITE_ACCESS_OFFSET_IN_TLV 0x07
@@ -425,8 +436,18 @@
/* size of V(6) for file control */
#define T4T_FILE_CONTROL_LENGTH 0x06
+#define T4T_ENDEF_FILE_CONTROL_TYPE 0x06 /* Extended NDEF File Control Type */
+/* size of T(1),L(1),V(8) for extended NDEF file control */
+#define T4T_ENDEF_FILE_CONTROL_TLV_SIZE 0x0A
+/* size of V(8) for extended NDEF file control */
+#define T4T_ENDEF_FILE_CONTROL_LENGTH 0x08
+
/* read access granted without any security */
#define T4T_FC_READ_ACCESS 0x00
+/* no read access granted at all */
+#define T4T_FC_NO_READ_ACCESS 0xFF
+/* proprietary read access range start */
+#define T4T_FC_READ_ACCESS_PROP_START 0x80
/* write access granted without any security */
#define T4T_FC_WRITE_ACCESS 0x00
/* proprietary write access range start */
@@ -435,6 +456,7 @@
#define T4T_FC_NO_WRITE_ACCESS 0xFF
#define T4T_FILE_LENGTH_SIZE 0x02
+#define T4T_EFILE_LENGTH_SIZE 0x04
#define T4T_ADDI_FRAME_RESP 0xAFU
#define T4T_DES_GET_VERSION_LEN 0x09
#define T4T_SIZE_IDENTIFIER_2K 0x16U
@@ -456,6 +478,8 @@
**
*/
+#define I93_VERSION_1_x 0x40 /* major mapping version 1.x */
+
/* A single sub-carrier frequency shall be used by VICC */
#define I93_FLAG_SUB_CARRIER_SINGLE 0x00
@@ -470,10 +494,13 @@
/* Protocol format is extended. Reserved for future use */
#define I93_FLAG_PROT_EXT_YES 0x08
-/* Request is addressed. UID field is included. It shall be executed only by
- * VICC */
+/* Request is addressed with AMS (Address Mode Selector). UID field is included.
+ * It shall be executed only by VICC */
#define I93_FLAG_ADDRESS_SET 0x20
/* whose UID matches the UID specified in the request */
+/* Request is addressed with SMS (Select Mode Selector). UID field is included
+ * or not. It shall be executed by the unique VICC to be in SELECTED state */
+#define I93_FLAG_SELECT_SET 0x10
/* AFI field is present */
#define I93_FLAG_AFI_PRESENT 0x10
@@ -530,6 +557,7 @@
#define I93_CMD_GET_MULTI_BLK_SEC 0x2C
/* Get extended multiple block security status */
#define I93_CMD_EXT_GET_MULTI_BLK_SEC 0x3C
+#define I93_CMD_SET_ADDR_MODE 0x3D /* Set address mode */
/* Information flags definition */
/* DSFID is supported and DSFID field is present */
@@ -558,6 +586,11 @@
/* Max block size in bytes */
#define I93_MAX_BLOCK_LENGH 32
+/* Block lengths */
+#define I93_BLEN_4BYTES 0x04
+#define I93_BLEN_8BYTES 0x08
+#define I93_BLEN_16BYTES 0x10
+#define I93_BLEN_32BYTES 0x20
/* ICODE Capability Container(CC) definition */
#define I93_ICODE_CC_MAGIC_NUMER_E1 0xE1 /* magic number in CC[0] */
#define I93_ICODE_CC_MAGIC_NUMER_E2 0xE2 /* magic number in CC[0] */
@@ -578,6 +611,8 @@
/* More than 2040 bytes are supported in CC[3] */
#define I93_STM_CC_OVERFLOW_MASK 0x04
#define I93_ONS_CC_OVERFLOW_MASK 0x04
+/* Special Frame are supported in CC[3] */
+#define I93_ICODE_CC_SPECIAL_FRAME_MASK 0x10
/* ICODE TLV type */
#define I93_ICODE_TLV_TYPE_NULL 0x00 /* NULL TLV */
@@ -647,7 +682,10 @@
/* IC Reference for M24LR16E-R: 01001110(b), blockSize: 4, numberBlocks: 0x200
*/
#define I93_IC_REF_STM_M24LR16E_R 0x4E
-/* IC Reference for M24LR64E-R: 01011110(b), blockSize: 4, numberBlocks: 0x800
+/* IC Reference for M24LR16D-W: 01001101(b), blockSize: 4, numberBlocks: 0x200
+ */
+#define I93_IC_REF_STM_M24LR16D_W 0x4D
+/* IC Reference for M24LR64D-W: 01011110(b), blockSize: 4, numberBlocks: 0x800
*/
#define I93_IC_REF_STM_M24LR64E_R 0x5E
/* IC Reference for ST25DV04K: 00100100(b), blockSize: 4, numberBlocks: 0x80
@@ -660,17 +698,17 @@
/* ONS, product version (IC manufacturer code) */
/* IC Reference for N36RW02: 00011010(b), blockSize: 4, numberBlocks: 0x40 */
-#define I93_IC_REF_ONS_N36RW02 0x1A
+#define I93_IC_REF_ONS_N36RW02 0x1A
/* IC Reference for N24RF04: 00101010(b), blockSize: 4, numberBlocks: 0x80 */
-#define I93_IC_REF_ONS_N24RF04 0x2A
+#define I93_IC_REF_ONS_N24RF04 0x2A
/* IC Reference for N24RF04E: 00101110(b), blockSize: 4, numberBlocks: 0x80 */
#define I93_IC_REF_ONS_N24RF04E 0x2E
/* IC Reference for N24RF16: 01001010(b), blockSize: 4, numberBlocks: 0x200 */
-#define I93_IC_REF_ONS_N24RF16 0x4A
+#define I93_IC_REF_ONS_N24RF16 0x4A
/* IC Reference for N24RF16E: 01001110(b), blockSize: 4, numberBlocks: 0x200 */
#define I93_IC_REF_ONS_N24RF16E 0x4E
/* IC Reference for N24RF64: 01101010(b), blockSize: 4, numberBlocks: 0x800 */
-#define I93_IC_REF_ONS_N24RF64 0x6A
+#define I93_IC_REF_ONS_N24RF64 0x6A
/* IC Reference for N24RF64E: 01101110(b), blockSize: 4, numberBlocks: 0x800 */
#define I93_IC_REF_ONS_N24RF64E 0x6E
@@ -680,4 +718,4 @@
#define I93_ONS_BLOCKS_PER_SECTOR 32
#define I93_ONS_MAX_BLOCKS_PER_READ 32
-#endif /* TAGS_DEFS_H */
\ No newline at end of file
+#endif /* TAGS_DEFS_H */
\ No newline at end of file
diff --git a/src/nfc/nci/nci_hrcv.cc b/src/nfc/nci/nci_hrcv.cc
index 7dfa408..50a6297 100644
--- a/src/nfc/nci/nci_hrcv.cc
+++ b/src/nfc/nci/nci_hrcv.cc
@@ -275,6 +275,10 @@
break;
case NCI_MSG_RF_FIELD:
+ if (p_msg->len < 4) {
+ android_errorWriteLog(0x534e4554, "176582502");
+ return;
+ }
nfc_ncif_proc_rf_field_ntf(*pp);
break;
@@ -299,6 +303,10 @@
#endif
#endif
case NCI_MSG_RF_ISO_DEP_NAK_PRESENCE:
+ if (p_msg->len < 4) {
+ android_errorWriteLog(0x534e4554, "176582502");
+ return;
+ }
nfc_ncif_proc_isodep_nak_presence_check_status(*pp, true);
break;
default:
@@ -356,6 +364,8 @@
nfc_response.mode_set.status = *pp;
} else {
nfc_response.mode_set.status = NFC_STATUS_FAILED;
+ android_errorWriteLog(0x534e4554, "176203800");
+ return;
}
nfc_response.mode_set.nfcee_id = *p_old++;
nfc_response.mode_set.mode = *p_old++;
@@ -471,9 +481,7 @@
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("tag:0x%x, len:0x%x", p_tlv->tag, p_tlv->len);
if (p_tlv->len > NFC_MAX_EE_INFO) p_tlv->len = NFC_MAX_EE_INFO;
- p = pp;
STREAM_TO_ARRAY(p_tlv->info, pp, p_tlv->len);
- pp = p += yy;
}
break;
case NCI_MSG_NFCEE_MODE_SET:
diff --git a/src/nfc/nfc/nfc_ncif.cc b/src/nfc/nfc/nfc_ncif.cc
index 93a3509..101b333 100644
--- a/src/nfc/nfc/nfc_ncif.cc
+++ b/src/nfc/nfc/nfc_ncif.cc
@@ -62,40 +62,9 @@
static struct timeval timer_start;
static struct timeval timer_end;
+#define DEFAULT_CRASH_NFCSNOOP_PATH "/data/misc/nfc/logs/native_crash_logs"
static const off_t NATIVE_CRASH_FILE_SIZE = (1024 * 1024);
-void storeNativeCrashLogs(void) {
- std::string filename = "/native_crash_logs";
- std::string filepath = nfc_storage_path + filename;
- int fileStream;
- off_t fileSize;
- DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf("%s: file=%s", __func__, filepath.c_str());
- // check file size
- struct stat st;
- if (stat(filepath.c_str(), &st) == 0) {
- fileSize = st.st_size;
- } else {
- fileSize = 0;
- }
-
- if (fileSize >= NATIVE_CRASH_FILE_SIZE) {
- fileStream =
- open(filepath.c_str(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
- } else {
- fileStream =
- open(filepath.c_str(), O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
- }
-
- if (fileStream >= 0) {
- debug_nfcsnoop_dump(fileStream);
- close(fileStream);
- } else {
- LOG(ERROR) << StringPrintf("%s: fail to create, error = %d", __func__,
- errno);
- }
-}
-
/*******************************************************************************
**
** Function nfc_ncif_update_window
@@ -136,7 +105,7 @@
void nfc_ncif_cmd_timeout(void) {
LOG(ERROR) << StringPrintf("nfc_ncif_cmd_timeout");
- storeNativeCrashLogs();
+ storeNfcSnoopLogs(DEFAULT_CRASH_NFCSNOOP_PATH, NATIVE_CRASH_FILE_SIZE);
/* report an error */
nfc_ncif_event_status(NFC_GEN_ERROR_REVT, NFC_STATUS_HW_TIMEOUT);
@@ -146,14 +115,6 @@
if (nfc_cb.nfc_state == NFC_STATE_CORE_INIT) {
nfc_enabled(NFC_STATUS_FAILED, nullptr);
}
-
- /* XXX maco since this failure is unrecoverable, abort the process */
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- // Do not abort if for fuzz testing -- this may have some undesired
- // effect but this is the best we can do.
-#else
- abort();
-#endif
}
/*******************************************************************************
@@ -1691,7 +1652,7 @@
status = *p_len > 0 ? *p++ : NCI_STATUS_FAILED;
if (*p_len > 2 && is_ntf) {
- LOG(ERROR) << StringPrintf("reset notification!!:0x%x ", status);
+ LOG(WARNING) << StringPrintf("reset notification!!:0x%x ", status);
/* clean up, if the state is OPEN
* FW does not report reset ntf right now */
if (status == NCI2_0_RESET_TRIGGER_TYPE_CORE_RESET_CMD_RECEIVED ||
@@ -1707,7 +1668,7 @@
status = NCI_STATUS_OK;
} else {
/* CORE_RESET_NTF received error case , trigger recovery*/
- DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ LOG(ERROR) << StringPrintf(
"CORE_RESET_NTF Received status nfc_state : 0x%x : 0x%x", status,
nfc_cb.nfc_state);
nfc_ncif_cmd_timeout();
diff --git a/src/nfc/nfc/nfc_utils.cc b/src/nfc/nfc/nfc_utils.cc
index 855908b..8131e48 100644
--- a/src/nfc/nfc/nfc_utils.cc
+++ b/src/nfc/nfc/nfc_utils.cc
@@ -159,7 +159,11 @@
while ((p_buf = GKI_dequeue(&p_cb->tx_q)) != nullptr) GKI_freebuf(p_buf);
- nfc_cb.conn_id[p_cb->conn_id] = 0;
+ if (p_cb->conn_id <= NFC_MAX_CONN_ID) {
+ nfc_cb.conn_id[p_cb->conn_id] = 0;
+ } else {
+ LOG(ERROR) << StringPrintf("invalid conn_id.");
+ }
p_cb->p_cback = nullptr;
p_cb->conn_id = NFC_ILLEGAL_CONN_ID;
}
diff --git a/src/nfc/tags/rw_i93.cc b/src/nfc/tags/rw_i93.cc
index 1c64ea8..5bf9afc 100644
--- a/src/nfc/tags/rw_i93.cc
+++ b/src/nfc/tags/rw_i93.cc
@@ -39,6 +39,7 @@
using android::base::StringPrintf;
extern bool nfc_debug_enabled;
+extern unsigned char appl_dta_mode_flag;
/* Response timeout */
#define RW_I93_TOUT_RESP 1000
@@ -50,48 +51,7 @@
#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
-/*Capability Container CC Size */
-#define RW_I93_CC_SIZE 4
-/* 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 */
-};
-
-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);
static void rw_i93_data_cback(uint8_t conn_id, tNFC_CONN_EVT event,
@@ -150,6 +110,8 @@
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_M24LR16D_W)
+ p_i93->product_version = RW_I93_STM_M24LR16D_W;
else if (p_i93->ic_reference == I93_IC_REF_STM_M24LR64E_R)
p_i93->product_version = RW_I93_STM_M24LR64E_R;
else if (p_i93->ic_reference == I93_IC_REF_STM_ST25DVHIK)
@@ -180,32 +142,32 @@
}
} else if ((p_uid[1] == I93_UID_IC_MFG_CODE_ONS) &&
(p_i93->info_flags & I93_INFO_FLAG_IC_REF)) {
- switch (p_i93->ic_reference) {
- case I93_IC_REF_ONS_N36RW02:
- p_i93->product_version = RW_I93_ONS_N36RW02;
+ switch (p_i93->ic_reference) {
+ case I93_IC_REF_ONS_N36RW02:
+ p_i93->product_version = RW_I93_ONS_N36RW02;
+ break;
+ case I93_IC_REF_ONS_N24RF04:
+ p_i93->product_version = RW_I93_ONS_N24RF04;
+ break;
+ case I93_IC_REF_ONS_N24RF04E:
+ p_i93->product_version = RW_I93_ONS_N24RF04E;
+ break;
+ case I93_IC_REF_ONS_N24RF16:
+ p_i93->product_version = RW_I93_ONS_N24RF16;
+ break;
+ case I93_IC_REF_ONS_N24RF16E:
+ p_i93->product_version = RW_I93_ONS_N24RF16E;
+ break;
+ case I93_IC_REF_ONS_N24RF64:
+ p_i93->product_version = RW_I93_ONS_N24RF64;
+ break;
+ case I93_IC_REF_ONS_N24RF64E:
+ p_i93->product_version = RW_I93_ONS_N24RF64E;
+ break;
+ default:
+ p_i93->product_version = RW_I93_UNKNOWN_PRODUCT;
break;
- case I93_IC_REF_ONS_N24RF04:
- p_i93->product_version = RW_I93_ONS_N24RF04;
- break;
- case I93_IC_REF_ONS_N24RF04E:
- p_i93->product_version = RW_I93_ONS_N24RF04E;
- break;
- case I93_IC_REF_ONS_N24RF16:
- p_i93->product_version = RW_I93_ONS_N24RF16;
- break;
- case I93_IC_REF_ONS_N24RF16E:
- p_i93->product_version = RW_I93_ONS_N24RF16E;
- break;
- case I93_IC_REF_ONS_N24RF64:
- p_i93->product_version = RW_I93_ONS_N24RF64;
- break;
- case I93_IC_REF_ONS_N24RF64E:
- p_i93->product_version = RW_I93_ONS_N24RF64E;
- break;
- default:
- p_i93->product_version = RW_I93_UNKNOWN_PRODUCT;
- break;
- }
+ }
} else {
p_i93->product_version = RW_I93_UNKNOWN_PRODUCT;
}
@@ -303,8 +265,7 @@
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_STM) ||
- (p_i93->uid[1] == I93_UID_IC_MFG_CODE_ONS)) {
+ if ((p_i93->uid[1] == I93_UID_IC_MFG_CODE_STM) || (p_i93->uid[1] == I93_UID_IC_MFG_CODE_ONS)){
/* STM & ONS supports more than 2040 bytes */
p_i93->intl_flags |= RW_I93_FLAG_EXT_COMMANDS;
}
@@ -403,12 +364,14 @@
** M24LR64-R: 001011xx(b), blockSize: 4, numberBlocks: 0x800
** M24LR04E-R: 01011010(b), blockSize: 4, numberBlocks: 0x80
** M24LR16E-R: 01001110(b), blockSize: 4, numberBlocks: 0x200
+ ** M24LR16D-W: 01001101(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_M24LR16D_W) ||
(p_i93->product_version == RW_I93_STM_M24LR64E_R)) {
/*
- ** M24LR16E-R or M24LR64E-R returns system information
+ ** M24LR16E-R or M24LR16D-W 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.
@@ -448,28 +411,28 @@
** N24RF64: 01101010(b), blockSize: 4, numberBlocks: 0x800
** N24RF64E: 01101110(b), blockSize: 4, numberBlocks: 0x800
*/
- p_i93->block_size = 4;
- switch (p_i93->product_version) {
- case RW_I93_ONS_N36RW02:
- p_i93->num_block = 0x40;
- break;
- case RW_I93_ONS_N24RF04:
- case RW_I93_ONS_N24RF04E:
- p_i93->num_block = 0x80;
- break;
- case RW_I93_ONS_N24RF16:
- case RW_I93_ONS_N24RF16E:
- p_i93->num_block = 0x200;
- p_i93->intl_flags |= RW_I93_FLAG_16BIT_NUM_BLOCK;
- break;
- case RW_I93_ONS_N24RF64:
- case RW_I93_ONS_N24RF64E:
- p_i93->num_block = 0x800;
- p_i93->intl_flags |= RW_I93_FLAG_16BIT_NUM_BLOCK;
- break;
- default:
- return false;
- }
+ p_i93->block_size = 4;
+ switch (p_i93->product_version){
+ case RW_I93_ONS_N36RW02:
+ p_i93->num_block = 0x40;
+ break;
+ case RW_I93_ONS_N24RF04:
+ case RW_I93_ONS_N24RF04E:
+ p_i93->num_block = 0x80;
+ break;
+ case RW_I93_ONS_N24RF16:
+ case RW_I93_ONS_N24RF16E:
+ p_i93->num_block = 0x200;
+ p_i93->intl_flags |= RW_I93_FLAG_16BIT_NUM_BLOCK;
+ break;
+ case RW_I93_ONS_N24RF64:
+ case RW_I93_ONS_N24RF64E:
+ p_i93->num_block = 0x800;
+ p_i93->intl_flags |= RW_I93_FLAG_16BIT_NUM_BLOCK;
+ break;
+ default:
+ return false;
+ }
}
}
}
@@ -492,8 +455,7 @@
DLOG_IF(INFO, nfc_debug_enabled) << __func__;
- if (((p_i93->uid[1] == I93_UID_IC_MFG_CODE_STM) ||
- (p_i93->uid[1] == I93_UID_IC_MFG_CODE_ONS)) &&
+ if (((p_i93->uid[1] == I93_UID_IC_MFG_CODE_STM) || (p_i93->uid[1] == I93_UID_IC_MFG_CODE_ONS)) &&
(p_i93->sent_cmd == I93_CMD_GET_SYS_INFO) &&
(error_code == I93_ERROR_CODE_OPTION_NOT_SUPPORTED) &&
(rw_i93_send_cmd_get_sys_info(nullptr, I93_FLAG_PROT_EXT_YES) ==
@@ -635,6 +597,7 @@
memcpy(rw_data.i93_sys_info.uid, p_i93->uid, I93_UID_BYTE_LEN);
+ p_i93->i93_t5t_mode = RW_I93_GET_SYS_INFO_MEM_INFO;
event = RW_I93_SYS_INFO_EVT;
} else {
/* retrying with protocol extension flag */
@@ -656,6 +619,7 @@
memcpy(rw_data.i93_sys_info.uid, p_i93->uid, I93_UID_BYTE_LEN);
+ p_i93->i93_t5t_mode = RW_I93_GET_SYS_INFO_MEM_INFO;
event = RW_I93_SYS_INFO_EVT;
} else {
/* retrying with protocol extension flag or with extended sys info
@@ -788,7 +752,7 @@
** Returns tNFC_STATUS
**
*******************************************************************************/
-tNFC_STATUS rw_i93_send_cmd_stay_quiet(void) {
+tNFC_STATUS rw_i93_send_cmd_stay_quiet(uint8_t* p_uid) {
NFC_HDR* p_cmd;
uint8_t* p;
@@ -813,7 +777,9 @@
UINT8_TO_STREAM(p, I93_CMD_STAY_QUIET);
/* Parameters */
- ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
+ /* Beware the UID is provided with the same order as the transmission
+ one (LSB first) */
+ ARRAY_TO_STREAM(p, p_uid, I93_UID_BYTE_LEN); /* UID */
if (rw_i93_send_to_lower(p_cmd)) {
rw_cb.tcb.i93.sent_cmd = I93_CMD_STAY_QUIET;
@@ -841,6 +807,7 @@
bool read_security) {
NFC_HDR* p_cmd;
uint8_t *p, flags;
+ tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
DLOG_IF(INFO, nfc_debug_enabled) << __func__;
@@ -852,13 +819,22 @@
}
p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
- p_cmd->len = 11;
+ if (p_i93->addr_mode == RW_I93_MODE_ADDRESSED)
+ p_cmd->len = 11;
+ else
+ p_cmd->len = 3;
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 (p_i93->addr_mode == RW_I93_MODE_ADDRESSED) {
+ flags = (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER |
+ RW_I93_FLAG_DATA_RATE);
+ } else {
+ flags = (RW_I93_FLAG_SUB_CARRIER | RW_I93_FLAG_DATA_RATE);
+ if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_SELECTED_STATE)
+ flags |= I93_FLAG_SELECT_SET;
+ }
if (read_security) flags |= I93_FLAG_OPTION_SET;
if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_16BIT_NUM_BLOCK)
@@ -874,7 +850,8 @@
}
/* Parameters */
- ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
+ if (flags & I93_FLAG_ADDRESS_SET)
+ ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_16BIT_NUM_BLOCK ||
rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_EXT_COMMANDS) {
@@ -908,6 +885,7 @@
uint8_t* p_data) {
NFC_HDR* p_cmd;
uint8_t *p, flags;
+ tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
DLOG_IF(INFO, nfc_debug_enabled) << __func__;
@@ -919,7 +897,10 @@
}
p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
- p_cmd->len = 11 + rw_cb.tcb.i93.block_size;
+ if (p_i93->addr_mode == RW_I93_MODE_ADDRESSED)
+ p_cmd->len = 11 + rw_cb.tcb.i93.block_size;
+ else
+ p_cmd->len = 3 + rw_cb.tcb.i93.block_size;
p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
/* Flags */
@@ -931,8 +912,19 @@
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 (p_i93->addr_mode == RW_I93_MODE_ADDRESSED) {
+ flags = (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER |
+ RW_I93_FLAG_DATA_RATE);
+ } else {
+ flags = (RW_I93_FLAG_SUB_CARRIER | RW_I93_FLAG_DATA_RATE);
+ if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_SELECTED_STATE)
+ flags |= I93_FLAG_SELECT_SET;
+ }
+
+ if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_SPECIAL_FRAME) {
+ /* Option Flag bit must be set */
+ flags |= I93_FLAG_OPTION_SET;
+ }
}
if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_16BIT_NUM_BLOCK)
@@ -948,7 +940,8 @@
}
/* Parameters */
- ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
+ if (flags & I93_FLAG_ADDRESS_SET)
+ ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_16BIT_NUM_BLOCK ||
rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_EXT_COMMANDS) {
@@ -978,15 +971,17 @@
**
** Description Send Lock Block Request to VICC
**
-** STM LRIS64K, M24LR64-R, M24LR04E-R, M24LR16E-R, M24LR64E-R
-** do not support.
+** STM LRIS64K, M24LR64-R, M24LR04E-R, M24LR16E-R, M24LR64E-R,
+** M24LR16D-W do not support.
**
** Returns tNFC_STATUS
**
*******************************************************************************/
-tNFC_STATUS rw_i93_send_cmd_lock_block(uint8_t block_number) {
+tNFC_STATUS rw_i93_send_cmd_lock_block(uint16_t block_number) {
NFC_HDR* p_cmd;
uint8_t* p;
+ tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
+ uint8_t flags;
DLOG_IF(INFO, nfc_debug_enabled) << __func__;
@@ -998,7 +993,10 @@
}
p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
- p_cmd->len = 11;
+ if (p_i93->addr_mode == RW_I93_MODE_ADDRESSED)
+ p_cmd->len = 11;
+ else
+ p_cmd->len = 3;
p = (uint8_t*)(p_cmd + 1) + p_cmd->offset;
/* Flags */
@@ -1010,8 +1008,21 @@
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));
+ if (p_i93->addr_mode == RW_I93_MODE_ADDRESSED) {
+ /* Address Mode Selector must be set */
+ flags = I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER |
+ RW_I93_FLAG_DATA_RATE;
+ } else {
+ flags = RW_I93_FLAG_SUB_CARRIER | RW_I93_FLAG_DATA_RATE;
+
+ if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_SELECTED_STATE)
+ flags |= I93_FLAG_SELECT_SET;
+ }
+ if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_SPECIAL_FRAME) {
+ /* Option Flag bit must be set */
+ flags |= I93_FLAG_OPTION_SET;
+ }
+ UINT8_TO_STREAM(p, flags);
}
/* Command Code */
@@ -1022,10 +1033,11 @@
}
/* Parameters */
- ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
+ if (p_i93->addr_mode == RW_I93_MODE_ADDRESSED)
+ ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_EXT_COMMANDS) {
- UINT8_TO_STREAM(p, block_number); /* Block number */
+ UINT16_TO_STREAM(p, block_number); /* Block number */
p_cmd->len++;
} else {
UINT8_TO_STREAM(p, block_number); /* Block number */
@@ -1055,6 +1067,7 @@
uint16_t number_blocks) {
NFC_HDR* p_cmd;
uint8_t *p, flags;
+ tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
DLOG_IF(INFO, nfc_debug_enabled) << __func__;
@@ -1066,12 +1079,22 @@
}
p_cmd->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
- p_cmd->len = 12;
+ if (p_i93->addr_mode == RW_I93_MODE_ADDRESSED)
+ p_cmd->len = 12;
+ else
+ p_cmd->len = 4;
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 (p_i93->addr_mode == RW_I93_MODE_ADDRESSED) {
+ flags = (I93_FLAG_ADDRESS_SET | RW_I93_FLAG_SUB_CARRIER |
+ RW_I93_FLAG_DATA_RATE);
+ } else {
+ flags = (RW_I93_FLAG_SUB_CARRIER | RW_I93_FLAG_DATA_RATE);
+
+ if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_SELECTED_STATE)
+ flags |= I93_FLAG_SELECT_SET;
+ }
if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_16BIT_NUM_BLOCK) {
flags |= I93_FLAG_PROT_EXT_YES;
@@ -1087,7 +1110,8 @@
}
/* Parameters */
- ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
+ if (flags & I93_FLAG_ADDRESS_SET)
+ ARRAY8_TO_STREAM(p, rw_cb.tcb.i93.uid); /* UID */
if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_16BIT_NUM_BLOCK ||
rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_EXT_COMMANDS) {
@@ -1224,7 +1248,9 @@
UINT8_TO_STREAM(p, I93_CMD_SELECT);
/* Parameters */
- ARRAY8_TO_STREAM(p, p_uid); /* UID */
+ /* Beware the UID is provided with the same order as the transmission
+ one (LSB first) */
+ ARRAY_TO_STREAM(p, p_uid, I93_UID_BYTE_LEN); /* UID */
if (rw_i93_send_to_lower(p_cmd)) {
rw_cb.tcb.i93.sent_cmd = I93_CMD_SELECT;
@@ -1650,11 +1676,21 @@
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;
+ // first_block is an offset related to the beginning of the T5T_Area for T5T
+ // tags but physical memory for ISO15693 tags
+ if (p_i93->i93_t5t_mode == RW_I93_GET_SYS_INFO_MEM_INFO) {
+ if (num_block + first_block > p_i93->num_block)
+ num_block = p_i93->num_block - first_block;
+ } else {
+ if (num_block + first_block >
+ p_i93->num_block + p_i93->t5t_area_start_block)
+ num_block =
+ p_i93->num_block - first_block + p_i93->t5t_area_start_block;
+ }
if (p_i93->uid[1] == I93_UID_IC_MFG_CODE_STM) {
- /* LRIS64K, M24LR64-R, M24LR04E-R, M24LR16E-R, M24LR64E-R requires
+ /* LRIS64K, M24LR64-R, M24LR04E-R, M24LR16E-R, M24LR16D-W, M24LR64E-R
+ ** require
** - The max number of blocks is 32 and they are all located in the
** same sector.
** - The sector is 32 blocks of 4 bytes.
@@ -1663,6 +1699,7 @@
(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_M24LR16D_W) ||
(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;
@@ -1683,9 +1720,9 @@
*/
if ((p_i93->product_version == RW_I93_ONS_N36RW02) ||
(p_i93->product_version == RW_I93_ONS_N24RF04) ||
- (p_i93->product_version == RW_I93_ONS_N24RF04E) ||
+ (p_i93->product_version == RW_I93_ONS_N24RF04E)||
(p_i93->product_version == RW_I93_ONS_N24RF16) ||
- (p_i93->product_version == RW_I93_ONS_N24RF16E) ||
+ (p_i93->product_version == RW_I93_ONS_N24RF16E)||
(p_i93->product_version == RW_I93_ONS_N24RF64) ||
(p_i93->product_version == RW_I93_ONS_N24RF64E)) {
if (num_block > I93_ONS_MAX_BLOCKS_PER_READ)
@@ -1699,6 +1736,11 @@
}
}
+ if (num_block == 0) {
+ /* only one remaining block to read */
+ return rw_i93_send_cmd_read_single_block(first_block, false);
+ }
+
return rw_i93_send_cmd_read_multi_blocks(first_block, num_block);
} else {
return rw_i93_send_cmd_read_single_block(first_block, false);
@@ -1763,7 +1805,7 @@
tNFC_STATUS status = NFC_STATUS_FAILED;
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
- "sub_state:%s (0x%x)",
+ "%s - sub_state:%s (0x%x)", __func__,
rw_i93_get_sub_state_name(p_i93->sub_state).c_str(), p_i93->sub_state);
if (length == 0) {
@@ -1781,7 +1823,7 @@
p_i93->intl_flags |= RW_I93_FLAG_16BIT_NUM_BLOCK;
} else {
DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf("Got error flags (0x%02x)", flags);
+ << StringPrintf("%s - Got error flags (0x%02x)", __func__, flags);
rw_i93_handle_error(NFC_STATUS_FAILED);
}
return;
@@ -1802,7 +1844,7 @@
if (u8 != I93_DFS_UNSUPPORTED) {
/* if Data Storage Format is unknown */
DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf("Got unknown DSFID (0x%02x)", u8);
+ << StringPrintf("%s - Got unknown DSFID (0x%02x)", __func__, u8);
rw_i93_handle_error(NFC_STATUS_FAILED);
} else {
/* get system information to get memory size */
@@ -1827,7 +1869,7 @@
if ((p_i93->block_size == 0) || (p_i93->num_block == 0)) {
DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf("Unable to get tag memory size");
+ << StringPrintf("%s - Unable to get tag memory size", __func__);
rw_i93_handle_error(status);
} else {
/* read CC in the first block */
@@ -1869,14 +1911,23 @@
** : Bit 2:More than 2040 bytes are supported [STM, ONS]
*/
- DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
- "cc: 0x%02X 0x%02X 0x%02X 0x%02X", cc[0], cc[1], cc[2], cc[3]);
DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf("Total blocks:0x%04X, Block size:0x%02X",
- p_i93->num_block, p_i93->block_size);
+ << StringPrintf("%s - cc[0-3]: 0x%02X 0x%02X 0x%02X 0x%02X", __func__,
+ cc[0], cc[1], cc[2], cc[3]);
+
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - Total blocks:0x%04X, Block size:0x%02X",
+ __func__, p_i93->num_block, p_i93->block_size);
if ((cc[0] == I93_ICODE_CC_MAGIC_NUMER_E1) ||
(cc[0] == I93_ICODE_CC_MAGIC_NUMER_E2)) {
+ if ((cc[1] & 0xC0) > I93_VERSION_1_x) {
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - Major mapping version above 1 %d.x", __func__, cc[1] >> 6);
+ /* major mapping version above 1 not supported */
+ rw_i93_handle_error(NFC_STATUS_FAILED);
+ break;
+ }
if ((cc[1] & I93_ICODE_CC_READ_ACCESS_MASK) ==
I93_ICODE_CC_READ_ACCESS_GRANTED) {
if ((cc[1] & I93_ICODE_CC_WRITE_ACCESS_MASK) !=
@@ -1885,9 +1936,13 @@
p_i93->intl_flags |= RW_I93_FLAG_READ_ONLY;
}
if (cc[3] & I93_ICODE_CC_MBREAD_MASK) {
- /* tag supports read multi blocks command */
+ /* tag supports read multiple blocks command */
p_i93->intl_flags |= RW_I93_FLAG_READ_MULTI_BLOCK;
}
+ if (cc[3] & I93_ICODE_CC_SPECIAL_FRAME_MASK) {
+ /* tag supports Special Frame for Write-Alike commands */
+ p_i93->intl_flags |= RW_I93_FLAG_SPECIAL_FRAME;
+ }
if (cc[0] == I93_ICODE_CC_MAGIC_NUMER_E2) {
p_i93->intl_flags |= RW_I93_FLAG_EXT_COMMANDS;
}
@@ -1934,8 +1989,8 @@
p_i93->tlv_type = I93_ICODE_TLV_TYPE_TERM;
break;
} else {
- DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf("Invalid type: 0x%02x", *(p + xx));
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - Invalid type: 0x%02x", __func__, *(p + xx));
rw_i93_handle_error(NFC_STATUS_FAILED);
return;
}
@@ -2134,7 +2189,7 @@
p_i93->sent_cmd = 0;
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
- "NDEF cur_size(%d),max_size (%d), flags (0x%x)",
+ "%s - NDEF cur_size(%d),max_size (%d), flags (0x%x)", __func__,
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);
@@ -2174,7 +2229,7 @@
if (flags & I93_FLAG_ERROR_DETECTED) {
DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf("Got error flags (0x%02x)", flags);
+ << StringPrintf("%s - Got error flags (0x%02x)", __func__, flags);
rw_i93_handle_error(NFC_STATUS_FAILED);
return;
}
@@ -2221,14 +2276,14 @@
p_i93->sent_cmd = 0;
DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf("NDEF read complete read (%d)/total (%d)", p_resp->len,
- p_i93->ndef_length);
+ << StringPrintf("%s - NDEF read complete read (%d)/total (%d)",
+ __func__, p_resp->len, p_i93->ndef_length);
(*(rw_cb.p_cback))(RW_I93_NDEF_READ_CPLT_EVT, &rw_data);
} else {
DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf("NDEF read segment read (%d)/total (%d)", p_resp->len,
- p_i93->ndef_length);
+ << StringPrintf("%s - NDEF read segment read (%d)/total (%d)", __func__,
+ p_resp->len, p_i93->ndef_length);
if (p_resp->len > 0) {
(*(rw_cb.p_cback))(RW_I93_NDEF_READ_EVT, &rw_data);
@@ -2264,7 +2319,7 @@
tRW_DATA rw_data;
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
- "sub_state:%s (0x%x)",
+ "%s - sub_state:%s (0x%x)", __func__,
rw_i93_get_sub_state_name(p_i93->sub_state).c_str(), p_i93->sub_state);
if (length == 0 || p_i93->block_size > I93_MAX_BLOCK_LENGH) {
@@ -2285,7 +2340,7 @@
/* ignore error */
} else {
DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf("Got error flags (0x%02x)", flags);
+ << StringPrintf("%s - Got error flags (0x%02x)", __func__, flags);
rw_i93_handle_error(NFC_STATUS_FAILED);
return;
}
@@ -2503,8 +2558,9 @@
}
} else {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
- "NDEF update complete, %d bytes, (%d-%d)", p_i93->ndef_length,
- p_i93->ndef_tlv_start_offset, p_i93->ndef_tlv_last_offset);
+ "%s - NDEF update complete, %d bytes, (%d-%d)", __func__,
+ 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;
@@ -3021,8 +3077,8 @@
tRW_DATA rw_data;
tRW_EVENT event;
- DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf("status:0x%02X, state:0x%X", status, p_i93->state);
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - status:0x%02X, state:0x%X", __func__, status, p_i93->state);
nfc_stop_quick_timer(&p_i93->timer);
@@ -3109,14 +3165,16 @@
void rw_i93_process_timeout(TIMER_LIST_ENT* p_tle) {
NFC_HDR* p_buf;
- DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("event=%d", p_tle->event);
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - event=%d", __func__, 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++;
- LOG(ERROR) << StringPrintf("retry_count = %d", rw_cb.tcb.i93.retry_count);
+ LOG(ERROR) << StringPrintf("%s - retry_count = %d", __func__,
+ rw_cb.tcb.i93.retry_count);
p_buf = rw_cb.tcb.i93.p_retry_cmd;
rw_cb.tcb.i93.p_retry_cmd = nullptr;
@@ -3134,7 +3192,7 @@
}
rw_i93_handle_error(NFC_STATUS_TIMEOUT);
} else {
- LOG(ERROR) << StringPrintf("unknown event=%d", p_tle->event);
+ LOG(ERROR) << StringPrintf("%s - unknown event=%d", __func__, p_tle->event);
}
}
@@ -3155,7 +3213,8 @@
uint8_t begin_state = p_i93->state;
- DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("event = 0x%X", event);
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - event = 0x%X", __func__, event);
if ((event == NFC_DEACTIVATE_CEVT) || (event == NFC_ERROR_CEVT) ||
((event == NFC_DATA_CEVT) && (p_data->status != NFC_STATUS_OK))) {
@@ -3165,7 +3224,8 @@
if ((p_i93->retry_count < RW_MAX_RETRIES) && (p_i93->p_retry_cmd)) {
p_i93->retry_count++;
- LOG(ERROR) << StringPrintf("retry_count = %d", p_i93->retry_count);
+ LOG(ERROR) << StringPrintf("%s - retry_count = %d", __func__,
+ p_i93->retry_count);
p_resp = p_i93->p_retry_cmd;
p_i93->p_retry_cmd = nullptr;
@@ -3219,8 +3279,8 @@
}
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
- "RW I93 state: <%s (%d)>", rw_i93_get_state_name(p_i93->state).c_str(),
- p_i93->state);
+ "%s - RW I93 state: <%s (%d)>", __func__,
+ rw_i93_get_state_name(p_i93->state).c_str(), p_i93->state);
switch (p_i93->state) {
case RW_I93_STATE_IDLE:
@@ -3243,7 +3303,15 @@
break;
case RW_I93_STATE_DETECT_NDEF:
- rw_i93_sm_detect_ndef(p_resp);
+ if (p_i93->i93_t5t_mode == RW_I93_GET_SYS_INFO_MEM_INFO) {
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - rw_i93_sm_detect_ndef()", __func__);
+ rw_i93_sm_detect_ndef(p_resp);
+ } else {
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - rw_t5t_sm_detect_ndef()", __func__);
+ rw_t5t_sm_detect_ndef(p_resp);
+ }
GKI_freebuf(p_resp);
break;
@@ -3253,7 +3321,15 @@
break;
case RW_I93_STATE_UPDATE_NDEF:
- rw_i93_sm_update_ndef(p_resp);
+ if (p_i93->i93_t5t_mode == RW_I93_GET_SYS_INFO_MEM_INFO) {
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - rw_i93_sm_update_ndef()", __func__);
+ rw_i93_sm_update_ndef(p_resp);
+ } else {
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - rw_t5t_sm_update_ndef()", __func__);
+ rw_t5t_sm_update_ndef(p_resp);
+ }
GKI_freebuf(p_resp);
break;
@@ -3263,7 +3339,15 @@
break;
case RW_I93_STATE_SET_READ_ONLY:
- rw_i93_sm_set_read_only(p_resp);
+ if (p_i93->i93_t5t_mode == RW_I93_GET_SYS_INFO_MEM_INFO) {
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - rw_i93_sm_set_read_only()", __func__);
+ rw_i93_sm_set_read_only(p_resp);
+ } else {
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - rw_t5t_sm_set_read_only()", __func__);
+ rw_t5t_sm_set_read_only(p_resp);
+ }
GKI_freebuf(p_resp);
break;
@@ -3278,14 +3362,15 @@
break;
default:
- LOG(ERROR) << StringPrintf("invalid state=%d", p_i93->state);
+ LOG(ERROR) << StringPrintf("%s - invalid state=%d", __func__,
+ p_i93->state);
GKI_freebuf(p_resp);
break;
}
if (begin_state != p_i93->state) {
DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf("RW I93 state changed:<%s> -> <%s>",
+ << StringPrintf("%s - RW I93 state changed:<%s> -> <%s>", __func__,
rw_i93_get_state_name(begin_state).c_str(),
rw_i93_get_state_name(p_i93->state).c_str());
}
@@ -3369,20 +3454,23 @@
** NFC_STATUS_FAILED if other error
**
*******************************************************************************/
-tNFC_STATUS RW_I93StayQuiet(void) {
- tNFC_STATUS status;
+tNFC_STATUS RW_I93StayQuiet(uint8_t* p_uid) {
+ tNFC_STATUS status = NFC_STATUS_FAILED;
DLOG_IF(INFO, nfc_debug_enabled) << __func__;
if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
- LOG(ERROR) << StringPrintf("Unable to start command at state (0x%X)",
- rw_cb.tcb.i93.state);
+ LOG(ERROR) << StringPrintf("%s - Unable to start command at state (0x%X)",
+ __func__, 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;
+ if (p_uid) {
+ status = rw_i93_send_cmd_stay_quiet(p_uid);
+ if (status == NFC_STATUS_OK) {
+ rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
+ rw_cb.tcb.i93.addr_mode = RW_I93_MODE_ADDRESSED;
+ }
}
return status;
@@ -3406,7 +3494,7 @@
tNFC_STATUS status;
DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf("block_number:0x%02X", block_number);
+ << StringPrintf("%s - block_number:0x%02X", __func__, block_number);
if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
LOG(ERROR) << StringPrintf("Unable to start command at state (0x%X)",
@@ -3594,8 +3682,8 @@
DLOG_IF(INFO, nfc_debug_enabled) << __func__;
if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
- LOG(ERROR) << StringPrintf("Unable to start command at state (0x%X)",
- rw_cb.tcb.i93.state);
+ LOG(ERROR) << StringPrintf("%s - Unable to start command at state (0x%X)",
+ __func__, rw_cb.tcb.i93.state);
return NFC_STATUS_BUSY;
}
@@ -3603,9 +3691,11 @@
status = rw_i93_send_cmd_select(p_uid);
if (status == NFC_STATUS_OK) {
rw_cb.tcb.i93.state = RW_I93_STATE_BUSY;
+ rw_cb.tcb.i93.addr_mode = RW_I93_MODE_NON_ADDRESSED;
+ rw_cb.tcb.i93.intl_flags |= RW_I93_FLAG_SELECTED_STATE;
}
} else {
- LOG(ERROR) << StringPrintf("UID shall be provided");
+ LOG(ERROR) << StringPrintf("%s - UID shall be provided", __func__);
status = NFC_STATUS_FAILED;
}
@@ -3632,8 +3722,8 @@
DLOG_IF(INFO, nfc_debug_enabled) << __func__;
if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
- LOG(ERROR) << StringPrintf("Unable to start command at state (0x%X)",
- rw_cb.tcb.i93.state);
+ LOG(ERROR) << StringPrintf("%s - Unable to start command at state (0x%X)",
+ __func__, rw_cb.tcb.i93.state);
return NFC_STATUS_BUSY;
}
@@ -3797,8 +3887,8 @@
DLOG_IF(INFO, nfc_debug_enabled) << __func__;
if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
- LOG(ERROR) << StringPrintf("Unable to start command at state (0x%X)",
- rw_cb.tcb.i93.state);
+ LOG(ERROR) << StringPrintf("%s - Unable to start command at state (0x%X)",
+ __func__, rw_cb.tcb.i93.state);
return NFC_STATUS_BUSY;
}
@@ -3872,16 +3962,18 @@
DLOG_IF(INFO, nfc_debug_enabled) << __func__;
if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
- LOG(ERROR) << StringPrintf("Unable to start command at state (0x%X)",
- rw_cb.tcb.i93.state);
+ LOG(ERROR) << StringPrintf("%s - Unable to start command at state (0x%X)",
+ __func__, 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(nullptr, 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)) {
+
+ } else if (((rw_cb.tcb.i93.num_block == 0) ||
+ (rw_cb.tcb.i93.block_size == 0)) &&
+ (!appl_dta_mode_flag)) {
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;
@@ -3926,8 +4018,8 @@
DLOG_IF(INFO, nfc_debug_enabled) << __func__;
if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
- LOG(ERROR) << StringPrintf("Unable to start command at state (0x%X)",
- rw_cb.tcb.i93.state);
+ LOG(ERROR) << StringPrintf("%s - Unable to start command at state (0x%X)",
+ __func__, rw_cb.tcb.i93.state);
return NFC_STATUS_FAILED;
}
@@ -3942,7 +4034,7 @@
return NFC_STATUS_FAILED;
}
} else {
- LOG(ERROR) << StringPrintf("No NDEF detected");
+ LOG(ERROR) << StringPrintf("%s - No NDEF detected", __func__);
return NFC_STATUS_FAILED;
}
@@ -3969,24 +4061,25 @@
tNFC_STATUS RW_I93UpdateNDef(uint16_t length, uint8_t* p_data) {
uint16_t block_number;
- DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("length:%d", length);
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - length:%d", __func__, length);
if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
- LOG(ERROR) << StringPrintf("Unable to start command at state (0x%X)",
- rw_cb.tcb.i93.state);
+ LOG(ERROR) << StringPrintf("%s - Unable to start command at state (0x%X)",
+ __func__, 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) {
- LOG(ERROR) << StringPrintf("NDEF is read-only");
+ LOG(ERROR) << StringPrintf("%s - NDEF is read-only", __func__);
return NFC_STATUS_FAILED;
}
if (rw_cb.tcb.i93.max_ndef_length < length) {
LOG(ERROR) << StringPrintf(
- "data (%d bytes) is more than max NDEF length "
+ "%s - data (%d bytes) is more than max NDEF length "
"(%d)",
- length, rw_cb.tcb.i93.max_ndef_length);
+ __func__, length, rw_cb.tcb.i93.max_ndef_length);
return NFC_STATUS_FAILED;
}
@@ -4007,7 +4100,7 @@
return NFC_STATUS_FAILED;
}
} else {
- LOG(ERROR) << StringPrintf("No NDEF detected");
+ LOG(ERROR) << StringPrintf("%s - No NDEF detected", __func__);
return NFC_STATUS_FAILED;
}
@@ -4077,17 +4170,20 @@
**
*******************************************************************************/
tNFC_STATUS RW_I93SetTagReadOnly(void) {
+ uint8_t cc_blk0[4];
+
DLOG_IF(INFO, nfc_debug_enabled) << __func__;
if (rw_cb.tcb.i93.state != RW_I93_STATE_IDLE) {
- LOG(ERROR) << StringPrintf("Unable to start command at state (0x%X)",
- rw_cb.tcb.i93.state);
+ LOG(ERROR) << StringPrintf("%s - Unable to start command at state (0x%X)",
+ __func__, 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.tlv_type == I93_ICODE_TLV_TYPE_NDEF) &&
+ (rw_cb.tcb.i93.i93_t5t_mode != RW_T5T_CC_READ_MEM_INFO)) {
if (rw_cb.tcb.i93.intl_flags & RW_I93_FLAG_READ_ONLY) {
- LOG(ERROR) << StringPrintf("NDEF is already read-only");
+ LOG(ERROR) << StringPrintf("%s - NDEF is already read-only", __func__);
return NFC_STATUS_FAILED;
}
@@ -4099,7 +4195,28 @@
return NFC_STATUS_FAILED;
}
} else {
- LOG(ERROR) << StringPrintf("No NDEF detected");
+ if (rw_cb.tcb.i93.i93_t5t_mode == RW_T5T_CC_READ_MEM_INFO) {
+ memcpy(cc_blk0, rw_cb.tcb.i93.gre_cc_content, 4);
+
+ /* mark CC as read-only */
+ *(cc_blk0 + 1) |= I93_ICODE_CC_READ_ONLY;
+
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - Set CC1 to RO - cc[0]=0x%02x, cc[1]=0x%02x, "
+ "cc[2]=0x%02x, cc[3]=0x%02x",
+ __func__, *cc_blk0, *(cc_blk0 + 1), *(cc_blk0 + 2), *(cc_blk0 + 3));
+
+ if (rw_i93_send_cmd_write_single_block(0, cc_blk0) == NFC_STATUS_OK) {
+ rw_cb.tcb.i93.state = RW_I93_STATE_SET_READ_ONLY;
+ rw_cb.tcb.i93.sub_state = RW_I93_SUBSTATE_WAIT_UPDATE_CC;
+ } else {
+ rw_i93_handle_error(NFC_STATUS_FAILED);
+ return NFC_STATUS_FAILED;
+ }
+
+ return NFC_STATUS_OK;
+ }
+ LOG(ERROR) << StringPrintf("%s - No NDEF detected", __func__);
return NFC_STATUS_FAILED;
}
@@ -4131,14 +4248,20 @@
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);
+ (*rw_cb.p_cback)(RW_I93_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 (rw_cb.tcb.i93.i93_t5t_mode == RW_I93_GET_SYS_INFO_MEM_INFO) {
+ /* 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);
+ } else {
+ /* Extended command not expected for presence check */
+ rw_cb.tcb.i93.intl_flags &= ~RW_I93_FLAG_EXT_COMMANDS;
+ status = rw_i93_send_cmd_read_single_block(0, false);
+ }
if (status == NFC_STATUS_OK) {
/* do not retry during presence check */
@@ -4150,6 +4273,38 @@
return (status);
}
+/*****************************************************************************
+**
+** Function RW_I93SetAddressingMode
+**
+** Description Set if the tag must be addressed with UID or not.
+**
+** The addressing mode (addressed or non-addressed) must be
+** done at the module initialization prior to the Tag
+** activation.
+**
+** Returns NFC_STATUS_OK, if mode is stored
+** NFC_STATUS_FAILED: other error
+**
+*****************************************************************************/
+tNFC_STATUS RW_I93SetAddressingMode(bool mode) {
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - I93 state:%d", __func__, rw_cb.tcb.i93.state);
+
+ if (rw_cb.tcb.i93.state == RW_I93_STATE_IDLE) {
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - mode:%d", __func__, mode);
+ if (mode) {
+ rw_cb.tcb.i93.addr_mode = RW_I93_MODE_ADDRESSED;
+ } else {
+ rw_cb.tcb.i93.addr_mode = RW_I93_MODE_NON_ADDRESSED;
+ }
+ return NFC_STATUS_OK;
+ } else {
+ return NFC_STATUS_FAILED;
+ }
+}
+
/*******************************************************************************
**
** Function rw_i93_get_state_name
@@ -4161,7 +4316,7 @@
** Returns pointer to the name
**
*******************************************************************************/
-static std::string rw_i93_get_state_name(uint8_t state) {
+std::string rw_i93_get_state_name(uint8_t state) {
switch (state) {
case RW_I93_STATE_NOT_ACTIVATED:
return "NOT_ACTIVATED";
@@ -4197,7 +4352,7 @@
** Returns pointer to the name
**
*******************************************************************************/
-static std::string rw_i93_get_sub_state_name(uint8_t sub_state) {
+std::string rw_i93_get_sub_state_name(uint8_t sub_state) {
switch (sub_state) {
case RW_I93_SUBSTATE_WAIT_UID:
return "WAIT_UID";
@@ -4205,6 +4360,8 @@
return "WAIT_SYS_INFO";
case RW_I93_SUBSTATE_WAIT_CC:
return "WAIT_CC";
+ case RW_I93_SUBSTATE_WAIT_CC_EXT:
+ return "WAIT_CC_EXT";
case RW_I93_SUBSTATE_SEARCH_NDEF_TLV:
return "SEARCH_NDEF_TLV";
case RW_I93_SUBSTATE_CHECK_LOCK_STATUS:
@@ -4227,6 +4384,8 @@
return "LOCK_NDEF_TLV";
case RW_I93_SUBSTATE_WAIT_LOCK_CC:
return "WAIT_LOCK_CC";
+ case RW_I93_SUBSTATE_LOCK_T5T_AREA:
+ return "LOCK_T5T_AREA";
default:
return "???? UNKNOWN SUBSTATE";
}
@@ -4273,6 +4432,8 @@
return "M24LR04E";
case RW_I93_STM_M24LR16E_R:
return "M24LR16E";
+ case RW_I93_STM_M24LR16D_W:
+ return "M24LR16D-W";
case RW_I93_STM_M24LR64E_R:
return "M24LR64E";
case RW_I93_STM_ST25DV04K:
diff --git a/src/nfc/tags/rw_mfc.cc b/src/nfc/tags/rw_mfc.cc
index aaa5908..649f333 100644
--- a/src/nfc/tags/rw_mfc.cc
+++ b/src/nfc/tags/rw_mfc.cc
@@ -634,6 +634,11 @@
NFC_HDR* mfc_data = nullptr;
tRW_DATA rw_data;
+ if (!p_data) {
+ LOG(ERROR) << __func__ << "Invalid p_data";
+ return;
+ }
+
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("%s conn_id=%i, evt=0x%x", __func__, conn_id, event);
/* Only handle static conn_id */
@@ -676,10 +681,7 @@
evt_data.status = (tNFC_STATUS)(*(uint8_t*)p_data);
} else if (p_data) {
evt_data.status = p_data->status;
- } else {
- evt_data.status = NFC_STATUS_FAILED;
}
-
evt_data.p_data = NULL;
(*rw_cb.p_cback)(RW_MFC_INTF_ERROR_EVT, (tRW_DATA*)&evt_data);
break;
@@ -691,6 +693,11 @@
break;
}
+ if ((p_mfc->state != RW_MFC_STATE_IDLE) && (mfc_data == NULL)) {
+ LOG(ERROR) << StringPrintf("%s NULL pointer", __func__);
+ return;
+ }
+
switch (p_mfc->state) {
case RW_MFC_STATE_IDLE:
/* Unexpected R-APDU, it should be raw frame response */
@@ -1012,7 +1019,7 @@
if (tlv_found) {
p_mfc->ndef_status = MFC_NDEF_DETECTED;
p_mfc->ndef_first_block = p_mfc->last_block_accessed.block;
- rw_mfc_ntf_tlv_detect_complete(tlv_found);
+ rw_mfc_ntf_tlv_detect_complete(NFC_STATUS_OK);
}
break;
diff --git a/src/nfc/tags/rw_t1t.cc b/src/nfc/tags/rw_t1t.cc
index c4e5e31..97c504a 100644
--- a/src/nfc/tags/rw_t1t.cc
+++ b/src/nfc/tags/rw_t1t.cc
@@ -628,7 +628,7 @@
rw_event = rw_t1t_info_to_event(p_cmd_rsp_info);
if (p_t1t->state != RW_T1T_STATE_NOT_ACTIVATED) rw_t1t_handle_op_complete();
- if (rw_event == RW_T2T_NDEF_DETECT_EVT) {
+ if (rw_event == RW_T1T_NDEF_DETECT_EVT) {
tRW_DETECT_NDEF_DATA ndef_data;
ndef_data.status = NFC_STATUS_TIMEOUT;
ndef_data.protocol = NFC_PROTOCOL_T1T;
diff --git a/src/nfc/tags/rw_t2t_ndef.cc b/src/nfc/tags/rw_t2t_ndef.cc
index ad98228..1297815 100644
--- a/src/nfc/tags/rw_t2t_ndef.cc
+++ b/src/nfc/tags/rw_t2t_ndef.cc
@@ -404,7 +404,7 @@
bool found = false;
tRW_EVENT event;
uint8_t index;
- uint8_t count = 0;
+ uint16_t count = 0;
uint8_t xx;
tNFC_STATUS status;
tT2T_CMD_RSP_INFO* p_cmd_rsp_info =
@@ -615,20 +615,16 @@
p_t2t->lock_tlv[p_t2t->num_lock_tlvs].offset =
(p_t2t->tlv_value[0] >> 4) & 0x0F;
p_t2t->lock_tlv[p_t2t->num_lock_tlvs].offset *=
- (uint8_t)tags_pow(2, p_t2t->tlv_value[2] & 0x0F);
+ (uint16_t)tags_pow(2, p_t2t->tlv_value[2] & 0x0F);
p_t2t->lock_tlv[p_t2t->num_lock_tlvs].offset +=
p_t2t->tlv_value[0] & 0x0F;
p_t2t->lock_tlv[p_t2t->num_lock_tlvs].bytes_locked_per_bit =
- (uint8_t)tags_pow(2, ((p_t2t->tlv_value[2] & 0xF0) >> 4));
- /* Note: 0 value in DLA_NbrLockBits means 256 */
+ (uint16_t)tags_pow(2, ((p_t2t->tlv_value[2] & 0xF0) >> 4));
+ /* Note: 0 value in DLA_NbrLockBits means 256 bits */
count = p_t2t->tlv_value[1];
/* Set it to max value that can be stored in lockbytes */
if (count == 0) {
-#if RW_T2T_MAX_LOCK_BYTES > 0x1F
- count = UCHAR_MAX;
-#else
count = RW_T2T_MAX_LOCK_BYTES * TAG_BITS_PER_BYTE;
-#endif
}
p_t2t->lock_tlv[p_t2t->num_lock_tlvs].num_bits = count;
count = count / TAG_BITS_PER_BYTE +
@@ -681,11 +677,17 @@
p_t2t->mem_tlv[p_t2t->num_mem_tlvs].offset =
(p_t2t->tlv_value[0] >> 4) & 0x0F;
p_t2t->mem_tlv[p_t2t->num_mem_tlvs].offset *=
- (uint8_t)tags_pow(2, p_t2t->tlv_value[2] & 0x0F);
+ (uint16_t)tags_pow(2, p_t2t->tlv_value[2] & 0x0F);
+
p_t2t->mem_tlv[p_t2t->num_mem_tlvs].offset +=
p_t2t->tlv_value[0] & 0x0F;
- p_t2t->mem_tlv[p_t2t->num_mem_tlvs].num_bytes =
- p_t2t->tlv_value[1];
+ count = p_t2t->tlv_value[1];
+ /* Note: 0 value in Rsvd_Area_Size means 256 bytes */
+ if (count == 0) {
+ count = RW_T2T_MAX_LOCK_BYTES * TAG_BITS_PER_BYTE;
+ }
+ p_t2t->mem_tlv[p_t2t->num_mem_tlvs].num_bytes = count;
+
p_t2t->num_mem_tlvs++;
rw_t2t_update_attributes();
p_t2t->substate = RW_T2T_SUBSTATE_WAIT_TLV_DETECT;
@@ -855,6 +857,7 @@
tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
const tT2T_INIT_TAG* p_ret;
uint8_t bytes_locked_per_lock_bit = T2T_DEFAULT_LOCK_BLPB;
+ uint16_t t2t_dyn_lock_area_size;
if ((p_t2t->num_lock_tlvs == 0) &&
(p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] > T2T_CC2_TMS_STATIC)) {
@@ -864,10 +867,12 @@
p_ret = t2t_tag_init_data(p_t2t->tag_hdr[0], false, 0);
if (p_ret != nullptr) bytes_locked_per_lock_bit = p_ret->default_lock_blpb;
- num_dynamic_lock_bits =
+ t2t_dyn_lock_area_size =
((p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) -
- (T2T_STATIC_SIZE - T2T_HEADER_SIZE)) /
- bytes_locked_per_lock_bit;
+ (T2T_STATIC_SIZE - T2T_HEADER_SIZE));
+ num_dynamic_lock_bits = t2t_dyn_lock_area_size / bytes_locked_per_lock_bit;
+ num_dynamic_lock_bits += (t2t_dyn_lock_area_size % 8 == 0) ? 0 : 1;
+
num_dynamic_lock_bytes = num_dynamic_lock_bits / 8;
num_dynamic_lock_bytes += (num_dynamic_lock_bits % 8 == 0) ? 0 : 1;
if (num_dynamic_lock_bytes > RW_T2T_MAX_LOCK_BYTES) {
@@ -921,8 +926,7 @@
uint16_t total_ndef_bytes;
uint16_t last_ndef_byte_offset;
uint16_t terminator_tlv_byte_index;
- tNFC_STATUS status;
- uint16_t block;
+ tNFC_STATUS status = NFC_STATUS_OK;
total_ndef_bytes = header_len + p_t2t->new_ndef_msg_len;
num_ndef_bytes = 0;
@@ -937,60 +941,23 @@
}
p_t2t->ndef_last_block_num =
(uint16_t)((last_ndef_byte_offset - 1) / T2T_BLOCK_SIZE);
- block = p_t2t->ndef_last_block_num;
- p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_NDEF_LAST_BLOCK;
- /* Read NDEF last block before updating */
- status = rw_t2t_read(block);
- if (status == NFC_STATUS_OK) {
- if ((p_t2t->new_ndef_msg_len + 1) <= p_t2t->max_ndef_msg_len) {
- /* Locate Terminator TLV Block */
- total_ndef_bytes++;
- terminator_tlv_byte_index = last_ndef_byte_offset;
+ if ((p_t2t->new_ndef_msg_len + 1) <= p_t2t->max_ndef_msg_len) {
+ /* Locate Terminator TLV Block */
+ terminator_tlv_byte_index = last_ndef_byte_offset;
- while (num_ndef_bytes < total_ndef_bytes) {
- if (rw_t2t_is_lock_res_byte((uint16_t)terminator_tlv_byte_index) ==
- false)
- num_ndef_bytes++;
-
- terminator_tlv_byte_index++;
- }
-
- p_t2t->terminator_byte_index = terminator_tlv_byte_index - 1;
- } else {
- /* No space for Terminator TLV */
+ if (rw_t2t_is_lock_res_byte((uint16_t)terminator_tlv_byte_index) == false)
+ p_t2t->terminator_byte_index = terminator_tlv_byte_index;
+ else
p_t2t->terminator_byte_index = 0x00;
- }
+ } else {
+ /* No space for Terminator TLV */
+ p_t2t->terminator_byte_index = 0x00;
}
+
return status;
}
-/*******************************************************************************
-**
-** Function rw_t2t_read_terminator_tlv_block
-**
-** Description This function will read the block where terminator tlv will
-** be added later
-**
-** Returns NCI_STATUS_OK, if read was started. Otherwise, error status.
-**
-*******************************************************************************/
-tNFC_STATUS rw_t2t_read_terminator_tlv_block(void) {
- tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
- tNFC_STATUS status;
- uint16_t block;
-
- /* Send read command to read base block (Block % 4==0) where this block is
- * also read as part of 16 bytes */
- block = p_t2t->terminator_byte_index / T2T_BLOCK_SIZE;
- block -= block % T2T_READ_BLOCKS;
-
- p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TERM_TLV_BLOCK;
- /* Read the block where Terminator TLV may be added later during NDEF Write
- * operation */
- status = rw_t2t_read(block);
- return status;
-}
/*******************************************************************************
**
@@ -1410,25 +1377,27 @@
*******************************************************************************/
static uint16_t rw_t2t_get_ndef_max_size(void) {
uint16_t offset;
- uint8_t xx;
tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
- uint16_t tag_size = (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR) +
- (T2T_FIRST_DATA_BLOCK * T2T_BLOCK_LEN) +
- p_t2t->num_lockbytes;
+ uint16_t tag_size = (p_t2t->tag_hdr[T2T_CC2_TMS_BYTE] * T2T_TMS_TAG_FACTOR);
- for (xx = 0; xx < p_t2t->num_mem_tlvs; xx++)
- tag_size += p_t2t->mem_tlv[xx].num_bytes;
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - T2T_Area size: %d", __func__, tag_size);
+
+ /* Add header to compute max T2T NDEF data offset */
+ tag_size += (T2T_FIRST_DATA_BLOCK * T2T_BLOCK_LEN);
offset = p_t2t->ndef_msg_offset;
p_t2t->max_ndef_msg_len = 0;
- if ((tag_size < T2T_STATIC_SIZE) ||
- (tag_size > (T2T_SECTOR_SIZE * T2T_MAX_SECTOR)) ||
+ if ((tag_size <= T2T_STATIC_SIZE) ||
((p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != T2T_CC0_NMN) &&
(p_t2t->tag_hdr[T2T_CC0_NMN_BYTE] != 0))) {
/* Tag not formated, assume static tag */
p_t2t->max_ndef_msg_len = T2T_STATIC_SIZE - T2T_HEADER_SIZE -
T2T_TLV_TYPE_LEN - T2T_SHORT_NDEF_LEN_FIELD_LEN;
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - Tag assumed static : max_ndef_msg_len=%d",
+ __func__, p_t2t->max_ndef_msg_len);
return p_t2t->max_ndef_msg_len;
}
@@ -1440,15 +1409,19 @@
}
offset++;
}
+
/* NDEF Length field length changes based on NDEF size */
if ((p_t2t->max_ndef_msg_len >= T2T_LONG_NDEF_LEN_FIELD_BYTE0) &&
((p_t2t->ndef_msg_offset - p_t2t->ndef_header_offset) ==
T2T_SHORT_NDEF_LEN_FIELD_LEN)) {
p_t2t->max_ndef_msg_len -=
- (p_t2t->max_ndef_msg_len == T2T_LONG_NDEF_LEN_FIELD_BYTE0)
- ? 1
- : (T2T_LONG_NDEF_LEN_FIELD_LEN - T2T_SHORT_NDEF_LEN_FIELD_LEN);
+ (T2T_LONG_NDEF_LEN_FIELD_LEN - T2T_SHORT_NDEF_LEN_FIELD_LEN);
}
+
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - Max NDEF data storage: max_ndef_msg_len=%d",
+ __func__, p_t2t->max_ndef_msg_len);
+
return p_t2t->max_ndef_msg_len;
}
@@ -1466,14 +1439,49 @@
tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
tNFC_STATUS status;
uint16_t block;
+ uint8_t term_byte_idx;
/* Add Terminator TLV after NDEF Message */
- p_t2t->terminator_tlv_block[p_t2t->terminator_byte_index % T2T_BLOCK_LEN] =
- TAG_TERMINATOR_TLV;
- p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT;
-
block = p_t2t->terminator_byte_index / T2T_BLOCK_LEN;
- status = rw_t2t_write(block, p_t2t->terminator_tlv_block);
+
+ if (block == p_t2t->ndef_last_block_num) {
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - Terminator TLV in same block %d as last NDEF"
+ " bytes",
+ __func__, block);
+
+ /* If Terminator TLV will reside on the NDEF Final block */
+ memcpy(p_t2t->terminator_tlv_block, p_t2t->ndef_last_block, T2T_BLOCK_LEN);
+
+ term_byte_idx = p_t2t->terminator_byte_index % T2T_BLOCK_LEN;
+
+ p_t2t->terminator_tlv_block[term_byte_idx] = TAG_TERMINATOR_TLV;
+ if (term_byte_idx < (T2T_BLOCK_LEN - 1)) {
+ for (int i = term_byte_idx + 1; i < T2T_BLOCK_LEN; i++)
+ p_t2t->terminator_tlv_block[i] = 0x00;
+ }
+
+ p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT;
+ status = rw_t2t_write(block, p_t2t->terminator_tlv_block);
+
+ } else if (p_t2t->terminator_byte_index != 0) {
+ /* If there is space for Terminator TLV and if it will reside outside
+ * NDEF Final block */
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - Terminator TLV in block %d following the last NDEF block",
+ __func__, block);
+ p_t2t->terminator_tlv_block[0] = TAG_TERMINATOR_TLV;
+ p_t2t->terminator_tlv_block[1] = 0x00;
+ p_t2t->terminator_tlv_block[2] = 0x00;
+ p_t2t->terminator_tlv_block[3] = 0x00;
+
+ p_t2t->substate = RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT;
+ status = rw_t2t_write(block, p_t2t->terminator_tlv_block);
+
+ } else {
+ /* If there is no space for Terminator TLV, conclude NDEF procedure */
+ status = NFC_STATUS_CONTINUE;
+ }
return status;
}
@@ -1554,6 +1562,7 @@
bool done = false;
uint16_t block;
uint8_t offset;
+ tNFC_STATUS status = NFC_STATUS_FAILED;
switch (p_t2t->substate) {
case RW_T2T_SUBSTATE_WAIT_READ_NDEF_FIRST_BLOCK:
@@ -1562,40 +1571,8 @@
memcpy(p_t2t->ndef_first_block, p_data, T2T_BLOCK_LEN);
/* Read ndef final block */
if (rw_t2t_read_ndef_last_block() != NFC_STATUS_OK) failed = true;
- break;
+ memset(p_t2t->terminator_tlv_block, 0, T2T_BLOCK_LEN);
- case RW_T2T_SUBSTATE_WAIT_READ_NDEF_LAST_BLOCK:
-
- offset = (uint8_t)(p_t2t->ndef_last_block_num - p_t2t->block_read) *
- T2T_BLOCK_SIZE;
- /* Backup the read NDEF final block */
- memcpy(p_t2t->ndef_last_block, &p_data[offset], T2T_BLOCK_LEN);
- if ((p_t2t->terminator_byte_index / T2T_BLOCK_SIZE) ==
- p_t2t->ndef_last_block_num) {
- /* If Terminator TLV will reside on the NDEF Final block */
- memcpy(p_t2t->terminator_tlv_block, p_t2t->ndef_last_block,
- T2T_BLOCK_LEN);
- if (rw_t2t_write_ndef_first_block(0x0000, false) != NFC_STATUS_OK)
- failed = true;
- } else if (p_t2t->terminator_byte_index != 0) {
- /* If there is space for Terminator TLV and if it will reside outside
- * NDEF Final block */
- if (rw_t2t_read_terminator_tlv_block() != NFC_STATUS_OK) failed = true;
- } else {
- if (rw_t2t_write_ndef_first_block(0x0000, false) != NFC_STATUS_OK)
- failed = true;
- }
- break;
-
- case RW_T2T_SUBSTATE_WAIT_READ_TERM_TLV_BLOCK:
-
- offset = (uint8_t)(((p_t2t->terminator_byte_index / T2T_BLOCK_SIZE) -
- p_t2t->block_read) *
- T2T_BLOCK_SIZE);
- /* Backup the read Terminator TLV block */
- memcpy(p_t2t->terminator_tlv_block, &p_data[offset], T2T_BLOCK_LEN);
-
- /* Write the first block for new NDEF Message */
if (rw_t2t_write_ndef_first_block(0x0000, false) != NFC_STATUS_OK)
failed = true;
break;
@@ -1673,7 +1650,11 @@
break;
case RW_T2T_SUBSTATE_WAIT_WRITE_NDEF_LEN_BLOCK:
- if (rw_t2t_add_terminator_tlv() != NFC_STATUS_OK) failed = true;
+ status = rw_t2t_add_terminator_tlv();
+ if (status == NFC_STATUS_CONTINUE)
+ done = true;
+ else if (status != NFC_STATUS_OK)
+ failed = true;
break;
case RW_T2T_SUBSTATE_WAIT_WRITE_TERM_TLV_CMPLT:
@@ -1756,7 +1737,10 @@
/* First soft lock the tag */
rw_t2t_soft_lock_tag();
-
+ if (p_t2t->b_hard_lock) {
+ /* Tag configuration not complete */
+ status = NFC_STATUS_OK;
+ }
break;
case RW_T2T_SUBSTATE_WAIT_SET_CC_RO:
@@ -1768,11 +1752,21 @@
status = NFC_STATUS_OK;
b_notify = true;
break;
+ } else {
+ /* Tag configuration not complete */
+ status = NFC_STATUS_OK;
+ /* Copy the internal bytes */
+ memcpy(write_block,
+ &p_t2t->tag_hdr[T2T_STATIC_LOCK0 - T2T_INTERNAL_BYTES_LEN],
+ T2T_INTERNAL_BYTES_LEN);
+ /* Set all Static lock bits */
+ write_block[T2T_STATIC_LOCK0 % T2T_BLOCK_SIZE] = 0xFF;
+ write_block[T2T_STATIC_LOCK1 % T2T_BLOCK_SIZE] = 0xFF;
+ p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_DYN_LOCK_BITS;
+ status = rw_t2t_write((T2T_STATIC_LOCK0 / T2T_BLOCK_SIZE), write_block);
}
- FALLTHROUGH_INTENDED;
+ break;
- /* Coverity: [FALSE-POSITIVE error] intended fall through */
- /* Missing break statement between cases in switch statement */
case RW_T2T_SUBSTATE_WAIT_SET_DYN_LOCK_BITS:
num_locks = 0;
@@ -1787,8 +1781,21 @@
if (!b_pending &&
p_t2t->lockbyte[num_locks].lock_status == RW_T2T_LOCK_NOT_UPDATED) {
/* One or more dynamic lock bits are not set */
- b_pending = true;
- read_lock = num_locks;
+ if (num_locks == 0) {
+ offset = p_t2t->lock_tlv[p_t2t->lockbyte[0].tlv_index].offset +
+ p_t2t->lockbyte[0].byte_index;
+ if (offset % T2T_BLOCK_SIZE) {
+ /* For backward compatibility in case the DynLock_Area is not
+ * aligned to a block boundary, first read the block not to
+ * overwrite possible NDEF or Reserved data
+ */
+ b_pending = true;
+ read_lock = num_locks;
+ } else {
+ /* Write zero in internal byte */
+ memset(write_block, 0, T2T_BLOCK_SIZE);
+ }
+ }
}
num_locks++;
}
@@ -1796,35 +1803,24 @@
if (b_pending) {
/* Read the block where dynamic lock bits are present to avoid writing
* to NDEF bytes in the same block */
- offset = p_t2t->lock_tlv[p_t2t->lockbyte[read_lock].tlv_index].offset +
- p_t2t->lockbyte[read_lock].byte_index;
p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_DYN_LOCK_BYTE_BLOCK;
status = rw_t2t_read((uint16_t)(offset / T2T_BLOCK_LEN));
} else {
- /* Now set Static lock bits as no more dynamic lock bits to set */
-
- /* Copy the internal bytes */
- memcpy(write_block,
- &p_t2t->tag_hdr[T2T_STATIC_LOCK0 - T2T_INTERNAL_BYTES_LEN],
- T2T_INTERNAL_BYTES_LEN);
- /* Set all Static lock bits */
- write_block[T2T_STATIC_LOCK0 % T2T_BLOCK_SIZE] = 0xFF;
- write_block[T2T_STATIC_LOCK1 % T2T_BLOCK_SIZE] = 0xFF;
- p_t2t->substate = RW_T2T_SUBSTATE_WAIT_SET_ST_LOCK_BITS;
- status = rw_t2t_write((T2T_STATIC_LOCK0 / T2T_BLOCK_SIZE), write_block);
+ /* Now set the dynamic lock bits present in the block read now */
+ status = rw_t2t_set_dynamic_lock_bits(write_block);
+ if (status == NFC_STATUS_CONTINUE) {
+ /* Tag configuration complete */
+ status = NFC_STATUS_OK;
+ b_notify = true;
+ }
}
+
break;
case RW_T2T_SUBSTATE_WAIT_READ_DYN_LOCK_BYTE_BLOCK:
/* Now set the dynamic lock bits present in the block read now */
status = rw_t2t_set_dynamic_lock_bits(p_data);
break;
-
- case RW_T2T_SUBSTATE_WAIT_SET_ST_LOCK_BITS:
- /* Tag configuration complete */
- status = NFC_STATUS_OK;
- b_notify = true;
- break;
}
if (status != NFC_STATUS_OK || b_notify) {
@@ -1970,6 +1966,9 @@
uint16_t lower_offset;
uint16_t upper_offset;
uint16_t offset;
+ uint16_t offset_in_seg;
+ uint16_t block_boundary;
+ uint8_t num_internal_bytes;
uint8_t num_bytes;
/* Prepare attr for the current segment */
@@ -1989,18 +1988,53 @@
if (offset >= lower_offset && offset < upper_offset) {
/* Calculate offset in the current segment as p_t2t->attr is prepared for
* one segment only */
- offset %= RW_T2T_SEGMENT_BYTES;
+ offset_in_seg = offset % RW_T2T_SEGMENT_BYTES;
/* Every bit in p_t2t->attr indicates one byte of the tag is either a
* lock/reserved byte or not
* So, each array element in p_t2t->attr covers two blocks in the tag as
* T2 block size is 4 and array element size is 8
* Set the corresponding bit in attr to indicate - reserved byte */
- p_t2t->attr[offset / TAG_BITS_PER_BYTE] |=
- rw_t2t_mask_bits[offset % TAG_BITS_PER_BYTE];
+ p_t2t->attr[offset_in_seg / TAG_BITS_PER_BYTE] |=
+ rw_t2t_mask_bits[offset_in_seg % TAG_BITS_PER_BYTE];
}
count++;
}
+ block_boundary = (offset + 1) % T2T_BLOCK_LEN;
+ if (block_boundary) {
+ /* End of DynLock_Area is not aligned to a block boundary. The bytes that
+ * are not part of the area within the same block are Internal Bytes (see
+ * [T2T-TS] section 4.7).
+ * According to REQ 4.4.1.5, either write them to 00h or to their existing
+ * values. However according to the NDEF Write procedure, REQ 7.5.5.5,
+ * symbol 5, the Reader SHALL not write to the DynLock_Area and the
+ * Rsvd_Area(s), as indicated by the Lock Control TLV or the Memory
+ * Control TLVs, if any.
+ * Choice is made to consider the bytes within the same block as the
+ * DynLock_Area last bytes as lock bytes i.e. they will not be written
+ * and therefore previously read (steps anyhow not expected by NFC Forum
+ * Test Specifications).
+ */
+ num_internal_bytes = T2T_BLOCK_LEN - block_boundary;
+ count = 1;
+
+ while (count <= num_internal_bytes) {
+ offset++;
+ if (offset >= lower_offset && offset < upper_offset) {
+ /* Calculate offset in the current segment as p_t2t->attr is prepared
+ * for one segment only */
+ offset_in_seg = offset % RW_T2T_SEGMENT_BYTES;
+ /* Every bit in p_t2t->attr indicates one byte of the tag is either a
+ * lock/reserved/internal byte or not
+ * So, each array element in p_t2t->attr covers two blocks in the tag as
+ * T2 block size is 4 and array element size is 8
+ * Set the corresponding bit in attr to indicate - reserved byte */
+ p_t2t->attr[offset_in_seg / TAG_BITS_PER_BYTE] |=
+ rw_t2t_mask_bits[offset_in_seg % TAG_BITS_PER_BYTE];
+ }
+ count++;
+ }
+ }
/* Search reserved bytes identified by all memory tlvs present in the tag */
count = 0;
while (count < p_t2t->num_mem_tlvs) {
@@ -2055,7 +2089,7 @@
uint16_t lower_offset, upper_offset;
uint8_t num_dynamic_locks = 0;
uint8_t bit_count = 0;
- uint8_t bytes_locked_per_bit;
+ uint16_t bytes_locked_per_bit;
uint8_t num_bits;
tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
bool b_all_bits_are_locks = true;
@@ -2189,10 +2223,10 @@
uint8_t num_static_lock_bytes = 0;
uint8_t num_dyn_lock_bytes = 0;
uint8_t bits_covered = 0;
- uint8_t bytes_covered = 0;
+ uint16_t bytes_covered = 0;
uint8_t block_count = 0;
bool b_all_bits_are_locks = true;
- uint8_t bytes_locked_per_lock_bit;
+ uint16_t bytes_locked_per_lock_bit;
uint8_t start_lock_byte;
uint8_t start_lock_bit;
uint8_t end_lock_byte;
@@ -2464,6 +2498,9 @@
status = NFC_STATUS_FAILED;
break;
+
+ } else {
+ status = NFC_STATUS_CONTINUE;
}
num_locks++;
}
diff --git a/src/nfc/tags/rw_t3t.cc b/src/nfc/tags/rw_t3t.cc
index 58b84fd..0e91498 100644
--- a/src/nfc/tags/rw_t3t.cc
+++ b/src/nfc/tags/rw_t3t.cc
@@ -1729,6 +1729,7 @@
/* Validate response for NDEF poll */
if ((nci_status == NCI_STATUS_OK) && (num_responses > 0)) {
/* Tag responded for NDEF poll */
+ p_cb->cur_active_sc = T3T_SYSTEM_CODE_NDEF;
/* Read NDEF attribute block */
p_cmd_buf = rw_t3t_get_cmd_buf();
@@ -1851,6 +1852,7 @@
/* Validate response for poll response */
if ((nci_status == NCI_STATUS_OK) && (num_responses > 0)) {
/* Tag responded for Felica-Lite poll */
+ p_cb->cur_active_sc = T3T_SYSTEM_CODE_FELICA_LITE;
/* Get MemoryControl block */
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
"Felica-Lite tag detected...getting Memory Control block.");
@@ -2298,7 +2300,7 @@
(p_data->data.status == NFC_STATUS_CONTINUE))) {
rw_t3t_data_cback(conn_id, &(p_data->data));
break;
- } else if (p_data->data.p_data != nullptr) {
+ } else if (p_data && p_data->data.p_data != nullptr) {
/* Free the response buffer in case of error response */
GKI_freebuf((NFC_HDR*)(p_data->data.p_data));
p_data->data.p_data = nullptr;
@@ -2588,6 +2590,14 @@
} else if (p_cb->ndef_attrib.ln == 0) {
LOG(ERROR) << StringPrintf("Type 3 tag contains empty NDEF message");
return (NFC_STATUS_FAILED);
+ } else if (p_cb->ndef_attrib.writef ==
+ T3T_MSG_NDEF_WRITEF_ON) /* Tag's NDEF memory write in progress? */
+ {
+ LOG(ERROR) << StringPrintf(
+ "%s - WriteFlag ON: NDEF data may be inconsistent, "
+ "conclude NDEF Read procedure",
+ __func__);
+ return (NFC_STATUS_FAILED);
}
/* Check number of blocks needed for this update */
@@ -2792,7 +2802,7 @@
}
} else {
/* IDLE state: send POLL command */
- retval = (tNFC_STATUS)nci_snd_t3t_polling(0xFFFF, T3T_POLL_RC_SC, 0);
+ retval = (tNFC_STATUS)nci_snd_t3t_polling(0xFFFF, T3T_POLL_RC_SC, 0x03);
if (retval == NCI_STATUS_OK) {
p_rw_cb->tcb.t3t.flags |= RW_T3T_FL_W4_PRESENCE_CHECK_POLL_RSP;
p_rw_cb->tcb.t3t.rw_state = RW_T3T_STATE_COMMAND_PENDING;
@@ -2918,7 +2928,12 @@
p_cb->rw_state);
return (NFC_STATUS_FAILED);
} else {
- retval = (tNFC_STATUS)nci_snd_t3t_polling(0xFFFF, T3T_POLL_RC_SC, 0);
+ /* Until the card answers properly to SC=12FCh, by default, consider
+ the card as a Felica card not NDEF compatible, answering to SC=0x88B4
+ possibly */
+ p_cb->cur_active_sc = T3T_SYSTEM_CODE_FELICA_LITE;
+
+ retval = (tNFC_STATUS)nci_snd_t3t_polling(0xFFFF, T3T_POLL_RC_SC, 0x0F);
if (retval == NCI_STATUS_OK) {
p_cb->cur_cmd = RW_T3T_CMD_GET_SYSTEM_CODES;
p_cb->cur_tout = RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS;
@@ -2987,7 +3002,8 @@
** Function RW_T3tSetReadOnly
**
** Description This function performs NDEF read-only procedure
-** Note: Only Felica-Lite tags are supported by this API.
+** Note: Both NFC Forum and Felica-Lite tags are supported by
+** this API.
** RW_T3tDetectNDef() must be called before using this
**
** The RW_T3T_SET_READ_ONLY_CPLT_EVT event will be returned.
@@ -3000,6 +3016,11 @@
tNFC_STATUS retval = NFC_STATUS_OK;
tRW_T3T_CB* p_cb = &rw_cb.tcb.t3t;
tRW_DATA evt_data;
+ uint8_t rw_t3t_ndef_attrib_info[T3T_MSG_BLOCKSIZE];
+ uint8_t* p;
+ uint32_t tempU32 = 0;
+ uint16_t checksum, i;
+ uint8_t tempU8;
DLOG_IF(INFO, nfc_debug_enabled)
<< StringPrintf("b_hard_lock=%d", b_hard_lock);
@@ -3026,22 +3047,71 @@
(*(rw_cb.p_cback))(RW_T3T_SET_READ_ONLY_CPLT_EVT, &evt_data);
return (retval);
} else {
- /* Poll tag, to see if Felica-Lite system is supported */
- retval = (tNFC_STATUS)nci_snd_t3t_polling(T3T_SYSTEM_CODE_FELICA_LITE,
- T3T_POLL_RC_SC, 0);
- if (retval == NCI_STATUS_OK) {
- if (b_hard_lock)
- p_cb->cur_cmd = RW_T3T_CMD_SET_READ_ONLY_HARD;
- else
+ if (p_cb->cur_active_sc == T3T_SYSTEM_CODE_NDEF) {
+ /* Tag previously responded for NDEF poll */
+ if (p_cb->ndef_attrib.rwflag != T3T_MSG_NDEF_RWFLAG_RO) {
+ /* First update attribute information block */
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - NDEF tag detected...update NDef attribution block.",
+ __func__);
p_cb->cur_cmd = RW_T3T_CMD_SET_READ_ONLY_SOFT;
- p_cb->cur_tout = RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS;
- p_cb->cur_poll_rc = T3T_POLL_RC_SC;
- p_cb->rw_state = RW_T3T_STATE_COMMAND_PENDING;
- p_cb->rw_substate = RW_T3T_SRO_SST_POLL_FELICA_LITE;
- p_cb->flags |= RW_T3T_FL_W4_SRO_FELICA_LITE_POLL_RSP;
- /* start timer for waiting for responses */
- rw_t3t_start_poll_timer(p_cb);
+ p_cb->rw_substate = RW_T3T_SRO_SST_UPDATE_NDEF_ATTRIB;
+
+ p = rw_t3t_ndef_attrib_info;
+
+ UINT8_TO_STREAM(p, p_cb->ndef_attrib.version);
+
+ /* Update NDEF info */
+ UINT8_TO_STREAM(
+ p, p_cb->ndef_attrib.nbr); /* NBr: number of blocks that can be read
+ using one Check command */
+ UINT8_TO_STREAM(p, p_cb->ndef_attrib.nbw); /* Nbw: number of blocks that
+ can be written using one
+ Update command */
+ UINT16_TO_BE_STREAM(
+ p, p_cb->ndef_attrib.nmaxb); /* Nmaxb: maximum number of blocks
+ available for NDEF data */
+ UINT32_TO_BE_STREAM(p, tempU32);
+ UINT8_TO_STREAM(
+ p, p_cb->ndef_attrib.writef); /* WriteFlag: 00h if writing
+ data finished; 0Fh if
+ writing data in progress */
+ UINT8_TO_STREAM(p, 0x00); /* RWFlag: 00h NDEF is read-only */
+
+ tempU8 = (uint8_t)(p_cb->ndef_attrib.ln >> 16);
+ /* Get length (3-byte, big-endian) */
+ UINT8_TO_STREAM(p, tempU8); /* Ln: high-byte */
+ UINT16_TO_BE_STREAM(p, p_cb->ndef_attrib.ln); /* Ln: lo-word */
+
+ /* Calculate and append Checksum */
+ checksum = 0;
+ for (i = 0; i < T3T_MSG_NDEF_ATTR_INFO_SIZE; i++) {
+ checksum += rw_t3t_ndef_attrib_info[i];
+ }
+ UINT16_TO_BE_STREAM(p, checksum);
+
+ retval =
+ rw_t3t_update_block(p_cb, 0, (uint8_t*)rw_t3t_ndef_attrib_info);
+ }
+ } else {
+ /* Poll tag, to see if Felica-Lite system is supported */
+ retval = (tNFC_STATUS)nci_snd_t3t_polling(T3T_SYSTEM_CODE_FELICA_LITE,
+ T3T_POLL_RC_SC, 0);
+ if (retval == NCI_STATUS_OK) {
+ if (b_hard_lock)
+ p_cb->cur_cmd = RW_T3T_CMD_SET_READ_ONLY_HARD;
+ else
+ p_cb->cur_cmd = RW_T3T_CMD_SET_READ_ONLY_SOFT;
+ p_cb->cur_tout = RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS;
+ p_cb->cur_poll_rc = T3T_POLL_RC_SC;
+ p_cb->rw_state = RW_T3T_STATE_COMMAND_PENDING;
+ p_cb->rw_substate = RW_T3T_SRO_SST_POLL_FELICA_LITE;
+ p_cb->flags |= RW_T3T_FL_W4_SRO_FELICA_LITE_POLL_RSP;
+
+ /* start timer for waiting for responses */
+ rw_t3t_start_poll_timer(p_cb);
+ }
}
}
return (retval);
diff --git a/src/nfc/tags/rw_t4t.cc b/src/nfc/tags/rw_t4t.cc
index b7b6144..e5d3ef2 100644
--- a/src/nfc/tags/rw_t4t.cc
+++ b/src/nfc/tags/rw_t4t.cc
@@ -39,6 +39,7 @@
using android::base::StringPrintf;
extern bool nfc_debug_enabled;
+extern unsigned char appl_dta_mode_flag;
/* main state */
/* T4T is not activated */
@@ -78,7 +79,8 @@
#define RW_T4T_SUBSTATE_WAIT_UPDATE_NLEN 0x07
/* waiting for response of updating CC */
#define RW_T4T_SUBSTATE_WAIT_UPDATE_CC 0x08
-
+/* waiting for response of reading CC */
+#define RW_T4T_SUBSTATE_WAIT_ENDEF_FILE_CTRL_TLV 0x11
#define RW_T4T_SUBSTATE_WAIT_GET_HW_VERSION 0x09
#define RW_T4T_SUBSTATE_WAIT_GET_SW_VERSION 0x0A
#define RW_T4T_SUBSTATE_WAIT_GET_UID 0x0B
@@ -93,9 +95,9 @@
static bool rw_t4t_send_to_lower(NFC_HDR* p_c_apdu);
static bool rw_t4t_select_file(uint16_t file_id);
-static bool rw_t4t_read_file(uint16_t offset, uint16_t length,
+static bool rw_t4t_read_file(uint32_t offset, uint32_t length,
bool is_continue);
-static bool rw_t4t_update_nlen(uint16_t ndef_len);
+static bool rw_t4t_update_nlen(uint32_t ndef_len);
static bool rw_t4t_update_file(void);
static bool rw_t4t_update_cc_to_readonly(void);
static bool rw_t4t_select_application(uint8_t version);
@@ -141,6 +143,159 @@
/*******************************************************************************
**
+** Function rw_t4t_set_ber_tlv
+**
+** Description Send UpdateBinary Command with ODO and DDO
+**
+** Returns TRUE if success
+**
+*******************************************************************************/
+static bool rw_t4t_set_ber_tlv(NFC_HDR* p_c_apdu, uint8_t* p, uint32_t length) {
+ tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
+ uint32_t data_length, tmp_length, tmp_offset;
+ uint8_t length_size, data_header = 0;
+
+ p_c_apdu->len = T4T_CMD_MIN_EXT_HDR_SIZE + 1; /* tag 53 */
+ /* Remove min data header for encoding offset and data length */
+ /* length is Lc data length */
+ /* data_length is the length of the data to be written to the ENDEF
+ * File */
+ data_length = length;
+ if (length <= 0x7F) {
+ /* Default Short Field Coding can be used */
+ /* BER-TLV length coded on one byte */
+ length_size = RW_T4T_BER_TLV_LENGTH_1_BYTE;
+
+ } else if ((length + RW_T4T_ODO_DDO_HEADER_2BYTES_LENGTH) <= 0xFF) {
+ /* Default Short Field Coding can be used */
+ /* BER-TLV length coded on two bytes: (81h+N) with N=0 to 255 */
+ length_size = RW_T4T_BER_TLV_LENGTH_2_BYTES;
+
+ } else {
+ if (p_t4t->intl_flags & RW_T4T_EXT_FIELD_CODING) {
+ /* Extended Field Coding can be used */
+ if (length <= 0xFF) {
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - Extended Field Coding used, 2-byte coding "
+ "for BER-TLV",
+ __func__);
+ /* BER-TLV length coded on two bytes still possible */
+ length_size = RW_T4T_BER_TLV_LENGTH_2_BYTES;
+
+ } else {
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - Extended Field Coding used, 3-byte coding "
+ "for BER-TLV",
+ __func__);
+ /* BER-TLV length coded on three bytes:
+ * (82h+N) with N=0 to 65535 */
+ length_size = RW_T4T_BER_TLV_LENGTH_3_BYTES;
+ }
+ } else {
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - Short Field Coding used", __func__);
+ /* Only Short Field Coding can be used */
+ /* Write a max of 255 bytes in data field,
+ * as Lc=00 is reserved for Extended Field coding */
+ /* BER-TLV length coded on two bytes */
+ length_size = RW_T4T_BER_TLV_LENGTH_2_BYTES;
+ length = 0;
+ }
+ }
+
+ data_header = RW_T4T_ODO_DDO_HEADER_MIN_LENGTH + length_size;
+ if (length == 0) {
+ length = T4T_MAX_LENGTH_LC;
+ if (length <= p_t4t->max_update_size) {
+ data_length = T4T_MAX_LENGTH_LC - data_header;
+ } else {
+ /* Realign with MLc (taking into account header now) */
+ length = p_t4t->max_update_size;
+ data_length = p_t4t->max_update_size - data_header;
+ }
+ } else {
+ if ((length + data_header) <= p_t4t->max_update_size) {
+ length += data_header;
+ } else {
+ /* Realign with MLc (taking into account header now) */
+ length = p_t4t->max_update_size;
+ data_length = p_t4t->max_update_size - data_header;
+ }
+ }
+
+ UINT8_TO_BE_STREAM(p, T4T_CMD_CLASS);
+ UINT8_TO_BE_STREAM(p, T4T_CMD_INS_UPDATE_BINARY_ODO);
+ /* P1 P2 field */
+ UINT16_TO_BE_STREAM(p, 0x0000);
+ /* Lc field */
+ if (p_t4t->intl_flags & RW_T4T_EXT_FIELD_CODING) {
+ /* Coded over three bytes */
+ UINT8_TO_BE_STREAM(p, 0x00);
+ tmp_length = length;
+ tmp_length >>= 8;
+ UINT8_TO_BE_STREAM(p, ((uint8_t)tmp_length));
+ tmp_length = length;
+ UINT8_TO_BE_STREAM(p, ((uint8_t)tmp_length));
+ p_c_apdu->len += 3;
+ } else {
+ /* Coded over 1 byte */
+ UINT8_TO_BE_STREAM(p, ((uint8_t)length));
+ p_c_apdu->len += 1;
+ }
+
+ /* Data field containing data offset coded over 3 bytes
+ * followed by data to be written to the ENDEF File */
+ UINT16_TO_BE_STREAM(p, 0x5403);
+ tmp_offset = p_t4t->rw_offset;
+ tmp_offset >>= 16;
+ UINT8_TO_BE_STREAM(p, ((uint8_t)tmp_offset));
+ tmp_offset = p_t4t->rw_offset;
+ tmp_offset >>= 8;
+ UINT8_TO_BE_STREAM(p, ((uint8_t)tmp_offset));
+ tmp_offset = p_t4t->rw_offset;
+ UINT8_TO_BE_STREAM(p, ((uint8_t)tmp_offset));
+
+ UINT8_TO_BE_STREAM(p, 0x53);
+ /* Data length */
+ if (length_size == RW_T4T_BER_TLV_LENGTH_1_BYTE) {
+ /* Length coded over 1 byte */
+ UINT8_TO_BE_STREAM(p, data_length);
+ p_c_apdu->len += 1;
+ } else if (length_size == RW_T4T_BER_TLV_LENGTH_2_BYTES) {
+ UINT8_TO_BE_STREAM(p, 0x81);
+ UINT8_TO_BE_STREAM(p, data_length);
+ p_c_apdu->len += 2;
+ } else if ((length_size == RW_T4T_BER_TLV_LENGTH_3_BYTES) &&
+ (data_length <= 0xFFFF)) {
+ /* Length coded over 3 bytes */
+ UINT8_TO_BE_STREAM(p, 0x82);
+ UINT16_TO_BE_STREAM(p, (uint16_t)data_length);
+ p_c_apdu->len += 3;
+ } else {
+ LOG(ERROR) << StringPrintf(
+ "%s - Data to be written to MV3.0 tag exceeds 0xFFFF", __func__);
+ return false;
+ }
+
+ memcpy(p, p_t4t->p_update_data, data_length);
+
+ p_c_apdu->len += data_length;
+
+ if (!rw_t4t_send_to_lower(p_c_apdu)) {
+ return false;
+ }
+ /* Le field not present */
+
+ /* adjust offset, length and pointer for remaining data */
+ p_t4t->rw_offset += data_length;
+ p_t4t->rw_length -= data_length;
+ p_t4t->p_update_data += data_length;
+
+ return true;
+}
+
+/*******************************************************************************
+**
** Function rw_t4t_get_hw_version
**
** Description Send get hw version cmd to peer
@@ -610,12 +765,13 @@
NFC_HDR* p_c_apdu;
uint8_t* p;
- DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("File ID:0x%04X", file_id);
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - File ID:0x%04X", __func__, file_id);
p_c_apdu = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
if (!p_c_apdu) {
- LOG(ERROR) << StringPrintf("Cannot allocate buffer");
+ LOG(ERROR) << StringPrintf("%s - Cannot allocate buffer", __func__);
return false;
}
@@ -627,7 +783,8 @@
UINT8_TO_BE_STREAM(p, T4T_CMD_P1_SELECT_BY_FILE_ID);
/* if current version mapping is V2.0 */
- if (rw_cb.tcb.t4t.version == T4T_VERSION_2_0) {
+ if ((rw_cb.tcb.t4t.version == T4T_VERSION_2_0) ||
+ (rw_cb.tcb.t4t.version == T4T_VERSION_3_0)) {
UINT8_TO_BE_STREAM(p, T4T_CMD_P2_FIRST_OR_ONLY_0CH);
} else /* version 1.0 */
{
@@ -655,19 +812,21 @@
** Returns TRUE if success
**
*******************************************************************************/
-static bool rw_t4t_read_file(uint16_t offset, uint16_t length,
+static bool rw_t4t_read_file(uint32_t offset, uint32_t length,
bool is_continue) {
tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
NFC_HDR* p_c_apdu;
uint8_t* p;
+ uint32_t tmp_offset;
- DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
- "offset:%d, length:%d, is_continue:%d, ", offset, length, is_continue);
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - offset:%d, length:%d, is_continue:%d, ", __func__,
+ offset, length, is_continue);
p_c_apdu = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
if (!p_c_apdu) {
- LOG(ERROR) << StringPrintf("Cannot allocate buffer");
+ LOG(ERROR) << StringPrintf("%s - Cannot allocate buffer", __func__);
return false;
}
@@ -682,18 +841,97 @@
/* adjust reading length if payload is bigger than max size per single command
*/
if (length > p_t4t->max_read_size) {
- length = (uint8_t)(p_t4t->max_read_size);
+ length = (uint32_t)(p_t4t->max_read_size);
}
p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
p = (uint8_t*)(p_c_apdu + 1) + p_c_apdu->offset;
UINT8_TO_BE_STREAM(p, (T4T_CMD_CLASS | rw_cb.tcb.t4t.channel));
- UINT8_TO_BE_STREAM(p, T4T_CMD_INS_READ_BINARY);
- UINT16_TO_BE_STREAM(p, offset);
- UINT8_TO_BE_STREAM(p, length); /* Le */
+ if ((p_t4t->rw_offset + p_t4t->rw_length) > 0x7FFF) {
+ /* ReadBinary with ODO must be used */
+ if (p_t4t->cc_file.version >= T4T_VERSION_3_0) {
+ /* MV 3.0 tag */
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - Read above 0x7FFF address offset detected", __func__);
- p_c_apdu->len = T4T_CMD_MIN_HDR_SIZE + 1; /* adding Le */
+ p_c_apdu->len = T4T_CMD_MIN_EXT_HDR_SIZE;
+
+ UINT8_TO_BE_STREAM(p, T4T_CMD_INS_READ_BINARY_ODO);
+ /* P1 P2 field */
+ UINT16_TO_BE_STREAM(p, 0x0000);
+ /* Lc field */
+ if (p_t4t->intl_flags & RW_T4T_EXT_FIELD_CODING) {
+ /* Coded over three bytes */
+ UINT16_TO_BE_STREAM(p, 0x0000);
+ UINT8_TO_BE_STREAM(p, 0x05);
+ p_c_apdu->len += 3;
+ } else {
+ /* Coded over 1 byte */
+ UINT8_TO_BE_STREAM(p, 0x05);
+ p_c_apdu->len += 1;
+ }
+ p_t4t->intl_flags |= RW_T4T_DDO_LC_FIELD_CODING;
+
+ /* Data field containing address offset */
+ UINT16_TO_BE_STREAM(p, 0x5403);
+ tmp_offset = offset;
+ tmp_offset >>= 16;
+ UINT8_TO_BE_STREAM(p, ((uint8_t)tmp_offset));
+ tmp_offset = offset;
+ tmp_offset >>= 8;
+ UINT8_TO_BE_STREAM(p, ((uint8_t)tmp_offset));
+ tmp_offset = offset;
+ UINT8_TO_BE_STREAM(p, ((uint8_t)tmp_offset));
+
+ /* Le field */
+ if (length < p_t4t->max_read_size) {
+ /* For the last R-APDU, must consider the DDO '53h' tag and data length
+ * size in the response. As difficult to know which coding will be used
+ * for BER-TLV, safer to request the remaining maximum number of bytes
+ * the tag can send */
+ length = 0x0000;
+ }
+ if (p_t4t->intl_flags & RW_T4T_EXT_FIELD_CODING) {
+ /* If Lc is coded over 3 bytes, Le is coded over 2 bytes */
+ p_c_apdu->len += 2;
+ UINT16_TO_BE_STREAM(p, length);
+ } else {
+ /* Coded over 1 byte */
+ p_c_apdu->len += 1;
+ UINT8_TO_BE_STREAM(p, length);
+ }
+ } else {
+ LOG(ERROR) << StringPrintf("%s - Cannot read above 0x7FFF for MV2.0",
+ __func__);
+ return false;
+ }
+ } else {
+ /* MV 2.0 tag or MV 3.0 tag read below 32kB */
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - Read below 0x8000 address offset detected", __func__);
+
+ UINT8_TO_BE_STREAM(p, T4T_CMD_INS_READ_BINARY);
+ /* Lc and Data fields absent */
+ UINT16_TO_BE_STREAM(p, offset);
+ if (p_t4t->intl_flags & RW_T4T_EXT_FIELD_CODING) {
+ /* Coded over three bytes with first one null */
+ p_c_apdu->len = T4T_CMD_MIN_HDR_SIZE + 3; /* adding Le */
+ UINT8_TO_BE_STREAM(p, 0x00);
+ UINT16_TO_BE_STREAM(p, length); /* Le */
+ } else {
+ /* If MLe=256 bytes, using UINT8_TO_BE_STREAM casts the length
+ * to Le=0x00 which is accepted by the specifications but not
+ * by all tags in the field. Force Le to 255 bytes to read the
+ * remaining bytes in two times
+ */
+ if (length == (T4T_MAX_LENGTH_LE + 1)) {
+ length = T4T_MAX_LENGTH_LE;
+ }
+ p_c_apdu->len = T4T_CMD_MIN_HDR_SIZE + 1; /* adding Le */
+ UINT8_TO_BE_STREAM(p, length); /* Le */
+ }
+ }
if (!rw_t4t_send_to_lower(p_c_apdu)) {
return false;
@@ -711,16 +949,18 @@
** Returns TRUE if success
**
*******************************************************************************/
-static bool rw_t4t_update_nlen(uint16_t ndef_len) {
+static bool rw_t4t_update_nlen(uint32_t ndef_len) {
+ tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
NFC_HDR* p_c_apdu;
uint8_t* p;
- DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("NLEN:%d", ndef_len);
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - NLEN:%d", __func__, ndef_len);
p_c_apdu = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
if (!p_c_apdu) {
- LOG(ERROR) << StringPrintf("Cannot allocate buffer");
+ LOG(ERROR) << StringPrintf("%s - Cannot allocate buffer", __func__);
return false;
}
@@ -730,10 +970,14 @@
UINT8_TO_BE_STREAM(p, T4T_CMD_CLASS);
UINT8_TO_BE_STREAM(p, T4T_CMD_INS_UPDATE_BINARY);
UINT16_TO_BE_STREAM(p, 0x0000); /* offset for NLEN */
- UINT8_TO_BE_STREAM(p, T4T_FILE_LENGTH_SIZE);
- UINT16_TO_BE_STREAM(p, ndef_len);
+ UINT8_TO_BE_STREAM(p, p_t4t->cc_file.ndef_fc.nlen_size);
+ if (p_t4t->cc_file.ndef_fc.nlen_size == T4T_FILE_LENGTH_SIZE) {
+ UINT16_TO_BE_STREAM(p, ndef_len);
+ } else {
+ UINT32_TO_BE_STREAM(p, ndef_len);
+ }
- p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + T4T_FILE_LENGTH_SIZE;
+ p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + p_t4t->cc_file.ndef_fc.nlen_size;
if (!rw_t4t_send_to_lower(p_c_apdu)) {
return false;
@@ -755,48 +999,83 @@
tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
NFC_HDR* p_c_apdu;
uint8_t* p;
- uint16_t length;
+ uint32_t length;
- DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
- "rw_offset:%d, rw_length:%d", p_t4t->rw_offset, p_t4t->rw_length);
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - rw_offset:%d, rw_length:%d", __func__,
+ p_t4t->rw_offset, p_t4t->rw_length);
p_c_apdu = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
if (!p_c_apdu) {
- LOG(ERROR) << StringPrintf("Cannot allocate buffer");
+ LOG(ERROR) << StringPrintf("%s - Cannot allocate buffer", __func__);
return false;
}
/* try to send all of remaining data */
length = p_t4t->rw_length;
+ if (length == 0) {
+ LOG(ERROR) << StringPrintf("%s - Length to write can not be null",
+ __func__);
+ return false;
+ }
+
/* adjust updating length if payload is bigger than max size per single
* command */
if (length > p_t4t->max_update_size) {
- length = (uint8_t)(p_t4t->max_update_size);
+ length = (uint32_t)(p_t4t->max_update_size);
}
p_c_apdu->offset = NCI_MSG_OFFSET_SIZE + NCI_DATA_HDR_SIZE;
p = (uint8_t*)(p_c_apdu + 1) + p_c_apdu->offset;
- UINT8_TO_BE_STREAM(p, T4T_CMD_CLASS);
- UINT8_TO_BE_STREAM(p, T4T_CMD_INS_UPDATE_BINARY);
- UINT16_TO_BE_STREAM(p, p_t4t->rw_offset);
- UINT8_TO_BE_STREAM(p, length);
+ if ((p_t4t->rw_offset + p_t4t->rw_length) > 0x7FFF) {
+ /* UpdateBinary with ODO and DDO */
+ if (p_t4t->cc_file.version >= T4T_VERSION_3_0) {
+ /* MV 3.0 tag */
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - MV 3.0 detected, update NDEF Message size > 0x7FFF", __func__);
- memcpy(p, p_t4t->p_update_data, length);
+ return rw_t4t_set_ber_tlv(p_c_apdu, p, length);
- p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + length;
+ } else {
+ LOG(ERROR) << StringPrintf("%s - Cannot write above 0x7FFF for MV2.0",
+ __func__);
+ return false;
+ }
+ } else {
+ /* MV 2.0 or MV 3.0 tag */
+ /* ReadBinary with Standard Data structure used */
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - NDEF Message to write < 0x8000, MV2.0 or MV3.0 tag", __func__);
- if (!rw_t4t_send_to_lower(p_c_apdu)) {
- return false;
+ UINT8_TO_BE_STREAM(p, T4T_CMD_CLASS);
+ UINT8_TO_BE_STREAM(p, T4T_CMD_INS_UPDATE_BINARY);
+ UINT16_TO_BE_STREAM(p, p_t4t->rw_offset);
+
+ /* Lc field encoded using Short Field Coding */
+ if (length > T4T_MAX_LENGTH_LC) {
+ /* Write a max of 255 bytes,
+ * as Lc=00 is reserved for Extended Field coding */
+ length = T4T_MAX_LENGTH_LC;
+ }
+ UINT8_TO_BE_STREAM(p, length);
+
+ memcpy(p, p_t4t->p_update_data, length);
+
+ p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + length;
+
+ if (!rw_t4t_send_to_lower(p_c_apdu)) {
+ return false;
+ }
+
+ /* adjust offset, length and pointer for remaining data */
+ p_t4t->rw_offset += length;
+ p_t4t->rw_length -= length;
+ p_t4t->p_update_data += length;
}
- /* adjust offset, length and pointer for remaining data */
- p_t4t->rw_offset += length;
- p_t4t->rw_length -= length;
- p_t4t->p_update_data += length;
-
return true;
}
@@ -814,12 +1093,12 @@
uint8_t* p;
DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf("Remove Write access from CC");
+ << StringPrintf("%s - Remove Write access from CC", __func__);
p_c_apdu = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
if (!p_c_apdu) {
- LOG(ERROR) << StringPrintf("Cannot allocate buffer");
+ LOG(ERROR) << StringPrintf("%s - Cannot allocate buffer", __func__);
return false;
}
@@ -859,6 +1138,7 @@
** CLA INS P1 P2 Lc Data(AID) Le
** V1.0: 00 A4 04 00 07 D2760000850100 -
** V2.0: 00 A4 04 00 07 D2760000850101 00
+** V3.0: 00 A4 04 00 07 D2760000850101 00
**
** Returns TRUE if success
**
@@ -867,12 +1147,13 @@
NFC_HDR* p_c_apdu;
uint8_t* p;
- DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("version:0x%X", version);
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - version:0x%X", __func__, version);
p_c_apdu = (NFC_HDR*)GKI_getpoolbuf(NFC_RW_POOL_ID);
if (!p_c_apdu) {
- LOG(ERROR) << StringPrintf("Cannot allocate buffer");
+ LOG(ERROR) << StringPrintf("%s - Cannot allocate buffer", __func__);
return false;
}
@@ -891,7 +1172,8 @@
memcpy(p, t4t_v10_ndef_tag_aid, T4T_V10_NDEF_TAG_AID_LEN);
p_c_apdu->len = T4T_CMD_MAX_HDR_SIZE + T4T_V10_NDEF_TAG_AID_LEN;
- } else if (version == T4T_VERSION_2_0) /* this is for V2.0 */
+ } else if ((version == T4T_VERSION_2_0) || /* this is for V2.0 */
+ (version == T4T_VERSION_3_0)) /* this is for V3.0 */
{
UINT8_TO_BE_STREAM(p, T4T_V20_NDEF_TAG_AID_LEN);
@@ -927,61 +1209,71 @@
DLOG_IF(INFO, nfc_debug_enabled) << __func__;
if (p_t4t->cc_file.cclen < T4T_CC_FILE_MIN_LEN) {
- LOG(ERROR) << StringPrintf("CCLEN (%d) is too short", p_t4t->cc_file.cclen);
+ LOG(ERROR) << StringPrintf("%s - CCLEN (%d) is too short", __func__,
+ p_t4t->cc_file.cclen);
return false;
}
- if (T4T_GET_MAJOR_VERSION(p_t4t->cc_file.version) !=
+ if (T4T_GET_MAJOR_VERSION(p_t4t->cc_file.version) >
T4T_GET_MAJOR_VERSION(p_t4t->version)) {
LOG(ERROR) << StringPrintf(
- "Peer version (0x%02X) is matched to ours "
+ "%s - Peer version (0x%02X) mismatched to ours "
"(0x%02X)",
- p_t4t->cc_file.version, p_t4t->version);
+ __func__, p_t4t->cc_file.version, p_t4t->version);
+
return false;
}
if (p_t4t->cc_file.max_le < 0x000F) {
- LOG(ERROR) << StringPrintf("MaxLe (%d) is too small",
+ LOG(ERROR) << StringPrintf("%s - MaxLe (%d) is too small", __func__,
p_t4t->cc_file.max_le);
return false;
}
- if (p_t4t->cc_file.max_lc < 0x0001) {
- LOG(ERROR) << StringPrintf("MaxLc (%d) is too small",
+ if (p_t4t->cc_file.max_lc < 0x0001 ||
+ ((p_t4t->cc_file.max_lc < 0x000D) && appl_dta_mode_flag)) {
+ LOG(ERROR) << StringPrintf("%s - MaxLc (%d) is too small", __func__,
p_t4t->cc_file.max_lc);
return false;
}
if ((p_t4t->cc_file.ndef_fc.file_id == T4T_CC_FILE_ID) ||
(p_t4t->cc_file.ndef_fc.file_id == 0xE102) ||
- (p_t4t->cc_file.ndef_fc.file_id == 0xE103) ||
((p_t4t->cc_file.ndef_fc.file_id == 0x0000) &&
- (p_t4t->cc_file.version == 0x20)) ||
+ ((p_t4t->cc_file.version == 0x20) ||
+ (p_t4t->cc_file.version == 0x30))) ||
(p_t4t->cc_file.ndef_fc.file_id == 0x3F00) ||
(p_t4t->cc_file.ndef_fc.file_id == 0x3FFF) ||
(p_t4t->cc_file.ndef_fc.file_id == 0xFFFF)) {
- LOG(ERROR) << StringPrintf("File ID (0x%04X) is invalid",
+ LOG(ERROR) << StringPrintf("%s - File ID (0x%04X) is invalid", __func__,
p_t4t->cc_file.ndef_fc.file_id);
return false;
}
- if ((p_t4t->cc_file.ndef_fc.max_file_size < 0x0005) ||
- (p_t4t->cc_file.ndef_fc.max_file_size == 0xFFFF)) {
- LOG(ERROR) << StringPrintf("max_file_size (%d) is reserved",
+ if (((p_t4t->cc_file.version == 0x20) &&
+ ((p_t4t->cc_file.ndef_fc.max_file_size < 0x0005) ||
+ (p_t4t->cc_file.ndef_fc.max_file_size > 0x7FFF))) ||
+ ((p_t4t->cc_file.version == 0x30) &&
+ ((p_t4t->cc_file.ndef_fc.max_file_size < 0x00000007) ||
+ (p_t4t->cc_file.ndef_fc.max_file_size == 0xFFFFFFFF)))) {
+ LOG(ERROR) << StringPrintf("%s - max_file_size (%d) is reserved", __func__,
p_t4t->cc_file.ndef_fc.max_file_size);
return false;
}
- if (p_t4t->cc_file.ndef_fc.read_access != T4T_FC_READ_ACCESS) {
- LOG(ERROR) << StringPrintf("Read Access (0x%02X) is invalid",
+ if (((p_t4t->cc_file.ndef_fc.read_access > T4T_FC_READ_ACCESS) &&
+ (p_t4t->cc_file.ndef_fc.read_access < T4T_FC_READ_ACCESS_PROP_START)) ||
+ (p_t4t->cc_file.ndef_fc.read_access == T4T_FC_NO_READ_ACCESS)) {
+ LOG(ERROR) << StringPrintf("%s - Read Access (0x%02X) is invalid", __func__,
p_t4t->cc_file.ndef_fc.read_access);
return false;
}
- if ((p_t4t->cc_file.ndef_fc.write_access != T4T_FC_WRITE_ACCESS) &&
- (p_t4t->cc_file.ndef_fc.write_access < T4T_FC_WRITE_ACCESS_PROP_START)) {
- LOG(ERROR) << StringPrintf("Write Access (0x%02X) is invalid",
- p_t4t->cc_file.ndef_fc.write_access);
+ if (((p_t4t->cc_file.ndef_fc.write_access > T4T_FC_WRITE_ACCESS) &&
+ (p_t4t->cc_file.ndef_fc.write_access <
+ T4T_FC_WRITE_ACCESS_PROP_START))) {
+ LOG(ERROR) << StringPrintf("%s - Write Access (0x%02X) is invalid",
+ __func__, p_t4t->cc_file.ndef_fc.write_access);
return false;
}
@@ -1003,9 +1295,9 @@
tRW_EVENT event;
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
- "status:0x%02X, sw1:0x%02X, sw2:0x%02X, "
+ "%s - status:0x%02X, sw1:0x%02X, sw2:0x%02X, "
"state:0x%X",
- status, sw1, sw2, p_t4t->state);
+ __func__, status, sw1, sw2, p_t4t->state);
nfc_stop_quick_timer(&p_t4t->timer);
@@ -1252,12 +1544,15 @@
static void rw_t4t_sm_detect_ndef(NFC_HDR* p_r_apdu) {
tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
uint8_t *p, type, length;
- uint16_t status_words, nlen;
+ uint32_t nlen;
+ uint32_t cc_file_offset = 0x00;
+ uint16_t status_words;
+ uint8_t cc_file_rsp_len = T4T_CC_FILE_MIN_LEN;
tRW_DATA rw_data;
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
- "sub_state:%s (%d)", rw_t4t_get_sub_state_name(p_t4t->sub_state).c_str(),
- p_t4t->sub_state);
+ "%s - sub_state:%s (%d)", __func__,
+ rw_t4t_get_sub_state_name(p_t4t->sub_state).c_str(), p_t4t->sub_state);
/* get status words */
p = (uint8_t*)(p_r_apdu + 1) + p_r_apdu->offset;
@@ -1265,13 +1560,14 @@
BE_STREAM_TO_UINT16(status_words, p);
if (status_words != T4T_RSP_CMD_CMPLTED) {
- /* try V1.0 after failing of V2.0 */
+ /* try V1.0 after failing of V2.0 or V3.0 */
if ((p_t4t->sub_state == RW_T4T_SUBSTATE_WAIT_SELECT_APP) &&
- (p_t4t->version == T4T_VERSION_2_0)) {
+ ((p_t4t->version == T4T_VERSION_2_0) ||
+ (p_t4t->version == T4T_VERSION_3_0))) {
p_t4t->version = T4T_VERSION_1_0;
- DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf("retry with version=0x%02X", p_t4t->version);
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - retry with version=0x%02X", __func__, p_t4t->version);
if (!rw_t4t_select_application(T4T_VERSION_1_0)) {
rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
@@ -1298,7 +1594,8 @@
case RW_T4T_SUBSTATE_WAIT_SELECT_CC:
/* CC file has been selected then read mandatory part of CC file */
- if (!rw_t4t_read_file(0x00, T4T_CC_FILE_MIN_LEN, false)) {
+ cc_file_offset = 0x00;
+ if (!rw_t4t_read_file(cc_file_offset, cc_file_rsp_len, false)) {
rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
} else {
p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_CC_FILE;
@@ -1308,7 +1605,7 @@
case RW_T4T_SUBSTATE_WAIT_CC_FILE:
/* CC file has been read then validate and select mandatory NDEF file */
- if (p_r_apdu->len >= T4T_CC_FILE_MIN_LEN + T4T_RSP_STATUS_WORDS_SIZE) {
+ if (p_r_apdu->len >= cc_file_rsp_len + T4T_RSP_STATUS_WORDS_SIZE) {
p = (uint8_t*)(p_r_apdu + 1) + p_r_apdu->offset;
BE_STREAM_TO_UINT16(p_t4t->cc_file.cclen, p);
@@ -1327,34 +1624,107 @@
BE_STREAM_TO_UINT8(p_t4t->cc_file.ndef_fc.write_access, p);
DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf("Capability Container (CC) file");
- DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf(" CCLEN: 0x%04X", p_t4t->cc_file.cclen);
- DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf(" Version:0x%02X", p_t4t->cc_file.version);
- DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf(" MaxLe: 0x%04X", p_t4t->cc_file.max_le);
- DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf(" MaxLc: 0x%04X", p_t4t->cc_file.max_lc);
- DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf(" NDEF File Control TLV");
+ << StringPrintf("%s - Capability Container (CC) file", __func__);
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
- " FileID: 0x%04X", p_t4t->cc_file.ndef_fc.file_id);
+ "%s - CCLEN: 0x%04X", __func__, p_t4t->cc_file.cclen);
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
- " MaxFileSize: 0x%04X", p_t4t->cc_file.ndef_fc.max_file_size);
+ "%s - Version:0x%02X", __func__, p_t4t->cc_file.version);
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
- " ReadAccess: 0x%02X", p_t4t->cc_file.ndef_fc.read_access);
+ "%s - MaxLe: 0x%04X", __func__, p_t4t->cc_file.max_le);
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
- " WriteAccess: 0x%02X", p_t4t->cc_file.ndef_fc.write_access);
+ "%s - MaxLc: 0x%04X", __func__, p_t4t->cc_file.max_lc);
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - NDEF File Control TLV", __func__);
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - FileID: 0x%04X", __func__,
+ p_t4t->cc_file.ndef_fc.file_id);
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - MaxFileSize: 0x%04X", __func__,
+ p_t4t->cc_file.ndef_fc.max_file_size);
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - ReadAccess: 0x%02X", __func__,
+ p_t4t->cc_file.ndef_fc.read_access);
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - WriteAccess: 0x%02X", __func__,
+ p_t4t->cc_file.ndef_fc.write_access);
if (rw_t4t_validate_cc_file()) {
if (!rw_t4t_select_file(p_t4t->cc_file.ndef_fc.file_id)) {
rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
} else {
+ p_t4t->cc_file.ndef_fc.nlen_size = T4T_FILE_LENGTH_SIZE;
p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE;
}
break;
}
+ } else if ((type == T4T_ENDEF_FILE_CONTROL_TYPE) &&
+ (length == T4T_ENDEF_FILE_CONTROL_LENGTH)) {
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - Capability Container (CC) file", __func__);
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - CCLEN: 0x%04X", __func__, p_t4t->cc_file.cclen);
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - Version:0x%02X", __func__, p_t4t->cc_file.version);
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - MaxLe: 0x%04X", __func__, p_t4t->cc_file.max_le);
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - MaxLc: 0x%04X", __func__, p_t4t->cc_file.max_lc);
+
+ cc_file_offset = T4T_ENDEF_FC_V_FIELD_OFFSET;
+ cc_file_rsp_len = T4T_ENDEF_FILE_CONTROL_TLV_SIZE - 2;
+
+ /* CC file has been selected then now read from control TLV area part
+ * of CC file */
+ /* assume ENDEF Ctrl TLV is the first one */
+ /* read again the TLV as 2 bytes missing */
+ if (!rw_t4t_read_file(cc_file_offset, cc_file_rsp_len, false)) {
+ rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
+ } else {
+ p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_ENDEF_FILE_CTRL_TLV;
+ }
+ break;
+ }
+ }
+
+ /* invalid response or CC file */
+ p_t4t->ndef_status &= ~(RW_T4T_NDEF_STATUS_NDEF_DETECTED);
+ rw_t4t_handle_error(NFC_STATUS_BAD_RESP, 0, 0);
+ break;
+
+ case RW_T4T_SUBSTATE_WAIT_ENDEF_FILE_CTRL_TLV:
+
+ if (p_r_apdu->len >=
+ T4T_ENDEF_FILE_CONTROL_LENGTH + T4T_RSP_STATUS_WORDS_SIZE) {
+ p = (uint8_t*)(p_r_apdu + 1) + p_r_apdu->offset;
+
+ BE_STREAM_TO_UINT16(p_t4t->cc_file.ndef_fc.file_id, p);
+ BE_STREAM_TO_UINT32(p_t4t->cc_file.ndef_fc.max_file_size, p);
+ BE_STREAM_TO_UINT8(p_t4t->cc_file.ndef_fc.read_access, p);
+ BE_STREAM_TO_UINT8(p_t4t->cc_file.ndef_fc.write_access, p);
+
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - ENDEF File Control TLV", __func__);
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - FileID: 0x%04X", __func__,
+ p_t4t->cc_file.ndef_fc.file_id);
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - MaxFileSize: 0x%08X", __func__,
+ p_t4t->cc_file.ndef_fc.max_file_size);
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - ReadAccess: 0x%02X", __func__,
+ p_t4t->cc_file.ndef_fc.read_access);
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - WriteAccess: 0x%02X", __func__,
+ p_t4t->cc_file.ndef_fc.write_access);
+
+ if (rw_t4t_validate_cc_file()) {
+ if (!rw_t4t_select_file(p_t4t->cc_file.ndef_fc.file_id)) {
+ rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
+ } else {
+ p_t4t->cc_file.ndef_fc.nlen_size = T4T_EFILE_LENGTH_SIZE;
+ p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE;
+ }
+ break;
}
}
@@ -1366,7 +1736,7 @@
case RW_T4T_SUBSTATE_WAIT_SELECT_NDEF_FILE:
/* NDEF file has been selected then read the first 2 bytes (NLEN) */
- if (!rw_t4t_read_file(0, T4T_FILE_LENGTH_SIZE, false)) {
+ if (!rw_t4t_read_file(0, p_t4t->cc_file.ndef_fc.nlen_size, false)) {
rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
} else {
p_t4t->sub_state = RW_T4T_SUBSTATE_WAIT_READ_NLEN;
@@ -1376,16 +1746,21 @@
case RW_T4T_SUBSTATE_WAIT_READ_NLEN:
/* NLEN has been read then report upper layer */
- if (p_r_apdu->len == T4T_FILE_LENGTH_SIZE + T4T_RSP_STATUS_WORDS_SIZE) {
+ if (p_r_apdu->len ==
+ p_t4t->cc_file.ndef_fc.nlen_size + T4T_RSP_STATUS_WORDS_SIZE) {
/* get length of NDEF */
p = (uint8_t*)(p_r_apdu + 1) + p_r_apdu->offset;
- BE_STREAM_TO_UINT16(nlen, p);
+ if (p_t4t->cc_file.ndef_fc.nlen_size == T4T_FILE_LENGTH_SIZE) {
+ BE_STREAM_TO_UINT16(nlen, p);
+ } else {
+ BE_STREAM_TO_UINT32(nlen, p);
+ }
- if (nlen <=
- p_t4t->cc_file.ndef_fc.max_file_size - T4T_FILE_LENGTH_SIZE) {
+ if (nlen <= p_t4t->cc_file.ndef_fc.max_file_size -
+ p_t4t->cc_file.ndef_fc.nlen_size) {
p_t4t->ndef_status = RW_T4T_NDEF_STATUS_NDEF_DETECTED;
- if (p_t4t->cc_file.ndef_fc.write_access != T4T_FC_WRITE_ACCESS) {
+ if (p_t4t->cc_file.ndef_fc.write_access == T4T_FC_NO_WRITE_ACCESS) {
p_t4t->ndef_status |= RW_T4T_NDEF_STATUS_NDEF_READ_ONLY;
}
@@ -1396,9 +1771,14 @@
p_t4t->max_read_size = p_t4t->cc_file.max_le;
}
- /* Le: valid range is 0x01 to 0xFF */
- if (p_t4t->max_read_size >= T4T_MAX_LENGTH_LE) {
- p_t4t->max_read_size = T4T_MAX_LENGTH_LE;
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - max_read_size: 0x%04X", __func__,
+ p_t4t->max_read_size);
+
+ /* Le: valid range is 0x0001 to 0xFFFF */
+ if (p_t4t->max_read_size > T4T_MAX_LENGTH_LE + 1) {
+ /* Extended Field Coding supported by the tag */
+ p_t4t->intl_flags |= RW_T4T_EXT_FIELD_CODING;
}
/* Get max bytes to update per command */
@@ -1408,9 +1788,10 @@
p_t4t->max_update_size = p_t4t->cc_file.max_lc;
}
- /* Lc: valid range is 0x01 to 0xFF */
- if (p_t4t->max_update_size >= T4T_MAX_LENGTH_LC) {
- p_t4t->max_update_size = T4T_MAX_LENGTH_LC;
+ /* Lc: valid range is 0x0001 to 0xFFFF */
+ if (p_t4t->max_update_size > T4T_MAX_LENGTH_LC) {
+ /* Extended Field Coding supported by the tag */
+ p_t4t->intl_flags |= RW_T4T_EXT_FIELD_CODING;
}
p_t4t->ndef_length = nlen;
@@ -1421,7 +1802,7 @@
rw_data.ndef.protocol = NFC_PROTOCOL_ISO_DEP;
rw_data.ndef.max_size =
(uint32_t)(p_t4t->cc_file.ndef_fc.max_file_size -
- (uint16_t)T4T_FILE_LENGTH_SIZE);
+ (uint16_t)p_t4t->cc_file.ndef_fc.nlen_size);
rw_data.ndef.cur_size = nlen;
rw_data.ndef.flags = RW_NDEF_FL_SUPPORTED | RW_NDEF_FL_FORMATED;
if (p_t4t->cc_file.ndef_fc.write_access != T4T_FC_WRITE_ACCESS) {
@@ -1431,23 +1812,23 @@
(*(rw_cb.p_cback))(RW_T4T_NDEF_DETECT_EVT, &rw_data);
DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf("Sent RW_T4T_NDEF_DETECT_EVT");
+ << StringPrintf("%s - Sent RW_T4T_NDEF_DETECT_EVT", __func__);
}
} else {
/* NLEN should be less than max file size */
LOG(ERROR) << StringPrintf(
- "NLEN (%d) + 2 must be <= max file "
+ "%s - NLEN (%d) + 2 must be <= max file "
"size (%d)",
- nlen, p_t4t->cc_file.ndef_fc.max_file_size);
+ __func__, nlen, p_t4t->cc_file.ndef_fc.max_file_size);
p_t4t->ndef_status &= ~(RW_T4T_NDEF_STATUS_NDEF_DETECTED);
rw_t4t_handle_error(NFC_STATUS_BAD_RESP, 0, 0);
}
} else {
- /* response payload size should be T4T_FILE_LENGTH_SIZE */
+ /* response payload size should be T4T_(E)FILE_LENGTH_SIZE */
LOG(ERROR) << StringPrintf(
- "Length (%d) of R-APDU must be %d", p_r_apdu->len,
- T4T_FILE_LENGTH_SIZE + T4T_RSP_STATUS_WORDS_SIZE);
+ "%s - Length (%d) of R-APDU must be %d", __func__, p_r_apdu->len,
+ p_t4t->cc_file.ndef_fc.nlen_size + T4T_RSP_STATUS_WORDS_SIZE);
p_t4t->ndef_status &= ~(RW_T4T_NDEF_STATUS_NDEF_DETECTED);
rw_t4t_handle_error(NFC_STATUS_BAD_RESP, 0, 0);
@@ -1455,7 +1836,8 @@
break;
default:
- LOG(ERROR) << StringPrintf("unknown sub_state=%d", p_t4t->sub_state);
+ LOG(ERROR) << StringPrintf("%s - unknown sub_state=%d", __func__,
+ p_t4t->sub_state);
rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
break;
}
@@ -1474,11 +1856,12 @@
tRW_T4T_CB* p_t4t = &rw_cb.tcb.t4t;
uint8_t* p;
uint16_t status_words;
+ uint16_t r_apdu_len;
tRW_DATA rw_data;
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
- "sub_state:%s (%d)", rw_t4t_get_sub_state_name(p_t4t->sub_state).c_str(),
- p_t4t->sub_state);
+ "%s - sub_state:%s (%d)", __func__,
+ rw_t4t_get_sub_state_name(p_t4t->sub_state).c_str(), p_t4t->sub_state);
/* get status words */
p = (uint8_t*)(p_r_apdu + 1) + p_r_apdu->offset;
@@ -1497,46 +1880,141 @@
/* Read partial or complete data */
p_r_apdu->len -= T4T_RSP_STATUS_WORDS_SIZE;
- if ((p_r_apdu->len > 0) && (p_r_apdu->len <= p_t4t->rw_length)) {
- p_t4t->rw_length -= p_r_apdu->len;
- p_t4t->rw_offset += p_r_apdu->len;
-
- if (rw_cb.p_cback) {
- rw_data.data.status = NFC_STATUS_OK;
- rw_data.data.p_data = p_r_apdu;
-
- /* if need to read more data */
- if (p_t4t->rw_length > 0) {
- (*(rw_cb.p_cback))(RW_T4T_NDEF_READ_EVT, &rw_data);
-
- if (!rw_t4t_read_file(p_t4t->rw_offset, p_t4t->rw_length, true)) {
- rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
+ p = (uint8_t*)(p_r_apdu + 1) + p_r_apdu->offset;
+ if (p_t4t->intl_flags & RW_T4T_DDO_LC_FIELD_CODING) {
+ if (*p == 0x53) {
+ /* ReadBinary command with ODO */
+ if (*(p + 1) <= 0x7F) {
+ p_r_apdu->len -= 2;
+ p_r_apdu->offset += 2;
+ /* Content read length coded over 1 byte in 1st byte
+ * of BER-TLV length field */
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - Content read length expected: 0x%02X, returned: 0x%02X",
+ __func__, *(p + 1), p_r_apdu->len);
+ if (*(p + 1) == p_r_apdu->len) {
+ if ((p_r_apdu->len > 0) && (p_r_apdu->len <= p_t4t->rw_length)) {
+ p_t4t->rw_length -= p_r_apdu->len;
+ p_t4t->rw_offset += p_r_apdu->len;
+ }
+ } else {
+ LOG(ERROR) << StringPrintf(
+ "%s - invalid payload length (%d), rw_length (%d)", __func__,
+ p_r_apdu->len, p_t4t->rw_length);
+ rw_t4t_handle_error(NFC_STATUS_BAD_RESP, 0, 0);
+ break;
+ }
+ } else if (*(p + 1) == 0x81) {
+ if (*(p + 2) <= 0xFD) {
+ p_r_apdu->len -= 3;
+ p_r_apdu->offset += 3;
+ /* Content read length coded over 1 byte in 2nd byte
+ * of BER-TLV length field */
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - Content read length expected: 0x%02X, returned: 0x%02X",
+ __func__, *(p + 2), p_r_apdu->len);
+ if (*(p + 2) == p_r_apdu->len) {
+ if ((p_r_apdu->len > 0) &&
+ (p_r_apdu->len <= p_t4t->rw_length)) {
+ p_t4t->rw_length -= p_r_apdu->len;
+ p_t4t->rw_offset += p_r_apdu->len;
+ }
+ } else {
+ LOG(ERROR) << StringPrintf(
+ "%s - invalid payload length (%d), rw_length "
+ "(%d)",
+ __func__, p_r_apdu->len, p_t4t->rw_length);
+ rw_t4t_handle_error(NFC_STATUS_BAD_RESP, 0, 0);
+ break;
+ }
+ } else {
+ LOG(ERROR) << StringPrintf(
+ "%s - invalid DDO length content length received (1)",
+ __func__);
+ rw_t4t_handle_error(NFC_STATUS_BAD_RESP, 0, 0);
+ break;
+ }
+ } else if (*(p + 1) == 0x82) {
+ /* Content read length coded over 2 bytes in 2nd and 3rd bytes
+ * of BER-TLV length field*/
+ r_apdu_len = (uint16_t)(*(p + 2) << 8);
+ r_apdu_len |= (uint8_t) * (p + 3);
+ if (r_apdu_len <= (p_t4t->max_read_size - 4)) {
+ p_r_apdu->len -= 4;
+ p_r_apdu->offset += 4;
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - Content read length expected: 0x%02X%02X, returned: "
+ "0x%02X%02X ",
+ __func__, *(p + 3), *(p + 2), (uint8_t)(p_r_apdu->len >> 8),
+ (uint8_t)p_r_apdu->len);
+ if (r_apdu_len == p_r_apdu->len) {
+ if ((p_r_apdu->len > 0) &&
+ (p_r_apdu->len <= p_t4t->rw_length)) {
+ p_t4t->rw_length -= p_r_apdu->len;
+ p_t4t->rw_offset += p_r_apdu->len;
+ }
+ } else {
+ LOG(ERROR) << StringPrintf(
+ "%s - invalid payload length (%d), rw_length "
+ "(%d)",
+ __func__, p_r_apdu->len, p_t4t->rw_length);
+ rw_t4t_handle_error(NFC_STATUS_BAD_RESP, 0, 0);
+ break;
+ }
}
} else {
- p_t4t->state = RW_T4T_STATE_IDLE;
-
- (*(rw_cb.p_cback))(RW_T4T_NDEF_READ_CPLT_EVT, &rw_data);
-
- DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf("Sent RW_T4T_NDEF_READ_CPLT_EVT");
+ LOG(ERROR) << StringPrintf(
+ "%s - invalid DDO length content length received (2)",
+ __func__);
+ rw_t4t_handle_error(NFC_STATUS_BAD_RESP, 0, 0);
+ break;
}
-
- p_r_apdu = nullptr;
} else {
- p_t4t->rw_length = 0;
- p_t4t->state = RW_T4T_STATE_IDLE;
+ LOG(ERROR) << StringPrintf("%s - invalid DDO tag", __func__);
+ rw_t4t_handle_error(NFC_STATUS_BAD_RESP, 0, 0);
+ break;
}
+ } else if ((p_r_apdu->len > 0) && (p_r_apdu->len <= p_t4t->rw_length)) {
+ p_t4t->rw_length -= p_r_apdu->len;
+ p_t4t->rw_offset += p_r_apdu->len;
} else {
LOG(ERROR) << StringPrintf(
- "invalid payload length (%d), rw_length "
+ "%s - invalid payload length (%d), rw_length "
"(%d)",
- p_r_apdu->len, p_t4t->rw_length);
+ __func__, p_r_apdu->len, p_t4t->rw_length);
rw_t4t_handle_error(NFC_STATUS_BAD_RESP, 0, 0);
+ break;
+ }
+ if (rw_cb.p_cback) {
+ rw_data.data.status = NFC_STATUS_OK;
+ rw_data.data.p_data = p_r_apdu;
+
+ /* if need to read more data */
+ if (p_t4t->rw_length > 0) {
+ (*(rw_cb.p_cback))(RW_T4T_NDEF_READ_EVT, &rw_data);
+
+ if (!rw_t4t_read_file(p_t4t->rw_offset, p_t4t->rw_length, true)) {
+ rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
+ }
+ } else {
+ p_t4t->state = RW_T4T_STATE_IDLE;
+
+ (*(rw_cb.p_cback))(RW_T4T_NDEF_READ_CPLT_EVT, &rw_data);
+
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - Sent RW_T4T_NDEF_READ_CPLT_EVT", __func__);
+ }
+
+ p_r_apdu = nullptr;
+ } else {
+ p_t4t->rw_length = 0;
+ p_t4t->state = RW_T4T_STATE_IDLE;
}
break;
default:
- LOG(ERROR) << StringPrintf("unknown sub_state = %d", p_t4t->sub_state);
+ LOG(ERROR) << StringPrintf("%s - unknown sub_state = %d", __func__,
+ p_t4t->sub_state);
rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
break;
}
@@ -1560,8 +2038,8 @@
tRW_DATA rw_data;
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
- "sub_state:%s (%d)", rw_t4t_get_sub_state_name(p_t4t->sub_state).c_str(),
- p_t4t->sub_state);
+ "%s - sub_state:%s (%d)", __func__,
+ rw_t4t_get_sub_state_name(p_t4t->sub_state).c_str(), p_t4t->sub_state);
/* Get status words */
p = (uint8_t*)(p_r_apdu + 1) + p_r_apdu->offset;
@@ -1593,8 +2071,8 @@
rw_data.status = NFC_STATUS_OK;
(*(rw_cb.p_cback))(RW_T4T_NDEF_UPDATE_CPLT_EVT, &rw_data);
- DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf("Sent RW_T4T_NDEF_UPDATE_CPLT_EVT");
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - Sent RW_T4T_NDEF_UPDATE_CPLT_EVT", __func__);
}
}
break;
@@ -1620,7 +2098,8 @@
break;
default:
- LOG(ERROR) << StringPrintf("unknown sub_state = %d", p_t4t->sub_state);
+ LOG(ERROR) << StringPrintf("%s - unknown sub_state = %d", __func__,
+ p_t4t->sub_state);
rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
break;
}
@@ -1642,8 +2121,8 @@
tRW_DATA rw_data;
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
- "sub_state:%s (%d)", rw_t4t_get_sub_state_name(p_t4t->sub_state).c_str(),
- p_t4t->sub_state);
+ "%s - sub_state:%s (%d)", __func__,
+ rw_t4t_get_sub_state_name(p_t4t->sub_state).c_str(), p_t4t->sub_state);
/* Get status words */
p = (uint8_t*)(p_r_apdu + 1) + p_r_apdu->offset;
@@ -1687,13 +2166,14 @@
rw_data.status = NFC_STATUS_OK;
DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf("Sent RW_T4T_SET_TO_RO_EVT");
+ << StringPrintf("%s - Sent RW_T4T_SET_TO_RO_EVT", __func__);
(*(rw_cb.p_cback))(RW_T4T_SET_TO_RO_EVT, &rw_data);
}
break;
default:
- LOG(ERROR) << StringPrintf("unknown sub_state = %d", p_t4t->sub_state);
+ LOG(ERROR) << StringPrintf("%s - unknown sub_state = %d", __func__,
+ p_t4t->sub_state);
rw_t4t_handle_error(NFC_STATUS_FAILED, 0, 0);
break;
}
@@ -1757,7 +2237,8 @@
uint8_t begin_state = p_t4t->state;
- DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("event = 0x%X", event);
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - event = 0x%X", __func__, event);
nfc_stop_quick_timer(&p_t4t->timer);
switch (event) {
@@ -1794,8 +2275,8 @@
}
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
- "RW T4T state: <%s (%d)>", rw_t4t_get_state_name(p_t4t->state).c_str(),
- p_t4t->state);
+ "%s - RW T4T state: <%s (%d)>", __func__,
+ rw_t4t_get_state_name(p_t4t->state).c_str(), p_t4t->state);
if (p_t4t->state != RW_T4T_STATE_IDLE &&
p_t4t->state != RW_T4T_STATE_PRESENCE_CHECK &&
@@ -1812,8 +2293,8 @@
/* Unexpected R-APDU, it should be raw frame response */
/* forward to upper layer without parsing */
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
- "RW T4T Raw Frame: Len [0x%X] Status [%s]", p_r_apdu->len,
- NFC_GetStatusName(p_data->data.status).c_str());
+ "%s - RW T4T Raw Frame: Len [0x%X] Status [%s]", __func__,
+ p_r_apdu->len, NFC_GetStatusName(p_data->data.status).c_str());
if (rw_cb.p_cback) {
rw_data.raw_frame.status = p_data->data.status;
rw_data.raw_frame.p_data = p_r_apdu;
@@ -1851,14 +2332,15 @@
GKI_freebuf(p_r_apdu);
break;
default:
- LOG(ERROR) << StringPrintf("invalid state=%d", p_t4t->state);
+ LOG(ERROR) << StringPrintf("%s - invalid state=%d", __func__,
+ p_t4t->state);
GKI_freebuf(p_r_apdu);
break;
}
if (begin_state != p_t4t->state) {
DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf("RW T4T state changed:<%s> -> <%s>",
+ << StringPrintf("%s - RW T4T state changed:<%s> -> <%s>", __func__,
rw_t4t_get_state_name(begin_state).c_str(),
rw_t4t_get_state_name(p_t4t->state).c_str());
}
@@ -1939,8 +2421,8 @@
DLOG_IF(INFO, nfc_debug_enabled) << __func__;
if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE) {
- LOG(ERROR) << StringPrintf("Unable to start command at state (0x%X)",
- rw_cb.tcb.t4t.state);
+ LOG(ERROR) << StringPrintf("%s - Unable to start command at state (0x%X)",
+ __func__, rw_cb.tcb.t4t.state);
return NFC_STATUS_FAILED;
}
@@ -1984,16 +2466,16 @@
DLOG_IF(INFO, nfc_debug_enabled) << __func__;
if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE) {
- LOG(ERROR) << StringPrintf("Unable to start command at state (0x%X)",
- rw_cb.tcb.t4t.state);
+ LOG(ERROR) << StringPrintf("%s - Unable to start command at state (0x%X)",
+ __func__, rw_cb.tcb.t4t.state);
return NFC_STATUS_FAILED;
}
/* if NDEF has been detected */
if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED) {
/* start reading NDEF */
- if (!rw_t4t_read_file(T4T_FILE_LENGTH_SIZE, rw_cb.tcb.t4t.ndef_length,
- false)) {
+ if (!rw_t4t_read_file(rw_cb.tcb.t4t.cc_file.ndef_fc.nlen_size,
+ rw_cb.tcb.t4t.ndef_length, false)) {
return NFC_STATUS_FAILED;
}
@@ -2002,7 +2484,7 @@
return NFC_STATUS_OK;
} else {
- LOG(ERROR) << StringPrintf("No NDEF detected");
+ LOG(ERROR) << StringPrintf("%s - No NDEF detected", __func__);
return NFC_STATUS_FAILED;
}
}
@@ -2024,12 +2506,13 @@
** NFC_STATUS_FAILED if T4T is busy or other error
**
*******************************************************************************/
-tNFC_STATUS RW_T4tUpdateNDef(uint16_t length, uint8_t* p_data) {
- DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("length:%d", length);
+tNFC_STATUS RW_T4tUpdateNDef(uint32_t length, uint8_t* p_data) {
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - length:%d", __func__, length);
if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE) {
- LOG(ERROR) << StringPrintf("Unable to start command at state (0x%X)",
- rw_cb.tcb.t4t.state);
+ LOG(ERROR) << StringPrintf("%s - Unable to start command at state (0x%X)",
+ __func__, rw_cb.tcb.t4t.state);
return NFC_STATUS_FAILED;
}
@@ -2037,16 +2520,16 @@
if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_DETECTED) {
/* if read-only */
if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_READ_ONLY) {
- LOG(ERROR) << StringPrintf("NDEF is read-only");
+ LOG(ERROR) << StringPrintf("%s - NDEF is read-only", __func__);
return NFC_STATUS_FAILED;
}
if (rw_cb.tcb.t4t.cc_file.ndef_fc.max_file_size <
- length + T4T_FILE_LENGTH_SIZE) {
+ length + rw_cb.tcb.t4t.cc_file.ndef_fc.nlen_size) {
LOG(ERROR) << StringPrintf(
- "data (%d bytes) plus NLEN is more than max file "
+ "%s - data (%d bytes) plus NLEN is more than max file "
"size (%d)",
- length, rw_cb.tcb.t4t.cc_file.ndef_fc.max_file_size);
+ __func__, length, rw_cb.tcb.t4t.cc_file.ndef_fc.max_file_size);
return NFC_STATUS_FAILED;
}
@@ -2054,7 +2537,7 @@
rw_cb.tcb.t4t.ndef_length = length;
rw_cb.tcb.t4t.p_update_data = p_data;
- rw_cb.tcb.t4t.rw_offset = T4T_FILE_LENGTH_SIZE;
+ rw_cb.tcb.t4t.rw_offset = rw_cb.tcb.t4t.cc_file.ndef_fc.nlen_size;
rw_cb.tcb.t4t.rw_length = length;
/* set NLEN to 0x0000 for the first step */
@@ -2067,7 +2550,7 @@
return NFC_STATUS_OK;
} else {
- LOG(ERROR) << StringPrintf("No NDEF detected");
+ LOG(ERROR) << StringPrintf("%s - No NDEF detected", __func__);
return NFC_STATUS_FAILED;
}
}
@@ -2096,7 +2579,7 @@
bool status;
NFC_HDR* p_data;
- DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%d", option);
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s - %d", __func__, option);
/* If RW_SelectTagType was not called (no conn_callback) return failure */
if (!rw_cb.p_cback) {
@@ -2158,8 +2641,8 @@
DLOG_IF(INFO, nfc_debug_enabled) << __func__;
if (rw_cb.tcb.t4t.state != RW_T4T_STATE_IDLE) {
- LOG(ERROR) << StringPrintf("Unable to start command at state (0x%X)",
- rw_cb.tcb.t4t.state);
+ LOG(ERROR) << StringPrintf("%s - Unable to start command at state (0x%X)",
+ __func__, rw_cb.tcb.t4t.state);
return NFC_STATUS_FAILED;
}
@@ -2168,7 +2651,7 @@
/* if read-only */
if (rw_cb.tcb.t4t.ndef_status & RW_T4T_NDEF_STATUS_NDEF_READ_ONLY) {
DLOG_IF(INFO, nfc_debug_enabled)
- << StringPrintf("NDEF is already read-only");
+ << StringPrintf("%s - NDEF is already read-only", __func__);
evt_data.status = NFC_STATUS_OK;
(*rw_cb.p_cback)(RW_T4T_SET_TO_RO_EVT, &evt_data);
@@ -2185,7 +2668,7 @@
return NFC_STATUS_OK;
} else {
- LOG(ERROR) << StringPrintf("No NDEF detected");
+ LOG(ERROR) << StringPrintf("%s - No NDEF detected", __func__);
return NFC_STATUS_FAILED;
}
return (retval);
@@ -2268,6 +2751,8 @@
return "WAIT_WRITE_CC";
case RW_T4T_SUBSTATE_WAIT_WRITE_NDEF:
return "WAIT_WRITE_NDEF";
+ case RW_T4T_SUBSTATE_WAIT_ENDEF_FILE_CTRL_TLV:
+ return "WAIT_ENDEF_FILE_CTRL_TLV";
default:
return "???? UNKNOWN SUBSTATE";
}
diff --git a/src/nfc/tags/rw_t5t.cc b/src/nfc/tags/rw_t5t.cc
new file mode 100644
index 0000000..06df3c9
--- /dev/null
+++ b/src/nfc/tags/rw_t5t.cc
@@ -0,0 +1,865 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 STMicroelectronics
+ *
+ * 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 specific NFC Forum T5T operations
+ * in Reader/Writer mode.
+ *
+ ******************************************************************************/
+
+#include <log/log.h>
+#include <string.h>
+
+#include <android-base/stringprintf.h>
+#include <base/logging.h>
+
+#include "nfc_target.h"
+
+#include "bt_types.h"
+#include "nfc_api.h"
+#include "nfc_int.h"
+#include "rw_api.h"
+#include "rw_int.h"
+
+using android::base::StringPrintf;
+
+extern void rw_i93_handle_error(tNFC_STATUS);
+extern tNFC_STATUS rw_i93_get_next_blocks(uint16_t);
+extern tNFC_STATUS rw_i93_send_cmd_read_single_block(uint16_t, bool);
+extern tNFC_STATUS rw_i93_send_cmd_write_single_block(uint16_t, uint8_t*);
+extern tNFC_STATUS rw_i93_send_cmd_lock_block(uint16_t);
+
+extern bool nfc_debug_enabled;
+
+/*******************************************************************************
+**
+** Function rw_t5t_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_t5t_sm_detect_ndef(NFC_HDR* p_resp) {
+ uint8_t* p = (uint8_t*)(p_resp + 1) + p_resp->offset;
+ uint8_t flags, cc[8];
+ uint32_t t5t_area_len = 0;
+ uint16_t length = p_resp->len, xx;
+ tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
+ tRW_DATA rw_data;
+ tNFC_STATUS status = NFC_STATUS_FAILED;
+
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - sub_state:%s (0x%x)", __func__,
+ rw_i93_get_sub_state_name(p_i93->sub_state).c_str(), p_i93->sub_state);
+
+ if (length == 0) {
+ android_errorWriteLog(0x534e4554, "121260197");
+ rw_i93_handle_error(NFC_STATUS_FAILED);
+ return;
+ }
+ STREAM_TO_UINT8(flags, p);
+ length--;
+
+ if (flags & I93_FLAG_ERROR_DETECTED) {
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - Got error flags (0x%02x)", __func__, flags);
+ rw_i93_handle_error(NFC_STATUS_FAILED);
+ return;
+ }
+
+ switch (p_i93->sub_state) {
+ case RW_I93_SUBSTATE_WAIT_CC_EXT:
+
+ /* assume block size is 4 */
+ STREAM_TO_ARRAY(cc, p, 4);
+
+ status = NFC_STATUS_FAILED;
+
+ /*
+ ** Capability Container (CC) second block
+ **
+ ** CC[4] : RFU
+ ** CC[5] : RFU
+ ** CC[6] : MSB MLEN
+ ** CC[7] : LSB MLEN
+ */
+
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - cc[4-7]: 0x%02X 0x%02X 0x%02X 0x%02X", __func__,
+ cc[0], cc[1], cc[2], cc[3]);
+
+ /* T5T_Area length = 8 * MLEN */
+ /* CC is 8-byte, MLEN is defined by bytes 6 & 7 */
+ t5t_area_len = cc[3] + (cc[2] << 8);
+ t5t_area_len <<= 3;
+ p_i93->max_ndef_length = t5t_area_len;
+
+ p_i93->t5t_area_last_offset = t5t_area_len + 8 - 1;
+ memcpy((uint8_t*)&rw_cb.tcb.i93.gre_cc_content[4], (uint8_t*)cc, 4);
+ p_i93->num_block = t5t_area_len / p_i93->block_size;
+ p_i93->t5t_area_start_block = 2;
+
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - T5T Area size:%d, Nb blocks:0x%04X, Block size:0x%02X, "
+ "T5T Area last offset:%d",
+ __func__, t5t_area_len, p_i93->num_block, p_i93->block_size,
+ p_i93->t5t_area_last_offset);
+
+ status = NFC_STATUS_OK;
+
+ /* search NDEF TLV from offset 8 when CC file coded on 8 bytes NFC Forum
+ */
+ p_i93->rw_offset = 8;
+
+ if (p_i93->gre_cc_content[0] == I93_ICODE_CC_MAGIC_NUMER_E2) {
+ p_i93->intl_flags |= RW_I93_FLAG_EXT_COMMANDS;
+ }
+
+ 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);
+ }
+ break;
+
+ case RW_I93_SUBSTATE_WAIT_CC:
+
+ if (length < RW_I93_CC_SIZE) {
+ android_errorWriteLog(0x534e4554, "139188579");
+ rw_i93_handle_error(NFC_STATUS_FAILED);
+ return;
+ }
+
+ /* assume block size is more than RW_I93_CC_SIZE 4 */
+ STREAM_TO_ARRAY(cc, p, RW_I93_CC_SIZE);
+
+ 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]
+ */
+
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - cc[0-3]: 0x%02X 0x%02X 0x%02X 0x%02X", __func__,
+ cc[0], cc[1], cc[2], cc[3]);
+
+ if ((cc[0] == I93_ICODE_CC_MAGIC_NUMER_E1) ||
+ (cc[0] == I93_ICODE_CC_MAGIC_NUMER_E2)) {
+ if ((cc[1] & 0xC0) > I93_VERSION_1_x) {
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - Major mapping version above 1 %d.x", __func__, cc[1] >> 6);
+ /* major mapping version above 1 not supported */
+ rw_i93_handle_error(NFC_STATUS_FAILED);
+ break;
+ }
+
+ 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 multiple blocks command */
+ p_i93->intl_flags |= RW_I93_FLAG_READ_MULTI_BLOCK;
+ }
+
+ if (cc[3] & I93_ICODE_CC_SPECIAL_FRAME_MASK) {
+ /* tag supports Special Frame for Write-Alike commands */
+ p_i93->intl_flags |= RW_I93_FLAG_SPECIAL_FRAME;
+ }
+
+ /* get block size from length of the first READ_SINGLE_BLOCK response
+ */
+ if (length == I93_BLEN_4BYTES)
+ p_i93->block_size = I93_BLEN_4BYTES;
+ else if (length == I93_BLEN_8BYTES)
+ p_i93->block_size = I93_BLEN_8BYTES;
+ else if (length == I93_BLEN_16BYTES)
+ p_i93->block_size = I93_BLEN_16BYTES;
+ else if (length == I93_BLEN_32BYTES)
+ p_i93->block_size = I93_BLEN_32BYTES;
+ else {
+ rw_i93_handle_error(NFC_STATUS_FAILED);
+ break;
+ }
+
+ /* T5T_Area length = 8 * MLEN */
+ if (cc[2] == 0) {
+ /* CC is 8-byte, MLEN is defined by bytes 6 & 7 */
+ if (length >= I93_BLEN_8BYTES) {
+ STREAM_TO_ARRAY(&cc[4], p, 4);
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - cc[4-7]: 0x%02X 0x%02X 0x%02X 0x%02X",
+ __func__, cc[4], cc[5], cc[6], cc[7]);
+ t5t_area_len = cc[7] + (cc[6] << 8);
+ t5t_area_len <<= 3;
+
+ p_i93->t5t_area_last_offset = t5t_area_len + 8 - 1;
+ p_i93->max_ndef_length = t5t_area_len;
+ p_i93->t5t_area_start_block = 1;
+
+ memcpy(p_i93->gre_cc_content, cc, 8);
+ } else {
+ /* require an additional read to get the second half of the
+ * CC from block 1 */
+ if (rw_i93_send_cmd_read_single_block(0x0001, false) ==
+ NFC_STATUS_OK) {
+ p_i93->sub_state = RW_I93_SUBSTATE_WAIT_CC_EXT;
+ } else {
+ rw_i93_handle_error(NFC_STATUS_FAILED);
+ }
+ memcpy(p_i93->gre_cc_content, cc, 4);
+ break;
+ }
+ } else {
+ /* CC is 4-byte, MLEN is defined by byte 2 */
+ t5t_area_len = cc[2] << 3;
+ p_i93->t5t_area_last_offset = t5t_area_len + 4 - 1;
+ p_i93->t5t_area_start_block = 1;
+
+ memcpy(p_i93->gre_cc_content, cc, 4);
+ }
+
+ p_i93->num_block = t5t_area_len / p_i93->block_size;
+
+ p_i93->max_ndef_length = t5t_area_len;
+
+ if (cc[0] == I93_ICODE_CC_MAGIC_NUMER_E2) {
+ /* can only be done here if CC is coded over 4 bytes */
+ p_i93->intl_flags |= RW_I93_FLAG_EXT_COMMANDS;
+ }
+
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - T5T Area size:%d, Nb blocks:0x%04X, "
+ "Block size:0x%02X, T5T Area last offset:%d",
+ __func__, t5t_area_len, p_i93->num_block, p_i93->block_size,
+ p_i93->t5t_area_last_offset);
+
+ status = NFC_STATUS_OK;
+ }
+ }
+
+ if (status == NFC_STATUS_OK) {
+ /* search NDEF TLV from offset 4 when CC file coded on 4 bytes
+ * NFC Forum during the next block reading, if CC file is coded
+ * on more than 4 bytes, start searching for NDEF TLV in the current
+ * block read except if the CC
+ */
+ if (cc[2] == 0) {
+ /* 8-byte CC length */
+ p_i93->rw_offset = 8;
+
+ if (length > I93_BLEN_8BYTES) {
+ /* Rest of the block contains T5T_Area, look for NDEF TLV */
+ p_i93->sub_state = RW_I93_SUBSTATE_SEARCH_NDEF_TLV;
+ p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_TYPE;
+ /* start TLV search after CC in the first block */
+ } else {
+ /* 8-byte block length, NDEF TLV search must continue
+ * in the next block */
+ 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);
+ }
+ break;
+ }
+ } else {
+ /* 4-byte CC length */
+ p_i93->rw_offset = 4;
+
+ if (length > I93_BLEN_4BYTES) {
+ /* Rest of the block contains T5T_Area, look for NDEF TLV */
+ p_i93->sub_state = RW_I93_SUBSTATE_SEARCH_NDEF_TLV;
+ p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_TYPE;
+ /* start TLV search after CC in the first block */
+ } else {
+ 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);
+ }
+ break;
+ }
+ }
+ } else {
+ rw_i93_handle_error(NFC_STATUS_FAILED);
+ break;
+ }
+
+ FALLTHROUGH_INTENDED;
+
+ 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_NDEF) {
+ /* 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 {
+ /* TLV with Tag field set as RFU are not interpreted */
+ p_i93->tlv_type = *(p + xx);
+ p_i93->tlv_detect_state = RW_I93_TLV_DETECT_STATE_LENGTH_1;
+ }
+ } 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 - 1;
+ 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;
+
+ 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; // NOTYPO
+ 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;
+ /* Assume tag is already in INITIALIZED or READ-WRITE state */
+ p_i93->max_ndef_length =
+ p_i93->t5t_area_last_offset - p_i93->ndef_tlv_start_offset + 1;
+ if (p_i93->max_ndef_length >= 0xFF) {
+ /* 3 bytes length field can be used */
+ p_i93->max_ndef_length -= 4;
+ } else {
+ /* 1 byte length field can be used */
+ p_i93->max_ndef_length -= 2;
+ }
+ rw_data.ndef.max_size = p_i93->max_ndef_length;
+ }
+
+ /* Complete the greedy collection */
+ p_i93->gre_ndef_tlv_pos = p_i93->ndef_tlv_start_offset;
+ p_i93->gre_ndef_tlv_length = p_i93->ndef_length;
+ p_i93->gre_validity = 1;
+ p_i93->state = RW_I93_STATE_IDLE;
+ p_i93->sent_cmd = 0;
+
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - NDEF cur_size (%d), max_size (%d), flags (0x%x)", __func__,
+ 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;
+ } else {
+ /* read more data */
+ p_i93->rw_offset += length;
+
+ if (p_i93->rw_offset > p_i93->t5t_area_last_offset) {
+ 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;
+
+ default:
+ break;
+ }
+}
+
+/*******************************************************************************
+**
+** Function rw_t5t_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_t5t_sm_update_ndef(NFC_HDR* p_resp) {
+ uint8_t* p = (uint8_t*)(p_resp + 1) + p_resp->offset;
+ uint8_t flags, xx, buff[I93_MAX_BLOCK_LENGH];
+ uint16_t length_offset;
+ uint16_t length = p_resp->len, block_number;
+ tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
+ tRW_DATA rw_data;
+
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - sub_state:%s (0x%x)", __func__,
+ rw_i93_get_sub_state_name(p_i93->sub_state).c_str(), p_i93->sub_state);
+
+ if (length == 0 || p_i93->block_size > I93_MAX_BLOCK_LENGH) {
+ android_errorWriteLog(0x534e4554, "122320256");
+ rw_i93_handle_error(NFC_STATUS_FAILED);
+ return;
+ }
+
+ STREAM_TO_UINT8(flags, p);
+ length--;
+
+ if (flags & I93_FLAG_ERROR_DETECTED) {
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - Got error flags (0x%02x)", __func__, 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;
+
+ if (length < length_offset) {
+ android_errorWriteLog(0x534e4554, "122320256");
+ rw_i93_handle_error(NFC_STATUS_FAILED);
+ return;
+ }
+
+ /* 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;
+ }
+
+ if (p_i93->ndef_length >= 0xFF) {
+ p_i93->ndef_tlv_last_offset = p_i93->ndef_tlv_start_offset + 3;
+ } else {
+ p_i93->ndef_tlv_last_offset = p_i93->ndef_tlv_start_offset + 1;
+ }
+
+ /* write the first part of NDEF in the same block */
+ for (; xx < p_i93->block_size; xx++) {
+ if (xx > length || p_i93->rw_length > p_i93->ndef_length) {
+ android_errorWriteLog(0x534e4554, "122320256");
+ rw_i93_handle_error(NFC_STATUS_FAILED);
+ return;
+ }
+ if (p_i93->rw_length < p_i93->ndef_length) {
+ *(p + xx) = *(p_i93->p_update_data + p_i93->rw_length++);
+ p_i93->ndef_tlv_last_offset++;
+ } 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->t5t_area_last_offset) {
+ // Note: Needed to write in the last block of the memory
+ 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 + xx) <=
+ p_i93->t5t_area_last_offset) &&
+ (xx < p_i93->block_size)) {
+ buff[xx] = I93_ICODE_TLV_TYPE_TERM;
+ }
+ // Note: Needed to write Terminator TLV in block following
+ // the NDEF Message ending in byte 3 of the previous block
+ p_i93->ndef_tlv_last_offset =
+ p_i93->rw_offset - p_i93->block_size + xx - 1;
+
+ } else {
+ p_i93->ndef_tlv_last_offset += p_i93->block_size;
+ }
+
+ 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 */
+ // Note: Needed to write Terminator TLV in block following
+ // the NDEF Message ending in byte 3 of the previous block
+ if ((block_number ==
+ (p_i93->ndef_tlv_last_offset / p_i93->block_size) + 1) &&
+ (((p_i93->ndef_tlv_last_offset + 1) % p_i93->block_size) == 0)) {
+ /* 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);
+ }
+
+ block_number =
+ (p_i93->ndef_tlv_start_offset + 1) / p_i93->block_size;
+
+ /* 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 {
+ /* 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);
+ }
+ }
+ }
+ } /* (p_i93->rw_offset <= p_i93->t5t_area_last_offset) */
+
+ 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 (xx > length) {
+ android_errorWriteLog(0x534e4554, "122320256");
+ rw_i93_handle_error(NFC_STATUS_FAILED);
+ return;
+ }
+
+ 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 {
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - NDEF update complete, %d bytes, (%d-%d)", __func__,
+ 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 = nullptr;
+
+ 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_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_t5t_sm_set_read_only(NFC_HDR* p_resp) {
+ uint8_t* p = (uint8_t*)(p_resp + 1) + p_resp->offset;
+ uint16_t block_number;
+ uint8_t flags;
+
+ uint16_t length = p_resp->len;
+ tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
+ tRW_DATA rw_data;
+
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - sub_state:%s (0x%x)", __func__,
+ rw_i93_get_sub_state_name(p_i93->sub_state).c_str(), p_i93->sub_state);
+
+ if (length == 0) {
+ android_errorWriteLog(0x534e4554, "122322613");
+ rw_i93_handle_error(NFC_STATUS_FAILED);
+ return;
+ }
+
+ STREAM_TO_UINT8(flags, p);
+ length--;
+
+ if (flags & I93_FLAG_ERROR_DETECTED) {
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s - Got error flags (0x%02x)", __func__, flags);
+ rw_i93_handle_error(NFC_STATUS_FAILED);
+ return;
+ }
+
+ switch (p_i93->sub_state) {
+ case RW_I93_SUBSTATE_WAIT_CC:
+
+ if (length < RW_I93_CC_SIZE) {
+ android_errorWriteLog(0x534e4554, "139188579");
+ rw_i93_handle_error(NFC_STATUS_FAILED);
+ return;
+ }
+ /* 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 CC and all blocks of T5T Area */
+ p_i93->rw_offset = 0;
+
+ if (rw_i93_send_cmd_lock_block(0) == NFC_STATUS_OK) {
+ p_i93->rw_offset += p_i93->block_size;
+ p_i93->sub_state = RW_I93_SUBSTATE_LOCK_T5T_AREA;
+ } else {
+ rw_i93_handle_error(NFC_STATUS_FAILED);
+ }
+ break;
+
+ case RW_I93_SUBSTATE_LOCK_T5T_AREA:
+
+ DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
+ "%s - rw_offset:0x%02x, t5t_area_last_offset:0x%02x", __func__,
+ p_i93->rw_offset, p_i93->t5t_area_last_offset);
+
+ /* 2nd block to be locked can be the last 4 bytes of CC in case CC
+ * is 8byte long, then T5T_Area starts */
+ if (p_i93->rw_offset <= p_i93->t5t_area_last_offset) {
+ /* get the next block of NDEF TLV */
+ block_number = (uint16_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);
+ }
+ } 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;
+
+ default:
+ break;
+ }
+}
diff --git a/utils/Android.bp b/utils/Android.bp
index e8021aa..d8a5e9d 100644
--- a/utils/Android.bp
+++ b/utils/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "system_nfc_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["system_nfc_license"],
+}
+
cc_defaults {
name: "nfc_utils_defaults",
include_dirs: [
@@ -18,6 +27,7 @@
sanitize: {
integer_overflow: true,
misc_undefined: ["bounds"],
+ scs: true,
},
}
@@ -49,6 +59,7 @@
static_libs: [
"libnfcutils",
"libgmock",
+ "libc++fs"
],
shared_libs: [
"libbase",
diff --git a/utils/test/config_test.cc b/utils/test/config_test.cc
index b2fde71..62e324c 100644
--- a/utils/test/config_test.cc
+++ b/utils/test/config_test.cc
@@ -16,9 +16,12 @@
#include <gtest/gtest.h>
#include <config.h>
+#include <filesystem>
namespace {
-const char SIMPLE_CONFIG_FILE[] = "/data/local/tmp/test_config.conf";
+const std::filesystem::path kConfigFile =
+ std::filesystem::temp_directory_path() / "test_config.conf";
+const char* SIMPLE_CONFIG_FILE = kConfigFile.c_str();
const char SIMPLE_CONFIG[] =
"# Simple config file test\n\
STRING_VALUE=\"Hello World!\"\n\
@@ -60,6 +63,9 @@
fwrite(SIMPLE_CONFIG, 1, sizeof(SIMPLE_CONFIG), fp);
fclose(fp);
}
+ void TearDown() override {
+ std::filesystem::remove(kConfigFile);
+ }
};
TEST(ConfigTestFromString, test_simple_config) {