Snap for 13256841 from 9c724f616856051759648ede513c208d3e2f4d3d to 25Q2-release

Change-Id: Ibb8d3f26fc7c7e1294b50a8768903c5d85f565db
diff --git a/aidl/StNfc_hal_api.h b/aidl/StNfc_hal_api.h
index 8f00964..1df55b6 100644
--- a/aidl/StNfc_hal_api.h
+++ b/aidl/StNfc_hal_api.h
@@ -66,5 +66,7 @@
 bool StNfc_hal_isLoggingEnabled();
 
 void StNfc_hal_dump(int fd);
+uint16_t
+iso14443_crc(const uint8_t *data, size_t szLen, int type);
 
 #endif /* _STNFC_HAL_API_H_ */
diff --git a/aidl/hal_st21nfc.cc b/aidl/hal_st21nfc.cc
index 3b5082e..fddbfa3 100644
--- a/aidl/hal_st21nfc.cc
+++ b/aidl/hal_st21nfc.cc
@@ -39,6 +39,13 @@
 #endif
 #define VENDOR_LIB_EXT ".so"
 
+
+#define CRC_PRESET_A 0x6363
+#define CRC_PRESET_B 0xFFFF
+#define Type_A 0
+#define Type_B 1
+
+
 bool dbg_logging = false;
 
 extern void HalCoreCallback(void* context, uint32_t event, const void* d,
@@ -393,12 +400,95 @@
       return 0;
     }
   } else if (!memcmp(p_data, NCI_ANDROID_PREFIX, sizeof(NCI_ANDROID_PREFIX)) &&
+             p_data[3] == 0x6) {
+    DispHal("TX DATA", (p_data), data_len);
+
+    memcpy(nci_cmd+3, p_data+4, 4);
+    nci_cmd[0] = 0x2f;
+    nci_cmd[1] = 0x19;
+
+    int index = 8;
+    int ll_index = 7;
+    uint8_t nci_length = 0;
+    uint16_t crc = 0;
+    bool prefix_match = false;
+    bool exact_match = true;
+
+    while (index < data_len) {
+      // Read the Type field (1 byte)
+      uint8_t type_field = p_data[index];
+      int tlv_len = p_data[index + 1];
+      prefix_match = false;
+      exact_match = true;
+      if (p_data[index] == 0x01) {
+        crc = iso14443_crc(p_data + index + 3, (uint8_t)((tlv_len - 1) / 2),
+                           Type_B);
+      } else if ((p_data[index] & 0xF0) == 0x00) {
+        crc = iso14443_crc(p_data + index + 3, (uint8_t)((tlv_len - 1) / 2),
+                           Type_A);
+      } else {
+        prefix_match = true;
+      }
+
+      nci_cmd[ll_index++] = p_data[index++];
+      nci_cmd[ll_index++] =
+          (!prefix_match) ? p_data[index++] + 4 : p_data[index++];
+      nci_cmd[ll_index++] = p_data[index++];
+
+      memcpy(nci_cmd + ll_index, p_data + index, (uint8_t)((tlv_len - 1) / 2));
+      ll_index += (tlv_len - 1) / 2;
+      index += (tlv_len - 1) / 2;
+      int crc_index = 0;
+      if (!prefix_match) {
+        crc_index = ll_index;
+        nci_cmd[ll_index++] = (uint8_t)crc;
+        nci_cmd[ll_index++] = (uint8_t)(crc >> 8);
+      }
+
+      memcpy(nci_cmd + ll_index, p_data + index, (tlv_len - 1) / 2);
+      for (int i = 0; i < (tlv_len - 1) / 2; ++i) {
+        if (p_data[index + i] != 0xFF) {
+            exact_match = false;
+            break;
+        }
+      }
+      ll_index += (tlv_len - 1) / 2;
+      index += (tlv_len - 1) / 2;
+      uint8_t crc_mask = exact_match ? 0xFF : 0x00;
+      if (!prefix_match) {
+        nci_cmd[ll_index++] = crc_mask;
+        nci_cmd[ll_index++] = crc_mask;
+
+        if (!exact_match) {
+        nci_cmd[crc_index] = crc_mask;
+        nci_cmd[crc_index +1] = crc_mask;
+        }
+
+      }
+    }
+    nci_length = ll_index;
+    nci_cmd[2] = ll_index -3;
+
+    if (!HalSendDownstream(dev.hHAL, nci_cmd, nci_length)) {
+      STLOG_HAL_E("HAL st21nfc %s  SendDownstream failed", __func__);
+      (void)pthread_mutex_unlock(&hal_mtx);
+      return 0;
+    }
+  } else if (!memcmp(p_data, NCI_ANDROID_PREFIX, sizeof(NCI_ANDROID_PREFIX)) &&
              p_data[3] == 0x9) {
     DispHal("TX DATA", (p_data), data_len);
     memcpy(nci_cmd + 3, p_data + 4, data_len - 4);
+
+    uint16_t crc = iso14443_crc(nci_cmd + 7, nci_cmd[5] - 1, Type_A);
+
+    uint8_t len = p_data[2];
     nci_cmd[0] = 0x2f;
     nci_cmd[1] = 0x1d;
-    nci_cmd[2] = p_data[2] - 1;
+    nci_cmd[5] = nci_cmd[5] + 2;
+    nci_cmd[data_len - 1] = (uint8_t)crc;
+    nci_cmd[data_len] = (uint8_t)(crc >> 8);
+
+    nci_cmd[2] = p_data[2] + 1;
     if (!HalSendDownstream(dev.hHAL, nci_cmd, nci_cmd[2] + 3)) {
       STLOG_HAL_E("HAL st21nfc %s  SendDownstream failed", __func__);
       (void)pthread_mutex_unlock(&hal_mtx);
@@ -627,3 +717,22 @@
 bool StNfc_hal_isLoggingEnabled() { return dbg_logging; }
 
 void StNfc_hal_dump(int fd) { hal_wrapper_dumplog(fd); }
+
+uint16_t iso14443_crc(const uint8_t* data, size_t szLen, int type) {
+  uint16_t tempCrc;
+  if (type == Type_A) {
+    tempCrc = (unsigned short)CRC_PRESET_A;
+  } else {
+    tempCrc = (unsigned short)CRC_PRESET_B;
+  }
+  do {
+    uint8_t bt;
+    bt = *data++;
+    bt = (bt ^ (uint8_t)(tempCrc & 0x00FF));
+    bt = (bt ^ (bt << 4));
+    tempCrc = (tempCrc >> 8) ^ ((uint32_t)bt << 8) ^ ((uint32_t)bt << 3) ^
+              ((uint32_t)bt >> 4);
+  } while (--szLen);
+
+  return tempCrc;
+}
diff --git a/st21nfc/hal/hal_event_logger.cc b/st21nfc/hal/hal_event_logger.cc
index 5e6264b..8774a9a 100644
--- a/st21nfc/hal/hal_event_logger.cc
+++ b/st21nfc/hal/hal_event_logger.cc
@@ -127,8 +127,8 @@
     oss << ss.str();
   }
 
-  dprintf(fd, "===== Nfc HAL Event Log =====\n");
+  dprintf(fd, "===== Nfc HAL Event Log v1 =====\n");
   ::android::base::WriteStringToFd(oss.str(), fd);
-  dprintf(fd, "===== Nfc HAL Event Log =====\n");
+  dprintf(fd, "===== Nfc HAL Event Log v1 =====\n");
   fsync(fd);
 }
