Merge "Workaround IPHONE problem" into klp-modular-dev
diff --git a/bta/gatt/bta_gattc_act.c b/bta/gatt/bta_gattc_act.c
index 90e9504..44f88e4 100644
--- a/bta/gatt/bta_gattc_act.c
+++ b/bta/gatt/bta_gattc_act.c
@@ -69,7 +69,8 @@
 {
     BTA_GATTC_API_READ_EVT,
     BTA_GATTC_API_WRITE_EVT,
-    BTA_GATTC_API_EXEC_EVT
+    BTA_GATTC_API_EXEC_EVT,
+    BTA_GATTC_API_CFG_MTU_EVT
 };
 
 #if (BT_TRACE_VERBOSE == TRUE)
@@ -349,7 +350,8 @@
                 bta_gattc_send_open_cback(p_clreg,
                                           BTA_GATT_NO_RESOURCES,
                                           p_msg->api_conn.remote_bda,
-                                          BTA_GATT_INVALID_CONN_ID);
+                                          BTA_GATT_INVALID_CONN_ID,
+                                          0);
             }
         }
         else
@@ -473,7 +475,8 @@
     bta_gattc_send_open_cback(p_clcb->p_rcb,
                               BTA_GATT_OK,
                               p_clcb->bda,
-                              p_clcb->bta_conn_id);
+                              p_clcb->bta_conn_id,
+                              0);
 }
 /*******************************************************************************
 **
@@ -491,7 +494,8 @@
     bta_gattc_send_open_cback(p_clcb->p_rcb,
                               BTA_GATT_ERROR,
                               p_clcb->bda,
-                              p_clcb->bta_conn_id);
+                              p_clcb->bta_conn_id,
+                              0);
 
     /* open failure, remove clcb */
     bta_gattc_clcb_dealloc(p_clcb);
@@ -579,7 +583,7 @@
     /* open failure, report OPEN_EVT */
     if (status != BTA_GATT_OK)
     {
-        bta_gattc_send_open_cback(p_clreg, status, p_data->remote_bda, BTA_GATT_INVALID_CONN_ID);
+        bta_gattc_send_open_cback(p_clreg, status, p_data->remote_bda, BTA_GATT_INVALID_CONN_ID, 0);
     }
 }
 /*******************************************************************************
@@ -687,6 +691,10 @@
     }
 
         p_clcb->p_srcb->connected = TRUE;
+
+        if (p_clcb->p_srcb->mtu == 0)
+            p_clcb->p_srcb->mtu = GATT_DEF_BLE_MTU_SIZE;
+
         /* start database cache if needed */
         if (p_clcb->p_srcb->p_srvc_cache == NULL ||
             p_clcb->p_srcb->state != BTA_GATTC_SERV_IDLE)
