From 81af2068816cfcb49a52b82580edbb0e60db5a0e Mon Sep 17 00:00:00 2001 From: Zhang Hai Peng Date: Fri, 26 Jun 2026 20:15:31 +0800 Subject: [PATCH 01/19] fix(ble/bluedroid): skip identity conversion for static random direct connect Do not rewrite static or non-resolvable random peer addresses to identity type 0x03 when CONFIG_BT_BLE_RPA_SUPPORTED is enabled. (cherry picked from commit 2ef10ef488d7a11f665ecac3a77fedfe875784db) Co-authored-by: zhanghaipeng --- components/bt/host/bluedroid/stack/l2cap/l2c_ble.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/components/bt/host/bluedroid/stack/l2cap/l2c_ble.c b/components/bt/host/bluedroid/stack/l2cap/l2c_ble.c index d4acd714ae8..39ce43265d7 100644 --- a/components/bt/host/bluedroid/stack/l2cap/l2c_ble.c +++ b/components/bt/host/bluedroid/stack/l2cap/l2c_ble.c @@ -993,12 +993,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); } From 6cc2ca26603d217ce69d68b652e35e83dd01831a Mon Sep 17 00:00:00 2001 From: Zhang Hai Peng Date: Fri, 26 Jun 2026 20:15:49 +0800 Subject: [PATCH 02/19] fix(ble/bluedroid): reject adv data on legacy directed ext adv (cherry picked from commit c339cec380f1df577faaba0cb852fde495ac3828) Co-authored-by: zhanghaipeng --- components/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c | 7 +++++++ 1 file changed, 7 insertions(+) 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 8be15ba602d..7cad2ec9dd0 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 @@ -260,6 +260,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)) { From 910d2f4de595f79391684fb2ae89c410039989b1 Mon Sep 17 00:00:00 2001 From: Zhang Hai Peng Date: Fri, 26 Jun 2026 20:16:09 +0800 Subject: [PATCH 03/19] fix(ble/bluedroid): return ESP_ERR_INVALID_ARG for invalid conn params Return ESP_ERR_INVALID_ARG instead of ESP_FAIL when connection parameter validation fails (cherry picked from commit 6c53838e6661a286e32e3cb6665fa345e714080c) Co-authored-by: zhanghaipeng --- components/bt/host/bluedroid/api/esp_gap_ble_api.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 9ac5a99b3bc..a6fdf95bae9 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) From 4d7da7ff481113ae41a650666c4fe94feb383459 Mon Sep 17 00:00:00 2001 From: Zhang Hai Peng Date: Fri, 26 Jun 2026 20:16:09 +0800 Subject: [PATCH 04/19] fix(ble/bluedroid): add context to GATTC reg-notify cache warning Include client_if, handle, bd_addr, and server cache state in the warning logged when notification registration skips handle validation. (cherry picked from commit 1085a32be8c97193aec94a4b0dc8bd17ef32be1e) Co-authored-by: zhanghaipeng --- components/bt/host/bluedroid/bta/gatt/bta_gattc_api.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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) { From f789848cc5eb5dffde3d6e95122c649c7b8d1ef1 Mon Sep 17 00:00:00 2001 From: Zhang Hai Peng Date: Fri, 26 Jun 2026 20:16:10 +0800 Subject: [PATCH 05/19] fix(ble/bluedroid): report conn param update failure for unknown BD_ADDR Route unknown BD_ADDR and other immediate failures through the existing need_cb path so ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT is always delivered. (cherry picked from commit f9eaeb5e84c8e3f5c29d586c1321a8dfd945b84a) Co-authored-by: zhanghaipeng --- .../bt/host/bluedroid/stack/l2cap/l2c_ble.c | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/components/bt/host/bluedroid/stack/l2cap/l2c_ble.c b/components/bt/host/bluedroid/stack/l2cap/l2c_ble.c index 39ce43265d7..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); From 8be2d0c2ef23bac0bba6f29393ac7c16d7866453 Mon Sep 17 00:00:00 2001 From: Zhang Hai Peng Date: Fri, 26 Jun 2026 20:16:27 +0800 Subject: [PATCH 06/19] fix(ble/bluedroid): set REQ_WAITING before GATTC service-change rediscovery When service change cancels in-progress discovery, bta_gattc_disc_cmpl() re-triggers discovery without marking auto_update as REQ_WAITING. If a client command is queued in p_q_cmd, bta_gattc_start_discover() refuses to restart and the command is never dispatched. (cherry picked from commit 13926bb9bc7a36beb5f4b67709924c7fc9ae5aa1) Co-authored-by: zhanghaipeng --- components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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..1b17e58622a 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 */ From bf03277906581ee1b399b1c40192922c21a70bf9 Mon Sep 17 00:00:00 2001 From: Zhang Hai Peng Date: Fri, 26 Jun 2026 20:16:45 +0800 Subject: [PATCH 07/19] fix(ble/bluedroid): unblock sync HCI cmd on Command Status error Release the BLE sync semaphore and record HCI status when a synchronous command is rejected via Command Status, since no Command Complete event follows. (cherry picked from commit 29ae92f4ef846600804ac9a7757d137f6ea9a2db) Co-authored-by: zhanghaipeng --- components/bt/host/bluedroid/hci/hci_layer.c | 12 ++++++++++++ components/bt/host/bluedroid/stack/btu/btu_hcif.c | 5 +++++ 2 files changed, 17 insertions(+) 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/btu/btu_hcif.c b/components/bt/host/bluedroid/stack/btu/btu_hcif.c index d9e34dcd10d..093b184a354 100644 --- a/components/bt/host/bluedroid/stack/btu/btu_hcif.c +++ b/components/bt/host/bluedroid/stack/btu/btu_hcif.c @@ -1834,6 +1834,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; From b02f53af64ed43f346f70d0fa224872dd11b05b5 Mon Sep 17 00:00:00 2001 From: Zhang Hai Peng Date: Fri, 26 Jun 2026 20:23:33 +0800 Subject: [PATCH 08/19] fix(ble/bluedroid): preserve ATT error on prepare write completion Skip prepare-write echo validation when the GATT stack reports a non-success status. ATT Error Response carries no prepare-write echo body (rsp_len=0), so the check incorrectly overwrote errors such as GATT_INSUF_AUTHENTICATION (0x05) with GATT_INVALID_PDU (0x04). (cherry picked from commit d5b9350d0fa2b74ea8810874163e972663d45fb2) Co-authored-by: zhanghaipeng --- components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 1b17e58622a..2fcf2bdcb8e 100644 --- a/components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c +++ b/components/bt/host/bluedroid/bta/gatt/bta_gattc_act.c @@ -1486,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; From 9da5a3a312218251fd9e6e98a5fbed07312838c8 Mon Sep 17 00:00:00 2001 From: Zhang Hai Peng Date: Fri, 26 Jun 2026 20:23:54 +0800 Subject: [PATCH 09/19] fix(ble/bluedroid): Fixed potential double Execute Write Response (cherry picked from commit 0a93ccd3b30852ed563698ec32d0aa02ae1a0b06) Co-authored-by: zhanghaipeng --- .../bt/host/bluedroid/stack/gatt/gatt_sr.c | 32 +++++++++++++++++++ .../bluedroid/stack/gatt/include/gatt_int.h | 1 + 2 files changed, 33 insertions(+) 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..44af16eec70 100644 --- a/components/bt/host/bluedroid/stack/gatt/include/gatt_int.h +++ b/components/bt/host/bluedroid/stack/gatt/include/gatt_int.h @@ -421,6 +421,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; From ff703331efc1ebfb51f2f8131f278975722999b7 Mon Sep 17 00:00:00 2001 From: Zhang Hai Peng Date: Fri, 26 Jun 2026 20:24:11 +0800 Subject: [PATCH 10/19] fix(ble/bluedroid): cap Read By Type response length at ATT maximum Read By Type Response Length is one octet (max 255). When MTU was large enough to return a long characteristic value in one pair, the server wrote (UINT8)(value_len + 2) and overflowed (e.g. 513 -> 1), so the client rejected the PDU as GATT_INVALID_PDU (0x04). Cap server value to 253 bytes per pair, clamp the length byte, and continue long reads via Read Blob when the capped size is returned. (cherry picked from commit 97905afccc3741266402e70aef1fc7227b8382e1) Co-authored-by: zhanghaipeng --- components/bt/host/bluedroid/stack/gatt/gatt_cl.c | 6 +++++- components/bt/host/bluedroid/stack/gatt/gatt_db.c | 8 +++++++- .../bt/host/bluedroid/stack/gatt/include/gatt_int.h | 4 ++++ 3 files changed, 16 insertions(+), 2 deletions(-) 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/include/gatt_int.h b/components/bt/host/bluedroid/stack/gatt/include/gatt_int.h index 44af16eec70..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, From f81903c0509de9319fbe4b58d9372840658a3cd4 Mon Sep 17 00:00:00 2001 From: Zhang Hai Peng Date: Fri, 26 Jun 2026 20:24:29 +0800 Subject: [PATCH 11/19] feat(ble/bluedroid): Optimize Bluedroid memory usage - Delete unused device records (~356B each) (cherry picked from commit 7d1c0e9a32c0cd508e112a7793c6f443b28d76bf) Co-authored-by: zhanghaipeng --- .../bt/host/bluedroid/btc/core/btc_main.c | 5 +- .../bt/host/bluedroid/stack/btm/btm_ble.c | 37 +++++++++--- .../bt/host/bluedroid/stack/btu/btu_hcif.c | 56 +++++++++++++++++++ 3 files changed, 87 insertions(+), 11 deletions(-) diff --git a/components/bt/host/bluedroid/btc/core/btc_main.c b/components/bt/host/bluedroid/btc/core/btc_main.c index 4de7c8aabd7..4809b118dee 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/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/btu/btu_hcif.c b/components/bt/host/bluedroid/stack/btu/btu_hcif.c index 093b184a354..ccf01eec870 100644 --- a/components/bt/host/bluedroid/stack/btu/btu_hcif.c +++ b/components/bt/host/bluedroid/stack/btu/btu_hcif.c @@ -951,6 +951,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) @@ -963,6 +977,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 } /******************************************************************************* From 01d1dd63bf9815c75ae2070c10b83a5166a93b22 Mon Sep 17 00:00:00 2001 From: Zhang Hai Peng Date: Fri, 26 Jun 2026 20:24:50 +0800 Subject: [PATCH 12/19] fix(ble/bluedroid): preserve HCI status on BLE 4.2 GAP failures Return BTM_HCI_ERROR | hci_status from legacy BLE 4.2 GAP HCI command paths instead of mapping failures to BTM_ILLEGAL_VALUE or BTM_NO_RESOURCES. Add btm_ble_status_from_hci() helper and propagate real status through scan start/stop completion callbacks. (cherry picked from commit 47dd785a1825c24b05561f55c32ab4cb663458b6) Co-authored-by: zhanghaipeng --- .../bt/host/bluedroid/bta/dm/bta_dm_act.c | 6 +- .../bt/host/bluedroid/stack/btm/btm_acl.c | 2 +- .../bt/host/bluedroid/stack/btm/btm_ble_gap.c | 88 ++++++++++++------- .../bt/host/bluedroid/stack/btm/btm_devctl.c | 6 +- .../bluedroid/stack/btm/include/btm_ble_int.h | 8 ++ 5 files changed, 69 insertions(+), 41 deletions(-) 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 8b44f27a28d..34561649b5e 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/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_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 bc4a33db287..29690bbe949 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 @@ -614,6 +614,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 From 1dffcb5560ba8fa8bb196bc4f2563e919eecc2e4 Mon Sep 17 00:00:00 2001 From: zhanghaipeng Date: Wed, 8 Jul 2026 11:03:04 +0800 Subject: [PATCH 13/19] fix(ble/bluedroid): downgrade numeric comparison log to warning --- components/bt/host/bluedroid/stack/smp/smp_keys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/bt/host/bluedroid/stack/smp/smp_keys.c b/components/bt/host/bluedroid/stack/smp/smp_keys.c index 8924b2f90e8..b0fdf3371df 100644 --- a/components/bt/host/bluedroid/stack/smp/smp_keys.c +++ b/components/bt/host/bluedroid/stack/smp/smp_keys.c @@ -1793,7 +1793,7 @@ UINT32 smp_calculate_g2(UINT8 *u, UINT8 *v, UINT8 *x, UINT8 *y) smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"cmac mod 2**32 mod 10**6", 4); #endif - SMP_TRACE_ERROR("Value for numeric comparison = %d", vres); + SMP_TRACE_WARNING("Value for numeric comparison = %d", vres); return vres; } From f6f289689ac50c745f74fa779108262315fae047 Mon Sep 17 00:00:00 2001 From: zhanghaipeng Date: Wed, 8 Jul 2026 10:50:30 +0800 Subject: [PATCH 14/19] fix(ble/bluedroid): preserve ext adv state when set params fails Only update extend_adv_cb after HCI Set Extended Advertising Parameters succeeds, so a failed update does not corrupt cached legacy_pdu and related fields used by adv data validation. --- .../host/bluedroid/stack/btm/btm_ble_5_gap.c | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) 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 7cad2ec9dd0..0322f24cfc0 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 @@ -242,31 +242,6 @@ tBTM_STATUS BTM_BleSetExtendedAdvParams(UINT8 instance, tBTM_BLE_GAP_EXT_ADV_PAR goto end; } - if (params->type & BTM_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE) { - extend_adv_cb.inst[instance].connetable = true; - } else { - extend_adv_cb.inst[instance].connetable = false; - } - - if (params->type & BTM_BLE_GAP_SET_EXT_ADV_PROP_SCANNABLE) { - extend_adv_cb.inst[instance].scannable = true; - } else { - extend_adv_cb.inst[instance].scannable = false; - } - - if (params->type & BTM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY) { - extend_adv_cb.inst[instance].legacy_pdu = true; - } else { - 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)) { @@ -303,6 +278,31 @@ tBTM_STATUS BTM_BleSetExtendedAdvParams(UINT8 instance, tBTM_BLE_GAP_EXT_ADV_PAR } #endif // (BT_BLE_FEAT_ADV_CODING_SELECTION == TRUE) + if (params->type & BTM_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE) { + extend_adv_cb.inst[instance].connetable = true; + } else { + extend_adv_cb.inst[instance].connetable = false; + } + + if (params->type & BTM_BLE_GAP_SET_EXT_ADV_PROP_SCANNABLE) { + extend_adv_cb.inst[instance].scannable = true; + } else { + extend_adv_cb.inst[instance].scannable = false; + } + + if (params->type & BTM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY) { + extend_adv_cb.inst[instance].legacy_pdu = true; + } else { + 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; + } + extend_adv_cb.inst[instance].configured = true; /* Record the post-fallback on-air address type for per-set conn_addr fixup. */ extend_adv_cb.inst[instance].own_addr_type = params->own_addr_type; From 0e6508a8fc467b1349e2a9f533972a2fac46b8fe Mon Sep 17 00:00:00 2001 From: zhanghaipeng Date: Thu, 2 Jul 2026 16:02:45 +0800 Subject: [PATCH 15/19] fix(ble/bluedroid): reject invalid ATT error code 0x00 on client Map received error reason 0x00 to GATT_UNKNOWN_ERROR so the client does not report GATT_SUCCESS with zero-length data on malformed errors. --- components/bt/host/bluedroid/stack/gatt/gatt_cl.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_cl.c b/components/bt/host/bluedroid/stack/gatt/gatt_cl.c index 1fc86945659..283851bbc47 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_cl.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_cl.c @@ -571,6 +571,11 @@ void gatt_process_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code, STREAM_TO_UINT16(handle, p); STREAM_TO_UINT8(reason, p); + /* 0x00 is not a valid ATT error code; treat as unknown error. */ + if (reason == GATT_SUCCESS) { + reason = GATT_UNKNOWN_ERROR; + } + if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY) { gatt_proc_disc_error_rsp(p_tcb, p_clcb, opcode, handle, reason); } else { @@ -579,9 +584,6 @@ void gatt_process_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code, (opcode == GATT_REQ_PREPARE_WRITE) && (p_attr) && (handle == p_attr->handle) ) { - if (reason == GATT_SUCCESS){ - reason = GATT_ERROR; - } p_clcb->status = reason; gatt_send_queue_write_cancel(p_tcb, p_clcb, GATT_PREP_WRITE_CANCEL); } else if ((p_clcb->operation == GATTC_OPTYPE_READ) && From 11bdcf82941c6c967c8c6e13d17cb91ea79b8e3f Mon Sep 17 00:00:00 2001 From: zhanghaipeng Date: Thu, 2 Jul 2026 16:02:41 +0800 Subject: [PATCH 16/19] fix(ble/bluedroid): use sr_cmd status for GATT server error rsp When sending an ATT error response after a failed server operation, use p_tcb->sr_cmd.status instead of the last app callback status so invalid error code 0x00 is not sent to the peer. --- components/bt/host/bluedroid/stack/gatt/gatt_sr.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_sr.c b/components/bt/host/bluedroid/stack/gatt/gatt_sr.c index 41b6db2d184..58ca35062f3 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_sr.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_sr.c @@ -476,10 +476,12 @@ tGATT_STATUS gatt_sr_process_app_rsp (tGATT_TCB *p_tcb, tGATT_IF gatt_if, ret_code = attp_send_sr_msg (p_tcb, p_tcb->sr_cmd.p_rsp_msg); p_tcb->sr_cmd.p_rsp_msg = NULL; } else { - if (p_tcb->sr_cmd.status == GATT_SUCCESS){ - status = GATT_UNKNOWN_ERROR; + tGATT_STATUS err_status = p_tcb->sr_cmd.status; + + if (err_status == GATT_SUCCESS) { + err_status = GATT_UNKNOWN_ERROR; } - ret_code = gatt_send_error_rsp (p_tcb, status, op_code, p_tcb->sr_cmd.handle, FALSE); + ret_code = gatt_send_error_rsp (p_tcb, err_status, op_code, p_tcb->sr_cmd.handle, FALSE); } gatt_dequeue_sr_cmd(p_tcb); From e76bd7359ca2019194630f43d255801061b244ad Mon Sep 17 00:00:00 2001 From: zhanghaipeng Date: Thu, 2 Jul 2026 16:02:04 +0800 Subject: [PATCH 17/19] fix(ble/bluedroid): match read-multiple-var responses by handle --- .../bt/host/bluedroid/stack/gatt/gatt_sr.c | 38 +++++-------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_sr.c b/components/bt/host/bluedroid/stack/gatt/gatt_sr.c index 58ca35062f3..05a076b7c64 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_sr.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_sr.c @@ -333,24 +333,11 @@ static BOOLEAN process_read_multi_var_rsp (tGATT_SR_CMD *p_cmd, tGATT_STATUS sta *p++ = GATT_RSP_READ_MULTI_VAR; p_buf->len = 1; - /* Now walk through the buffers putting the data into the response in order */ - list_t *list = NULL; - const list_node_t *node = NULL; - if (! fixed_queue_is_empty(p_cmd->multi_rsp_q)) { - list = fixed_queue_get_list(p_cmd->multi_rsp_q); - } + /* Match responses by handle; replies may arrive out of order. */ for (ii = 0; ii < p_cmd->multi_req.num_handles; ii++) { - tGATTS_RSP *p_rsp = NULL; - if (list != NULL) { - if (ii == 0) { - node = list_begin(list); - } else { - node = list_next(node); - } - if (node != list_end(list)) { - p_rsp = (tGATTS_RSP *)list_node(node); - } - } + tGATTS_RSP *p_rsp = gatt_find_multi_rsp_by_handle( + p_cmd, p_cmd->multi_req.handles[ii], + gatt_get_multi_handle_occurrence(p_cmd, ii)); if (p_rsp != NULL) { @@ -362,16 +349,11 @@ static BOOLEAN process_read_multi_var_rsp (tGATT_SR_CMD *p_cmd, tGATT_STATUS sta } len = MIN(p_rsp->attr_value.len, (mtu - total_len)); // attribute value length - if (p_rsp->attr_value.handle == p_cmd->multi_req.handles[ii]) { - GATT_TRACE_DEBUG("%s handle %x len %u", __func__, p_rsp->attr_value.handle, p_rsp->attr_value.len); - UINT16_TO_STREAM(p, p_rsp->attr_value.len); - memcpy (p, p_rsp->attr_value.value, len); - p += len; - p_buf->len += (2+len); - } else { - p_cmd->status = GATT_NOT_FOUND; - break; - } + GATT_TRACE_DEBUG("%s handle %x len %u", __func__, p_rsp->attr_value.handle, p_rsp->attr_value.len); + UINT16_TO_STREAM(p, p_rsp->attr_value.len); + memcpy (p, p_rsp->attr_value.value, len); + p += len; + p_buf->len += (2+len); } else { p_cmd->status = GATT_NOT_FOUND; break; @@ -380,7 +362,7 @@ static BOOLEAN process_read_multi_var_rsp (tGATT_SR_CMD *p_cmd, tGATT_STATUS sta } /* loop through all handles*/ /* Sanity check on the buffer length */ - if (p_buf->len == 0) { + if (p_buf->len <= 1) { GATT_TRACE_ERROR("%s - nothing found!!", __func__); p_cmd->status = GATT_NOT_FOUND; osi_free (p_buf); From 7f6057647787ef6608a5b19f49d30aa834059a52 Mon Sep 17 00:00:00 2001 From: zhanghaipeng Date: Thu, 2 Jul 2026 16:01:17 +0800 Subject: [PATCH 18/19] fix(ble/bluedroid): match read-multiple responses by handle Read Multiple may mix stack auto-responses with app async responses, so multi_rsp_q order can differ from the request handle order. Look up each response by handle (with occurrence for duplicates) instead of walking the queue by index, and treat opcode-only buffers as empty. --- .../bt/host/bluedroid/stack/gatt/gatt_sr.c | 97 +++++++++++++------ 1 file changed, 70 insertions(+), 27 deletions(-) diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_sr.c b/components/bt/host/bluedroid/stack/gatt/gatt_sr.c index 05a076b7c64..6f56b8bc450 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_sr.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_sr.c @@ -148,6 +148,66 @@ void gatt_dequeue_sr_cmd (tGATT_TCB *p_tcb) memset( &p_tcb->sr_cmd, 0, sizeof(tGATT_SR_CMD)); } +/******************************************************************************* +** +** Function gatt_find_multi_rsp_by_handle +** +** Description Find a read-multiple response entry by attribute handle. +** occurrence selects the Nth matching entry (for duplicate +** handles in the same request). +** +** Returns Pointer to response, or NULL if not found +** +*******************************************************************************/ +static tGATTS_RSP *gatt_find_multi_rsp_by_handle(tGATT_SR_CMD *p_cmd, UINT16 handle, + UINT16 occurrence) +{ + list_t *list; + const list_node_t *node; + UINT16 match_count = 0; + + if (p_cmd->multi_rsp_q == NULL || fixed_queue_is_empty(p_cmd->multi_rsp_q)) { + return NULL; + } + + list = fixed_queue_get_list(p_cmd->multi_rsp_q); + for (node = list_begin(list); node != list_end(list); node = list_next(node)) { + tGATTS_RSP *p_rsp = (tGATTS_RSP *)list_node(node); + + if (p_rsp->attr_value.handle == handle) { + if (match_count == occurrence) { + return p_rsp; + } + match_count++; + } + } + + return NULL; +} + +/******************************************************************************* +** +** Function gatt_get_multi_handle_occurrence +** +** Description Return occurrence index of handle at multi_req index. +** +** Returns occurrence count +** +*******************************************************************************/ +static UINT16 gatt_get_multi_handle_occurrence(tGATT_SR_CMD *p_cmd, UINT16 index) +{ + UINT16 ii; + UINT16 occurrence = 0; + + for (ii = 0; ii < index; ii++) { + if (p_cmd->multi_req.handles[ii] == p_cmd->multi_req.handles[index]) { + occurrence++; + } + } + + return occurrence; +} + /******************************************************************************* ** ** Function process_read_multi_rsp @@ -206,24 +266,12 @@ static BOOLEAN process_read_multi_rsp (tGATT_SR_CMD *p_cmd, tGATT_STATUS status, *p++ = GATT_RSP_READ_MULTI; p_buf->len = 1; - /* Now walk through the buffers putting the data into the response in order */ - list_t *list = NULL; - const list_node_t *node = NULL; - if (! fixed_queue_is_empty(p_cmd->multi_rsp_q)) { - list = fixed_queue_get_list(p_cmd->multi_rsp_q); - } + /* Walk request handles in order; match responses by handle because + * stack (sync) and app (async) replies may arrive out of order. */ for (ii = 0; ii < p_cmd->multi_req.num_handles; ii++) { - tGATTS_RSP *p_rsp = NULL; - if (list != NULL) { - if (ii == 0) { - node = list_begin(list); - } else { - node = list_next(node); - } - if (node != list_end(list)) { - p_rsp = (tGATTS_RSP *)list_node(node); - } - } + tGATTS_RSP *p_rsp = gatt_find_multi_rsp_by_handle( + p_cmd, p_cmd->multi_req.handles[ii], + gatt_get_multi_handle_occurrence(p_cmd, ii)); if (p_rsp != NULL) { @@ -238,16 +286,11 @@ static BOOLEAN process_read_multi_rsp (tGATT_SR_CMD *p_cmd, tGATT_STATUS status, len = p_rsp->attr_value.len; } - if (p_rsp->attr_value.handle == p_cmd->multi_req.handles[ii]) { - memcpy (p, p_rsp->attr_value.value, len); - if (!is_overflow) { - p += len; - } - p_buf->len += len; - } else { - p_cmd->status = GATT_NOT_FOUND; - break; + memcpy (p, p_rsp->attr_value.value, len); + if (!is_overflow) { + p += len; } + p_buf->len += len; if (is_overflow) { break; @@ -262,7 +305,7 @@ static BOOLEAN process_read_multi_rsp (tGATT_SR_CMD *p_cmd, tGATT_STATUS status, /* Sanity check on the buffer length */ - if (p_buf->len == 0) { + if (p_buf->len <= 1) { GATT_TRACE_ERROR("process_read_multi_rsp - nothing found!!"); p_cmd->status = GATT_NOT_FOUND; osi_free (p_buf); From c9f2abadb8bca10facf82a7ec167db850108ffe9 Mon Sep 17 00:00:00 2001 From: Zhang Hai Peng Date: Tue, 14 Jul 2026 10:37:19 +0800 Subject: [PATCH 19/19] docs(ble/bluedroid): fix markdown formatting in example docs (cherry picked from commit dba450de6b0000ad4bf7a4168b7eb06dacd52f0b) Co-authored-by: zhanghaipeng --- .../ble_compatibility_test_case.md | 4 ++-- .../bluetooth/bluedroid/ble/gatt_client/README.md | 2 +- .../tutorial/Gatt_Client_Example_Walkthrough.md | 12 ++++++------ .../bluedroid/ble/gatt_security_client/README.md | 2 +- .../bluedroid/ble/gatt_security_server/README.md | 2 +- .../bluetooth/bluedroid/ble/gatt_server/README.md | 2 +- .../tutorial/Gatt_Server_Example_Walkthrough.md | 4 ++-- .../ble/gatt_server_service_table/README.md | 2 +- .../Gatt_Server_Service_Table_Example_Walkthrough.md | 6 +++--- ...tt_Client_Multi_Connection_Example_Walkthrough.md | 10 +++++----- .../bluedroid/ble_50/ble50_security_client/README.md | 2 +- .../ble50_security_client_Example_Walkthrough.md | 6 +++--- .../bluedroid/ble_50/ble50_security_server/README.md | 2 +- .../bluetooth/bluedroid/ble_50/multi-adv/README.md | 6 +++--- .../tutorial/Mulit_Adv_Example_Walkthrough.md | 8 ++++---- .../bluedroid/ble_50/periodic_adv/README.md | 6 +++--- .../tutorial/Periodic_adv_Example_Walkthrough.md | 10 +++++----- .../bluedroid/ble_50/periodic_sync/README.md | 2 +- .../tutorial/Periodic_Sync_Example_Walkthrough.md | 10 +++++----- .../bluedroid/classic_bt/bt_discovery/README.md | 4 ++-- .../bluedroid/classic_bt/bt_spp_initiator/README.md | 12 ++++++------ .../classic_bt/bt_spp_vfs_initiator/README.md | 2 +- 22 files changed, 58 insertions(+), 58 deletions(-) diff --git a/examples/bluetooth/bluedroid/ble/ble_compatibility_test/ble_compatibility_test_case.md b/examples/bluetooth/bluedroid/ble/ble_compatibility_test/ble_compatibility_test_case.md index 84922d014bd..150a6e7d8d0 100644 --- a/examples/bluetooth/bluedroid/ble/ble_compatibility_test/ble_compatibility_test_case.md +++ b/examples/bluetooth/bluedroid/ble/ble_compatibility_test/ble_compatibility_test_case.md @@ -6,7 +6,7 @@ This document provides a test case for BLE smartphone compatibility and includes ### What You Need -* ESP device which needs to flash [this test program] (https://github.com/espressif/esp-idf/blob/master/examples/bluetooth/bluedroid/ble/ble_compatibility_test/main/ble_compatibility_test.c) +* ESP device which needs to flash [this test program](https://github.com/espressif/esp-idf/blob/master/examples/bluetooth/bluedroid/ble/ble_compatibility_test/main/ble_compatibility_test.c) * Smartphone with LightBlue® Explorer app ### Initialization @@ -24,7 +24,7 @@ Prior to conducting tests, please initialize the smartphone and the ESP device a * For tests marked with (*) further in the document, please bear in mind the following: * Your phone performance may affect the results of these tests. If such a test fails, it does not mean the phone fails to meet the test requirements, but that you need to arrange targeted tests. * Taking "Test for Connection Success Rate" as an example: if the test cannot be passed for 10 consecutive times, you need to record how many times the test was passed and then arrange targeted tests. -* For extended testing, please use the [examples] (https://github.com/espressif/esp-idf/tree/master/examples/bluetooth) provided by Espressif. +* For extended testing, please use the [examples](https://github.com/espressif/esp-idf/tree/master/examples/bluetooth) provided by Espressif. ## Test for ADV Performance (*) diff --git a/examples/bluetooth/bluedroid/ble/gatt_client/README.md b/examples/bluetooth/bluedroid/ble/gatt_client/README.md index d7348f8ed1c..b38b52d9050 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_client/README.md +++ b/examples/bluetooth/bluedroid/ble/gatt_client/README.md @@ -76,7 +76,7 @@ To test this example, you first run the [gatt_server_demo](../gatt_server), whic This example will enable gatt server's notification function once the connection is established and then the devices start exchanging data. -Please, check this [tutorial](tutorial/Gatt_Client_Example_Walkthrough.md) for more information about this example. +Please check this [tutorial](tutorial/Gatt_Client_Example_Walkthrough.md) for more information about this example. ### Hardware Required diff --git a/examples/bluetooth/bluedroid/ble/gatt_client/tutorial/Gatt_Client_Example_Walkthrough.md b/examples/bluetooth/bluedroid/ble/gatt_client/tutorial/Gatt_Client_Example_Walkthrough.md index 9fdd2a6ac87..ff087f67e8b 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_client/tutorial/Gatt_Client_Example_Walkthrough.md +++ b/examples/bluetooth/bluedroid/ble/gatt_client/tutorial/Gatt_Client_Example_Walkthrough.md @@ -4,7 +4,7 @@ In this tutorial, the GATT client example code for the ESP32 is reviewed. The code implements a Bluetooth Low Energy (BLE) Generic Attribute (GATT) client, which scans for nearby peripheral servers and connects to a predefined service. The client then searches for available characteristics and subscribes to a known characteristic in order to receive notifications or indications. The example can register an Application Profile and initializes a sequence of events, which can be used to configure Generic Access Profile (GAP) parameters and to handle events such as scanning, connecting to peripherals and reading and writing characteristics. -# Includes +## Includes This example is located in the examples folder of the ESP-IDF under the [bluetooth/bluedroid/ble/gatt_client/main](../main). The [gattc_demo.c](../main/gattc_demo.c) file located in the main folder contains all the functionality that we are going to review. The header files contained in [gattc_demo.c](../main/gattc_demo.c) are: @@ -25,7 +25,7 @@ This example is located in the examples folder of the ESP-IDF under the [bluetoo #include "esp_gatt_common_api.h" ``` -These `includes` are required for the FreeRTOS and underlying system components to run, including the logging functionality and a library to store data in non-volatile flash memory. We are interested in `“bt.h”`, `“esp_bt_main.h”`, `"esp_gap_ble_api.h"` and `“esp_gattc_api.h”`, which expose the BLE APIs required to implement this example. +These `includes` are required for the FreeRTOS and underlying system components to run, including the logging functionality and a library to store data in non-volatile flash memory. We are interested in `"bt.h"`, `"esp_bt_main.h"`, `"esp_gap_ble_api.h"` and `"esp_gattc_api.h"`, which expose the BLE APIs required to implement this example. * `bt.h`: configures the BT controller and VHCI from the host side. * `esp_bt_main.h`: initializes and enables the Bluedroid stack. @@ -34,7 +34,7 @@ These `includes` are required for the FreeRTOS and underlying system components ## Main Entry Point -The program’s entry point is the app_main() function: +The program's entry point is the app_main() function: ```c void app_main() @@ -413,7 +413,7 @@ ESP_LOGI(GATTC_TAG, "searched Device Name Len %d", adv_name_len); ESP_LOG_BUFFER_CHAR(GATTC_TAG, adv_name, adv_name_len); ``` -Finally if the remote device name is the same as we have defined above, the local device stops scanning and tries to open a connection to the remote device using the `esp_ble_gattc_enh_open()` function. This function takes as parameters the Application Profile GATT interface, the remote server address and a boolean value. The boolean value is used to indicate if the connection is done directly or if it’s done in the background (auto-connection), at the moment this boolean value must be set to true in order to establish the connection. Notice that the client opens a virtual connection to the server. The virtual connection returns a connection ID. The virtual connection is the connection between the Application Profile and the remote server. Since many Application Profiles can run on one ESP32, there could be many virtual connection opened to the same remote server. There is also the physical connection which is the actual BLE link between the client and the server. Therefore, if the physical connection is disconnected with the `esp_ble_gap_disconnect()` function, all other virtual connections are closed as well. In this example, each Application Profile creates a virtual connection to the same server with the `esp_ble_gattc_enh_open()` function, so when the close function is called, only that connection from the Application Profile is closed, while if the gap disconnect function is called, both connections will be closed. In addition, connect events are propagated to all profiles because it relates to the physical connection, while open events are propagated only to the profile that creates the virtual connection. +Finally if the remote device name is the same as we have defined above, the local device stops scanning and tries to open a connection to the remote device using the `esp_ble_gattc_enh_open()` function. This function takes as parameters the Application Profile GATT interface, the remote server address and a boolean value. The boolean value is used to indicate if the connection is done directly or if it's done in the background (auto-connection), at the moment this boolean value must be set to true in order to establish the connection. Notice that the client opens a virtual connection to the server. The virtual connection returns a connection ID. The virtual connection is the connection between the Application Profile and the remote server. Since many Application Profiles can run on one ESP32, there could be many virtual connection opened to the same remote server. There is also the physical connection which is the actual BLE link between the client and the server. Therefore, if the physical connection is disconnected with the `esp_ble_gap_disconnect()` function, all other virtual connections are closed as well. In this example, each Application Profile creates a virtual connection to the same server with the `esp_ble_gattc_enh_open()` function, so when the close function is called, only that connection from the Application Profile is closed, while if the gap disconnect function is called, both connections will be closed. In addition, connect events are propagated to all profiles because it relates to the physical connection, while open events are propagated only to the profile that creates the virtual connection. ## Configuring the MTU Size @@ -627,7 +627,7 @@ case ESP_GATTC_SEARCH_CMPL_EVT: break; ``` -`esp_ble_gattc_get_attr_count()` gets the attribute count with the given service or characteristic in the gattc cache. The parameters of `esp_ble_gattc_get_attr_count()` function are the GATT interface, the connection ID, the attribute type defined in `esp_gatt_db_attr_type_t`, the attribute start handle, the attribute end handle, the characteristic handle (this parameter is only valid when the type is set to `ESP_GATT_DB_DESCRIPTOR`.) and output the number of attribute has been found in the gattc cache with the given attribute type. Then we allocate a buffer to save the char information for `esp_ble_gattc_get_char_by_uuid()` function. The function finds the characteristic with the given characteristic UUID in the gattc cache. It just gets characteristic from local cache, instead of the remote devices. In a server, there might be more than one chars sharing the same UUID. However, in our gatt_server demo, every char has an unique UUID and that’s why we only use the first char in `char_elem_result`, which is the pointer to the characteristic of the service. Count initially stores the number of the characteristics that the client wants to find, and will be updated with the number of the characteristics that have been actually found in the gattc cache with `esp_ble_gattc_get_char_by_uuid`. +`esp_ble_gattc_get_attr_count()` gets the attribute count with the given service or characteristic in the gattc cache. The parameters of `esp_ble_gattc_get_attr_count()` function are the GATT interface, the connection ID, the attribute type defined in `esp_gatt_db_attr_type_t`, the attribute start handle, the attribute end handle, the characteristic handle (this parameter is only valid when the type is set to `ESP_GATT_DB_DESCRIPTOR`.) and output the number of attribute has been found in the gattc cache with the given attribute type. Then we allocate a buffer to save the char information for `esp_ble_gattc_get_char_by_uuid()` function. The function finds the characteristic with the given characteristic UUID in the gattc cache. It just gets characteristic from local cache, instead of the remote devices. In a server, there might be more than one chars sharing the same UUID. However, in our gatt_server demo, every char has an unique UUID and that's why we only use the first char in `char_elem_result`, which is the pointer to the characteristic of the service. Count initially stores the number of the characteristics that the client wants to find, and will be updated with the number of the characteristics that have been actually found in the gattc cache with `esp_ble_gattc_get_char_by_uuid`. ## Registering for Notifications @@ -723,7 +723,7 @@ Where `ESP_GATT_UUID_CHAR_CLIENT_CONFIG` is defined with the UUID to identify th ```c #define ESP_GATT_UUID_CHAR_CLIENT_CONFIG 0x2902 /* Client Characteristic Configuration */ ``` -The value to write is “1” to enable notifications. We also pass `ESP_GATT_WRITE_TYPE_RSP` to request that the server responds to the request of enabling notifications and `ESP_GATT_AUTH_REQ_NONE` to indicate that the Write request does not need authorization. +The value to write is "1" to enable notifications. We also pass `ESP_GATT_WRITE_TYPE_RSP` to request that the server responds to the request of enabling notifications and `ESP_GATT_AUTH_REQ_NONE` to indicate that the Write request does not need authorization. diff --git a/examples/bluetooth/bluedroid/ble/gatt_security_client/README.md b/examples/bluetooth/bluedroid/ble/gatt_security_client/README.md index f6ab4b81a24..9c866acb609 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_security_client/README.md +++ b/examples/bluetooth/bluedroid/ble/gatt_security_client/README.md @@ -73,7 +73,7 @@ There are some important points for this demo: 2. `esp_ble_set_encryption` should be used to start encryption with peer device. If the peer device initiates the encryption, `esp_ble_gap_security_rsp` should be used to send security response to the peer device when `ESP_GAP_BLE_SEC_REQ_EVT` is received. 3. The `gatt_security_client_demo` will receive a `ESP_GAP_BLE_AUTH_CMPL_EVT` once the encryption procedure has completed. -Please, check this [tutorial](tutorial/Gatt_Security_Client_Example_Walkthrough.md) for more information about this example. +Please check this [tutorial](tutorial/Gatt_Security_Client_Example_Walkthrough.md) for more information about this example. ### Hardware Required diff --git a/examples/bluetooth/bluedroid/ble/gatt_security_server/README.md b/examples/bluetooth/bluedroid/ble/gatt_security_server/README.md index 337689ebc75..84a057af871 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_security_server/README.md +++ b/examples/bluetooth/bluedroid/ble/gatt_security_server/README.md @@ -7,7 +7,7 @@ This example shows how to use the APIs to connect to and encrypt with peer devic To test this example, you can run [gatt_security_client_demo](../gatt_security_client), which starts scanning, connects to and starts encryption with `gatt_security_server_demo` automatically. -Please, check this [tutorial](tutorial/Gatt_Security_Server_Example_Walkthrough.md) for more information about this example. +Please check this [tutorial](tutorial/Gatt_Security_Server_Example_Walkthrough.md) for more information about this example. ## Flow Diagram diff --git a/examples/bluetooth/bluedroid/ble/gatt_server/README.md b/examples/bluetooth/bluedroid/ble/gatt_server/README.md index 07c4481b61d..1856f99d423 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_server/README.md +++ b/examples/bluetooth/bluedroid/ble/gatt_server/README.md @@ -11,7 +11,7 @@ This demo creates GATT a service and then starts advertising, waiting to be conn To test this demo, we can run the [gatt_client_demo](../gatt_client), which can scan for and connect to this demo automatically. They will start exchanging data once the GATT client has enabled the notification function of the GATT server. -Please, check this [tutorial](tutorial/Gatt_Server_Example_Walkthrough.md) for more information about this example. +Please check this [tutorial](tutorial/Gatt_Server_Example_Walkthrough.md) for more information about this example. ## Flow Diagram diff --git a/examples/bluetooth/bluedroid/ble/gatt_server/tutorial/Gatt_Server_Example_Walkthrough.md b/examples/bluetooth/bluedroid/ble/gatt_server/tutorial/Gatt_Server_Example_Walkthrough.md index 0f227722717..58a238d3e61 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_server/tutorial/Gatt_Server_Example_Walkthrough.md +++ b/examples/bluetooth/bluedroid/ble/gatt_server/tutorial/Gatt_Server_Example_Walkthrough.md @@ -6,7 +6,7 @@ In this document, we review the GATT SERVER example code which implements a Blue ## Includes -First, let’s take a look at the includes: +First, let's take a look at the includes: ```c #include @@ -947,7 +947,7 @@ case ESP_GATTS_EXEC_WRITE_EVT: example_exec_write_event_env(&a_prepare_write_env, param); break; ``` -Let’s take a look at the Executive Write function: +Let's take a look at the Executive Write function: ```c void example_exec_write_event_env(prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param){ diff --git a/examples/bluetooth/bluedroid/ble/gatt_server_service_table/README.md b/examples/bluetooth/bluedroid/ble/gatt_server_service_table/README.md index 6296ff6ad31..8961381b2d9 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_server_service_table/README.md +++ b/examples/bluetooth/bluedroid/ble/gatt_server_service_table/README.md @@ -5,7 +5,7 @@ This example shows how to create a GATT service with an attribute table defined in one place. Provided API releases the user from adding attributes one by one as implemented in BLUEDROID. A demo of the other method to create the attribute table is presented in [gatt_server_demo](../gatt_server). -Please, check this [tutorial](tutorial/Gatt_Server_Service_Table_Example_Walkthrough.md) for more information about this example. +Please check this [tutorial](tutorial/Gatt_Server_Service_Table_Example_Walkthrough.md) for more information about this example. ## Flow Diagram diff --git a/examples/bluetooth/bluedroid/ble/gatt_server_service_table/tutorial/Gatt_Server_Service_Table_Example_Walkthrough.md b/examples/bluetooth/bluedroid/ble/gatt_server_service_table/tutorial/Gatt_Server_Service_Table_Example_Walkthrough.md index ea255f2d5da..de34e99c607 100644 --- a/examples/bluetooth/bluedroid/ble/gatt_server_service_table/tutorial/Gatt_Server_Service_Table_Example_Walkthrough.md +++ b/examples/bluetooth/bluedroid/ble/gatt_server_service_table/tutorial/Gatt_Server_Service_Table_Example_Walkthrough.md @@ -2,7 +2,7 @@ ## Introduction -This document presents a walkthrough of the GATT Server Service Table example code for the ESP32. This example implements a Bluetooth Low Energy (BLE) Generic Attribute (GATT) Server using a table-like data structure to define the server services and characteristics such as the one shown in the figure below Therefore, it demonstrates a practical way to define the server functionality in one place instead of adding services and characteristics one by one. +This document presents a walkthrough of the GATT Server Service Table example code for the ESP32. This example implements a Bluetooth Low Energy (BLE) Generic Attribute (GATT) Server using a table-like data structure to define the server services and characteristics such as the one shown in the figure below. Therefore, it demonstrates a practical way to define the server functionality in one place instead of adding services and characteristics one by one. This example implements the *Heart Rate Profile* as defined by the [Traditional Profile Specifications](https://www.bluetooth.com/specifications/profiles-overview). @@ -10,7 +10,7 @@ This example implements the *Heart Rate Profile* as defined by the [Traditional ## Includes -Let’s start by taking a look at the included headers in the [gatts_table_creat_demo.c](../main/gatts_table_creat_demo.c) file: +Let's start by taking a look at the included headers in the [gatts_table_creat_demo.c](../main/gatts_table_creat_demo.c) file: ```c #include "freertos/FreeRTOS.h" @@ -26,7 +26,7 @@ Let’s start by taking a look at the included headers in the [gatts_table_creat #include "esp_gatts_api.h" #include "esp_bt_defs.h" #include "esp_bt_main.h" -#include “gatts_table_creat_demo.h" +#include "gatts_table_creat_demo.h" ``` These includes are required for the *FreeRTOS* and underlying system components to run, including logging functionality and a library to store data in non-volatile flash memory. We are interested in ``bt.h``, ``esp_bt_main.h``, ``esp_gap_ble_api.h`` and ``esp_gatts_api.h`` which expose the BLE APIs required to implement this example. diff --git a/examples/bluetooth/bluedroid/ble/gattc_multi_connect/tutorial/Gatt_Client_Multi_Connection_Example_Walkthrough.md b/examples/bluetooth/bluedroid/ble/gattc_multi_connect/tutorial/Gatt_Client_Multi_Connection_Example_Walkthrough.md index 88e14d2ed3d..3b5bf1f6276 100644 --- a/examples/bluetooth/bluedroid/ble/gattc_multi_connect/tutorial/Gatt_Client_Multi_Connection_Example_Walkthrough.md +++ b/examples/bluetooth/bluedroid/ble/gattc_multi_connect/tutorial/Gatt_Client_Multi_Connection_Example_Walkthrough.md @@ -1,9 +1,9 @@ # GATT Client Multi-connection Example Walkthrough ## Introduction -This document presents a description of the multi-connection BLE GATT client example for the ESP32. In this implementation, a single ESP32 working as a GATT client connects to three different GATT servers at the same time. This set up illustrates the use case of an ESP32 device acting in a way so that it receives data from different BLE sensors. The unique combination of ESP32’s BLE + Wi-Fi capabilities in addition to connection to multiple peripherals makes it a great candidate to serve as an IoT gateway. +This document presents a description of the multi-connection BLE GATT client example for the ESP32. In this implementation, a single ESP32 working as a GATT client connects to three different GATT servers at the same time. This set up illustrates the use case of an ESP32 device acting in a way so that it receives data from different BLE sensors. The unique combination of ESP32's BLE + Wi-Fi capabilities in addition to connection to multiple peripherals makes it a great candidate to serve as an IoT gateway. -This example’s workflow is similar to the [GATT Client Example Walkthrough](../../gatt_client/tutorial/Gatt_Client_Example_Walkthrough.md) and is shown in the figure below. However, in the multi-connection implementation, a GATT client searches for three specific server names and once that it has found them it opens a connection to all three of them one after the other. In code, each connection is handled separately with one Application Profile. +This example's workflow is similar to the [GATT Client Example Walkthrough](../../gatt_client/tutorial/Gatt_Client_Example_Walkthrough.md) and is shown in the figure below. However, in the multi-connection implementation, a GATT client searches for three specific server names and once that it has found them it opens a connection to all three of them one after the other. In code, each connection is handled separately with one Application Profile. Four ESP32 devices are needed in order to demonstrate this example, among which: @@ -13,7 +13,7 @@ Four ESP32 devices are needed in order to demonstrate this example, among which:
Multi-Connection GATT Client Flowchart
## Includes -The multi-connection example’s main source file is [gattc_multi_connect.c](../main/gattc_multi_connect.c). For details, see Section [Includes](../../gatt_client/tutorial/Gatt_Client_Example_Walkthrough.md#includes) in [GATT Client Example Walkthrough](../../gatt_client/tutorial/Gatt_Client_Example_Walkthrough.md). +The multi-connection example's main source file is [gattc_multi_connect.c](../main/gattc_multi_connect.c). For details, see Section [Includes](../../gatt_client/tutorial/Gatt_Client_Example_Walkthrough.md#includes) in [GATT Client Example Walkthrough](../../gatt_client/tutorial/Gatt_Client_Example_Walkthrough.md). ## Main Entry Point See Section [Main Entry Point](../../gatt_client/tutorial/Gatt_Client_Example_Walkthrough.md#main-entry-point) in [GATT Client Example Walkthrough](../../gatt_client/tutorial/Gatt_Client_Example_Walkthrough.md). @@ -69,7 +69,7 @@ See Section [Getting Scan Results](../../gatt_client/tutorial/Gatt_Client_Exampl * Then, the device name found is compared to the server names that the client wants to connect to. The server names are defined in the ``remote_device_name`` array: ```c - static const char remote_device_name[3][20] = {"ESP_GATTS_DEMO_1", "ESP_GATTS_DEMO_2", “ESP_GATTS_DEMO_3"}; + static const char remote_device_name[3][20] = {"ESP_GATTS_DEMO_1", "ESP_GATTS_DEMO_2", "ESP_GATTS_DEMO_3"}; ``` The name comparison takes places as follows: @@ -334,7 +334,7 @@ At this point the client has acquired all characteristics from the remote device ```c #define ESP_GATT_UUID_CHAR_CLIENT_CONFIG 0x2902 /* Client Characteristic Configuration */ ``` - The value to write is “1” to enable notifications. The parameter ``ESP_GATT_WRITE_TYPE_RSP`` is also passed to request that the server responds to the write request, as well as the ``ESP_GATT_AUTH_REQ_NONE`` parameter to indicate that the write request does not need authorization: + The value to write is "1" to enable notifications. The parameter ``ESP_GATT_WRITE_TYPE_RSP`` is also passed to request that the server responds to the write request, as well as the ``ESP_GATT_AUTH_REQ_NONE`` parameter to indicate that the write request does not need authorization: ```c case ESP_GATTC_REG_FOR_NOTIFY_EVT: { diff --git a/examples/bluetooth/bluedroid/ble_50/ble50_security_client/README.md b/examples/bluetooth/bluedroid/ble_50/ble50_security_client/README.md index c94cd0d3ff6..474127a6154 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble50_security_client/README.md +++ b/examples/bluetooth/bluedroid/ble_50/ble50_security_client/README.md @@ -22,7 +22,7 @@ There are some important points for this demo: `esp_ble_gap_security_rsp` should be used to send security response to the peer device when `ESP_GAP_BLE_SEC_REQ_EVT` is received. 3. The `gatt_security_client_demo` will receive a `ESP_GAP_BLE_AUTH_CMPL_EVT` once the encryption procedure has completed. -Please, check this [tutorial](tutorial/ble50_security_client_Example_Walkthrough.md) for more information about this example. +Please check this [tutorial](tutorial/ble50_security_client_Example_Walkthrough.md) for more information about this example. ### Hardware Required diff --git a/examples/bluetooth/bluedroid/ble_50/ble50_security_client/tutorial/ble50_security_client_Example_Walkthrough.md b/examples/bluetooth/bluedroid/ble_50/ble50_security_client/tutorial/ble50_security_client_Example_Walkthrough.md index afd4b1a32fb..63c4c24b537 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble50_security_client/tutorial/ble50_security_client_Example_Walkthrough.md +++ b/examples/bluetooth/bluedroid/ble_50/ble50_security_client/tutorial/ble50_security_client_Example_Walkthrough.md @@ -7,9 +7,9 @@ * The peripheral device is normally a GATT Server that exposes Services and Characteristics. The peripheral replies with a *Aux Connect Pairing Response* followed by authentication and exchange of keys. If the bonding process is also executed, the Long Term Keys are stored for subsequent connections. Finally an encrypted channel is established which can support protection against Man-In-The-Middle (MITM) attacks depending on the security configuration. * The code is implemented using an Application Profile that upon registration, allows to set the local privacy configuration as events are triggered during the life time of the program. -This document only includes a description of the security aspects of the BLE5.0 Security GATT Client implementation, for the more info about extended scan , periodic scan please refer to [Periodic_Sync_Example Walkthrough] (../../periodic_sync/tutorial/Periodic_Sync_Example_Walkthrough.md). +This document only includes a description of the security aspects of the BLE5.0 Security GATT Client implementation. For more information about extended scan and periodic scan, please refer to [Periodic Sync Example Walkthrough](../../periodic_sync/tutorial/Periodic_Sync_Example_Walkthrough.md). -##include +## Includes ```c #include @@ -27,7 +27,7 @@ This document only includes a description of the security aspects of the BLE5.0 #include "esp_log.h" #include "freertos/FreeRTOS.h" ``` -These `includes` are required for the FreeRTOS and underlying system components to run, including the logging functionality and a library to store data in non-volatile flash memory. We are interested in `“bt.h”`, `“esp_bt_main.h”`, `"esp_gap_ble_api.h"` and `“esp_gattc_api.h”`, which expose the BLE APIs required to implement this example. +These `includes` are required for the FreeRTOS and underlying system components to run, including the logging functionality and a library to store data in non-volatile flash memory. We are interested in `"bt.h"`, `"esp_bt_main.h"`, `"esp_gap_ble_api.h"` and `"esp_gattc_api.h"`, which expose the BLE APIs required to implement this example. * `bt.h`: configures the BT controller and VHCI from the host side. * `esp_bt_main.h`: initializes and enables the Bluedroid stack. diff --git a/examples/bluetooth/bluedroid/ble_50/ble50_security_server/README.md b/examples/bluetooth/bluedroid/ble_50/ble50_security_server/README.md index ae64baa5a6f..4132306a8fb 100644 --- a/examples/bluetooth/bluedroid/ble_50/ble50_security_server/README.md +++ b/examples/bluetooth/bluedroid/ble_50/ble50_security_server/README.md @@ -7,7 +7,7 @@ This example shows how to use the APIs to connect in secure manner with peer dev To test this example, you can run [ble50_security_client_demo](../ble50_security_client), which starts scanning, connects to and starts encryption with `ble50_sec_gattc_demo` automatically. -Please, check this [tutorial](tutorial/ble50_security_server_Example_Walkthrough.md) for more information about this example. +Please check this [tutorial](tutorial/ble50_security_server_Example_Walkthrough.md) for more information about this example. ## How to Use Example diff --git a/examples/bluetooth/bluedroid/ble_50/multi-adv/README.md b/examples/bluetooth/bluedroid/ble_50/multi-adv/README.md index 3f7a212d7d3..156eef237fb 100644 --- a/examples/bluetooth/bluedroid/ble_50/multi-adv/README.md +++ b/examples/bluetooth/bluedroid/ble_50/multi-adv/README.md @@ -1,11 +1,11 @@ | Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | | ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -#ESP-IDF Multi Adv Example +# ESP-IDF Multi Adv Example -This example support legacy as well as extended advertisement for all phy. +This example supports legacy as well as extended advertisement for all phy. -Please, check this [tutorial](tutorial/Mulit_Adv_Example_Walkthrough.md) for more information about this example. +Please check this [tutorial](tutorial/Mulit_Adv_Example_Walkthrough.md) for more information about this example. ## How to Use Example diff --git a/examples/bluetooth/bluedroid/ble_50/multi-adv/tutorial/Mulit_Adv_Example_Walkthrough.md b/examples/bluetooth/bluedroid/ble_50/multi-adv/tutorial/Mulit_Adv_Example_Walkthrough.md index 369ed3f8452..aec0a404970 100644 --- a/examples/bluetooth/bluedroid/ble_50/multi-adv/tutorial/Mulit_Adv_Example_Walkthrough.md +++ b/examples/bluetooth/bluedroid/ble_50/multi-adv/tutorial/Mulit_Adv_Example_Walkthrough.md @@ -1,12 +1,12 @@ # Multi Adv Example Walkthrough -## introduction +## Introduction In this document, we review the Multi Adv example code which implements a Bluetooth Low Energy (BLE5.0) Multi adv profile on the ESP32C3. This example is designed around two Application Profiles and a series of events that are handled in order to execute a sequence of configuration steps, such as defining extended advertising parameters with all phy 1M,2M and coded and Ext adv data. ## Includes -First, let’s take a look at the include +First, let's take a look at the include ```c #include @@ -162,7 +162,7 @@ shed to the application from the BLE stack. The register application event is the first one that is triggered during the lifetime of the program, this example uses the Profile A GATT event handle to configure the advertising parameters upon registration. This example has the option to use both standard Bluetooth Core Specification advertising parameters or a customized raw buffer. The option can be selected with the `CONFIG_SET_RAW_ADV_DATA` define. The raw advertising data can be used to implement iBeacons, Eddystone or other proprietary, and custom frame types such as the ones used for Indoor Location Services that are different from the standard specifications. -The function is used to configure different types of extended advertisement types and legacy adv with 1M,2M and coded phy in esp_ble_gap_ext_adv_set_params , esp_ble_gap_ext_adv_set_rand_addr and esp_ble_gap_config_ext_adv_data_raw. Respective structure of each one of them mentioned below with one example: +The function is used to configure different types of extended advertisement types and legacy adv with 1M,2M and coded phy in esp_ble_gap_ext_adv_set_params, esp_ble_gap_ext_adv_set_rand_addr and esp_ble_gap_config_ext_adv_data_raw. Respective structure of each one of them mentioned below with one example: ```c /** @@ -268,7 +268,7 @@ rt.status); } ``` -## Default config +## Default Config This example by default configured with 1M phy extend adv, Connectable advertising diff --git a/examples/bluetooth/bluedroid/ble_50/periodic_adv/README.md b/examples/bluetooth/bluedroid/ble_50/periodic_adv/README.md index cc9a06c40e0..5dc9afee4ac 100644 --- a/examples/bluetooth/bluedroid/ble_50/periodic_adv/README.md +++ b/examples/bluetooth/bluedroid/ble_50/periodic_adv/README.md @@ -1,15 +1,15 @@ | Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S3 | | ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -# ESP_IDF Periodic Adv Example +# ESP-IDF Periodic Adv Example -This example support for the periodic advertisement which allow the scanner to sync with the advertiser so that scanner and advertiser wake up same time. It support extended adv with 2M phy in connectable mode. +This example supports the periodic advertisement which allow the scanner to sync with the advertiser so that scanner and advertiser wake up same time. It support extended adv with 2M phy in connectable mode. To test this demo, we can run the [periodic_sync_demo](../periodic_sync), which can do periodic scan and try to sync with periodic adv. -Please, check this [tutorial](tutorial/Periodic_adv_Example_Walkthrough.md) for more information about this example. +Please check this [tutorial](tutorial/Periodic_adv_Example_Walkthrough.md) for more information about this example. ## How to Use Example diff --git a/examples/bluetooth/bluedroid/ble_50/periodic_adv/tutorial/Periodic_adv_Example_Walkthrough.md b/examples/bluetooth/bluedroid/ble_50/periodic_adv/tutorial/Periodic_adv_Example_Walkthrough.md index 3f99664ac66..cc0b857a0c0 100644 --- a/examples/bluetooth/bluedroid/ble_50/periodic_adv/tutorial/Periodic_adv_Example_Walkthrough.md +++ b/examples/bluetooth/bluedroid/ble_50/periodic_adv/tutorial/Periodic_adv_Example_Walkthrough.md @@ -1,11 +1,11 @@ # Periodic Adv Example Walkthrough -## introduction +## Introduction In this document, We review the Periodic Adv example code which implements a Bluetooth Low Energy (BLE5.0) Multi adv profile on the ESP32C3. This example is designed the periodic advertisement which allow the scanner to sync with the advertiser so that scanner and advertiser wake up same time. -##include -First, let’s take a look at the include +## Includes +First, let's take a look at the include ```c #include @@ -166,7 +166,7 @@ The functions `gap_event_handler()` handle all the events that are pushed to th The register application event is the first one that is triggered during the lifetime of the program, this example uses the Profile A GATT event handle to configure the advertising parameters upon registration. This example has the option to use both standard Bluetooth Core Specification advertising parameters or a customized raw buffer. The option can be selected with the `CONFIG_SET_RAW_ADV_DATA` define. The raw advertising data can be used to implement iBeacons, Eddystone or other proprietaries, and custom frame types such as the ones used for Indoor Location Services that are different from the standard specifications. -The function is used to configure different types of extended advertisement types and legacy adv with 1M,2M and coded phy is esp_ble_gap_ext_adv_set_params , esp_ble_gap_ext_adv_set_rand_addr and esp_ble_gap_config_ext_adv_data_raw. Respective structure of each one of them mentioned below with one example: +The function is used to configure different types of extended advertisement types and legacy adv with 1M,2M and coded phy is esp_ble_gap_ext_adv_set_params, esp_ble_gap_ext_adv_set_rand_addr and esp_ble_gap_config_ext_adv_data_raw. Respective structure of each one of them mentioned below with one example: ```c /** @@ -299,7 +299,7 @@ static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param } } ``` -## Default config +## Default Config 2M phy with connectable mode of periodic adv. diff --git a/examples/bluetooth/bluedroid/ble_50/periodic_sync/README.md b/examples/bluetooth/bluedroid/ble_50/periodic_sync/README.md index 6cf9dceebb2..861b69616d0 100644 --- a/examples/bluetooth/bluedroid/ble_50/periodic_sync/README.md +++ b/examples/bluetooth/bluedroid/ble_50/periodic_sync/README.md @@ -7,7 +7,7 @@ This example supports the periodic extended scan to scan the extended advertisem To test this demo, we can run the [periodic_adv_demo](../periodic_adv), which can start extended advertisement with supported param. -Please, check this [tutorial](tutorial/Periodic_Sync_Example_Walkthrough.md) for more information about this example. +Please check this [tutorial](tutorial/Periodic_Sync_Example_Walkthrough.md) for more information about this example. ## How to Use Example diff --git a/examples/bluetooth/bluedroid/ble_50/periodic_sync/tutorial/Periodic_Sync_Example_Walkthrough.md b/examples/bluetooth/bluedroid/ble_50/periodic_sync/tutorial/Periodic_Sync_Example_Walkthrough.md index c53b9b30457..df06c5f41d5 100644 --- a/examples/bluetooth/bluedroid/ble_50/periodic_sync/tutorial/Periodic_Sync_Example_Walkthrough.md +++ b/examples/bluetooth/bluedroid/ble_50/periodic_sync/tutorial/Periodic_Sync_Example_Walkthrough.md @@ -1,12 +1,12 @@ -#Periodic Sync Example Walkthrough +# Periodic Sync Example Walkthrough ## Introduction -In this tutorial, the Periodic sync example code for the ESP32C3 is reviewed. The code implement Bluetooth Low Energy (BLE5.0) periodic sync , which scans for nearby peripheral which can support legacy, extended and periodic advertisement. Periodic Sync allow the advertiser to sync with scanner so that scanner and advertiser wake up at same time. +In this tutorial, the Periodic sync example code for the ESP32C3 is reviewed. The code implement Bluetooth Low Energy (BLE5.0) periodic sync, which scans for nearby peripheral which can support legacy, extended and periodic advertisement. Periodic Sync allow the advertiser to sync with scanner so that scanner and advertiser wake up at same time. * ADV_EXT_IND is over primary advertising channels * AUX_ADV_IND and AUX_SYNC_IND are over secondary advertising channels -Little info about the EXT_ADV_IND , AUX_ADV_IND and AUX_SYNC_IND with scanner support of periodic sync. +Little info about the EXT_ADV_IND, AUX_ADV_IND and AUX_SYNC_IND with scanner support of periodic sync. ADV_EXT_IND is over primary advertising channels and is used to indicate that an advertisement will be sent on a secondary advertisement channel. The information in ADV_EXT_IND will inform the scanner: @@ -35,7 +35,7 @@ With this information, the scanner can synchronize with the advertiser and they #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/event_groups.h +#include "freertos/event_groups.h" #include "esp_system.h" #include "esp_log.h" #include "nvs_flash.h" @@ -49,7 +49,7 @@ With this information, the scanner can synchronize with the advertiser and they #include "freertos/semphr.h" ``` -These `includes` are required for the FreeRTOS and underlying system components to run, including the logging functionality and a library to store data in non-volatile flash memory. We are interested in `“bt.h”`, `“esp_bt_main.h”`, `"esp_gap_ble_api.h"` and `“esp_gattc_api.h”`, which expose the BLE APIs required to implement this example. +These `includes` are required for the FreeRTOS and underlying system components to run, including the logging functionality and a library to store data in non-volatile flash memory. We are interested in `"bt.h"`, `"esp_bt_main.h"`, `"esp_gap_ble_api.h"` and `"esp_gattc_api.h"`, which expose the BLE APIs required to implement this example. * `esp_bt.h`: configures the BT controller and VHCI from the host side. * `esp_bt_main.h`: initializes and enables the Bluedroid stack. diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_discovery/README.md b/examples/bluetooth/bluedroid/classic_bt/bt_discovery/README.md index af561b931e1..68bd28a5066 100644 --- a/examples/bluetooth/bluedroid/classic_bt/bt_discovery/README.md +++ b/examples/bluetooth/bluedroid/classic_bt/bt_discovery/README.md @@ -31,7 +31,7 @@ To exit the serial monitor, type `Ctrl-]`. See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects. -# TUTORIAL +## Tutorial ## Includes @@ -59,7 +59,7 @@ These `includes` are required for the FreeRTOS and underlying system components ## Main Entry Point -The program’s entry point is the `app_main()` function. +The program's entry point is the `app_main()` function. ### Non-volatile Storage Library Initialization diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_spp_initiator/README.md b/examples/bluetooth/bluedroid/classic_bt/bt_spp_initiator/README.md index f6c15b3a062..5d5b874bac8 100644 --- a/examples/bluetooth/bluedroid/classic_bt/bt_spp_initiator/README.md +++ b/examples/bluetooth/bluedroid/classic_bt/bt_spp_initiator/README.md @@ -1,7 +1,7 @@ | Supported Targets | ESP32 | | ----------------- | ----- | -# ESP-IDF BT-SPP-INITATOR demo +# ESP-IDF BT-SPP-INITIATOR demo This example is to show how to use the APIs of **Serial Port Protocol** (**SPP**) to create an SPP initiator which performs as a client. we aggregate **Secure Simple Pair** (**SSP**) into this demo to show how to use SPP when creating your own APPs. We also provide the demo `bt_spp_acceptor` or the demo `bt_spp_vfs_acceptor` to create an SPP acceptor which performs as a server. In fact, you can create SPP acceptors and SPP initiators on a single device at the same time. @@ -45,17 +45,17 @@ See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/l After the program starts, the example will initiate a Bluetooth discovery procedure and filter out the peer device by the name in the EIR(Extended Inquiry Response). After discovering the SPP service, it will connect to the SPP acceptor and send data. The example will calculate the data rate or print the sent data after the SPP connection is established. ### Example Output -When you run this example and the IO capability is `ESP_IO_CAP_IO` or `ESP_IO_CAP_IN` , the commands help table prints the following at the very beginning: +When you run this example and the IO capability is `ESP_IO_CAP_IO` or `ESP_IO_CAP_IN`, the commands help table prints the following at the very beginning: ``` ######################################################################## Supported commands are as follows, arguments are embraced with < and > spp h; -- show command manual -Use this cmmand table if the IO Capability of local device set as IO_CAP_IO. +Use this command table if the IO Capability of local device set as IO_CAP_IO. spp ok; -- manual Numeric Confirmation. -Use this cmmand table if the IO Capability of local device set as IO_CAP_IN. +Use this command table if the IO Capability of local device set as IO_CAP_IN. spp key ; -- manual Passkey. (e.g. spp key 136245;) ######################################################################## @@ -114,7 +114,7 @@ Whether you should passkey or confirm the number also depends on the IO capabili ## Example Breakdown -To clearly show how the SSP aggregate with the SPP , we use the Commands and Effects scheme to illustrate the process of secure paring and connection establishment. +To clearly show how the SSP aggregate with the SPP, we use the Commands and Effects scheme to illustrate the process of secure paring and connection establishment. - The example will respond to user command through UART console. Please go to `console_uart.c` for the configuration details. @@ -127,7 +127,7 @@ Q: How to change the process of SSP? A: Users can set the IO Capability and Security Mask for their device (fixed Security Mode, Security Mode 4). In short, the Security Mask sets the security level for authentication stage and the IO Capability determines the way of user interaction during pairing. The default Security Mask of this demo is `ESP_SPP_SEC_AUTHENTICATE` which support MITM (Man In The Middle) protection. For more information about Security Simple Pair on ESP32, please refer to [ESP32_SSP](../bt_spp_acceptor/ESP32_SSP.md). Q: How can we reach the maximum throughput when using SPP? -A: The default MTU size of classic Bluetooth SPP on ESP32 is 990 bytes, and higher throughput can be achieved in the case that data chunck size is close to the MTU size or multiple of MTU size. For example, sending 100 bytes data per second is much better than sending 10 bytes every 100 milliseconds. +A: The default MTU size of classic Bluetooth SPP on ESP32 is 990 bytes, and higher throughput can be achieved in the case that data chunk size is close to the MTU size or multiple of MTU size. For example, sending 100 bytes data per second is much better than sending 10 bytes every 100 milliseconds. Q: What is the difference between the event `ESP_SPP_CONG_EVT` and the parameter `cong` of the event `ESP_SPP_WRITE_EVT`? A: The event `ESP_SPP_CONG_EVT` shows the changing status from `congest` to `uncongest`, or form `uncongest` to `congest`. Congestion can have many causes, such as using out of the credit which is sent by peer, reaching the high watermark of the Tx buffer, the congestion at Bluetooth L2CAP layer and so on. The parameter `cong` of the event `ESP_SPP_WRITE_EVT` shows a snapshot of the state of the flow control manager after the write operation is completed. The user needs to carefully consider retransmitting or continuing to write according to these two events. The ESP32 offers an VFS mode of SPP which hides the details of retransmitting, but it will block the caller and is not more efficient than the callback mode. diff --git a/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_initiator/README.md b/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_initiator/README.md index c8b1dc82742..13cc86f3d8b 100644 --- a/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_initiator/README.md +++ b/examples/bluetooth/bluedroid/classic_bt/bt_spp_vfs_initiator/README.md @@ -1,7 +1,7 @@ | Supported Targets | ESP32 | | ----------------- | ----- | -# ESP-IDF BT-SPP-INITATOR demo +# ESP-IDF BT-SPP-INITIATOR demo This example is to show how to use the APIs of **Serial Port Protocol** (**SPP**) to create an SPP initiator which performs as a client, and it will register into the VFS. we aggregate **Secure Simple Pair** (**SSP**) into this demo to show how to use SPP when creating your own APPs. We also provide the demo `bt_spp_acceptor` or the demo `bt_spp_vfs_acceptor` to create an SPP acceptor which performs as a server. In fact, you can create SPP acceptors and SPP initiators on a single device at the same time.