From 3aa60544585b5fb0f35c1165539a4a859fc0f25c Mon Sep 17 00:00:00 2001 From: Andre Eisenbach Date: Fri, 22 Mar 2013 18:00:51 -0700 Subject: [PATCH] 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 --- bta/dm/bta_dm_act.c | 12 +- bta/dm/bta_dm_api.c | 19 +- bta/dm/bta_dm_int.h | 2 +- bta/include/bta_api.h | 11 +- stack/btm/btm_acl.c | 488 +++++++++++++++++++++++++--------- stack/btm/btm_ble_gap.c | 56 ++-- stack/btm/btm_dev.c | 40 ++- stack/btm/btm_devctl.c | 683 ++++++++++++++++++++++++++++++++++++++---------- stack/btm/btm_inq.c | 44 ++-- stack/btm/btm_int.h | 46 ++-- stack/btm/btm_sco.c | 4 +- stack/btm/btm_sec.c | 30 ++- stack/btu/btu_hcif.c | 16 +- stack/include/btm_api.h | 78 +++++- stack/include/hcidefs.h | 66 ++++- stack/l2cap/l2c_utils.c | 5 +- 16 files changed, 1233 insertions(+), 367 deletions(-) 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 @@ static BOOLEAN bta_dm_check_av(UINT16 event); #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_bl_change_cback (tBTM_BL_EVENT_DATA *p_data) ** *******************************************************************************/ 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 @@ static void bta_dm_set_eir (char *local_name) 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 @@ tBTA_STATUS BTA_DmVendorSpecificCommand (UINT16 opcode, UINT8 param_len, { 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 @@ void BTA_DmAddDevice(BD_ADDR bd_addr, DEV_CLASS dev_class, LINK_KEY link_key, } 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 @@ tBTA_STATUS BTA_DmRemoveDevice(BD_ADDR bd_addr) ** *******************************************************************************/ 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 @@ void BTA_DmAddDevWithName (BD_ADDR bd_addr, DEV_CLASS dev_class, 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 @@ typedef struct 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 @@ typedef UINT8 tBTA_DM_BLE_SCAN_COND_OP; #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 @@ typedef tSDP_DISCOVERY_DB tBTA_DISCOVERY_DB; #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 @@ BTA_API extern void BTA_DmAddDevice(BD_ADDR bd_addr, DEV_CLASS dev_class, ** ** 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 @@ tACL_CONN *btm_bda_to_acl (BD_ADDR bda) } } } - BTM_TRACE_DEBUG0 ("btm_bda_to_acl Not found"); /* If here, no BD Addr found */ return((tACL_CONN *)NULL); @@ -216,27 +221,27 @@ void btm_acl_created (BD_ADDR bda, DEV_CLASS dc, BD_NAME bdn, 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->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; + + 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 { - 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; - - btm_establish_continue (p); - return; } + + btm_establish_continue (p); + return; } } @@ -278,8 +283,8 @@ void btm_acl_report_role_change (UINT8 hci_status, BD_ADDR bda) { 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 @@ void btm_acl_removed (BD_ADDR bda) 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 @@ tBTM_STATUS BTM_SwitchRole (BD_ADDR remote_bd_addr, UINT8 new_role, tBTM_CMPL_CB 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 @@ tBTM_STATUS BTM_ChangeLinkKey (BD_ADDR remote_bd_addr, tBTM_CMPL_CB *p_cb) /* 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 @@ void btm_acl_encrypt_change (UINT16 handle, UINT8 status, UINT8 encr_enable) 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 @@ tBTM_STATUS BTM_SetLinkPolicy (BD_ADDR remote_bda, UINT16 *settings) } 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 @@ void btm_read_remote_version_complete (UINT8 *p) /******************************************************************************* ** +** 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_version_complete (UINT8 *p) *******************************************************************************/ 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_features_complete (UINT8 *p) *******************************************************************************/ 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); + btm_read_remote_ext_features_failed (status); + return; + } - /* 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); + /* Extract parameters */ + STREAM_TO_UINT16 (handle, p); + STREAM_TO_UINT8 (page_num, p); + STREAM_TO_UINT8 (max_page, p); - req_pend = (p_dev_rec->sm4 & BTM_SM4_REQ_PEND); + /* 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 (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 (max_page > HCI_EXT_FEATURES_PAGE_MAX) + { + BTM_TRACE_ERROR1("btm_read_remote_ext_features_complete page=%d unknown", max_page); + return; + } - if (HCI_SSP_HOST_SUPPORTED(ext_features)) - { - p_dev_rec->sm4 = BTM_SM4_TRUE; - } - } + p_acl_cb = &btm_cb.acl_db[acl_idx]; - 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); + /* Copy the received features page */ + STREAM_TO_ARRAY(p_acl_cb->peer_lmp_features[page_num], p, HCI_FEATURE_BYTES_PER_PAGE); - if (!BTM_SEC_IS_SM4(p_dev_rec->sm4)) - { - p_dev_rec->sm4 = BTM_SM4_KNOWN; - } + /* 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; + } - if (req_pend) - l2cu_resubmit_pending_sec_req (p_dev_rec->bd_addr); + /* Reading of remote feature pages is complete */ + BTM_TRACE_DEBUG1("BTM reached last remote extended features page (%d)", page_num); - btm_establish_continue (p_acl_cb); + /* Process the pages */ + btm_process_remote_ext_features (p_acl_cb, (UINT8) (page_num + 1)); - break; - } - } - } + /* Continue with HCI connection establishment */ + btm_establish_continue (p_acl_cb); } /******************************************************************************* @@ -1379,7 +1538,8 @@ static void btm_establish_continue (tACL_CONN *p_acl_cb) 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 @@ static void btm_establish_continue (tACL_CONN *p_acl_cb) (*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_process_clk_off_comp_evt (UINT16 hci_handle, UINT16 clock_offset) *******************************************************************************/ 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 @@ void btm_acl_role_changed (UINT8 hci_status, BD_ADDR bd_addr, UINT8 new_role) 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 @@ tBTM_STATUS BTM_ReadRemoteVersion (BD_ADDR addr, UINT8 *lmp_version, ** ** 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 @@ UINT8 *BTM_ReadRemoteFeatures (BD_ADDR addr) 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 @@ tBTM_STATUS BTM_SetQoS (BD_ADDR bd, FLOW_SPEC *p_flow, tBTM_CMPL_CB *p_cb) 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 @@ void btm_read_link_quality_complete (UINT8 *p) 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 @@ void btm_acl_paging (BT_HDR *p, BD_ADDR bda) 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 @@ BOOLEAN btm_acl_notif_conn_collision (BD_ADDR bda) 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 @@ void BTM_BleUpdateAdvFilterPolicy(tBTM_BLE_AFP adv_policy) 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 @@ tBTM_STATUS BTM_BleObserve(BOOLEAN start, UINT8 duration, 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_STATUS BTM_BleBroadcast(BOOLEAN start) 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 BTM_BleSetBgConnType(tBTM_BLE_CONN_TYPE bg_conn_type, 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_STATUS BTM_BleSetConnMode(BOOLEAN is_directed) 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 @@ tBTM_STATUS BTM_BleSetAdvParams(UINT16 adv_int_min, UINT16 adv_int_max, 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 @@ void BTM_BleReadAdvParams (UINT16 *adv_int_min, UINT16 *adv_int_max, 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 @@ void BTM_BleSetScanParams(UINT16 scan_interval, UINT16 scan_window, tBTM_BLE_SCA 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 @@ tBTM_STATUS BTM_BleWriteScanRsp(tBTM_BLE_AD_MASK data_mask, tBTM_BLE_ADV_DATA *p *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 @@ tBTM_STATUS BTM_BleWriteAdvData(tBTM_BLE_AD_MASK data_mask, tBTM_BLE_ADV_DATA *p 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_STATUS btm_ble_read_remote_name(BD_ADDR remote_bda, tBTM_INQ_INFO *p_cur, t { 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 @@ static tBTM_STATUS btm_ble_stop_adv(void) *******************************************************************************/ 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_timeout(TIMER_LIST_ENT *p_tle) 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 @@ static tBTM_SEC_DEV_REC *btm_find_oldest_dev (void); ** 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 @@ static tBTM_SEC_DEV_REC *btm_find_oldest_dev (void); ** *******************************************************************************/ 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 @@ BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name, (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 @@ char *BTM_SecReadDevName (BD_ADDR bd_addr) ** 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 @@ BOOLEAN btm_dev_support_switch (BD_ADDR bd_addr) 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 @@ BOOLEAN btm_dev_support_switch (BD_ADDR bd_addr) /* 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 @@ tBTM_SEC_DEV_REC *btm_find_or_alloc_dev (BD_ADDR bd_addr) ** 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_dev_reset (void); 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 @@ tBTM_STATUS BTM_SetAfhChannels (UINT8 first, UINT8 last) 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_SetAfhChannels (UINT8 first, UINT8 last) 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 @@ void btm_get_ble_buffer_size(void) /* 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 @@ void btm_get_local_version (void) ** 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 @@ void btm_after_reset_hold_complete (void) ** ** 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 @@ void btm_read_hci_buf_size_complete (UINT8 *p, UINT16 evt_len) ** ** 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 @@ void btm_read_ble_buf_size_complete (UINT8 *p, UINT16 evt_len) 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 @@ void btm_read_white_list_size_complete(UINT8 *p, UINT16 evt_len) 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 @@ void btm_read_local_version_complete (UINT8 *p, UINT16 evt_len) 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 -** -** Description Local function called to send a read local extended feature to controller -** -** Returns void -** -*******************************************************************************/ -void btm_read_local_extended_feature (void) -{ - 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 +** Function btm_decode_ext_features_page ** - -** Description This function is called when local features read is complete. -** This is the last step of the startup sequence. +** Description This function is decodes a features page. ** ** Returns void ** *******************************************************************************/ -void btm_read_local_ext_features_complete(UINT8 *p, UINT16 evt_len) +static void btm_decode_ext_features_page (UINT8 page_number, const UINT8 *p_features) { - 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) - { - 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); - } - - 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) + BTM_TRACE_DEBUG1 ("btm_decode_ext_features_page page: %d", page_number); + switch (page_number) { - /* 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); + /* Extended (Legacy) Page 0 */ + case HCI_EXT_FEATURES_PAGE_0: - /* 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 @@ void btm_read_local_features_complete (UINT8 *p, UINT16 evt_len) 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 @@ void btm_read_local_features_complete (UINT8 *p, UINT16 evt_len) } /* 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 @@ void btm_read_local_features_complete (UINT8 *p, UINT16 evt_len) 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 @@ void btm_read_local_features_complete (UINT8 *p, UINT16 evt_len) 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 @@ void btm_read_local_features_complete (UINT8 *p, UINT16 evt_len) 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 @@ void btm_read_local_features_complete (UINT8 *p, UINT16 evt_len) 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; + } +} + +/******************************************************************************* +** +** 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(); } - btm_read_local_extended_feature (); } /******************************************************************************* @@ -1077,9 +1462,9 @@ UINT8 btm_get_voice_coding_support( void ) { 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_ReadDeviceClass (void) *******************************************************************************/ 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 @@ tBTM_STATUS BTM_SetDiscoverability (UINT16 inq_mode, UINT16 window, UINT16 inter 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 @@ tBTM_STATUS BTM_SetInquiryScanType (UINT16 scan_type) 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 @@ tBTM_STATUS BTM_SetPageScanType (UINT16 scan_type) 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 @@ tBTM_STATUS BTM_SetInquiryMode (UINT8 mode) } 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 @@ tBTM_STATUS BTM_SetConnectability (UINT16 page_mode, UINT16 window, UINT16 inter 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 @@ tBTM_STATUS BTM_StartInquiry (tBTM_INQ_PARMS *p_inqparms, tBTM_INQ_RESULTS_CB *p #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 @@ void btm_process_inq_complete (UINT8 status, UINT8 mode) 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 @@ void btm_read_linq_tx_power_complete(UINT8 *p) 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 @@ typedef char tBTM_LOC_BD_NAME[BTM_MAX_LOC_BD_NAME_LEN + 1]; 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 @@ typedef struct 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 @@ typedef struct 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 @@ typedef struct /* 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 */ + + /* 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_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 */ + 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 @@ typedef struct 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 @@ typedef struct 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 @@ typedef struct 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_features_complete (UINT8 *p, UINT16 evt_len); extern void btm_read_local_ext_features_complete (UINT8 *p, UINT16 evt_len); extern void btm_read_local_name_complete (UINT8 *p, UINT16 evt_len); 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 @@ static tBTM_STATUS btm_send_connect_request(UINT16 acl_handle, 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 @@ void BTM_SetSecurityMode (UINT8 security_mode) } 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_STATUS BTM_SecBond (BD_ADDR bd_addr, UINT8 pin_len, UINT8 *p_pin, UINT32 tr { 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 @@ tBTM_STATUS BTM_SecBond (BD_ADDR bd_addr, UINT8 pin_len, UINT8 *p_pin, UINT32 tr #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 @@ tBTM_STATUS BTM_SecBond (BD_ADDR bd_addr, UINT8 pin_len, UINT8 *p_pin, UINT32 tr } } - 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 @@ tBTM_STATUS BTM_SecBond (BD_ADDR bd_addr, UINT8 pin_len, UINT8 *p_pin, UINT32 tr } 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 @@ void btm_sec_dev_reset (void) #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 @@ void btm_sec_rmt_host_support_feat_evt (UINT8 *p) 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 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l 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 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l 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 @@ static void btu_hcif_hdl_command_status (UINT16 opcode, UINT8 status, UINT8 *p_c 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 @@ typedef UINT8 (tBTM_FILTER_CB) (BD_ADDR bd_addr, DEV_CLASS dc); /* 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 @@ typedef UINT16 tBTM_BL_EVENT_MASK; #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 @@ typedef struct 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 @@ typedef void (tBTM_BL_CHANGE_CB) (tBTM_BL_EVENT_DATA *p_data); ** 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 @@ extern "C" { /******************************************************************************* ** +** 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 @@ BTM_API extern BOOLEAN BTM_TryAllocateSCN(UINT8 scn); ** ** 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 tBTM_STATUS BTM_SetWBSCodec (tBTM_SCO_CODEC_TYPE codec_type); ** *******************************************************************************/ 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 @@ typedef struct #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 @@ typedef struct #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 @@ typedef struct #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 @@ typedef struct #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 @@ BOOLEAN l2cu_create_conn (tL2C_LCB *p_lcb) 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 @@ BOOLEAN l2cu_create_conn (tL2C_LCB *p_lcb) 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 */ -- 2.11.0