LE: UPF 45 bug fixes

This change fixes the following issues:
- Second GATT-over-BR/EDR channel cannot be established when there
  already is an existing GATT-over-BR/EDR channel
- If encryption fails for an LE connection due to a missing key,
  the security state is not being cleared and blocks all further
  security processing
- When DM discovery of an LE Peripheral device fails with a
  connection timeout, no further discovery requests can be made
- GATT service discovery can get into endless loop when duplicate descriptor
  definitions are found on the remote device
- When GATT over BR/EDR fails, BTA does not give a connection
  callback to the application initiating the connection
- BR/EDR connection to remote platform does not generate API callbacks
- Stack crash discovered during UPF after remote disconnects
- The host is sending HCI disconnect to invalid HCI handle when
  SMP fails because of a connection timeout
- Possible race condition:
  If a disconnect is immediately followed by a connection complete,
  the connection complete cannot be processed in the BTA GATT state
  machine
- Write Complete event is not triggered for Prepare Write requests

Change-Id: I539cdedd68007818ff4f0d0213cee1c913f72d0f

Conflicts:
	bta/gatt/bta_gatts_act.c
diff --git a/bta/dm/bta_dm_act.c b/bta/dm/bta_dm_act.c
index c1b1086..68bae03 100644
--- a/bta/dm/bta_dm_act.c
+++ b/bta/dm/bta_dm_act.c
@@ -92,9 +92,6 @@
 static BOOLEAN bta_dm_dev_blacklisted_for_switch (BD_ADDR remote_bd_addr);
 static void bta_dm_delay_role_switch_cback (TIMER_LIST_ENT *p_tle);
 
-static void bta_dm_remove_sec_dev_entry(BD_ADDR remote_bd_addr);
-
-
 static void bta_dm_disable_search_and_disc(void);
 #if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
     #if ((defined SMP_INCLUDED) && (SMP_INCLUDED == TRUE))
@@ -110,6 +107,8 @@
 static void bta_dm_observe_results_cb (tBTM_INQ_RESULTS *p_inq, UINT8 *p_eir);
 static void bta_dm_observe_cmpl_cb (void * p_result);
 
+static void bta_dm_remove_sec_dev_entry(BD_ADDR remote_bd_addr);
+
 #ifndef BTA_DM_BLE_ADV_CHNL_MAP
 #define BTA_DM_BLE_ADV_CHNL_MAP (BTM_BLE_ADV_CHNL_37|BTM_BLE_ADV_CHNL_38|BTM_BLE_ADV_CHNL_39)
 #endif
@@ -193,6 +192,7 @@
 #if BLE_INCLUDED && BTA_GATT_INCLUDED
     ,BTM_SEC_SERVICE_ATT                    /* BTA_GATT_SERVICE_ID */
 #endif
+
 };
 
 /* bta security callback */
@@ -267,7 +267,6 @@
     tBTA_SYS_HW_MSG *sys_enable_event;
     tBTA_DM_SEC sec_event;
 
-
     /* if already in use, return an error */
     if( bta_dm_cb.is_bta_dm_active == TRUE  )
     {
@@ -279,7 +278,6 @@
         return;
     }
 
-
     /* first, register our callback to SYS HW manager */
     bta_sys_hw_register( BTA_SYS_HW_BLUETOOTH, bta_dm_sys_hw_cback );
 
@@ -382,6 +380,7 @@
         {
             BTM_BleLoadLocalKeys(BTA_BLE_LOCAL_KEY_TYPE_ID, (tBTM_BLE_LOCAL_KEYS *)&id_key);
         }
+        bta_dm_search_cb.conn_id = BTA_GATT_INVALID_CONN_ID;
 #endif
 
         BTM_SecRegister((tBTM_APPL_INFO*)&bta_security);
@@ -2353,11 +2352,6 @@
 {
     tBTA_DM_MSG * p_msg;
 
-#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
-    tBT_DEVICE_TYPE dev_type;
-    tBLE_ADDR_TYPE  addr_type;
-#endif
-
     APPL_TRACE_DEBUG6("bta_dm_discover_device, BDA:0x%02X%02X%02X%02X%02X%02X",
                         remote_bd_addr[0],remote_bd_addr[1],
                         remote_bd_addr[2],remote_bd_addr[3],
@@ -2434,9 +2428,7 @@
                                     bta_dm_search_cb.services_to_search
                                     );
             }
-            BTM_ReadDevInfo(remote_bd_addr, &dev_type, &addr_type);
-
-            if (dev_type == BT_DEVICE_TYPE_BLE)
+            if (BTM_UseLeLink(bta_dm_search_cb.peer_bdaddr))
             /*
             if ( bta_dm_search_cb.p_btm_inq_info != NULL &&
                  bta_dm_search_cb.p_btm_inq_info->results.device_type == BT_DEVICE_TYPE_BLE &&
@@ -2656,10 +2648,6 @@
 static void bta_dm_remname_cback (tBTM_REMOTE_DEV_NAME *p_remote_name)
 {
     tBTA_DM_REM_NAME * p_msg;
-#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
-    tBT_DEVICE_TYPE dev_type;
-    tBLE_ADDR_TYPE  addr_type;
-#endif
 
     APPL_TRACE_DEBUG2("bta_dm_remname_cback len = %d name=<%s>", p_remote_name->length,
                       p_remote_name->remote_bd_name);
@@ -2671,8 +2659,7 @@
 
     BTM_SecDeleteRmtNameNotifyCallback(&bta_dm_service_search_remname_cback);
 #if BLE_INCLUDED == TRUE
-    BTM_ReadDevInfo(p_remote_name->remote_bd_name, &dev_type, &addr_type);
-    if (dev_type == BT_DEVICE_TYPE_BLE)
+    if (BTM_UseLeLink(bta_dm_search_cb.peer_bdaddr))
         GAP_BleReadPeerPrefConnParams (bta_dm_search_cb.peer_bdaddr);
 #endif
     if ((p_msg = (tBTA_DM_REM_NAME *) GKI_getbuf(sizeof(tBTA_DM_REM_NAME))) != NULL)
@@ -2958,6 +2945,7 @@
         }
         /* delete this device entry from Sec Dev DB */
         bta_dm_remove_sec_dev_entry(bd_addr);
+
     }
 
     return BTM_SUCCESS;
@@ -3188,7 +3176,6 @@
 *******************************************************************************/
 static void bta_dm_bl_change_cback (tBTM_BL_EVENT_DATA *p_data)
 {
-
     tBTA_DM_ACL_CHANGE * p_msg;
 
     if ((p_msg = (tBTA_DM_ACL_CHANGE *) GKI_getbuf(sizeof(tBTA_DM_ACL_CHANGE))) != NULL)
@@ -3763,6 +3750,7 @@
     }
 }
 
+
 /*******************************************************************************
 **
 ** Function         bta_dm_adjust_roles
@@ -4974,6 +4962,9 @@
 }
 
 #if ((defined BTA_GATT_INCLUDED) &&  (BTA_GATT_INCLUDED == TRUE))
+#ifndef BTA_DM_GATT_CLOSE_DELAY_TOUT
+#define BTA_DM_GATT_CLOSE_DELAY_TOUT    1000
+#endif
 
 /*******************************************************************************
 **
@@ -5133,15 +5124,41 @@
         }
         if (conn_id != BTA_GATT_INVALID_CONN_ID)
         {
-            BTA_GATTC_Close(conn_id);
+            if (BTA_DM_GATT_CLOSE_DELAY_TOUT != 0)
+            {
+                bta_sys_start_timer(&bta_dm_search_cb.gatt_close_timer, BTA_DM_DISC_CLOSE_TOUT_EVT,
+                                     BTA_DM_GATT_CLOSE_DELAY_TOUT);
+            }
+            else
+            {
+                BTA_GATTC_Close(conn_id);
+                bta_dm_search_cb.conn_id = BTA_GATT_INVALID_CONN_ID;
+            }
         }
-        bta_dm_search_cb.conn_id = BTA_GATT_INVALID_CONN_ID;
+
         bta_dm_search_cb.gatt_disc_active = FALSE;
     }
 }
 
 /*******************************************************************************
 **
+** Function         bta_dm_close_gatt_conn
+**
+** Description      This function close the GATT connection after delay timeout.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_close_gatt_conn(tBTA_DM_MSG *p_data)
+{
+    if (bta_dm_search_cb.conn_id != BTA_GATT_INVALID_CONN_ID)
+        BTA_GATTC_Close(bta_dm_search_cb.conn_id);
+
+    bta_dm_search_cb.conn_id = BTA_GATT_INVALID_CONN_ID;
+}
+
+/*******************************************************************************
+**
 ** Function         btm_dm_start_gatt_discovery
 **
 ** Description      This is GATT initiate the service search by open a GATT connection
@@ -5153,7 +5170,17 @@
 void btm_dm_start_gatt_discovery (BD_ADDR bd_addr)
 {
     bta_dm_search_cb.gatt_disc_active = TRUE;
-    BTA_GATTC_Open(bta_dm_search_cb.client_if, bd_addr, TRUE);
+
+    /* connection is already open */
+    if (bdcmp(bta_dm_search_cb.pending_close_bda, bd_addr) == 0 &&
+        bta_dm_search_cb.conn_id != BTA_GATT_INVALID_CONN_ID)
+    {
+        memset(bta_dm_search_cb.pending_close_bda, 0, BD_ADDR_LEN);
+        bta_sys_stop_timer(&bta_dm_search_cb.gatt_close_timer);
+        btm_dm_start_disc_gatt_services(bta_dm_search_cb.conn_id);
+    }
+    else
+        BTA_GATTC_Open(bta_dm_search_cb.client_if, bd_addr, TRUE);
 }
 
 /*******************************************************************************
diff --git a/bta/dm/bta_dm_int.h b/bta/dm/bta_dm_int.h
index ca34356..9b3069d 100644
--- a/bta/dm/bta_dm_int.h
+++ b/bta/dm/bta_dm_int.h
@@ -128,8 +128,8 @@
     BTA_DM_SDP_RESULT_EVT,
     BTA_DM_SEARCH_CMPL_EVT,
     BTA_DM_DISCOVERY_RESULT_EVT,
-    BTA_DM_API_DI_DISCOVER_EVT
-
+    BTA_DM_API_DI_DISCOVER_EVT,
+    BTA_DM_DISC_CLOSE_TOUT_EVT
 };
 
 /* data type for BTA_DM_API_ENABLE_EVT */
@@ -818,6 +818,8 @@
     UINT8 *                 p_ble_rawdata;
     UINT32                 ble_raw_size;
     UINT32                 ble_raw_used;
+    TIMER_LIST_ENT         gatt_close_timer;
+    BD_ADDR                pending_close_bda;
 #endif
 #endif
 
@@ -991,6 +993,7 @@
 extern void bta_dm_ble_set_bg_conn_type (tBTA_DM_MSG *p_data);
 extern void bta_dm_ble_set_conn_params (tBTA_DM_MSG *p_data);
 extern void bta_dm_ble_set_scan_params (tBTA_DM_MSG *p_data);
+extern void bta_dm_close_gatt_conn(tBTA_DM_MSG *p_data);
 extern void bta_dm_ble_observe (tBTA_DM_MSG *p_data);
 #endif
 extern void bta_dm_set_encryption(tBTA_DM_MSG *p_data);
diff --git a/bta/dm/bta_dm_main.c b/bta/dm/bta_dm_main.c
index dc94c6c..c68f315 100644
--- a/bta/dm/bta_dm_main.c
+++ b/bta/dm/bta_dm_main.c
@@ -61,18 +61,18 @@
     bta_dm_close_acl,         /* 10 BTA_DM_API_ADD_DEVICE_EVT */
 
     /* security API events */
-    bta_dm_bond,              /* 10  BTA_DM_API_BOND_EVT */
-    bta_dm_bond_cancel,       /* 11  BTA_DM_API_BOND_CANCEL_EVT */
-    bta_dm_pin_reply,         /* 12 BTA_DM_API_PIN_REPLY_EVT */
-    bta_dm_link_policy,       /* 13 BTA_DM_API_LINK_POLICY_EVT */
-    bta_dm_auth_reply,        /* 14 BTA_DM_API_AUTH_REPLY_EVT */
+    bta_dm_bond,              /* 11  BTA_DM_API_BOND_EVT */
+    bta_dm_bond_cancel,       /* 12  BTA_DM_API_BOND_CANCEL_EVT */
+    bta_dm_pin_reply,         /* 13 BTA_DM_API_PIN_REPLY_EVT */
+    bta_dm_link_policy,       /* 14 BTA_DM_API_LINK_POLICY_EVT */
+    bta_dm_auth_reply,        /* 15 BTA_DM_API_AUTH_REPLY_EVT */
 
     /* power manger events */
-    bta_dm_pm_btm_status,     /* 15 BTA_DM_PM_BTM_STATUS_EVT */
-    bta_dm_pm_timer,          /* 16 BTA_DM_PM_TIMER_EVT*/
+    bta_dm_pm_btm_status,     /* 16 BTA_DM_PM_BTM_STATUS_EVT */
+    bta_dm_pm_timer,          /* 17 BTA_DM_PM_TIMER_EVT*/
 
     /* simple pairing events */
-    bta_dm_confirm,           /* 17 BTA_DM_API_CONFIRM_EVT */
+    bta_dm_confirm,           /* 18 BTA_DM_API_CONFIRM_EVT */
 
     bta_dm_set_encryption,    /* BTA_DM_API_SET_ENCRYPTION_EVT */
 
@@ -134,7 +134,10 @@
     BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL,  /* 15 bta_dm_search_cancel_transac_cmpl */
     BTA_DM_DISC_RMT_NAME,               /* 16 bta_dm_disc_rmt_name */
     BTA_DM_API_DI_DISCOVER,             /* 17 bta_dm_di_disc */
-    BTA_DM_SEARCH_NUM_ACTIONS           /* 18 */
+#if BLE_INCLUDED == TRUE
+    BTA_DM_CLOSE_GATT_CONN,             /* 18 bta_dm_close_gatt_conn */
+#endif
+    BTA_DM_SEARCH_NUM_ACTIONS           /* 19 */
 };
 
 
@@ -160,6 +163,9 @@
   bta_dm_search_cancel_transac_cmpl, /* 15 BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL */
   bta_dm_disc_rmt_name,             /* 16 BTA_DM_DISC_RMT_NAME */
   bta_dm_di_disc                    /* 17 BTA_DM_API_DI_DISCOVER */
+#if BLE_INCLUDED == TRUE
+  ,bta_dm_close_gatt_conn
+#endif
 };
 
 #define BTA_DM_SEARCH_IGNORE       BTA_DM_SEARCH_NUM_ACTIONS
@@ -184,6 +190,9 @@
 /* SEARCH_CMPL_EVT */       {BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_IDLE},
 /* DISCV_RES_EVT */         {BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_IDLE},
 /* API_DI_DISCOVER_EVT */   {BTA_DM_API_DI_DISCOVER,           BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_ACTIVE}
+#if BLE_INCLUDED == TRUE
+/* DISC_CLOSE_TOUT_EVT */   ,{BTA_DM_CLOSE_GATT_CONN,           BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_IDLE}
+#endif
 
 };
 const UINT8 bta_dm_search_search_active_st_table[][BTA_DM_SEARCH_NUM_COLS] =
@@ -200,6 +209,9 @@
 /* DISCV_RES_EVT */         {BTA_DM_SEARCH_RESULT,             BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_ACTIVE},
 /* API_DI_DISCOVER_EVT */   {BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_ACTIVE}
 
+#if BLE_INCLUDED == TRUE
+/* DISC_CLOSE_TOUT_EVT */   ,{BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_ACTIVE}
+#endif
 
 };
 
@@ -217,6 +229,9 @@
 /* DISCV_RES_EVT */         {BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL, BTA_DM_SEARCH_CANCEL_CMPL,     BTA_DM_SEARCH_IDLE},
 /* API_DI_DISCOVER_EVT */   {BTA_DM_SEARCH_IGNORE,              BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_CANCELLING}
 
+#if BLE_INCLUDED == TRUE
+/* DISC_CLOSE_TOUT_EVT */   ,{BTA_DM_SEARCH_IGNORE,              BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_CANCELLING}
+#endif
 
 };
 
@@ -234,6 +249,10 @@
 /* DISCV_RES_EVT */         {BTA_DM_DISC_RESULT,               BTA_DM_SEARCH_IGNORE,          BTA_DM_DISCOVER_ACTIVE},
 /* API_DI_DISCOVER_EVT */   {BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_DISCOVER_ACTIVE}
 
+#if BLE_INCLUDED == TRUE
+/* DISC_CLOSE_TOUT_EVT */   ,{BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_DISCOVER_ACTIVE}
+#endif
+
 };
 
 typedef const UINT8 (*tBTA_DM_ST_TBL)[BTA_DM_SEARCH_NUM_COLS];
diff --git a/bta/gatt/bta_gattc_act.c b/bta/gatt/bta_gattc_act.c
index a3b18c8..211ec34 100644
--- a/bta/gatt/bta_gattc_act.c
+++ b/bta/gatt/bta_gattc_act.c
@@ -471,7 +471,7 @@
                                       p_data->api_conn.remote_bda,
                                       &p_clcb->bta_conn_id))
         {
-            gattc_data.hdr.layer_specific = p_clcb->bta_conn_id;
+            gattc_data.int_conn.hdr.layer_specific = p_clcb->bta_conn_id;
 
             bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CONN_EVT, &gattc_data);
         }
