Merge "LE (2/3): Add application ID to connection callback" into jb-mr2-dev
diff --git a/btif/co/bta_pan_co.c b/btif/co/bta_pan_co.c
index e78a5f8..c6310d4 100644
--- a/btif/co/bta_pan_co.c
+++ b/btif/co/bta_pan_co.c
@@ -16,36 +16,25 @@
  *
  ******************************************************************************/
 
-/************************************************************************************
+/******************************************************************************
  *
  *  Filename:      bta_pan_co.c
  *
  *  Description:   PAN stack callout api
  *
  *
- ***********************************************************************************/
+ ******************************************************************************/
 #include "bta_api.h"
 #include "bta_pan_api.h"
 #include "bta_pan_ci.h"
 #include "bta_pan_co.h"
 #include "pan_api.h"
 #include "gki.h"
-//#include "btui.h"
-//#include "btui_int.h"
 #include <hardware/bluetooth.h>
 #include <hardware/bt_pan.h>
 #include "btif_pan_internal.h"
 #include "bd.h"
-
-
-#include <cutils/log.h>
-#define info(fmt, ...)  ALOGI ("%s: " fmt,__FUNCTION__,  ## __VA_ARGS__)
-#define debug(fmt, ...) ALOGD ("%s: " fmt,__FUNCTION__,  ## __VA_ARGS__)
-#define warn(fmt, ...) ALOGW ("## WARNING : %s: " fmt "##",__FUNCTION__,  ## __VA_ARGS__)
-#define error(fmt, ...) ALOGE ("## ERROR : %s: " fmt "##",__FUNCTION__,  ## __VA_ARGS__)
-#define asrt(s) if(!(s)) ALOGE ("## %s assert %s failed at line:%d ##",__FUNCTION__, #s, __LINE__)
-
-
+#include <string.h>
 
 
 /*******************************************************************************
@@ -60,8 +49,7 @@
 *******************************************************************************/
 UINT8 bta_pan_co_init(UINT8 *q_level)
 {
-
-    ALOGD("bta_pan_co_init");
+    BTIF_TRACE_API0("bta_pan_co_init");
 
     /* set the q_level to 30 buffers */
     *q_level = 30;
@@ -70,10 +58,7 @@
     return (BTA_PAN_RX_PUSH_BUF | BTA_PAN_RX_PUSH | BTA_PAN_TX_PULL);
 }
 
-
-
-
-/*******************************************************************************
+/******************************************************************************
 **
 ** Function         bta_pan_co_open
 **
@@ -86,18 +71,20 @@
 ** Returns          void
 **
 *******************************************************************************/
-
-void bta_pan_co_open(UINT16 handle, UINT8 app_id, tBTA_PAN_ROLE local_role, tBTA_PAN_ROLE peer_role, BD_ADDR peer_addr)
+void bta_pan_co_open(UINT16 handle, UINT8 app_id, tBTA_PAN_ROLE local_role,
+                            tBTA_PAN_ROLE peer_role, BD_ADDR peer_addr)
 {
-    ALOGD("bta_pan_co_open:app_id:%d, local_role:%d, peer_role:%d, handle:%d",
-            app_id, local_role, peer_role, handle);
+    BTIF_TRACE_API4("bta_pan_co_open:app_id:%d, local_role:%d, peer_role:%d, "
+                    "handle:%d", app_id, local_role, peer_role, handle);
     btpan_conn_t* conn = btpan_find_conn_addr(peer_addr);
     if(conn == NULL)
         conn = btpan_new_conn(handle, peer_addr, local_role, peer_role);
     if(conn)
     {
-        ALOGD("bta_pan_co_open:tap_fd:%d, open_count:%d, conn->handle:%d should = handle:%d, local_role:%d, remote_role:%d",
-             btpan_cb.tap_fd, btpan_cb.open_count, conn->handle, handle, conn->local_role, conn->remote_role);
+        BTIF_TRACE_DEBUG6("bta_pan_co_open:tap_fd:%d, open_count:%d, "
+            "conn->handle:%d should = handle:%d, local_role:%d, remote_role:%d",
+             btpan_cb.tap_fd, btpan_cb.open_count, conn->handle, handle,
+             conn->local_role, conn->remote_role);
         //refresh the role & bt address
 
         btpan_cb.open_count++;
@@ -117,7 +104,6 @@
     }
 }
 
