Add Peer-To-Peer priority mechanism

Most of NFC devices support card emulation now, there is a chance
that the remote NFC device is detected as a card not peer device.
This peer-to-peer priority mechanism will always try to establish
peer-to-peer connection than card emulation

Peer-To-Peer priority mechanism works only if NFCC is running in
bail out mode. The configuration option NFA_POLL_BAIL_OUT_MODE is to
define the mode of NFCC.

Change-Id: I45a099efa77fab132189ea92da97a90240cfba1d
diff --git a/src/adaptation/NfcAdaptation.cpp b/src/adaptation/NfcAdaptation.cpp
index 1a9e191..99bc87d 100644
--- a/src/adaptation/NfcAdaptation.cpp
+++ b/src/adaptation/NfcAdaptation.cpp
@@ -54,6 +54,7 @@
 static UINT8 deviceHostWhiteList [NFA_HCI_MAX_HOST_IN_NETWORK];
 static tNFA_HCI_CFG jni_nfa_hci_cfg;
 extern tNFA_HCI_CFG *p_nfa_hci_cfg;
+extern BOOLEAN nfa_poll_bail_out_mode;
 
 /*******************************************************************************
 **
@@ -141,6 +142,11 @@
         nfa_ee_max_ee_cfg = num;
         ALOGD("%s: Overriding NFA_EE_MAX_EE_SUPPORTED to use %d", func, nfa_ee_max_ee_cfg);
     }
+    if ( GetNumValue ( NAME_NFA_POLL_BAIL_OUT_MODE, &num, sizeof ( num ) ) )
+    {
+        nfa_poll_bail_out_mode = num;
+        ALOGD("%s: Overriding NFA_POLL_BAIL_OUT_MODE to use %d", func, nfa_poll_bail_out_mode);
+    }
 
     //configure device host whitelist of HCI host ID's; see specification ETSI TS 102 622 V11.1.10
     //(2012-10), section 6.1.3.1
diff --git a/src/include/config.h b/src/include/config.h
index 7f978aa..6b108dc 100644
--- a/src/include/config.h
+++ b/src/include/config.h
@@ -88,6 +88,7 @@
 #define NAME_POWER_OFF_MODE             "POWER_OFF_MODE"
 #define NAME_GLOBAL_RESET               "DO_GLOBAL_RESET"
 #define NAME_NCI_HAL_MODULE             "NCI_HAL_MODULE"
+#define NAME_NFA_POLL_BAIL_OUT_MODE     "NFA_POLL_BAIL_OUT_MODE"
 
 #define                     LPTD_PARAM_LEN (40)
 
diff --git a/src/nfa/dm/nfa_dm_act.c b/src/nfa/dm/nfa_dm_act.c
index 156b03c..942e301 100644
--- a/src/nfa/dm/nfa_dm_act.c
+++ b/src/nfa/dm/nfa_dm_act.c
@@ -1329,6 +1329,19 @@
 
 /*******************************************************************************
 **
+** Function         nfa_dm_act_get_rf_disc_duration
+**
+** Description      Get duration for RF discovery
+**
+** Returns          UINT16
+**
+*******************************************************************************/
+UINT16 nfa_dm_act_get_rf_disc_duration ( )
+{
+    return (nfa_dm_cb.disc_cb.disc_duration);
+}
+/*******************************************************************************
+**
 ** Function         nfa_dm_act_select
 **
 ** Description      Process RF select command
diff --git a/src/nfa/dm/nfa_dm_cfg.c b/src/nfa/dm/nfa_dm_cfg.c
index 202e213..285573e 100644
--- a/src/nfa/dm/nfa_dm_cfg.c
+++ b/src/nfa/dm/nfa_dm_cfg.c
@@ -121,3 +121,5 @@
 };
 
 tNFA_HCI_CFG *p_nfa_hci_cfg = (tNFA_HCI_CFG *) &nfa_hci_cfg;
+
+BOOLEAN nfa_poll_bail_out_mode = FALSE;
diff --git a/src/nfa/dm/nfa_dm_discover.c b/src/nfa/dm/nfa_dm_discover.c
index f9e179f..d0f5fd5 100644
--- a/src/nfa/dm/nfa_dm_discover.c
+++ b/src/nfa/dm/nfa_dm_discover.c
@@ -29,12 +29,14 @@
 #include "nfa_dm_int.h"
 #include "nfa_p2p_int.h"
 #include "nfa_sys_int.h"
+#include "nci_hmsgs.h"
 #if (NFC_NFCEE_INCLUDED == TRUE)
 #include "nfa_ee_api.h"
 #include "nfa_ee_int.h"
 #endif
 #include "nfa_rw_int.h"
 
+#include "nfc_int.h"
 /*
 **  static functions
 */