@@ -511,7 +511,7 @@
                                           p_data->remote_bda,
                                           &conn_id))
             {
-                if ((p_clcb = bta_gattc_clcb_alloc(p_data->client_if, p_data->remote_bda)) != NULL)
+                if ((p_clcb = bta_gattc_find_alloc_clcb(p_data->client_if, p_data->remote_bda)) != NULL)
                 {
                     gattc_data.hdr.layer_specific = p_clcb->bta_conn_id = conn_id;
 
@@ -628,11 +628,11 @@
     if (p_data != NULL)
     {
         APPL_TRACE_DEBUG1("bta_gattc_conn conn_id=%d",p_data->hdr.layer_specific);
+        p_clcb->bta_conn_id  = p_data->int_conn.hdr.layer_specific;
+        GATT_GetConnectionInfor(p_data->int_conn.hdr.layer_specific, &gatt_if, p_clcb->bda);
+    }
 
         p_clcb->p_srcb->connected = TRUE;
-        p_clcb->bta_conn_id  = p_data->hdr.layer_specific;
-        GATT_GetConnectionInfor(p_data->hdr.layer_specific, &gatt_if, p_clcb->bda);
-
         /* start database cache if needed */
         if (p_clcb->p_srcb->p_srvc_cache == NULL ||
             p_clcb->p_srcb->state != BTA_GATTC_SERV_IDLE)
@@ -640,7 +640,7 @@
             if (p_clcb->p_srcb->state == BTA_GATTC_SERV_IDLE)
             {
                 p_clcb->p_srcb->state = BTA_GATTC_SERV_LOAD;
-                bta_gattc_sm_execute(p_clcb, BTA_GATTC_START_CACHE_EVT, p_data);
+                bta_gattc_sm_execute(p_clcb, BTA_GATTC_START_CACHE_EVT, NULL);
             }
             else /* cache is building */
                 p_clcb->state = BTA_GATTC_DISCOVER_ST;
@@ -668,7 +668,6 @@
                                       p_clcb->bta_conn_id);
         }
     }
-}
 /*******************************************************************************
 **
 ** Function         bta_gattc_close_fail
@@ -721,19 +720,13 @@
     if (!BTM_IsBleLink(p_clcb->bda))
         bta_sys_conn_close( BTA_ID_GATTC ,BTA_ALL_APP_ID, p_clcb->bda);
 
-    if (p_clcb->status == BTA_GATT_OK)
-    {
-        bta_gattc_clcb_dealloc(p_clcb);
-    }
+    bta_gattc_clcb_dealloc(p_clcb);
 
     if (p_data->hdr.event == BTA_GATTC_API_CLOSE_EVT)
         cb_data.close.status = GATT_Disconnect(p_data->hdr.layer_specific);
 
-    if ((p_cback != NULL) && (*p_cback != NULL))
-    {
-        (*p_cback)(BTA_GATTC_CLOSE_EVT,(tBTA_GATTC *)&cb_data);
-    }
-
+    if(p_cback)
+        (* p_cback)(BTA_GATTC_CLOSE_EVT,   (tBTA_GATTC *)&cb_data);
 
     if (p_clreg->num_clcb == 0 && p_clreg->dereg_pending)
     {
@@ -955,7 +948,7 @@
         if ((handle = bta_gattc_id2handle(p_clcb->p_srcb,
                                           &p_data->api_read.srvc_id,
                                           &p_data->api_read.char_id,
-                                          p_data->api_read.descr_type)) == 0)
+                                          p_data->api_read.p_descr_type)) == 0)
         {
             op_cmpl.status = BTA_GATT_ERROR;
         }
@@ -992,11 +985,9 @@
     tGATT_READ_PARAM    read_param;
     tBTA_GATTC_OP_CMPL  op_cmpl;
     tBTA_GATTC_ATTR_ID  *p_id;
-    tBT_UUID            dummy_uuid;
 
     if (bta_gattc_enqueue(p_clcb, p_data))
     {
-        memset(&dummy_uuid, 0, sizeof(tBT_UUID));
         memset(&read_param, 0, sizeof(tGATT_READ_PARAM));
 
         p_id = p_data->api_read_multi.p_id_list;
@@ -1010,14 +1001,14 @@
                 handle = bta_gattc_id2handle(p_clcb->p_srcb,
                                      &p_id->id_value.char_id.srvc_id,
                                      &p_id->id_value.char_id.char_id,
-                                     dummy_uuid);
+                                     NULL);
             }
             else if (p_id->id_type == BTA_GATT_TYPE_CHAR_DESCR)
             {
                 handle = bta_gattc_id2handle(p_clcb->p_srcb,
                                      &p_id->id_value.char_descr_id.char_id.srvc_id,
                                      &p_id->id_value.char_descr_id.char_id.char_id,
-                                     p_id->id_value.char_descr_id.descr_type);
+                                     &p_id->id_value.char_descr_id.descr_id);
             }
             else
             {
@@ -1072,7 +1063,7 @@
         if ((handle = bta_gattc_id2handle(p_clcb->p_srcb,
                                           &p_data->api_write.srvc_id,
                                           &p_data->api_write.char_id,
-                                          p_data->api_write.descr_type)) == 0)
+                                          p_data->api_write.p_descr_type)) == 0)
         {
             status = BTA_GATT_ERROR;
         }
@@ -1143,12 +1134,11 @@
 void bta_gattc_confirm(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
 {
     UINT16 handle;
-    tBT_UUID    null_uuid = {0};
 
     if ((handle = bta_gattc_id2handle(p_clcb->p_srcb,
                                       &p_data->api_confirm.srvc_id,
                                       &p_data->api_confirm.char_id,
-                                      null_uuid)) == 0)
+                                      NULL)) == 0)
     {
         APPL_TRACE_ERROR0("Can not map service/char ID into valid handle");
     }
@@ -1165,7 +1155,6 @@
             bta_sys_busy(BTA_ID_GATTC, BTA_ALL_APP_ID, p_clcb->bda);
             bta_sys_idle(BTA_ID_GATTC, BTA_ALL_APP_ID, p_clcb->bda);
         }
-
     }
 }
 /*******************************************************************************
@@ -1202,7 +1191,7 @@
         else
         {
             cb_data.read.status = bta_gattc_pack_read_cb_data(p_clcb->p_srcb,
-                                                              cb_data.read.descr_type,
+                                                              &cb_data.read.descr_type.uuid,
                                                               &p_data->p_cmpl->att_value,
                                                               &read_value);
             cb_data.read.p_value = &read_value;
@@ -1212,10 +1201,11 @@
     {
         cb_data.read.srvc_id = p_clcb->p_q_cmd->api_read.srvc_id;
         cb_data.read.char_id = p_clcb->p_q_cmd->api_read.char_id;
-        cb_data.read.descr_type = p_clcb->p_q_cmd->api_read.descr_type;
+        if (p_clcb->p_q_cmd->api_read.p_descr_type)
+            memcpy(&cb_data.read.descr_type, p_clcb->p_q_cmd->api_read.p_descr_type, sizeof(tBTA_GATT_ID));
     }
 
-    event = (p_clcb->p_q_cmd->api_read.descr_type.len == 0) ? BTA_GATTC_READ_CHAR_EVT: BTA_GATTC_READ_DESCR_EVT;
+    event = (p_clcb->p_q_cmd->api_read.p_descr_type == NULL) ? BTA_GATTC_READ_CHAR_EVT: BTA_GATTC_READ_DESCR_EVT;
     cb_data.read.conn_id = p_clcb->bta_conn_id;
 
     utl_freebuf((void **)&p_clcb->p_q_cmd);
@@ -1237,6 +1227,8 @@
     tBTA_GATTC      cb_data = {0};
     UINT8          event;
 
+    memset(&cb_data, 0, sizeof(tBTA_GATTC));
+
     cb_data.write.status     = p_data->status;
 
     if (p_data->p_cmpl != NULL)
@@ -1247,9 +1239,10 @@
     }
     else
     {
-        cb_data.write.srvc_id = p_clcb->p_q_cmd->api_write.srvc_id;
-        cb_data.write.char_id = p_clcb->p_q_cmd->api_write.char_id;
-        cb_data.write.descr_type = p_clcb->p_q_cmd->api_write.descr_type;
+        memcpy(&cb_data.write.srvc_id, &p_clcb->p_q_cmd->api_write.srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+        memcpy(&cb_data.write.char_id, &p_clcb->p_q_cmd->api_write.char_id, sizeof(tBTA_GATT_ID));
+        if (p_clcb->p_q_cmd->api_write.p_descr_type)
+            memcpy(&cb_data.write.descr_type, p_clcb->p_q_cmd->api_write.p_descr_type, sizeof(tBTA_GATT_ID));
     }
 
     if (p_clcb->p_q_cmd->api_write.hdr.event == BTA_GATTC_API_WRITE_EVT &&
@@ -1257,7 +1250,7 @@
 
         event = BTA_GATTC_PREP_WRITE_EVT;
 
-    else if (p_clcb->p_q_cmd->api_write.descr_type.len == 0)
+    else if (p_clcb->p_q_cmd->api_write.p_descr_type == NULL)
 
         event = BTA_GATTC_WRITE_CHAR_EVT;
 
@@ -1392,7 +1385,7 @@
     {
         status = BTA_GATT_OK;
         /* search the local cache of a server device */
-        bta_gattc_search_service(p_clcb, p_data->api_search.srvc_uuid);
+        bta_gattc_search_service(p_clcb, p_data->api_search.p_srvc_uuid);
     }
     cb_data.search_cmpl.status  = status;
     cb_data.search_cmpl.conn_id = p_clcb->bta_conn_id;
@@ -1609,72 +1602,26 @@
 static void bta_gattc_conn_cback(tGATT_IF gattc_if, BD_ADDR bda, UINT16 conn_id,
                                  BOOLEAN connected, tGATT_DISCONN_REASON reason)
 {
-    BT_HDR          *p_buf;
-    tBTA_GATTC_CLCB *p_clcb = NULL;
-    UINT8           role ;
+    tBTA_GATTC_DATA *p_buf;
 
     APPL_TRACE_DEBUG4("bta_gattc_conn_cback: cif = %d connected = %d conn_id = %d reaosn = 0x%04x",
                       gattc_if, connected, conn_id, reason);
 
-    if (connected)
+    if ((p_buf = (tBTA_GATTC_DATA *) GKI_getbuf(sizeof(tBTA_GATTC_DATA))) != NULL)
     {
-        role = L2CA_GetBleConnRole(bda);
+        memset(p_buf, 0, sizeof(tBTA_GATTC_DATA));
 
-        if (role == HCI_ROLE_SLAVE)
-            bta_gattc_conn_find_alloc(bda);
-
-        /* outgoing connection : locate a logic channel */
-        if ((p_clcb = bta_gattc_find_clcb_by_cif(gattc_if, bda)) == NULL)
-        {
-            /* for a background connection or listening connection */
-            if (/* L2CA_GetBleConnRole(bda)== HCI_ROLE_MASTER && */
-                bta_gattc_check_bg_conn(gattc_if, bda, role))
-            {
-                /* allocate a new channel */
-                p_clcb = bta_gattc_clcb_alloc(gattc_if, bda);
-            }
-        }
-        if (p_clcb != NULL)
-        {
-            p_clcb->bta_conn_id = conn_id;
-
-            if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
-            {
-                p_buf->event = BTA_GATTC_INT_CONN_EVT;
-                p_buf->layer_specific = conn_id;
+        p_buf->int_conn.hdr.event            = connected ? BTA_GATTC_INT_CONN_EVT: BTA_GATTC_INT_DISCONN_EVT;
+        p_buf->int_conn.hdr.layer_specific   = conn_id;
+        p_buf->int_conn.client_if            = gattc_if;
+        p_buf->int_conn.role                 = L2CA_GetBleConnRole(bda);
+        p_buf->int_conn.reason               = reason;
+        bdcpy(p_buf->int_conn.remote_bda, bda);
 
                 bta_sys_sendmsg(p_buf);
             }
         }
-    }
-    else
-    {
-#if BLE_INCLUDED == TRUE
-        bta_gattc_conn_dealloc(bda);
-#endif
-        /* connection attempt timeout, send connection callback event */
-        if (reason == GATT_CONN_CANCEL )
-        {
-            p_clcb = bta_gattc_find_alloc_clcb(gattc_if, bda);
-            p_clcb->bta_conn_id = conn_id;
-        }
-        if ((p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id)) != NULL)
-        {
-            if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
-            {
-                p_buf->event = BTA_GATTC_INT_DISCONN_EVT;
-                p_buf->layer_specific = conn_id;
-                p_clcb->reason        = reason;
 
-                bta_sys_sendmsg(p_buf);
-            }
-        }
-        else
-        {
-            APPL_TRACE_DEBUG1(" connection ID: [%d] not used by BTA", conn_id);
-        }
-    }
-}
 /*******************************************************************************
 **
 ** Function         bta_gattc_process_api_refresh
@@ -1750,8 +1697,8 @@
     srvc_chg_uuid.len = 2;
     srvc_chg_uuid.uu.uuid16 = GATT_UUID_GATT_SRV_CHGD;
 
-    if (bta_gattc_uuid_compare(p_notify->char_id.srvc_id.id.uuid, gattp_uuid, TRUE) &&
-        bta_gattc_uuid_compare(p_notify->char_id.char_id.uuid, srvc_chg_uuid, TRUE))
+    if (bta_gattc_uuid_compare(&p_notify->char_id.srvc_id.id.uuid, &gattp_uuid, TRUE) &&
+        bta_gattc_uuid_compare(&p_notify->char_id.char_id.uuid, &srvc_chg_uuid, TRUE))
     {
         processed = TRUE;
         /* mark service handle change pending */
@@ -1879,11 +1826,7 @@
                     {
                         p_clcb->bta_conn_id = conn_id;
 
-                        /* send connection event */
-                        bta_gattc_send_open_cback(p_clrcb,
-                                                  BTA_GATT_OK,
-                                                  remote_bda,
-                                                  conn_id);
+                        bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CONN_EVT, NULL);
                     }
                     else
                     {
diff --git a/bta/gatt/bta_gattc_api.c b/bta/gatt/bta_gattc_api.c
index 2341aa6..a57fa90 100644
--- a/bta/gatt/bta_gattc_api.c
+++ b/bta/gatt/bta_gattc_api.c
@@ -252,8 +252,12 @@
 
         if (p_srvc_uuid)
         {
-            memcpy(&p_buf->srvc_uuid, p_srvc_uuid, sizeof(tBT_UUID));
+            p_buf->p_srvc_uuid = (tBT_UUID *)(p_buf + 1);
+            memcpy(p_buf->p_srvc_uuid, p_srvc_uuid, sizeof(tBT_UUID));
         }
+        else
+            p_buf->p_srvc_uuid = NULL;
+
         bta_sys_sendmsg(p_buf);
     }
     return;
@@ -289,7 +293,7 @@
         return BTA_GATT_ILLEGAL_PARAMETER;
 
     if ((status = bta_gattc_query_cache(conn_id, BTA_GATTC_ATTR_TYPE_CHAR, p_srvc_id, NULL,
-                                        p_char_uuid_cond, &p_char_result->char_id, p_property))
+                                        p_char_uuid_cond, &p_char_result->char_id, (void *)p_property))
         == BTA_GATT_OK)
     {
         memcpy(&p_char_result->srvc_id, p_srvc_id, sizeof(tBTA_GATT_SRVC_ID));
@@ -333,7 +337,7 @@
                                         &p_start_char_id->char_id,
                                         p_char_uuid_cond,
                                         &p_char_result->char_id,
-                                        p_property))
+                                        (void *) p_property))
         == BTA_GATT_OK)
     {
         memcpy(&p_char_result->srvc_id, &p_start_char_id->srvc_id, sizeof(tBTA_GATT_SRVC_ID));
@@ -379,7 +383,7 @@
                                         NULL))
         == BTA_GATT_OK)
     {
-        memcpy(&p_descr_result->descr_type, &p_descr_result->char_id.char_id.uuid, sizeof(tBT_UUID));
+        memcpy(&p_descr_result->descr_id, &p_descr_result->char_id.char_id, sizeof(tBTA_GATT_ID));
         memcpy(&p_descr_result->char_id, p_char_id, sizeof(tBTA_GATTC_CHAR_ID));
     }
 
@@ -421,10 +425,10 @@
                                         &p_start_descr_id->char_id.char_id,
                                         p_descr_uuid_cond,
                                         &p_descr_result->char_id.char_id,
-                                        (void *)&p_start_descr_id->descr_type))
+                                        (void *)&p_start_descr_id->descr_id))
         == BTA_GATT_OK)
     {
-        memcpy(&p_descr_result->descr_type, &p_descr_result->char_id.char_id.uuid, sizeof(tBT_UUID));
+        memcpy(&p_descr_result->descr_id, &p_descr_result->char_id.char_id, sizeof(tBTA_GATT_ID));
         memcpy(&p_descr_result->char_id, p_start_descr_id, sizeof(tBTA_GATTC_CHAR_ID));
     }
 
@@ -463,7 +467,7 @@
                                         NULL,
                                         p_uuid_cond,
                                         &p_result->incl_svc_id.id,
-                                        (tBTA_GATT_CHAR_PROP *)&p_result->incl_svc_id.is_primary))
+                                        (void *)&p_result->incl_svc_id.is_primary))
         == BTA_GATT_OK)
     {
         memcpy(&p_result->srvc_id, p_srvc_id, sizeof(tBTA_GATT_SRVC_ID));
@@ -505,7 +509,7 @@
                                         &p_start_id->incl_svc_id.id,
                                         p_uuid_cond,
                                         &p_result->incl_svc_id.id,
-                                        (tBTA_GATT_CHAR_PROP *)&p_result->incl_svc_id.is_primary))
+                                        (void *)&p_result->incl_svc_id.is_primary))
         == BTA_GATT_OK)
     {
         memcpy(&p_result->srvc_id, &p_start_id->srvc_id, sizeof(tBTA_GATT_SRVC_ID));
@@ -542,6 +546,7 @@
 
         memcpy(&p_buf->srvc_id, &p_char_id->srvc_id, sizeof(tBTA_GATT_SRVC_ID));
         memcpy(&p_buf->char_id, &p_char_id->char_id, sizeof(tBTA_GATT_ID));
+        p_buf->p_descr_type = NULL;
 
         bta_sys_sendmsg(p_buf);
     }
