From 8fe332539a533fe5bc29d07fe89fd1e2be089166 Mon Sep 17 00:00:00 2001 From: Zhang Hai Peng Date: Tue, 14 Oct 2025 21:53:33 +0800 Subject: [PATCH 1/2] fix(ble/bluedroid): Fixed resolve adv data crash if host deinitialized or disabled (cherry picked from commit 7ce921ed95b85ec94b6b2f3542548aa589d77bf8) Co-authored-by: zhanghaipeng --- components/bt/host/bluedroid/stack/btm/btm_ble_gap.c | 1 - 1 file changed, 1 deletion(-) 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 b063aefd9b9..b8d050a4271 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_ble_gap.c +++ b/components/bt/host/bluedroid/stack/btm/btm_ble_gap.c @@ -2063,7 +2063,6 @@ UINT8 *BTM_CheckAdvData( UINT8 *p_adv, UINT16 adv_data_len, UINT8 type, UINT8 *p UINT8 *p = p_adv; UINT8 length; UINT8 adv_type; - BTM_TRACE_API("BTM_CheckAdvData type=0x%02X", type); STREAM_TO_UINT8(length, p); From bd464da6c63822d4e764686e78e991916e771ef1 Mon Sep 17 00:00:00 2001 From: Zhang Hai Peng Date: Tue, 14 Oct 2025 21:53:36 +0800 Subject: [PATCH 2/2] fix(ble/bluedroid): prevent crash when deinit/disable host during scan Crash occurs if the BLE host is deinitialized or disabled while scanning is still active. This usage is not recommended. (cherry picked from commit ca2c78f53e89676bf8d68feac1d42e152d81fd02) Co-authored-by: zhanghaipeng --- .../bt/host/bluedroid/api/esp_bt_main.c | 47 ++++++++----------- .../bluedroid/api/include/api/esp_bt_main.h | 7 +-- components/bt/host/bluedroid/hci/hci_hal_h4.c | 6 +++ 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/components/bt/host/bluedroid/api/esp_bt_main.c b/components/bt/host/bluedroid/api/esp_bt_main.c index 2058e86c650..420ea826b87 100644 --- a/components/bt/host/bluedroid/api/esp_bt_main.c +++ b/components/bt/host/bluedroid/api/esp_bt_main.c @@ -18,20 +18,11 @@ #include "hci_log/bt_hci_log.h" #include "bt_common.h" -static bool bd_already_enable = false; -static bool bd_already_init = false; +static esp_bluedroid_status_t s_bt_host_state = ESP_BLUEDROID_STATUS_UNINITIALIZED; esp_bluedroid_status_t esp_bluedroid_get_status(void) { - if (bd_already_init) { - if (bd_already_enable) { - return ESP_BLUEDROID_STATUS_ENABLED; - } else { - return ESP_BLUEDROID_STATUS_INITIALIZED; - } - } else { - return ESP_BLUEDROID_STATUS_UNINITIALIZED; - } + return s_bt_host_state; } esp_err_t esp_bluedroid_enable(void) @@ -39,12 +30,12 @@ esp_err_t esp_bluedroid_enable(void) btc_msg_t msg; future_t **future_p; - if (!bd_already_init) { + if (s_bt_host_state == ESP_BLUEDROID_STATUS_UNINITIALIZED) { LOG_ERROR("Bludroid not initialised\n"); return ESP_ERR_INVALID_STATE; } - if (bd_already_enable) { + if (s_bt_host_state == ESP_BLUEDROID_STATUS_ENABLED) { LOG_ERROR("Bluedroid already enabled\n"); return ESP_ERR_INVALID_STATE; } @@ -70,8 +61,7 @@ esp_err_t esp_bluedroid_enable(void) return ESP_FAIL; } - bd_already_enable = true; - + s_bt_host_state = ESP_BLUEDROID_STATUS_ENABLED; return ESP_OK; } @@ -80,15 +70,18 @@ esp_err_t esp_bluedroid_disable(void) btc_msg_t msg; future_t **future_p; - if (!bd_already_enable) { + if (s_bt_host_state != ESP_BLUEDROID_STATUS_ENABLED) { LOG_ERROR("Bluedroid already disabled\n"); return ESP_ERR_INVALID_STATE; } + s_bt_host_state = ESP_BLUEDROID_STATUS_DISABLING; + future_p = btc_main_get_future_p(BTC_MAIN_DISABLE_FUTURE); *future_p = future_new(); if (*future_p == NULL) { LOG_ERROR("Bluedroid disable failed\n"); + s_bt_host_state = ESP_BLUEDROID_STATUS_ENABLED; return ESP_ERR_NO_MEM; } @@ -98,16 +91,17 @@ esp_err_t esp_bluedroid_disable(void) if (btc_transfer_context(&msg, NULL, 0, NULL, NULL) != BT_STATUS_SUCCESS) { LOG_ERROR("Bluedroid disable failed\n"); + s_bt_host_state = ESP_BLUEDROID_STATUS_ENABLED; return ESP_FAIL; } if (future_await(*future_p) == FUTURE_FAIL) { LOG_ERROR("Bluedroid disable failed\n"); + s_bt_host_state = ESP_BLUEDROID_STATUS_ENABLED; return ESP_FAIL; } - bd_already_enable = false; - + s_bt_host_state = ESP_BLUEDROID_STATUS_INITIALIZED; return ESP_OK; } @@ -135,7 +129,7 @@ esp_err_t esp_bluedroid_init_with_cfg(esp_bluedroid_config_t *cfg) } #endif - if (bd_already_init) { + if (s_bt_host_state != ESP_BLUEDROID_STATUS_UNINITIALIZED) { LOG_ERROR("Bluedroid already initialised\n"); return ESP_ERR_INVALID_STATE; } @@ -180,28 +174,28 @@ esp_err_t esp_bluedroid_init_with_cfg(esp_bluedroid_config_t *cfg) return ESP_FAIL; } - bd_already_init = true; - #if (BT_HCI_LOG_INCLUDED == TRUE) bt_hci_log_init(); #endif // (BT_HCI_LOG_INCLUDED == TRUE) + s_bt_host_state = ESP_BLUEDROID_STATUS_INITIALIZED; + return ESP_OK; } - esp_err_t esp_bluedroid_deinit(void) { btc_msg_t msg; future_t **future_p; - if (!bd_already_init) { + if (s_bt_host_state == ESP_BLUEDROID_STATUS_UNINITIALIZED) { LOG_ERROR("Bluedroid already de-initialised\n"); return ESP_ERR_INVALID_STATE; } - if (bd_already_enable) { - LOG_ERROR("Bludroid already enabled, do disable first\n"); + if (s_bt_host_state == ESP_BLUEDROID_STATUS_ENABLED || + s_bt_host_state == ESP_BLUEDROID_STATUS_DISABLING) { + LOG_ERROR("Bludroid still enabled or stopping, disable first\n"); return ESP_ERR_INVALID_STATE; } @@ -234,8 +228,7 @@ esp_err_t esp_bluedroid_deinit(void) bt_hci_log_deinit(); #endif // (BT_HCI_LOG_INCLUDED == TRUE) - bd_already_init = false; - + s_bt_host_state = ESP_BLUEDROID_STATUS_UNINITIALIZED; return ESP_OK; } diff --git a/components/bt/host/bluedroid/api/include/api/esp_bt_main.h b/components/bt/host/bluedroid/api/include/api/esp_bt_main.h index 4a00afd130a..185ea42cd1d 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_bt_main.h +++ b/components/bt/host/bluedroid/api/include/api/esp_bt_main.h @@ -20,9 +20,10 @@ extern "C" { * @brief Bluetooth stack status type, to indicate whether the bluetooth stack is ready. */ typedef enum { - ESP_BLUEDROID_STATUS_UNINITIALIZED = 0, /*!< Bluetooth not initialized */ - ESP_BLUEDROID_STATUS_INITIALIZED, /*!< Bluetooth initialized but not enabled */ - ESP_BLUEDROID_STATUS_ENABLED /*!< Bluetooth initialized and enabled */ + ESP_BLUEDROID_STATUS_UNINITIALIZED = 0, /*!< Bluetooth stack is not initialized */ + ESP_BLUEDROID_STATUS_INITIALIZED, /*!< Bluetooth stack is initialized but not yet enabled */ + ESP_BLUEDROID_STATUS_ENABLED, /*!< Bluetooth stack is fully initialized and enabled */ + ESP_BLUEDROID_STATUS_DISABLING /*!< Bluetooth stack is in the process of being disabled */ } esp_bluedroid_status_t; /** diff --git a/components/bt/host/bluedroid/hci/hci_hal_h4.c b/components/bt/host/bluedroid/hci/hci_hal_h4.c index ef874844eda..5baf97fc081 100644 --- a/components/bt/host/bluedroid/hci/hci_hal_h4.c +++ b/components/bt/host/bluedroid/hci/hci_hal_h4.c @@ -25,6 +25,7 @@ #include "hci/hci_trans_int.h" #include "osi/thread.h" #include "osi/pkt_queue.h" +#include "esp_bt_main.h" #if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) #include "osi/mutex.h" #include "osi/alarm.h" @@ -645,6 +646,11 @@ static int host_recv_pkt_cb(uint8_t *data, uint16_t len) fixed_queue_enqueue(hci_hal_env.rx_q, pkt, FIXED_QUEUE_MAX_TIMEOUT); } } else { + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + // Prevent race condition during host deinit/disable + // Host not ready, dropped advertising report + return 0; + } #if (BLE_42_SCAN_EN == TRUE) #if !BLE_ADV_REPORT_FLOW_CONTROL // drop the packets if pkt_queue length goes beyond upper limit