Monitor the RW power notification.

To prevent any CLF lock, analyze the PROP_PWR_MON_RW notification and
recover if a timeout is detected.
A recovery is also done if several occurrences of duplicated
PROP_PWR_MON_RW_OFF_NTF are detected.

Bug: 136432213
Bug: 137352121
Bug: 137237286
Test: NFC R/W mode stress test
Merged-In: I8a5e00a139ad104a0336334359f17646d2cb6402
Change-Id: I8a5e00a139ad104a0336334359f17646d2cb6402
diff --git a/1.1/hal_st21nfc.cc b/1.1/hal_st21nfc.cc
index 927e9a1..59823e6 100644
--- a/1.1/hal_st21nfc.cc
+++ b/1.1/hal_st21nfc.cc
@@ -43,7 +43,7 @@
   nfc_stack_callback_t* p_cback_unwrap;
 } st21nfc_dev_t;
 
-const char* halVersion = "ST21NFC HAL1.1 Version 3.1.15";
+const char* halVersion = "ST21NFC HAL1.1 Version 3.1.16";
 
 uint8_t cmd_set_nfc_mode_enable[] = {0x2f, 0x02, 0x02, 0x02, 0x01};
 uint8_t hal_is_closed = 1;
diff --git a/1.2/hal_st21nfc.cc b/1.2/hal_st21nfc.cc
index dfac627..c7e8d16 100644
--- a/1.2/hal_st21nfc.cc
+++ b/1.2/hal_st21nfc.cc
@@ -43,7 +43,7 @@
   nfc_stack_callback_t* p_cback_unwrap;
 } st21nfc_dev_t;
 
-const char* halVersion = "ST21NFC HAL1.2 Version 3.2.4";
+const char* halVersion = "ST21NFC HAL1.2 Version 3.2.5";
 
 uint8_t cmd_set_nfc_mode_enable[] = {0x2f, 0x02, 0x02, 0x02, 0x01};
 uint8_t hal_is_closed = 1;
diff --git a/st21nfc/hal/halcore.cc b/st21nfc/hal/halcore.cc
index 8f432f8..0828bf5 100644
--- a/st21nfc/hal/halcore.cc
+++ b/st21nfc/hal/halcore.cc
@@ -343,6 +343,18 @@
   }
 }
 
+bool HalSendDownstreamTimer(HALHANDLE hHAL, uint32_t duration) {
+  HalInstance* inst = (HalInstance*)hHAL;
+
+  ThreadMesssage msg;
+
+  msg.command = MSG_TIMER_START;
+  msg.payload = 0;
+  msg.length = duration;
+  msg.buffer = NULL;
+
+  return HalEnqueueThreadMessage(inst, &msg);
+}
 /**
  * Send an NCI message downstream to HAL protocol layer (DH->NFCC transfer).
  * Block if more than NUM_BUFFERS (10) transfers are outstanding, otherwise will
@@ -745,6 +757,11 @@
                                     msg.length);
               break;
 
+            case MSG_TIMER_START:
+              // Start timer
+              HalStartTimer(inst, msg.length);
+              STLOG_HAL_D("MSG_TIMER_START \n");
+              break;
             default:
               STLOG_HAL_E("!received unkown thread message?\n");
               break;
diff --git a/st21nfc/hal/halcore_private.h b/st21nfc/hal/halcore_private.h
index 2932706..27483db 100644
--- a/st21nfc/hal/halcore_private.h
+++ b/st21nfc/hal/halcore_private.h
@@ -50,6 +50,7 @@
 
 // HAL _WRAPPER
 #define MSG_TX_DATA_TIMER_START 3
+#define MSG_TIMER_START 4
 
 /* number of buffers used for incoming & outgoing data */
 #define NUM_BUFFERS 10
diff --git a/st21nfc/hal_wrapper.cc b/st21nfc/hal_wrapper.cc
index 7558521..1d42540 100644
--- a/st21nfc/hal_wrapper.cc
+++ b/st21nfc/hal_wrapper.cc
@@ -52,6 +52,8 @@
 int mRetryFwDwl;
 uint8_t mFwUpdateResMask = 0;
 uint8_t* ConfigBuffer = NULL;
+uint8_t mError_count = 0;
+bool mIsActiveRW = false;
 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
 pthread_cond_t ready_cond = PTHREAD_COND_INITIALIZER;
 