-
 /*******************************************************************************
 **
 ** Function         bta_pan_co_close
@@ -131,11 +117,11 @@
 *******************************************************************************/
 void bta_pan_co_close(UINT16 handle, UINT8 app_id)
 {
-    ALOGD("bta_pan_co_close:app_id:%d, handle:%d", app_id, handle);
+    BTIF_TRACE_API2("bta_pan_co_close:app_id:%d, handle:%d", app_id, handle);
     btpan_conn_t* conn = btpan_find_conn_handle(handle);
     if(conn && conn->state == PAN_STATE_OPEN)
     {
-        ALOGD("bta_pan_co_close");
+        BTIF_TRACE_DEBUG0("bta_pan_co_close");
 
         // let bta close event reset this handle as it needs
         // the handle to find the connection upon CLOSE
@@ -182,36 +168,40 @@
     BOOLEAN            ext;
     BOOLEAN         forward;
 
-    ALOGD("bta_pan_co_tx_path, handle:%d, app_id:%d", handle, app_id);
+    BTIF_TRACE_API2("bta_pan_co_tx_path, handle:%d, app_id:%d", handle, app_id);
 
     btpan_conn_t* conn = btpan_find_conn_handle(handle);
     if(conn && conn->state != PAN_STATE_OPEN)
     {
-        ALOGE("bta_pan_co_tx_path: cannot find pan connction or conn is not opened, conn:%p, conn->state:%d", conn, conn->state);
+        BTIF_TRACE_ERROR2("bta_pan_co_tx_path: cannot find pan connction or conn"
+            "is not opened, conn:%p, conn->state:%d", conn, conn->state);
         return;
     }
     do
     {
-
         /* read next data buffer from pan */
         if ((p_buf = bta_pan_ci_readbuf(handle, src, dst, &protocol,
                                  &ext, &forward)))
         {
-            ALOGD("bta_pan_co_tx_path, calling btapp_tap_send, p_buf->len:%d, offset:%d", p_buf->len, p_buf->offset);
+            BTIF_TRACE_DEBUG2("bta_pan_co_tx_path, calling btapp_tap_send, "
+                "p_buf->len:%d, offset:%d", p_buf->len, p_buf->offset);
             if(is_empty_eth_addr(conn->eth_addr) && is_valid_bt_eth_addr(src))
             {
-                ALOGD("pan bt peer addr: %02x:%02x:%02x:%02x:%02x:%02x, update its ethernet addr: %02x:%02x:%02x:%02x:%02x:%02x",
-                        conn->peer[0], conn->peer[1], conn->peer[2], conn->peer[3],conn->peer[4], conn->peer[5],
-                        src[0], src[1], src[2], src[3],src[4], src[5]);
+                BTIF_TRACE_DEBUG6("pan bt peer addr: %02x:%02x:%02x:%02x:%02x:%02x",
+                    conn->peer[0], conn->peer[1], conn->peer[2],
+                    conn->peer[3],conn->peer[4], conn->peer[5]);
+                BTIF_TRACE_DEBUG6("     update its ethernet addr: "
+                    "%02x:%02x:%02x:%02x:%02x:%02x", src[0], src[1], src[2],
+                    src[3],src[4], src[5]);
                 memcpy(conn->eth_addr, src, sizeof(conn->eth_addr));
 
             }
-            btpan_tap_send(btpan_cb.tap_fd, src, dst, protocol, (char*)(p_buf + 1) + p_buf->offset, p_buf->len, ext, forward);
+            btpan_tap_send(btpan_cb.tap_fd, src, dst, protocol,
+                (char*)(p_buf + 1) + p_buf->offset, p_buf->len, ext, forward);
             GKI_freebuf(p_buf);
         }
 
     } while (p_buf != NULL);
-
 }
 
 /*******************************************************************************
@@ -228,13 +218,7 @@
 *******************************************************************************/
 void bta_pan_co_rx_path(UINT16 handle, UINT8 app_id)
 {
-
-
-    UINT8           i;
-
-    ALOGD("bta_pan_co_rx_path not used");
-
-
+    BTIF_TRACE_API0("bta_pan_co_rx_path not used");
 }
 
 /*******************************************************************************
@@ -250,11 +234,11 @@
 ** Returns          void
 **
 *******************************************************************************/
-void bta_pan_co_tx_write(UINT16 handle, UINT8 app_id, BD_ADDR src, BD_ADDR dst, UINT16 protocol, UINT8 *p_data,
+void bta_pan_co_tx_write(UINT16 handle, UINT8 app_id, BD_ADDR src, BD_ADDR dst,
+                                UINT16 protocol, UINT8 *p_data,
                                 UINT16 len, BOOLEAN ext, BOOLEAN forward)
 {
-     ALOGD("bta_pan_co_tx_write not used");
-
+     BTIF_TRACE_API0("bta_pan_co_tx_write not used");
 }
 
 /*******************************************************************************
@@ -270,13 +254,11 @@
 ** Returns          TRUE if flow enabled
 **
 *******************************************************************************/
-void  bta_pan_co_tx_writebuf(UINT16 handle, UINT8 app_id, BD_ADDR src, BD_ADDR dst, UINT16 protocol, BT_HDR *p_buf,
-                                   BOOLEAN ext, BOOLEAN forward)
+void  bta_pan_co_tx_writebuf(UINT16 handle, UINT8 app_id, BD_ADDR src,
+                                    BD_ADDR dst, UINT16 protocol, BT_HDR *p_buf,
+                                    BOOLEAN ext, BOOLEAN forward)
 {
-
-    ALOGD("bta_pan_co_tx_writebuf not used");
-
-
+    BTIF_TRACE_API0("bta_pan_co_tx_writebuf not used");
 }
 
 /*******************************************************************************
@@ -295,12 +277,9 @@
 *******************************************************************************/
 void bta_pan_co_rx_flow(UINT16 handle, UINT8 app_id, BOOLEAN enable)
 {
-
-    ALOGD("bta_pan_co_rx_flow, enabled:%d, not used", enable);
-
+    BTIF_TRACE_API1("bta_pan_co_rx_flow, enabled:%d, not used", enable);
 }
 
-
 /*******************************************************************************
 **
 ** Function         bta_pan_co_filt_ind
@@ -313,9 +292,9 @@
 void bta_pan_co_pfilt_ind(UINT16 handle, BOOLEAN indication, tBTA_PAN_STATUS result,
                                     UINT16 len, UINT8 *p_filters)
 {
-    ALOGD("bta_pan_co_pfilt_ind");
-
+    BTIF_TRACE_API0("bta_pan_co_pfilt_ind");
 }
+
 /*******************************************************************************
 **
 ** Function         bta_pan_co_mfilt_ind
@@ -328,7 +307,6 @@
 void bta_pan_co_mfilt_ind(UINT16 handle, BOOLEAN indication, tBTA_PAN_STATUS result,
                                     UINT16 len, UINT8 *p_filters)
 {
-
-    ALOGD("bta_pan_co_mfilt_ind");
+    BTIF_TRACE_API0("bta_pan_co_mfilt_ind");
 }
 
diff --git a/btif/include/btif_hh.h b/btif/include/btif_hh.h
index c77d597..f7b9f3d 100644
--- a/btif/include/btif_hh.h
+++ b/btif/include/btif_hh.h
@@ -23,6 +23,8 @@
 #include <hardware/bt_hh.h>
 #include <stdint.h>
 #include "bta_hh_api.h"
+#include "btu.h"
+
 
 /*******************************************************************************
 **  Constants & Macros
@@ -64,6 +66,8 @@
     BT_HDR                        *p_buf;
     UINT32                        hh_poll_thread_id;
     UINT8                         hh_keep_polling;
+    BOOLEAN                       vup_timer_active;
+    TIMER_LIST_ENT                vup_timer;
 } btif_hh_device_t;
 
 /* Control block to maintain properties of devices */
diff --git a/btif/src/btif_hh.c b/btif/src/btif_hh.c
index 61dd894..e4da0be 100644
--- a/btif/src/btif_hh.c
+++ b/btif/src/btif_hh.c
@@ -73,6 +73,8 @@
 #define BTIF_HH_ID_1        0
 #define BTIF_HH_DEV_DISCONNECTED 3
 
+#define BTIF_TIMEOUT_VUP_SECS   3
+
 
 #ifndef BTUI_HH_SECURITY
 #define BTUI_HH_SECURITY (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT)
@@ -163,6 +165,7 @@
 static void toggle_os_keylockstates(int fd, int changedkeystates);
 static void sync_lockstate_on_connect(btif_hh_device_t *p_dev);
 //static void hh_update_keyboard_lockstates(btif_hh_device_t *p_dev);
+void btif_hh_tmr_hdlr(TIMER_LIST_ENT *tle);
 
 
 /************************************************************************************
@@ -404,6 +407,58 @@
 
 /*******************************************************************************
 **
+** Function      btif_hh_stop_vup_timer
+**
+** Description  stop vitual unplug timer
+**
+** Returns      void
+*******************************************************************************/
+void btif_hh_stop_vup_timer(bt_bdaddr_t *bd_addr)
+{
+    btif_hh_device_t *p_dev  = btif_hh_find_connected_dev_by_bda(bd_addr);
+    if(p_dev != NULL)
+    {
+        if (p_dev->vup_timer_active)
+        {
+            BTIF_TRACE_DEBUG0("stop VUP timer ");
+            btu_stop_timer(&p_dev->vup_timer);
+        }
+        p_dev->vup_timer_active = FALSE;
+    }
+}
+/*******************************************************************************
+**
+** Function      btif_hh_start_vup_timer
+**
+** Description  start virtual unplug timer
+**
+** Returns      void
+*******************************************************************************/
+void btif_hh_start_vup_timer(bt_bdaddr_t *bd_addr)
+{
+    btif_hh_device_t *p_dev  = btif_hh_find_connected_dev_by_bda(bd_addr);
+
+    if (p_dev->vup_timer_active == FALSE)
+    {
+        BTIF_TRACE_DEBUG0("Start VUP timer ");
+        memset(&p_dev->vup_timer, 0, sizeof(TIMER_LIST_ENT));
+        p_dev->vup_timer.param = (UINT32)btif_hh_tmr_hdlr;
+        btu_start_timer(&p_dev->vup_timer, BTU_TTYPE_USER_FUNC,
+                        BTIF_TIMEOUT_VUP_SECS);
+    }
+    else
+    {
+        BTIF_TRACE_DEBUG0("Restart VUP timer ");
+        btu_stop_timer(&p_dev->vup_timer);
+        btu_start_timer(&p_dev->vup_timer, BTU_TTYPE_USER_FUNC,
+                        BTIF_TIMEOUT_VUP_SECS);
+    }
+        p_dev->vup_timer_active = TRUE;
+
+}
+
+/*******************************************************************************
+**
 ** Function         btif_hh_add_added_dev
 **
 ** Description      Add a new device to the added device list.
@@ -545,6 +600,8 @@
         && (p_dev->attr_mask & HID_VIRTUAL_CABLE))
     {
         BTIF_TRACE_DEBUG1("%s Sending BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG", __FUNCTION__);
+        /* start the timer */
+        btif_hh_start_vup_timer(bd_addr);
         BTA_HhSendCtrl(p_dev->dev_handle, BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG);
         return BT_STATUS_SUCCESS;
     }
@@ -612,7 +669,7 @@
         BD_ADDR *bda = (BD_ADDR*)bd_addr;
         BTA_HhOpen(*bda, BTA_HH_PROTO_RPT_MODE, sec_mask);
     }