@@ -719,7 +727,8 @@
             bta_gattc_send_open_cback(p_clcb->p_rcb,
                                       BTA_GATT_OK,
                                       p_clcb->bda,
-                                      p_clcb->bta_conn_id);
+                                      p_clcb->bta_conn_id,
+                                      p_clcb->p_srcb->mtu);
         }
     }
 /*******************************************************************************
@@ -871,6 +880,38 @@
     p_clcb->status      = BTA_GATT_CANCEL;
     p_clcb->auto_update = BTA_GATTC_DISC_WAITING;
 }
+
+/*******************************************************************************
+**
+** Function         bta_gattc_cfg_mtu
+**
+** Description      Configure MTU size on the GATT connection.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_cfg_mtu(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    tBTA_GATTC_OP_CMPL  op_cmpl;
+    tBTA_GATT_STATUS    status;
+
+    if (bta_gattc_enqueue(p_clcb, p_data))
+    {
+        status = GATTC_ConfigureMTU (p_clcb->bta_conn_id, p_data->api_mtu.mtu);
+
+        /* if failed, return callback here */
+        if (status != GATT_SUCCESS && status != GATT_CMD_STARTED)
+        {
+            memset(&op_cmpl, 0, sizeof(tBTA_GATTC_OP_CMPL));
+
+            op_cmpl.status  = status;
+            op_cmpl.op_code = GATTC_OPTYPE_CONFIG;
+            op_cmpl.p_cmpl  = NULL;
+
+            bta_gattc_sm_execute(p_clcb, BTA_GATTC_OP_CMPL_EVT, (tBTA_GATTC_DATA *)&op_cmpl);
+        }
+    }
+}
 /*******************************************************************************
 **
 ** Function         bta_gattc_start_discover
@@ -1346,6 +1387,35 @@
     ( *p_clcb->p_rcb->p_cback)(BTA_GATTC_EXEC_EVT,  &cb_data);
 
 }
+
+/*******************************************************************************
+**
+** Function         bta_gattc_cfg_mtu_cmpl
+**
+** Description      configure MTU operation complete
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_cfg_mtu_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data)
+{
+    tBTA_GATTC          cb_data;
+
+    utl_freebuf((void **)&p_clcb->p_q_cmd);
+
+
+    if (p_data->p_cmpl  &&  p_data->status == BTA_GATT_OK)
+        p_clcb->p_srcb->mtu  = p_data->p_cmpl->mtu;
+
+    /* configure MTU complete, callback */
+    p_clcb->status          = p_data->status;
+    cb_data.cfg_mtu.conn_id = p_clcb->bta_conn_id;
+    cb_data.cfg_mtu.status  = p_data->status;
+    cb_data.cfg_mtu.mtu     = p_clcb->p_srcb->mtu;
+
+    (*p_clcb->p_rcb->p_cback) (BTA_GATTC_CFG_MTU_EVT,  &cb_data);
+
+}
 /*******************************************************************************
 **
 ** Function         bta_gattc_op_cmpl
@@ -1403,11 +1473,9 @@
 
         else if (op == GATTC_OPTYPE_EXE_WRITE)
             bta_gattc_exec_cmpl(p_clcb, &p_data->op_cmpl);
-        /*
-        else if (op == GATTC_OPTYPE_CONFIG) // API to be added
-        {
-        }
-       */
+
+        else if (op == GATTC_OPTYPE_CONFIG)
+            bta_gattc_cfg_mtu_cmpl(p_clcb, &p_data->op_cmpl);
     }
 }
 /*******************************************************************************
diff --git a/bta/gatt/bta_gattc_api.c b/bta/gatt/bta_gattc_api.c
index d264458..0bc87ec 100644
--- a/bta/gatt/bta_gattc_api.c
+++ b/bta/gatt/bta_gattc_api.c
@@ -224,6 +224,34 @@
 }
 /*******************************************************************************
 **
+** Function         BTA_GATTC_ConfigureMTU
+**
+** Description      Configure the MTU size in the GATT channel. This can be done
+**                  only once per connection.
+**
+** Parameters       conn_id: connection ID.
+**                  mtu: desired MTU size to use.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_GATTC_ConfigureMTU (UINT16 conn_id, UINT16 mtu)
+{
+    tBTA_GATTC_API_CFG_MTU  *p_buf;
+
+    if ((p_buf = (tBTA_GATTC_API_CFG_MTU *) GKI_getbuf(sizeof(tBTA_GATTC_API_CFG_MTU))) != NULL)
+    {
+        p_buf->hdr.event = BTA_GATTC_API_CFG_MTU_EVT;
+        p_buf->hdr.layer_specific = conn_id;
+
+        p_buf->mtu = mtu;
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+/*******************************************************************************
+**
 ** Function         BTA_GATTC_ServiceSearchRequest
 **
 ** Description      This function is called to request a GATT service discovery
diff --git a/bta/gatt/bta_gattc_int.h b/bta/gatt/bta_gattc_int.h
index 255090d..4f192cb 100644
--- a/bta/gatt/bta_gattc_int.h
+++ b/bta/gatt/bta_gattc_int.h
@@ -45,6 +45,7 @@
     BTA_GATTC_API_READ_EVT,
     BTA_GATTC_API_WRITE_EVT,
     BTA_GATTC_API_EXEC_EVT,
+    BTA_GATTC_API_CFG_MTU_EVT,
 
     BTA_GATTC_API_CLOSE_EVT,
 
@@ -188,6 +189,13 @@
     BOOLEAN                 start;
 } tBTA_GATTC_API_LISTEN;
 
+
+typedef struct
+{
+    BT_HDR              hdr;
+    UINT16              mtu;
+}tBTA_GATTC_API_CFG_MTU;
+
 typedef struct
 {
     BT_HDR                  hdr;
@@ -217,6 +225,7 @@
     tBTA_GATTC_API_CONFIRM      api_confirm;
     tBTA_GATTC_API_EXEC         api_exec;
     tBTA_GATTC_API_READ_MULTI   api_read_multi;
+    tBTA_GATTC_API_CFG_MTU      api_mtu;
     tBTA_GATTC_OP_CMPL          op_cmpl;
     tBTA_GATTC_CI_EVT           ci_open;
     tBTA_GATTC_CI_EVT           ci_save;
@@ -327,6 +336,7 @@
     UINT8               srvc_hdl_chg;   /* service handle change indication pending */
     UINT16              attr_index;     /* cahce NV saving/loading attribute index */
 