@@ -565,8 +570,9 @@
                               tBTA_GATT_AUTH_REQ auth_req)
 {
     tBTA_GATTC_API_READ  *p_buf;
+    UINT16  len = (UINT16)(sizeof(tBTA_GATT_ID) + sizeof(tBTA_GATTC_API_READ));
 
-    if ((p_buf = (tBTA_GATTC_API_READ *) GKI_getbuf(sizeof(tBTA_GATTC_API_READ))) != NULL)
+    if ((p_buf = (tBTA_GATTC_API_READ *) GKI_getbuf(len)) != NULL)
     {
         memset(p_buf, 0, sizeof(tBTA_GATTC_API_READ));
 
@@ -576,7 +582,9 @@
 
         memcpy(&p_buf->srvc_id, &p_descr_id->char_id.srvc_id, sizeof(tBTA_GATT_SRVC_ID));
         memcpy(&p_buf->char_id, &p_descr_id->char_id.char_id, sizeof(tBTA_GATT_ID));
-        memcpy(&p_buf->descr_type, &p_descr_id->descr_type, sizeof(tBT_UUID));
+        p_buf->p_descr_type  = (tBTA_GATT_ID *)(p_buf + 1);
+
+        memcpy(p_buf->p_descr_type, &p_descr_id->descr_id, sizeof(tBTA_GATT_ID));
 
         bta_sys_sendmsg(p_buf);
     }
@@ -699,7 +707,7 @@
                                tBTA_GATT_AUTH_REQ auth_req)
 {
     tBTA_GATTC_API_WRITE  *p_buf;
-    UINT16  len = sizeof(tBTA_GATTC_API_WRITE);
+    UINT16  len = sizeof(tBTA_GATTC_API_WRITE) + sizeof(tBTA_GATT_ID);
 
     if (p_data != NULL)
         len += p_data->len;
@@ -714,12 +722,13 @@
 
         memcpy(&p_buf->srvc_id, &p_char_descr_id->char_id.srvc_id, sizeof(tBTA_GATT_SRVC_ID));
         memcpy(&p_buf->char_id, &p_char_descr_id->char_id.char_id, sizeof(tBTA_GATT_ID));
-        memcpy(&p_buf->descr_type, &p_char_descr_id->descr_type, sizeof(tBT_UUID));
+        p_buf->p_descr_type = (tBTA_GATT_ID *)(p_buf + 1);
+        memcpy(p_buf->p_descr_type, &p_char_descr_id->descr_id, sizeof(tBTA_GATT_ID));
         p_buf->write_type = write_type;
 
         if (p_data && p_data->len != 0)
         {
-            p_buf->p_value  = (UINT8 *)(p_buf + 1);
+            p_buf->p_value  = (UINT8 *)(p_buf->p_descr_type + 1);
             p_buf->len      = p_data->len;
             /* pack the descr data */
             memcpy(p_buf->p_value, p_data->p_value, p_data->len);
diff --git a/bta/gatt/bta_gattc_cache.c b/bta/gatt/bta_gattc_cache.c
index 45fafe8..bc784d7 100644
--- a/bta/gatt/bta_gattc_cache.c
+++ b/bta/gatt/bta_gattc_cache.c
@@ -219,7 +219,7 @@
     {
         p_srvc_rec = p_srvc_cb->p_srvc_list + i;
 
-        if (bta_gattc_uuid_compare(p_srvc_rec->uuid, uuid, TRUE))
+        if (bta_gattc_uuid_compare(&p_srvc_rec->uuid, &uuid, TRUE))
             inst ++;
     }
     return inst ;
@@ -233,7 +233,7 @@
 ** Returns          characteristic instance ID.
 **
 *******************************************************************************/
-static UINT8 bta_gattc_get_char_inst_id(tBTA_GATTC_CACHE *p_service_cache, tBT_UUID uuid)
+static UINT8 bta_gattc_get_char_inst_id(tBTA_GATTC_CACHE *p_service_cache, tBT_UUID *p_uuid)
 {
     UINT8 inst = 0;
     tBTA_GATTC_CACHE_ATTR   *p_attr;
@@ -245,11 +245,40 @@
     {
         bta_gattc_pack_attr_uuid(p_attr, &attr_uuid);
 
-        if (bta_gattc_uuid_compare(attr_uuid, uuid, TRUE))
+        if (bta_gattc_uuid_compare(&attr_uuid, p_uuid, TRUE))
             inst ++;
 
         p_attr = p_attr->p_next;
     }
+
+    return inst ;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_get_char_descr_inst_id
+**
+** Description      get characteristic descriptor instance number
+**
+** Returns          characteristic instance ID.
+**
+*******************************************************************************/
+static UINT8 bta_gattc_get_char_descr_inst_id(tBTA_GATTC_CACHE_ATTR *p_char_attr, tBT_UUID *p_uuid)
+{
+    UINT8 inst = 0;
+    tBT_UUID    attr_uuid;
+
+    if (p_char_attr != NULL)
+        p_char_attr = p_char_attr->p_next;
+
+    while (p_char_attr)
+    {
+        bta_gattc_pack_attr_uuid(p_char_attr, &attr_uuid);
+
+        if (bta_gattc_uuid_compare(&attr_uuid, p_uuid, TRUE))
+            inst ++;
+
+        p_char_attr = p_char_attr->p_next;
+    }
     return inst ;
 }
 
@@ -293,6 +322,7 @@
     if (p_srvc_cb->p_cur_srvc != NULL)
         p_srvc_cb->p_cur_srvc->p_next = p_new_srvc;
     p_srvc_cb->p_cur_srvc = p_new_srvc;
+    p_srvc_cb->p_cur_srvc->p_cur_char = NULL;
 
     /* first service */
     if (p_srvc_cb->p_srvc_cache == NULL)
@@ -364,9 +394,13 @@
     }
 
     if (type == BTA_GATTC_ATTR_TYPE_CHAR)
-        p_attr->inst_id = bta_gattc_get_char_inst_id(p_srvc_cb->p_cur_srvc, *p_uuid);
-    /* else: char descriptor, no instance ID needed */
-    else /* TODO: --->> temp treat included service same as char descriptor */
+    {
+        p_attr->inst_id = bta_gattc_get_char_inst_id(p_srvc_cb->p_cur_srvc, p_uuid);
+        p_srvc_cb->p_cur_srvc->p_cur_char = p_attr;
+    }
+    else if (type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
+        p_attr->inst_id = bta_gattc_get_char_descr_inst_id(p_srvc_cb->p_cur_srvc->p_cur_char, p_uuid);
+    else /* TODO: --->> temp treat included service as single instance */
         p_attr->inst_id = 0;
 
     /* update service information */
@@ -427,16 +461,10 @@
 *******************************************************************************/
 tBTA_GATT_STATUS bta_gattc_discover_pri_service(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb, UINT8 disc_type)
 {
-    tBT_DEVICE_TYPE dev_type;
-    tBLE_ADDR_TYPE  addr_type;
-
-    BTM_ReadDevInfo(p_server_cb->server_bda, &dev_type, &addr_type);
-    if (dev_type == BT_DEVICE_TYPE_BLE)
+    if (BTM_IsBleLink(p_server_cb->server_bda))
         return bta_gattc_discover_procedure(conn_id, p_server_cb, disc_type);
     else
         return bta_gattc_sdp_service_disc(conn_id, p_server_cb);
-    return BTA_GATT_ERROR;
-
 }
 /*******************************************************************************
 **
@@ -1019,7 +1047,7 @@
 **
 *******************************************************************************/
 UINT16 bta_gattc_id2handle(tBTA_GATTC_SERV *p_srcb, tBTA_GATT_SRVC_ID *p_service_id,
-                           tBTA_GATT_ID *p_char_id, tBT_UUID descr_uuid)
+                           tBTA_GATT_ID *p_char_id, tBTA_GATT_ID *p_descr_uuid)
 {
     tBTA_GATTC_CACHE    *p_cache = p_srcb->p_srvc_cache;
     tBTA_GATTC_CACHE_ATTR   *p_attr;
@@ -1047,10 +1075,10 @@
 #endif
                 bta_gattc_pack_attr_uuid(p_attr, &attr_uuid);
 
-                if (bta_gattc_uuid_compare(p_char_id->uuid, attr_uuid, TRUE) &&
+                if (bta_gattc_uuid_compare(&p_char_id->uuid, &attr_uuid, TRUE) &&
                     p_char_id->inst_id == p_attr->inst_id)
                 {
-                    if (descr_uuid.len == 0)
+                    if (p_descr_uuid == NULL)
                     {
                         handle = p_attr->attr_handle;
                         done = TRUE;
@@ -1069,7 +1097,9 @@
                     if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
                     {
 
-                        if (bta_gattc_uuid_compare(descr_uuid, attr_uuid, TRUE))
+                        if (p_descr_uuid != NULL &&
+                            bta_gattc_uuid_compare(&p_descr_uuid->uuid, &attr_uuid, TRUE) &&
+                            p_descr_uuid->inst_id == p_attr->inst_id)
                         {
 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
                             APPL_TRACE_DEBUG0("found descriptor!!");
@@ -1114,7 +1144,7 @@
 *******************************************************************************/
 
 BOOLEAN bta_gattc_handle2id(tBTA_GATTC_SERV *p_srcb, UINT16 handle, tBTA_GATT_SRVC_ID *p_service_id,
-                            tBTA_GATT_ID *p_char_id, tBT_UUID *p_descr_type)
+                            tBTA_GATT_ID *p_char_id, tBTA_GATT_ID *p_descr_type)
 {
     tBTA_GATTC_CACHE    *p_cache = p_srcb->p_srvc_cache;
     tBTA_GATTC_CACHE_ATTR   *p_attr, *p_char = NULL;
@@ -1122,7 +1152,7 @@
 
     memset(p_service_id, 0, sizeof(tBTA_GATT_SRVC_ID));
     memset(p_char_id, 0, sizeof(tBTA_GATT_ID));
-    memset(p_descr_type, 0, sizeof(tBT_UUID));
+    memset(p_descr_type, 0, sizeof(tBTA_GATT_ID));
 
     while (p_cache)
     {
@@ -1157,7 +1187,8 @@
 
                     if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
                     {
-                        bta_gattc_pack_attr_uuid(p_attr, p_descr_type);
+                        bta_gattc_pack_attr_uuid(p_attr, &p_descr_type->uuid);
+                        p_descr_type->inst_id = p_attr->inst_id;
 
                         if (p_char != NULL)
                         {
@@ -1195,7 +1226,7 @@
 ** Returns          FALSE if map can not be found.
 **
 *******************************************************************************/
-void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID uuid)
+void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID *p_uuid)
 {
     tBTA_GATTC_SERV     *p_srcb = p_clcb->p_srcb;
     tBTA_GATTC_CACHE    *p_cache = p_srcb->p_srvc_cache;
@@ -1203,7 +1234,7 @@
 
     while (p_cache)
     {
-        if (bta_gattc_uuid_compare(uuid, p_cache->service_uuid.id.uuid, FALSE))
+        if (bta_gattc_uuid_compare(p_uuid, &p_cache->service_uuid.id.uuid, FALSE))
         {
 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
             APPL_TRACE_DEBUG3("found service [0x%04x], inst[%d] handle [%d]",
@@ -1246,13 +1277,10 @@
 {
     tBTA_GATTC_CACHE    *p_cache = p_srcb->p_srvc_cache;
     tBTA_GATT_STATUS    status = BTA_GATT_ERROR;
-    tBT_UUID            uuid_cond = {0}, start_descr = {0};
     UINT8               i, j;
     tBTA_GATTC_CACHE_ATTR   *p_attr;
     BOOLEAN             char_found = FALSE, descr_found = FALSE;
-
-    if (p_uuid_cond)
-        memcpy(&uuid_cond, p_uuid_cond, sizeof(tBT_UUID));
+    tBTA_GATT_ID        *p_descr_id = (tBTA_GATT_ID *)p_param;;
 
     for (i = 0; p_cache && status != BTA_GATT_OK; i ++)
     {
@@ -1279,11 +1307,12 @@
                 if (p_start_rec != NULL && char_found == FALSE)
                 {
                     /* find the starting record first */
-                    if (bta_gattc_uuid_compare(p_start_rec->uuid, p_result->uuid, FALSE) &&
+                    if (bta_gattc_uuid_compare(&p_start_rec->uuid, &p_result->uuid, FALSE) &&
                         p_start_rec->inst_id  == p_attr->inst_id &&
                         (attr_type == p_attr->attr_type ||
                         /* find descriptor would look for characteristic first */
-                         (attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR && p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR)))
+                         (attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR &&
+                          p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR)))
                     {
                         char_found = TRUE;
                     }
@@ -1293,9 +1322,6 @@
                     /* if looking for descriptor, here is the where the descrptor to be found */
                     if (attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
                     {
-                        /* starting descriptor UUID */
-                        if (p_param != NULL)
-                            memcpy(&start_descr, p_param, sizeof(tBT_UUID));
                         /* next characeteristic already, return error */
                         if (p_attr->attr_type != BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
                         {
@@ -1303,9 +1329,11 @@
                         }
                         else
                         {
-                            if (start_descr.len != 0 && !descr_found)
+                            /* find starting descriptor */
+                            if (p_descr_id != NULL && !descr_found)
                             {
-                                if (bta_gattc_uuid_compare(start_descr, p_result->uuid, FALSE))
+                                if (bta_gattc_uuid_compare(&p_descr_id->uuid, &p_result->uuid, TRUE)
+                                    && p_descr_id->inst_id == p_attr->inst_id)
                                 {
                                     descr_found = TRUE;
                                 }
@@ -1313,8 +1341,9 @@
                             else
                             {
                                 /* with matching descriptor */
-                                if (bta_gattc_uuid_compare(uuid_cond, p_result->uuid, FALSE))
+                                if (bta_gattc_uuid_compare(p_uuid_cond, &p_result->uuid, FALSE))
                                 {
+                                    p_result->inst_id = p_attr->inst_id;
                                     status = BTA_GATT_OK;
                                     break;
                                 }
@@ -1323,7 +1352,7 @@
                     }
                     else
                     {
-                        if (bta_gattc_uuid_compare(uuid_cond, p_result->uuid, FALSE) &&
+                        if (bta_gattc_uuid_compare(p_uuid_cond, &p_result->uuid, FALSE) &&
                             attr_type == p_attr->attr_type)
                         {
 
diff --git a/bta/gatt/bta_gattc_int.h b/bta/gatt/bta_gattc_int.h
index 2228d24..7730113 100644
--- a/bta/gatt/bta_gattc_int.h
+++ b/bta/gatt/bta_gattc_int.h
@@ -125,7 +125,7 @@
     tBTA_GATT_AUTH_REQ      auth_req;
     tBTA_GATT_SRVC_ID       srvc_id;
     tBTA_GATT_ID            char_id;
-    tBT_UUID                descr_type;
+    tBTA_GATT_ID            *p_descr_type;
 } tBTA_GATTC_API_READ;
 
 typedef struct
@@ -134,7 +134,7 @@
     tBTA_GATT_AUTH_REQ      auth_req;
     tBTA_GATT_SRVC_ID       srvc_id;
     tBTA_GATT_ID            char_id;
-    tBT_UUID                descr_type;
+    tBTA_GATT_ID            *p_descr_type;
     tBTA_GATTC_WRITE_TYPE   write_type;
     UINT16                  offset;
     UINT16                  len;
@@ -167,7 +167,7 @@
 typedef struct
 {
     BT_HDR              hdr;
-    tBT_UUID            srvc_uuid;
+    tBT_UUID            *p_srvc_uuid;
 }tBTA_GATTC_API_SEARCH;
 
 typedef struct
@@ -178,6 +178,15 @@
     tBTA_GATTC_ATTR_ID      *p_id_list;
 }tBTA_GATTC_API_READ_MULTI;
 
+typedef struct
+{
+    BT_HDR                  hdr;
+    BD_ADDR                 remote_bda;
+    tBTA_GATTC_IF           client_if;
+    UINT8                   role;
+    tGATT_DISCONN_REASON    reason;
+}tBTA_GATTC_INT_CONN;
+
 typedef union
 {
     BT_HDR                      hdr;
@@ -195,6 +204,7 @@
     tBTA_GATTC_CI_EVT           ci_open;
     tBTA_GATTC_CI_EVT           ci_save;
     tBTA_GATTC_CI_LOAD          ci_load;
+    tBTA_GATTC_INT_CONN         int_conn;
 
     tBTA_GATTC_INT_START_IF     int_start_if;
     tBTA_GATTC_INT_DEREG        int_dereg;
@@ -232,6 +242,7 @@
     UINT16                  s_handle;
     UINT16                  e_handle;
     struct                  gattc_svc_cache *p_next;
+    tBTA_GATTC_CACHE_ATTR   *p_cur_char;
 // btla-specific ++
 } __attribute__((packed)) tBTA_GATTC_CACHE;
 // btla-specific --
@@ -462,14 +473,17 @@
 extern tBTA_GATTC_SERV * bta_gattc_find_srcb(BD_ADDR bda);
 extern tBTA_GATTC_SERV * bta_gattc_srcb_alloc(BD_ADDR bda);
 extern tBTA_GATTC_SERV * bta_gattc_find_scb_by_cid (UINT16 conn_id);
+extern tBTA_GATTC_CLCB * bta_gattc_find_int_conn_clcb(tBTA_GATTC_DATA *p_msg);
+extern tBTA_GATTC_CLCB * bta_gattc_find_int_disconn_clcb(tBTA_GATTC_DATA *p_msg);
+
 extern BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
 
-extern UINT16 bta_gattc_id2handle(tBTA_GATTC_SERV *p_srcb, tBTA_GATT_SRVC_ID *p_service_id, tBTA_GATT_ID *p_char_id, tBT_UUID descr_uuid);
-extern BOOLEAN bta_gattc_handle2id(tBTA_GATTC_SERV *p_srcb, UINT16 handle, tBTA_GATT_SRVC_ID *service_id, tBTA_GATT_ID *char_id, tBT_UUID *p_type);
-extern BOOLEAN bta_gattc_uuid_compare (tBT_UUID src, tBT_UUID tar, BOOLEAN is_precise);
+extern UINT16 bta_gattc_id2handle(tBTA_GATTC_SERV *p_srcb, tBTA_GATT_SRVC_ID *p_service_id, tBTA_GATT_ID *p_char_id, tBTA_GATT_ID *p_descr_uuid);
+extern BOOLEAN bta_gattc_handle2id(tBTA_GATTC_SERV *p_srcb, UINT16 handle, tBTA_GATT_SRVC_ID *service_id, tBTA_GATT_ID *char_id, tBTA_GATT_ID *p_type);
+extern BOOLEAN bta_gattc_uuid_compare (tBT_UUID *p_src, tBT_UUID *p_tar, BOOLEAN is_precise);
 extern void bta_gattc_pack_attr_uuid(tBTA_GATTC_CACHE_ATTR   *p_attr, tBT_UUID *p_uuid);
 extern BOOLEAN bta_gattc_check_notif_registry(tBTA_GATTC_RCB  *p_clreg, tBTA_GATTC_SERV *p_srcb, tBTA_GATTC_NOTIFY  *p_notify);
-extern tBTA_GATT_STATUS bta_gattc_pack_read_cb_data(tBTA_GATTC_SERV *p_srcb, tBT_UUID descr_uuid, tGATT_VALUE *p_attr, tBTA_GATT_READ_VAL *p_value);
+extern tBTA_GATT_STATUS bta_gattc_pack_read_cb_data(tBTA_GATTC_SERV *p_srcb, tBT_UUID *p_descr_uuid, tGATT_VALUE *p_attr, tBTA_GATT_READ_VAL *p_value);
 extern BOOLEAN bta_gattc_mark_bg_conn (tBTA_GATTC_IF client_if,  BD_ADDR_PTR remote_bda, BOOLEAN add, BOOLEAN is_listen);
 extern BOOLEAN bta_gattc_check_bg_conn (tBTA_GATTC_IF client_if,  BD_ADDR remote_bda, UINT8 role);
 extern UINT8 bta_gattc_num_reg_app(void);
@@ -484,10 +498,10 @@
 extern void bta_gattc_disc_cmpl_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_STATUS status);
 extern tBTA_GATT_STATUS bta_gattc_discover_procedure(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb, UINT8 disc_type);
 extern tBTA_GATT_STATUS bta_gattc_discover_pri_service(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb, UINT8 disc_type);
-extern void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID uuid);
+extern void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID *p_uuid);
 extern tBTA_GATT_STATUS bta_gattc_query_cache(UINT16 conn_id, UINT8 query_type, tBTA_GATT_SRVC_ID *p_srvc_id,
                                               tBTA_GATT_ID *p_start_rec,tBT_UUID *p_uuid_cond,
-                                              tBTA_GATT_ID *p_output, void *p_property);
+                                              tBTA_GATT_ID *p_output, void *p_param);
 extern tBTA_GATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV *p_srvc_cb);
 extern void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srcv, UINT16 num_attr, tBTA_GATTC_NV_ATTR *p_attr, UINT16 attr_index);
 extern BOOLEAN bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id);
diff --git a/bta/gatt/bta_gattc_main.c b/bta/gatt/bta_gattc_main.c
index e6c6819..0479546 100644
--- a/bta/gatt/bta_gattc_main.c
+++ b/bta/gatt/bta_gattc_main.c
@@ -162,7 +162,7 @@
 /* BTA_GATTC_API_WRITE_EVT          */   {BTA_GATTC_FAIL,               BTA_GATTC_W4_CONN_ST},
 /* BTA_GATTC_API_EXEC_EVT           */   {BTA_GATTC_FAIL,               BTA_GATTC_W4_CONN_ST},
 
-/* BTA_GATTC_API_CLOSE_EVT          */   {BTA_GATTC_CLOSE_FAIL,         BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_API_CLOSE_EVT          */   {BTA_GATTC_CANCEL_OPEN,         BTA_GATTC_W4_CONN_ST},
 
 /* BTA_GATTC_API_SEARCH_EVT         */   {BTA_GATTC_FAIL,               BTA_GATTC_W4_CONN_ST},
 /* BTA_GATTC_API_CONFIRM_EVT        */   {BTA_GATTC_FAIL,               BTA_GATTC_W4_CONN_ST},
@@ -173,7 +173,7 @@
 /* BTA_GATTC_INT_DISCOVER_EVT       */   {BTA_GATTC_IGNORE,             BTA_GATTC_W4_CONN_ST},
 /* BTA_GATTC_DISCOVER_CMPL_EVT       */  {BTA_GATTC_IGNORE,             BTA_GATTC_W4_CONN_ST},
 /* BTA_GATTC_OP_CMPL_EVT            */   {BTA_GATTC_IGNORE,             BTA_GATTC_W4_CONN_ST},
-/* BTA_GATTC_INT_DISCONN_EVT      */     {BTA_GATTC_CLOSE,              BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_INT_DISCONN_EVT      */     {BTA_GATTC_OPEN_FAIL,          BTA_GATTC_IDLE_ST},
 
 /* ===> for cache loading, saving   */
 /* BTA_GATTC_START_CACHE_EVT        */   {BTA_GATTC_IGNORE,             BTA_GATTC_W4_CONN_ST},
@@ -236,7 +236,7 @@
 /* BTA_GATTC_API_READ_MULTI_EVT     */   {BTA_GATTC_Q_CMD,              BTA_GATTC_DISCOVER_ST},
 /* BTA_GATTC_API_REFRESH_EVT        */   {BTA_GATTC_IGNORE,             BTA_GATTC_DISCOVER_ST},
 
-/* BTA_GATTC_INT_CONN_EVT           */   {BTA_GATTC_IGNORE,             BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_INT_CONN_EVT           */   {BTA_GATTC_CONN,               BTA_GATTC_DISCOVER_ST},
 /* BTA_GATTC_INT_DISCOVER_EVT       */   {BTA_GATTC_RESTART_DISCOVER,   BTA_GATTC_DISCOVER_ST},
 /* BTA_GATTC_DISCOVER_CMPL_EVT      */   {BTA_GATTC_DISC_CMPL,          BTA_GATTC_CONN_ST},
 /* BTA_GATTC_OP_CMPL_EVT            */   {BTA_GATTC_IGNORE_OP_CMPL,     BTA_GATTC_DISCOVER_ST},
@@ -382,14 +382,20 @@
             break;
 
         default:
-            if ((p_clcb = bta_gattc_find_clcb_by_conn_id(p_msg->layer_specific))
-                != NULL)
+            if (p_msg->event == BTA_GATTC_INT_CONN_EVT)
+                p_clcb = bta_gattc_find_int_conn_clcb((tBTA_GATTC_DATA *) p_msg);
+            else if (p_msg->event == BTA_GATTC_INT_DISCONN_EVT)
+                p_clcb = bta_gattc_find_int_disconn_clcb((tBTA_GATTC_DATA *) p_msg);
+            else
+                p_clcb = bta_gattc_find_clcb_by_conn_id(p_msg->layer_specific);
+
+            if (p_clcb != NULL)
             {
                 bta_gattc_sm_execute(p_clcb, p_msg->event, (tBTA_GATTC_DATA *) p_msg);
             }
             else
             {
-                APPL_TRACE_ERROR1("Unknown conn ID: %d", p_msg->layer_specific);
+                APPL_TRACE_DEBUG1("Ignore unknown conn ID: %d", p_msg->layer_specific);
             }
 
             break;
@@ -468,8 +474,6 @@
             return "BTA_GATTC_API_REFRESH_EVT";
         case BTA_GATTC_API_DISABLE_EVT:
             return "BTA_GATTC_API_DISABLE_EVT";
-        case BTA_GATTC_API_ENABLE_EVT:
-            return "BTA_GATTC_API_ENABLE_EVT";
         default:
             return "unknown GATTC event code";
     }
diff --git a/bta/gatt/bta_gattc_utils.c b/bta/gatt/bta_gattc_utils.c
index 4749f21..151b7ba 100644
--- a/bta/gatt/bta_gattc_utils.c
+++ b/bta/gatt/bta_gattc_utils.c
@@ -31,6 +31,7 @@
 #include "gki.h"
 #include "bta_sys.h"
 #include "bta_gattc_int.h"
+#include "l2c_api.h"
 #include "bd.h"
 
 /*****************************************************************************
@@ -41,6 +42,8 @@
 static const UINT8  base_uuid[LEN_UUID_128] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
     0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 
+static const BD_ADDR dummy_bda = {0,0,0,0,0,0};
+
 /*******************************************************************************
 **
 ** Function         bta_gatt_convert_uuid16_to_uuid128
@@ -67,13 +70,13 @@
 ** Returns          TRUE if two uuid match; FALSE otherwise.
 **
 *******************************************************************************/
-BOOLEAN bta_gattc_uuid_compare (tBT_UUID src, tBT_UUID tar, BOOLEAN is_precise)
+BOOLEAN bta_gattc_uuid_compare (tBT_UUID *p_src, tBT_UUID *p_tar, BOOLEAN is_precise)
 {
     UINT8  su[LEN_UUID_128], tu[LEN_UUID_128];
     UINT8  *ps, *pt;
 
     /* any of the UUID is unspecified */
-    if (src.len == 0 || tar.len == 0)
+    if (p_src == 0 || p_tar == 0)
     {
         if (is_precise)
             return FALSE;
@@ -82,29 +85,29 @@
     }
 
     /* If both are 16-bit, we can do a simple compare */
-    if (src.len == 2 && tar.len == 2)
+    if (p_src->len == 2 && p_tar->len == 2)
     {
-        return src.uu.uuid16 == tar.uu.uuid16;
+        return p_src->uu.uuid16 == p_tar->uu.uuid16;
     }
 
     /* One or both of the UUIDs is 128-bit */
-    if (src.len == LEN_UUID_16)
+    if (p_src->len == LEN_UUID_16)
     {
         /* convert a 16 bits UUID to 128 bits value */
-        bta_gatt_convert_uuid16_to_uuid128(su, src.uu.uuid16);
+        bta_gatt_convert_uuid16_to_uuid128(su, p_src->uu.uuid16);
         ps = su;
     }
     else
-        ps = src.uu.uuid128;
+        ps = p_src->uu.uuid128;
 
-    if (tar.len == LEN_UUID_16)
+    if (p_tar->len == LEN_UUID_16)
     {
         /* convert a 16 bits UUID to 128 bits value */
-        bta_gatt_convert_uuid16_to_uuid128(tu, tar.uu.uuid16);
+        bta_gatt_convert_uuid16_to_uuid128(tu, p_tar->uu.uuid16);
         pt = tu;
     }
     else
-        pt = tar.uu.uuid128;
+        pt = p_tar->uu.uuid128;
 
     return(memcmp(ps, pt, LEN_UUID_128) == 0);
 }
@@ -276,15 +279,18 @@
 *******************************************************************************/
 void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB *p_clcb)
 {
-    tBTA_GATTC_SERV     *p_srcb = p_clcb->p_srcb;
+    tBTA_GATTC_SERV     *p_srcb = NULL;
 
     if (p_clcb)
     {
+        p_srcb = p_clcb->p_srcb;
         if (p_srcb->num_clcb)
             p_srcb->num_clcb --;
 
         if (p_clcb->p_rcb->num_clcb)
             p_clcb->p_rcb->num_clcb --;
+
+        /* if the srcb is no longer needed, reset the state */
         if ( p_srcb->num_clcb == 0)
         {
             p_srcb->connected = FALSE;
@@ -505,7 +511,7 @@
 BOOLEAN bta_gattc_gattid_compare(tBTA_GATT_ID *p_src, tBTA_GATT_ID *p_tar)
 {
     if (p_src->inst_id == p_tar->inst_id &&
-        bta_gattc_uuid_compare (p_src->uuid, p_tar->uuid, TRUE ))
+        bta_gattc_uuid_compare (&p_src->uuid, &p_tar->uuid, TRUE ))
         return TRUE;
     else
         return FALSE;
@@ -616,8 +622,10 @@
 ** Returns
 **
 *******************************************************************************/
-tBTA_GATT_STATUS bta_gattc_pack_read_cb_data(tBTA_GATTC_SERV *p_srcb, tBT_UUID descr_uuid,
-                                             tGATT_VALUE *p_attr, tBTA_GATT_READ_VAL *p_value)
+tBTA_GATT_STATUS bta_gattc_pack_read_cb_data(tBTA_GATTC_SERV *p_srcb,
+                                             tBT_UUID *p_descr_uuid,
+                                             tGATT_VALUE *p_attr,
+                                             tBTA_GATT_READ_VAL *p_value)
 {
     UINT8                   i = 0, *pp = p_attr->value;
     tBT_UUID                uuid = {LEN_UUID_16, {GATT_UUID_CHAR_AGG_FORMAT}};
@@ -625,7 +633,7 @@
     tBTA_GATT_STATUS        status = BTA_GATT_OK;
 
     /* GATT_UUID_CHAR_AGG_FORMAT */
-    if (bta_gattc_uuid_compare (uuid, descr_uuid, TRUE))
+    if (bta_gattc_uuid_compare (&uuid, p_descr_uuid, TRUE))
     {
         while (p_attr->len >= 2 && i < BTA_GATTC_MULTI_MAX)
         {
@@ -635,7 +643,7 @@
                                     handle,
                                     &p_value->aggre_value.pre_format[i].char_id.srvc_id,
                                     &p_value->aggre_value.pre_format[i].char_id.char_id,
-                                    &p_value->aggre_value.pre_format[i].descr_type) == FALSE)
+                                    &p_value->aggre_value.pre_format[i].descr_id) == FALSE)
             {
                 status = BTA_GATT_INTERNAL_ERROR;
                 APPL_TRACE_ERROR1("can not map to GATT ID. handle = 0x%04x", handle);
@@ -675,7 +683,7 @@
     {
         if (p_bg_tck->in_use &&
             ((remote_bda_ptr != NULL && bdcmp(p_bg_tck->remote_bda, remote_bda_ptr) == 0) ||
-            (remote_bda_ptr == NULL && bdcmp(p_bg_tck->remote_bda, bd_addr_null) == 0)))
+            (remote_bda_ptr == NULL && bdcmp(p_bg_tck->remote_bda, dummy_bda) == 0)))
         {
              p_cif_mask = is_listen ? &p_bg_tck->cif_adv_mask : &p_bg_tck->cif_mask;
 
@@ -713,7 +721,7 @@
                 if (remote_bda_ptr)
                     bdcpy(p_bg_tck->remote_bda, remote_bda_ptr);
                 else
-                    bdcpy(p_bg_tck->remote_bda, bd_addr_null);
+                    bdcpy(p_bg_tck->remote_bda, dummy_bda);
 
                 p_cif_mask = is_listen ? &p_bg_tck->cif_adv_mask : &p_bg_tck->cif_mask;
 
@@ -744,7 +752,7 @@
     {
         if (p_bg_tck->in_use &&
             (bdcmp(p_bg_tck->remote_bda, remote_bda) == 0 ||
-             bdcmp(p_bg_tck->remote_bda, bd_addr_null) == 0))
+             bdcmp(p_bg_tck->remote_bda, dummy_bda) == 0))
         {
             if (((p_bg_tck->cif_mask &(1 <<(client_if - 1))) != 0) &&
                 role == HCI_ROLE_MASTER)
@@ -882,4 +890,66 @@
     return FALSE;
 }
 
+/*******************************************************************************
+**
+** Function         bta_gattc_find_int_conn_clcb
+**
+** Description      try to locate a clcb when an internal connecion event arrives.
+**
+** Returns          pointer to the clcb
+**
+*******************************************************************************/
+tBTA_GATTC_CLCB * bta_gattc_find_int_conn_clcb(tBTA_GATTC_DATA *p_msg)
+{
+    tBTA_GATTC_CLCB *p_clcb = NULL;
+
+    if (p_msg->int_conn.role == HCI_ROLE_SLAVE)
+        bta_gattc_conn_find_alloc(p_msg->int_conn.remote_bda);
+
+    /* try to locate a logic channel */
+    if ((p_clcb = bta_gattc_find_clcb_by_cif(p_msg->int_conn.client_if,
+                                             p_msg->int_conn.remote_bda)) == NULL)
+    {
+        /* for a background connection or listening connection */
+        if (p_msg->int_conn.role == HCI_ROLE_SLAVE ||
+            bta_gattc_check_bg_conn(p_msg->int_conn.client_if,
+                                    p_msg->int_conn.remote_bda,
+                                    p_msg->int_conn.role))
+        {
+            /* allocate a new channel */
+            p_clcb = bta_gattc_clcb_alloc(p_msg->int_conn.client_if, p_msg->int_conn.remote_bda);
+        }
+    }
+    return p_clcb;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_find_int_disconn_clcb
+**
+** Description      try to locate a clcb when an internal disconnect callback arrives.
+**
+** Returns          pointer to the clcb
+**
+*******************************************************************************/
+tBTA_GATTC_CLCB * bta_gattc_find_int_disconn_clcb(tBTA_GATTC_DATA *p_msg)
+{
+    tBTA_GATTC_CLCB         *p_clcb = NULL;
+    tGATT_DISCONN_REASON    reason = p_msg->int_conn.reason;
+
+    bta_gattc_conn_dealloc(p_msg->int_conn.remote_bda);
+    /* connection attempt timeout, send connection callback event */
+    if (reason == GATT_CONN_CANCEL || reason == GATT_CONN_L2C_FAILURE)
+    {
+        p_clcb = bta_gattc_find_clcb_by_cif(p_msg->int_conn.client_if,
+                                            p_msg->int_conn.remote_bda);
+    }
+    else if ((p_clcb = bta_gattc_find_clcb_by_conn_id(p_msg->int_conn.hdr.layer_specific)) == NULL)
+    {
+        APPL_TRACE_DEBUG1("disconnection ID: [%d] not used by BTA",
+                           p_msg->int_conn.hdr.layer_specific);
+    }
+    return p_clcb;
+}
+
 #endif /* BTA_GATT_INCLUDED */
diff --git a/bta/gatt/bta_gatts_act.c b/bta/gatt/bta_gatts_act.c
index 244624d..dd7e1fc 100644
--- a/bta/gatt/bta_gatts_act.c
+++ b/bta/gatt/bta_gatts_act.c
@@ -589,9 +589,9 @@
 }
 /*******************************************************************************
 **
-** Function         bta_gatts_indicate_handle
+** Function         bta_gatts_send_rsp
 **
-** Description      GATTS send handle value indication or notification.
+** Description      GATTS send response.
 **
 ** Returns          none.
 **
@@ -612,7 +612,11 @@
 **
 ** Function         bta_gatts_indicate_handle
 **
+<<<<<<< HEAD
 ** Description      GATTS indicate handel value
+=======
+** Description      GATTS send handle value indication or notification.
+>>>>>>> 6ea30bf... LE: UPF 45 bug fixes
 **
 ** Returns          none.
 **
@@ -856,7 +860,12 @@
     {
         /* there is no RM for GATT */
         if (!BTM_IsBleLink(bda))
-            bta_sys_conn_open(BTA_ID_GATTS, BTA_ALL_APP_ID, bda);
+        {
+            if (connected)
+                bta_sys_conn_open(BTA_ID_GATTS, BTA_ALL_APP_ID, bda);
+            else
+                bta_sys_conn_close( BTA_ID_GATTS ,BTA_ALL_APP_ID, bda);
+        }
 
         cb_data.conn.conn_id = conn_id;
         cb_data.conn.server_if = gatt_if;
diff --git a/bta/include/bta_gatt_api.h b/bta/include/bta_gatt_api.h
index a63afb3..f052323 100644
--- a/bta/include/bta_gatt_api.h
+++ b/bta/include/bta_gatt_api.h
@@ -162,7 +162,7 @@
 typedef UINT8 tBTA_GATTC_WRITE_TYPE;
 
 #define BTA_GATT_CONN_UNKNOWN                   0
-#define BTA_GATT_CONN_NO_RESOURCES              GATT_CONN_NO_RESOURCES        /* connection fail for l2cap resource failure */
+#define BTA_GATT_CONN_L2C_FAILURE               GATT_CONN_L2C_FAILURE         /* general l2cap resource failure */
 #define BTA_GATT_CONN_TIMEOUT                   GATT_CONN_TIMEOUT             /* 0x08 connection timeout  */
 #define BTA_GATT_CONN_TERMINATE_PEER_USER       GATT_CONN_TERMINATE_PEER_USER /* 0x13 connection terminate by peer user  */
 #define BTA_GATT_CONN_TERMINATE_LOCAL_HOST      GATT_CONN_TERMINATE_LOCAL_HOST/* 0x16 connectionterminated by local host  */
@@ -187,7 +187,7 @@
 typedef struct
 {
     tBTA_GATTC_CHAR_ID      char_id;
-    tBT_UUID                descr_type;
+    tBTA_GATT_ID            descr_id;
 }tBTA_GATTC_CHAR_DESCR_ID;
 
 typedef struct
@@ -278,7 +278,7 @@
     tBTA_GATT_STATUS    status;
     tBTA_GATT_SRVC_ID   srvc_id;
     tBTA_GATT_ID        char_id;
-    tBT_UUID            descr_type;
+    tBTA_GATT_ID        descr_type;
     tBTA_GATT_READ_VAL  *p_value;
 }tBTA_GATTC_READ;
 
@@ -288,7 +288,7 @@
     tBTA_GATT_STATUS    status;
     tBTA_GATT_SRVC_ID   srvc_id;
     tBTA_GATT_ID        char_id;
-    tBT_UUID            descr_type;
+    tBTA_GATT_ID        descr_type;
 }tBTA_GATTC_WRITE;
 
 typedef struct
@@ -332,7 +332,7 @@
     UINT16              conn_id;
     BD_ADDR             bda;
     tBTA_GATTC_CHAR_ID  char_id;
-    tBT_UUID            descr_type;
+    tBTA_GATT_ID        descr_type;
     UINT16              len;
     UINT8               value[BTA_GATT_MAX_ATTR_LEN];
     BOOLEAN             is_notify;
diff --git a/btif/src/btif_gatt_client.c b/btif/src/btif_gatt_client.c
index f611c40..937f807 100644
--- a/btif/src/btif_gatt_client.c
+++ b/btif/src/btif_gatt_client.c
@@ -26,7 +26,6 @@
  *******************************************************************************/
 
 #include <hardware/bluetooth.h>
-#include <hardware/bt_gatt.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
@@ -40,6 +39,7 @@
 #if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
 
 #include "gki.h"
+#include <hardware/bt_gatt.h>
 #include "bta_api.h"
 #include "bta_gatt_api.h"
 #include "bd.h"
@@ -173,7 +173,7 @@
                         sizeof(tBTA_GATT_READ_VAL));
 
                     // Allocate buffer for att value if necessary
-                    if (get_uuid16(&p_src_data->read.descr_type) != GATT_UUID_CHAR_AGG_FORMAT
+                    if (get_uuid16(&p_src_data->read.descr_type.uuid) != GATT_UUID_CHAR_AGG_FORMAT
                       && p_src_data->read.p_value->unformat.len > 0
                       && p_src_data->read.p_value->unformat.p_value != NULL)
                     {
@@ -210,7 +210,7 @@
         case BTA_GATTC_READ_DESCR_EVT:
             if (p_data != NULL && p_data->read.p_value != NULL)
             {
-                if (get_uuid16 (&p_data->read.descr_type) != GATT_UUID_CHAR_AGG_FORMAT
+                if (get_uuid16 (&p_data->read.descr_type.uuid) != GATT_UUID_CHAR_AGG_FORMAT
                   && p_data->read.p_value->unformat.len > 0
                   && p_data->read.p_value->unformat.p_value != NULL)
                 {
@@ -386,7 +386,7 @@
             btgatt_write_params_t data;
             bta_to_btif_srvc_id(&data.srvc_id, &p_data->write.srvc_id);
             bta_to_btif_char_id(&data.char_id, &p_data->write.char_id);
-            bta_to_btif_uuid(&data.descr_id, &p_data->write.descr_type);
+            bta_to_btif_uuid(&data.descr_id, &p_data->write.descr_type.uuid);
 
             HAL_CBACK(bt_gatt_callbacks, client->write_descriptor_cb
                 , p_data->write.conn_id, p_data->write.status, &data);
@@ -422,11 +422,11 @@
             bt_bdaddr_t bda;
             bdcpy(bda.address, p_data->open.remote_bda);
 
-            if (p_data->open.status == BTA_GATT_OK)
-                btif_gatt_check_encrypted_link(p_data->open.remote_bda);
-
             HAL_CBACK(bt_gatt_callbacks, client->open_cb, p_data->open.conn_id
                 , p_data->open.status, p_data->open.client_if, &bda);
+
+            if (p_data->open.status == BTA_GATT_OK)
+                btif_gatt_check_encrypted_link(p_data->open.remote_bda);
             break;
         }
 
@@ -479,14 +479,14 @@
     btapp_gattc_free_req_data(event, p_data);
 }
 
-static void bte_gattc_cback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data)
+static void bta_gattc_cback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data)
 {
     bt_status_t status = btif_transfer_context(btif_gattc_upstreams_evt,
                     (uint16_t) event, (void*)p_data, sizeof(tBTA_GATTC), btapp_gattc_req_data);
     ASSERTC(status == BT_STATUS_SUCCESS, "Context transfer failed!", status);
 }
 
-static void bte_scan_results_cb (tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data)
+static void bta_scan_results_cb (tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data)
 {
     btif_gattc_cb_t btif_cb;
     uint8_t len;
@@ -552,6 +552,7 @@
     tBTA_GATTC_INCL_SVC_ID     in_incl_svc_id;
     tBTA_GATTC_INCL_SVC_ID     out_incl_svc_id;
     tBTA_GATT_UNFMT            descr_val;
+    static  UINT8              descr_inst = 0;
 
     btif_gattc_cb_t* p_cb = (btif_gattc_cb_t*)p_param;
     if (!p_cb) return;
@@ -562,7 +563,7 @@
     {
         case BTIF_GATTC_REGISTER_APP:
             btif_to_bta_uuid(&uuid, &p_cb->uuid);
-            BTA_GATTC_AppRegister(&uuid, bte_gattc_cback);
+            BTA_GATTC_AppRegister(&uuid, bta_gattc_cback);
             break;
 
         case BTIF_GATTC_UNREGISTER_APP:
@@ -571,7 +572,7 @@
 
         case BTIF_GATTC_SCAN_START:
             btif_gattc_init_dev_cb();
-            BTA_DmBleObserve(TRUE, 0, bte_scan_results_cb);
+            BTA_DmBleObserve(TRUE, 0, bta_scan_results_cb);
             break;
 
         case BTIF_GATTC_SCAN_STOP:
@@ -586,7 +587,7 @@
             break;
 
         case BTIF_GATTC_CLOSE:
-            // Disconnect establiched connections
+            // Disconnect established connections
             if (p_cb->conn_id != 0)
                 BTA_GATTC_Close(p_cb->conn_id);
             else
@@ -647,12 +648,13 @@
             bt_uuid_t descr_id;
             btif_to_bta_srvc_id(&in_char_id.srvc_id, &p_cb->srvc_id);
             btif_to_bta_char_id(&in_char_id.char_id, &p_cb->char_id);
+            descr_inst = 0;
 
             status = BTA_GATTC_GetFirstCharDescr(p_cb->conn_id, &in_char_id, NULL,
                                                     &out_char_descr_id);
 
             if (status == 0)
-                bta_to_btif_uuid(&descr_id, &out_char_descr_id.descr_type);
+                bta_to_btif_uuid(&descr_id, &out_char_descr_id.descr_id.uuid);
 
             HAL_CBACK(bt_gatt_callbacks, client->get_descriptor_cb,
                 p_cb->conn_id, status, &p_cb->srvc_id,
@@ -665,13 +667,15 @@
             bt_uuid_t descr_id;
             btif_to_bta_srvc_id(&in_char_descr_id.char_id.srvc_id, &p_cb->srvc_id);
             btif_to_bta_char_id(&in_char_descr_id.char_id.char_id, &p_cb->char_id);
-            btif_to_bta_uuid(&in_char_descr_id.descr_type, &p_cb->uuid);
+            btif_to_bta_uuid(&in_char_descr_id.descr_id.uuid, &p_cb->uuid);
+            in_char_descr_id.descr_id.inst_id = descr_inst; /* TODO: need app layer input */
+            descr_inst ++;
 
             status = BTA_GATTC_GetNextCharDescr(p_cb->conn_id, &in_char_descr_id
                                         , NULL, &out_char_descr_id);
 
             if (status == 0)
-                bta_to_btif_uuid(&descr_id, &out_char_descr_id.descr_type);
+                bta_to_btif_uuid(&descr_id, &out_char_descr_id.descr_id.uuid);
 
             HAL_CBACK(bt_gatt_callbacks, client->get_descriptor_cb,
                 p_cb->conn_id, status, &p_cb->srvc_id,
@@ -722,7 +726,8 @@
         case BTIF_GATTC_READ_CHAR_DESCR:
             btif_to_bta_srvc_id(&in_char_descr_id.char_id.srvc_id, &p_cb->srvc_id);
             btif_to_bta_char_id(&in_char_descr_id.char_id.char_id, &p_cb->char_id);
-            btif_to_bta_uuid(&in_char_descr_id.descr_type, &p_cb->uuid);
+            btif_to_bta_uuid(&in_char_descr_id.descr_id.uuid, &p_cb->uuid);
+            in_char_descr_id.descr_id.inst_id = 0; /* TODO: need app layer input */
 
             BTA_GATTC_ReadCharDescr(p_cb->conn_id, &in_char_descr_id, p_cb->auth_req);
             break;
@@ -741,7 +746,8 @@
         case BTIF_GATTC_WRITE_CHAR_DESCR:
             btif_to_bta_srvc_id(&in_char_descr_id.char_id.srvc_id, &p_cb->srvc_id);
             btif_to_bta_char_id(&in_char_descr_id.char_id.char_id, &p_cb->char_id);
-            btif_to_bta_uuid(&in_char_descr_id.descr_type, &p_cb->uuid);
+            btif_to_bta_uuid(&in_char_descr_id.descr_id.uuid, &p_cb->uuid);
+            in_char_descr_id.descr_id.inst_id = 0; /* TODO: need app layer input */
 
             descr_val.len = p_cb->len;
             descr_val.p_value = p_cb->value;
diff --git a/btif/src/btif_gatt_util.c b/btif/src/btif_gatt_util.c
index d07c737..252d221 100644
--- a/btif/src/btif_gatt_util.c
+++ b/btif/src/btif_gatt_util.c
@@ -228,9 +228,9 @@
     p_dest->status = p_src->status;
     bta_to_btif_srvc_id(&p_dest->srvc_id, &p_src->srvc_id);
     bta_to_btif_char_id(&p_dest->char_id, &p_src->char_id);
-    bta_to_btif_uuid(&p_dest->descr_id, &p_src->descr_type);
+    bta_to_btif_uuid(&p_dest->descr_id, &p_src->descr_type.uuid);
 
-    descr_type = get_uuid16(&p_src->descr_type);
+    descr_type = get_uuid16(&p_src->descr_type.uuid);
 
     switch (descr_type)
     {
diff --git a/stack/btm/btm_ble.c b/stack/btm/btm_ble.c
index 71e7d8c..ad5663f 100644
--- a/stack/btm/btm_ble.c
+++ b/stack/btm/btm_ble.c
@@ -309,6 +309,35 @@
 
 #endif
 }
+/*******************************************************************************
+**
+** Function         BTM_IsBleConnection
+**
+** Description      This function is called to check if the connection handle
+**                  for an LE link
+**
+** Returns          TRUE if connection is LE link, otherwise FALSE.
+**
+*******************************************************************************/
+BOOLEAN BTM_IsBleConnection (UINT16 conn_handle)
+{
+#if (BLE_INCLUDED == TRUE)
+    UINT8                xx;
+    tACL_CONN            *p;
+
+    BTM_TRACE_API1 ("BTM_IsBleConnection: conn_handle: %d", conn_handle);
+
+    xx = btm_handle_to_acl_index (conn_handle);
+    if (xx >= MAX_L2CAP_LINKS)
+        return FALSE;
+
+    p = &btm_cb.acl_db[xx];
+
+    return(p->is_le_link);
+#else
+    return FALSE;
+#endif
+}
 
 /*******************************************************************************
 **
@@ -327,7 +356,10 @@
     tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev(pseudo_addr);
 
     memcpy(conn_addr, pseudo_addr, BD_ADDR_LEN);
-    *p_addr_type = p_dev_rec->ble.ble_addr_type;
+    if (p_dev_rec != NULL)
+    {
+        *p_addr_type = p_dev_rec->ble.ble_addr_type;
+    }
 #endif
     return st;
 }
@@ -689,7 +721,35 @@
 #endif
         return FALSE;
 }
+/*******************************************************************************
+**
+** Function         BTM_UseLeLink
+**
+** Description      This function is to select the underneath physical link to use.
+**
+** Returns          TRUE to use LE, FALSE use BR/EDR.
+**
+*******************************************************************************/
+BOOLEAN BTM_UseLeLink (BD_ADDR bd_addr)
+{
+    tACL_CONN         *p;
+    tBT_DEVICE_TYPE     dev_type;
+    tBLE_ADDR_TYPE      addr_type;
+    BOOLEAN             use_le = FALSE;
 
+    if ((p = btm_bda_to_acl(bd_addr)) != NULL)
+    {
+#if (BLE_INCLUDED == TRUE)
+        use_le = (p->is_le_link);
+#endif
+    }
+    else
+    {
+        BTM_ReadDevInfo(bd_addr, &dev_type, &addr_type);
+        use_le = (dev_type == BT_DEVICE_TYPE_BLE);
+    }
+    return use_le;
+}
 /*******************************************************************************
 **
 ** Function         btm_ble_rand_enc_complete
@@ -1006,7 +1066,7 @@
 void btm_ble_link_sec_check(BD_ADDR bd_addr, tBTM_LE_AUTH_REQ auth_req, tBTM_BLE_SEC_REQ_ACT *p_sec_req_act)
 {
     tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
-    UINT8 req_sec_level, cur_sec_level;
+    UINT8 req_sec_level = BTM_LE_SEC_NONE, cur_sec_level = BTM_LE_SEC_NONE;
 
     BTM_TRACE_DEBUG1 ("btm_ble_link_sec_check auth_req =0x%x", auth_req);
 
@@ -1167,9 +1227,11 @@
 
     memcpy(p_cb->enc_rand, rand, BT_OCTET8_LEN);
 
-    if (!smp_proc_ltk_request(p_dev_rec->bd_addr))
-        btm_ble_ltk_request_reply(p_dev_rec->bd_addr, FALSE, dummy_stk);
-
+    if (p_dev_rec != NULL)
+    {
+        if (!smp_proc_ltk_request(p_dev_rec->bd_addr))
+            btm_ble_ltk_request_reply(p_dev_rec->bd_addr, FALSE, dummy_stk);
+    }
 
 }
 
@@ -1188,6 +1250,7 @@
     tBTM_CB *p_cb = &btm_cb;
     tBTM_SEC_DEV_REC    *p_rec = btm_find_dev (bda);
     BT_OCTET8    dummy_rand = {0};
+    BOOLEAN     rt = FALSE;
 
     BTM_TRACE_DEBUG0 ("btm_ble_start_encrypt");
 
@@ -1195,27 +1258,30 @@
         (p_rec && p_rec->sec_state == BTM_SEC_STATE_ENCRYPTING))
         return FALSE;
 
-    if (p_rec->sec_state == BTM_SEC_STATE_IDLE)
-        p_rec->sec_state = BTM_SEC_STATE_ENCRYPTING;
     p_cb->enc_handle = p_rec->hci_handle;
 
     if (use_stk)
     {
-        if (!btsnd_hcic_ble_start_enc(p_rec->hci_handle, dummy_rand, 0, stk))
-            return FALSE;
+        if (btsnd_hcic_ble_start_enc(p_rec->hci_handle, dummy_rand, 0, stk))
+            rt = TRUE;
     }
     else if (p_rec->ble.key_type & BTM_LE_KEY_PENC)
     {
-        if (!btsnd_hcic_ble_start_enc(p_rec->hci_handle, p_rec->ble.keys.rand,
+        if (btsnd_hcic_ble_start_enc(p_rec->hci_handle, p_rec->ble.keys.rand,
                                       p_rec->ble.keys.ediv, p_rec->ble.keys.ltk))
-            return FALSE;
+            rt = TRUE;
     }
     else
     {
-        return FALSE;
+        BTM_TRACE_ERROR0("No key available to encrypt the link");
+    }
+    if (rt)
+    {
+        if (p_rec->sec_state == BTM_SEC_STATE_IDLE)
+            p_rec->sec_state = BTM_SEC_STATE_ENCRYPTING;
     }
 
-    return TRUE;
+    return rt;
 }
 
 /*******************************************************************************
@@ -1519,6 +1585,9 @@
         if (status == HCI_ERR_DIRECTED_ADVERTISING_TIMEOUT)
             btm_ble_dir_adv_tout();
     }
+
+    btm_ble_set_conn_st(BLE_CONN_IDLE);
+
     btm_ble_update_mode_operation(role, bda, TRUE);
 }
 
@@ -1548,6 +1617,9 @@
             case SMP_OOB_REQ_EVT:
                 p_dev_rec->sec_flags |= BTM_SEC_LINK_KEY_AUTHED;
             case SMP_SEC_REQUEST_EVT:
+                memcpy (btm_cb.pairing_bda, bd_addr, BD_ADDR_LEN);
+                p_dev_rec->sec_state = BTM_SEC_STATE_AUTHENTICATING;
+                /* fall through */
             case SMP_COMPLT_EVT:
                 if (btm_cb.api.p_le_callback)
                 {
@@ -1575,7 +1647,7 @@
 #if BTM_BLE_CONFORMANCE_TESTING == TRUE
                     if (res != BTM_SUCCESS)
                     {
-                        if (!btm_cb.devcb.no_disc_if_pair_fail)
+                        if (!btm_cb.devcb.no_disc_if_pair_fail && p_data->cmplt.reason != SMP_CONN_TOUT)
                         {
                             BTM_TRACE_DEBUG0 ("Pairing failed - Remove ACL");
                             btm_remove_acl(bd_addr);
@@ -1587,7 +1659,7 @@
                         }
                     }
 #else
-                    if (res != BTM_SUCCESS)
+                    if (res != BTM_SUCCESS && p_data->cmplt.reason != SMP_CONN_TOUT)
                         btm_remove_acl(bd_addr);
 #endif
 
@@ -1600,6 +1672,7 @@
                                       btm_cb.pairing_bda[3], btm_cb.pairing_bda[4], btm_cb.pairing_bda[5]);
 
                     memset (btm_cb.pairing_bda, 0xff, BD_ADDR_LEN);
+                    btm_cb.pairing_state = BTM_PAIR_STATE_IDLE;
                     btm_cb.pairing_flags = 0;
                 }
                 break;
@@ -1665,6 +1738,7 @@
         if ((p_buf = (UINT8 *)GKI_getbuf((UINT16)(len + 4))) != NULL)
         {
             BTM_TRACE_DEBUG0("Start to generate Local CSRK");
+            pp = p_buf;
             /* prepare plain text */
             if (p_text)
             {
diff --git a/stack/btm/btm_ble_bgconn.c b/stack/btm/btm_ble_bgconn.c
index 3b8b1e2..727390c 100644
--- a/stack/btm/btm_ble_bgconn.c
+++ b/stack/btm/btm_ble_bgconn.c
@@ -62,29 +62,17 @@
 }
 /*******************************************************************************
 **
-** Function         btm_update_dev_to_white_list
+** Function         btm_add_dev_to_controller
 **
-** Description      This function adds a device into white list.
+** Description      This function load the device into controller white list
 *******************************************************************************/
-BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr, UINT8 attr)
+BOOLEAN btm_add_dev_to_controller (BOOLEAN to_add, BD_ADDR bd_addr, UINT8 attr)
 {
-    /* look up the sec device record, and find the address */
-    tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
     tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_dev (bd_addr);
-    BD_ADDR             dummy_bda = {0};
-    BOOLEAN             started = FALSE;
-    UINT8       wl_state = p_cb->wl_state;
-    tBT_DEVICE_TYPE dev_type;
     tBLE_ADDR_TYPE  addr_type = BLE_ADDR_PUBLIC;
-
-    if ((to_add && p_cb->num_empty_filter == 0) ||
-        (!to_add && p_cb->num_empty_filter == p_cb->max_filter_entries))
-    {
-        BTM_TRACE_ERROR1("WL full or empty, unable to update to WL. num_entry available: %d", p_cb->num_empty_filter);
-        return started;
-    }
-
-    btm_suspend_wl_activity(wl_state);
+    BOOLEAN             started = FALSE;
+    BD_ADDR             dummy_bda = {0};
+    tBT_DEVICE_TYPE dev_type;
 
     if (p_dev_rec != NULL &&
         p_dev_rec->device_type == BT_DEVICE_TYPE_BLE)
@@ -92,7 +80,7 @@
 
         if (to_add)
         {
-            if (!BTM_BLE_IS_RESOLVE_BDA(bd_addr))
+            if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_PUBLIC || !BTM_BLE_IS_RESOLVE_BDA(bd_addr))
             {
                 started = btsnd_hcic_ble_add_white_list (p_dev_rec->ble.ble_addr_type, bd_addr);
             }
@@ -108,7 +96,8 @@
             {
                     started = btsnd_hcic_ble_remove_from_white_list (p_dev_rec->ble.ble_addr_type, bd_addr);
             }
-            if (memcmp(p_dev_rec->ble.static_addr, dummy_bda, BD_ADDR_LEN) != 0)
+            if (memcmp(p_dev_rec->ble.static_addr, dummy_bda, BD_ADDR_LEN) != 0 &&
+                memcmp(p_dev_rec->ble.static_addr, bd_addr, BD_ADDR_LEN) != 0)
             {
                     started = btsnd_hcic_ble_remove_from_white_list (p_dev_rec->ble.static_addr_type, p_dev_rec->ble.static_addr);
             }
@@ -117,12 +106,101 @@
     else
     {
         BTM_ReadDevInfo(bd_addr, &dev_type, &addr_type);
+
         if (to_add)
             started = btsnd_hcic_ble_add_white_list (addr_type, bd_addr);
         else
             started = btsnd_hcic_ble_remove_from_white_list (addr_type, bd_addr);
     }
 
+    return started;
+
+}
+/*******************************************************************************
+**
+** Function         btm_execute_wl_dev_operation
+**
+** Description      execute the pending whitelist device operation(loading or removing)
+*******************************************************************************/
+BOOLEAN btm_execute_wl_dev_operation(void)
+{
+    tBTM_BLE_WL_OP *p_dev_op = btm_cb.ble_ctr_cb.wl_op_q;
+    UINT8   i = 0;
+    BOOLEAN rt = TRUE;
+
+    for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM && rt; i ++, p_dev_op ++)
+    {
+        if (p_dev_op->in_use)
+        {
+            rt = btm_add_dev_to_controller(p_dev_op->to_add, p_dev_op->bd_addr, p_dev_op->attr);
+            memset(p_dev_op, 0, sizeof(tBTM_BLE_WL_OP));
+        }
+        else
+            break;
+    }
+    return rt;
+}
+/*******************************************************************************
+**
+** Function         btm_enq_wl_dev_operation
+**
+** Description      enqueue the pending whitelist device operation(loading or removing).
+*******************************************************************************/
+void btm_enq_wl_dev_operation(BOOLEAN to_add, BD_ADDR bd_addr, UINT8 attr)
+{
+    tBTM_BLE_WL_OP *p_dev_op = btm_cb.ble_ctr_cb.wl_op_q;
+    UINT8   i = 0;
+
+    for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM; i ++, p_dev_op ++)
+    {
+        if (p_dev_op->in_use && !memcmp(p_dev_op->bd_addr, bd_addr, BD_ADDR_LEN))
+        {
+            p_dev_op->to_add = to_add;
+            p_dev_op->attr = attr;
+            return;
+        }
+        else if (!p_dev_op->in_use)
+            break;
+    }
+    if (i != BTM_BLE_MAX_BG_CONN_DEV_NUM)
+    {
+        p_dev_op->in_use = TRUE;
+        p_dev_op->to_add = to_add;
+        p_dev_op->attr  = attr;
+        memcpy(p_dev_op->bd_addr, bd_addr, BD_ADDR_LEN);
+    }
+    else
+    {
+        BTM_TRACE_ERROR0("max pending WL operation reached, discard");
+    }
+    return;
+}
+/*******************************************************************************
+**
+** Function         btm_update_dev_to_white_list
+**
+** Description      This function adds a device into white list.
+*******************************************************************************/
+BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr, UINT8 attr)
+{
+    /* look up the sec device record, and find the address */
+    tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
+    BOOLEAN     started = FALSE;
+    UINT8       wl_state = p_cb->wl_state;
+
+    if ((to_add && p_cb->num_empty_filter == 0) ||
+        (!to_add && p_cb->num_empty_filter == p_cb->max_filter_entries))
+    {
+        BTM_TRACE_ERROR1("WL full or empty, unable to update to WL. num_entry available: %d",
+                          p_cb->num_empty_filter);
+        return started;
+    }
+
+    btm_suspend_wl_activity(wl_state);
+
+    /* enq pending WL device operation */
+    btm_enq_wl_dev_operation(to_add, bd_addr, attr);
+
     btm_resume_wl_activity(wl_state);
 
     return started;
@@ -217,7 +295,6 @@
 *******************************************************************************/
 BOOLEAN btm_update_bg_conn_list(BOOLEAN to_add, BD_ADDR bd_addr, UINT8 *p_attr_tag)
 {
-    UINT8                   white_list_type = *p_attr_tag;
     tBTM_BLE_CB             *p_cb = &btm_cb.ble_ctr_cb;
     tBTM_LE_BG_CONN_DEV     *p_bg_dev = &p_cb->bg_dev_list[0], *p_next, *p_cur;
     UINT8                   i, j;
@@ -235,12 +312,7 @@
     {
         if (p_bg_dev->in_use && memcmp(p_bg_dev->bd_addr, bd_addr, BD_ADDR_LEN) == 0)
         {
-            if (to_add)
-                p_bg_dev->attr |= white_list_type;
-            else
-                p_bg_dev->attr &=  ~white_list_type;
-
-            if (p_bg_dev->attr == 0)
+            if (!to_add)
             {
                 memset(p_bg_dev, 0, sizeof(tBTM_LE_BG_CONN_DEV));
                 p_cb->bg_dev_num --;
@@ -258,7 +330,6 @@
 
             memcpy(p_bg_dev->bd_addr, bd_addr, BD_ADDR_LEN);
             p_bg_dev->in_use = TRUE;
-            p_bg_dev->attr |= white_list_type;
             p_cb->bg_dev_num ++;
 
             ret = TRUE;
@@ -266,8 +337,6 @@
         }
     }
 
-    if (i != BTM_BLE_MAX_BG_CONN_DEV_NUM)
-        *p_attr_tag = p_bg_dev->attr;
 
     return ret;
 }
@@ -295,6 +364,7 @@
     {
         if (p_cb->conn_state == BLE_CONN_IDLE && btm_ble_count_unconn_dev_in_whitelist() > 0)
         {
+            btm_execute_wl_dev_operation();
 
             scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_SLOW_INT_1 : p_cb->scan_int;
             scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_SLOW_WIN_1 : p_cb->scan_win;
@@ -317,7 +387,7 @@
             }
             else
             {
-                p_cb->conn_state = BLE_BG_CONN;
+                btm_ble_set_conn_st (BLE_BG_CONN);
 
             }
         }
@@ -331,7 +401,7 @@
         if (p_cb->conn_state == BLE_BG_CONN)
         {
             btsnd_hcic_ble_create_conn_cancel();
-            p_cb->conn_state = BLE_CONN_IDLE;
+            btm_ble_set_conn_st (BLE_CONN_CANCEL); 
 
         }
         else
@@ -417,11 +487,9 @@
 
         btm_update_scanner_filter_policy(SP_ADV_ALL);
         /* stop scanning */
-        if (p_cb->bg_dev_num > 0)
-        {
             if (!btsnd_hcic_ble_set_scan_enable(FALSE, TRUE)) /* duplicate filtering enabled */
                 return FALSE;
-        }
+        btm_update_scanner_filter_policy(SP_ADV_ALL);
     }
     return TRUE;
 }
diff --git a/stack/btm/btm_ble_gap.c b/stack/btm/btm_ble_gap.c
index 7cef5f2..387f661 100644
--- a/stack/btm/btm_ble_gap.c
+++ b/stack/btm/btm_ble_gap.c
@@ -363,8 +363,7 @@
 BOOLEAN BTM_BleUpdateBgConnDev(BOOLEAN add_remove, BD_ADDR   remote_bda)
 {
     BOOLEAN ret = TRUE;
-    UINT8   dev_wl_type = BTM_BLE_WL_INIT;
-
+    UINT8   dev_wl_type = 0;
     BTM_TRACE_EVENT0 (" BTM_BleUpdateBgConnDev");
 
     /* update white list */
@@ -2033,10 +2032,6 @@
         btm_ble_set_connectability ( btm_cb.ble_ctr_cb.inq_var.connectable_mode );
     }
 
-    /* if connection complete */
-    if (conn_cancel || link_role != HCI_ROLE_UNKNOWN)
-        btm_ble_set_conn_st(BLE_CONN_IDLE);
-
     if (btm_ble_get_conn_st() == BLE_CONN_IDLE)
     {
         if (!btm_send_pending_direct_conn())
@@ -2074,7 +2069,7 @@
     /* for background connection, reset connection params to be undefined */
     p_cb->scan_int = p_cb->scan_win = BTM_BLE_CONN_PARAM_UNDEF;
 
-    p_cb->inq_var.evt_type = BTM_BLE_UNKNOWN_EVT;
+    p_cb->inq_var.evt_type = BTM_BLE_NON_CONNECT_EVT;
 }
 
 #endif  /* BLE_INCLUDED */
diff --git a/stack/btm/btm_ble_int.h b/stack/btm/btm_ble_int.h
index 2b17610..4aeab19 100644
--- a/stack/btm/btm_ble_int.h
+++ b/stack/btm/btm_ble_int.h
@@ -190,12 +190,22 @@
 #define BLE_CONN_IDLE    0
 #define BLE_DIR_CONN     1
 #define BLE_BG_CONN      2
+#define BLE_CONN_CANCEL  3
 typedef UINT8 tBTM_BLE_CONN_ST;
 
 typedef struct
 {
     void    *p_param;
 }tBTM_BLE_CONN_REQ;
+
+
+typedef struct
+{
+    BOOLEAN     in_use;
+    BOOLEAN     to_add;
+    BD_ADDR     bd_addr;
+    UINT8       attr;
+}tBTM_BLE_WL_OP;
 /* Define BLE Device Management control structure
 */
 typedef struct
@@ -226,12 +236,12 @@
     tBTM_LE_RANDOM_CB   addr_mgnt_cb;
 
     BOOLEAN          enabled;
+    tBTM_BLE_WL_OP  wl_op_q[BTM_BLE_MAX_BG_CONN_DEV_NUM];
 
 #ifdef BTM_BLE_PC_ADV_TEST_MODE
     tBTM_BLE_SCAN_REQ_CBACK *p_scan_req_cback;
 #endif
 
-    BOOLEAN         scatternet_enable;
 } tBTM_BLE_CB;
 
 #ifdef __cplusplus
diff --git a/stack/btm/btm_inq.c b/stack/btm/btm_inq.c
index d67f4d4..b1d9eac 100644
--- a/stack/btm/btm_inq.c
+++ b/stack/btm/btm_inq.c
@@ -968,11 +968,6 @@
     tBTM_INQ_INFO   *p_cur = NULL;
     tINQ_DB_ENT     *p_i;
 
-#if BLE_INCLUDED == TRUE
-    tBT_DEVICE_TYPE dev_type;
-    tBLE_ADDR_TYPE  addr_type;
-#endif
-
     BTM_TRACE_API6 ("BTM_ReadRemoteDeviceName: bd addr [%02x%02x%02x%02x%02x%02x]",
                remote_bda[0], remote_bda[1], remote_bda[2],
                remote_bda[3], remote_bda[4], remote_bda[5]);
@@ -989,8 +984,7 @@
     BTM_TRACE_API0 ("no device found in inquiry db");
 
 #if (BLE_INCLUDED == TRUE)
-    BTM_ReadDevInfo(remote_bda, &dev_type, &addr_type);
-    if (dev_type == BT_DEVICE_TYPE_BLE)
+    if (BTM_UseLeLink(remote_bda))
     {
         return btm_ble_read_remote_name(remote_bda, p_cur, p_cb);
     }
@@ -1021,19 +1015,13 @@
 {
     tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
 
-#if BLE_INCLUDED == TRUE
-    tBT_DEVICE_TYPE dev_type;
-    tBLE_ADDR_TYPE  addr_type;
-#endif
-
     BTM_TRACE_API0 ("BTM_CancelRemoteDeviceName()");
 
     /* Make sure there is not already one in progress */
     if (p_inq->remname_active)
     {
 #if BLE_INCLUDED == TRUE
-        BTM_ReadDevInfo(p_inq->remname_bda, &dev_type, &addr_type);
-        if (dev_type == BT_DEVICE_TYPE_BLE)
+        if (BTM_UseLeLink(p_inq->remname_bda))
         {
             if (btm_ble_cancel_remote_name(p_inq->remname_bda))
                 return (BTM_CMD_STARTED);
@@ -2533,11 +2521,6 @@
     UINT8                  *p_n;
     tBTM_INQ_INFO          *p_cur;
 #endif
-#if BLE_INCLUDED == TRUE
-    tBT_DEVICE_TYPE     dev_type;
-    tBLE_ADDR_TYPE      addr_type;
-#endif
-
 
     if (bda != NULL)
     {
@@ -2559,8 +2542,7 @@
 
 	{
 #if BLE_INCLUDED == TRUE
-        BTM_ReadDevInfo(p_inq->remname_bda, &dev_type, &addr_type);
-        if (dev_type == BT_DEVICE_TYPE_BLE)
+        if (BTM_UseLeLink(p_inq->remname_bda))
         {
             if (hci_status == HCI_ERR_UNSPECIFIED)
                 btm_ble_cancel_remote_name(p_inq->remname_bda);
@@ -2658,8 +2640,7 @@
             {
                 p_cur->remote_name_state = BTM_INQ_RMT_NAME_PENDING;
 #if (BLE_INCLUDED == TRUE)
-                BTM_ReadDevInfo(remote_bda, &dev_type, &addr_type);
-                if (dev_type == BT_DEVICE_TYPE_BLE)
+                if (BTM_UseLeLink(remote_bda))
                 {
                     if (btm_ble_read_remote_name(remote_bda, p_cur, p_cb) != BTM_CMD_STARTED)
                         p_cur->remote_name_state = BTM_INQ_RMT_NAME_FAILED;
diff --git a/stack/btm/btm_sec.c b/stack/btm/btm_sec.c
index 402f81f..8bcf435 100644
--- a/stack/btm/btm_sec.c
+++ b/stack/btm/btm_sec.c
@@ -44,9 +44,10 @@
 BOOLEAN (APPL_AUTH_WRITE_EXCEPTION)(BD_ADDR bd_addr);
 #endif
 
-/********************************************************************************/
-/*              L O C A L    F U N C T I O N     P R O T O T Y P E S            */
-/********************************************************************************/
+
+/********************************************************************************
+**              L O C A L    F U N C T I O N     P R O T O T Y P E S            *
+*********************************************************************************/
 static tBTM_SEC_SERV_REC *btm_sec_find_first_serv (BOOLEAN is_originator, UINT16 psm);
 static tBTM_SEC_SERV_REC *btm_sec_find_next_serv (tBTM_SEC_SERV_REC *p_cur);
 static tBTM_SEC_SERV_REC *btm_sec_find_mx_serv (UINT8 is_originator, UINT16 psm,
@@ -1051,12 +1052,7 @@
     tBTM_STATUS      status;
     UINT8            *p_features;
     UINT8            ii;
-#if SMP_INCLUDED == TRUE
-    tACL_CONN   *p=NULL;
-    BOOLEAN     is_le_slave_role=FALSE;
-    tBT_DEVICE_TYPE     dev_type;
-    tBLE_ADDR_TYPE      addr_type;
-#endif
+
     BTM_TRACE_API6 ("BTM_SecBond BDA: %02x:%02x:%02x:%02x:%02x:%02x",
                     bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);
 
@@ -1067,47 +1063,13 @@
         return(BTM_WRONG_MODE);
     }
 
+    if ((p_dev_rec = btm_find_or_alloc_dev (bd_addr)) == NULL)
+    {
+        return(BTM_NO_RESOURCES);
+        }
 
-    p_dev_rec = btm_find_or_alloc_dev (bd_addr);
     BTM_TRACE_DEBUG1 ("before update sec_flags=0x%x", p_dev_rec->sec_flags);
 
-
-#if SMP_INCLUDED == TRUE
-    p = btm_bda_to_acl(bd_addr);
-    if (p && p->is_le_link )
-    {
-        if (p_dev_rec->sec_state == BTM_SEC_STATE_AUTHENTICATING)
-        {
-            BTM_TRACE_ERROR1 ("BTM_SecBond: LE already busy in state: %x", p_dev_rec->sec_state );
-            return(BTM_WRONG_MODE);
-        }
-
-        if (p->link_role == BTM_ROLE_SLAVE)
-        {
-            is_le_slave_role = TRUE;
-            BTM_TRACE_DEBUG0 ("LE Link Slave" );
-        }
-        else
-        {
-            BTM_TRACE_DEBUG0 ("LE Link Maste" );
-        }
-    }
-    else
-    {
-        BTM_TRACE_DEBUG0 ("No LE Link" );
-    }
-
-    if (!is_le_slave_role)
-    {
-        /* Finished if connection is active and already paired */
-        if ( (p_dev_rec->hci_handle != BTM_SEC_INVALID_HANDLE)
-             &&  (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED) )
-        {
-            BTM_TRACE_WARNING0("BTM_SecBond -> Already Paired");
-            return(BTM_SUCCESS);
-        }
-    }
-#else
     /* Finished if connection is active and already paired */
     if ( (p_dev_rec->hci_handle != BTM_SEC_INVALID_HANDLE)
          &&  (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED) )
@@ -1115,7 +1077,6 @@
         BTM_TRACE_WARNING0("BTM_SecBond -> Already Paired");
         return(BTM_SUCCESS);
     }
-#endif
 
     /* Tell controller to get rid of the link key if it has one stored */
     if ((BTM_DeleteStoredLinkKey (bd_addr, NULL)) != BTM_SUCCESS)
@@ -1137,32 +1098,23 @@
     if (trusted_mask)
         BTM_SEC_COPY_TRUSTED_DEVICE(trusted_mask, p_dev_rec->trusted_mask);
 
-
-
-#if SMP_INCLUDED == TRUE
-
-    if (!is_le_slave_role)
-    {
-        p_dev_rec->sec_flags &= ~(BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED
+    p_dev_rec->sec_flags &= ~(BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED
                                   | BTM_SEC_ROLE_SWITCHED  | BTM_SEC_LINK_KEY_AUTHED);
 
-    }
 
-    BTM_ReadDevInfo(bd_addr, &dev_type, &addr_type);
+#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
     /* LE device, do SMP pairing */
-    if (dev_type == BT_DEVICE_TYPE_BLE)
+    if (BTM_UseLeLink(bd_addr))
     {
         if (SMP_Pair(bd_addr) == SMP_STARTED)
         {
+            btm_cb.pairing_state = BTM_PAIR_STATE_WAIT_AUTH_COMPLETE;
             p_dev_rec->sec_state = BTM_SEC_STATE_AUTHENTICATING;
             return BTM_CMD_STARTED;
         }
         else
             return(BTM_NO_RESOURCES);
     }
-#else
-    p_dev_rec->sec_flags &= ~(BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED
-                              | BTM_SEC_ROLE_SWITCHED  | BTM_SEC_LINK_KEY_AUTHED);
 #endif
 
     BTM_TRACE_DEBUG1 ("after update sec_flags=0x%x", p_dev_rec->sec_flags);
@@ -1180,9 +1132,6 @@
         }
     }
 
-    BTM_TRACE_EVENT1("BTM_SecBond: Local device supports SSP=%d",
-            HCI_SIMPLE_PAIRING_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]));
-
     for (ii = 0; ii <= HCI_EXT_FEATURES_PAGE_MAX; ii++)
     {
         p_features = p_dev_rec->features[ii];
diff --git a/stack/gap/gap_ble.c b/stack/gap/gap_ble.c
index 19e24a9..6e3afeb 100644
--- a/stack/gap/gap_ble.c
+++ b/stack/gap/gap_ble.c
@@ -15,7 +15,6 @@
  *  limitations under the License.
  *
  ******************************************************************************/
-
 #include "bt_target.h"
 
 #if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
@@ -585,9 +584,6 @@
     p_clcb->cl_op_uuid = 0;
     p_clcb->p_cback=NULL;
 
-    if (!gap_ble_process_pending_op(p_clcb) && op != 0)
-        GATT_Disconnect(p_clcb->conn_id);
-
     if (p_dev_name_cback)
     {
         GAP_TRACE_EVENT0("calling gap_ble_cl_op_cmpl");
@@ -596,6 +592,10 @@
             (* p_dev_name_cback)(status, p_clcb->bda, len, (char *)p_name);
     }
 
+    if (!gap_ble_process_pending_op(p_clcb) &&
+        p_clcb->cl_op_uuid == 0)
+        GATT_Disconnect(p_clcb->conn_id);
+
 }
 
 /*******************************************************************************
@@ -779,16 +779,17 @@
 *******************************************************************************/
 BOOLEAN GAP_BleReadPeerPrefConnParams (BD_ADDR peer_bda)
 {
-    tGAP_CLCB   *p_clcb;
 
+    tGAP_CLCB   *p_clcb = gap_find_clcb_by_bd_addr (peer_bda);
 
-    /* This function should only be called if there is a connection to  */
-    /* the peer. Get a client handle for that connection.               */
-    if ((p_clcb = gap_find_clcb_by_bd_addr (peer_bda)) == NULL ||
-        !p_clcb->connected)
+    if (p_clcb == NULL)
     {
-        GAP_TRACE_ERROR0("No connection, can not update reconnect address");
-        return(FALSE);
+        if ((p_clcb = gap_clcb_alloc(0, peer_bda)) == NULL)
+        {
+            GAP_TRACE_ERROR0("GAP_BleReadPeerPrefConnParams max connection reached");
+            return FALSE;
+        }
+        p_clcb->connected = FALSE;
     }
 
     GAP_TRACE_API3 ("GAP_BleReadPeerPrefConnParams() - BDA: %08x%04x  cl_op_uuid: 0x%04x",
@@ -799,7 +800,18 @@
     if (p_clcb->cl_op_uuid != 0)
         return(FALSE);
 
+    /* hold the link here */
+    GATT_Connect(gap_cb.gatt_if, p_clcb->bda, TRUE);
+
+    if (p_clcb->connected)
+    {
     return gap_ble_cl_read_request(p_clcb, GATT_UUID_GAP_PREF_CONN_PARAM, NULL);
+    }
+    /* Mark currently active operation */
+    p_clcb->cl_op_uuid = GATT_UUID_GAP_PREF_CONN_PARAM;
+
+    return(TRUE);
+
 
 }
 
@@ -814,22 +826,20 @@
 *******************************************************************************/
 BOOLEAN GAP_BleReadPeerDevName (BD_ADDR peer_bda, tGAP_BLE_DEV_NAME_CBACK *p_cback)
 {
-    tGAP_CLCB   *p_clcb = gap_find_clcb_by_bd_addr (peer_bda);
+    tGAP_CLCB   *p_clcb = NULL;
 
     if (p_cback == NULL)
         return(FALSE);
 
-    if (p_clcb == NULL)
+    if ((p_clcb = gap_find_clcb_by_bd_addr (peer_bda)) == NULL)
     {
-        p_clcb = gap_clcb_alloc(0, peer_bda);
-        p_clcb->connected = FALSE;
-    }
-
-    if (p_clcb == NULL)
+        if ((p_clcb = gap_clcb_alloc(0, peer_bda)) == NULL)
     {
         GAP_TRACE_ERROR0("GAP_BleReadPeerDevName max connection reached");
+            return FALSE;
     }
-
+        p_clcb->connected = FALSE;
+    }
 
     GAP_TRACE_EVENT3 ("GAP_BleReadPeerDevName() - BDA: %08x%04x  cl_op_uuid: 0x%04x",
                       (peer_bda[0]<<24)+(peer_bda[1]<<16)+(peer_bda[2]<<8)+peer_bda[3],
diff --git a/stack/gatt/gatt_api.c b/stack/gatt/gatt_api.c
index 91eca96..a96c58a 100644
--- a/stack/gatt/gatt_api.c
+++ b/stack/gatt/gatt_api.c
@@ -1537,7 +1537,7 @@
 **                   bd_addr: peer device address. (input)
 **                   p_conn_id: connection id  (output)
 **
-** Returns          TRUE the ligical link is connected
+** Returns          TRUE the logical link is connected
 **
 *******************************************************************************/
 BOOLEAN GATT_GetConnIdIfConnected(tGATT_IF gatt_if, BD_ADDR bd_addr, UINT16 *p_conn_id)
diff --git a/stack/gatt/gatt_auth.c b/stack/gatt/gatt_auth.c
index ab74001..504b7d8 100644
--- a/stack/gatt/gatt_auth.c
+++ b/stack/gatt/gatt_auth.c
@@ -316,7 +316,7 @@
     if (auth_req == GATT_AUTH_REQ_NONE )
         return act;
 
-    is_le_link = BTM_IsBleLink(p_tcb->peer_bda);
+    is_le_link = BTM_UseLeLink(p_tcb->peer_bda);
     BTM_GetSecurityFlags(p_tcb->peer_bda, &sec_flag);
     btm_ble_link_sec_check(p_tcb->peer_bda, auth_req, &sec_act);
 
diff --git a/stack/gatt/gatt_cl.c b/stack/gatt/gatt_cl.c
index e9402aa..b6dc9d8 100644
--- a/stack/gatt/gatt_cl.c
+++ b/stack/gatt/gatt_cl.c
@@ -73,6 +73,7 @@
 {
     UINT8       op_code = disc_type_to_att_opcode[p_clcb->op_subtype];
     tGATT_CL_MSG   cl_req;
+    tGATT_STATUS    st;
 
     if (p_clcb->s_handle <= p_clcb->e_handle && p_clcb->s_handle != 0)
     {
@@ -97,7 +98,9 @@
             memcpy (cl_req.find_type_value.value,  &p_clcb->uuid.uu, p_clcb->uuid.len);
         }
 
-        if (attp_send_cl_msg(p_clcb->p_tcb, p_clcb->clcb_idx, op_code, &cl_req) !=  GATT_SUCCESS)
+        st = attp_send_cl_msg(p_clcb->p_tcb, p_clcb->clcb_idx, op_code, &cl_req);
+
+        if (st !=  GATT_SUCCESS && st != GATT_CMD_STARTED)
         {
             gatt_end_operation(p_clcb, GATT_ERROR, NULL);
         }
@@ -185,8 +188,10 @@
             break;
     }
 
-    if ( op_code == 0 ||
-         (rt = attp_send_cl_msg(p_tcb, p_clcb->clcb_idx, op_code, &msg)) != GATT_SUCCESS)
+    if (op_code != 0)
+        rt = attp_send_cl_msg(p_tcb, p_clcb->clcb_idx, op_code, &msg);
+
+    if ( op_code == 0 || (rt != GATT_SUCCESS && rt != GATT_CMD_STARTED))
     {
         gatt_end_operation(p_clcb, rt, NULL);
     }
@@ -204,7 +209,7 @@
 void gatt_act_write (tGATT_CLCB *p_clcb, UINT8 sec_act)
 {
     tGATT_TCB           *p_tcb = p_clcb->p_tcb;
-    UINT8               rt = GATT_SUCCESS, op_code;
+    UINT8               rt = GATT_SUCCESS, op_code = 0;
     tGATT_VALUE         *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf;
 
     if (p_attr)
@@ -373,7 +378,7 @@
     /* remember the write long attribute length */
     p_clcb->counter = to_send;
 
-    if (rt != GATT_SUCCESS )
+    if (rt != GATT_SUCCESS && rt != GATT_CMD_STARTED)
     {
         gatt_end_operation(p_clcb, rt, NULL);
     }
@@ -820,7 +825,7 @@
             }
             return;
         }
-        else /* discover characterisitic or read characteristic value */
+        else /* discover characterisitic */
         {
             STREAM_TO_UINT8 (record_value.dclr_value.char_prop, p);
             STREAM_TO_UINT16(record_value.dclr_value.val_handle, p);
diff --git a/stack/gatt/gatt_main.c b/stack/gatt/gatt_main.c
index dcd9398..075bda3 100644
--- a/stack/gatt/gatt_main.c
+++ b/stack/gatt/gatt_main.c
@@ -36,6 +36,10 @@
 #define GATT_L2C_CFG_IND_DONE   (1<<0)
 #define GATT_L2C_CFG_CFM_DONE   (1<<1)
 
+/* minimum GATT MTU size over BR/EDR link
+*/
+#define GATT_MIN_BR_MTU_SIZE       48
+
 /********************************************************************************/
 /*              L O C A L    F U N C T I O N     P R O T O T Y P E S            */
 /********************************************************************************/
@@ -139,24 +143,21 @@
 *******************************************************************************/
 BOOLEAN gatt_connect (BD_ADDR rem_bda, tGATT_TCB *p_tcb)
 {
-    BOOLEAN             gatt_ret = TRUE;
-    tBT_DEVICE_TYPE     dev_type;
-    tBLE_ADDR_TYPE      addr_type;
-
-    BTM_ReadDevInfo(rem_bda, &dev_type, &addr_type);
+    BOOLEAN             gatt_ret = FALSE;
 
     if (gatt_get_ch_state(p_tcb) != GATT_CH_OPEN)
         gatt_set_ch_state(p_tcb, GATT_CH_CONN);
 
-    if (dev_type == BT_DEVICE_TYPE_BLE)
+    /* select the physical link for GATT connection */
+    if (BTM_UseLeLink(rem_bda))
     {
         p_tcb->att_lcid = L2CAP_ATT_CID;
         gatt_ret = L2CA_ConnectFixedChnl (L2CAP_ATT_CID, rem_bda);
     }
     else
     {
-        if ((p_tcb->att_lcid = L2CA_ConnectReq(BT_PSM_ATT, rem_bda)) == 0)
-            gatt_ret = FALSE;
+        if ((p_tcb->att_lcid = L2CA_ConnectReq(BT_PSM_ATT, rem_bda)) != 0)
+            gatt_ret = TRUE;
     }
 
     return gatt_ret;
@@ -328,7 +329,9 @@
         st = gatt_get_ch_state(p_tcb);
 
         /* before link down, another app try to open a GATT connection */
-        if(st == GATT_CH_OPEN &&  gatt_num_apps_hold_link(p_tcb) == 0 )
+        if(st == GATT_CH_OPEN &&  gatt_num_apps_hold_link(p_tcb) == 0 &&
+            /* only connection on fix channel when the l2cap channel is already open */
+            p_tcb->att_lcid == L2CAP_ATT_CID )
         {
             if (!gatt_connect(bd_addr,  p_tcb))
                 ret = FALSE;
@@ -419,11 +422,6 @@
 
                 gatt_send_conn_cback(p_tcb);
             }
-            else /* there was an exisiting link, ignore the callback */
-            {
-                GATT_TRACE_ERROR0("connection already up, ignore it");
-                return;
-            }
         }
         /* this is incoming connection or background connection callback */
         else
@@ -585,7 +583,7 @@
             /* else initiating connection failure */
             else
             {
-                gatt_cleanup_upon_disc(p_tcb->peer_bda, result);
+                gatt_cleanup_upon_disc(p_tcb->peer_bda, GATT_CONN_L2C_FAILURE);
             }
         }
         else /* wrong state, disconnect it */
@@ -637,11 +635,8 @@
                     }
                     else
                     {
-                        if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda) &&
-                            btm_sec_is_le_capable_dev(p_tcb->peer_bda))
-                        {
+                        if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda))
                             gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
-                        }
                     }
 
                     /* send callback */
@@ -676,7 +671,8 @@
     if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL)
     {
         /* GATT uses the smaller of our MTU and peer's MTU  */
-        if ( (p_cfg->mtu_present) && (p_cfg->mtu < L2CAP_DEFAULT_MTU) )
+        if ( p_cfg->mtu_present &&
+             (p_cfg->mtu >= GATT_MIN_BR_MTU_SIZE && p_cfg->mtu < L2CAP_DEFAULT_MTU))
             p_tcb->payload_size = p_cfg->mtu;
         else
             p_tcb->payload_size = L2CAP_DEFAULT_MTU;
@@ -998,11 +994,6 @@
     {
         gatt_send_srv_chg_ind(p_srv_chg_clt->bda);
     }
-    else
-    {
-        GATT_TRACE_DEBUG0("No need to send srv chg ");
-    }
-
 }
 
 /*******************************************************************************
diff --git a/stack/gatt/gatt_sr.c b/stack/gatt/gatt_sr.c
index b7ad6f9..da36722 100644
--- a/stack/gatt/gatt_sr.c
+++ b/stack/gatt/gatt_sr.c
@@ -338,7 +338,7 @@
         GATT_TRACE_DEBUG2("conf test forced err rsp for %s error status=%d",
                            __FUNCTION__,gatt_cb.err_status);
 
-        gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, 0, FALSE);
+        gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, gatt_cb.handle, FALSE);
 
         return;
     }
@@ -395,7 +395,7 @@
 void gatt_process_read_multi_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, UINT8 *p_data)
 {
     UINT32          trans_id;
-    UINT16          handle, ll = len;
+    UINT16          handle = 0, ll = len;
     UINT8           *p = p_data, i_rcb;
     tGATT_STATUS    err = GATT_SUCCESS;
     UINT8           sec_flag, key_size;
@@ -1241,6 +1241,7 @@
     len -= 2;
 
 #if GATT_CONFORMANCE_TESTING == TRUE
+    gatt_cb.handle = handle;
     if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code)
     {
         GATT_TRACE_DEBUG1("Conformance tst: forced err rsp: error status=%d", gatt_cb.err_status);
diff --git a/stack/gatt/gatt_utils.c b/stack/gatt/gatt_utils.c
index 5b375b5..b7f5224 100644
--- a/stack/gatt/gatt_utils.c
+++ b/stack/gatt/gatt_utils.c
@@ -710,7 +710,7 @@
 
     for (i = start_idx ; i < GATT_MAX_PHY_CHANNEL; i ++)
     {
-        if (gatt_cb.tcb[i].in_use)
+        if (gatt_cb.tcb[i].in_use && gatt_cb.tcb[i].ch_state == GATT_CH_OPEN)
         {
             memcpy( bda, gatt_cb.tcb[i].peer_bda, BD_ADDR_LEN);
             *p_found_idx = i;
@@ -2543,7 +2543,9 @@
                 if (p_dev_list->listen_gif[j] == gatt_if)
                 {
                     p_dev_list->listen_gif[j] = 0;
-                    p_reg->listening --;
+
+                    if (p_reg != NULL && p_reg->listening > 0)
+                        p_reg->listening --;
 
                     /* move all element behind one forward */
                     for (k = j + 1; k < GATT_MAX_APPS; k ++)
diff --git a/stack/include/btm_ble_api.h b/stack/include/btm_ble_api.h
index bb654e5..0dcc8d2 100644
--- a/stack/include/btm_ble_api.h
+++ b/stack/include/btm_ble_api.h
@@ -875,6 +875,17 @@
 *******************************************************************************/
 BTM_API extern BOOLEAN BTM_IsBleLink (BD_ADDR bd_addr);
 
+/*******************************************************************************
+**
+** Function         BTM_UseLeLink
+**
+** Description      This function is to select the underneath physical link to use.
+**
+** Returns          TRUE to use LE, FALSE use BR/EDR.
+**
+*******************************************************************************/
+BTM_API extern BOOLEAN BTM_UseLeLink (BD_ADDR bd_addr);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/stack/include/gatt_api.h b/stack/include/gatt_api.h
index d53a80e..01afb71 100644
--- a/stack/include/gatt_api.h
+++ b/stack/include/gatt_api.h
@@ -100,7 +100,7 @@
 #define  GATT_HANDLE_IS_VALID(x) ((x) != 0)
 
 #define GATT_CONN_UNKNOWN                   0
-#define GATT_CONN_NO_RESOURCES              L2CAP_CONN_NO_RESOURCES         /* connection fail for l2cap resource failure */
+#define GATT_CONN_L2C_FAILURE               1                               /* general L2cap failure  */
 #define GATT_CONN_TIMEOUT                   HCI_ERR_CONNECTION_TOUT         /* 0x08 connection timeout  */
 #define GATT_CONN_TERMINATE_PEER_USER       HCI_ERR_PEER_USER               /* 0x13 connection terminate by peer user  */
 #define GATT_CONN_TERMINATE_LOCAL_HOST      HCI_ERR_CONN_CAUSE_LOCAL_HOST   /* 0x16 connectionterminated by local host  */
@@ -244,6 +244,15 @@
     UINT8               name_spc;   /* The name space of the description */
 } tGATT_CHAR_PRES;
 
+/* Characteristic Report reference Descriptor format
+*/
+typedef struct
+{
+    UINT8              rpt_id;       /* report ID */
+    UINT8              rpt_type;       /* report type */
+} tGATT_CHAR_RPT_REF;
+
+
 #define GATT_VALID_RANGE_MAX_SIZE       16
 typedef struct
 {
@@ -522,12 +531,10 @@
     tGATT_INCL_SRVC     incl_service;  /* include service value */
     tGATT_GROUP_VALUE   group_value;   /* Service UUID type.
                                           This field is used with GATT_DISC_SRVC_ALL
+                                          or GATT_DISC_SRVC_BY_UUID
                                           type of discovery result callback. */
 
-    UINT16              handle;        /* When used with GATT_DISC_SRVC_BY_UUID type
-                                          discovery result, it is the ending handle of a
-                                          known service to be discovered. When used with
-                                          GATT_DISC_INC_SRVC type discovery result,
+    UINT16              handle;        /* When used with GATT_DISC_INC_SRVC type discovery result,
                                           it is the included service starting handle.*/
 
     tGATT_CHAR_DCLR_VAL dclr_value;    /* Characteristic declaration value.
@@ -1047,7 +1054,8 @@
 **
 ** Function         GATT_Connect
 **
-** Description      This function initiate a connecttion to a ATT server.
+** Description      This function initiate a connecttion to a remote device on GATT
+**                  channel.
 **
 ** Parameters       gatt_if: applicaiton interface
 **                  bd_addr: peer device address.
@@ -1063,7 +1071,8 @@
 **
 ** Function         GATT_CancelConnect
 **
-** Description      This function initiate a cancel connecttion to a ATT server.
+** Description      This function terminate the connection initaition to a remote
+**                  device on GATT channel.
 **
 ** Parameters       gatt_if: client interface. If 0 used as unconditionally disconnect,
 **                          typically used for direct connection cancellation.
@@ -1079,7 +1088,8 @@
 **
 ** Function         GATT_Disconnect
 **
-** Description      This function disconnect a logic channel.
+** Description      This function disconnect the GATT channel for this registered
+**                  application.
 **
 ** Parameters       conn_id: connection identifier.
 **
diff --git a/stack/l2cap/l2c_ble.c b/stack/l2cap/l2c_ble.c
index 75053bd..494c6e6 100644
--- a/stack/l2cap/l2c_ble.c
+++ b/stack/l2cap/l2c_ble.c
@@ -48,7 +48,7 @@
     tL2C_LCB *p_lcb;
 
     /* There can be only one BLE connection request outstanding at a time */
-    if (btm_ble_get_conn_st() == BLE_DIR_CONN)
+    if (btm_ble_get_conn_st() == BLE_CONN_IDLE)
     {
         L2CAP_TRACE_WARNING0 ("L2CA_CancelBleConnectReq - no connection pending");
         return(FALSE);
@@ -72,8 +72,8 @@
             p_lcb->disc_reason = L2CAP_CONN_CANCEL;
             l2cu_release_lcb (p_lcb);
         }
-        /* update conn state to IDLE */
-        btm_ble_set_conn_st (BLE_CONN_IDLE);
+        /* update state to be cancel, wait for connection cancel complete */
+        btm_ble_set_conn_st (BLE_CONN_CANCEL);
 
         return(TRUE);
     }
@@ -551,9 +551,9 @@
     if (!btsnd_hcic_ble_create_ll_conn (scan_int,/* UINT16 scan_int      */
                                         scan_win, /* UINT16 scan_win      */
                                         FALSE,                   /* UINT8 white_list     */
-                                        p_lcb->ble_addr_type,          /* UINT8 addr_type_peer */
-                                        p_lcb->remote_bd_addr,         /* BD_ADDR bda_peer     */
-                                        BLE_ADDR_PUBLIC,         /* UINT8 addr_type_own  */
+                                        init_addr_type,          /* UINT8 addr_type_peer */
+                                        init_addr,               /* BD_ADDR bda_peer     */
+                                        own_addr_type,         /* UINT8 addr_type_own  */
                                         (UINT16) ((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN),  /* UINT16 conn_int_min  */
                                         (UINT16) ((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MIN),  /* UINT16 conn_int_max  */
                                         (UINT16) ((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.slave_latency : 0), /* UINT16 conn_latency  */
@@ -568,6 +568,7 @@
     else
     {
         p_lcb->link_state = LST_CONNECTING;
+        l2cb.is_ble_connecting = TRUE;
         memcpy (l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN);
         btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, L2CAP_BLE_LINK_CONNECT_TOUT);
         btm_ble_set_conn_st (BLE_DIR_CONN);
diff --git a/stack/smp/smp_act.c b/stack/smp/smp_act.c
index e3f676b..032f3ed 100644
--- a/stack/smp/smp_act.c
+++ b/stack/smp/smp_act.c
@@ -889,10 +889,27 @@
 {
     SMP_TRACE_DEBUG0 ("smp_pair_terminate ");
 
-    if (p_data->reason == L2CAP_CONN_CANCEL)
         p_cb->status = SMP_CONN_TOUT;
+
+    smp_proc_pairing_cmpl(p_cb);
+}
+
+/*******************************************************************************
+** Function         smp_delay_terminate
+** Description      This function is called when connection dropped when smp delay
+**                  timer is still active.
+*******************************************************************************/
+void smp_delay_terminate(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG0 ("smp_delay_terminate ");
+
+    btu_stop_timer (&p_cb->rsp_timer_ent);
+
+    /* if remote user terminate connection, finish SMP pairing as normal */
+    if (p_data->reason == HCI_ERR_PEER_USER)
+        p_cb->status = SMP_SUCCESS;
     else
-        p_cb->status = SMP_PAIR_FAIL_UNKNOWN;
+        p_cb->status = SMP_CONN_TOUT;
 
     smp_proc_pairing_cmpl(p_cb);
 }
diff --git a/stack/smp/smp_int.h b/stack/smp/smp_int.h
index e8d93de..51cdbb3 100644
--- a/stack/smp/smp_int.h
+++ b/stack/smp/smp_int.h
@@ -287,6 +287,7 @@
 extern void smp_key_distribution(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_proc_srk_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_generate_csrk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_delay_terminate(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 /* smp_l2c */
 extern void smp_l2cap_if_init (void);
 
diff --git a/stack/smp/smp_main.c b/stack/smp/smp_main.c
index 59dddb4..f8e450c 100644
--- a/stack/smp/smp_main.c
+++ b/stack/smp/smp_main.c
@@ -113,6 +113,7 @@
     SMP_PROC_DISCARD,
     SMP_PROC_REL_DELAY,
     SMP_PROC_REL_DELAY_TOUT,
+    SMP_DELAY_TERMINATE,
     SMP_SM_NO_ACTION
 };
 
@@ -154,6 +155,7 @@
     smp_proc_discard,
     smp_proc_release_delay,
     smp_proc_release_delay_tout,
+    smp_delay_terminate,
 };
 /************ SMP Master FSM State/Event Indirection Table **************/
 static const UINT8 smp_ma_entry_map[][SMP_ST_MAX] =
@@ -174,7 +176,7 @@
 /* KEY_READY          */{ 0,    3,     0,      3,     1,   0,    2,   1,    6,     0   },
 /* ENC_CMPL           */{ 0,    0,     0,      0,     0,   0,    0,   2,    0,     0   },
 /* L2C_CONN           */{ 1,    0,     0,      0,     0,   0,    0,   0,    0,     0   },
-/* L2C_DISC           */{ 0x83,	0x83,  0,      0x83,  0x83,0x83, 0x83,0x83, 0x83,  2   },
+/* L2C_DISC           */{ 0x83,	0x83,  0,      0x83,  0x83,0x83, 0x83,0x83, 0x83,  3   },
 /* IO_RSP             */{ 0,    2,     0,      0,     0,   0,    0,   0,    0,     0   },
 /* SEC_GRANT          */{ 0,    1,     0,      0,     0,   0,    0,   0,    0,     0   },
 /* TK_REQ             */{ 0,    0,     0,      2,     0,   0,    0,   0,    0,     0   },
@@ -250,7 +252,8 @@
 static const UINT8 smp_ma_rel_delay_table[][SMP_SM_NUM_COLS] = {
 /* Event       Action                   Next State */
 /* RELEASE_DELAY*/       {SMP_PROC_REL_DELAY,      SMP_SM_NO_ACTION,      SMP_ST_RELEASE_DELAY},
-/* RELEASE_DELAY_TOUT*/  {SMP_PROC_REL_DELAY_TOUT, SMP_SM_NO_ACTION,      SMP_ST_IDLE}
+/* RELEASE_DELAY_TOUT*/  {SMP_PROC_REL_DELAY_TOUT, SMP_SM_NO_ACTION,      SMP_ST_IDLE},
+/* L2C_DISC*/            {SMP_DELAY_TERMINATE,     SMP_SM_NO_ACTION,     SMP_ST_IDLE}
 };
 
 
@@ -445,7 +448,7 @@
     /* lookup entry /w event & curr_state */
     /* If entry is ignore, return.
      * Otherwise, get state table (according to curr_state or all_state) */
-    if ( (entry = entry_table[event - 1][curr_state]) != SMP_SM_IGNORE )
+    if ((event < SMP_MAX_EVT) && ( (entry = entry_table[event - 1][curr_state]) != SMP_SM_IGNORE ))
     {
         if (entry & SMP_ALL_TBL_MASK)
         {