-    else 
+    else
     {
         // This device shall be connected from the host side.
         BTIF_TRACE_ERROR2("%s: Error, device %s can only be reconnected from device side",
@@ -647,7 +704,6 @@
         BTIF_TRACE_DEBUG1("%s-- Error: device not connected:",__FUNCTION__);
 }
 
-
 /*******************************************************************************
 **
 ** Function         btif_btif_hh_setreport
@@ -799,6 +855,10 @@
                     hidreport[0]=1;
                     bta_hh_co_write(p_dev->fd , hidreport, sizeof(hidreport));
                 }
+                if(p_dev->vup_timer_active)
+                {
+                    btif_hh_stop_vup_timer(&(p_dev->bd_addr));
+                }
                 btif_hh_cb.status = BTIF_HH_DEV_DISCONNECTED;
                 p_dev->dev_status = BTHH_CONN_STATE_DISCONNECTED;
                 HAL_CBACK(bt_hh_callbacks, connection_state_cb,&(p_dev->bd_addr), p_dev->dev_status);
@@ -890,8 +950,9 @@
                     bdcpy(bda, p_dev->bd_addr.address);
                     btif_hh_copy_hid_info(&dscp_info, &p_data->dscp_info);
                     BTIF_TRACE_DEBUG6("BTA_HH_GET_DSCP_EVT:bda = %02x:%02x:%02x:%02x:%02x:%02x",
-                              p_dev->bd_addr.address[0], p_dev->bd_addr.address[1], p_dev->bd_addr.address[2],
-                              p_dev->bd_addr.address[3], p_dev->bd_addr.address[4], p_dev->bd_addr.address[5]);
+                              p_dev->bd_addr.address[0], p_dev->bd_addr.address[1],
+                              p_dev->bd_addr.address[2],p_dev->bd_addr.address[3],
+                              p_dev->bd_addr.address[4], p_dev->bd_addr.address[5]);
                     BTA_HhAddDev(bda, p_dev->attr_mask,p_dev->sub_class,p_dev->app_id, dscp_info);
                     // write hid info to nvram
                     ret = btif_storage_add_hid_device_info(&(p_dev->bd_addr), p_dev->attr_mask,p_dev->sub_class,p_dev->app_id,
@@ -971,14 +1032,21 @@
                 btif_hh_cb.status = BTIF_HH_DEV_DISCONNECTED;
                 if (p_dev != NULL) {
                     BTIF_TRACE_DEBUG6("BTA_HH_VC_UNPLUG_EVT:bda = %02x:%02x:%02x:%02x:%02x:%02x",
-                         p_dev->bd_addr.address[0], p_dev->bd_addr.address[1], p_dev->bd_addr.address[2],
-                         p_dev->bd_addr.address[3], p_dev->bd_addr.address[4], p_dev->bd_addr.address[5]);
+                         p_dev->bd_addr.address[0], p_dev->bd_addr.address[1],
+                         p_dev->bd_addr.address[2],p_dev->bd_addr.address[3],
+                         p_dev->bd_addr.address[4], p_dev->bd_addr.address[5]);
+                    /* Stop the VUP timer */
+                    if(p_dev->vup_timer_active)
+                    {
+                        btif_hh_stop_vup_timer(&(p_dev->bd_addr));
+                    }
                     p_dev->dev_status = BTHH_CONN_STATE_DISCONNECTED;
                     BTIF_TRACE_DEBUG1("%s---Sending connection state change", __FUNCTION__);
                     HAL_CBACK(bt_hh_callbacks, connection_state_cb,&(p_dev->bd_addr), p_dev->dev_status);
-                    BTIF_TRACE_DEBUG1("%s---Removing HID mouse bond", __FUNCTION__);
+                    BTIF_TRACE_DEBUG1("%s---Removing HID bond", __FUNCTION__);
                     BTA_DmRemoveDevice((UINT8 *)p_dev->bd_addr.address);
-                    HAL_CBACK(bt_hh_callbacks, virtual_unplug_cb,&(p_dev->bd_addr),p_data->dev_status.status);
+                    HAL_CBACK(bt_hh_callbacks, virtual_unplug_cb,&(p_dev->bd_addr),
+                                    p_data->dev_status.status);
                 }
                 break;
 