+    UINT16              mtu;
 } tBTA_GATTC_SERV;
 
 #ifndef BTA_GATTC_NOTIF_REG_MAX
@@ -481,8 +491,9 @@
 extern void bta_gattc_init_bk_conn(tBTA_GATTC_API_OPEN *p_data, tBTA_GATTC_RCB *p_clreg);
 extern void bta_gattc_cancel_bk_conn(tBTA_GATTC_API_CANCEL_OPEN *p_data);
 extern void bta_gattc_send_open_cback( tBTA_GATTC_RCB *p_clreg, tBTA_GATT_STATUS status,
-                                       BD_ADDR remote_bda, UINT16 conn_id);
+                                       BD_ADDR remote_bda, UINT16 conn_id, UINT16 mtu);
 extern void bta_gattc_process_api_refresh(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg);
+extern void bta_gattc_cfg_mtu(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
 #if BLE_INCLUDED == TRUE
 extern void bta_gattc_listen(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg);
 extern void bta_gattc_broadcast(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg);
diff --git a/bta/gatt/bta_gattc_main.c b/bta/gatt/bta_gattc_main.c
index 638f2f9..341e420 100644
--- a/bta/gatt/bta_gattc_main.c
+++ b/bta/gatt/bta_gattc_main.c
@@ -69,6 +69,7 @@
     BTA_GATTC_IGNORE_OP_CMPL,
     BTA_GATTC_DISC_CLOSE,
     BTA_GATTC_RESTART_DISCOVER,
+    BTA_GATTC_CFG_MTU,
 
     BTA_GATTC_IGNORE
 };
@@ -106,7 +107,8 @@
     bta_gattc_cache_open,
     bta_gattc_ignore_op_cmpl,
     bta_gattc_disc_close,
-    bta_gattc_restart_discover
+    bta_gattc_restart_discover,
+    bta_gattc_cfg_mtu
 };
 
 
@@ -127,6 +129,7 @@
 /* BTA_GATTC_API_READ_EVT           */   {BTA_GATTC_FAIL,              BTA_GATTC_IDLE_ST},
 /* BTA_GATTC_API_WRITE_EVT          */   {BTA_GATTC_FAIL,              BTA_GATTC_IDLE_ST},
 /* BTA_GATTC_API_EXEC_EVT           */   {BTA_GATTC_FAIL,              BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_API_CFG_MTU_EVT        */   {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST},
 
 /* BTA_GATTC_API_CLOSE_EVT          */   {BTA_GATTC_CLOSE_FAIL,        BTA_GATTC_IDLE_ST},
 
@@ -161,6 +164,7 @@
 /* BTA_GATTC_API_READ_EVT           */   {BTA_GATTC_FAIL,               BTA_GATTC_W4_CONN_ST},
 /* 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_CFG_MTU_EVT        */   {BTA_GATTC_IGNORE,             BTA_GATTC_W4_CONN_ST},
 
 /* BTA_GATTC_API_CLOSE_EVT          */   {BTA_GATTC_CANCEL_OPEN,         BTA_GATTC_W4_CONN_ST},
 
@@ -194,6 +198,7 @@
 /* BTA_GATTC_API_READ_EVT           */   {BTA_GATTC_READ,               BTA_GATTC_CONN_ST},
 /* BTA_GATTC_API_WRITE_EVT          */   {BTA_GATTC_WRITE,              BTA_GATTC_CONN_ST},
 /* BTA_GATTC_API_EXEC_EVT           */   {BTA_GATTC_EXEC,               BTA_GATTC_CONN_ST},
+/* BTA_GATTC_API_CFG_MTU_EVT        */   {BTA_GATTC_CFG_MTU,            BTA_GATTC_CONN_ST},
 
 /* BTA_GATTC_API_CLOSE_EVT          */   {BTA_GATTC_CLOSE,              BTA_GATTC_IDLE_ST},
 
@@ -228,6 +233,7 @@
 /* BTA_GATTC_API_READ_EVT           */   {BTA_GATTC_Q_CMD,              BTA_GATTC_DISCOVER_ST},
 /* BTA_GATTC_API_WRITE_EVT          */   {BTA_GATTC_Q_CMD,              BTA_GATTC_DISCOVER_ST},
 /* BTA_GATTC_API_EXEC_EVT           */   {BTA_GATTC_Q_CMD,              BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_API_CFG_MTU_EVT        */   {BTA_GATTC_Q_CMD,              BTA_GATTC_DISCOVER_ST},
 
 /* BTA_GATTC_API_CLOSE_EVT          */   {BTA_GATTC_DISC_CLOSE,         BTA_GATTC_DISCOVER_ST},
 
@@ -489,6 +495,8 @@
             return "BTA_GATTC_API_LISTEN_EVT";
         case BTA_GATTC_API_DISABLE_EVT:
             return "BTA_GATTC_API_DISABLE_EVT";
+        case BTA_GATTC_API_CFG_MTU_EVT:
+            return "BTA_GATTC_API_CFG_MTU_EVT";
         default:
             return "unknown GATTC event code";
     }
diff --git a/bta/gatt/bta_gattc_utils.c b/bta/gatt/bta_gattc_utils.c
index d81e121..b52e52c 100644
--- a/bta/gatt/bta_gattc_utils.c
+++ b/bta/gatt/bta_gattc_utils.c
@@ -294,6 +294,7 @@
         {
             p_srcb->connected = FALSE;
             p_srcb->state = BTA_GATTC_SERV_IDLE;
+            p_srcb->mtu = 0;
         }
 
         utl_freebuf((void **)&p_clcb->p_q_cmd);
@@ -557,6 +558,18 @@
                 }
                 break;
             }