@@ -58,6 +60,15 @@
 static char *nfa_dm_disc_event_2_str (UINT8 event);
 #endif
 
+typedef struct nfa_dm_p2p_prio_logic
+{
+    BOOLEAN          isodep_detected; /* flag to check if ISO-DEP is detected */
+    BOOLEAN          timer_expired;   /* flag to check whether timer is expired */
+    TIMER_LIST_ENT   timer_list; /*timer structure pointer */
+    UINT8            first_tech_mode;
+}nfa_dm_p2p_prio_logic_t;
+
+static nfa_dm_p2p_prio_logic_t p2p_prio_logic_data;
 
 /*******************************************************************************
 **
@@ -2962,3 +2973,190 @@
     return "Unknown";
 }
 #endif /* BT_TRACE_VERBOSE */
+
+/*******************************************************************************
+**
+** Function         P2P_Prio_Logic
+**
+** Description      Implements algorithm for NFC-DEP protocol priority over
+**                  ISO-DEP protocol.
+**
+** Returns          True if success
+**
+*******************************************************************************/
+BOOLEAN nfa_dm_p2p_prio_logic (UINT8 event, UINT8 *p, UINT8 event_type)
+{
+    if (!nfa_poll_bail_out_mode)
+    {
+        NFA_TRACE_DEBUG0 ("p2p priority is running under bail out mode ONLY.");
+        return TRUE;
+    }
+
+    if ((nfa_dm_cb.flags & NFA_DM_FLAGS_P2P_PAUSED) &&
+       (nfa_dm_cb.flags & NFA_DM_FLAGS_LISTEN_DISABLED))
+    {
+        NFA_TRACE_DEBUG0 ("returning from nfa_dm_p2p_prio_logic  Disable p2p_prio_logic");
+        return TRUE;
+    }
+
+    if (event == NCI_MSG_RF_DISCOVER && p2p_prio_logic_data.timer_expired == TRUE && event_type == NFA_DM_P2P_PRIO_RSP)
+    {
+        NFA_TRACE_DEBUG0 ("nfa_dm_p2p_prio_logic starting a timer for next rf intf activated ntf");
+        nfc_start_quick_timer (&p2p_prio_logic_data.timer_list,
+                        NFC_TTYPE_P2P_PRIO_LOGIC_CLEANUP,
+                        ((UINT32) nfa_dm_act_get_rf_disc_duration() * QUICK_TIMER_TICKS_PER_SEC) / 1000);
+        return TRUE;
+    }
+
+    if (event == NCI_MSG_RF_INTF_ACTIVATED && p2p_prio_logic_data.timer_expired == TRUE)
+    {
+        NFA_TRACE_DEBUG0 ("nfa_dm_p2p_prio_logic stopping a timer for next rf intf activated ntf");
+        nfc_stop_quick_timer (&p2p_prio_logic_data.timer_list);
+    }
+
+    if (nfa_dm_cb.disc_cb.disc_state == NFA_DM_RFST_DISCOVERY)
+    {
+        UINT8 rf_disc_id = 0xFF;
+        UINT8 type = 0xFF;
+        UINT8 protocol = 0xFF;
+        UINT8 tech_mode = 0xFF;
+
+        NFA_TRACE_DEBUG0 ("P2P_Prio_Logic");
+
+        if (event == NCI_MSG_RF_INTF_ACTIVATED )
+        {
+            rf_disc_id    = *p++;
+            type          = *p++;
+            protocol      = *p++;
+            tech_mode     = *p++;
+        }
+        NFA_TRACE_DEBUG1 ("nfa_dm_p2p_prio_logic event_type = 0x%x", event_type);
+
+        if (event == NCI_MSG_RF_INTF_ACTIVATED && tech_mode >= 0x80)
+        {
+            NFA_TRACE_DEBUG0 ("nfa_dm_p2p_prio_logic listen mode activated reset all the nfa_dm_p2p_prio_logic variables ");
+            nfa_dm_p2p_prio_logic_cleanup ();
+        }
+
+        if ((tech_mode < 0x80) &&
+            event == NCI_MSG_RF_INTF_ACTIVATED &&
+            protocol == NCI_PROTOCOL_ISO_DEP &&
+            p2p_prio_logic_data.isodep_detected == FALSE)
+        {
+            nfa_dm_p2p_prio_logic_cleanup ();
+            p2p_prio_logic_data.isodep_detected = TRUE;
+            p2p_prio_logic_data.first_tech_mode = tech_mode;
+            NFA_TRACE_DEBUG0 ("ISO-DEP Detected First Time  Resume the Polling Loop");
+            nci_snd_deactivate_cmd (NFA_DEACTIVATE_TYPE_DISCOVERY);
+            return FALSE;
+        }
+
+        else if (event == NCI_MSG_RF_INTF_ACTIVATED &&
+                protocol == NCI_PROTOCOL_ISO_DEP &&
+                p2p_prio_logic_data.isodep_detected == TRUE &&
+                p2p_prio_logic_data.first_tech_mode != tech_mode)
+        {
+            p2p_prio_logic_data.isodep_detected = TRUE;
+            p2p_prio_logic_data.timer_expired = FALSE;
+            NFA_TRACE_DEBUG0 ("ISO-DEP Detected Second Time Other Techmode  Resume the Polling Loop");
+            nfc_stop_quick_timer (&p2p_prio_logic_data.timer_list);
+            nci_snd_deactivate_cmd (NFA_DEACTIVATE_TYPE_DISCOVERY);
+            return FALSE;
+        }
+
+        else if (event == NCI_MSG_RF_INTF_ACTIVATED &&
+                 protocol == NCI_PROTOCOL_ISO_DEP &&
+                 p2p_prio_logic_data.isodep_detected == TRUE &&
+                 p2p_prio_logic_data.timer_expired == TRUE)
+        {
+            NFA_TRACE_DEBUG0 ("ISO-DEP Detected TimerExpired, Final Notifying the Event");
+            nfc_stop_quick_timer (&p2p_prio_logic_data.timer_list);
+            nfa_dm_p2p_prio_logic_cleanup ();
+        }
+
+        else if (event == NCI_MSG_RF_INTF_ACTIVATED &&
+                 protocol == NCI_PROTOCOL_ISO_DEP &&
+                 p2p_prio_logic_data.isodep_detected == TRUE &&
+                 p2p_prio_logic_data.first_tech_mode == tech_mode)
+        {
+            NFA_TRACE_DEBUG0 ("ISO-DEP Detected Same Techmode, Final Notifying the Event");
+            nfc_stop_quick_timer (&p2p_prio_logic_data.timer_list);
+            NFA_TRACE_DEBUG0 ("P2P_Stop_Timer");
+            nfa_dm_p2p_prio_logic_cleanup ();
+        }
+
+        else if (event == NCI_MSG_RF_INTF_ACTIVATED &&
+                 protocol != NCI_PROTOCOL_ISO_DEP &&
+                 p2p_prio_logic_data.isodep_detected == TRUE)
+        {
+            NFA_TRACE_DEBUG0 ("ISO-DEP Not Detected  Giving Priority for other Technology");
+            nfc_stop_quick_timer (&p2p_prio_logic_data.timer_list);
+            NFA_TRACE_DEBUG0 ("P2P_Stop_Timer");
+            nfa_dm_p2p_prio_logic_cleanup ();
+        }
+
+        else if (event == NCI_MSG_RF_DEACTIVATE &&
+                 p2p_prio_logic_data.isodep_detected == TRUE &&
+                 p2p_prio_logic_data.timer_expired == FALSE &&
+                 event_type == NFA_DM_P2P_PRIO_RSP)
+        {
+            NFA_TRACE_DEBUG0 ("NFA_DM_RF_DEACTIVATE_RSP");
+            return FALSE;
+        }
+
+        else if (event == NCI_MSG_RF_DEACTIVATE &&
+                 p2p_prio_logic_data.isodep_detected == TRUE &&
+                 p2p_prio_logic_data.timer_expired == FALSE &&
+                 event_type == NFA_DM_P2P_PRIO_NTF)
+        {
+            NFA_TRACE_DEBUG0 ("NFA_DM_RF_DEACTIVATE_NTF");
+
+            nfc_start_quick_timer (&p2p_prio_logic_data.timer_list,
+                                   NFC_TTYPE_P2P_PRIO_RESPONSE,
+                                   ((UINT32) 160 * QUICK_TIMER_TICKS_PER_SEC) / 1000 );
+
+            NFA_TRACE_DEBUG0 ("P2P_Start_Timer");
+
+            return FALSE;
+        }
+    }
+
+    NFA_TRACE_DEBUG0 ("returning TRUE");
+    return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function         p2p_prio_logic_timeout
+**
+** Description      Callback function for p2p timer
+**
+** Returns          void
+**
+*******************************************************************************/
+void nfa_dm_p2p_timer_event ()
+{
+    NFA_TRACE_DEBUG0 ("P2P_Timer_timeout NFC-DEP Not Discovered!!");
+
+    p2p_prio_logic_data.timer_expired = TRUE;
+
+    if (p2p_prio_logic_data.isodep_detected == TRUE)
+    {
+        NFA_TRACE_DEBUG0 ("Deactivate and Restart RF discovery");
+        nci_snd_deactivate_cmd (NFC_DEACTIVATE_TYPE_IDLE);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         nfa_dm_p2p_prio_logic_cleanup
+**
+** Description      Callback function for p2p prio logic cleanup timer
+**
+** Returns          void
+**
+*******************************************************************************/
+void nfa_dm_p2p_prio_logic_cleanup ()
+{
+    memset (&p2p_prio_logic_data, 0x00, sizeof(nfa_dm_p2p_prio_logic_t));
+}
diff --git a/src/nfa/int/nfa_dm_int.h b/src/nfa/int/nfa_dm_int.h
index fc9b906..cadd18b 100644
--- a/src/nfa/int/nfa_dm_int.h
+++ b/src/nfa/int/nfa_dm_int.h
@@ -539,6 +539,7 @@
 extern UINT8 nfa_ee_max_ee_cfg;
 extern tNCI_DISCOVER_MAPS *p_nfa_dm_interface_mapping;
 extern UINT8 nfa_dm_num_dm_interface_mapping;
+extern BOOLEAN nfa_poll_bail_out_mode;
 
 /* NFA device manager control block */
 #if NFA_DYNAMIC_MEMORY == FALSE
@@ -597,6 +598,7 @@
 BOOLEAN nfa_dm_tout (tNFA_DM_MSG *p_data);
 BOOLEAN nfa_dm_act_reg_vsc (tNFA_DM_MSG *p_data);
 BOOLEAN nfa_dm_act_send_vsc (tNFA_DM_MSG *p_data);
+UINT16 nfa_dm_act_get_rf_disc_duration ();
 BOOLEAN nfa_dm_act_disable_timeout (tNFA_DM_MSG *p_data);
 BOOLEAN nfa_dm_act_nfc_cback_data (tNFA_DM_MSG *p_data);
 
diff --git a/src/nfc/int/nfc_int.h b/src/nfc/int/nfc_int.h
index 7845c69..5a45072 100644
--- a/src/nfc/int/nfc_int.h
+++ b/src/nfc/int/nfc_int.h
@@ -62,6 +62,8 @@
 #define NFC_TTYPE_RW_T4T_RESPONSE           107
 #define NFC_TTYPE_RW_I93_RESPONSE           108
 #define NFC_TTYPE_CE_T4T_UPDATE             109
+#define NFC_TTYPE_P2P_PRIO_RESPONSE         110  /* added for p2p prio logic timer */
+#define NFC_TTYPE_P2P_PRIO_LOGIC_CLEANUP    111  /* added for p2p prio logic clenaup */
 #define NFC_TTYPE_VS_BASE                   200
 
 
@@ -81,6 +83,13 @@
 };
 typedef UINT8 tNFC_STATE;
 
+/* DM P2P Priority event type */
+enum
+{
+    NFA_DM_P2P_PRIO_RSP = 0x01,         /* P2P priority event from RSP   */
+    NFA_DM_P2P_PRIO_NTF          /* P2P priority event from NTF   */
+};
+
 /* NFC control block flags */
 #define NFC_FL_DEACTIVATING             0x0001  /* NFC_Deactivate () is called and the NCI cmd is not sent   */
 #define NFC_FL_RESTARTING               0x0002  /* restarting NFCC after PowerOffSleep          */
@@ -249,6 +258,9 @@
 NFC_API extern void nfc_ncif_proc_init_rsp (BT_HDR *p_msg);
 NFC_API extern void nfc_ncif_proc_get_config_rsp (BT_HDR *p_msg);
 NFC_API extern void nfc_ncif_proc_data (BT_HDR *p_msg);
+NFC_API extern BOOLEAN nfa_dm_p2p_prio_logic(UINT8 event, UINT8 *p, UINT8 ntf_rsp);
+NFC_API extern void nfa_dm_p2p_timer_event ();
+NFC_API extern void nfa_dm_p2p_prio_logic_cleanup ();
 
 #if (NFC_RW_ONLY == FALSE)
 NFC_API extern void nfc_ncif_proc_rf_field_ntf (UINT8 rf_status);
diff --git a/src/nfc/nci/nci_hrcv.c b/src/nfc/nci/nci_hrcv.c
index 0248212..e2a6384 100644
--- a/src/nfc/nci/nci_hrcv.c
+++ b/src/nfc/nci/nci_hrcv.c
@@ -169,6 +169,7 @@
     switch (op_code)
     {
     case NCI_MSG_RF_DISCOVER:
+        nfa_dm_p2p_prio_logic (op_code, pp, NFA_DM_P2P_PRIO_RSP);
         nfc_ncif_rf_management_status (NFC_START_DEVT, *pp);
         break;
 
@@ -184,6 +185,10 @@
         break;
 
     case NCI_MSG_RF_DEACTIVATE:
+        if (FALSE == nfa_dm_p2p_prio_logic (op_code, pp, NFA_DM_P2P_PRIO_RSP))
+        {
+            return;
+        }
         nfc_ncif_proc_deactivate (*pp, *p_old, FALSE);
         break;
 
@@ -238,10 +243,18 @@
         break;
 
     case NCI_MSG_RF_DEACTIVATE:
+        if (FALSE == nfa_dm_p2p_prio_logic (op_code, pp, NFA_DM_P2P_PRIO_NTF))
+        {
+            return;
+        }
         nfc_ncif_proc_deactivate (NFC_STATUS_OK, *pp, TRUE);
         break;
 
     case NCI_MSG_RF_INTF_ACTIVATED:
+        if (FALSE == nfa_dm_p2p_prio_logic (op_code, pp, NFA_DM_P2P_PRIO_NTF))
+        {
+            return;
+        }
         nfc_ncif_proc_activate (pp, len);
         break;
 
diff --git a/src/nfc/nfc/nfc_task.c b/src/nfc/nfc/nfc_task.c
index 9d9b74a..1ead9b2 100644
--- a/src/nfc/nfc/nfc_task.c
+++ b/src/nfc/nfc/nfc_task.c
@@ -278,6 +278,12 @@
         case NFC_TTYPE_RW_I93_RESPONSE:
             rw_i93_process_timeout (p_tle);
             break;
+        case NFC_TTYPE_P2P_PRIO_RESPONSE:
+            nfa_dm_p2p_timer_event ();
+            break;
+        case NFC_TTYPE_P2P_PRIO_LOGIC_CLEANUP:
+            nfa_dm_p2p_prio_logic_cleanup ();
+            break;
 #if (NFC_RW_ONLY == FALSE)
         case NFC_TTYPE_CE_T4T_UPDATE:
             ce_t4t_process_timeout (p_tle);