Parse LMP features to enable LE support

Only send LE commands if the local Bluetooth radio supports LE.
Improved remote feature parsing by reading extended features. Before
this change, only the first page of the features was parsed.
bug 8332905

Change-Id: I0b90771dcfc453efea157f463b9df006e0178609
diff --git a/bta/dm/bta_dm_act.c b/bta/dm/bta_dm_act.c
index 63f81d2..e1acad6 100644
--- a/bta/dm/bta_dm_act.c
+++ b/bta/dm/bta_dm_act.c
@@ -56,7 +56,7 @@
 #if (BTM_BUSY_LEVEL_CHANGE_INCLUDED == TRUE)
 static void bta_dm_bl_change_cback (tBTM_BL_EVENT_DATA *p_data);
 #else
-static void bta_dm_acl_change_cback (BD_ADDR p_bda, DEV_CLASS p_dc, BD_NAME p_bdn, BD_FEATURES features, BOOLEAN is_new);
+static void bta_dm_acl_change_cback (BD_ADDR p_bda, DEV_CLASS p_dc, BD_NAME p_bdn, UINT8 *features, BOOLEAN is_new);
 #endif
 static void bta_dm_policy_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
 
@@ -3230,7 +3230,7 @@
 **
 *******************************************************************************/
 static void bta_dm_acl_change_cback (BD_ADDR p_bda, DEV_CLASS p_dc, BD_NAME p_bdn,
-                                     BD_FEATURES features, BOOLEAN is_new)
+                                     UINT8 *features, BOOLEAN is_new)
 {
 
     tBTA_DM_ACL_CHANGE * p_msg;
@@ -4072,8 +4072,12 @@
 
     UINT8_TO_STREAM(p, local_name_len + 1);
     UINT8_TO_STREAM(p, data_type);
-    memcpy(p, local_name, local_name_len);
-    p += local_name_len;
+
+    if (local_name != NULL)
+    {
+        memcpy(p, local_name, local_name_len);
+        p += local_name_len;
+    }
     free_eir_length -= local_name_len + 2;
 
 #if (BTA_EIR_CANNED_UUID_LIST == TRUE)
diff --git a/bta/dm/bta_dm_api.c b/bta/dm/bta_dm_api.c
index aedbe81..a81618d 100644
--- a/bta/dm/bta_dm_api.c
+++ b/bta/dm/bta_dm_api.c
@@ -350,11 +350,20 @@
         {
             p_msg->hdr.event = BTA_DM_API_VENDOR_SPECIFIC_COMMAND_EVT;
             p_msg->opcode = opcode;
-            p_msg->param_len = param_len;
             p_msg->p_param_buf = (UINT8 *)(p_msg + 1);
             p_msg->p_cback = p_cback;
 
-            memcpy (p_msg->p_param_buf, p_param_buf, param_len);
+            if (p_param_buf && param_len)
+            {
+                memcpy (p_msg->p_param_buf, p_param_buf, param_len);
+                p_msg->param_len = param_len;
+            }
+            else
+            {
+                p_msg->param_len = 0;
+                p_msg->p_param_buf = NULL;
+
+            }
 
             bta_sys_sendmsg(p_msg);
         }
@@ -726,7 +735,7 @@
         }
 
         memset (p_msg->bd_name, 0, BD_NAME_LEN);
-        memset (p_msg->features, 0, BD_FEATURES_LEN);
+        memset (p_msg->features, 0, sizeof (p_msg->features));
 
         bta_sys_sendmsg(p_msg);
     }
@@ -776,7 +785,7 @@
 **
 *******************************************************************************/
 void BTA_DmAddDevWithName (BD_ADDR bd_addr, DEV_CLASS dev_class,
-                                      BD_NAME bd_name, BD_FEATURES features,
+                                      BD_NAME bd_name, UINT8 *features,
                                       LINK_KEY link_key, tBTA_SERVICE_MASK trusted_mask,
                                       BOOLEAN is_trusted, UINT8 key_type, tBTA_IO_CAP io_cap)
 {
@@ -810,7 +819,7 @@
             memcpy(p_msg->bd_name, bd_name, BD_NAME_LEN);
 
         if (features)
-            memcpy(p_msg->features, features, BD_FEATURES_LEN);
+            memcpy(p_msg->features, features, sizeof(p_msg->features));
 
         bta_sys_sendmsg(p_msg);
     }
diff --git a/bta/dm/bta_dm_int.h b/bta/dm/bta_dm_int.h
index 245c871..3ca57a7 100644
--- a/bta/dm/bta_dm_int.h
+++ b/bta/dm/bta_dm_int.h
@@ -398,7 +398,7 @@
     BOOLEAN             link_key_known;
     BOOLEAN             dc_known;
     BD_NAME             bd_name;
-    BD_FEATURES         features;
+    UINT8               features[BTA_FEATURE_BYTES_PER_PAGE * (BTA_EXT_FEATURES_PAGE_MAX + 1)];
 } tBTA_DM_API_ADD_DEVICE;
 
 /* data type for BTA_DM_API_REMOVE_ACL_EVT */
diff --git a/bta/include/bta_api.h b/bta/include/bta_api.h
index 042e487..26302bc 100644
--- a/bta/include/bta_api.h
+++ b/bta/include/bta_api.h
@@ -434,6 +434,7 @@
 #define BTA_DM_BLE_PF_MANU_DATA            BTM_BLE_PF_MANU_DATA
 #define BTA_DM_BLE_PF_SRVC_DATA            BTM_BLE_PF_SRVC_DATA
 #define BTA_DM_BLE_PF_TYPE_MAX             BTM_BLE_PF_TYPE_MAX
+#define BTA_DM_BLE_PF_TYPE_ALL             BTM_BLE_PF_TYPE_ALL
 typedef UINT8   tBTA_DM_BLE_PF_COND_TYPE;
 
 typedef struct
@@ -996,6 +997,10 @@
 #define         BTA_DI_NUM_MAX       3
 #endif
 
+/* Device features mask definitions */
+#define BTA_FEATURE_BYTES_PER_PAGE  BTM_FEATURE_BYTES_PER_PAGE
+#define BTA_EXT_FEATURES_PAGE_MAX   BTM_EXT_FEATURES_PAGE_MAX
+
 /*****************************************************************************
 **  External Function Declarations
 *****************************************************************************/
@@ -1354,9 +1359,13 @@
 **
 ** Returns          void
 **
+** Note:            features points to the remote device features array.
+**                  The array size is
+**                  BTA_FEATURE_BYTES_PER_PAGE * (BTA_EXT_FEATURES_PAGE_MAX + 1)
+**
 *******************************************************************************/
 BTA_API extern void BTA_DmAddDevWithName (BD_ADDR bd_addr, DEV_CLASS dev_class,
-                                      BD_NAME bd_name, BD_FEATURES features,
+                                      BD_NAME bd_name, UINT8 *features,
                                       LINK_KEY link_key, tBTA_SERVICE_MASK trusted_mask,
                                       BOOLEAN is_trusted, UINT8 key_type, tBTA_IO_CAP io_cap);
 
diff --git a/stack/btm/btm_acl.c b/stack/btm/btm_acl.c
index eb847bb..ac173a5 100644
--- a/stack/btm/btm_acl.c
+++ b/stack/btm/btm_acl.c
@@ -37,7 +37,13 @@
 #include "btm_int.h"
 #include "l2c_int.h"
 #include "hcidefs.h"
+
 static void btm_establish_continue (tACL_CONN *p_acl_cb);
+static void btm_read_remote_features (UINT16 handle);
+static void btm_read_remote_ext_features (UINT16 handle, UINT8 page_number);
+static void btm_process_remote_ext_features_page (tACL_CONN *p_acl_cb, tBTM_SEC_DEV_REC *p_dev_rec,
+                                                  UINT8 page_idx);
+static void btm_process_remote_ext_features (tACL_CONN *p_acl_cb, UINT8 num_read_pages);
 
 #define BTM_DEV_REPLY_TIMEOUT   3       /* 3 second timeout waiting for responses */
 
@@ -96,7 +102,6 @@
             }
         }
     }
-    BTM_TRACE_DEBUG0 ("btm_bda_to_acl Not found");
 
     /* If here, no BD Addr found */
     return((tACL_CONN *)NULL);
@@ -216,27 +221,27 @@
 
             if (p_dev_rec && !is_le_link)
             {
-
-                for (yy = 0; yy < BD_FEATURES_LEN; yy++)
+                /* If remote features already known, copy them and continue connection setup */
+                if ((p_dev_rec->num_read_pages) &&
+                    (p_dev_rec->num_read_pages <= (HCI_EXT_FEATURES_PAGE_MAX + 1)) /* sanity check */)
                 {
-                    if (p_dev_rec->features[yy])
-                    {
-                        memcpy (p->features, p_dev_rec->features, BD_FEATURES_LEN);
-                        if (BTM_SEC_MODE_SP == btm_cb.security_mode &&
-                            HCI_SIMPLE_PAIRING_SUPPORTED(p->features))
-                        {
-                            /* if SM4 supported, check peer support for SM4
-                             * The remote controller supports SSP according to saved remote features
-                             * read the extended feature page 1 for the host support for SSP */
-                            if (btsnd_hcic_rmt_ext_features (p_dev_rec->hci_handle, 1))
-                                return;
-                        }
-                        /* peer does not support SSP */
-                        p_dev_rec->sm4 |= BTM_SM4_KNOWN;
+                    memcpy (p->peer_lmp_features, p_dev_rec->features,
+                        (HCI_FEATURE_BYTES_PER_PAGE * p_dev_rec->num_read_pages));
+                    p->num_read_pages = p_dev_rec->num_read_pages;
 
-                        btm_establish_continue (p);
-                        return;
+                    if (BTM_SEC_MODE_SP == btm_cb.security_mode
+                        && HCI_SSP_HOST_SUPPORTED(p_dev_rec->features[HCI_EXT_FEATURES_PAGE_1])
+                        && HCI_SIMPLE_PAIRING_SUPPORTED(p_dev_rec->features[HCI_EXT_FEATURES_PAGE_0]))
+                    {
+                        p_dev_rec->sm4 = BTM_SM4_TRUE;
                     }
+                    else
+                    {
+                        p_dev_rec->sm4 |= BTM_SM4_KNOWN;
+                    }
+
+                    btm_establish_continue (p);
+                    return;
                 }
             }
 
@@ -278,8 +283,8 @@
 {
     tBTM_ROLE_SWITCH_CMPL   ref_data;
     BTM_TRACE_DEBUG0 ("btm_acl_report_role_change");
-    if (btm_cb.devcb.p_switch_role_cb && (bda &&
-                                          (0 == memcmp(btm_cb.devcb.switch_role_ref_data.remote_bd_addr, bda, BD_ADDR_LEN))))
+    if (btm_cb.devcb.p_switch_role_cb
+        && (bda && (0 == memcmp(btm_cb.devcb.switch_role_ref_data.remote_bd_addr, bda, BD_ADDR_LEN))))
     {
         memcpy (&ref_data, &btm_cb.devcb.switch_role_ref_data, sizeof(tBTM_ROLE_SWITCH_CMPL));
         ref_data.hci_status = hci_status;
@@ -370,7 +375,8 @@
             else
             {
                 BTM_TRACE_DEBUG0("Bletooth link down");
-                p_dev_rec->sec_flags &= ~(BTM_SEC_AUTHORIZED | BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED | BTM_SEC_ROLE_SWITCHED);
+                p_dev_rec->sec_flags &= ~(BTM_SEC_AUTHORIZED | BTM_SEC_AUTHENTICATED
+                                        | BTM_SEC_ENCRYPTED | BTM_SEC_ROLE_SWITCHED);
             }
             BTM_TRACE_DEBUG1("after update p_dev_rec->sec_flags=0x%x", p_dev_rec->sec_flags);
         }
@@ -554,7 +560,7 @@
                     remote_bd_addr[3], remote_bd_addr[4], remote_bd_addr[5]);
 
     /* Make sure the local device supports switching */
-    if (!(HCI_SWITCH_SUPPORTED(btm_cb.devcb.local_features)))
+    if (!(HCI_SWITCH_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0])))
         return(BTM_MODE_UNSUPPORTED);
 
     if (btm_cb.devcb.p_switch_role_cb && p_cb)
@@ -699,7 +705,8 @@
     /* Ignore change link key request if the previsous request has not completed */
     if (p->change_key_state != BTM_ACL_SWKEY_STATE_IDLE)
     {
-        BTM_TRACE_DEBUG0 ("Link key change request declined since the previous request for this device has not completed ");
+        BTM_TRACE_DEBUG0 ("Link key change request declined since the previous request"
+                          " for this device has not completed ");
         return(BTM_BUSY);
     }
 
@@ -847,7 +854,8 @@
     tBTM_BL_ROLE_CHG_DATA   evt;
 #endif
 
-    BTM_TRACE_DEBUG3 ("btm_acl_encrypt_change handle=%d status=%d encr_enabl=%d", handle, status, encr_enable);
+    BTM_TRACE_DEBUG3 ("btm_acl_encrypt_change handle=%d status=%d encr_enabl=%d",
+                      handle, status, encr_enable);
     xx = btm_handle_to_acl_index(handle);
     /* don't assume that we can never get a bad hci_handle */
     if (xx < MAX_L2CAP_LINKS)
@@ -1004,7 +1012,8 @@
     }
 
     if ((p = btm_bda_to_acl(remote_bda)) != NULL)
-        return(btsnd_hcic_write_policy_set (p->hci_handle, *settings) ? BTM_CMD_STARTED : BTM_NO_RESOURCES);
+        return(btsnd_hcic_write_policy_set (p->hci_handle, *settings) ?
+                                                BTM_CMD_STARTED : BTM_NO_RESOURCES);
 
     /* If here, no BD Addr found */
     return(BTM_UNKNOWN_ADDR);
