Use timeout value calculated from PMm for T3T Check and Update commands.

Change-Id: I0c6cbf0f8ceb52305c3f3ba1df9db715193f57b0
diff --git a/src/nfc/tags/rw_t3t.c b/src/nfc/tags/rw_t3t.c
index 323ee75..b24eefa 100644
--- a/src/nfc/tags/rw_t3t.c
+++ b/src/nfc/tags/rw_t3t.c
@@ -49,6 +49,7 @@
 #define RW_T3T_POLL_CMD_TIMEOUT_TICKS                               ((RW_T3T_TOUT_RESP*2*QUICK_TIMER_TICKS_PER_SEC) / 1000)
 #define RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS                            ((RW_T3T_TOUT_RESP*QUICK_TIMER_TICKS_PER_SEC) / 1000)
 #define RW_T3T_RAW_FRAME_CMD_TIMEOUT_TICKS                          (RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS * 4)
+#define RW_T3T_MIN_TIMEOUT_TICKS                                    3
 
 /* Macro to extract major version from NDEF version byte */
 #define T3T_GET_MAJOR_VERSION(ver)      (ver>>4)
@@ -160,10 +161,53 @@
 
 };
 
-/*****************************************************************************
-**  Type3 TAG COMMANDS
-*****************************************************************************/
+/* This is (T/t3t * 4^E) , E is the index of the array. The unit is .0001 ms */
+static const UINT32 rw_t3t_mrti_base [] =
+{
+    302,
+    1208,
+    4832,
+    19328
+};
 
+
+/*******************************************************************************
+**
+** Function         rw_t3t_check_timeout
+**
+** Description      The timeout value is a + b * number_blocks)
+**
+** Returns          timeout value in ticks
+**
+*******************************************************************************/
+static UINT32 rw_t3t_check_timeout (UINT16 num_blocks)
+{
+    tRW_T3T_CB  *p_cb    = &rw_cb.tcb.t3t;
+    UINT32      timeout;
+    timeout = (p_cb->check_tout_a + num_blocks * p_cb->check_tout_b)*QUICK_TIMER_TICKS_PER_SEC/1000000;
+    if (timeout < RW_T3T_MIN_TIMEOUT_TICKS)
+        timeout = RW_T3T_MIN_TIMEOUT_TICKS;
+    return timeout;
+}
+
+/*******************************************************************************
+**
+** Function         rw_t3t_update_timeout
+**
+** Description      The timeout value is a + b * number_blocks)
+**
+** Returns          timeout value in ticks
+**
+*******************************************************************************/
+static UINT32 rw_t3t_update_timeout (UINT16 num_blocks)
+{
+    tRW_T3T_CB  *p_cb    = &rw_cb.tcb.t3t;
+    UINT32      timeout;
+    timeout = (p_cb->update_tout_a + num_blocks * p_cb->update_tout_b)*QUICK_TIMER_TICKS_PER_SEC/1000000;
+    if (timeout < RW_T3T_MIN_TIMEOUT_TICKS)
+        timeout = RW_T3T_MIN_TIMEOUT_TICKS;
+    return timeout;
+}
 /*******************************************************************************
 **
 ** Function         rw_t3t_process_error
@@ -582,7 +626,7 @@
 ** Returns          tNFC_STATUS
 **
 *****************************************************************************/