+            case BTA_GATTC_API_CFG_MTU_EVT:
+            {
+                len = sizeof(tBTA_GATTC_API_CFG_MTU);
+                p_clcb->p_q_cmd = (tBTA_GATTC_DATA *)GKI_getbuf(len);
+                if (p_clcb->p_q_cmd == NULL)
+                {
+                    APPL_TRACE_ERROR0("allocate buffer failed for p_q_cmd");
+                    return FALSE;
+                }
+                memcpy(p_clcb->p_q_cmd, p_data, len);
+                break;
+            }
             default:
                 APPL_TRACE_ERROR1("queue unsupported command %d", p_data->hdr.event);
                 return FALSE;
@@ -906,7 +919,7 @@
 **
 *******************************************************************************/
 void bta_gattc_send_open_cback( tBTA_GATTC_RCB *p_clreg, tBTA_GATT_STATUS status,
-                                BD_ADDR remote_bda, UINT16 conn_id)
+                                BD_ADDR remote_bda, UINT16 conn_id, UINT16 mtu)
 {
     tBTA_GATTC      cb_data;
 
@@ -917,6 +930,7 @@
         cb_data.open.status = status;
         cb_data.open.client_if = p_clreg->client_if;
         cb_data.open.conn_id = conn_id;
+        cb_data.open.mtu = mtu;
         bdcpy(cb_data.open.remote_bda, remote_bda);
 
         (*p_clreg->p_cback)(BTA_GATTC_OPEN_EVT, &cb_data);
diff --git a/bta/include/bta_gatt_api.h b/bta/include/bta_gatt_api.h
index e5ce5a4..b53b180 100644
--- a/bta/include/bta_gatt_api.h
+++ b/bta/include/bta_gatt_api.h
@@ -116,6 +116,7 @@
 #define BTA_GATTC_SRVC_CHG_EVT      15  /* service change event */
 #define BTA_GATTC_LISTEN_EVT        16  /* listen event */
 #define BTA_GATTC_ENC_CMPL_CB_EVT   17  /* encryption complete callback event */
+#define BTA_GATTC_CFG_MTU_EVT       18  /* configure MTU complete event */
 
 typedef UINT8 tBTA_GATTC_EVT;
 
@@ -311,6 +312,12 @@
     tBTA_GATT_SRVC_ID   service_uuid;
 }tBTA_GATTC_SRVC_RES;
 
+typedef struct
+{
+    UINT16              conn_id;
+    tBTA_GATT_STATUS    status;
+    UINT16              mtu;
+}tBTA_GATTC_CFG_MTU;
 
 typedef struct
 {
@@ -318,6 +325,7 @@
     UINT16              conn_id;
     tBTA_GATTC_IF       client_if;
     BD_ADDR             remote_bda;
+    UINT16              mtu;
 }tBTA_GATTC_OPEN;
 
 typedef struct
@@ -371,6 +379,7 @@
     tBTA_GATTC_NOTIFY       notify;           /* notification/indication event data */
     tBTA_GATTC_ENC_CMPL_CB  enc_cmpl;
     BD_ADDR                 remote_bda;     /* service change event */
+    tBTA_GATTC_CFG_MTU      cfg_mtu;        /* configure MTU operation */
 } tBTA_GATTC;
 
 /* GATTC enable callback function */