@@ -1086,6 +1154,46 @@
     }
 }
 
+/*******************************************************************************
+**
+** Function      btif_hh_tmr_hdlr
+**
+** Description   Process timer timeout
+**
+** Returns      void
+*******************************************************************************/
+void btif_hh_tmr_hdlr(TIMER_LIST_ENT *tle)
+{
+    btif_hh_device_t *p_dev;
+    UINT8               i,j;
+    tBTA_HH_EVT event;
+    tBTA_HH p_data;
+    int param_len = 0;
+    memset(&p_data, 0, sizeof(tBTA_HH));
+
+    BTIF_TRACE_DEBUG2("%s timer_in_use=%d",  __FUNCTION__, tle->in_use );
+
+    for (i = 0; i < BTIF_HH_MAX_HID; i++) {
+        if (btif_hh_cb.devices[i].dev_status == BTHH_CONN_STATE_CONNECTED)
+        {
+
+            p_dev = &btif_hh_cb.devices[i];
+
+            if (p_dev->vup_timer_active)
+            {
+                p_dev->vup_timer_active = FALSE;
+                event = BTA_HH_VC_UNPLUG_EVT;
+                p_data.dev_status.status = BTHH_ERR;
+                p_data.dev_status.handle = p_dev->dev_handle;
+                param_len = sizeof(tBTA_HH_CBDATA);
+
+                /* switch context to btif task context */
+                btif_transfer_context(btif_hh_upstreams_evt, (uint16_t)event, (void*)&p_data,
+                            param_len, NULL);
+            }
+        }
+    }
+}
 
 /*******************************************************************************
 **
diff --git a/stack/btm/btm_acl.c b/stack/btm/btm_acl.c
index bcb7de6..ea1c68e 100644
--- a/stack/btm/btm_acl.c
+++ b/stack/btm/btm_acl.c
@@ -1336,16 +1336,9 @@
     p_acl_cb->num_read_pages = 0;
     memset (p_acl_cb->peer_lmp_features, 0, sizeof(p_acl_cb->peer_lmp_features));
 
-    /* If this BT controller supports Read Extended Feature */
-    if (btm_cb.devcb.local_version.hci_version >= HCI_PROTO_VERSION_2_0)
-    {
-        btm_read_remote_ext_features(handle, HCI_EXT_FEATURES_PAGE_0);
-    }
-    /* else, if this is a very old BT controller */
-    else
-    {
-        btsnd_hcic_rmt_features_req (handle);
-    }
+    /* first send read remote supported features HCI command */
+    /* because we don't know whether the remote support extended feature command */
+    btsnd_hcic_rmt_features_req (handle);
 }
 
 