-tNFC_STATUS rw_t3t_send_cmd (tRW_T3T_CB *p_cb, UINT8 rw_t3t_cmd, BT_HDR *p_cmd_buf, UINT32 timeout_ms)
+tNFC_STATUS rw_t3t_send_cmd (tRW_T3T_CB *p_cb, UINT8 rw_t3t_cmd, BT_HDR *p_cmd_buf, UINT32 timeout_ticks)
 {
     tNFC_STATUS retval;
 
@@ -591,13 +635,13 @@
     memcpy (p_cb->p_cur_cmd_buf, p_cmd_buf, sizeof (BT_HDR) + p_cmd_buf->offset + p_cmd_buf->len);
 
     p_cb->cur_cmd = rw_t3t_cmd;
-    p_cb->cur_tout = timeout_ms;
+    p_cb->cur_tout = timeout_ticks;
     p_cb->rw_state = RW_T3T_STATE_COMMAND_PENDING;
 
     if ((retval = rw_t3t_send_to_lower (p_cmd_buf)) == NFC_STATUS_OK)
     {
         /* Start timer for waiting for response */
-        nfc_start_quick_timer (&p_cb->timer, NFC_TTYPE_RW_T3T_RESPONSE, timeout_ms);
+        nfc_start_quick_timer (&p_cb->timer, NFC_TTYPE_RW_T3T_RESPONSE, timeout_ticks);
     }
     else
     {
@@ -605,6 +649,7 @@
         p_cb->rw_state = RW_T3T_STATE_IDLE;
     }
 
+    RW_TRACE_DEBUG3 ("rw_t3t_send_cmd: cur_tout: %d, timeout_ticks: %d ret:%d",p_cb->cur_tout, timeout_ticks, retval);
     return (retval);
 }
 
@@ -688,7 +733,7 @@
         p_cmd_buf->len = (UINT16) (p - p_cmd_start);
 
         /* Send the T3T message */
