Merge "Implementing support for NFC observe mode, polling loop fingerprints and field strength along with their associated APIs." into main am: f57bf9dad9
Original change: https://android-review.googlesource.com/c/platform/hardware/st/nfc/+/2823391
Change-Id: Ib2797010ce17aed61697eea8c1ed44667e58b789
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/st21nfc/Android.bp b/st21nfc/Android.bp
index 6358c4a..018c9fc 100644
--- a/st21nfc/Android.bp
+++ b/st21nfc/Android.bp
@@ -52,6 +52,7 @@
"include",
"gki/ulinux",
],
+
shared_libs: [
"libbase",
"libcutils",
@@ -61,4 +62,10 @@
"liblog",
"libutils",
],
+
+ static_libs: [
+ "android_nfc_flags_aconfig_c_lib",
+ "server_configurable_flags",
+ ],
+
}
diff --git a/st21nfc/adaptation/i2clayer.cc b/st21nfc/adaptation/i2clayer.cc
index 4cbff2e..16b61a8 100644
--- a/st21nfc/adaptation/i2clayer.cc
+++ b/st21nfc/adaptation/i2clayer.cc
@@ -51,6 +51,8 @@
#define LINUX_DBGBUFFER_SIZE 300
+extern "C" { bool android_nfc_nfc_read_polling_loop_st_shim(); }
+
static int fidI2c = 0;
static int cmdPipe[2] = {0, 0};
static int notifyResetRequest = 0;
@@ -76,6 +78,126 @@
static int i2cGetGPIOState(int fid);
static int i2cWrite(int fd, const uint8_t* pvBuffer, int length);
+static const int T_CERx = 0x09;
+static const int T_fieldOn = 0x10;
+static const int T_fieldOff = 0x11;
+static const int T_CERxError = 0x19;
+
+static const unsigned char PROPRIETARY_GID = 0x6F;
+static const unsigned char ANDROID_OID = 0x0C;
+static const unsigned char TYPE_REMOTE_FIELD = 0x00;
+static const unsigned char TYPE_REQA = 0x01;
+static const unsigned char TYPE_REQB = 0x02;
+static const unsigned char TYPE_REQF = 0x03;
+static const unsigned char TYPE_UNKNOWN = 0x07;
+
+
+typedef union timestamp_bytes {
+ unsigned char ts1;
+ unsigned char ts2;
+ unsigned char ts3;
+ unsigned char ts4;
+} timestamp_bytes;
+
+void sendFieldChange(HALHANDLE hHAL, timestamp_bytes timestamp, bool on) {
+ unsigned char value_len = 0x06;
+ unsigned char msg[10] = {PROPRIETARY_GID, ANDROID_OID, TYPE_REMOTE_FIELD,
+ value_len, timestamp.ts1, timestamp.ts2, timestamp.ts3, timestamp.ts4,
+ 0xFF /* no gain data */, static_cast<unsigned char>(on ? 0x01 : 0x00)};
+ HalSendUpstream(hHAL, msg, sizeof(msg));
+}
+
+void sendKnownPollingLoopFrame(HALHANDLE hHAL, char type, timestamp_bytes timestamp, unsigned char gain) {
+ unsigned char value_len = 0x05;
+ unsigned char type_code;
+ switch (type) {
+ case 'A':
+ type_code = TYPE_REQA;
+ break;
+ case 'B':
+ type_code = TYPE_REQB;
+ break;
+ case 'F':
+ type_code = TYPE_REQF;
+ break;
+ default:
+ STLOG_HAL_D("VSLogNFC unknown frame type in known frame");
+ return;
+ }
+ unsigned char msg[9] = {PROPRIETARY_GID, ANDROID_OID, type_code, value_len,
+ timestamp.ts1, timestamp.ts2, timestamp.ts3, timestamp.ts4, gain};
+ HalSendUpstream(hHAL, msg, sizeof(msg));
+}
+
+void sendUnknownPollingLoopFrame(HALHANDLE hHAL, timestamp_bytes timestamp, unsigned char gain,
+ unsigned char* buffer, unsigned char data_len) {
+ size_t header_len = 9;
+ size_t msg_len = header_len + data_len;
+ unsigned char value_len = data_len + 5;
+ unsigned char msg_header[9] = {PROPRIETARY_GID, ANDROID_OID, TYPE_UNKNOWN, value_len,
+ timestamp.ts1, timestamp.ts2, timestamp.ts3, timestamp.ts4, gain};
+ unsigned char* msg_buffer = (unsigned char*)malloc(msg_len);
+ memcpy(msg_buffer, msg_header, header_len);
+ memcpy(msg_buffer + header_len, buffer, data_len);
+ HalSendUpstream(hHAL, msg_buffer, msg_len);
+ free(msg_buffer);
+}
+
+void handlePollingLoopData(HALHANDLE hHAL, int data_len,
+ unsigned char* tlvBuffer) {
+ timestamp_bytes timestamp;
+ timestamp.ts1 = tlvBuffer[data_len - 4];
+ timestamp.ts2 = tlvBuffer[data_len - 3];
+ timestamp.ts3 = tlvBuffer[data_len - 2];
+ timestamp.ts4 = tlvBuffer[data_len - 1];
+
+ int t = tlvBuffer[0];
+ switch (t) {
+ case T_fieldOn:
+ sendFieldChange(hHAL, timestamp, true);
+ break;
+ case T_fieldOff:
+ sendFieldChange(hHAL, timestamp, false);
+ break;
+ case T_CERxError:
+ case T_CERx:
+ {
+ unsigned char gain;
+ if ((tlvBuffer[3] & 0x30) == 0x20) {
+ // ST54J
+ gain = (tlvBuffer[3] & 0xF0) >> 4;
+ } else {
+ // ST21
+ gain = tlvBuffer[3];
+ }
+ switch (tlvBuffer[2] & 0xF) {
+ case 0x1:
+ sendKnownPollingLoopFrame(hHAL, 'A', timestamp, gain);
+ break;
+ case 0x7:
+ sendKnownPollingLoopFrame(hHAL, 'B', timestamp, gain);
+ break;
+ case 0x9:
+ sendKnownPollingLoopFrame(hHAL, 'F', timestamp, gain);
+ break;
+ case 0x3:
+ sendUnknownPollingLoopFrame(hHAL, timestamp, gain, tlvBuffer + 4,
+ data_len - 4);
+ break;
+ }
+ }
+ }
+}
+
+void notifyPollingLoopFrames(HALHANDLE hHAL, unsigned char* buffer, int data_len) {
+ int current_tlv_length = 0;
+ for (int current_tlv_pos = 6;current_tlv_pos + current_tlv_length + 1 <= data_len; current_tlv_pos+= current_tlv_length) {
+ current_tlv_length = buffer[current_tlv_pos + 1] + 2;
+ unsigned char* tlvBuffer = buffer + current_tlv_pos;
+ handlePollingLoopData(hHAL, current_tlv_length, tlvBuffer);
+ }
+}
+
/**************************************************************************************************
*
* Public API Entry-Points
@@ -170,6 +292,11 @@
}
if (bytesRead == remaining) {
DispHal("RX DATA", buffer, 3 + bytesRead);
+ if (android_nfc_nfc_read_polling_loop_st_shim() &&
+ buffer[0] == 0x6f /* Proprietary NTF */ &&
+ buffer[1] == 0x02 /* VS Log */) {
+ notifyPollingLoopFrames(hHAL, buffer, 3 + bytesRead);
+ }
HalSendUpstream(hHAL, buffer, 3 + bytesRead);
} else {
readOk = false;
diff --git a/st21nfc/hal/halcore.cc b/st21nfc/hal/halcore.cc
index d705fd9..07001ab 100644
--- a/st21nfc/hal/halcore.cc
+++ b/st21nfc/hal/halcore.cc
@@ -35,6 +35,8 @@
extern uint32_t ScrProtocolTraceFlag; // = SCR_PROTO_TRACE_ALL;
+extern "C" { bool android_nfc_nfc_observe_mode_st_shim(); }
+
// HAL WRAPPER
static void HalStopTimer(HalInstance* inst);
static bool rf_deactivate_delay;
@@ -102,13 +104,32 @@
rf_deactivate_delay = false;
}
STLOG_HAL_V("!! got event HAL_EVENT_DSWRITE for %zu bytes\n", length);
- DispHal("TX DATA", (data), length);
// Send write command to IO thread
cmd = 'W';
I2cWriteCmd(&cmd, sizeof(cmd));
- I2cWriteCmd((const uint8_t*)&length, sizeof(length));
- I2cWriteCmd(data, length);
+
+ if (android_nfc_nfc_observe_mode_st_shim() && length == 5 &&
+ data[0] == ((NCI_MT_CMD << NCI_MT_SHIFT) | NCI_GID_PROP) &&
+ data[1] == NCI_MSG_PROP_ANDROID &&
+ data[2] == NCI_ANDROID_PASSIVE_OBSERVER_PARAM_SIZE &&
+ data[3] == NCI_ANDROID_PASSIVE_OBSERVER) {
+ const uint8_t msg[7] = {(NCI_MT_CMD << NCI_MT_SHIFT) | NCI_GID_CORE,
+ NCI_MSG_CORE_SET_CONFIG,
+ 0x04 /* Length*/,
+ 0x01 /* One param */,
+ 0xa3 /* RF_DONT_ANSWER_PASSIVE_LISTEN */,
+ 0x01 /* data len*/,
+ data[4] /* enable or disable */};
+ size_t msg_len = 7;
+ DispHal("TX DATA", (msg), msg_len);
+ I2cWriteCmd((const uint8_t*)&msg_len, sizeof(msg_len));
+ I2cWriteCmd(msg, msg_len);
+ } else {
+ DispHal("TX DATA", (data), length);
+ I2cWriteCmd((const uint8_t*)&length, sizeof(length));
+ I2cWriteCmd(data, length);
+ }
break;
case HAL_EVENT_DATAIND:
diff --git a/st21nfc/hal/halcore_private.h b/st21nfc/hal/halcore_private.h
index 27483db..63629ab 100644
--- a/st21nfc/hal/halcore_private.h
+++ b/st21nfc/hal/halcore_private.h
@@ -65,6 +65,24 @@
#define HAL_SLEEP_TIMER 0
#define HAL_SLEEP_TIMER_DURATION 500 /* ordinary t1 timeout to resent data */
+#define NCI_MT_SHIFT 5
+#define NCI_MT_CMD 1 /* (NCI_MT_CMD << NCI_MT_SHIFT) = 0x20 */
+
+#define NCI_MSG_CORE_SET_CONFIG 2
+
+#define NCI_GID_CORE 0x00 /* 0000b NCI Core group */
+#define NCI_GID_PROP 0x0F /* 1111b Proprietary */
+
+#define NCI_MSG_PROP_ANDROID 0x0C
+
+#define NCI_ANDROID_SIGNAL_STRENGTH_NTF 0x01
+#define NCI_ANDROID_FIELD_CHANGE_NTF 0x02
+#define NCI_ANDROID_POLLING_FRAME_NTF 0x03
+
+#define NCI_ANDROID_PASSIVE_OBSERVER 0x2
+
+#define NCI_ANDROID_PASSIVE_OBSERVER_PARAM_SIZE 0x2
+
typedef struct tagHalBuffer {
uint8_t data[MAX_BUFFER_SIZE];
size_t length;