pn80t: clean up timing and power

This change does a bit of clean up:
- ETU is reduced by a factor of 7 to increase the poll interval to 1ms.
- Reset will use a soft-reset unless there is an ese_error()
- Common doesn't wait for gpio/power resets and lets the platform handle that.
- nq-nci doesn't sleep atfer power up since the kernel handles it.
- Cleaned up more error checking in cooldown.

Test: integration tests pass
Bug: 37954581
Change-Id: I4a86eebe1155cf0b8754dc29db530a8d2565a643
diff --git a/libese-hw/nxp/pn80t/common.c b/libese-hw/nxp/pn80t/common.c
index fd0cf3a..9164fae 100644
--- a/libese-hw/nxp/pn80t/common.c
+++ b/libese-hw/nxp/pn80t/common.c
@@ -42,8 +42,11 @@
 static const struct Teq1ProtocolOptions kTeq1Options = {
     .host_address = 0xA5,
     .node_address = 0x5A,
-    .bwt = 1.624f,   /* cwt by default would be ~8k * 1.05s */
-    .etu = 0.00105f, /* seconds */
+    .bwt = 1.624f, /* cwt by default would be ~8k * 1.05s */
+    /* 1.05ms is the vendor defined ETU.  However, we use this
+     * for polling and 7 * etu (7ms) is a long time to wait
+     * between poll attempts so we divided by 7. */
+    .etu = 0.00015f, /* elementary time unit, in seconds */
     .preprocess = &nxp_pn80t_preprocess,
 };
 
@@ -84,19 +87,28 @@
   }
   /* Power on eSE */
   platform->toggle_reset(ns->handle, 1);
-  /* Let the eSE boot. */
-  platform->wait(ns->handle, 5000);
   return 0;
 }
 