@@ -1046,6 +1055,21 @@
 
 
 /*******************************************************************************
+**
+** Function         BTA_GATTC_ConfigureMTU
+**
+** Description      Configure the MTU size in the GATT channel. This can be done
+**                  only once per connection.
+**
+** Parameters       conn_id: connection ID.
+**                  mtu: desired MTU size to use.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_ConfigureMTU (UINT16 conn_id, UINT16 mtu);
+
+/*******************************************************************************
 **  BTA GATT Server API
 ********************************************************************************/
 
diff --git a/btif/src/btif_gatt_client.c b/btif/src/btif_gatt_client.c
index 80c50d0..c788bd8 100644
--- a/btif/src/btif_gatt_client.c
+++ b/btif/src/btif_gatt_client.c
@@ -90,7 +90,8 @@
     BTIF_GATTC_REFRESH,
     BTIF_GATTC_READ_RSSI,
     BTIF_GATTC_LISTEN,
-    BTIF_GATTC_SET_ADV_DATA
+    BTIF_GATTC_SET_ADV_DATA,
+    BTIF_GATTC_CONFIGURE_MTU,
 } btif_gattc_event_t;
 
 #define BTIF_GATT_MAX_OBSERVED_DEV 40
@@ -438,6 +439,12 @@
             HAL_CBACK(bt_gatt_callbacks, client->open_cb, p_data->open.conn_id
                 , p_data->open.status, p_data->open.client_if, &bda);
 
+            if (GATT_DEF_BLE_MTU_SIZE != p_data->open.mtu && p_data->open.mtu)
+            {
+                HAL_CBACK(bt_gatt_callbacks, client->configure_mtu_cb, p_data->open.conn_id
+                    , p_data->open.status , p_data->open.mtu);
+            }
+
             if (p_data->open.status == BTA_GATT_OK)
                 btif_gatt_check_encrypted_link(p_data->open.remote_bda);
             break;
@@ -510,6 +517,14 @@
             );
             break;
         }
+
+        case BTA_GATTC_CFG_MTU_EVT:
+        {
+            HAL_CBACK(bt_gatt_callbacks, client->configure_mtu_cb, p_data->cfg_mtu.conn_id
+                , p_data->cfg_mtu.status , p_data->cfg_mtu.mtu);
+            break;
+        }
+
         default:
             ALOGE("%s: Unhandled event (%d)!", __FUNCTION__, event);
             break;
@@ -882,6 +897,9 @@
 
             break;
         }
+        case BTIF_GATTC_CONFIGURE_MTU:
+            BTA_GATTC_ConfigureMTU(p_cb->conn_id, p_cb->len);
+            break;
 
         default:
             ALOGE("%s: Unknown event (%d)!", __FUNCTION__, event);
@@ -1306,6 +1324,16 @@
                                  (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
 }
 