@@ -1406,7 +1399,19 @@
     STREAM_TO_ARRAY(p_acl_cb->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0], p,
                     HCI_FEATURE_BYTES_PER_PAGE);
 
-    /* Process this features page */
+    if ((HCI_LMP_EXTENDED_SUPPORTED(p_acl_cb->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0])) &&
+        (HCI_READ_REMOTE_EXT_FEATURES_SUPPORTED(btm_cb.devcb.supported_cmds)))
+    {
+        /* if the remote controller has extended features and local controller supports
+        ** HCI_Read_Remote_Extended_Features command then start reading these feature starting
+        ** with extended features page 1 */
+        BTM_TRACE_DEBUG0 ("Start reading remote extended features");
+        btm_read_remote_ext_features(handle, HCI_EXT_FEATURES_PAGE_1);
+        return;
+    }
+
+    /* Remote controller has no extended features. Process remote controller supported features
+       (features page HCI_EXT_FEATURES_PAGE_0). */
     btm_process_remote_ext_features (p_acl_cb, 1);
 
     /* Continue with HCI connection establishment */
@@ -1433,14 +1438,6 @@
     BTM_TRACE_DEBUG0 ("btm_read_remote_ext_features_complete");
 
     STREAM_TO_UINT8  (status, p);
-
-    if (status != HCI_SUCCESS)
-    {
-        btm_read_remote_ext_features_failed (status);
-        return;
-    }
-
-    /* Extract parameters */
     STREAM_TO_UINT16 (handle, p);
     STREAM_TO_UINT8  (page_num, p);
     STREAM_TO_UINT8  (max_page, p);
@@ -1493,9 +1490,27 @@
 ** Returns          void
 **
 *******************************************************************************/