@@ -1191,9 +1200,177 @@
 
 /*******************************************************************************
 **
+** Function         btm_process_remote_ext_features
+**
+** Description      Local function called to process all extended features pages
+**                  read from a remote device.
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_process_remote_ext_features (tACL_CONN *p_acl_cb, UINT8 num_read_pages)
+{
+    UINT16              handle = p_acl_cb->hci_handle;
+    tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_dev_by_handle (handle);
+    UINT8               page_idx;
+
+    BTM_TRACE_DEBUG0 ("btm_process_remote_ext_features");
+
+    /* Make sure we have the record to save remote features information */
+    if (p_dev_rec == NULL)
+    {
+        /* Get a new device; might be doing dedicated bonding */
+        p_dev_rec = btm_find_or_alloc_dev (p_acl_cb->remote_addr);
+    }
+
+    p_acl_cb->num_read_pages = num_read_pages;
+    p_dev_rec->num_read_pages = num_read_pages;
+
+    /* Process the pages one by one */
+    for (page_idx = 0; page_idx < num_read_pages; page_idx++)
+    {
+        btm_process_remote_ext_features_page (p_acl_cb, p_dev_rec, page_idx);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         btm_process_remote_ext_features_page
+**
+** Description      Local function called to process the information located
+**                  in the specific extended features page read from a remote device.
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_process_remote_ext_features_page (tACL_CONN *p_acl_cb, tBTM_SEC_DEV_REC *p_dev_rec,
+                                           UINT8 page_idx)
+{
+    UINT16            handle;
+    UINT8             req_pend;
+
+    handle = p_acl_cb->hci_handle;
+
+    memcpy (p_dev_rec->features[page_idx], p_acl_cb->peer_lmp_features[page_idx],
+            HCI_FEATURE_BYTES_PER_PAGE);
+
+    switch (page_idx)
+    {
+    /* Extended (Legacy) Page 0 */
+    case HCI_EXT_FEATURES_PAGE_0:
+        /* Page 0 indicates Controller support for SSP */
+        if (btm_cb.security_mode < BTM_SEC_MODE_SP ||
+            !HCI_SIMPLE_PAIRING_SUPPORTED(p_dev_rec->features[HCI_EXT_FEATURES_PAGE_0]))
+        {
+            req_pend = (p_dev_rec->sm4 & BTM_SM4_REQ_PEND);
+            p_dev_rec->sm4 = BTM_SM4_KNOWN;
+            if (req_pend)
+            {
+                l2cu_resubmit_pending_sec_req (p_dev_rec->bd_addr);
+            }
+        }
+        break;
+
+    /* Extended Page 1 */
+    case HCI_EXT_FEATURES_PAGE_1:
+        /* Page 1 indicates Host support for SSP and SC */
+        req_pend = (p_dev_rec->sm4 & BTM_SM4_REQ_PEND);
+
+        if (btm_cb.security_mode == BTM_SEC_MODE_SP
+            && HCI_SSP_HOST_SUPPORTED(p_dev_rec->features[HCI_EXT_FEATURES_PAGE_1])
+            && HCI_SIMPLE_PAIRING_SUPPORTED(p_dev_rec->features[HCI_EXT_FEATURES_PAGE_0]))
+        {
+            p_dev_rec->sm4 = BTM_SM4_TRUE;
+        }
+        else
+        {
+            p_dev_rec->sm4 = BTM_SM4_KNOWN;
+        }
+
+        BTM_TRACE_API4 ("ext_features_complt page_num:%d f[0]:x%02x, sm4:%x, pend:%d",
+                        HCI_EXT_FEATURES_PAGE_1, *(p_dev_rec->features[HCI_EXT_FEATURES_PAGE_1]),
+                        p_dev_rec->sm4, req_pend);
+
+        if (req_pend)
+            l2cu_resubmit_pending_sec_req (p_dev_rec->bd_addr);
+
+        break;
+
+    /* Extended Page 2 */
+    case HCI_EXT_FEATURES_PAGE_2:
+        /* Page 2 indicates Ping support*/
+        break;
+
+    default:
+        BTM_TRACE_ERROR1("btm_process_remote_ext_features_page page=%d unexpected", page_idx);
+        break;
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         btm_read_remote_features
+**
+** Description      Local function called to send a read remote supported features/
+**                  remote extended features page[0].
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_read_remote_features (UINT16 handle)
+{
+    UINT8       acl_idx;
+    tACL_CONN   *p_acl_cb;
+
+    BTM_TRACE_DEBUG1("btm_read_remote_features() handle: %d", handle);
+
+    if ((acl_idx = btm_handle_to_acl_index(handle)) >= MAX_L2CAP_LINKS)
+    {
+        BTM_TRACE_ERROR1("btm_read_remote_features handle=%d invalid", handle);
+        return;
+    }
+
+    p_acl_cb = &btm_cb.acl_db[acl_idx];
+    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);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         btm_read_remote_ext_features
+**
+** Description      Local function called to send a read remote extended features
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_read_remote_ext_features (UINT16 handle, UINT8 page_number)
+{
+    BTM_TRACE_DEBUG2("btm_read_remote_ext_features() handle: %d page: %d", handle, page_number);
+
+    btsnd_hcic_rmt_ext_features(handle, page_number);
+}
+
+
+/*******************************************************************************
+**
 ** Function         btm_read_remote_features_complete
 **
-** Description      This function is called when the remote extended features
+** Description      This function is called when the remote supported features
 **                  complete event is received from the HCI.
 **
 ** Returns          void
@@ -1201,59 +1378,39 @@
 *******************************************************************************/
 void btm_read_remote_features_complete (UINT8 *p)
 {
-    tACL_CONN        *p_acl_cb = &btm_cb.acl_db[0];
+    tACL_CONN        *p_acl_cb;
     UINT8             status;
     UINT16            handle;
-    int               xx, yy;
-    UINT8             req_pend;
-    tBTM_SEC_DEV_REC *p_dev_rec;
+    UINT8            acl_idx;
+
     BTM_TRACE_DEBUG0 ("btm_read_remote_features_complete");
     STREAM_TO_UINT8  (status, p);
-    if (status == HCI_SUCCESS)
+
+    if (status != HCI_SUCCESS)
     {
+        BTM_TRACE_ERROR1 ("btm_read_remote_features_complete failed (status 0x%02x)", status);
+        return;
+    }
+
         STREAM_TO_UINT16 (handle, p);
 
-        /* Look up the connection by handle and copy features */
-        for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_acl_cb++)
+    if ((acl_idx = btm_handle_to_acl_index(handle)) >= MAX_L2CAP_LINKS)
         {
-            if ((p_acl_cb->in_use) && (p_acl_cb->hci_handle == handle))
-            {
-                for (yy = 0; yy < BD_FEATURES_LEN; yy++)
-                    STREAM_TO_UINT8 (p_acl_cb->features[yy], p);
-
-                p_dev_rec = btm_find_dev_by_handle (handle);
-                if (!p_dev_rec)
-                {
-                    /* Get a new device; might be doing dedicated bonding */
-                    p_dev_rec = btm_find_or_alloc_dev (p_acl_cb->remote_addr);
+        BTM_TRACE_ERROR1("btm_read_remote_features_complete handle=%d invalid", handle);
+        return;
                 }
 
-                memcpy (p_dev_rec->features, p_acl_cb->features, BD_FEATURES_LEN);
+    p_acl_cb = &btm_cb.acl_db[acl_idx];
 
-                if (BTM_SEC_MODE_SP == btm_cb.security_mode &&
-                    HCI_SIMPLE_PAIRING_SUPPORTED(p_acl_cb->features))
-                {
-                    /* if SM4 supported, check peer support for SM4
-                     * The remote controller supports SSP
-                     * read the extended feature page 1 for the host support for SSP */
-                    if (btsnd_hcic_rmt_ext_features (handle, 1))
-                        break;
-                }
-                else
-                {
-                    req_pend = (p_dev_rec->sm4 & BTM_SM4_REQ_PEND);
-                    p_dev_rec->sm4 = BTM_SM4_KNOWN;
-                    if (req_pend)
-                    {
-                        l2cu_resubmit_pending_sec_req (p_dev_rec->bd_addr);
-                    }
-                }
+    /* Copy the received features page */
+    STREAM_TO_ARRAY(p_acl_cb->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0], p,
+                    HCI_FEATURE_BYTES_PER_PAGE);
 
-                btm_establish_continue (p_acl_cb);
-                break;
-            }
-        }
-    }
+    /* Process this features page */
+    btm_process_remote_ext_features (p_acl_cb, 1);
+
+    /* Continue with HCI connection establishment */
+    btm_establish_continue (p_acl_cb);
 }
 
 /*******************************************************************************
@@ -1268,60 +1425,62 @@
 *******************************************************************************/
 void btm_read_remote_ext_features_complete (UINT8 *p)
 {
-    tACL_CONN        *p_acl_cb = &btm_cb.acl_db[0];
-    tBTM_SEC_DEV_REC *p_dev_rec;
-    UINT8             status, page_num, max_page;
-    UINT16            handle;
-    int               xx;
-    BD_FEATURES       ext_features;       /* extended Features suported by the device    */
-    UINT8             req_pend;
+    tACL_CONN   *p_acl_cb;
+    UINT8       status, page_num, max_page;
+    UINT16      handle;
+    UINT8       acl_idx;
+
     BTM_TRACE_DEBUG0 ("btm_read_remote_ext_features_complete");
+
     STREAM_TO_UINT8  (status, p);
-    if (status == HCI_SUCCESS)
+
+    if (status != HCI_SUCCESS)
     {
-        STREAM_TO_UINT16 (handle, p);
-
-        /* Look up the connection by handle and copy features */
-        for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_acl_cb++)
-        {
-            if ((p_acl_cb->in_use) && (p_acl_cb->hci_handle == handle))
-            {
-                STREAM_TO_UINT8  (page_num, p);
-                STREAM_TO_UINT8  (max_page, p);
-                p_dev_rec = btm_find_dev_by_handle (handle);
-                if (!p_dev_rec)
-                    p_dev_rec = btm_find_or_alloc_dev (p_acl_cb->remote_addr);
-
-                req_pend = (p_dev_rec->sm4 & BTM_SM4_REQ_PEND);
-
-                if (page_num == 1 && max_page >= 1)
-                {
-                    /* only the byte 0 of page 1 is used right now */
-                    STREAM_TO_UINT8 (ext_features[0], p);
-
-                    if (HCI_SSP_HOST_SUPPORTED(ext_features))
-                    {
-                        p_dev_rec->sm4 = BTM_SM4_TRUE;
-                    }
-                }
-
-                BTM_TRACE_API5 ("ext_features_complt page_num:%d max_page:%d f[0]:x%02x, sm4:%x, pend:%d",
-                                page_num, max_page, *p, p_dev_rec->sm4, req_pend);
-
-                if (!BTM_SEC_IS_SM4(p_dev_rec->sm4))
-                {
-                    p_dev_rec->sm4 = BTM_SM4_KNOWN;
-                }
-
-                if (req_pend)
-                    l2cu_resubmit_pending_sec_req (p_dev_rec->bd_addr);
-
-                btm_establish_continue (p_acl_cb);
-
-                break;
-            }
-        }
+        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);
+
+    /* Validate parameters */
+    if ((acl_idx = btm_handle_to_acl_index(handle)) >= MAX_L2CAP_LINKS)
+    {
+        BTM_TRACE_ERROR1("btm_read_remote_ext_features_complete handle=%d invalid", handle);
+        return;
+    }
+
+    if (max_page > HCI_EXT_FEATURES_PAGE_MAX)
+    {
+        BTM_TRACE_ERROR1("btm_read_remote_ext_features_complete page=%d unknown", max_page);
+        return;
+    }
+
+    p_acl_cb = &btm_cb.acl_db[acl_idx];
+
+    /* Copy the received features page */
+    STREAM_TO_ARRAY(p_acl_cb->peer_lmp_features[page_num], p, HCI_FEATURE_BYTES_PER_PAGE);
+
+    /* If there is the next remote features page and
+     * we have space to keep this page data - read this page */
+    if ((page_num < max_page) && (page_num < HCI_EXT_FEATURES_PAGE_MAX))
+    {
+        page_num++;
+        BTM_TRACE_DEBUG1("BTM reads next remote extended features page (%d)", page_num);
+        btm_read_remote_ext_features (handle, page_num);
+        return;
+    }
+
+    /* Reading of remote feature pages is complete */
+    BTM_TRACE_DEBUG1("BTM reached last remote extended features page (%d)", page_num);
+
+    /* Process the pages */
+    btm_process_remote_ext_features (p_acl_cb, (UINT8) (page_num + 1));
+
+    /* Continue with HCI connection establishment */
+    btm_establish_continue (p_acl_cb);
 }
 
 /*******************************************************************************
@@ -1379,7 +1538,8 @@
         evt_data.conn.p_bda = p_acl_cb->remote_addr;
         evt_data.conn.p_bdn = p_acl_cb->remote_name;
         evt_data.conn.p_dc  = p_acl_cb->remote_dc;
-        evt_data.conn.p_features = p_acl_cb->features;
+        evt_data.conn.p_features = p_acl_cb->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0];
+
 
         (*btm_cb.p_bl_changed_cb)(&evt_data);
     }
@@ -1389,7 +1549,7 @@
         (*btm_cb.p_acl_changed_cb) (p_acl_cb->remote_addr,
                                     p_acl_cb->remote_dc,
                                     p_acl_cb->remote_name,
-                                    p_acl_cb->features,
+                                    p_acl_cb->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0],
                                     TRUE);
 #endif
 }
@@ -1991,7 +2151,8 @@
 *******************************************************************************/
 void btm_acl_role_changed (UINT8 hci_status, BD_ADDR bd_addr, UINT8 new_role)
 {
-    UINT8                   *p_bda = (bd_addr) ? bd_addr : btm_cb.devcb.switch_role_ref_data.remote_bd_addr;
+    UINT8                   *p_bda = (bd_addr) ? bd_addr :
+                                        btm_cb.devcb.switch_role_ref_data.remote_bd_addr;
     tACL_CONN               *p = btm_bda_to_acl(p_bda);
     tBTM_ROLE_SWITCH_CMPL   *p_data = &btm_cb.devcb.switch_role_ref_data;
     tBTM_SEC_DEV_REC        *p_dev_rec;
@@ -2090,7 +2251,8 @@
             BTM_TRACE_WARNING0("btm_acl_role_changed -> Issuing delayed HCI_Disconnect!!!");
             btsnd_hcic_disconnect(p_dev_rec->hci_handle, HCI_ERR_PEER_USER);
         }
-        BTM_TRACE_ERROR2("tBTM_SEC_DEV:0x%x rs_disc_pending=%d", (UINT32)p_dev_rec, p_dev_rec->rs_disc_pending);
+        BTM_TRACE_ERROR2("tBTM_SEC_DEV:0x%x rs_disc_pending=%d",
+                         (UINT32)p_dev_rec, p_dev_rec->rs_disc_pending);
         p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING;     /* reset flag */
     }
 