+static bt_status_t btif_gattc_configure_mtu(int conn_id, int mtu)
+{
+    CHECK_BTGATT_INIT();
+    btif_gattc_cb_t btif_cb;
+    btif_cb.conn_id = conn_id;
+    btif_cb.len = mtu; // Re-use len field
+    return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_CONFIGURE_MTU,
+                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
 static int btif_gattc_get_device_type( const bt_bdaddr_t *bd_addr )
 {
     int device_type = 0;
@@ -1347,6 +1375,7 @@
     btif_gattc_read_remote_rssi,
     btif_gattc_get_device_type,
     btif_gattc_set_adv_data,
+    btif_gattc_configure_mtu,
     btif_gattc_test_command
 };
 
diff --git a/btif/src/btif_gatt_util.c b/btif/src/btif_gatt_util.c
index 614d496..715dcd6 100644
--- a/btif/src/btif_gatt_util.c
+++ b/btif/src/btif_gatt_util.c
@@ -271,7 +271,7 @@
 
 static void btif_gatt_set_encryption_cb (BD_ADDR bd_addr, tBTA_STATUS result)
 {
-    if (result != BTA_SUCCESS)
+    if (result != BTA_SUCCESS && result != BTA_BUSY)
     {
         bt_bdaddr_t bda;
         bdcpy(bda.address, bd_addr);
diff --git a/stack/btm/btm_ble_addr.c b/stack/btm/btm_ble_addr.c
index a3f6a7e..3c646e9 100644
--- a/stack/btm/btm_ble_addr.c
+++ b/stack/btm/btm_ble_addr.c
@@ -287,7 +287,7 @@
     {
         p_dev_rec = &btm_cb.sec_dev_rec[rec_index];
 
-        BTM_TRACE_ERROR2("sec_flags = %02x device_type = %d", p_dev_rec->sec_flags, p_dev_rec->device_type);
+        BTM_TRACE_DEBUG2("sec_flags = %02x device_type = %d", p_dev_rec->sec_flags, p_dev_rec->device_type);
 
         if ((p_dev_rec->device_type == BT_DEVICE_TYPE_BLE) &&
             (p_dev_rec->ble.key_type & BTM_LE_KEY_PID))
diff --git a/stack/btm/btm_ble_gap.c b/stack/btm/btm_ble_gap.c
index 6ab0415..54f1b55 100644
--- a/stack/btm/btm_ble_gap.c
+++ b/stack/btm/btm_ble_gap.c
@@ -157,7 +157,7 @@
     tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var;
     tBTM_STATUS     status = BTM_NO_RESOURCES;
 
-    BTM_TRACE_EVENT0 ("BTM_BleObserve ");
+    BTM_TRACE_EVENT1 ("BTM_BleObserve : scan_type:%d",btm_cb.btm_inq_vars.scan_type);
 
     if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
         return BTM_ILLEGAL_VALUE;
@@ -166,10 +166,22 @@
     {
         /* shared inquiry database, do not allow observe if any inquiry is active */
         if (btm_cb.btm_inq_vars.inq_active || p_inq->proc_mode != BTM_BLE_INQUIRY_NONE)
-            return BTM_BUSY;
-
-        btm_cb.btm_inq_vars.p_inq_results_cb = p_results_cb;
-        btm_cb.btm_inq_vars.p_inq_cmpl_cb = p_cmpl_cb;
+        {
+            /*check if an interleave scan is already in progress*/
+            if(btm_cb.btm_inq_vars.scan_type == INQ_GENERAL
+                && btm_cb.btm_inq_vars.p_inq_results_cb != NULL)
+            {
+                BTM_TRACE_EVENT0 ("BTM_BleObserve general inq in progress, redirecting the results");
+                btm_cb.btm_inq_vars.p_inq_ble_results_cb = p_results_cb;
+                btm_cb.btm_inq_vars.p_inq_ble_cmpl_cb = p_cmpl_cb;
+                return BTM_SUCCESS;
+            }
+            else
+                return BTM_BUSY;
+        }
+        btm_cb.btm_inq_vars.scan_type = INQ_LE_OBSERVE;
+        btm_cb.btm_inq_vars.p_inq_ble_results_cb = p_results_cb;
+        btm_cb.btm_inq_vars.p_inq_ble_cmpl_cb = p_cmpl_cb;
         p_inq->scan_type = (p_inq->scan_type == BTM_BLE_SCAN_MODE_NONE) ? BTM_BLE_SCAN_MODE_ACTI: p_inq->scan_type;
 
         /* allow config scanning type */
@@ -194,10 +206,19 @@
             }
         }
     }
-    else if (p_inq->proc_mode == BTM_BLE_OBSERVE)
+    else/*start = 0*/
     {
-        btm_cb.btm_inq_vars.inq_active &= ~BTM_LE_OBSERVE_ACTIVE;
-        btm_ble_stop_scan();
+        if(btm_cb.btm_inq_vars.scan_type == INQ_GENERAL)
+        {
+            //Dont stop the scan. Just nullify the cbs
+            btm_cb.btm_inq_vars.p_inq_ble_results_cb = NULL;
+            btm_cb.btm_inq_vars.p_inq_ble_cmpl_cb = NULL;
+        }
+        else if (p_inq->proc_mode == BTM_BLE_OBSERVE)
+        {
+            btm_cb.btm_inq_vars.inq_active &= ~BTM_LE_OBSERVE_ACTIVE;
+            btm_ble_stop_scan();
+        }
     }
 
     return status;
@@ -1591,6 +1612,8 @@
     if ((btm_cb.ble_ctr_cb.inq_var.scan_type == BTM_BLE_SCAN_MODE_ACTI &&
          (evt_type == BTM_BLE_CONNECT_EVT || evt_type == BTM_BLE_DISCOVER_EVT)))
     {
+        BTM_TRACE_DEBUG1("btm_ble_update_inq_result scan_rsp=false, to_report=false,\
+                              scan_type_active=%d", btm_cb.ble_ctr_cb.inq_var.scan_type);
         p_i->scan_rsp = FALSE;
         to_report = FALSE;
     }
@@ -1744,6 +1767,8 @@
          btm_cb.ble_ctr_cb.p_select_cback == NULL))
         return;
 