-void btm_read_remote_ext_features_failed (UINT8 status)
+void btm_read_remote_ext_features_failed (UINT8 status, UINT16 handle)
 {
-    BTM_TRACE_ERROR1 ("btm_read_remote_ext_features_failed (status 0x%02x)", status);
+    tACL_CONN   *p_acl_cb;
+    UINT8       acl_idx;
+
+    BTM_TRACE_WARNING2 ("btm_read_remote_ext_features_failed (status 0x%02x) for handle %d",
+                         status, handle);
+
+    if ((acl_idx = btm_handle_to_acl_index(handle)) >= MAX_L2CAP_LINKS)
+    {
+        BTM_TRACE_ERROR1("btm_read_remote_ext_features_failed handle=%d invalid", handle);
+        return;
+    }
+
+    p_acl_cb = &btm_cb.acl_db[acl_idx];
+
+    /* Process supported features only */
+    btm_process_remote_ext_features (p_acl_cb, 1);
+
+    /* Continue HCI connection establishment */
+    btm_establish_continue (p_acl_cb);
 }
 
 /*******************************************************************************
diff --git a/stack/btm/btm_devctl.c b/stack/btm/btm_devctl.c
index 8e883d7..79b2350 100644
--- a/stack/btm/btm_devctl.c
+++ b/stack/btm/btm_devctl.c
@@ -120,6 +120,7 @@
 static void btm_set_lmp_features_host_may_support (UINT8 max_page_number);
 static void btm_get_local_features (void);
 static void btm_issue_host_support_for_lmp_features (void);
+static void btm_read_local_supported_cmds (UINT8 local_controller_id);
 
 #if BLE_INCLUDED == TRUE
 static void btm_read_ble_local_supported_features (void);
@@ -511,6 +512,24 @@
 
 /*******************************************************************************
 **
+** Function         btm_read_local_supported_cmds
+**
+** Description      Local function called to send a read local supported commands
+**
+** Returns          void
+**
+*******************************************************************************/
+static void btm_read_local_supported_cmds (UINT8 local_controller_id)
+{
+    BTM_TRACE_DEBUG0("Start reading local supported commands");
+
+    btu_start_timer (&btm_cb.devcb.reset_timer, BTU_TTYPE_BTM_DEV_CTL, BTM_DEV_REPLY_TIMEOUT);
+
+    btsnd_hcic_read_local_supported_cmds(local_controller_id);
+}
+
+/*******************************************************************************
+**
 ** Function         btm_get_local_features
 **
 ** Description      Local function called to send a read local features
@@ -891,7 +910,14 @@
         STREAM_TO_UINT16 (p_vi->lmp_subversion, p);
     }
 
-    btm_get_local_features ();
+    if (p_vi->hci_version >= HCI_PROTO_VERSION_1_2)
+    {
+        btm_read_local_supported_cmds(LOCAL_BR_EDR_CONTROLLER_ID);
+    }
+    else
+    {
+        btm_get_local_features ();
+    }
 }
 
 /*******************************************************************************
@@ -1214,7 +1240,8 @@
         return;
     }
 
-    BTM_TRACE_ERROR1("btm_issue_host_support_for_lmp_features lmp_features_host_may_support: 0x%02x. This is unexpected.", btm_cb.devcb.lmp_features_host_may_support);
+    BTM_TRACE_ERROR2("%s lmp_features_host_may_support: 0x%02x. This is unexpected.",__FUNCTION__,
+                      btm_cb.devcb.lmp_features_host_may_support);
 }
 
 /*******************************************************************************
@@ -1303,10 +1330,9 @@
 void btm_read_local_features_complete (UINT8 *p, UINT16 evt_len)
 {
     tBTM_DEVCB     *p_devcb = &btm_cb.devcb;
-    tBTM_CMPL_CB   *p_cb = p_devcb->p_reset_cmpl_cb;
     UINT8           status;
 
-    btu_stop_timer (&btm_cb.devcb.reset_timer);
+    btu_stop_timer (&p_devcb->reset_timer);
 
     STREAM_TO_UINT8  (status, p);
     if (status == HCI_SUCCESS)
@@ -1315,7 +1341,19 @@
         STREAM_TO_ARRAY(p_devcb->local_lmp_features[0],
                 p, HCI_FEATURE_BYTES_PER_PAGE);
 
-        btm_read_all_lmp_features_complete (HCI_EXT_FEATURES_PAGE_0);
+        if ((HCI_LMP_EXTENDED_SUPPORTED(p_devcb->local_lmp_features[HCI_EXT_FEATURES_PAGE_0])) &&
+            (HCI_READ_LOCAL_EXT_FEATURES_SUPPORTED(p_devcb->supported_cmds)))
+        {
+            /* if local controller has extended features and supports
+            **HCI_Read_Local_Extended_Features command,
+            ** then start reading these feature starting with extended features page 1 */
+            BTM_TRACE_DEBUG0 ("Start reading local extended features");
+            btm_get_local_ext_features(HCI_EXT_FEATURES_PAGE_1);
+        }
+        else
+        {
+            btm_read_all_lmp_features_complete (HCI_EXT_FEATURES_PAGE_0);
+        }
     }
 }
 
@@ -1340,50 +1378,85 @@
     btu_stop_timer (&btm_cb.devcb.reset_timer);
 
     STREAM_TO_UINT8 (status, p);
