mirror of
https://github.com/espressif/esp-idf.git
synced 2025-12-27 13:43:25 +00:00
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.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -150,7 +144,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;
|
||||
}
|
||||
@@ -195,28 +189,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;
|
||||
}
|
||||
|
||||
@@ -249,8 +243,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user