+    BTM_TRACE_DEBUG6("btm_ble_process_adv_pkt:bda= %0x:%0x:%0x:%0x:%0x:%0x",
+                                     bda[0],bda[1],bda[2],bda[3],bda[4],bda[5]);
 #if (defined BTM_BLE_PRIVACY_SPT && BTM_BLE_PRIVACY_SPT == TRUE)
 #if SMP_INCLUDED == TRUE
     /* always do RRA resolution on host */
@@ -1775,9 +1800,12 @@
 {
     tINQ_DB_ENT          *p_i;
     BOOLEAN              to_report = FALSE;
+    BOOLEAN              to_report_LE = TRUE; //var for reporting to LE observe
     tBTM_INQUIRY_VAR_ST  *p_inq = &btm_cb.btm_inq_vars;
     tBTM_INQ_RESULTS_CB  *p_inq_results_cb = p_inq->p_inq_results_cb;
+    tBTM_INQ_RESULTS_CB  *p_inq_ble_results_cb = p_inq->p_inq_ble_results_cb;
     tBTM_BLE_INQ_CB      *p_le_inq_cb = &btm_cb.ble_ctr_cb.inq_var;
+    BTM_TRACE_DEBUG2("btm_ble_process_adv_pkt_cont: addr_type: %d, evt_type: %d", addr_type, evt_type);
 
     p_i = btm_inq_db_find (bda);
 
@@ -1797,11 +1825,10 @@
         }
         else
         {
-            /* if yes, skip it */
-            return; /* assumption: one result per event */
+            to_report = FALSE;
         }
     }
-    else /* not been processed int his round */
+    else /* not been processed in this round */
     {
         to_report = TRUE;
     }
@@ -1809,33 +1836,31 @@
     /* If existing entry, use that, else get  a new one (possibly reusing the oldest) */
     if (p_i == NULL)
     {
-        if (btm_ble_is_discoverable(bda, evt_type, p))
+        if ((p_i = btm_inq_db_new (bda)) != NULL)
         {
-            if ((p_i = btm_inq_db_new (bda)) != NULL)
-            {
-                p_inq->inq_cmpl_info.num_resp++;
-                to_report = TRUE;
-            }
-            else
-                return;
+            p_inq->inq_cmpl_info.num_resp++;
+        }
+        else
+            return;
+
+        if (to_report && btm_ble_is_discoverable(bda, evt_type, p))
+        {
+            to_report = TRUE;
         }
         else
         {
             BTM_TRACE_ERROR0("discard adv pkt");
-            return;
+            to_report = FALSE;
         }
     }
     else if (p_i->inq_count != p_inq->inq_counter) /* first time seen in this inquiry */
     {
         p_inq->inq_cmpl_info.num_resp++;
     }
-
     /* update the LE device information in inquiry database */
+    to_report_LE = btm_ble_update_inq_result(p_i, addr_type, evt_type, p);
     if (to_report)
-    {
-        to_report = btm_ble_update_inq_result(p_i, addr_type, evt_type, p);
-    }
-
+        to_report = to_report_LE;
 #if BTM_USE_INQ_RESULTS_FILTER == TRUE
     /* If the number of responses found and limited, issue a cancel inquiry */
     if (p_inq->inqparms.max_resps &&
@@ -1863,6 +1888,8 @@
     }
 #endif
 
+    BTM_TRACE_DEBUG2("btm_ble_process_adv_pkt_cont: to_report =%d, to_report_le=%d",
+                                                               to_report, to_report_LE);
     /* background connection in selective connection mode */
     if (btm_cb.ble_ctr_cb.bg_conn_type == BTM_BLE_CONN_SELECTIVE)
     {
@@ -1874,9 +1901,13 @@
             BTM_TRACE_DEBUG0("None LE device, can not initiate selective connection");
         }
     }
-    else if (p_inq_results_cb && to_report)
+    else if (to_report || to_report_LE)
     {
-        (p_inq_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache);
+        if(p_inq_results_cb && to_report)
+            (p_inq_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache);
+        if(p_inq_ble_results_cb && to_report_LE)
+            (p_inq_ble_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results,
+                                                      p_le_inq_cb->adv_data_cache);
     }
 }
 
diff --git a/stack/btm/btm_inq.c b/stack/btm/btm_inq.c
index 4c5eecb..24f91a8 100644
--- a/stack/btm/btm_inq.c
+++ b/stack/btm/btm_inq.c
@@ -810,8 +810,8 @@
          */
 #endif
 
-        p_inq->inq_counter++;
-        btm_clr_inq_result_flt();
+         p_inq->inq_counter++;
+         btm_clr_inq_result_flt();
     }
 
     return (status);