+
+    if (status != HCI_SUCCESS)
+    {
+        BTM_TRACE_WARNING1("btm_read_local_ext_features_complete status = 0x%02X", status);
+        btm_read_all_lmp_features_complete (HCI_EXT_FEATURES_PAGE_0);
+        return;
+    }
+
+    /* Extract Page number */
+    STREAM_TO_UINT8  (page_number, p);
+
+    /* Extract Page number Max */
+    STREAM_TO_UINT8  (page_number_max, p);
+
+    if (page_number > HCI_EXT_FEATURES_PAGE_MAX)
+    {
+        BTM_TRACE_ERROR1("btm_read_local_ext_features_complete page=%d unknown",
+                page_number);
+        return;
+    }
+
+    /* Save the extended features Page received */
+    STREAM_TO_ARRAY(btm_cb.devcb.local_lmp_features[page_number],
+            p, HCI_FEATURE_BYTES_PER_PAGE);
+
+    /* If this is re-read of the 1-st extended page after host supported LMP features are set */
+    if ((page_number == HCI_EXT_FEATURES_PAGE_1) &&
+        (btm_cb.devcb.lmp_features_host_may_support == BTM_RE_READ_1ST_PAGE))
+    {
+        btm_cb.devcb.lmp_features_host_may_support &= ~BTM_RE_READ_1ST_PAGE;
+        btm_issue_host_support_for_lmp_features();
+        return;
+    }
+
+    /* If this is the last page supported by the local BT controller OR */
+    /* if this is the last page supported by the Host */
+    if ((page_number == page_number_max) ||
+        (page_number == HCI_EXT_FEATURES_PAGE_MAX))
+    {
+        BTM_TRACE_DEBUG1("BTM reached last extended features page (%d)", page_number);
+        btm_read_all_lmp_features_complete(page_number);
+    }
+    /* Else (another page must be read) */
+    else
+    {
+        /* Read the next features page */
+        page_number++;
+        BTM_TRACE_DEBUG1("BTM reads next extended features page (%d)", page_number);
+        btm_get_local_ext_features(page_number);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         btm_read_local_supported_cmds_complete
+**
+** Description      This function is called when local supported commands read
+**                  is complete.
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_read_local_supported_cmds_complete (UINT8 *p)
+{
+    tBTM_DEVCB     *p_devcb = &btm_cb.devcb;
+    UINT8           status;
+
+    btu_stop_timer (&(p_devcb->reset_timer));
+
+    STREAM_TO_UINT8  (status, p);
+    BTM_TRACE_DEBUG1("btm_read_local_supported_cmds_complete status (0x%02x)", status);
+
     if (status == HCI_SUCCESS)
     {
-        /* Extract Page number */
-        STREAM_TO_UINT8  (page_number, p);
-
-        /* Extract Page number Max */
-        STREAM_TO_UINT8  (page_number_max, p);
-
-        if (page_number > HCI_EXT_FEATURES_PAGE_MAX)
-        {
-            BTM_TRACE_ERROR1("btm_read_local_ext_features_complete page=%d unknown",
-                    page_number);
-            return;
-        }
-
-        /* Save the extended features Page received */
-        STREAM_TO_ARRAY(btm_cb.devcb.local_lmp_features[page_number],
-                p, HCI_FEATURE_BYTES_PER_PAGE);
-
-        /* If this is re-read of the 1-st extended page after host supported LMP features are set */
-        if ((page_number == HCI_EXT_FEATURES_PAGE_1) && (btm_cb.devcb.lmp_features_host_may_support == BTM_RE_READ_1ST_PAGE))
-        {
-            btm_cb.devcb.lmp_features_host_may_support &= ~BTM_RE_READ_1ST_PAGE;
-            btm_issue_host_support_for_lmp_features();
-            return;
-        }
-
-        /* If this is the last page supported by the local BT controller OR */
-        /* if this is the last page supported by the Host */
-        if ((page_number == page_number_max) ||
-            (page_number == HCI_EXT_FEATURES_PAGE_MAX))
-        {
-            BTM_TRACE_DEBUG1("BTM reached last extended features page (%d)", page_number);
-            btm_read_all_lmp_features_complete(page_number);
-        }
-        /* Else (another page must be read) */
-        else
-        {
-            /* Read the next features page */
-            page_number++;
-            BTM_TRACE_DEBUG1("BTM reads next extended features page (%d)", page_number);
-            btm_get_local_ext_features(page_number);
-        }
+        /* Save the supported commands bit mask */
+        STREAM_TO_ARRAY(p_devcb->supported_cmds, p, HCI_NUM_SUPP_COMMANDS_BYTES);
     }
+
+    btm_get_local_features();
 }
 
 /*******************************************************************************
diff --git a/stack/btm/btm_int.h b/stack/btm/btm_int.h
index 7b862fe..42bd3ad 100644
--- a/stack/btm/btm_int.h
+++ b/stack/btm/btm_int.h
@@ -220,6 +220,7 @@
 #define BTM_HOST_MAY_SUPP_LE            0x04
 #define BTM_HOST_MAY_SUPP_SIMULT_BR_LE  0x08
     UINT8               lmp_features_host_may_support;  /* The flags of LMP features host may support via BR/EDR ctrlr + BTM_RE_READ_1ST_PAGE */
+    UINT8               supported_cmds[HCI_NUM_SUPP_COMMANDS_BYTES]; /* Supported Commands bit field */
 
 } tBTM_DEVCB;
 
@@ -967,7 +968,7 @@
 BTM_API extern tBTM_STATUS  btm_remove_acl (BD_ADDR bd_addr);
 extern void         btm_read_remote_features_complete (UINT8 *p);
 extern void         btm_read_remote_ext_features_complete (UINT8 *p);
-extern void         btm_read_remote_ext_features_failed (UINT8 status);
+extern void         btm_read_remote_ext_features_failed (UINT8 status, UINT16 handle);
 extern void         btm_read_remote_version_complete (UINT8 *p);
 // btla-specific ++
 extern void         btm_acl_chk_peer_pkt_type_support (tACL_CONN *p, UINT16 *p_pkt_type);
@@ -1030,6 +1031,7 @@
 extern void btm_reset_complete (void);
 extern void btm_read_local_version_complete (UINT8 *p, UINT16 evt_len);
 extern void btm_read_hci_buf_size_complete (UINT8 *p, UINT16 evt_len);
+extern void btm_read_local_supported_cmds_complete (UINT8 *p);
 extern void btm_read_local_features_complete (UINT8 *p, UINT16 evt_len);
 extern void btm_read_local_ext_features_complete (UINT8 *p, UINT16 evt_len);
 extern void btm_read_local_name_complete (UINT8 *p, UINT16 evt_len);