\ No newline at end of file
diff --git a/st21nfc/hal/hal_fd.cc b/st21nfc/hal/hal_fd.cc
index e92fc22..4b73b91 100644
--- a/st21nfc/hal/hal_fd.cc
+++ b/st21nfc/hal/hal_fd.cc
@@ -433,7 +433,9 @@
       (mFWInfo->chipHwVersion == HW_ST54L)) {
     if ((mFwFileBin != NULL) &&
         (mFWInfo->fileFwVersion != mFWInfo->chipFwVersion)) {
-      STLOG_HAL_D("---> Firmware update needed\n");
+      STLOG_HAL_D("---> Firmware update needed from 0x%08X to 0x%08X\n",
+                  mFWInfo->chipFwVersion, mFWInfo->fileFwVersion);
+
       result |= FW_UPDATE_NEEDED;
     } else {
       STLOG_HAL_D("---> No Firmware update needed\n");
@@ -442,8 +444,9 @@
     if ((mFWInfo->fileCustVersion != 0) &&
         (mFWInfo->chipCustVersion != mFWInfo->fileCustVersion)) {
       STLOG_HAL_D(
-          "%s - Need to apply new st21nfc custom configuration settings\n",
-          __func__);
+          "%s - Need to apply new st21nfc custom configuration settings from "
+          "0x%04X to 0x%04X\n",
+          __func__, mFWInfo->chipCustVersion, mFWInfo->fileCustVersion);
       if (!mCustomParamFailed) result |= CONF_UPDATE_NEEDED;
     } else {
       STLOG_HAL_D("%s - No need to apply custom configuration settings\n",
@@ -467,6 +470,12 @@
   } else {
     mFWCap->ObserveMode = 0x1;
   }
+  if (hal_fd_getFwInfo()->chipHwVersion == HW_ST54L &&
+      (FWVersionMajor >= 0x2) && (FWVersionMinor >= 0x6)) {
+    mFWCap->ExitFrameSupport = 0x1;
+  } else {
+    mFWCap->ExitFrameSupport = 0x0;
+  }
   return result;
 } /* ft_cmd_HwReset */
 
diff --git a/st21nfc/hal/halcore.cc b/st21nfc/hal/halcore.cc
index 1d8fc7c..da5d043 100644
--- a/st21nfc/hal/halcore.cc
+++ b/st21nfc/hal/halcore.cc
@@ -42,11 +42,14 @@
 struct timespec start_tx_data;
 uint8_t NCI_ANDROID_GET_CAPS[] = {0x2f, 0x0c, 0x01, 0x0};
 uint8_t NCI_ANDROID_GET_CAPS_RSP[] = {
-    0x4f, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x04,                          // Number of capabilities
+    0x4f, 0x0c,
+    0x14,                          // Command length
+    0x00, 0x00, 0x00, 0x00,
+    0x05,                          // Nb of capabilities
     0x00, 0x01, 0x01,              // Passive Observe mode
     0x01, 0x01, 0x01,              // Polling frame ntf
     0x03, 0x01, 0x00,              // Autotransact polling loop filter
+    0x04, 0x01, 0x05,              // Nb of max exit frame entries
     0x05, 0x01, 0x01               // Polling loop annotations
 };
 
@@ -118,15 +121,16 @@
           !memcmp(data, NCI_ANDROID_GET_CAPS, sizeof(NCI_ANDROID_GET_CAPS))) {
         NCI_ANDROID_GET_CAPS_RSP[2] = sizeof(NCI_ANDROID_GET_CAPS_RSP) - 3;
         NCI_ANDROID_GET_CAPS_RSP[10] = hal_fd_getFwCap()->ObserveMode;
+        NCI_ANDROID_GET_CAPS_RSP[16] = hal_fd_getFwCap()->ExitFrameSupport;
         uint8_t FWVersionMajor = (uint8_t)(hal_fd_getFwInfo()->chipFwVersion >> 24);
         uint8_t FWVersionMinor =
           (uint8_t)((hal_fd_getFwInfo()->chipFwVersion & 0x00FF0000) >> 16);
         // Declare support for reader mode annotation only if fw version >= 2.06.
         if (hal_fd_getFwInfo()->chipHwVersion == HW_ST54L &&
           (FWVersionMajor >= 0x2) && (FWVersionMinor >= 0x6)) {
-            NCI_ANDROID_GET_CAPS_RSP[19] = 1;
+            NCI_ANDROID_GET_CAPS_RSP[22] = 1;
         } else {
-            NCI_ANDROID_GET_CAPS_RSP[19] = 0;
+            NCI_ANDROID_GET_CAPS_RSP[22] = 0;
         }
 
         dev->p_data_cback(sizeof(NCI_ANDROID_GET_CAPS_RSP),
diff --git a/st21nfc/hal_wrapper.cc b/st21nfc/hal_wrapper.cc
index 6848327..c86238d 100644
--- a/st21nfc/hal_wrapper.cc
+++ b/st21nfc/hal_wrapper.cc
@@ -83,6 +83,7 @@
 bool mObserverRsp = false;
 bool mPerTechCmdRsp = false;
 bool storedLog = false;
+bool mObserveModeSuspended = false;
 
 void wait_ready() {
   pthread_mutex_lock(&mutex);
@@ -117,6 +118,7 @@
 
   mObserverMode = 0;
   mObserverRsp = false;
+  mObserveModeSuspended = false;
 
   mHalWrapperCallback = p_cback;
   mHalWrapperDataCallback = p_data_cback;
@@ -215,6 +217,7 @@
   mObserverMode = enable;
   mObserverRsp = true;
   mPerTechCmdRsp = per_tech_cmd;
+  mObserveModeSuspended = false;
 }
 void hal_wrapper_get_observer_mode() { mObserverRsp = true; }
 
@@ -559,7 +562,11 @@
               STLOG_HAL_E("mObserverMode got out of sync");
               mObserverMode = p_data[4];
             }
+            if (!mObserveModeSuspended) {
             p_data[5] = p_data[4];
+            } else {
+              p_data[5] =  0x00;
+            }
           } else {
             if (p_data[7] != mObserverMode) {
               STLOG_HAL_E("mObserverMode got out of sync");
@@ -573,6 +580,7 @@
           p_data[3] = 0x04;
           p_data[4] = rsp_status;
           data_len = 0x6;
+          DispHal("RX DATA", (p_data), data_len);
         }
       }
 
