diff --git a/components/bt/host/bluedroid/api/esp_gap_ble_api.c b/components/bt/host/bluedroid/api/esp_gap_ble_api.c index eca58b2515e..81a8069848b 100644 --- a/components/bt/host/bluedroid/api/esp_gap_ble_api.c +++ b/components/bt/host/bluedroid/api/esp_gap_ble_api.c @@ -154,7 +154,7 @@ esp_err_t esp_ble_gap_update_conn_params(esp_ble_conn_update_params_t *params) ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); if(!params) { LOG_ERROR("%s,params is NULL", __func__); - return ESP_FAIL; + return ESP_ERR_INVALID_ARG; } if (ESP_BLE_IS_VALID_PARAM(params->min_int, BLE_CONN_INT_MIN_HOST_CHECK, ESP_BLE_CONN_INT_MAX) && @@ -187,7 +187,7 @@ esp_err_t esp_ble_gap_update_conn_params(esp_ble_conn_update_params_t *params) } else { LOG_ERROR("%s,invalid connection params:min_int = %d, max_int = %d, latency = %d, timeout = %d",\ __func__, params->min_int, params->max_int, params->latency, params->timeout); - return ESP_FAIL; + return ESP_ERR_INVALID_ARG; } } @@ -433,7 +433,7 @@ esp_err_t esp_ble_gap_set_prefer_conn_params(esp_bd_addr_t bd_addr, } else { LOG_ERROR("%s,invalid connection params:min_int = %d, max_int = %d, latency = %d, timeout = %d",\ __func__, min_conn_int, max_conn_int, slave_latency, supervision_tout); - return ESP_FAIL; + return ESP_ERR_INVALID_ARG; } } #endif // #if (BLE_42_FEATURE_SUPPORT == TRUE) diff --git a/components/bt/host/bluedroid/bta/dm/bta_dm_act.c b/components/bt/host/bluedroid/bta/dm/bta_dm_act.c index 8c2aef3554c..9b51c486c06 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_act.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_act.c @@ -5402,10 +5402,11 @@ void bta_dm_ble_scan (tBTA_DM_MSG *p_data) if ((status = BTM_BleScan(TRUE, p_data->ble_scan.duration, bta_dm_scan_results_cb, bta_dm_scan_cmpl_cb, bta_dm_scan_discard_cb)) != BTM_CMD_STARTED) { APPL_TRACE_WARNING(" %s start scan failed. status=0x%x\n", __FUNCTION__, status); + } else { + status = BTM_SUCCESS; } memset(&cb_params, 0, sizeof(cb_params)); - status = (status == BTM_CMD_STARTED ? BTA_SUCCESS : BTA_FAILURE); cb_params.status = status; BTM_LegacyBleCallbackTrigger(BTM_BLE_LEGACY_GAP_SCAN_START_COMPLETE_EVT, &cb_params); @@ -5415,10 +5416,11 @@ void bta_dm_ble_scan (tBTA_DM_MSG *p_data) if (status != BTM_CMD_STARTED){ APPL_TRACE_WARNING(" %s stop scan failed, status=0x%x\n", __FUNCTION__, status); + } else { + status = BTM_SUCCESS; } memset(&cb_params, 0, sizeof(cb_params)); - status = (status == BTM_CMD_STARTED ? BTA_SUCCESS : BTA_FAILURE); cb_params.status = status; BTM_LegacyBleCallbackTrigger(BTM_BLE_LEGACY_GAP_SCAN_STOP_COMPLETE_EVT, &cb_params); #if (BLE_TOPOLOGY_CHECK == TRUE) diff --git a/components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c b/components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c index 9dce7417070..2fcf2bdcb8e 100644 --- a/components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c +++ b/components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c @@ -1153,7 +1153,9 @@ void bta_gattc_disc_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) } if (p_clcb->auto_update == BTA_GATTC_DISC_WAITING) { - /* start discovery again */ + /* Service change arrived during discovery; restart even if p_q_cmd is set. + * Mirrors bta_gattc_op_cmpl(). */ + p_clcb->auto_update = BTA_GATTC_REQ_WAITING; bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL); } /* get any queued command to proceed */ @@ -1484,8 +1486,9 @@ void bta_gattc_write_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data) ( *p_clcb->p_rcb->p_cback)(BTA_GATTC_PREP_WRITE_EVT, (tBTA_GATTC *)&cb_data); return; } - /* Rsp value is one ATT chunk (<= MTU-5), not necessarily full api_write.len. */ - { + /* Rsp value is one ATT chunk (<= MTU-5), not necessarily full api_write.len. + * Only validate echo on success; ATT Error Response has no prepare-write body. */ + if (p_data->status == BTA_GATT_OK) { UINT16 rsp_len = p_data->p_cmpl->att_value.len; UINT16 req_len = p_clcb->p_q_cmd->api_write.len; tGATT_VALUE *a = &p_data->p_cmpl->att_value; diff --git a/components/bt/host/bluedroid/bta/gatt/bta_gattc_api.c b/components/bt/host/bluedroid/bta/gatt/bta_gattc_api.c index 6eb81b24311..c0de44c2b44 100644 --- a/components/bt/host/bluedroid/bta/gatt/bta_gattc_api.c +++ b/components/bt/host/bluedroid/bta/gatt/bta_gattc_api.c @@ -951,7 +951,10 @@ tBTA_GATT_STATUS BTA_GATTC_RegisterForNotifications (tBTA_GATTC_IF client_if, return BTA_GATT_ILLEGAL_PARAMETER; } } else { - APPL_TRACE_WARNING("reg notif: cache not ready, skip check"); + APPL_TRACE_WARNING("reg notif: cache not ready, skip check, client_if=%d handle=0x%04x bd_addr:%02x:%02x:%02x:%02x:%02x:%02x state=%d", + client_if, handle, + bda[0], bda[1], bda[2], bda[3], bda[4], bda[5], + p_srcb ? p_srcb->state : 0xff); } if ((p_clreg = bta_gattc_cl_get_regcb(client_if)) != NULL) { diff --git a/components/bt/host/bluedroid/btc/core/btc_main.c b/components/bt/host/bluedroid/btc/core/btc_main.c index bbcb17b670b..f42d37771de 100644 --- a/components/bt/host/bluedroid/btc/core/btc_main.c +++ b/components/bt/host/bluedroid/btc/core/btc_main.c @@ -183,7 +183,6 @@ uint32_t btc_get_ble_status(void) } #endif // #if ((SMP_INCLUDED == TRUE) || (BLE_PRIVACY_SPT == TRUE)) -#if (SMP_INCLUDED == TRUE) // Number of recorded devices extern uint8_t btm_ble_sec_dev_record_count(void); uint8_t sec_dev_cnt = btm_ble_sec_dev_record_count(); @@ -191,14 +190,14 @@ uint32_t btc_get_ble_status(void) BTC_TRACE_WARNING("%s security device record count %d", __func__, sec_dev_cnt); status |= BIT(BTC_BLE_STATUS_DEVICE_REC); } - +#if SMP_INCLUDED == TRUE // Number of saved bonded devices int bond_cnt = btc_storage_get_num_ble_bond_devices(); if (bond_cnt) { BTC_TRACE_WARNING("%s bonded devices count %d", __func__, bond_cnt); status |= BIT(BTC_BLE_STATUS_BOND); } -#endif // SMP_INCLUDED +#endif // SMP_INCLUDED == TRUE #if (BLE_PRIVACY_SPT == TRUE) // Privacy enabled diff --git a/components/bt/host/bluedroid/hci/hci_layer.c b/components/bt/host/bluedroid/hci/hci_layer.c index 4bf553d0ce6..5c4a904b249 100644 --- a/components/bt/host/bluedroid/hci/hci_layer.c +++ b/components/bt/host/bluedroid/hci/hci_layer.c @@ -518,6 +518,18 @@ static bool filter_incoming_event(BT_HDR *packet) metadata = (hci_cmd_metadata_t *)(wait_entry->data); if (metadata->command_status_cb) { metadata->command_status_cb(status, &metadata->command, metadata->context); +#if ((BLE_50_FEATURE_SUPPORT == TRUE) || (BLE_42_FEATURE_SUPPORT == TRUE)) + /* No Command Complete follows a failed Command Status (Core Spec Vol 4 Part E). */ + if (status != HCI_SUCCESS) { + BlE_SYNC *sync_info = btsnd_hcic_ble_get_sync_info(); + if (!sync_info) { + HCI_TRACE_WARNING("%s sync_info is NULL. opcode = 0x%x", __func__, opcode); + } else if (sync_info->sync_sem && sync_info->opcode == opcode) { + osi_sem_give(&sync_info->sync_sem); + sync_info->opcode = 0; + } + } +#endif // #if ((BLE_50_FEATURE_SUPPORT == TRUE) || (BLE_42_FEATURE_SUPPORT == TRUE)) } goto intercepted; diff --git a/components/bt/host/bluedroid/stack/btm/btm_acl.c b/components/bt/host/bluedroid/stack/btm/btm_acl.c index 4621e6092e8..cc22fb5e4e8 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_acl.c +++ b/components/bt/host/bluedroid/stack/btm/btm_acl.c @@ -2393,7 +2393,7 @@ void btm_read_channel_map_complete(UINT8 *p) memcpy(results.rem_bda, p_acl_cb->remote_addr, BD_ADDR_LEN); } } else { - results.status = BTM_ERR_PROCESSING; + results.status = BTM_HCI_ERROR | results.hci_status; BTM_TRACE_ERROR("BTM Channel Map Read Failed: hci status 0x%02x", results.hci_status); } diff --git a/components/bt/host/bluedroid/stack/btm/btm_ble.c b/components/bt/host/bluedroid/stack/btm/btm_ble.c index 81a0c449547..7bc86d38e70 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_ble.c +++ b/components/bt/host/bluedroid/stack/btm/btm_ble.c @@ -2989,26 +2989,47 @@ uint8_t btm_ble_scan_active_count(void) return count; } +#if (BLE_INCLUDED == TRUE) #if (SMP_INCLUDED == TRUE) +extern bool btc_config_has_section(const char *section); +#endif + uint8_t btm_ble_sec_dev_record_count(void) { tBTM_SEC_DEV_REC *p_dev_rec = NULL; list_node_t *p_node = NULL; uint8_t count = 0; - /* First look for the non-paired devices for the oldest entry */ for (p_node = list_begin(btm_cb.p_sec_dev_rec_list); p_node; p_node = list_next(p_node)) { p_dev_rec = list_node(p_node); +#if (SMP_INCLUDED == TRUE) if (p_dev_rec && (p_dev_rec->sec_flags & BTM_SEC_IN_USE) && (p_dev_rec->ble.key_type != BTM_LE_KEY_NONE)) { - BTM_TRACE_DEBUG("%s BLE security device #%d: bd_addr=%02X:%02X:%02X:%02X:%02X:%02X", +#else + if (p_dev_rec && (p_dev_rec->sec_flags & BTM_SEC_IN_USE)) { +#endif +#if (SMP_INCLUDED == TRUE) + /* Check if device exists in NVS */ + char bdstr[18] = {0}; + bdaddr_to_string((bt_bdaddr_t *)p_dev_rec->bd_addr, bdstr, sizeof(bdstr)); + + BTM_TRACE_WARNING("%s device #%d: "MACSTR", key_type=0x%02x (PENC:%d PID:%d PCSRK:%d LENC:%d LID:%d LCSRK:%d), in_nvs=%d", __func__, count, - p_dev_rec->bd_addr[0], - p_dev_rec->bd_addr[1], - p_dev_rec->bd_addr[2], - p_dev_rec->bd_addr[3], - p_dev_rec->bd_addr[4], - p_dev_rec->bd_addr[5]); + MAC2STR(p_dev_rec->bd_addr), + p_dev_rec->ble.key_type, + (p_dev_rec->ble.key_type & BTM_LE_KEY_PENC) ? 1 : 0, + (p_dev_rec->ble.key_type & BTM_LE_KEY_PID) ? 1 : 0, + (p_dev_rec->ble.key_type & BTM_LE_KEY_PCSRK) ? 1 : 0, + (p_dev_rec->ble.key_type & BTM_LE_KEY_LENC) ? 1 : 0, + (p_dev_rec->ble.key_type & BTM_LE_KEY_LID) ? 1 : 0, + (p_dev_rec->ble.key_type & BTM_LE_KEY_LCSRK) ? 1 : 0, + btc_config_has_section(bdstr)); +#else + BTM_TRACE_WARNING("%s device #%d: "MACSTR, + __func__, + count, + MAC2STR(p_dev_rec->bd_addr)); +#endif count++; } } diff --git a/components/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c b/components/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c index bcf2cc0ea45..f9fa9ebec74 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c +++ b/components/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c @@ -269,6 +269,13 @@ tBTM_STATUS BTM_BleSetExtendedAdvParams(UINT8 instance, tBTM_BLE_GAP_EXT_ADV_PAR extend_adv_cb.inst[instance].legacy_pdu = false; } + if (params->type & (BTM_BLE_GAP_SET_EXT_ADV_PROP_DIRECTED | + BTM_BLE_GAP_SET_EXT_ADV_PROP_HD_DIRECTED)) { + extend_adv_cb.inst[instance].directed = true; + } else { + extend_adv_cb.inst[instance].directed = false; + } + #if (CONTROLLER_RPA_LIST_ENABLE == FALSE) // if own_addr_type == BLE_ADDR_PUBLIC_ID or BLE_ADDR_RANDOM_ID, if((params->own_addr_type == BLE_ADDR_PUBLIC_ID || params->own_addr_type == BLE_ADDR_RANDOM_ID) && BTM_GetLocalResolvablePrivateAddr(rand_addr)) { diff --git a/components/bt/host/bluedroid/stack/btm/btm_ble_gap.c b/components/bt/host/bluedroid/stack/btm/btm_ble_gap.c index 2446251dd54..5d317fe4db9 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_ble_gap.c +++ b/components/bt/host/bluedroid/stack/btm/btm_ble_gap.c @@ -1117,15 +1117,17 @@ tBTM_STATUS BTM_BleStartAdvWithParams(UINT16 adv_int_min, UINT16 adv_int_max, UI tBTM_STATUS status = BTM_SUCCESS; /* update adv params */ - if (btsnd_hcic_ble_write_adv_params (adv_int_min, + UINT8 hci_status = btsnd_hcic_ble_write_adv_params (adv_int_min, adv_int_max, adv_type, own_bda_type, p_dir_bda->type, p_dir_bda->bda, chnl_map, - p_cb->afp) != HCI_SUCCESS) { - status = BTM_NO_RESOURCES; + p_cb->afp); + if (hci_status != HCI_SUCCESS) { + BTM_BLE_TRACE_HCI_CMD_FAIL(__func__, hci_status); + status = btm_ble_status_from_hci(hci_status); } osi_mutex_unlock(&btm_lock); @@ -1175,13 +1177,13 @@ tBTM_STATUS BTM_BleSetScanFilterParams(tGATT_IF client_if, UINT32 scan_interval, (scan_mode == BTM_BLE_SCAN_MODE_ACTI || scan_mode == BTM_BLE_SCAN_MODE_PASS) && (scan_duplicate_filter < BTM_BLE_SCAN_DUPLICATE_MAX) && (scan_window <= scan_interval)) { - if ((btsnd_hcic_ble_set_scan_params(scan_mode, (UINT16)scan_interval, - (UINT16)scan_window, - addr_type_own, - scan_filter_policy)) != HCI_SUCCESS) { - ret = BTM_ILLEGAL_VALUE; - BTM_TRACE_ERROR("Illegal params: scan_interval = %d scan_window = %d\n", - scan_interval, scan_window); + UINT8 hci_status = btsnd_hcic_ble_set_scan_params(scan_mode, (UINT16)scan_interval, + (UINT16)scan_window, + addr_type_own, + scan_filter_policy); + if (hci_status != HCI_SUCCESS) { + BTM_BLE_TRACE_HCI_CMD_FAIL(__func__, hci_status); + ret = btm_ble_status_from_hci(hci_status); } else { p_cb->scan_type = scan_mode; p_cb->scan_interval = scan_interval; @@ -1232,8 +1234,10 @@ tBTM_STATUS BTM_BleWriteScanRsp(tBTM_BLE_AD_MASK data_mask, tBTM_BLE_ADV_DATA *p BTM_TRACE_WARNING("%s, Partial data write into ADV", __func__); } - if (btsnd_hcic_ble_set_scan_rsp_data((UINT8)(p - rsp_data), rsp_data) != HCI_SUCCESS) { - ret = BTM_ILLEGAL_VALUE; + UINT8 hci_status = btsnd_hcic_ble_set_scan_rsp_data((UINT8)(p - rsp_data), rsp_data); + if (hci_status != HCI_SUCCESS) { + BTM_BLE_TRACE_HCI_CMD_FAIL(__func__, hci_status); + ret = btm_ble_status_from_hci(hci_status); btm_cb.ble_ctr_cb.inq_var.scan_rsp = FALSE; } else { ret = BTM_SUCCESS; @@ -1265,8 +1269,10 @@ tBTM_STATUS BTM_BleWriteScanRspRaw(UINT8 *p_raw_scan_rsp, UINT32 raw_scan_rsp_le tBTM_STATUS ret = BTM_SUCCESS; osi_mutex_lock(&btm_lock, OSI_MUTEX_MAX_TIMEOUT); - if (btsnd_hcic_ble_set_scan_rsp_data((UINT8)raw_scan_rsp_len, p_raw_scan_rsp) != HCI_SUCCESS) { - ret = BTM_NO_RESOURCES; + UINT8 hci_status = btsnd_hcic_ble_set_scan_rsp_data((UINT8)raw_scan_rsp_len, p_raw_scan_rsp); + if (hci_status != HCI_SUCCESS) { + BTM_BLE_TRACE_HCI_CMD_FAIL(__func__, hci_status); + ret = btm_ble_status_from_hci(hci_status); } osi_mutex_unlock(&btm_lock); @@ -1377,9 +1383,11 @@ tBTM_STATUS BTM_BleWriteAdvData(tBTM_BLE_AD_MASK data_mask, tBTM_BLE_ADV_DATA *p p_cb_data->data_mask &= ~mask; - if ((btsnd_hcic_ble_set_adv_data((UINT8)(p_cb_data->p_pad - p_cb_data->ad_data), - p_cb_data->ad_data)) != HCI_SUCCESS) { - ret = BTM_NO_RESOURCES; + UINT8 hci_status = btsnd_hcic_ble_set_adv_data((UINT8)(p_cb_data->p_pad - p_cb_data->ad_data), + p_cb_data->ad_data); + if (hci_status != HCI_SUCCESS) { + BTM_BLE_TRACE_HCI_CMD_FAIL(__func__, hci_status); + ret = btm_ble_status_from_hci(hci_status); } osi_mutex_unlock(&btm_lock); return ret; @@ -1400,8 +1408,10 @@ tBTM_STATUS BTM_BleWriteAdvDataRaw(UINT8 *p_raw_adv, UINT32 raw_adv_len) { tBTM_STATUS ret = BTM_SUCCESS; osi_mutex_lock(&btm_lock, OSI_MUTEX_MAX_TIMEOUT); - if ((btsnd_hcic_ble_set_adv_data((UINT8)raw_adv_len, p_raw_adv)) != HCI_SUCCESS) { - ret = BTM_NO_RESOURCES; + UINT8 hci_status = btsnd_hcic_ble_set_adv_data((UINT8)raw_adv_len, p_raw_adv); + if (hci_status != HCI_SUCCESS) { + BTM_BLE_TRACE_HCI_CMD_FAIL(__func__, hci_status); + ret = btm_ble_status_from_hci(hci_status); } osi_mutex_unlock(&btm_lock); @@ -2065,15 +2075,17 @@ tBTM_STATUS btm_ble_set_discoverability(UINT16 combined_mode) #endif // #if (BLE_42_ADV_EN == TRUE) /* update adv params */ - if (btsnd_hcic_ble_write_adv_params (adv_int_min, + UINT8 hci_status = btsnd_hcic_ble_write_adv_params (adv_int_min, adv_int_max, evt_type, own_addr_type, init_addr_type, p_addr_ptr, p_cb->adv_chnl_map, - p_cb->afp) != HCI_SUCCESS) { - status = BTM_NO_RESOURCES; + p_cb->afp); + if (hci_status != HCI_SUCCESS) { + BTM_BLE_TRACE_HCI_CMD_FAIL(__func__, hci_status); + status = btm_ble_status_from_hci(hci_status); } else { p_cb->evt_type = evt_type; p_cb->adv_addr_type = own_addr_type; @@ -2163,15 +2175,17 @@ tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode) btm_ble_stop_adv(); #endif // #if (BLE_42_ADV_EN == TRUE) - if (btsnd_hcic_ble_write_adv_params (adv_int_min, + UINT8 hci_status = btsnd_hcic_ble_write_adv_params (adv_int_min, adv_int_max, evt_type, own_addr_type, peer_addr_type, p_addr_ptr, p_cb->adv_chnl_map, - p_cb->afp) != HCI_SUCCESS) { - status = BTM_NO_RESOURCES; + p_cb->afp); + if (hci_status != HCI_SUCCESS) { + BTM_BLE_TRACE_HCI_CMD_FAIL(__func__, hci_status); + status = btm_ble_status_from_hci(hci_status); } else { p_cb->evt_type = evt_type; p_cb->adv_addr_type = own_addr_type; @@ -3241,8 +3255,10 @@ tBTM_STATUS btm_ble_start_scan(void) p_inq->scan_duplicate_filter = BTM_BLE_DUPLICATE_DISABLE; } /* start scan, disable duplicate filtering */ - if ((btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, p_inq->scan_duplicate_filter)) != HCI_SUCCESS) { - status = BTM_NO_RESOURCES; + UINT8 hci_status = btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, p_inq->scan_duplicate_filter); + if (hci_status != HCI_SUCCESS) { + BTM_BLE_TRACE_HCI_CMD_FAIL(__func__, hci_status); + status = btm_ble_status_from_hci(hci_status); } else { btm_cb.ble_ctr_cb.inq_var.state |= BTM_BLE_SCANNING; #if (BLE_TOPOLOGY_CHECK == TRUE) @@ -3312,8 +3328,10 @@ static tBTM_STATUS btm_ble_stop_discover(void) /* Clear the inquiry callback if set */ btm_cb.ble_ctr_cb.inq_var.state &= ~BTM_BLE_SCANNING; /* stop discovery now */ - if (btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE) != HCI_SUCCESS) { - status = BTM_NO_RESOURCES; + UINT8 hci_status = btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE); + if (hci_status != HCI_SUCCESS) { + BTM_BLE_TRACE_HCI_CMD_FAIL(__func__, hci_status); + status = btm_ble_status_from_hci(hci_status); } #if (BLE_TOPOLOGY_CHECK == TRUE) /* reset status */ @@ -3428,8 +3446,10 @@ tBTM_STATUS btm_ble_start_adv(void) #if (BLE_TOPOLOGY_CHECK == TRUE) btm_ble_adv_states_operation(btm_ble_set_topology_mask, p_cb->evt_type); #endif // (BLE_TOPOLOGY_CHECK == TRUE) - if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_ENABLE) != HCI_SUCCESS) { - rt = BTM_NO_RESOURCES; + UINT8 hci_status = btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_ENABLE); + if (hci_status != HCI_SUCCESS) { + BTM_BLE_TRACE_HCI_CMD_FAIL(__func__, hci_status); + rt = btm_ble_status_from_hci(hci_status); p_cb->state = temp_state; p_cb->adv_mode = adv_mode; #if (BLE_TOPOLOGY_CHECK == TRUE) @@ -3472,7 +3492,8 @@ tBTM_STATUS btm_ble_stop_adv(void) /* clear all adv states */ btm_ble_clear_topology_mask (BTM_BLE_STATE_ALL_ADV_MASK); #endif // (BLE_TOPOLOGY_CHECK == TRUE) - if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE) != HCI_SUCCESS) { + UINT8 hci_status = btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE); + if (hci_status != HCI_SUCCESS) { // reset state p_cb->fast_adv_on = temp_fast_adv_on; p_cb->adv_mode = temp_adv_mode; @@ -3481,7 +3502,8 @@ tBTM_STATUS btm_ble_stop_adv(void) #if (BLE_TOPOLOGY_CHECK == TRUE) btm_ble_set_topology_mask (temp_mask); #endif // (BLE_TOPOLOGY_CHECK == TRUE) - rt = BTM_NO_RESOURCES; + BTM_BLE_TRACE_HCI_CMD_FAIL(__func__, hci_status); + rt = btm_ble_status_from_hci(hci_status); } if(rt != HCI_SUCCESS) { p_cb->adv_mode = temp_adv_mode; diff --git a/components/bt/host/bluedroid/stack/btm/btm_devctl.c b/components/bt/host/bluedroid/stack/btm/btm_devctl.c index 9b6052f9adb..854f4778d1d 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_devctl.c +++ b/components/bt/host/bluedroid/stack/btm/btm_devctl.c @@ -1327,12 +1327,8 @@ void btm_ble_set_channels_complete (UINT8 *p) case HCI_SUCCESS: cb_params.set_channels.status = BTM_SUCCESS; break; - case HCI_ERR_UNSUPPORTED_VALUE: - case HCI_ERR_ILLEGAL_PARAMETER_FMT: - cb_params.set_channels.status = BTM_ILLEGAL_VALUE; - break; default: - cb_params.set_channels.status = BTM_ERR_PROCESSING; + cb_params.set_channels.status = BTM_HCI_ERROR | cb_params.set_channels.hci_status; break; } BTM_LegacyBleCallbackTrigger(BTM_BLE_LEGACY_GAP_SET_CHANNELS_COMPLETE_EVT, &cb_params); diff --git a/components/bt/host/bluedroid/stack/btm/include/btm_ble_int.h b/components/bt/host/bluedroid/stack/btm/include/btm_ble_int.h index 398c2fec990..6057f7951f5 100644 --- a/components/bt/host/bluedroid/stack/btm/include/btm_ble_int.h +++ b/components/bt/host/bluedroid/stack/btm/include/btm_ble_int.h @@ -628,6 +628,14 @@ void btm_ble_cs_subevt_result_evt(tBTM_BLE_CS_SUBEVT_RESULT_CMPL_EVT *subevt_res void btm_ble_cs_subevt_continue_result_evt(tBTM_BLE_CS_SUBEVT_RESULT_CONTINUE_EVT *subevt_continue_result); #endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE) +static inline tBTM_STATUS btm_ble_status_from_hci(UINT8 hci_status) +{ + return (hci_status == HCI_SUCCESS) ? BTM_SUCCESS : (tBTM_STATUS)(BTM_HCI_ERROR | hci_status); +} + +#define BTM_BLE_TRACE_HCI_CMD_FAIL(func, hci_status) \ + BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = 0x%x", (func), (hci_status)) + /* #ifdef __cplusplus diff --git a/components/bt/host/bluedroid/stack/btu/btu_hcif.c b/components/bt/host/bluedroid/stack/btu/btu_hcif.c index 2f65fb0d475..b56bf58969e 100644 --- a/components/bt/host/bluedroid/stack/btu/btu_hcif.c +++ b/components/bt/host/bluedroid/stack/btu/btu_hcif.c @@ -983,6 +983,20 @@ static void btu_hcif_disconnection_comp_evt (UINT8 *p) handle = HCID_GET_HANDLE (handle); +#if BLE_INCLUDED == TRUE + /* Capture the disconnecting device's address before btm_acl_disconnected() + * clears the matched connection handle. The record itself is re-looked-up + * afterwards (by address) because callbacks fired during disconnection may + * have already freed it. */ + BD_ADDR disc_bda; + BOOLEAN have_disc_bda = FALSE; + tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev_by_handle(handle); + if (p_dev_rec) { + memcpy(disc_bda, p_dev_rec->bd_addr, BD_ADDR_LEN); + have_disc_bda = TRUE; + } +#endif + dev_find = btm_acl_disconnected(handle, reason); #if (BLE_FEAT_ISO_CIG_EN == TRUE) @@ -995,6 +1009,48 @@ static void btu_hcif_disconnection_comp_evt (UINT8 *p) HCI_TRACE_WARNING("hcif disc complete: hdl 0x%x, rsn 0x%x dev_find %d", handle, reason, dev_find); UNUSED(dev_find); + +#if BLE_INCLUDED == TRUE + /* Delete unpaired device records to free memory (~356B per device). + * + * Re-find the record by address: callbacks invoked during + * btm_acl_disconnected() may already have freed it, so the pointer captured + * before the call cannot be trusted. + * + * Only delete when the device is fully idle and unpaired: + * 1. No active BR/EDR connection (hci_handle invalid) + * 2. No active LE connection (ble_hci_handle invalid) - protects the still + * connected transport of a dual-mode device when the other one drops + * 3. No BLE security keys (unpaired) - when SMP is enabled + * + * BT_TRANSPORT_LE is used so that any retained BR/EDR link key keeps a + * BR/EDR-bonded record alive; an LE-unpaired record that has no BR/EDR key + * collapses to BTM_SEC_IN_USE only and is removed from the list. + * + * Skip deletion on HCI_ERR_CONN_FAILED_ESTABLISHMENT when connect + * retry is enabled. + */ + if (have_disc_bda +#if (GATTC_CONNECT_RETRY_EN == TRUE) + && reason != HCI_ERR_CONN_FAILED_ESTABLISHMENT +#endif + ) { + p_dev_rec = btm_find_dev(disc_bda); + if (p_dev_rec + && p_dev_rec->hci_handle == BTM_SEC_INVALID_HANDLE /* No active BR/EDR connection */ + && p_dev_rec->ble_hci_handle == BTM_SEC_INVALID_HANDLE /* No active LE connection */ +#if SMP_INCLUDED == TRUE + && !p_dev_rec->ble.key_type /* No BLE security keys */ +#endif + ) { + BTM_TRACE_WARNING( + "Deleting unpaired device %02X:%02X:%02X:%02X:%02X:%02X", + p_dev_rec->bd_addr[0], p_dev_rec->bd_addr[1], p_dev_rec->bd_addr[2], + p_dev_rec->bd_addr[3], p_dev_rec->bd_addr[4], p_dev_rec->bd_addr[5]); + btm_sec_free_dev(p_dev_rec, BT_TRANSPORT_LE); + } + } +#endif // BLE_INCLUDED == TRUE } /******************************************************************************* @@ -1909,6 +1965,11 @@ static void btu_hcif_command_status_evt(uint8_t status, BT_HDR *command, void *c { BT_HDR *event = osi_calloc(sizeof(BT_HDR) + sizeof(command_status_hack_t)); command_status_hack_t *hack = (command_status_hack_t *)&event->data[0]; +#if ((BLE_50_FEATURE_SUPPORT == TRUE) || (BLE_42_FEATURE_SUPPORT == TRUE)) + if (status != HCI_SUCCESS) { + btsnd_hci_ble_set_status(status); + } +#endif // #if ((BLE_50_FEATURE_SUPPORT == TRUE) || (BLE_42_FEATURE_SUPPORT == TRUE)) hack->callback = btu_hcif_command_status_evt_on_task; hack->status = status; diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_cl.c b/components/bt/host/bluedroid/stack/gatt/gatt_cl.c index 28a50c4ac35..1fc86945659 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_cl.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_cl.c @@ -891,7 +891,11 @@ void gatt_process_read_by_type_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 /* value_len is the length of current record's value; use it to avoid overread when multiple records present */ p_clcb->counter = value_len; p_clcb->s_handle = handle; - if ( p_clcb->counter == (p_clcb->p_tcb->payload_size - 4)) { + UINT16 max_rbtype_val_len = (p_clcb->p_tcb->payload_size - 4); + if (max_rbtype_val_len > GATT_MAX_READ_BY_TYPE_VALUE_LEN) { + max_rbtype_val_len = GATT_MAX_READ_BY_TYPE_VALUE_LEN; + } + if (p_clcb->counter == max_rbtype_val_len) { p_clcb->op_subtype = GATT_READ_BY_HANDLE; if (!p_clcb->p_attr_buf) { p_clcb->p_attr_buf = (UINT8 *)osi_malloc(GATT_MAX_ATTR_LEN); diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_db.c b/components/bt/host/bluedroid/stack/gatt/gatt_db.c index 73037155f27..299eb80927d 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_db.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_db.c @@ -370,7 +370,13 @@ tGATT_STATUS gatts_db_read_attr_value_by_type (tGATT_TCB *p_tcb, UINT16_TO_STREAM (p, p_attr->handle); - status = read_attr_value ((void *)p_attr, 0, &p, FALSE, (UINT16)(*p_len - 2), &len, sec_flag, key_size); + { + UINT16 max_val_len = (UINT16)(*p_len - 2); + if (max_val_len > GATT_MAX_READ_BY_TYPE_VALUE_LEN) { + max_val_len = GATT_MAX_READ_BY_TYPE_VALUE_LEN; + } + status = read_attr_value ((void *)p_attr, 0, &p, FALSE, max_val_len, &len, sec_flag, key_size); + } if (status == GATT_PENDING) { diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_sr.c b/components/bt/host/bluedroid/stack/gatt/gatt_sr.c index b30fd173f0e..41b6db2d184 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_sr.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_sr.c @@ -414,6 +414,27 @@ tGATT_STATUS gatt_sr_process_app_rsp (tGATT_TCB *p_tcb, tGATT_IF gatt_if, UINT32 trans_id, UINT8 op_code, tGATT_STATUS status, tGATTS_RSP *p_msg) { + if ((p_tcb->exec_write_rsp_trans_id == trans_id) && (op_code == GATT_REQ_EXEC_WRITE)) { + /* + * Execute Write is a special case without a handle, so both stack and application + * may try to send a response. + * - Stack: may have already sent an automatic Execute Write Response. + * - App: may call esp_gatts_send_response() with the same trans_id. + * + * To prevent sending two responses for the same Execute Write request, + * we check if this trans_id has already been auto-responded by stack. + * If so, ignore the application response without sending another ATT packet. + * Still update cback_cnt/dequeue sr_cmd so state stays consistent when multiple + * apps are registered; only clear exec_write_rsp_trans_id after all apps respond. + */ + gatt_sr_update_cback_cnt(p_tcb, gatt_if, FALSE, FALSE); + if (gatt_sr_is_cback_cnt_zero(p_tcb)) { + gatt_dequeue_sr_cmd(p_tcb); + p_tcb->exec_write_rsp_trans_id = 0; + } + return GATT_SUCCESS; + } + tGATT_STATUS ret_code = GATT_SUCCESS; UNUSED(trans_id); @@ -481,6 +502,7 @@ tGATT_STATUS gatt_sr_process_app_rsp (tGATT_TCB *p_tcb, tGATT_IF gatt_if, *******************************************************************************/ void gatt_process_exec_write_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, UINT8 *p_data) { + BOOLEAN response_sent = false; UINT8 *p = p_data, flag, i = 0; UINT32 trans_id = 0; tGATT_IF gatt_if; @@ -536,6 +558,7 @@ void gatt_process_exec_write_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, U is_prepare_write_valid = TRUE; } GATT_TRACE_DEBUG("Send execute_write_rsp\n"); + response_sent = TRUE; } else if ((prepare_record->error_code_app == GATT_SUCCESS) && (prepare_record->total_num > queue_num)){ //No error for stack_rsp's handles and there exist some app_rsp's handles, @@ -580,6 +603,10 @@ void gatt_process_exec_write_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, U trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, 0); gatt_sr_copy_prep_cnt_to_cback_cnt(p_tcb); } + /* Record trans_id if stack already sent response, to prevent app from sending duplicate */ + if (response_sent) { + p_tcb->exec_write_rsp_trans_id = trans_id; + } for (i = 0; i < GATT_MAX_APPS; i++) { if (p_tcb->prep_cnt[i]) { gatt_if = (tGATT_IF) (i + 1); @@ -657,6 +684,11 @@ void gatt_process_exec_write_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, U gatt_sr_copy_prep_cnt_to_cback_cnt(p_tcb); } + /* Record trans_id if stack already sent response, to prevent app from sending duplicate */ + if (response_sent) { + p_tcb->exec_write_rsp_trans_id = trans_id; + } + for (i = 0; i < GATT_MAX_APPS; i++) { if (p_tcb->prep_cnt[i]) { gatt_if = (tGATT_IF) (i + 1); diff --git a/components/bt/host/bluedroid/stack/gatt/include/gatt_int.h b/components/bt/host/bluedroid/stack/gatt/include/gatt_int.h index 76432c4f1b6..0f2a7b08831 100644 --- a/components/bt/host/bluedroid/stack/gatt/include/gatt_int.h +++ b/components/bt/host/bluedroid/stack/gatt/include/gatt_int.h @@ -76,6 +76,10 @@ typedef UINT8 tGATT_SEC_ACTION; #define GATT_HDR_SIZE 3 /* 1B opcode + 2B handle */ +/* ATT Read By Type Response: Length field is 1 octet (max 255). */ +#define GATT_MAX_READ_BY_TYPE_PAIR_LEN 255 +#define GATT_MAX_READ_BY_TYPE_VALUE_LEN (GATT_MAX_READ_BY_TYPE_PAIR_LEN - 2) + /** * Wait for ATT cmd response timeout value (40 seconds). * The max connection supervision timeout is 32 seconds, @@ -421,6 +425,7 @@ typedef struct { UINT8 tcb_idx; #if (GATTS_INCLUDED == TRUE) tGATT_PREPARE_WRITE_RECORD prepare_write_record; /* prepare write packets record */ + UINT32 exec_write_rsp_trans_id; /* trans_id of auto-responded execute write */ #endif // (GATTS_INCLUDED == TRUE) } tGATT_TCB; diff --git a/components/bt/host/bluedroid/stack/l2cap/l2c_ble.c b/components/bt/host/bluedroid/stack/l2cap/l2c_ble.c index d4acd714ae8..3dfd210cc24 100644 --- a/components/bt/host/bluedroid/stack/l2cap/l2c_ble.c +++ b/components/bt/host/bluedroid/stack/l2cap/l2c_ble.c @@ -147,40 +147,42 @@ BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bda, UINT16 min_int, UINT16 max_in /* See if we have a link control block for the remote device */ p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_LE); - /* If we don't have one, create one and accept the connection. */ if (!p_lcb || !p_acl_cb) { L2CAP_TRACE_WARNING ("L2CA_UpdateBleConnParams - unknown BD_ADDR "MACSTR"", MAC2STR(rem_bda)); - return (FALSE); - } - - if (p_lcb->transport != BT_TRANSPORT_LE) { + status = HCI_ERR_NO_CONNECTION; + need_cb = true; + } else if (p_lcb->transport != BT_TRANSPORT_LE) { L2CAP_TRACE_WARNING ("L2CA_UpdateBleConnParams - BD_ADDR "MACSTR" not LE", MAC2STR(rem_bda)); - return (FALSE); - } - - /* Check whether the request conn params is already set */ - if ((max_int == p_lcb->current_used_conn_interval) && (latency == p_lcb->current_used_conn_latency) && - (timeout == p_lcb->current_used_conn_timeout)) { - status = HCI_SUCCESS; + status = HCI_ERR_NO_CONNECTION; need_cb = true; - L2CAP_TRACE_WARNING("%s connection parameter already set", __func__); - } + } else { + /* Check whether the request conn params is already set */ + if ((max_int == p_lcb->current_used_conn_interval) && (latency == p_lcb->current_used_conn_latency) && + (timeout == p_lcb->current_used_conn_timeout)) { + status = HCI_SUCCESS; + need_cb = true; + L2CAP_TRACE_WARNING("%s connection parameter already set", __func__); + } - if (p_lcb->conn_update_mask & L2C_BLE_UPDATE_PARAM_FULL){ - status = HCI_ERR_ILLEGAL_COMMAND; - need_cb = true; - L2CAP_TRACE_ERROR("%s connection parameter update in progress, please try later", __func__); + if (p_lcb->conn_update_mask & L2C_BLE_UPDATE_PARAM_FULL){ + status = HCI_ERR_ILLEGAL_COMMAND; + need_cb = true; + L2CAP_TRACE_ERROR("%s connection parameter update in progress, please try later", __func__); + } } if (need_cb) { tBTM_BLE_LEGACY_GAP_CB_PARAMS cb_params = {0}; cb_params.conn_params_update.status = status; - memcpy(cb_params.conn_params_update.remote_bd_addr, p_lcb->remote_bd_addr, BD_ADDR_LEN); + memcpy(cb_params.conn_params_update.remote_bd_addr, + p_lcb ? p_lcb->remote_bd_addr : rem_bda, BD_ADDR_LEN); cb_params.conn_params_update.min_conn_int = min_int; cb_params.conn_params_update.max_conn_int = max_int; - cb_params.conn_params_update.conn_int = p_lcb->current_used_conn_interval; - cb_params.conn_params_update.slave_latency = p_lcb->current_used_conn_latency; - cb_params.conn_params_update.supervision_tout = p_lcb->current_used_conn_timeout; + if (p_lcb) { + cb_params.conn_params_update.conn_int = p_lcb->current_used_conn_interval; + cb_params.conn_params_update.slave_latency = p_lcb->current_used_conn_latency; + cb_params.conn_params_update.supervision_tout = p_lcb->current_used_conn_timeout; + } BTM_LegacyBleCallbackTrigger(BTM_BLE_LEGACY_GAP_CONNECTION_PARAMS_UPDATE_EVT, &cb_params); @@ -993,12 +995,14 @@ BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb) #if (CONTROLLER_RPA_LIST_ENABLE) if (p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) { - if (btm_cb.ble_ctr_cb.privacy_mode >= BTM_PRIVACY_1_2) { - own_addr_type |= BLE_ADDR_TYPE_ID_BIT; - } + if (!(peer_addr_type == BLE_ADDR_RANDOM && !BTM_BLE_IS_RESOLVE_BDA(peer_addr))) { + if (btm_cb.ble_ctr_cb.privacy_mode >= BTM_PRIVACY_1_2) { + own_addr_type |= BLE_ADDR_TYPE_ID_BIT; + } - //btm_ble_enable_resolving_list(BTM_BLE_RL_INIT); - btm_random_pseudo_to_identity_addr(peer_addr, &peer_addr_type); + //btm_ble_enable_resolving_list(BTM_BLE_RL_INIT); + btm_random_pseudo_to_identity_addr(peer_addr, &peer_addr_type); + } } else { btm_ble_disable_resolving_list(BTM_BLE_RL_INIT, TRUE); }