diff --git a/stack/btu/btu_hcif.c b/stack/btu/btu_hcif.c
index 665b03c..a486036 100644
--- a/stack/btu/btu_hcif.c
+++ b/stack/btu/btu_hcif.c
@@ -870,11 +870,19 @@
 *******************************************************************************/
 static void btu_hcif_read_rmt_ext_features_comp_evt (UINT8 *p, UINT16 evt_len)
 {
-    /* Status is in first byte of stream */
-    if (*p == HCI_SUCCESS)
+    UINT8 *p_cur = p;
+    UINT8 status;
+    UINT16 handle;
+
+    STREAM_TO_UINT8 (status, p_cur);
+
+    if (status == HCI_SUCCESS)
         btm_read_remote_ext_features_complete(p);
     else
-        btm_read_remote_ext_features_failed(*p);
+    {
+        STREAM_TO_UINT16 (handle, p_cur);
+        btm_read_remote_ext_features_failed(status, handle);
+    }
 }
 
 /*******************************************************************************
@@ -1036,6 +1044,10 @@
             btm_read_hci_buf_size_complete (p, evt_len);
             break;
 
+        case HCI_READ_LOCAL_SUPPORTED_CMDS:
+            btm_read_local_supported_cmds_complete (p);
+            break;
+
         case HCI_READ_LOCAL_FEATURES:
             btm_read_local_features_complete (p, evt_len);
             break;
@@ -1341,8 +1353,16 @@
                         }
                         break;
 
-                    case HCI_READ_RMT_EXT_FEATURES_COMP_EVT:
-                        btm_read_remote_ext_features_failed(status);
+                    case HCI_READ_RMT_EXT_FEATURES:
+                        if (p_cmd != NULL)
+                        {
+                            p_cmd++; /* skip command length */
+                            STREAM_TO_UINT16 (handle, p_cmd);
+                        }
+                        else
+                            handle = HCI_INVALID_HANDLE;
+
+                        btm_read_remote_ext_features_failed(status, handle);
                         break;
 
                     case HCI_AUTHENTICATION_REQUESTED:
@@ -1594,7 +1614,7 @@
         case HCI_CREATE_CONNECTION:
         case HCI_CHANGE_CONN_LINK_KEY:
         case HCI_SWITCH_ROLE:
-        case HCI_READ_RMT_EXT_FEATURES_COMP_EVT:
+        case HCI_READ_RMT_EXT_FEATURES:
         case HCI_AUTHENTICATION_REQUESTED:
         case HCI_SET_CONN_ENCRYPTION:
 #if BTM_SCO_INCLUDED == TRUE
diff --git a/stack/include/btm_api.h b/stack/include/btm_api.h
index 0f1bb2b..3a7ed1d 100644
--- a/stack/include/btm_api.h
+++ b/stack/include/btm_api.h
@@ -2681,7 +2681,7 @@
 **
 ** Function         BTM_ReadRemoteFeatures
 **
-** Description      This function is called to read a remote device's 
+** Description      This function is called to read a remote device's
 **                  supported features mask (features mask located at page 0)
 **
 **                  Note: The size of device features mask page is
diff --git a/stack/l2cap/l2c_link.c b/stack/l2cap/l2c_link.c
index 4bb2be7..1974bb2 100644
--- a/stack/l2cap/l2c_link.c
+++ b/stack/l2cap/l2c_link.c
@@ -1394,19 +1394,19 @@
             (*p_lcb->p_nocp_cb)(p_lcb->remote_bd_addr);
         }
 
-#if (BLE_INCLUDED == TRUE)
-        if (p_lcb && p_lcb->is_ble_link)
-            l2cb.controller_le_xmit_window += num_sent;
-        else
-#endif
-        {
-
-            /* Maintain the total window to the controller */
-            l2cb.controller_xmit_window += num_sent;
-        }
-
         if (p_lcb)
         {
+#if (BLE_INCLUDED == TRUE)
+            if (p_lcb->is_ble_link)
+            {
+                l2cb.controller_le_xmit_window += num_sent;
+            }
+            else
+#endif
+            {
+                /* Maintain the total window to the controller */
+                l2cb.controller_xmit_window += num_sent;
+            }
             /* If doing round-robin, adjust communal counts */
             if (p_lcb->link_xmit_quota == 0)
             {
diff --git a/stack/l2cap/l2c_utils.c b/stack/l2cap/l2c_utils.c
index c684118..b911db2 100644
--- a/stack/l2cap/l2c_utils.c
+++ b/stack/l2cap/l2c_utils.c
@@ -183,6 +183,15 @@
     if (l2cb.num_links_active >= 1)
         l2cb.num_links_active--;
 
+    if (p_lcb->sent_not_acked > 0)
+    {
+        l2cb.controller_xmit_window += p_lcb->sent_not_acked;
+        if (l2cb.controller_xmit_window > l2cb.num_lm_acl_bufs)
+        {
+            l2cb.controller_xmit_window = l2cb.num_lm_acl_bufs;
+        }
+    }
+
     l2c_link_adjust_allocation();
 
     /* Check for ping outstanding */