@@ -586,7 +594,13 @@
         DispHal("RX DATA", (p_data), data_len);
       } else if ((p_data[0] == 0x6f) && (p_data[1] == 0x1b)) {
         // PROP_RF_OBSERVE_MODE_SUSPENDED_NTF
+        mObserveModeSuspended = true;
+        // Remove two byte CRC at end of frame.
+        data_len -= 2;
+        p_data[2] -= 2;
+        p_data[4] -= 2;
         memcpy(nciAndroidPassiveObserver, p_data + 3, data_len - 3);
+
         p_data[0] = 0x6f;
         p_data[1] = 0x0c;
         p_data[2] = p_data[2] + 1;
@@ -596,6 +610,8 @@
         DispHal("RX DATA", (p_data), data_len);
       } else if ((p_data[0] == 0x6f) && (p_data[1] == 0x1c)) {
         // PROP_RF_OBSERVE_MODE_RESUMED_NTF
+        mObserveModeSuspended = false;
+
         p_data[0] = 0x6f;
         p_data[1] = 0x0c;
         p_data[2] = p_data[2] + 1;
@@ -803,6 +819,8 @@
       }
       break;
     case HAL_WRAPPER_STATE_RECOVERY:
+      STLOG_HAL_W("%s - mHalWrapperState = HAL_WRAPPER_STATE_RECOVERY",
+                  __func__);
       break;
   }
 }