@@ -2357,7 +2519,7 @@
 **
 ** Function         BTM_ReadRemoteFeatures
 **
-** Returns          pointer to the features string
+** Returns          pointer to the remote supported features mask (8 bytes)
 **
 *******************************************************************************/
 UINT8 *BTM_ReadRemoteFeatures (BD_ADDR addr)
@@ -2369,7 +2531,71 @@
         return(NULL);
     }
 
-    return(p->features);
+    return(p->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0]);
+}
+
+/*******************************************************************************
+**
+** Function         BTM_ReadRemoteExtendedFeatures
+**
+** Returns          pointer to the remote extended features mask (8 bytes)
+**                  or NULL if bad page
+**
+*******************************************************************************/
+UINT8 *BTM_ReadRemoteExtendedFeatures (BD_ADDR addr, UINT8 page_number)
+{
+    tACL_CONN        *p = btm_bda_to_acl(addr);
+    BTM_TRACE_DEBUG0 ("BTM_ReadRemoteExtendedFeatures");
+    if (p == NULL)
+    {
+        return(NULL);
+    }
+
+    if (page_number > HCI_EXT_FEATURES_PAGE_MAX)
+    {
+        BTM_TRACE_ERROR1("Warning: BTM_ReadRemoteExtendedFeatures page %d unknown", page_number);
+        return NULL;
+    }
+
+    return(p->peer_lmp_features[page_number]);
+}
+
+/*******************************************************************************
+**
+** Function         BTM_ReadNumberRemoteFeaturesPages
+**
+** Returns          number of features pages read from the remote device.
+**
+*******************************************************************************/
+UINT8 BTM_ReadNumberRemoteFeaturesPages (BD_ADDR addr)
+{
+    tACL_CONN        *p = btm_bda_to_acl(addr);
+    BTM_TRACE_DEBUG0 ("BTM_ReadNumberRemoteFeaturesPages");
+    if (p == NULL)
+    {
+        return(0);
+    }
+
+    return(p->num_read_pages);
+}
+
+/*******************************************************************************
+**
+** Function         BTM_ReadAllRemoteFeatures
+**
+** Returns          pointer to all features of the remote (24 bytes).
+**
+*******************************************************************************/
+UINT8 *BTM_ReadAllRemoteFeatures (BD_ADDR addr)
+{
+    tACL_CONN        *p = btm_bda_to_acl(addr);
+    BTM_TRACE_DEBUG0 ("BTM_ReadAllRemoteFeatures");
+    if (p == NULL)
+    {
+        return(NULL);
+    }
+
+    return(p->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0]);
 }
 
 /*******************************************************************************
@@ -2451,7 +2677,8 @@
         btm_cb.devcb.p_qossu_cmpl_cb = p_cb;
 
         if (!btsnd_hcic_qos_setup (p->hci_handle, p_flow->qos_flags, p_flow->service_type,
-                                   p_flow->token_rate, p_flow->peak_bandwidth, p_flow->latency,p_flow->delay_variation))
+                                   p_flow->token_rate, p_flow->peak_bandwidth,
+                                   p_flow->latency,p_flow->delay_variation))
         {
             btm_cb.devcb.p_qossu_cmpl_cb = NULL;
             btu_stop_timer(&btm_cb.devcb.qossu_timer);
@@ -2788,7 +3015,7 @@
     tACL_CONN               *p_acl_cb = &btm_cb.acl_db[0];
     UINT16                   index;
     BTM_TRACE_DEBUG0 ("btm_read_link_quality_complete");
-    btu_stop_timer (&btm_cb.devcb.rssi_timer);
+    btu_stop_timer (&btm_cb.devcb.lnk_quality_timer);
 
     /* If there was a callback registered for read rssi, call it */
     btm_cb.devcb.p_lnk_qual_cmpl_cb = NULL;
