Merge "Apply recovery sequence if the CLF is mute after a nReset pulse"
diff --git a/1.2/hal_st21nfc.cc b/1.2/hal_st21nfc.cc
index fb4f3c9..74e8c2c 100644
--- a/1.2/hal_st21nfc.cc
+++ b/1.2/hal_st21nfc.cc
@@ -49,7 +49,7 @@
   nfc_stack_callback_t* p_cback_unwrap;
 } st21nfc_dev_t;
 
-const char* halVersion = "ST21NFC HAL1.2 Version 3.2.53";
+const char* halVersion = "ST21NFC HAL1.2 Version 3.2.54";
 
 uint8_t cmd_set_nfc_mode_enable[] = {0x2f, 0x02, 0x02, 0x02, 0x01};
 uint8_t hal_is_closed = 1;
diff --git a/st21nfc/adaptation/i2clayer.cc b/st21nfc/adaptation/i2clayer.cc
index f0500f6..4cad4db 100644
--- a/st21nfc/adaptation/i2clayer.cc
+++ b/st21nfc/adaptation/i2clayer.cc
@@ -44,6 +44,7 @@
 #define ST21NFC_SET_POLARITY_FALLING _IOR(ST21NFC_MAGIC, 0x04, unsigned int)
 #define ST21NFC_SET_POLARITY_HIGH _IOR(ST21NFC_MAGIC, 0x05, unsigned int)
 #define ST21NFC_SET_POLARITY_LOW _IOR(ST21NFC_MAGIC, 0x06, unsigned int)
+#define ST21NFC_RECOVERY _IOR(ST21NFC_MAGIC, 0x08, unsigned int)
 #define ST21NFC_CLK_ENABLE _IOR(ST21NFC_MAGIC, 0x11, unsigned int)
 #define ST21NFC_CLK_DISABLE _IOR(ST21NFC_MAGIC, 0x12, unsigned int)
 #define ST21NFC_CLK_STATE _IOR(ST21NFC_MAGIC, 0x13, unsigned int)
@@ -53,6 +54,7 @@
 static int fidI2c = 0;
 static int cmdPipe[2] = {0, 0};
 static int notifyResetRequest = 0;
+static bool recovery_mode = false;
 
 static struct pollfd event_table[3];
 static pthread_t threadHandle = (pthread_t)NULL;
@@ -69,6 +71,7 @@
 
 static int i2cSetPolarity(int fid, bool low, bool edge);
 static int i2cResetPulse(int fid);
+static int SetToRecoveryMode(int fid);
 static int i2cRead(int fid, uint8_t* pvBuffer, int length);
 static int i2cGetGPIOState(int fid);
 static int i2cWrite(int fd, const uint8_t* pvBuffer, int length);
@@ -116,11 +119,13 @@
 
     if (event_table[0].revents & POLLIN) {
       STLOG_HAL_V("echo thread wakeup from chip...\n");
-
       uint8_t buffer[300];
       int count = 0;
 
       do {
+        if (recovery_mode) {
+          break;
+        }
         // load first four bytes:
         int bytesRead = i2cRead(fidI2c, buffer, 3);
 
@@ -173,7 +178,6 @@
 
         readOk = false;
         memset(buffer, 0xca, sizeof(buffer));
-
         /* read while we have data available, up to 2 times then allow writes */
       } while ((i2cGetGPIOState(fidI2c) == 1) && (count++ < 2));
     }
@@ -359,6 +363,15 @@
   i2cResetPulse(fidI2c);
   (void)pthread_mutex_unlock(&i2ctransport_mtx);
 }
+void I2cRecovery() {
+  ALOGD("%s: enter\n", __func__);
+
+  (void)pthread_mutex_lock(&i2ctransport_mtx);
+  recovery_mode = true;
+  SetToRecoveryMode(fidI2c);
+  recovery_mode = false;
+  (void)pthread_mutex_unlock(&i2ctransport_mtx);
+}
 /**************************************************************************************************
  *
  *                                      Private API Definition
@@ -413,6 +426,21 @@
 } /* i2cResetPulse*/
 
 /**
+ * Call the st21nfc driver to generate pulses on RESET line to get a recovery.
+ * @param fid File descriptor for NFC device
+ * @return Result of IOCTL system call (0 if ok)
+ */
+static int SetToRecoveryMode(int fid) {
+  int result;
+
+  if (-1 == (result = ioctl(fid, ST21NFC_RECOVERY, NULL))) {
+    result = -1;
+  }
+  STLOG_HAL_D("! SetToRecoveryMode!!, result = %d", result);
+  return result;
+} /* SetToRecoveryMode*/
+
+/**
  * Write data to st21nfc, on failure do max 3 retries.
  * @param fid File descriptor for NFC device
  * @param pvBuffer Data to write
diff --git a/st21nfc/hal_wrapper.cc b/st21nfc/hal_wrapper.cc
index a75cb21..65cfc1a 100644
--- a/st21nfc/hal_wrapper.cc
+++ b/st21nfc/hal_wrapper.cc
@@ -31,6 +31,7 @@
                             size_t length);
 extern bool I2cOpenLayer(void* dev, HAL_CALLBACK callb, HALHANDLE* pHandle);
 extern void I2cCloseLayer();
+extern void I2cRecovery();
 
 typedef struct {
   struct nfc_nci_device nci_device;  // nci_device must be first struct member
@@ -122,6 +123,8 @@
   isDebuggable = property_get_int32("ro.debuggable", 0);
   mHalHandle = *pHandle;
 
+  HalSendDownstreamTimer(mHalHandle, 10000);
+
   return 1;
 }
 
@@ -572,6 +575,15 @@
       }
       break;
 
+    case HAL_WRAPPER_STATE_OPEN:
+      if (event == HAL_WRAPPER_TIMEOUT_EVT) {
+        STLOG_HAL_D("NFC-NCI HAL: %s  Timeout accessing the CLF.", __func__);
+        HalSendDownstreamStopTimer(mHalHandle);
+        I2cRecovery();
+        return;
+      }
+      break;
+
     case HAL_WRAPPER_STATE_CLOSED:
       if (event == HAL_WRAPPER_TIMEOUT_EVT) {
         STLOG_HAL_D("NFC-NCI HAL: %s  Timeout. Close anyway", __func__);