@@ -68,6 +70,8 @@
 bool mHciCreditLent = false;
 bool mfactoryReset = false;
 bool ready_flag = 0;
+bool mTimerStarted = false;
+bool forceRecover = false;
 
 void wait_ready() {
   pthread_mutex_lock(&mutex);
@@ -98,6 +102,7 @@
   mHalWrapperState = HAL_WRAPPER_STATE_OPEN;
   mHciCreditLent = false;
   mReadFwConfigDone = false;
+  mError_count = 0;
 
   mHalWrapperCallback = p_cback;
   mHalWrapperDataCallback = p_data_cback;
@@ -414,8 +419,42 @@
               }
             }
           }
+        } else if ((p_data[0] == 0x6f) && (p_data[1] == 0x05)) {
+          // start timer
+          mTimerStarted = true;
+          HalSendDownstreamTimer(mHalHandle, 1000);
+          mIsActiveRW = true;
+        } else if ((p_data[0] == 0x6f) && (p_data[1] == 0x06)) {
+          // stop timer
+          if (mTimerStarted) {
+            HalSendDownstreamStopTimer(mHalHandle);
+            mTimerStarted = false;
+          }
+          if(mIsActiveRW == true) {
+            mIsActiveRW = false;
+          } else {
+            mError_count ++;
+            STLOG_HAL_E("Error Act -> Act count=%d", mError_count);
+            if(mError_count > 20) {
+              mError_count = 0;
+              STLOG_HAL_E("NFC Recovery Start");
+              mTimerStarted = true;
+              HalSendDownstreamTimer(mHalHandle, 1);
+            }
+          }
+        } else if (((p_data[0] == 0x61) && (p_data[1] == 0x05)) ||
+                   ((p_data[0] == 0x61) && (p_data[1] == 0x03))) {
+          mError_count = 0;
+          // stop timer
+          if (mTimerStarted) {
+            HalSendDownstreamStopTimer(mHalHandle);
+            mTimerStarted = false;
+          }
         }
         mHalWrapperDataCallback(data_len, p_data);
+      } else if (forceRecover == true) {
+        forceRecover = false;
+        mHalWrapperDataCallback(data_len, p_data);
       } else {
         STLOG_HAL_V("%s - Core reset notification - Nfc mode ", __func__);
       }
@@ -454,6 +493,7 @@
 
 static void halWrapperCallback(uint8_t event, uint8_t event_status) {
   uint8_t coreInitCmd[] = {0x20, 0x01, 0x02, 0x00, 0x00};
+  uint8_t propNfcModeSetCmdOn[] = {0x2f, 0x02, 0x02, 0x02, 0x01};
 
   switch (mHalWrapperState) {
     case HAL_WRAPPER_STATE_CLOSED:
@@ -496,6 +536,22 @@
       }
       break;
 
+    case HAL_WRAPPER_STATE_READY:
+      if (event == HAL_WRAPPER_TIMEOUT_EVT) {
+        if (mTimerStarted) {
+          STLOG_HAL_D("NFC-NCI HAL: %s  Timeout.. Recover", __func__);
+          HalSendDownstreamStopTimer(mHalHandle);
+          mTimerStarted = false;
+          forceRecover = true;
+          if (!HalSendDownstream(mHalHandle, propNfcModeSetCmdOn,
+                                 sizeof(propNfcModeSetCmdOn))) {
+            STLOG_HAL_E("NFC-NCI HAL: %s  SendDownstream failed", __func__);
+          }
+        }
+        return;
+      }
+      break;
+
     default:
       break;
   }
diff --git a/st21nfc/include/halcore.h b/st21nfc/include/halcore.h
index c700aec..a068803 100644
--- a/st21nfc/include/halcore.h
+++ b/st21nfc/include/halcore.h
@@ -74,6 +74,7 @@
 // HAL WRAPPER
 bool HalSendDownstreamTimer(HALHANDLE hHAL, const uint8_t* data, size_t size,
                             uint32_t duration);
+bool HalSendDownstreamTimer(HALHANDLE hHAL, uint32_t duration);
 bool HalSendDownstreamStopTimer(HALHANDLE hHAL);
 
 /* send a complete HDLC frame from the CLF to the HOST */