+/* Used for soft-reset when possible. */
+uint32_t nxp_pn80t_send_cooldown(struct EseInterface *ese, bool end);
+
 int nxp_pn80t_reset(struct EseInterface *ese) {
   const struct Pn80tPlatform *platform = ese->ops->opts;
   struct NxpState *ns = NXP_PN80T_STATE(ese);
+
+  /* Attempt a soft reset, but if it fails, then do a hard reset.  */
+  if (!ese_error(ese)) {
+    const uint32_t cooldownSec = nxp_pn80t_send_cooldown(ese, false);
+    if (!ese_error(ese)) {
+      return 0;
+    }
+  }
+
   if (platform->toggle_reset(ns->handle, 0) < 0) {
     ese_set_error(ese, kNxpPn80tErrorResetToggle);
     return -1;
   }
-  platform->wait(ns->handle, 1000);
   if (platform->toggle_reset(ns->handle, 1) < 0) {
     ese_set_error(ese, kNxpPn80tErrorResetToggle);
     return -1;
@@ -109,7 +121,8 @@
   struct NxpState *ns = NXP_PN80T_STATE(ese);
   const struct Pn80tPlatform *platform = ese->ops->opts;
   /* Attempt to read a 8-bit character once per 8-bit character transmission
-   * window (in seconds). */
+   * window (in seconds).
+   */
   int intervals = (int)(0.5f + timeout / (7.0f * kTeq1Options.etu));
   uint8_t byte = 0xff;
   ALOGV("interface polling for start of frame/host node address: %x", poll_for);
@@ -152,23 +165,36 @@
 #define ATTACK_COUNTER 0xF2
 #define RESTRICTED_MODE_PENALTY 0xF3
 uint32_t nxp_pn80t_send_cooldown(struct EseInterface *ese, bool end) {
-  if (ese->error.is_err) {
-    return 0;
-  }
-
   const static uint8_t kEndofApduSession[] = {0x5a, 0xc5, 0x00, 0xc5};
   const static uint8_t kResetSession[] = {0x5a, 0xc4, 0x00, 0xc4};
   const uint8_t *const message = end ? kEndofApduSession : kResetSession;
   const uint32_t message_len =
       end ? sizeof(kEndofApduSession) : sizeof(kResetSession);
+
+  if (ese_error(ese)) {
+    return 0;
+  }
+
   ese->ops->hw_transmit(ese, message, message_len, 1);
+  if (ese_error(ese)) {
+    ALOGE("failed to transmit cooldown check");
+    return 0;
+  }
 
   nxp_pn80t_poll(ese, kTeq1Options.host_address, 5.0f, 0);
+  if (ese_error(ese)) {
+    ALOGE("failed to poll during cooldown");
+    return 0;
+  }
   uint8_t rx_buf[32];
   const uint32_t bytes_read =
       ese->ops->hw_receive(ese, rx_buf, sizeof(rx_buf), 1);
-  ALOGI("Requested power-down delay times (sec):");
+  if (ese_error(ese)) {
+    ALOGE("failed to receive cooldown response");
+    return 0;
+  }
 
+  ALOGI("Requested power-down delay times (sec):");
   /* For each tag type, walk the response to extract the value. */
   uint32_t max_wait = 0;
   if (bytes_read >= 0x8 && rx_buf[0] == 0xe5 && rx_buf[1] == 0x12) {
@@ -177,24 +203,24 @@
       const uint8_t tag = *tag_ptr;
       const uint8_t length = *(tag_ptr + 1);
 
-      // The cooldown timers are 32-bit values
-      if (length == 4) {
+      /* The cooldown timers are 32-bit values. */
+      if (length == sizeof(uint32_t)) {
         const uint32_t *const value_ptr = (uint32_t *)(tag_ptr + 2);
         uint32_t cooldown = ese_be32toh(*value_ptr);
         switch (tag) {
-        case ATTACK_COUNTER:
-          // This cooldown timer is in minutes, so convert it to seconds
-          cooldown *= 60;
-        // Fallthrough
-        case SECURE_TIMER:
         case RESTRICTED_MODE_PENALTY:
+          /* This timer is in minutes, so convert it to seconds. */
+          cooldown *= 60;
+        /* Fallthrough */
+        case SECURE_TIMER:
+        case ATTACK_COUNTER:
           ALOGI("- Timer 0x%.2X: %d", tag, cooldown);
           if (cooldown > max_wait) {
             max_wait = cooldown;
           }
           break;
         default:
-          // Ignore -- not a cooldown timer
+          /* Ignore -- not a known tag. */
           break;
         }
       }
@@ -230,7 +256,6 @@
   case kResetCommand:
     ALOGI("interface command received: reset");
     if (nxp_pn80t_reset(ese) < 0) {
-      /* TODO(wad): wire up a call to hw_reset and teq1_reset */
       /* Warning, state unchanged error. */
       ok[0] = 0x62;
     }
@@ -255,6 +280,10 @@
     uint8_t reply[6] = {0, 0, 0, 0, 0x90, 0x00};
     const uint32_t cooldownSec = nxp_pn80t_send_cooldown(ese, false);
     *(uint32_t *)(&reply[0]) = ese_htole32(cooldownSec);
+    if (ese_error(ese)) {
+      /* Return SW_UKNOWN on an ese failure. */
+      reply[sizeof(reply) - 2] = 0x6f;
+    }
     return ese_sg_from_buf(rx_buf, rx_len, 0, sizeof(reply), reply);
   }
   return 0;
@@ -276,14 +305,13 @@
   ALOGV("%s: called", __func__);
   struct NxpState *ns = NXP_PN80T_STATE(ese);
   const struct Pn80tPlatform *platform = ese->ops->opts;
-  const uint32_t wait_sec =
-      ese->error.is_err ? 0 : nxp_pn80t_send_cooldown(ese, true);
+  const uint32_t wait_sec = nxp_pn80t_send_cooldown(ese, true);
 
-  /* In practice, this should probably migrate into the kernel
-   * and into the spidev code such that each platform can handle it
-   * as needed.
+  /* After the cooldown, the device should go to sleep.
+   * There is no need to pull the power explicitly unless
+   * we're in an error state.
    */
-  if (wait_sec == 0) {
+  if (ese_error(ese)) {
     platform->toggle_reset(ns->handle, 0);
     if (platform->toggle_power_req) {
       platform->toggle_power_req(ns->handle, 0);