-        retval = rw_t3t_send_cmd (p_cb, RW_T3T_CMD_UPDATE_NDEF, p_cmd_buf, RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS);
+        retval = rw_t3t_send_cmd (p_cb, RW_T3T_CMD_UPDATE_NDEF, p_cmd_buf, rw_t3t_update_timeout(1));
     }
     else
     {
@@ -779,7 +824,7 @@
 
         /* Add number of blocks in this UPDATE command */
         UINT8_TO_STREAM (p, ndef_blocks_to_write);   /* Number of blocks to write in this command */
-        timeout = RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS * (UINT32) ndef_blocks_to_write;
+        timeout = rw_t3t_update_timeout(ndef_blocks_to_write);
 
         for (block_id = first_block_to_write; block_id < (first_block_to_write + ndef_blocks_to_write); block_id++)
         {
@@ -896,9 +941,7 @@
         RW_TRACE_DEBUG3 ("rw_t3t_send_next_ndef_check_cmd: bytes_remaining: %i, cur_blocks_to_read: %i, is_final: %i",
             ndef_bytes_remaining, cur_blocks_to_read, (p_cb->flags & RW_T3T_FL_IS_FINAL_NDEF_SEGMENT));
 
-        /* Write to command header for UPDATE */
-
-        /* Add UPDATE opcode to message  */
+        /* Add CHECK opcode to message  */
         UINT8_TO_STREAM (p, T3T_MSG_OPC_CHECK_CMD);
 
         /* Add IDm to message */
@@ -917,7 +960,7 @@
             UINT16_TO_STREAM (p, T3T_MSG_NDEF_SC_RW);
         }
 
-        /* Add number of blocks in this UPDATE command */
+        /* Add number of blocks in this CHECK command */
         UINT8_TO_STREAM (p, cur_blocks_to_read);     /* Number of blocks to check in this command */
 
         for (block_id = first_block_to_read; block_id < (first_block_to_read + cur_blocks_to_read); block_id++)
@@ -941,7 +984,7 @@
         p_cmd_buf->len = (UINT16) (p - p_cmd_start);
 
         /* Send the T3T message */
-        retval = rw_t3t_send_cmd (p_cb, RW_T3T_CMD_CHECK_NDEF, p_cmd_buf, RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS * (UINT32) cur_blocks_to_read);
+        retval = rw_t3t_send_cmd (p_cb, RW_T3T_CMD_CHECK_NDEF, p_cmd_buf, rw_t3t_check_timeout (cur_blocks_to_read));
     }
     else
     {
@@ -1060,7 +1103,7 @@
         p_cmd_buf->len = (UINT16) (p - p_cmd_start);
 
         /* Send the T3T message */
-        retval = rw_t3t_send_cmd (p_cb, RW_T3T_CMD_CHECK, p_cmd_buf, RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS * (UINT32) num_blocks);
+        retval = rw_t3t_send_cmd (p_cb, RW_T3T_CMD_CHECK, p_cmd_buf, rw_t3t_check_timeout(num_blocks));
     }
     else
     {
@@ -1099,7 +1142,7 @@
         p_cmd_buf->len = (UINT16) (p - p_cmd_start);
 
         /* Send the T3T message */
-        retval = rw_t3t_send_cmd (p_cb, RW_T3T_CMD_UPDATE, p_cmd_buf, RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS * (UINT32) num_blocks);
+        retval = rw_t3t_send_cmd (p_cb, RW_T3T_CMD_UPDATE, p_cmd_buf, rw_t3t_update_timeout(num_blocks));
     }
     else
     {
@@ -1150,7 +1193,7 @@
         p_cmd_buf->len = (UINT16) (p - p_cmd_start);
 
         /* Send the T3T message */
-        return rw_t3t_send_cmd (p_cb, p_cb->cur_cmd, p_cmd_buf, RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS);
+        return rw_t3t_send_cmd (p_cb, p_cb->cur_cmd, p_cmd_buf, rw_t3t_check_timeout(1));
     }
     else
     {
@@ -1716,7 +1759,7 @@
             p_cmd_buf->len = (UINT16) (p - p_cmd_start);
 
             /* Send the T3T message */
-            if ((evt_data.status = rw_t3t_send_cmd (p_cb, RW_T3T_CMD_DETECT_NDEF, p_cmd_buf, RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS)) == NFC_STATUS_OK)
+            if ((evt_data.status = rw_t3t_send_cmd (p_cb, RW_T3T_CMD_DETECT_NDEF, p_cmd_buf, rw_t3t_check_timeout(1))) == NFC_STATUS_OK)
             {
                 /* CHECK command sent. Wait for response */
                 return;
@@ -1823,7 +1866,7 @@
         p_cmd_buf->len = (UINT16) (p_dst - p_cmd_start);
 
         /* Send the T3T message */
-        status = rw_t3t_send_cmd (p_cb, p_cb->cur_cmd, p_cmd_buf, RW_T3T_DEFAULT_CMD_TIMEOUT_TICKS);
+        status = rw_t3t_send_cmd (p_cb, p_cb->cur_cmd, p_cmd_buf, rw_t3t_update_timeout(1));
     }
     else
     {
@@ -2343,6 +2386,31 @@
 
 /*******************************************************************************
 **
+** Function         rw_t3t_mrti_to_a_b
+**
+** Description      Converts the given MRTI (Maximum Response Time Information)
+**                  to the base to calculate timeout value.
+**                  (The timeout value is a + b * number_blocks)
+**
+** Returns          NFC_STATUS_OK
+**
+*******************************************************************************/
+static void rw_t3t_mrti_to_a_b (UINT8 mrti, UINT32 *p_a, UINT32 *p_b)
+{
+    UINT8 a, b, e;
+
+    a = (mrti & 0x7) + 1;   /* A is bit 0 ~ bit 2 */
+    mrti >>=3;
+    b = (mrti & 0x7) + 1;   /* B is bit 3 ~ bit 5 */
+    mrti >>=3;
+    e = mrti & 0x3;         /* E is bit 6 ~ bit 7 */
+    *p_a = rw_t3t_mrti_base[e] * a; /* (A+1) * base (i.e T/t3t * 4^E) */
+    *p_b = rw_t3t_mrti_base[e] * b; /* (B+1) * base (i.e T/t3t * 4^E) */
+}
+
+
+/*******************************************************************************
+**
 ** Function         rw_t3t_select
 **
 ** Description      Called by NFC manager when a Type3 tag has been activated
@@ -2360,6 +2428,8 @@
     p_cb->ndef_attrib.status = NFC_STATUS_NOT_INITIALIZED;  /* Indicate that NDEF detection has not been performed yet */
     p_cb->rw_state = RW_T3T_STATE_IDLE;
     p_cb->flags = 0;
+    rw_t3t_mrti_to_a_b (mrti_check, &p_cb->check_tout_a, &p_cb->check_tout_b);
+    rw_t3t_mrti_to_a_b (mrti_update, &p_cb->update_tout_a, &p_cb->update_tout_b);
 
     /* Alloc cmd buf for retransmissions */
     if (p_cb->p_cur_cmd_buf ==  NULL)