@@ -860,7 +860,27 @@
     /* Only one active inquiry is allowed in this implementation.
        Also do not allow an inquiry if the inquiry filter is being updated */
     if (p_inq->inq_active || p_inq->inqfilt_active)
-        return (BTM_BUSY);
+    {
+#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
+        /*check if LE observe is already running*/
+        if(p_inq->scan_type==INQ_LE_OBSERVE && p_inq->p_inq_ble_results_cb!=NULL)
+        {
+            BTM_TRACE_API0("BTM_StartInquiry: LE observe in progress");
+            p_inq->scan_type = INQ_GENERAL;
+            p_inq->inq_active = BTM_INQUIRY_INACTIVE;
+            btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE;
+            btm_cb.ble_ctr_cb.inq_var.proc_mode = BTM_BLE_INQUIRY_NONE;
+            btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
+        }
+        else
+#endif
+        {
+            return (BTM_BUSY);
+            BTM_TRACE_API0("BTM_StartInquiry: return BUSY");
+        }
+    }
+    else
+        p_inq->scan_type = INQ_GENERAL;
 
         /*** Make sure the device is ready ***/
     if (!BTM_IsDeviceUp())
@@ -2402,7 +2422,13 @@
     p_inq->inqparms.mode &= ~(mode);
 #endif
 
-
+    if(p_inq->scan_type == INQ_LE_OBSERVE && !p_inq->inq_active)
+    {
+        /*end of LE observe*/
+        p_inq->p_inq_ble_results_cb = (tBTM_INQ_RESULTS_CB *) NULL;
+        p_inq->p_inq_ble_cmpl_cb = (tBTM_CMPL_CB *) NULL;
+        p_inq->scan_type=INQ_NONE;
+    }
 
 
 #if (BTM_INQ_DEBUG == TRUE)
@@ -2473,9 +2499,22 @@
                 p_inq->inq_active = BTM_INQUIRY_INACTIVE;
                 /* call the inquiry again */
                 BTM_StartInquiry(&p_inq->inqparms,p_inq->p_inq_results_cb,p_inq->p_inq_cmpl_cb);
+                return;
             }
 #endif
     }
+    if(p_inq->inqparms.mode == 0 && p_inq->scan_type == INQ_GENERAL)//this inquiry is complete
+    {
+        p_inq->scan_type = INQ_NONE;
+#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
+        /* check if the LE observe is pending */
+        if(p_inq->p_inq_ble_results_cb != NULL)
+        {
+            BTM_TRACE_DEBUG0("BTM Inq Compl: resuming a pending LE scan");
+            BTM_BleObserve(1,0, p_inq->p_inq_ble_results_cb, p_inq->p_inq_ble_cmpl_cb);
+        }
+#endif
+    }
 #if (BTM_INQ_DEBUG == TRUE)
     BTM_TRACE_DEBUG3 ("inq_active:0x%x state:%d inqfilt_active:%d",
         btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
diff --git a/stack/btm/btm_int.h b/stack/btm/btm_int.h
index 5129efc..7865b3e 100644
--- a/stack/btm/btm_int.h
+++ b/stack/btm/btm_int.h
@@ -271,6 +271,14 @@
 } tINQ_DB_ENT;
 
 
+enum
+{
+    INQ_NONE,
+    INQ_LE_OBSERVE,
+    INQ_GENERAL
+};
+typedef UINT8 tBTM_INQ_TYPE;
+
 typedef struct
 {
     tBTM_CMPL_CB *p_remname_cmpl_cb;
@@ -288,6 +296,7 @@
     UINT16           inq_scan_period;
     UINT16           inq_scan_type;
     UINT16           page_scan_type;        /* current page scan type */
+    tBTM_INQ_TYPE    scan_type;
 
     BD_ADDR          remname_bda;           /* Name of bd addr for active remote name request */
 #define BTM_RMT_NAME_INACTIVE       0
@@ -298,6 +307,8 @@
 
     tBTM_CMPL_CB    *p_inq_cmpl_cb;
     tBTM_INQ_RESULTS_CB *p_inq_results_cb;
+    tBTM_CMPL_CB    *p_inq_ble_cmpl_cb;     /*completion callback exclusively for LE Observe*/
+    tBTM_INQ_RESULTS_CB *p_inq_ble_results_cb;/*results callback exclusively for LE observe*/
     tBTM_CMPL_CB    *p_inqfilter_cmpl_cb;   /* Called (if not NULL) after inquiry filter completed */
     tBTM_INQ_DB_CHANGE_CB *p_inq_change_cb; /* Inquiry database changed callback    */
     UINT32           inq_counter;           /* Counter incremented each time an inquiry completes */