@@ -929,6 +947,31 @@
       }
       break;
 
+    case HAL_WRAPPER_STATE_EXIT_HIBERNATE_INTERNAL:
+      if (event == HAL_WRAPPER_TIMEOUT_EVT) {
+        STLOG_HAL_E("NFC-NCI HAL: %s  Timeout at state: %s", __func__,
+                    hal_wrapper_state_to_str(mHalWrapperState).c_str());
+        HalEventLogger::getInstance().log()
+            << __func__ << " Timer when sending conf parameters, retry"
+            << " mHalWrapperState="
+            << hal_wrapper_state_to_str(mHalWrapperState)
+            << " mIsActiveRW=" << mIsActiveRW
+            << " mTimerStarted=" << mTimerStarted << std::endl;
+        HalEventLogger::getInstance().store_log();
+        HalSendDownstreamStopTimer(mHalHandle);
+        p_data[0] = 0x60;
+        p_data[1] = 0x00;
+        p_data[2] = 0x03;
+        p_data[3] = 0xAB;
+        p_data[4] = 0x00;
+        p_data[5] = 0x00;
+        data_len = 0x6;
+        mHalWrapperDataCallback(data_len, p_data);
+        mHalWrapperState = HAL_WRAPPER_STATE_OPEN;
+        return;
+      }
+      break;
+
     default:
       if (event == HAL_WRAPPER_TIMEOUT_EVT) {
         STLOG_HAL_E("NFC-NCI HAL: %s  Timeout at state: %s", __func__,
diff --git a/st21nfc/include/hal_fd.h b/st21nfc/include/hal_fd.h
index affc06b..56a6ac9 100644
--- a/st21nfc/include/hal_fd.h
+++ b/st21nfc/include/hal_fd.h
@@ -47,7 +47,7 @@
  */
 typedef struct FWCap {
   uint8_t ObserveMode;
-
+  uint8_t ExitFrameSupport;
 } FWCap;
 
 typedef enum {