@@ -3056,8 +3283,10 @@
         if (!BTM_ACL_IS_CONNECTED (bda))
         {
             BTM_TRACE_DEBUG2 ("connecting_bda: %06x%06x",
-                              (btm_cb.connecting_bda[0]<<16) + (btm_cb.connecting_bda[1]<<8) + btm_cb.connecting_bda[2],
-                              (btm_cb.connecting_bda[3]<<16) + (btm_cb.connecting_bda[4] << 8) + btm_cb.connecting_bda[5]);
+                              (btm_cb.connecting_bda[0]<<16) + (btm_cb.connecting_bda[1]<<8) +
+                               btm_cb.connecting_bda[2],
+                              (btm_cb.connecting_bda[3]<<16) + (btm_cb.connecting_bda[4] << 8) +
+                               btm_cb.connecting_bda[5]);
             if (btm_cb.paging &&
                 memcmp (bda, btm_cb.connecting_bda, BD_ADDR_LEN) != 0)
             {
@@ -3128,32 +3357,35 @@
 void btm_acl_chk_peer_pkt_type_support (tACL_CONN *p, UINT16 *p_pkt_type)
 {
     /* 3 and 5 slot packets? */
-    if (!HCI_3_SLOT_PACKETS_SUPPORTED(p->features))
+    if (!HCI_3_SLOT_PACKETS_SUPPORTED(p->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
         *p_pkt_type &= ~(BTM_ACL_PKT_TYPES_MASK_DH3 +BTM_ACL_PKT_TYPES_MASK_DM3);
 
-    if (!HCI_5_SLOT_PACKETS_SUPPORTED(p->features))
+    if (!HCI_5_SLOT_PACKETS_SUPPORTED(p->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
         *p_pkt_type &= ~(BTM_ACL_PKT_TYPES_MASK_DH5 + BTM_ACL_PKT_TYPES_MASK_DM5);
 
     /* If HCI version > 2.0, then also check EDR packet types */
     if (btm_cb.devcb.local_version.hci_version >= HCI_PROTO_VERSION_2_0)
     {
         /* 2 and 3 MPS support? */
-        if (!HCI_EDR_ACL_2MPS_SUPPORTED(p->features))
+        if (!HCI_EDR_ACL_2MPS_SUPPORTED(p->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
             /* Not supported. Add 'not_supported' mask for all 2MPS packet types */
-            *p_pkt_type |= (BTM_ACL_PKT_TYPES_MASK_NO_2_DH1 + BTM_ACL_PKT_TYPES_MASK_NO_2_DH3 + BTM_ACL_PKT_TYPES_MASK_NO_2_DH5);
+            *p_pkt_type |= (BTM_ACL_PKT_TYPES_MASK_NO_2_DH1 + BTM_ACL_PKT_TYPES_MASK_NO_2_DH3 +
+                                BTM_ACL_PKT_TYPES_MASK_NO_2_DH5);
 
-        if (!HCI_EDR_ACL_3MPS_SUPPORTED(p->features))
+        if (!HCI_EDR_ACL_3MPS_SUPPORTED(p->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
             /* Not supported. Add 'not_supported' mask for all 3MPS packet types */
-            *p_pkt_type |= (BTM_ACL_PKT_TYPES_MASK_NO_3_DH1 + BTM_ACL_PKT_TYPES_MASK_NO_3_DH3 + BTM_ACL_PKT_TYPES_MASK_NO_3_DH5);
+            *p_pkt_type |= (BTM_ACL_PKT_TYPES_MASK_NO_3_DH1 + BTM_ACL_PKT_TYPES_MASK_NO_3_DH3 +
+                                BTM_ACL_PKT_TYPES_MASK_NO_3_DH5);
 
         /* EDR 3 and 5 slot support? */
-        if (HCI_EDR_ACL_2MPS_SUPPORTED(p->features) || HCI_EDR_ACL_3MPS_SUPPORTED(p->features))
+        if (HCI_EDR_ACL_2MPS_SUPPORTED(p->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0])
+         || HCI_EDR_ACL_3MPS_SUPPORTED(p->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
         {
-            if (!HCI_3_SLOT_EDR_ACL_SUPPORTED(p->features))
+            if (!HCI_3_SLOT_EDR_ACL_SUPPORTED(p->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
                 /* Not supported. Add 'not_supported' mask for all 3-slot EDR packet types */
                 *p_pkt_type |= (BTM_ACL_PKT_TYPES_MASK_NO_2_DH3 + BTM_ACL_PKT_TYPES_MASK_NO_3_DH3);
 
-            if (!HCI_5_SLOT_EDR_ACL_SUPPORTED(p->features))
+            if (!HCI_5_SLOT_EDR_ACL_SUPPORTED(p->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
                 /* Not supported. Add 'not_supported' mask for all 5-slot EDR packet types */
                 *p_pkt_type |= (BTM_ACL_PKT_TYPES_MASK_NO_2_DH5 + BTM_ACL_PKT_TYPES_MASK_NO_3_DH5);
         }
diff --git a/stack/btm/btm_ble_gap.c b/stack/btm/btm_ble_gap.c
index d13e36b..12385a7 100644
--- a/stack/btm/btm_ble_gap.c
+++ b/stack/btm/btm_ble_gap.c
@@ -107,6 +107,9 @@
 
     BTM_TRACE_EVENT0 ("BTM_BleUpdateAdvFilterPolicy");
 
+    if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
+        return;
+
     if (p_cb->afp != adv_policy)
     {
         p_cb->afp = adv_policy;
@@ -152,6 +155,9 @@
 
     BTM_TRACE_EVENT0 ("BTM_BleObserve ");
 
+    if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
+        return BTM_ILLEGAL_VALUE;
+
     if (start)
     {
         /* shared inquiry database, do not allow observe if any inquiry is active */
@@ -211,6 +217,9 @@
     tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
     UINT8 evt_type = p_cb->scan_rsp ? BTM_BLE_DISCOVER_EVT: BTM_BLE_NON_CONNECT_EVT;
 
+    if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
+        return BTM_ILLEGAL_VALUE;
+
 #ifdef  BTM_BLE_PC_ADV_TEST_MODE
     if (BTM_BLE_PC_ADV_TEST_MODE)
     {
@@ -293,6 +302,8 @@
     BOOLEAN started = TRUE;
 
     BTM_TRACE_EVENT0 ("BTM_BleSetBgConnType ");
+    if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
+        return FALSE;
 
     if (btm_cb.ble_ctr_cb.bg_conn_type != bg_conn_type)
     {
@@ -374,6 +385,8 @@
     tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
 
     BTM_TRACE_EVENT1 ("BTM_BleSetConnMode is_directed = %d ", is_directed);
+    if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
+        return BTM_ILLEGAL_VALUE;
 
     p_cb->directed_conn = is_directed;
     return btm_ble_set_connectability( p_cb->connectable_mode);
@@ -442,6 +455,9 @@
 
     BTM_TRACE_EVENT0 ("BTM_BleSetAdvParams");
 
+    if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
+        return BTM_ILLEGAL_VALUE;
+
     if (!BTM_BLE_VALID_PRAM(adv_int_min, BTM_BLE_ADV_INT_MIN, BTM_BLE_ADV_INT_MAX) ||
         !BTM_BLE_VALID_PRAM(adv_int_max, BTM_BLE_ADV_INT_MIN, BTM_BLE_ADV_INT_MAX))
     {
@@ -500,6 +516,8 @@
     tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
 
     BTM_TRACE_EVENT0 ("BTM_BleReadAdvParams ");
+    if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
+        return ;
 
     *adv_int_min = p_cb->adv_interval_min;
     *adv_int_max = p_cb->adv_interval_max;
@@ -531,6 +549,8 @@
     tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
 
     BTM_TRACE_EVENT0 (" BTM_BleSetScanParams");
+    if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
+        return ;
 
     if (BTM_BLE_VALID_PRAM(scan_interval, BTM_BLE_SCAN_INT_MIN, BTM_BLE_SCAN_INT_MAX) &&
         BTM_BLE_VALID_PRAM(scan_window, BTM_BLE_SCAN_WIN_MIN, BTM_BLE_SCAN_WIN_MAX) &&
@@ -570,6 +590,10 @@
             *p = rsp_data;
 
     BTM_TRACE_EVENT0 (" BTM_BleWriteScanRsp");
+
+    if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
+        return BTM_ILLEGAL_VALUE;
+
     memset(rsp_data, 0, BTM_BLE_AD_DATA_LEN);
     btm_ble_build_adv_data(&data_mask, &p, p_data);
 
@@ -605,11 +629,15 @@
     UINT8  *p;
     UINT16   mask = data_mask;
 
+    BTM_TRACE_EVENT0 ("BTM_BleWriteAdvData ");
+
+    if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
+        return BTM_ILLEGAL_VALUE;
+
     memset(p_cb_data, 0, sizeof(tBTM_BLE_LOCAL_ADV_DATA));
     p = p_cb_data->ad_data;
     p_cb_data->data_mask = data_mask;
 
-    BTM_TRACE_EVENT0 ("BTM_BleWriteAdvData ");
     p_cb_data->p_flags = btm_ble_build_adv_data(&mask, &p, p_data);
 
     p_cb_data->p_pad = p;
@@ -1137,6 +1165,9 @@
 {
     tBTM_INQUIRY_VAR_ST      *p_inq = &btm_cb.btm_inq_vars;
 
+    if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
+        return BTM_ERR_PROCESSING;
+
     if (p_cur &&
         p_cur->results.ble_evt_type != BTM_BLE_EVT_CONN_ADV &&
         p_cur->results.ble_evt_type != BTM_BLE_EVT_CONN_DIR_ADV)
@@ -1854,8 +1885,6 @@
 *******************************************************************************/
 void btm_ble_timeout(TIMER_LIST_ENT *p_tle)
 {
-    BTM_TRACE_EVENT0 ("btm_ble_timeout");
-
     switch (p_tle->event)
     {
         case BTU_TTYPE_BLE_INQUIRY:
@@ -1895,32 +1924,21 @@
 void btm_ble_read_remote_features_complete(UINT8 *p)
 {
     tACL_CONN        *p_acl_cb = &btm_cb.acl_db[0];
-    UINT8             size;
+    UINT8             status;
     UINT16            handle;
-    int               xx, yy;
-    tBTM_SEC_DEV_REC *p_dev_rec;
+    int               xx;
 
     BTM_TRACE_EVENT0 ("btm_ble_read_remote_features_complete ");
 
-    STREAM_TO_UINT16  (handle, p);
-    STREAM_TO_UINT8  (size, p);
+    STREAM_TO_UINT8  (status, p);
+    STREAM_TO_UINT16 (handle, p);
 
     /* Look up the connection by handle and copy features */
     for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_acl_cb++)
     {
         if ((p_acl_cb->in_use) && (p_acl_cb->hci_handle == handle))
         {
-            for (yy = 0; yy < BD_FEATURES_LEN; yy++)
-                STREAM_TO_UINT8 (p_acl_cb->features[yy], p);
-
-            p_dev_rec = btm_find_dev_by_handle (handle);
-            if (!p_dev_rec)
-            {
-                /* Get a new device; might be doing dedicated bonding */
-                p_dev_rec = btm_find_or_alloc_dev (p_acl_cb->remote_addr);
-            }
-
-            memcpy (p_dev_rec->features, p_acl_cb->features, BD_FEATURES_LEN);
+            STREAM_TO_ARRAY(p_acl_cb->peer_le_features, p, BD_FEATURES_LEN);
             break;
         }
     }
diff --git a/stack/btm/btm_dev.c b/stack/btm/btm_dev.c
index 40919fa..0dd534c 100644
--- a/stack/btm/btm_dev.c
+++ b/stack/btm/btm_dev.c
@@ -48,7 +48,7 @@
 ** Parameters:      bd_addr          - BD address of the peer
 **                  dev_class        - Device Class
 **                  bd_name          - Name of the peer device.  NULL if unknown.
-**                  features         - Remote device's supported features. NULL if not known
+**                  features         - Remote device's features (up to 3 pages). NULL if not known
 **                  trusted_mask     - Bitwise OR of services that do not
 **                                     require authorization. (array of UINT32)
 **                  link_key         - Connection link key. NULL if unknown.
@@ -57,11 +57,12 @@
 **
 *******************************************************************************/
 BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name,
-                          BD_FEATURES features, UINT32 trusted_mask[],
+                          UINT8 *features, UINT32 trusted_mask[],
                           LINK_KEY link_key, UINT8 key_type, tBTM_IO_CAP io_cap)
 {
     tBTM_SEC_DEV_REC  *p_dev_rec;
-    int               i;
+    int               i, j;
+    BOOLEAN           found = FALSE;
 
     p_dev_rec = btm_find_dev (bd_addr);
     if (!p_dev_rec)
@@ -107,10 +108,29 @@
             (char *)bd_name, BTM_MAX_REM_BD_NAME_LEN);
     }
 
+    p_dev_rec->num_read_pages = 0;
     if (features)
-        memcpy (p_dev_rec->features, features, sizeof (BD_FEATURES));
+    {
+        memcpy (p_dev_rec->features, features, sizeof (p_dev_rec->features));
+        for (i = HCI_EXT_FEATURES_PAGE_MAX; i >= 0; i--)
+        {
+            for (j = 0; j < HCI_FEATURE_BYTES_PER_PAGE; j++)
+            {
+                if (p_dev_rec->features[i][j] != 0)
+                {
+                    found = TRUE;
+                    break;
+                }
+            }
+            if (found)
+            {
+                p_dev_rec->num_read_pages = i + 1;
+                break;
+            }
+        }
+    }
     else
-        memset (p_dev_rec->features, 0, sizeof (BD_FEATURES));
+        memset (p_dev_rec->features, 0, sizeof (p_dev_rec->features));
 
     BTM_SEC_COPY_TRUSTED_DEVICE(trusted_mask, p_dev_rec->trusted_mask);
 
@@ -197,7 +217,7 @@
 ** Description      Look for the record in the device database for the record
 **                  with specified handle
 **
-** Returns          Pointer to the record or NULL
+** Returns          Pointer to the record
 **
 *******************************************************************************/
 tBTM_SEC_DEV_REC *btm_sec_alloc_dev (BD_ADDR bd_addr)
@@ -308,9 +328,9 @@
         return(FALSE);
 #endif
     p_dev_rec = btm_find_dev (bd_addr);
-    if (p_dev_rec && HCI_SWITCH_SUPPORTED(btm_cb.devcb.local_features))
+    if (p_dev_rec && HCI_SWITCH_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
     {
-        if (HCI_SWITCH_SUPPORTED(p_dev_rec->features))
+        if (HCI_SWITCH_SUPPORTED(p_dev_rec->features[HCI_EXT_FEATURES_PAGE_0]))
         {
             BTM_TRACE_DEBUG0("btm_dev_support_switch return TRUE (feature found)");
             return (TRUE);
@@ -319,7 +339,7 @@
         /* If the feature field is all zero, we never received them */
         for (xx = 0 ; xx < BD_FEATURES_LEN ; xx++)
         {
-            if (p_dev_rec->features[xx] != 0x00)
+            if (p_dev_rec->features[HCI_EXT_FEATURES_PAGE_0][xx] != 0x00)
             {
                 feature_empty = FALSE; /* at least one is != 0 */
                 break;
@@ -420,7 +440,7 @@
 **                  the oldest non-paired device.  If all devices are paired it
 **                  deletes the oldest paired device.
 **
-** Returns          Pointer to the record or NULL
+** Returns          Pointer to the record
 **
 *******************************************************************************/
 tBTM_SEC_DEV_REC *btm_find_oldest_dev (void)
diff --git a/stack/btm/btm_devctl.c b/stack/btm/btm_devctl.c
index 5a88a77..e893edf 100644
--- a/stack/btm/btm_devctl.c
+++ b/stack/btm/btm_devctl.c
@@ -114,6 +114,17 @@
 static void btm_after_reset_hold_complete (void);
 static void btm_continue_reset (void);
 
+static void btm_get_local_ext_features (UINT8 page_number);
+static void btm_decode_ext_features_page (UINT8 page_number, const BD_FEATURES p_features);
+static void btm_read_all_lmp_features_complete (UINT8 max_page_number);
+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);
+
+#if BLE_INCLUDED == TRUE
+static void btm_read_ble_local_supported_features (void);
+#endif
+
 /*******************************************************************************
 **
 ** Function         btm_dev_init
@@ -314,9 +325,9 @@
                        btm_cb.last_disabled_channel);
 
     /* Make sure the local device supports the feature before sending */
-    if ((!HCI_LMP_AFH_CAP_MASTR_SUPPORTED(btm_cb.devcb.local_features))   &&
-        (!HCI_LMP_AFH_CLASS_SLAVE_SUPPORTED(btm_cb.devcb.local_features)) &&
-        (!HCI_LMP_AFH_CLASS_MASTR_SUPPORTED(btm_cb.devcb.local_features)))
+    if ((!HCI_LMP_AFH_CAP_MASTR_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]))   &&
+        (!HCI_LMP_AFH_CLASS_SLAVE_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0])) &&
+        (!HCI_LMP_AFH_CLASS_MASTR_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0])))
         return (BTM_MODE_UNSUPPORTED);
 
     if (!BTM_IsDeviceUp())
@@ -348,7 +359,7 @@
 tBTM_STATUS BTM_SetAfhChannelAssessment (BOOLEAN enable_or_disable)
 {
     /* whatever app wants if device is not 1.2 scan type should be STANDARD */
-    if (!HCI_LMP_AFH_CAP_SLAVE_SUPPORTED(btm_cb.devcb.local_features))
+    if (!HCI_LMP_AFH_CAP_SLAVE_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
      return (BTM_MODE_UNSUPPORTED);
 
     if (!btsnd_hcic_write_afh_channel_assessment_mode (enable_or_disable))
@@ -454,6 +465,25 @@
     /* Send a Read Buffer Size message to the Host Controller. */
     btsnd_hcic_ble_read_buffer_size ();
 }
+
+/*******************************************************************************
+**
+** Function         btm_read_ble_local_supported_features
+**
+** Description      Local function called to send a read BLE local supported
+**                  features command
+**
+** Returns          void
+**
+*******************************************************************************/
+static void btm_read_ble_local_supported_features(void)
+{
+    BTM_TRACE_DEBUG0("btm_read_ble_local_supported_features ");
+    btu_start_timer (&btm_cb.devcb.reset_timer, BTU_TTYPE_BTM_DEV_CTL, BTM_DEV_REPLY_TIMEOUT);
+
+    /* Send a Read Local Supported Features message to the Host Controller. */
+    btsnd_hcic_ble_read_local_spt_feat ();
+}
 #endif
 /*******************************************************************************
 **
@@ -488,12 +518,38 @@
 ** Returns          void
 **
 *******************************************************************************/
-void btm_get_local_features (void)
+static void btm_get_local_features (void)
+{
+    /* If this BT controller supports Read Extended Feature */
+    if (btm_cb.devcb.local_version.hci_version >= HCI_PROTO_VERSION_2_0)
+    {
+        btm_get_local_ext_features(HCI_EXT_FEATURES_PAGE_0);
+    }
+    /* else, if this is a very old BT controller */
+    else
 {
     btu_start_timer (&btm_cb.devcb.reset_timer, BTU_TTYPE_BTM_DEV_CTL, BTM_DEV_REPLY_TIMEOUT);
 
+        /* Just read the basic features (legacy HCI command) */
     btsnd_hcic_read_local_features ();
 }
+}
+
+/*******************************************************************************
+**
+** Function         btm_get_local_ext_features
+**
+** Description      Local function called to send a read local extended features
+**
+** Returns          void
+**
+*******************************************************************************/
+static void btm_get_local_ext_features (UINT8 page_number)
+{
+    btu_start_timer (&btm_cb.devcb.reset_timer, BTU_TTYPE_BTM_DEV_CTL, BTM_DEV_REPLY_TIMEOUT);
+
+    btsnd_hcic_read_local_ext_features(page_number);
+}
 
 /*******************************************************************************
 **
@@ -647,7 +703,7 @@
 **
 ** Description      This function is called when command complete for
 **                  get HCI buffer size is received.  Start timer and send
-**                  read local featues request
+**                  read local features request
 **
 ** Returns          void
 **
@@ -711,7 +767,7 @@
 **
 ** Description      This function is called when command complete for
 **                  get HCI buffer size is received.  Start timer and send
-**                  read local featues request
+**                  read local supported features request
 **
 ** Returns          void
 **
@@ -733,14 +789,47 @@
         l2c_link_processs_ble_num_bufs (lm_num_le_bufs);
     }
 
+    btm_read_ble_local_supported_features();
+}
+
+/*******************************************************************************
+**
+** Function         btm_read_ble_local_supported_features_complete
+**
+** Description      This function is called when command complete for
+**                  Read LE Local Supported Features is received.  Start timer and send
+**                  read LMP local features request
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_read_ble_local_supported_features_complete (UINT8 *p, UINT16 evt_len)
+{
+    UINT8       status;
+
+    BTM_TRACE_DEBUG0("btm_read_ble_local_supported_features_complete ");
+
+    btu_stop_timer (&btm_cb.devcb.reset_timer);
+
+    STREAM_TO_UINT8  (status, p);
+    if (status == HCI_SUCCESS)
+    {
+        STREAM_TO_ARRAY(&btm_cb.devcb.local_le_features, p, HCI_FEATURE_BYTES_PER_PAGE);
+    }
+    else
+    {
+        BTM_TRACE_WARNING1 ("btm_read_ble_local_supported_features_complete status = %d", status);
+    }
+
 #if BTM_INTERNAL_BB == TRUE
     {
         UINT8 buf[9] = BTM_INTERNAL_LOCAL_FEA;
         btm_read_local_features_complete( buf, 9 );
     }
 #else
+
     /* get local feature if BRCM specific feature is not included  */
-    btm_get_local_features ();
+    btm_reset_ctrlr_complete();
 #endif
 
 }
@@ -763,8 +852,6 @@
         STREAM_TO_UINT8(btm_cb.ble_ctr_cb.max_filter_entries, p);
         btm_cb.ble_ctr_cb.num_empty_filter = btm_cb.ble_ctr_cb.max_filter_entries;
     }
-    /* write LE host support and simultaneous LE supported */
-    btsnd_hcic_ble_write_host_supported(BTM_BLE_HOST_SUPPORT, BTM_BLE_SIMULTANEOUS_HOST);
 
     btm_get_ble_buffer_size();
 }
@@ -801,123 +888,38 @@
         STREAM_TO_UINT16 (p_vi->lmp_subversion, p);
     }
 
-#if BLE_INCLUDED == TRUE
-    {
-        btm_read_ble_wl_size();
-    }
-#elif BTM_INTERNAL_BB == TRUE
-    {
-        UINT8 buf[9] = BTM_INTERNAL_LOCAL_FEA;
-        btm_read_local_features_complete( buf, 9 );
-    }
-#else
-    /* get local feature if BRCM specific feature is not included  */
     btm_get_local_features ();
-#endif
 }
 
 /*******************************************************************************
 **
-** Function         btm_read_local_extended_feature
+** Function         btm_decode_ext_features_page
 **
-** Description      Local function called to send a read local extended feature to controller
+** Description      This function is decodes a features page.
 **
 ** Returns          void
 **
 *******************************************************************************/
-void btm_read_local_extended_feature (void)
+static void btm_decode_ext_features_page (UINT8 page_number, const UINT8 *p_features)
 {
-    btu_start_timer (&btm_cb.devcb.reset_timer, BTU_TTYPE_BTM_DEV_CTL, BTM_DEV_REPLY_TIMEOUT);
-
-    /* Send a Read Local extended feature message to the Controller. */
-    btsnd_hcic_read_local_ext_features (1);
-
-}
-/*******************************************************************************
-**
-** Function         btm_read_local_ext_features_complete
-**
-
-** Description      This function is called when local features read is complete.
-**                  This is the last step of the startup sequence.
-**
-** Returns          void
-**
-*******************************************************************************/
-void btm_read_local_ext_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 last;
     UINT8 first;
 
-    btu_stop_timer (&btm_cb.devcb.reset_timer);
-    /* If there was a callback address for reset complete, call it */
-    p_devcb->p_reset_cmpl_cb = NULL;
-
-    btm_sec_dev_reset ();
-
-    /* If 802.11 present might have to disable some channels */
-    if (btm_cb.last_disabled_channel != 0xff)
+    BTM_TRACE_DEBUG1 ("btm_decode_ext_features_page page: %d", page_number);
+    switch (page_number)
     {
-        last  = btm_cb.last_disabled_channel;
-        first = btm_cb.first_disabled_channel;
-        btm_cb.last_disabled_channel  = 0xff;
-        btm_cb.first_disabled_channel = 0xff;
-        BTM_SetAfhChannels(first, last);
-    }
+    /* Extended (Legacy) Page 0 */
+    case HCI_EXT_FEATURES_PAGE_0:
 
-    BTM_SetPageScanType (BTM_DEFAULT_SCAN_TYPE);
-    BTM_SetInquiryScanType (BTM_DEFAULT_SCAN_TYPE);
-
-    /* If anyone wants device status notifications, give him one */
-    btm_report_device_status (BTM_DEV_STATUS_UP);
-
-    /* Reset sequence is complete. If this was an application originated */
-    /* reset, tell him its done.                                         */
-    if (p_cb)
-        (*p_cb)((void *) NULL);
-}
-/*******************************************************************************
-**
-** Function         btm_read_local_features_complete
-**
-
-** Description      This function is called when local features read is complete.
-**                  This is the last step of the startup sequence.
-**
-** Returns          void
-**
-*******************************************************************************/
-void btm_read_local_features_complete (UINT8 *p, UINT16 evt_len)
-{
-    tBTM_DEVCB     *p_devcb = &btm_cb.devcb;
-    UINT8           status;
-    UINT16          xx;
-
-    STREAM_TO_UINT8  (status, p);
-    if (status == HCI_SUCCESS)
-    {
-        /* stop guard timer to avoid accidental timeout */
-        btu_stop_timer(&p_devcb->reset_timer);
-
-        p_devcb->state = BTM_DEV_STATE_READY;
-
-        /* Extract features and create "btm_acl_pkt_types_supported" flag
-        */
-        for (xx = 0; xx < HCI_NUM_FEATURE_BYTES; xx++)
-            STREAM_TO_UINT8 (p_devcb->local_features[xx], p);
-
-        /* Create ACL supported packet types mask
-        */
+        /* Create ACL supported packet types mask */
         btm_cb.btm_acl_pkt_types_supported = (BTM_ACL_PKT_TYPES_MASK_DH1 +
                                               BTM_ACL_PKT_TYPES_MASK_DM1);
 
-        if (HCI_3_SLOT_PACKETS_SUPPORTED(p_devcb->local_features))
+        if (HCI_3_SLOT_PACKETS_SUPPORTED(p_features))
             btm_cb.btm_acl_pkt_types_supported |= (BTM_ACL_PKT_TYPES_MASK_DH3 +
                                                    BTM_ACL_PKT_TYPES_MASK_DM3);
 
-        if (HCI_5_SLOT_PACKETS_SUPPORTED(p_devcb->local_features))
+        if (HCI_5_SLOT_PACKETS_SUPPORTED(p_features))
             btm_cb.btm_acl_pkt_types_supported |= (BTM_ACL_PKT_TYPES_MASK_DH5 +
                                                    BTM_ACL_PKT_TYPES_MASK_DM5);
 
@@ -925,16 +927,15 @@
            Set them only for later versions of controller */
         if (btm_cb.devcb.local_version.hci_version >= HCI_PROTO_VERSION_2_0)
         {
-
             /* Add in EDR related ACL types */
-            if (!HCI_EDR_ACL_2MPS_SUPPORTED(p_devcb->local_features))
+            if (!HCI_EDR_ACL_2MPS_SUPPORTED(p_features))
             {
                 btm_cb.btm_acl_pkt_types_supported |= (BTM_ACL_PKT_TYPES_MASK_NO_2_DH1 +
                                                        BTM_ACL_PKT_TYPES_MASK_NO_2_DH3 +
                                                        BTM_ACL_PKT_TYPES_MASK_NO_2_DH5);
             }
 
-            if (!HCI_EDR_ACL_3MPS_SUPPORTED(p_devcb->local_features))
+            if (!HCI_EDR_ACL_3MPS_SUPPORTED(p_features))
             {
                 btm_cb.btm_acl_pkt_types_supported |= (BTM_ACL_PKT_TYPES_MASK_NO_3_DH1 +
                                                        BTM_ACL_PKT_TYPES_MASK_NO_3_DH3 +
@@ -942,14 +943,14 @@
             }
 
             /* Check to see if 3 and 5 slot packets are available */
-            if (HCI_EDR_ACL_2MPS_SUPPORTED(p_devcb->local_features) ||
-                HCI_EDR_ACL_3MPS_SUPPORTED(p_devcb->local_features))
+            if (HCI_EDR_ACL_2MPS_SUPPORTED(p_features) ||
+                HCI_EDR_ACL_3MPS_SUPPORTED(p_features))
             {
-                if (!HCI_3_SLOT_EDR_ACL_SUPPORTED(p_devcb->local_features))
+                if (!HCI_3_SLOT_EDR_ACL_SUPPORTED(p_features))
                     btm_cb.btm_acl_pkt_types_supported |= (BTM_ACL_PKT_TYPES_MASK_NO_2_DH3 +
                                                            BTM_ACL_PKT_TYPES_MASK_NO_3_DH3);
 
-                if (!HCI_5_SLOT_EDR_ACL_SUPPORTED(p_devcb->local_features))
+                if (!HCI_5_SLOT_EDR_ACL_SUPPORTED(p_features))
                     btm_cb.btm_acl_pkt_types_supported |= (BTM_ACL_PKT_TYPES_MASK_NO_2_DH5 +
                                                            BTM_ACL_PKT_TYPES_MASK_NO_3_DH5);
             }
@@ -958,30 +959,29 @@
         BTM_TRACE_DEBUG1("Local supported ACL packet types: 0x%04x",
                          btm_cb.btm_acl_pkt_types_supported);
 
-        /* Create (e)SCO supported packet types mask
-        */
+        /* Create (e)SCO supported packet types mask */
         btm_cb.btm_sco_pkt_types_supported = 0;
 #if BTM_SCO_INCLUDED == TRUE
         btm_cb.sco_cb.esco_supported = FALSE;
 #endif
-        if (HCI_SCO_LINK_SUPPORTED(p_devcb->local_features))
+        if (HCI_SCO_LINK_SUPPORTED(p_features))
         {
             btm_cb.btm_sco_pkt_types_supported = BTM_SCO_PKT_TYPES_MASK_HV1;
 
-            if (HCI_HV2_PACKETS_SUPPORTED(p_devcb->local_features))
+            if (HCI_HV2_PACKETS_SUPPORTED(p_features))
                 btm_cb.btm_sco_pkt_types_supported |= BTM_SCO_PKT_TYPES_MASK_HV2;
 
-            if (HCI_HV3_PACKETS_SUPPORTED(p_devcb->local_features))
+            if (HCI_HV3_PACKETS_SUPPORTED(p_features))
                 btm_cb.btm_sco_pkt_types_supported |= BTM_SCO_PKT_TYPES_MASK_HV3;
         }
 
-        if (HCI_ESCO_EV3_SUPPORTED(p_devcb->local_features))
+        if (HCI_ESCO_EV3_SUPPORTED(p_features))
             btm_cb.btm_sco_pkt_types_supported |= BTM_SCO_PKT_TYPES_MASK_EV3;
 
-        if (HCI_ESCO_EV4_SUPPORTED(p_devcb->local_features))
+        if (HCI_ESCO_EV4_SUPPORTED(p_features))
             btm_cb.btm_sco_pkt_types_supported |= BTM_SCO_PKT_TYPES_MASK_EV4;
 
-        if (HCI_ESCO_EV5_SUPPORTED(p_devcb->local_features))
+        if (HCI_ESCO_EV5_SUPPORTED(p_features))
             btm_cb.btm_sco_pkt_types_supported |= BTM_SCO_PKT_TYPES_MASK_EV5;
 #if BTM_SCO_INCLUDED == TRUE
         if (btm_cb.btm_sco_pkt_types_supported & BTM_ESCO_LINK_ONLY_MASK)
@@ -989,9 +989,9 @@
             btm_cb.sco_cb.esco_supported = TRUE;
 
             /* Add in EDR related eSCO types */
-            if (HCI_EDR_ESCO_2MPS_SUPPORTED(p_devcb->local_features))
+            if (HCI_EDR_ESCO_2MPS_SUPPORTED(p_features))
             {
-                if (!HCI_3_SLOT_EDR_ESCO_SUPPORTED(p_devcb->local_features))
+                if (!HCI_3_SLOT_EDR_ESCO_SUPPORTED(p_features))
                     btm_cb.btm_sco_pkt_types_supported |= BTM_SCO_PKT_TYPES_MASK_NO_2_EV5;
             }
             else
@@ -1000,9 +1000,9 @@
                                                        BTM_SCO_PKT_TYPES_MASK_NO_2_EV5);
             }
 
-            if (HCI_EDR_ESCO_3MPS_SUPPORTED(p_devcb->local_features))
+            if (HCI_EDR_ESCO_3MPS_SUPPORTED(p_features))
             {
-                if (!HCI_3_SLOT_EDR_ESCO_SUPPORTED(p_devcb->local_features))
+                if (!HCI_3_SLOT_EDR_ESCO_SUPPORTED(p_features))
                     btm_cb.btm_sco_pkt_types_supported |= BTM_SCO_PKT_TYPES_MASK_NO_3_EV5;
             }
             else
@@ -1016,48 +1016,433 @@
         BTM_TRACE_DEBUG1("Local supported SCO packet types: 0x%04x",
                          btm_cb.btm_sco_pkt_types_supported);
 
-        /* Create Default Policy Settings
-        */
-        if (HCI_SWITCH_SUPPORTED(p_devcb->local_features))
+        /* Create Default Policy Settings */
+        if (HCI_SWITCH_SUPPORTED(p_features))
             btm_cb.btm_def_link_policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
         else
             btm_cb.btm_def_link_policy &= ~HCI_ENABLE_MASTER_SLAVE_SWITCH;
 
-        if (HCI_HOLD_MODE_SUPPORTED(p_devcb->local_features))
+        if (HCI_HOLD_MODE_SUPPORTED(p_features))
             btm_cb.btm_def_link_policy |= HCI_ENABLE_HOLD_MODE;
         else
             btm_cb.btm_def_link_policy &= ~HCI_ENABLE_HOLD_MODE;
 
-        if (HCI_SNIFF_MODE_SUPPORTED(p_devcb->local_features))
+        if (HCI_SNIFF_MODE_SUPPORTED(p_features))
             btm_cb.btm_def_link_policy |= HCI_ENABLE_SNIFF_MODE;
         else
             btm_cb.btm_def_link_policy &= ~HCI_ENABLE_SNIFF_MODE;
 
-        if (HCI_PARK_MODE_SUPPORTED(p_devcb->local_features))
+        if (HCI_PARK_MODE_SUPPORTED(p_features))
             btm_cb.btm_def_link_policy |= HCI_ENABLE_PARK_MODE;
         else
             btm_cb.btm_def_link_policy &= ~HCI_ENABLE_PARK_MODE;
 
+        btm_sec_dev_reset ();
 #if ((BTM_EIR_SERVER_INCLUDED == TRUE)||(BTM_EIR_CLIENT_INCLUDED == TRUE))
-        if (HCI_LMP_INQ_RSSI_SUPPORTED(p_devcb->local_features))
+        if (HCI_LMP_INQ_RSSI_SUPPORTED(p_features))
         {
-            if (HCI_EXT_INQ_RSP_SUPPORTED(p_devcb->local_features))
+            if (HCI_EXT_INQ_RSP_SUPPORTED(p_features))
                 BTM_SetInquiryMode (BTM_INQ_RESULT_EXTENDED);
             else
                 BTM_SetInquiryMode (BTM_INQ_RESULT_WITH_RSSI);
         }
 #else
-        if (HCI_LMP_INQ_RSSI_SUPPORTED(p_devcb->local_features))
+        if (HCI_LMP_INQ_RSSI_SUPPORTED(p_features))
             BTM_SetInquiryMode (BTM_INQ_RESULT_WITH_RSSI);
 #endif
 #if L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE
-        if( HCI_NON_FLUSHABLE_PB_SUPPORTED(p_devcb->local_features))
+        if( HCI_NON_FLUSHABLE_PB_SUPPORTED(p_features))
             l2cu_set_non_flushable_pbf(TRUE);
         else
             l2cu_set_non_flushable_pbf(FALSE);
 #endif
+        BTM_SetPageScanType (BTM_DEFAULT_SCAN_TYPE);
+        BTM_SetInquiryScanType (BTM_DEFAULT_SCAN_TYPE);
+
+        break;
+
+    /* Extended Page 1 */
+    case HCI_EXT_FEATURES_PAGE_1:
+        /* Nothing to do for page 1 */
+        break;
+
+    /* Extended Page 2 */
+    case HCI_EXT_FEATURES_PAGE_2:
+        /* Nothing to do for page 2 */
+        break;
+
+    default:
+        BTM_TRACE_ERROR1("btm_decode_ext_features_page page=%d unknown", page_number);
+        break;
     }
-    btm_read_local_extended_feature ();
+}
+
+/*******************************************************************************
+**
+** Function         btm_reset_ctrlr_complete
+**
+** Description      This is the last step of BR/EDR controller startup sequence.
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_reset_ctrlr_complete ()
+{
+    tBTM_DEVCB     *p_devcb = &btm_cb.devcb;
+    tBTM_CMPL_CB   *p_cb = p_devcb->p_reset_cmpl_cb;
+    BOOLEAN         found = FALSE;
+    UINT8           i, j, max_page_number;
+
+    btu_stop_timer (&btm_cb.devcb.reset_timer);
+
+    /* find the highest feature page number which contains non-zero bits */
+    for (i = HCI_EXT_FEATURES_PAGE_MAX; i >= 0; i--)
+    {
+        for (j = 0; j < HCI_FEATURE_BYTES_PER_PAGE; j++)
+        {
+            if (p_devcb->local_lmp_features[i][j] != 0)
+            {
+                found = TRUE;
+                break;
+            }
+        }
+        if (found || !i)
+        {
+             break;
+        }
+    }
+
+    if (!found)
+        BTM_TRACE_WARNING0 ("btm_reset_ctrlr_complete: NONE of local controller features is set");
+
+    max_page_number = i;
+
+    BTM_TRACE_DEBUG1 ("btm_reset_ctrlr_complete: max_page_number: %d", max_page_number);
+
+    /*
+    * Set State to Ready (needs to be done before btm_decode_ext_features_page
+    * to allow it to send some HCI configuration commands)
+    */
+    p_devcb->state = BTM_DEV_STATE_READY;
+
+    /* For every received/saved feature page */
+    for (i = 0; i <= max_page_number; i++)
+    {
+        /* Decode the saved Feature Page */
+        btm_decode_ext_features_page(i, p_devcb->local_lmp_features[i]);
+    }
+
+    /* If there was a callback address for reset complete, reset it */
+    p_devcb->p_reset_cmpl_cb = NULL;
+
+    /* If anyone wants device status notifications, give him one */
+    btm_report_device_status(BTM_DEV_STATUS_UP);
+
+    /* Reset sequence is complete. If this was an application originated */
+    /* reset, tell him its done.                                         */
+    if (p_cb)
+        (*p_cb)((void *) NULL);
+}
+
+/*******************************************************************************
+**
+** Function         btm_issue_host_support_for_lmp_features
+**
+** Description      This function:
+**                  - issues commands to set host supported LMP features (one at
+**                    a time);
+**                  - after this is done it issues command to re-read LMP features
+**                    page 1;
+**                  - after this is done it calls the last step of BR/EDR
+**                    controller startup sequence.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void btm_issue_host_support_for_lmp_features (void)
+{
+    BTM_TRACE_DEBUG1("btm_issue_host_support_for_lmp_features lmp_features_host_may_support: 0x%02x", btm_cb.devcb.lmp_features_host_may_support);
+
+    if (btm_cb.devcb.lmp_features_host_may_support & BTM_HOST_MAY_SUPP_SSP)
+    {
+        btsnd_hcic_write_simple_pairing_mode(HCI_SP_MODE_ENABLED);
+        return;
+    }
+
+#if (BLE_INCLUDED == TRUE)
+    if (btm_cb.devcb.lmp_features_host_may_support & BTM_HOST_MAY_SUPP_LE)
+    {
+        if (btm_cb.devcb.lmp_features_host_may_support & BTM_HOST_MAY_SUPP_SIMULT_BR_LE)
+        {
+            /* At the moment the host can't work simultaneously with BR/EDR and LE */
+            btsnd_hcic_ble_write_host_supported(BTM_BLE_HOST_SUPPORT, 0);
+        }
+        else
+        {
+            btsnd_hcic_ble_write_host_supported(BTM_BLE_HOST_SUPPORT, 0);
+        }
+        return;
+    }
+#endif
+
+    if (btm_cb.devcb.lmp_features_host_may_support & BTM_RE_READ_1ST_PAGE)
+    {
+        btm_get_local_ext_features(HCI_EXT_FEATURES_PAGE_1);
+        return;
+    }
+
+    if (!btm_cb.devcb.lmp_features_host_may_support)
+    {
+#if BLE_INCLUDED == TRUE
+        if (HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
+        {
+            btm_read_ble_wl_size();
+        }
+#elif BTM_INTERNAL_BB == TRUE
+        {
+            UINT8 buf[9] = BTM_INTERNAL_LOCAL_FEA;
+            btm_read_local_features_complete( buf, 9 );
+        }
+#endif
+        else
+        {
+            btm_reset_ctrlr_complete();
+        }
+        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);
+}
+
+/*******************************************************************************
+**
+** Function         btm_set_lmp_features_host_may_support
+**
+** Description      This function is called after all LMP features provided by
+**                  controller are read. It sets the mask that indicates LMP
+**                  features the host may support based on LMP features supported
+**                  by controller.
+**                  Example:
+**                  Host may set SSP (host support) bit only if SSP (controller
+**                  support) bit is set by controller.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void btm_set_lmp_features_host_may_support (UINT8 max_page_number)
+{
+    btm_cb.devcb.lmp_features_host_may_support = 0;
+
+    /* LMP page 0 is always read */
+    if (HCI_SIMPLE_PAIRING_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
+    {
+        /* host may support SSP */
+        btm_cb.devcb.lmp_features_host_may_support |= BTM_HOST_MAY_SUPP_SSP;
+    }
+
+#if (BLE_INCLUDED == TRUE)
+    if (HCI_LE_SPT_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
+    {
+        /* host may support LE */
+        btm_cb.devcb.lmp_features_host_may_support |= BTM_HOST_MAY_SUPP_LE;
+
+        if (HCI_SIMUL_LE_BREDR_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
+        {
+            /* host may support BR/EDR and LE simultaneously */
+            btm_cb.devcb.lmp_features_host_may_support |= BTM_HOST_MAY_SUPP_SIMULT_BR_LE;
+        }
+    }
+#endif
+
+    if (max_page_number >= HCI_EXT_FEATURES_PAGE_1)
+    {
+        /* nothing yet for HCI_EXT_FEATURES_PAGE_1 */
+    }
+
+    if (max_page_number >= HCI_EXT_FEATURES_PAGE_1)
+    {
+        /* nothing yet for HCI_EXT_FEATURES_PAGE_2 */
+    }
+
+    if (btm_cb.devcb.lmp_features_host_may_support)
+        btm_cb.devcb.lmp_features_host_may_support |= BTM_RE_READ_1ST_PAGE;
+}
+
+/*******************************************************************************
+**
+** Function         btm_read_all_lmp_features_complete
+**
+** Description      This function is called after all LMP features provided by
+**                  controller are read.
+**                  It works with controller supported LMP features which host
+**                  may support too.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void btm_read_all_lmp_features_complete (UINT8 max_page_number)
+{
+    btm_set_lmp_features_host_may_support(max_page_number);
+
+    btm_issue_host_support_for_lmp_features();
+}
+
+/*******************************************************************************
+**
+** Function         btm_read_local_features_complete
+**
+** Description      This function is called when local supported features read
+**                  is complete.
+**
+** Returns          void
+**
+*******************************************************************************/
+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);
+
+    STREAM_TO_UINT8  (status, p);
+    if (status == HCI_SUCCESS)
+    {
+        /* Save the Feature Page 0 */
+        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);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         btm_read_local_ext_features_complete
+**
+** Description      This function is called when read local extended features
+**                  command complete message is received from the HCI.
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_read_local_ext_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;
+    UINT8           page_number;
+    UINT8           page_number_max;
+
+    btu_stop_timer (&btm_cb.devcb.reset_timer);
+
+    STREAM_TO_UINT8 (status, p);
+    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);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         btm_write_simple_paring_mode_complete
+**
+** Description      This function is called when the command complete message
+**                  is received from the HCI for the write simple pairing mode
+**                  command.
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_write_simple_paring_mode_complete (UINT8 *p)
+{
+    UINT8   status;
+
+    STREAM_TO_UINT8 (status, p);
+
+    if (status != HCI_SUCCESS)
+    {
+        BTM_TRACE_WARNING1("btm_write_simple_paring_mode_complete status: 0x%02x", status);
+    }
+
+    if (btm_cb.devcb.lmp_features_host_may_support & BTM_HOST_MAY_SUPP_SSP)
+    {
+        btm_cb.devcb.lmp_features_host_may_support &= ~BTM_HOST_MAY_SUPP_SSP;
+        btm_issue_host_support_for_lmp_features();
+    }
+}
+
+/*******************************************************************************
+**
+** Function         btm_write_le_host_supported_complete
+**
+** Description      This function is called when the command complete message
+**                  is received from the HCI for the write LE host supported
+**                  command.
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_write_le_host_supported_complete (UINT8 *p)
+{
+    UINT8   status;
+
+    STREAM_TO_UINT8 (status, p);
+
+    if (status != HCI_SUCCESS)
+    {
+        BTM_TRACE_WARNING1("btm_write_le_host_supported_complete status: 0x%02x", status);
+    }
+
+    if (btm_cb.devcb.lmp_features_host_may_support & BTM_HOST_MAY_SUPP_LE)
+    {
+        btm_cb.devcb.lmp_features_host_may_support &= ~BTM_HOST_MAY_SUPP_LE;
+        if (btm_cb.devcb.lmp_features_host_may_support & BTM_HOST_MAY_SUPP_SIMULT_BR_LE)
+        {
+            btm_cb.devcb.lmp_features_host_may_support &= ~BTM_HOST_MAY_SUPP_SIMULT_BR_LE;
+        }
+        btm_issue_host_support_for_lmp_features();
+    }
 }
 
 /*******************************************************************************
@@ -1077,9 +1462,9 @@
 {
     UINT8 code = 0;
 
-    if( HCI_LMP_CVSD_SUPPORTED(btm_cb.devcb.local_features) ) code |= 0x01 ;
-    if( HCI_LMP_A_LAW_SUPPORTED(btm_cb.devcb.local_features) ) code |= 0x02 ;
-    if( HCI_LMP_U_LAW_SUPPORTED(btm_cb.devcb.local_features) )  code |= 0x04 ;
+    if( HCI_LMP_CVSD_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]) ) code |= 0x01 ;
+    if( HCI_LMP_A_LAW_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]) ) code |= 0x02 ;
+    if( HCI_LMP_U_LAW_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]) )  code |= 0x04 ;
 
     return code ;
 }
@@ -1338,7 +1723,27 @@
 *******************************************************************************/
 UINT8 *BTM_ReadLocalFeatures (void)
 {
-    return (btm_cb.devcb.local_features);
+    return (btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]);
+}
+
+/*******************************************************************************
+**
+** Function         BTM_ReadLocalExtendedFeatures
+**
+** Description      This function is called to read the local extended features
+**
+** Returns          pointer to the local extended features mask or NULL if bad
+**                  page
+**
+*******************************************************************************/
+UINT8 *BTM_ReadLocalExtendedFeatures (UINT8 page_number)
+{
+    if (page_number <= HCI_EXT_FEATURES_PAGE_MAX)
+        return (btm_cb.devcb.local_lmp_features[page_number]);
+
+    BTM_TRACE_ERROR1("Warning: BTM_ReadLocalExtendedFeatures page %d unknown",
+            page_number);
+    return NULL;
 }
 
 /*******************************************************************************
diff --git a/stack/btm/btm_inq.c b/stack/btm/btm_inq.c
index a9feed7..d67f4d4 100644
--- a/stack/btm/btm_inq.c
+++ b/stack/btm/btm_inq.c
@@ -185,11 +185,14 @@
 
     BTM_TRACE_API0 ("BTM_SetDiscoverability");
 #if (BLE_INCLUDED == TRUE && BLE_INCLUDED == TRUE)
-    if (btm_ble_set_discoverability((UINT16)(inq_mode))
-                        == BTM_SUCCESS)
+    if (HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
     {
-        btm_cb.btm_inq_vars.discoverable_mode &= (~BTM_BLE_DISCOVERABLE_MASK);
-        btm_cb.btm_inq_vars.discoverable_mode |= (inq_mode & BTM_BLE_CONNECTABLE_MASK);
+        if (btm_ble_set_discoverability((UINT16)(inq_mode))
+                            == BTM_SUCCESS)
+        {
+            btm_cb.btm_inq_vars.discoverable_mode &= (~BTM_BLE_DISCOVERABLE_MASK);
+            btm_cb.btm_inq_vars.discoverable_mode |= (inq_mode & BTM_BLE_CONNECTABLE_MASK);
+        }
     }
     inq_mode &= ~BTM_BLE_DISCOVERABLE_MASK;
 #endif
@@ -313,7 +316,7 @@
         return (BTM_ILLEGAL_VALUE);
 
     /* whatever app wants if device is not 1.2 scan type should be STANDARD */
-    if (!HCI_LMP_INTERLACED_INQ_SCAN_SUPPORTED(btm_cb.devcb.local_features))
+    if (!HCI_LMP_INTERLACED_INQ_SCAN_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
      return (BTM_MODE_UNSUPPORTED);
 
     /* Check for scan type if configuration has been changed */
@@ -350,7 +353,7 @@
         return (BTM_ILLEGAL_VALUE);
 
     /* whatever app wants if device is not 1.2 scan type should be STANDARD */
-    if (!HCI_LMP_INTERLACED_PAGE_SCAN_SUPPORTED(btm_cb.devcb.local_features))
+    if (!HCI_LMP_INTERLACED_PAGE_SCAN_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
      return (BTM_MODE_UNSUPPORTED);
 
     /* Check for scan type if configuration has been changed */
@@ -393,13 +396,13 @@
     }
     else if (mode == BTM_INQ_RESULT_WITH_RSSI)
     {
-    if (!HCI_LMP_INQ_RSSI_SUPPORTED(btm_cb.devcb.local_features))
+    if (!HCI_LMP_INQ_RSSI_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
         return (BTM_MODE_UNSUPPORTED);
     }
 #if (( BTM_EIR_CLIENT_INCLUDED == TRUE )||( BTM_EIR_SERVER_INCLUDED == TRUE ))
     else if (mode == BTM_INQ_RESULT_EXTENDED)
     {
-        if (!HCI_EXT_INQ_RSP_SUPPORTED(btm_cb.devcb.local_features))
+        if (!HCI_EXT_INQ_RSP_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
             return (BTM_MODE_UNSUPPORTED);
     }
 #endif
@@ -619,12 +622,15 @@
     BTM_TRACE_API0 ("BTM_SetConnectability");
 
 #if (BLE_INCLUDED == TRUE && BLE_INCLUDED == TRUE)
-    if (btm_ble_set_connectability(page_mode) != BTM_SUCCESS)
+    if (HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
     {
-        return BTM_NO_RESOURCES;
+        if (btm_ble_set_connectability(page_mode) != BTM_SUCCESS)
+        {
+            return BTM_NO_RESOURCES;
+        }
+        p_inq->connectable_mode &= (~BTM_BLE_CONNECTABLE_MASK);
+        p_inq->connectable_mode |= (page_mode & BTM_BLE_CONNECTABLE_MASK);
     }
-    p_inq->connectable_mode &= (~BTM_BLE_CONNECTABLE_MASK);
-    p_inq->connectable_mode |= (page_mode & BTM_BLE_CONNECTABLE_MASK);
     page_mode &= ~BTM_BLE_CONNECTABLE_MASK;
 #endif
 
@@ -875,9 +881,14 @@
 #if BLE_INCLUDED == TRUE
     if (p_inqparms->mode & BTM_BLE_INQUIRY_MASK)
     {
+        if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
+        {
+            p_inq->inqparms.mode &= ~ BTM_BLE_INQUIRY_MASK;
+            status = BTM_ILLEGAL_VALUE;
+        }
         /* BLE for now does not support filter condition for inquiry */
-        if ((status = btm_ble_start_inquiry((UINT8)(p_inqparms->mode & BTM_BLE_INQUIRY_MASK),
-                        p_inq->inqparms.duration)) != BTM_CMD_STARTED)
+        else if ((status = btm_ble_start_inquiry((UINT8)(p_inqparms->mode & BTM_BLE_INQUIRY_MASK),
+                                            p_inqparms->duration)) != BTM_CMD_STARTED)
         {
             BTM_TRACE_ERROR0("Err Starting LE Inquiry.");
             p_inq->inqparms.mode &= ~ BTM_BLE_INQUIRY_MASK;
@@ -2334,7 +2345,8 @@
 
             btm_clr_inq_result_flt();
 
-            if((p_inq->inq_cmpl_info.status == BTM_SUCCESS) && HCI_LMP_INQ_RSSI_SUPPORTED(btm_cb.devcb.local_features))
+            if((p_inq->inq_cmpl_info.status == BTM_SUCCESS) &&
+                HCI_LMP_INQ_RSSI_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
             {
                 btm_sort_inq_result();
             }
@@ -2764,7 +2776,7 @@
 tBTM_STATUS BTM_WriteEIR( BT_HDR *p_buff )
 {
 #if (BTM_EIR_SERVER_INCLUDED == TRUE)
-    if (HCI_EXT_INQ_RSP_SUPPORTED(btm_cb.devcb.local_features))
+    if (HCI_EXT_INQ_RSP_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
     {
         BTM_TRACE_API0("Write Extended Inquiry Response to controller");
         btsnd_hcic_write_ext_inquiry_response (p_buff, BTM_EIR_DEFAULT_FEC_REQUIRED);
diff --git a/stack/btm/btm_int.h b/stack/btm/btm_int.h
index 0b83051..7b862fe 100644
--- a/stack/btm/btm_int.h
+++ b/stack/btm/btm_int.h
@@ -68,13 +68,12 @@
                                           HCI_PKT_TYPES_MASK_NO_2_DH5   | \
                                           HCI_PKT_TYPES_MASK_NO_3_DH5)
 
-#define BTM_EPR_AVAILABLE(p) ((HCI_ATOMIC_ENCRYPT_SUPPORTED((p)->features) && \
-                               HCI_ATOMIC_ENCRYPT_SUPPORTED(btm_cb.devcb.local_features)) \
+#define BTM_EPR_AVAILABLE(p) ((HCI_ATOMIC_ENCRYPT_SUPPORTED((p)->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0]) && \
+                               HCI_ATOMIC_ENCRYPT_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0])) \
                                ? TRUE : FALSE)
 
 #define BTM_IS_BRCM_CONTROLLER() (btm_cb.devcb.local_version.manufacturer == LMP_COMPID_BROADCOM)
 
-
 /* Define the ACL Management control structure
 */
 typedef struct
@@ -90,7 +89,8 @@
     UINT16          manufacturer;
     UINT16          lmp_subversion;
     UINT16          link_super_tout;
-    BD_FEATURES     features;           /* Features suported by the device    */
+    BD_FEATURES     peer_lmp_features[HCI_EXT_FEATURES_PAGE_MAX + 1];    /* Peer LMP Extended features mask table for the device */
+    UINT8           num_read_pages;
     UINT8           lmp_version;
 
     BOOLEAN         in_use;
@@ -121,6 +121,7 @@
     UINT8           conn_addr_type;         /* local device address type for this connection */
     BD_ADDR         active_remote_addr;     /* remote address used on this connection */
     UINT8           active_remote_addr_type;         /* local device address type for this connection */
+    BD_FEATURES     peer_le_features;       /* Peer LE Used features mask for the device */
 
 #endif
 
@@ -174,21 +175,21 @@
                                             /* change of link key is completed      */
 
     TIMER_LIST_ENT       tx_power_timer;
-    tBTM_CMPL_CB        *p_tx_power_cmpl_cb;   /* Callback function to be called       */
+    tBTM_CMPL_CB        *p_tx_power_cmpl_cb;/* Callback function to be called       */
 
-#if BLE_INCLUDED == TRUE
-    tBTM_CMPL_CB        *p_le_test_cmd_cmpl_cb;   /* Callback function to be called when
-                                                  LE test mode command has been sent successfully */
-#endif
     BD_ADDR              local_addr;        /* BD_ADDR of the local device          */
     tBTM_VERSION_INFO    local_version;     /* Local Version Information            */
-    BD_FEATURES          local_features;    /* Local features bit mask              */
     DEV_CLASS            dev_class;         /* Local device class                   */
-#if BLE_INCLUDED == TRUE
-    BD_ADDR                 read_tx_pwr_addr;   /* read TX power target address */
 
-    tBTM_BLE_LOCAL_ID_KEYS  id_keys;            /* local BLE ID keys */
-    BT_OCTET16              er;                 /* BLE encryption key */
+    /* Local LMP Extended features mask table for the device */
+    BD_FEATURES          local_lmp_features[HCI_EXT_FEATURES_PAGE_MAX + 1];
+
+#if BLE_INCLUDED == TRUE
+    BD_ADDR                 read_tx_pwr_addr;   /* read TX power target address     */
+    BD_FEATURES             local_le_features;  /* Local LE Supported features mask for the device */
+
+    tBTM_BLE_LOCAL_ID_KEYS  id_keys;        /* local BLE ID keys                    */
+    BT_OCTET16              er;             /* BLE encryption key                   */
 
 #if BTM_BLE_CONFORMANCE_TESTING == TRUE
     BOOLEAN                 no_disc_if_pair_fail;
@@ -198,6 +199,10 @@
     UINT32			        test_local_sign_cntr;
 #endif
 
+#if BLE_INCLUDED == TRUE
+    tBTM_CMPL_CB        *p_le_test_cmd_cmpl_cb;   /* Callback function to be called when
+                                                  LE test mode command has been sent successfully */
+#endif
 
 #endif  /* BLE_INCLUDED */
 
@@ -209,6 +214,13 @@
     tBTM_IO_CAP          loc_io_caps;       /* IO capability of the local device */
     BOOLEAN              loc_auth_req;      /* the auth_req flag  */
     BD_FEATURES          brcm_features;     /* Broadcom specific features bit mask  */
+
+#define BTM_RE_READ_1ST_PAGE            0x01            /* Set it if you set at least one of "..._HOST_MAY_SUPP_..." bits */
+#define BTM_HOST_MAY_SUPP_SSP           0x02
+#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 */
+
 } tBTM_DEVCB;
 
 
@@ -511,7 +523,8 @@
     UINT8           sec_flags;          /* Current device security state      */
 
     tBTM_BD_NAME    sec_bd_name;        /* User friendly name of the device. (may be truncated to save space in dev_rec table) */
-    BD_FEATURES     features;           /* Features suported by the device    */
+    BD_FEATURES     features[HCI_EXT_FEATURES_PAGE_MAX + 1];           /* Features supported by the device */
+    UINT8           num_read_pages;
 
 #define BTM_SEC_STATE_IDLE              0
 #define BTM_SEC_STATE_AUTHENTICATING    1
@@ -1021,10 +1034,13 @@
 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);
 extern void btm_read_local_addr_complete (UINT8 *p, UINT16 evt_len);
-extern void btm_get_local_features (void);
+extern  void btm_reset_ctrlr_complete (void);
+extern void btm_write_simple_paring_mode_complete (UINT8 *p);
+extern void btm_write_le_host_supported_complete (UINT8 *p);
 
 #if (BLE_INCLUDED == TRUE)
 extern void btm_read_ble_buf_size_complete (UINT8 *p, UINT16 evt_len);
+extern void btm_read_ble_local_supported_features_complete (UINT8 *p, UINT16 evt_len);
 extern void btm_read_white_list_size_complete(UINT8 *p, UINT16 evt_len);
 extern void btm_ble_add_2_white_list_complete(UINT8 status);
 extern void btm_ble_remove_from_white_list_complete(UINT8 *p, UINT16 evt_len);
diff --git a/stack/btm/btm_sco.c b/stack/btm/btm_sco.c
index f580232..3eb010c 100644
--- a/stack/btm/btm_sco.c
+++ b/stack/btm/btm_sco.c
@@ -427,14 +427,14 @@
         if ((xx = btm_handle_to_acl_index(acl_handle)) < MAX_L2CAP_LINKS)
         {
             p_acl = &btm_cb.acl_db[xx];
-            if (!HCI_EDR_ESCO_2MPS_SUPPORTED(p_acl->features))
+            if (!HCI_EDR_ESCO_2MPS_SUPPORTED(p_acl->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
             {
 
                 BTM_TRACE_WARNING0("BTM Remote does not support 2-EDR eSCO");
                 temp_pkt_types |= (HCI_ESCO_PKT_TYPES_MASK_NO_2_EV3 |
                                    HCI_ESCO_PKT_TYPES_MASK_NO_2_EV5);
             }
-            if (!HCI_EDR_ESCO_3MPS_SUPPORTED(p_acl->features))
+            if (!HCI_EDR_ESCO_3MPS_SUPPORTED(p_acl->peer_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
             {
 
                 BTM_TRACE_WARNING0("BTM Remote does not support 3-EDR eSCO");
diff --git a/stack/btm/btm_sec.c b/stack/btm/btm_sec.c
index b2ffac5..402f81f 100644
--- a/stack/btm/btm_sec.c
+++ b/stack/btm/btm_sec.c
@@ -312,7 +312,7 @@
     }
     btm_cb.security_mode = security_mode;
 
-    if (HCI_SIMPLE_PAIRING_SUPPORTED(btm_cb.devcb.local_features))
+    if (HCI_SIMPLE_PAIRING_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
     {
         /* Lisbon devices and only use BTM_SEC_MODE_SP */
         btm_cb.security_mode = BTM_SEC_MODE_SP;
@@ -1049,6 +1049,8 @@
 {
     tBTM_SEC_DEV_REC *p_dev_rec;
     tBTM_STATUS      status;
+    UINT8            *p_features;
+    UINT8            ii;
 #if SMP_INCLUDED == TRUE
     tACL_CONN   *p=NULL;
     BOOLEAN     is_le_slave_role=FALSE;
@@ -1164,7 +1166,7 @@
 #endif
 
     BTM_TRACE_DEBUG1 ("after update sec_flags=0x%x", p_dev_rec->sec_flags);
-    if (!HCI_SIMPLE_PAIRING_SUPPORTED(btm_cb.devcb.local_features))
+    if (!HCI_SIMPLE_PAIRING_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
     {
         /* The special case when we authenticate keyboard.  Set pin type to fixed */
         /* It would be probably better to do it from the application, but it is */
@@ -1178,12 +1180,17 @@
         }
     }
 
-    BTM_TRACE_EVENT1("BTM_SecBond: Local device supports SSP=%d", HCI_SIMPLE_PAIRING_SUPPORTED(btm_cb.devcb.local_features));
+    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]));
 
-    BTM_TRACE_EVENT4("  remote_features=%02x-%02x-%02x-%02x",
-                     p_dev_rec->features[0], p_dev_rec->features[1], p_dev_rec->features[2], p_dev_rec->features[3]);
-    BTM_TRACE_EVENT4("                  %02x-%02x-%02x-%02x",
-                     p_dev_rec->features[4], p_dev_rec->features[5], p_dev_rec->features[6], p_dev_rec->features[7]);
+    for (ii = 0; ii <= HCI_EXT_FEATURES_PAGE_MAX; ii++)
+    {
+        p_features = p_dev_rec->features[ii];
+        BTM_TRACE_EVENT5("  remote_features page[%1d] = %02x-%02x-%02x-%02x",
+                         ii, p_features[0], p_features[1], p_features[2], p_features[3]);
+        BTM_TRACE_EVENT4("                              %02x-%02x-%02x-%02x",
+                             p_features[4], p_features[5], p_features[6], p_features[7]);
+    }
 
     BTM_TRACE_EVENT2 ("BTM_SecBond: Remote sm4: 0x%x  HCI Handle: 0x%04x", p_dev_rec->sm4, p_dev_rec->hci_handle);
 
@@ -1205,7 +1212,7 @@
     }
 
     BTM_TRACE_DEBUG2 ("sec mode: %d sm4:x%x", btm_cb.security_mode, p_dev_rec->sm4);
-    if (!HCI_SIMPLE_PAIRING_SUPPORTED(btm_cb.devcb.local_features)
+    if (!HCI_SIMPLE_PAIRING_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0])
         || (p_dev_rec->sm4 == BTM_SM4_KNOWN))
     {
         if ( btm_sec_check_prefetch_pin (p_dev_rec) )
@@ -2778,11 +2785,10 @@
 #if (BTM_PRE_LISBON_INCLUDED == TRUE)
     else
 #endif
-        /* this function is only called from btm_read_local_features_complete()
+        /* btm_sec_dev_reset() is only called from btm_decode_ext_features_page(...)
          * right now. */
-        if (HCI_SIMPLE_PAIRING_SUPPORTED(btm_cb.devcb.local_features))
+        if (HCI_SIMPLE_PAIRING_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
     {
-        btsnd_hcic_write_simple_pairing_mode(HCI_SP_MODE_ENABLED);
 #if BLE_INCLUDED == TRUE
         btsnd_hcic_set_event_mask(LOCAL_BR_EDR_CONTROLLER_ID,
                                   (UINT8 *)HCI_DUMO_EVENT_MASK_EXT);
@@ -3165,7 +3171,7 @@
     if (BTM_SEC_IS_SM4_UNKNOWN(p_dev_rec->sm4))
     {
         p_dev_rec->sm4 = BTM_SM4_KNOWN;
-        STREAM_TO_ARRAY(features, p, BD_FEATURES_LEN);
+        STREAM_TO_ARRAY(features, p, HCI_FEATURE_BYTES_PER_PAGE);
         if (HCI_SSP_HOST_SUPPORTED(features))
         {
             p_dev_rec->sm4 = BTM_SM4_TRUE;
diff --git a/stack/btu/btu_hcif.c b/stack/btu/btu_hcif.c
index 4aa82ef..dd8d33c 100644
--- a/stack/btu/btu_hcif.c
+++ b/stack/btu/btu_hcif.c
@@ -1079,6 +1079,14 @@
             btm_read_linq_tx_power_complete (p);
             break;
 
+        case HCI_WRITE_SIMPLE_PAIRING_MODE:
+            btm_write_simple_paring_mode_complete (p);
+            break;
+
+        case HCI_WRITE_LE_HOST_SUPPORTED:
+            btm_write_le_host_supported_complete (p);
+            break;
+
 #if (BLE_INCLUDED == TRUE)
 /* BLE Commands */
         case HCI_BLE_READ_WHITE_LIST_SIZE :
@@ -1106,6 +1114,10 @@
             btm_read_ble_buf_size_complete(p, evt_len);
             break;
 
+        case HCI_BLE_READ_LOCAL_SPT_FEAT:
+            btm_read_ble_local_supported_features_complete(p, evt_len);
+            break;
+
         case HCI_BLE_READ_ADV_CHNL_TX_POWER:
             btm_read_tx_power_complete(p, TRUE);
             break;
@@ -1330,9 +1342,7 @@
                         break;
 
                     case HCI_READ_RMT_EXT_FEATURES_COMP_EVT:
-// btla-specific ++
-		                btu_hcif_read_rmt_ext_features_comp_evt (p_cmd - 3, 0);
-// btla-specific --
+                        btm_read_remote_ext_features_failed(status);
                         break;
 
                     case HCI_AUTHENTICATION_REQUESTED:
diff --git a/stack/include/btm_api.h b/stack/include/btm_api.h
index a639fa6..0f1bb2b 100644
--- a/stack/include/btm_api.h
+++ b/stack/include/btm_api.h
@@ -172,7 +172,7 @@
 
 /* Inquiry modes
  * Note: These modes are associated with the inquiry active values (BTM_*ACTIVE) */
-#define BTM_INQUIRY_NONE			0
+#define BTM_INQUIRY_NONE            0
 #define BTM_GENERAL_INQUIRY         0x01
 #define BTM_LIMITED_INQUIRY         0x02
 #define BTM_BR_INQUIRY_MASK         (BTM_GENERAL_INQUIRY | BTM_LIMITED_INQUIRY)
@@ -808,6 +808,10 @@
 #define BTM_BL_UPDATE_MASK      0x0004
 #define BTM_BL_ROLE_CHG_MASK    0x0008
 
+/* Device features mask definitions */
+#define BTM_FEATURE_BYTES_PER_PAGE  HCI_FEATURE_BYTES_PER_PAGE
+#define BTM_EXT_FEATURES_PAGE_MAX   HCI_EXT_FEATURES_PAGE_MAX
+
 /* the data type associated with BTM_BL_CONN_EVT */
 typedef struct
 {
@@ -815,7 +819,7 @@
     BD_ADDR_PTR     p_bda;      /* The address of the newly connected device */
     DEV_CLASS_PTR   p_dc;       /* The device class */
     BD_NAME_PTR     p_bdn;      /* The device name */
-    UINT8          *p_features; /* The remote device's supported features */
+    UINT8          *p_features; /* pointer to the remote device's features page[0] (supported features page) */
 } tBTM_BL_CONN_DATA;
 
 /* the data type associated with BTM_BL_DISCN_EVT */
@@ -873,7 +877,7 @@
 ** Registered through BTM_AclRegisterForChanges call.
 */
 typedef void (tBTM_ACL_DB_CHANGE_CB) (BD_ADDR p_bda, DEV_CLASS p_dc,
-                                      BD_NAME p_bdn, BD_FEATURES features,
+                                      BD_NAME p_bdn, UINT8 *features,
                                       BOOLEAN is_new);
 
 /*****************************************************************************
@@ -2178,6 +2182,18 @@
 
 /*******************************************************************************
 **
+** Function         BTM_ReadLocalExtendedFeatures
+**
+** Description      This function is called to read the local extended features
+**
+** Returns          pointer to the local extended features mask or NULL if bad
+**                  page
+**
+*******************************************************************************/
+    BTM_API extern UINT8 *BTM_ReadLocalExtendedFeatures (UINT8 page_number);
+
+/*******************************************************************************
+**
 ** Function         BTM_ReadBrcmFeatures
 **
 ** Description      This function is called to read the Broadcom specific features
@@ -2665,15 +2681,65 @@
 **
 ** Function         BTM_ReadRemoteFeatures
 **
-** Description      This function is called to read a remote device's features
+** Description      This function is called to read a remote device's 
+**                  supported features mask (features mask located at page 0)
 **
-** Returns          pointer to the features string
+**                  Note: The size of device features mask page is
+**                  BTM_FEATURE_BYTES_PER_PAGE bytes.
+**
+** Returns          pointer to the remote supported features mask
 **
 *******************************************************************************/
     BTM_API extern UINT8 *BTM_ReadRemoteFeatures (BD_ADDR addr);
 
 /*******************************************************************************
 **
+** Function         BTM_ReadRemoteExtendedFeatures
+**
+** Description      This function is called to read a specific extended features
+**                  page of the remote device
+**
+**                  Note1: The size of device features mask page is
+**                  BTM_FEATURE_BYTES_PER_PAGE bytes.
+**                  Note2: The valid device features mask page number depends on
+**                  the remote device capabilities. It is expected to be in the
+**                  range [0 - BTM_EXT_FEATURES_PAGE_MAX].
+
+** Returns          pointer to the remote extended features mask
+**                  or NULL if page_number is not valid
+**
+*******************************************************************************/
+    BTM_API extern UINT8 *BTM_ReadRemoteExtendedFeatures (BD_ADDR addr, UINT8 page_number);
+
+/*******************************************************************************
+**
+** Function         BTM_ReadNumberRemoteFeaturesPages
+**
+** Description      This function is called to retrieve the number of feature pages
+**                  read from the remote device
+**
+** Returns          number of features pages read from the remote device
+**
+*******************************************************************************/
+    BTM_API extern UINT8 BTM_ReadNumberRemoteFeaturesPages (BD_ADDR addr);
+
+/*******************************************************************************
+**
+** Function         BTM_ReadAllRemoteFeatures
+**
+** Description      This function is called to read all features of the remote device
+**
+** Returns          pointer to the byte[0] of the page[0] of the remote device
+**                  feature mask.
+**
+** Note:            the function returns the pointer to the array of the size
+**                  BTM_FEATURE_BYTES_PER_PAGE * (BTM_EXT_FEATURES_PAGE_MAX + 1).
+**
+*******************************************************************************/
+    BTM_API extern UINT8 *BTM_ReadAllRemoteFeatures (BD_ADDR addr);
+
+/*******************************************************************************
+**
 ** Function         BTM_InqFirstResult
 **
 ** Description      This function looks through the inquiry database for the first
@@ -3764,7 +3830,7 @@
 **
 *******************************************************************************/
     BTM_API extern BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class,
-                                             BD_NAME bd_name, BD_FEATURES features,
+                                             BD_NAME bd_name, UINT8 *features,
                                              UINT32 trusted_mask[], LINK_KEY link_key,
                                              UINT8 key_type, tBTM_IO_CAP io_cap);
 
diff --git a/stack/include/hcidefs.h b/stack/include/hcidefs.h
index 0584f65..ad31d52 100644
--- a/stack/include/hcidefs.h
+++ b/stack/include/hcidefs.h
@@ -608,6 +608,18 @@
     0x0000000000002000 AMP Status Change Event
 */
 
+/* the event mask page 2 (CLB + CSA4) for BR/EDR controller */
+#define HCI_PAGE_2_EVENT_MASK                  "\x00\x00\x00\x00\x00\x7F\xC0\x00"
+/*  0x0000000000004000 Triggered Clock Capture Event
+    0x0000000000008000 Sync Train Complete Event
+    0x0000000000010000 Sync Train Received Event
+    0x0000000000020000 Connectionless Broadcast Receive Event
+    0x0000000000040000 Connectionless Broadcast Timeout Event
+    0x0000000000080000 Truncated Page Complete Event
+    0x0000000000100000 Salve Page Response Timeout Event
+    0x0000000000200000 Connectionless Broadcast Channel Map Change Event
+    0x0000000000400000 Inquiry Response Notification Event
+*/
 
 /*
 ** Definitions for packet type masks (BT1.2 and BT2.0 definitions)
@@ -1293,12 +1305,19 @@
 #define HCI_EDR3_DH3_PACKET_SIZE    552
 #define HCI_EDR3_DH5_PACKET_SIZE    1021
 
-/*
-**   Features encoding - page 0
-*/
-#define HCI_NUM_FEATURE_BYTES           8
+/* Feature Pages */
+#define HCI_EXT_FEATURES_PAGE_0     0       /* Extended Feature Page 0 (regular features) */
+#define HCI_EXT_FEATURES_PAGE_1     1       /* Extended Feature Page 1 */
+#define HCI_EXT_FEATURES_PAGE_2     2       /* Extended Feature Page 2 */
+#define HCI_EXT_FEATURES_PAGE_MAX   HCI_EXT_FEATURES_PAGE_2
+
+#define HCI_FEATURE_BYTES_PER_PAGE      8
+
 #define HCI_FEATURES_KNOWN(x) ((x[0] | x[1] | x[2] | x[3] | x[4] | x[5] | x[6] | x[7]) != 0)
 
+/*
+**   LMP features encoding - page 0
+*/
 #define HCI_FEATURE_3_SLOT_PACKETS_MASK 0x01
 #define HCI_FEATURE_3_SLOT_PACKETS_OFF  0
 #define HCI_3_SLOT_PACKETS_SUPPORTED(x) ((x)[HCI_FEATURE_3_SLOT_PACKETS_OFF] & HCI_FEATURE_3_SLOT_PACKETS_MASK)
@@ -1550,7 +1569,7 @@
 #define HCI_LMP_EXTENDED_SUPPORTED(x)   ((x)[HCI_FEATURE_EXTENDED_OFF] & HCI_FEATURE_EXTENDED_MASK)
 
 /*
-**   Features encoding - page 1
+**   LMP features encoding - page 1
 */
 #define HCI_EXT_FEATURE_SSP_HOST_MASK 0x01
 #define HCI_EXT_FEATURE_SSP_HOST_OFF  0
@@ -1565,6 +1584,37 @@
 #define HCI_SIMUL_DUMO_HOST_SUPPORTED(x) ((x)[HCI_EXT_FEATURE_SIMUL_DUMO_HOST_OFF] & HCI_EXT_FEATURE_SIMUL_DUMO_HOST_MASK)
 
 /*
+**   LMP features encoding - page 2
+*/
+#define HCI_EXT_FEATURE_CSB_MASTER_MASK         0x01
+#define HCI_EXT_FEATURE_CSB_MASTER_OFF          0
+#define HCI_CSB_MASTER_SUPPORTED(x) ((x)[HCI_EXT_FEATURE_CSB_MASTER_OFF] & HCI_EXT_FEATURE_CSB_MASTER_MASK)
+
+#define HCI_EXT_FEATURE_CSB_SLAVE_MASK          0x02
+#define HCI_EXT_FEATURE_CSB_SLAVE_OFF           0
+#define HCI_CSB_SLAVE_SUPPORTED(x) ((x)[HCI_EXT_FEATURE_CSB_SLAVE_OFF] & HCI_EXT_FEATURE_CSB_SLAVE_MASK)
+
+#define HCI_EXT_FEATURE_SYNC_TRAIN_MASTER_MASK  0x04
+#define HCI_EXT_FEATURE_SYNC_TRAIN_MASTER_OFF   0
+#define HCI_SYNC_TRAIN_MASTER_SUPPORTED(x) ((x)[HCI_EXT_FEATURE_SYNC_TRAIN_MASTER_OFF] & HCI_EXT_FEATURE_SYNC_TRAIN_MASTER_MASK)
+
+#define HCI_EXT_FEATURE_SYNC_SCAN_SLAVE_MASK    0x08
+#define HCI_EXT_FEATURE_SYNC_SCAN_SLAVE_OFF     0
+#define HCI_SYNC_SCAN_SLAVE_SUPPORTED(x) ((x)[HCI_EXT_FEATURE_SYNC_SCAN_SLAVE_OFF] & HCI_EXT_FEATURE_SYNC_SCAN_SLAVE_MASK)
+
+#define HCI_EXT_FEATURE_INQ_RESP_NOTIF_MASK     0x10
+#define HCI_EXT_FEATURE_INQ_RESP_NOTIF_OFF      0
+#define HCI_INQ_RESP_NOTIF_SUPPORTED(x) ((x)[HCI_EXT_FEATURE_INQ_RESP_NOTIF_OFF] & HCI_EXT_FEATURE_INQ_RESP_NOTIF_MASK)
+
+/*
+**   LE features encoding - page 0 (the only page for now)
+*/
+#define HCI_LE_FEATURE_LE_ENCRYPTION_MASK       0x01
+#define HCI_LE_FEATURE_LE_ENCRYPTION_OFF        0
+#define HCI_LE_ENCRYPTION_SUPPORTED(x) ((x)[HCI_LE_FEATURE_LE_ENCRYPTION_OFF] & HCI_LE_FEATURE_LE_ENCRYPTION_MASK)
+
+
+/*
 **   Local Supported Commands encoding
 */
 #define HCI_NUM_SUPP_COMMANDS_BYTES           64
@@ -2295,6 +2345,12 @@
 #define HCI_SUPP_COMMANDS_SET_MWS_PATTERN_CONF_OFF       30
 #define HCI_SET_MWS_PATTERN_CONFIGURATION_SUPPORTED(x)   ((x)[HCI_SUPP_COMMANDS_SET_MWS_PATTERN_CONF_OFF] & HCI_SUPP_COMMANDS_SET_MWS_PATTERN_CONF_MASK)
 
+/* Supported Commands (Byte 30 bit 5) */
+#define HCI_SUPP_COMMANDS_SET_TRIG_CLK_CAP_MASK         0x20
+#define HCI_SUPP_COMMANDS_SET_TRIG_CLK_CAP_OFF          30
+#define HCI_SET_TRIG_CLK_CAP_SUPPORTED(x)               ((x)[HCI_SUPP_COMMANDS_SET_TRIG_CLK_CAP_OFF] & HCI_SUPP_COMMANDS_SET_TRIG_CLK_CAP_MASK)
+
+
 /* Supported Commands (Byte 30 bit 6-7) */
 #define HCI_SUPP_COMMANDS_TRUNCATED_PAGE             0x06
 #define HCI_SUPP_COMMANDS_TRUNCATED_PAGE_OFF         30
diff --git a/stack/l2cap/l2c_utils.c b/stack/l2cap/l2c_utils.c
index 581930f..c684118 100644
--- a/stack/l2cap/l2c_utils.c
+++ b/stack/l2cap/l2c_utils.c
@@ -2086,6 +2086,9 @@
 
     if (dev_type == BT_DEVICE_TYPE_BLE)
     {
+        if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
+            return FALSE;
+
         p_lcb->ble_addr_type = addr_type;
         p_lcb->is_ble_link   = TRUE;
 
@@ -2118,7 +2121,7 @@
                 continue; /* No Master Slave switch not allowed when SCO Active */
 #endif
 
-            if (HCI_SWITCH_SUPPORTED(btm_cb.devcb.local_features))
+            if (HCI_SWITCH_SUPPORTED(BTM_ReadLocalFeatures()))
             {
                 /* mark this lcb waiting for switch to be completed and
                    start switch on the other one */