Merge branch 'feat/add_support_for_host_only_mode_v5.2' into 'release/v5.2'

Feat/add support for host only mode v5.2

See merge request espressif/esp-idf!26881
This commit is contained in:
Jiang Jiang Jian
2023-11-03 20:57:33 +08:00
38 changed files with 972 additions and 57 deletions

View File

@@ -70,7 +70,7 @@ if(CONFIG_BT_ENABLED)
set(srcs "") set(srcs "")
set(include_dirs "") set(include_dirs "")
set(ldfragments "linker.lf") set(ldfragments "linker.lf")
if(CONFIG_BT_CONTROLLER_ENABLED)
if(CONFIG_IDF_TARGET_ESP32) if(CONFIG_IDF_TARGET_ESP32)
list(APPEND srcs "controller/esp32/bt.c" list(APPEND srcs "controller/esp32/bt.c"
"controller/esp32/hli_api.c" "controller/esp32/hli_api.c"
@@ -82,6 +82,9 @@ if(CONFIG_BT_ENABLED)
elseif(CONFIG_IDF_TARGET_ESP32S3) elseif(CONFIG_IDF_TARGET_ESP32S3)
list(APPEND srcs "controller/esp32c3/bt.c") list(APPEND srcs "controller/esp32c3/bt.c")
elseif(CONFIG_IDF_TARGET_ESP32C2)
list(APPEND srcs "controller/esp32c2/bt.c")
elseif(CONFIG_IDF_TARGET_ESP32C2) elseif(CONFIG_IDF_TARGET_ESP32C2)
set(ldfragments "linker.lf.esp32c2") set(ldfragments "linker.lf.esp32c2")
list(APPEND srcs "controller/esp32c2/bt.c") list(APPEND srcs "controller/esp32c2/bt.c")
@@ -95,6 +98,8 @@ if(CONFIG_BT_ENABLED)
list(APPEND include_dirs ${target_specific_include_dirs}) list(APPEND include_dirs ${target_specific_include_dirs})
endif()
# Common # Common
list(APPEND include_dirs common/osi/include) list(APPEND include_dirs common/osi/include)
@@ -174,6 +179,7 @@ if(CONFIG_BT_ENABLED)
list(APPEND srcs "host/bluedroid/api/esp_a2dp_api.c" list(APPEND srcs "host/bluedroid/api/esp_a2dp_api.c"
"host/bluedroid/api/esp_avrc_api.c" "host/bluedroid/api/esp_avrc_api.c"
"host/bluedroid/api/esp_bluedroid_hci.c"
"host/bluedroid/api/esp_bt_device.c" "host/bluedroid/api/esp_bt_device.c"
"host/bluedroid/api/esp_bt_main.c" "host/bluedroid/api/esp_bt_main.c"
"host/bluedroid/api/esp_gap_ble_api.c" "host/bluedroid/api/esp_gap_ble_api.c"

View File

@@ -1,9 +1,8 @@
menu "Bluetooth" menu "Bluetooth"
visible if SOC_BT_SUPPORTED
config BT_ENABLED config BT_ENABLED
bool "Bluetooth" bool "Bluetooth"
depends on SOC_BT_SUPPORTED && !APP_NO_BLOBS depends on !APP_NO_BLOBS
help help
Select this option to enable Bluetooth and show the submenu with Bluetooth configuration choices. Select this option to enable Bluetooth and show the submenu with Bluetooth configuration choices.
@@ -22,10 +21,12 @@ menu "Bluetooth"
config BT_NIMBLE_ENABLED config BT_NIMBLE_ENABLED
bool "NimBLE - BLE only" bool "NimBLE - BLE only"
depends on BT_CONTROLLER_ENABLED
help help
This option is recommended for BLE only usecases to save on memory This option is recommended for BLE only usecases to save on memory
config BT_CONTROLLER_ONLY config BT_CONTROLLER_ONLY
depends on SOC_BT_SUPPORTED
bool "Disabled" bool "Disabled"
help help
This option is recommended when you want to communicate directly with the This option is recommended when you want to communicate directly with the
@@ -42,6 +43,7 @@ menu "Bluetooth"
This helps to choose Bluetooth controller stack This helps to choose Bluetooth controller stack
config BT_CONTROLLER_ENABLED config BT_CONTROLLER_ENABLED
depends on SOC_BT_SUPPORTED
bool "Enabled" bool "Enabled"
help help
This option is recommended for Bluetooth controller usecases This option is recommended for Bluetooth controller usecases

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -29,6 +29,12 @@
#define UC_BT_STACK_NO_LOG FALSE #define UC_BT_STACK_NO_LOG FALSE
#endif #endif
#ifdef CONFIG_BT_CONTROLLER_ENABLED
#define UC_BT_CONTROLLER_INCLUDED TRUE
#else
#define UC_BT_CONTROLLER_INCLUDED FALSE
#endif
/********************************************************** /**********************************************************
* Thread/Task reference * Thread/Task reference
**********************************************************/ **********************************************************/

View File

@@ -49,7 +49,7 @@ config BT_BLUEDROID_ESP_COEX_VSC
config BT_CLASSIC_ENABLED config BT_CLASSIC_ENABLED
bool "Classic Bluetooth" bool "Classic Bluetooth"
depends on BT_BLUEDROID_ENABLED && IDF_TARGET_ESP32 depends on BT_BLUEDROID_ENABLED && ((BT_CONTROLLER_ENABLED && SOC_BT_CLASSIC_SUPPORTED) || BT_CONTROLLER_DISABLED)
default n default n
help help
For now this option needs "SMP_ENABLE" to be set to yes For now this option needs "SMP_ENABLE" to be set to yes
@@ -1116,8 +1116,9 @@ config BT_MAX_DEVICE_NAME_LEN
config BT_BLE_RPA_SUPPORTED config BT_BLE_RPA_SUPPORTED
bool "Update RPA to Controller" bool "Update RPA to Controller"
depends on BT_BLUEDROID_ENABLED && !SOC_BLE_DEVICE_PRIVACY_SUPPORTED depends on (BT_BLUEDROID_ENABLED && ((BT_CONTROLLER_ENABLED && !SOC_BLE_DEVICE_PRIVACY_SUPPORTED) || BT_CONTROLLER_DISABLED))
default n default n if (BT_CONTROLLER_ENABLED && !SOC_BLE_DEVICE_PRIVACY_SUPPORTED)
default y if BT_CONTROLLER_DISABLED
help help
This enables controller RPA list function. This enables controller RPA list function.
For ESP32, ESP32 only support network privacy mode. If this option is enabled, ESP32 will only accept For ESP32, ESP32 only support network privacy mode. If this option is enabled, ESP32 will only accept
@@ -1141,28 +1142,28 @@ config BT_BLE_RPA_TIMEOUT
config BT_BLE_50_FEATURES_SUPPORTED config BT_BLE_50_FEATURES_SUPPORTED
bool "Enable BLE 5.0 features" bool "Enable BLE 5.0 features"
depends on (BT_BLUEDROID_ENABLED && (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 || SOC_ESP_NIMBLE_CONTROLLER)) depends on (BT_BLUEDROID_ENABLED && ((BT_CONTROLLER_ENABLED && SOC_BLE_50_SUPPORTED) || BT_CONTROLLER_DISABLED))
default y default y
help help
This enables BLE 5.0 features, this option only support esp32c3/esp32s3 chip This enables BLE 5.0 features, this option only support esp32c3/esp32s3 chip
config BT_BLE_42_FEATURES_SUPPORTED config BT_BLE_42_FEATURES_SUPPORTED
bool "Enable BLE 4.2 features" bool "Enable BLE 4.2 features"
depends on (BT_BLUEDROID_ENABLED && (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 || SOC_ESP_NIMBLE_CONTROLLER)) depends on (BT_BLUEDROID_ENABLED && ((BT_CONTROLLER_ENABLED && SOC_BLE_SUPPORTED) || BT_CONTROLLER_DISABLED))
default n default n
help help
This enables BLE 4.2 features. This enables BLE 4.2 features.
config BT_BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER config BT_BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER
bool "Enable BLE periodic advertising sync transfer feature" bool "Enable BLE periodic advertising sync transfer feature"
depends on (BT_BLUEDROID_ENABLED && BT_BLE_50_FEATURES_SUPPORTED && SOC_ESP_NIMBLE_CONTROLLER) depends on (BT_BLUEDROID_ENABLED && BT_BLE_50_FEATURES_SUPPORTED && ((BT_CONTROLLER_ENABLED && SOC_ESP_NIMBLE_CONTROLLER) || BT_CONTROLLER_DISABLED))
default n default n
help help
This enables BLE periodic advertising sync transfer feature This enables BLE periodic advertising sync transfer feature
config BT_BLE_FEAT_PERIODIC_ADV_ENH config BT_BLE_FEAT_PERIODIC_ADV_ENH
bool "Enable periodic adv enhancements(adi support)" bool "Enable periodic adv enhancements(adi support)"
depends on (BT_BLUEDROID_ENABLED && BT_BLE_50_FEATURES_SUPPORTED && SOC_ESP_NIMBLE_CONTROLLER) depends on (BT_BLUEDROID_ENABLED && BT_BLE_50_FEATURES_SUPPORTED && ((BT_CONTROLLER_ENABLED && SOC_ESP_NIMBLE_CONTROLLER) || BT_CONTROLLER_DISABLED))
default n default n
help help
Enable the periodic advertising enhancements Enable the periodic advertising enhancements

View File

@@ -0,0 +1,89 @@
/*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include "esp_log.h"
#include "esp_bluedroid_hci.h"
#include "common/bt_target.h"
#include "hci/hci_trans_int.h"
#if (BT_CONTROLLER_INCLUDED == TRUE)
#include "esp_bt.h"
#endif
#define LOG_TAG "HCI_API"
static esp_bluedroid_hci_driver_operations_t s_hci_driver_ops = { 0 };
esp_err_t esp_bluedroid_attach_hci_driver(const esp_bluedroid_hci_driver_operations_t *p_ops)
{
if (!p_ops) {
ESP_LOGE(LOG_TAG, "%s invalid function parameter", __func__);
return ESP_FAIL;
}
s_hci_driver_ops.send = p_ops->send;
s_hci_driver_ops.check_send_available = p_ops->check_send_available;
s_hci_driver_ops.register_host_callback = p_ops->register_host_callback;
return ESP_OK;
}
esp_err_t esp_bluedroid_detach_hci_driver(void)
{
s_hci_driver_ops.send = NULL;
s_hci_driver_ops.check_send_available = NULL;
s_hci_driver_ops.register_host_callback = NULL;
return ESP_OK;
}
/****************************************************************
* INTERNAL USE *
****************************************************************/
bool hci_host_check_send_available(void)
{
bool can_send = false;
#if (BT_CONTROLLER_INCLUDED == TRUE)
can_send = esp_vhci_host_check_send_available();
#else /* BT_CONTROLLER_INCLUDED == TRUE */
if (s_hci_driver_ops.check_send_available) {
can_send = s_hci_driver_ops.check_send_available();
}
#endif /* BT_CONTROLLER_INCLUDED == TRUE */
return can_send;
}
void hci_host_send_packet(uint8_t *data, uint16_t len)
{
#if (BT_CONTROLLER_INCLUDED == TRUE)
esp_vhci_host_send_packet(data, len);
#else /* BT_CONTROLLER_INCLUDED == TRUE */
if (s_hci_driver_ops.send) {
s_hci_driver_ops.send(data, len);
}
#endif /* BT_CONTROLLER_INCLUDED == TRUE */
}
esp_err_t hci_host_register_callback(const esp_bluedroid_hci_driver_callbacks_t *callback)
{
esp_err_t ret = ESP_FAIL;
if (!callback) {
ESP_LOGE(LOG_TAG, "%s invalid function parameter", __func__);
return ESP_FAIL;
}
#if (BT_CONTROLLER_INCLUDED == TRUE)
ret = esp_vhci_host_register_callback((esp_vhci_host_callback_t *)callback);
#else /* BT_CONTROLLER_INCLUDED == TRUE */
if (s_hci_driver_ops.register_host_callback) {
ret = s_hci_driver_ops.register_host_callback(callback);
}
#endif /* BT_CONTROLLER_INCLUDED == TRUE */
return ret;
}

View File

@@ -5,10 +5,13 @@
*/ */
#include "common/bt_target.h"
#include "esp_bt_main.h" #include "esp_bt_main.h"
#include "btc/btc_task.h" #include "btc/btc_task.h"
#include "btc/btc_main.h" #include "btc/btc_main.h"
#if (BT_CONTROLLER_INCLUDED == TRUE)
#include "esp_bt.h" #include "esp_bt.h"
#endif
#include "osi/future.h" #include "osi/future.h"
#include "osi/allocator.h" #include "osi/allocator.h"
#include "config/stack_config.h" #include "config/stack_config.h"
@@ -123,10 +126,12 @@ esp_err_t esp_bluedroid_init_with_cfg(esp_bluedroid_config_t *cfg)
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
#if (BT_CONTROLLER_INCLUDED == TRUE)
if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) { if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) {
LOG_ERROR("Controller not initialised\n"); LOG_ERROR("Controller not initialised\n");
return ESP_ERR_INVALID_STATE; return ESP_ERR_INVALID_STATE;
} }
#endif
if (bd_already_init) { if (bd_already_init) {
LOG_ERROR("Bluedroid already initialised\n"); LOG_ERROR("Bluedroid already initialised\n");

View File

@@ -21,7 +21,9 @@
#include "common/bt_target.h" #include "common/bt_target.h"
#include "common/bt_defs.h" #include "common/bt_defs.h"
#include "device/bdaddr.h" #include "device/bdaddr.h"
#if (BT_CONTROLLER_INCLUDED == TRUE)
#include "esp_bt.h" #include "esp_bt.h"
#endif
#include "esp_hf_ag_api.h" #include "esp_hf_ag_api.h"
#include "esp_err.h" #include "esp_err.h"
#include "esp_bt_main.h" #include "esp_bt_main.h"

View File

@@ -0,0 +1,84 @@
/*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __ESP_BLUEDROID_HCI_H__
#define __ESP_BLUEDROID_HCI_H__
#include <stdbool.h>
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
/* HCI driver callbacks */
typedef struct esp_bluedroid_hci_driver_callbacks {
/**
* @brief callback used to notify that the host can send packet to controller
*/
void (*notify_host_send_available)(void);
/**
* @brief callback used to notify that the controller has a packet to send to the host
*
* @param[in] data pointer to data buffer
* @param[in] len length of data
*
* @return 0 received successfully, failed otherwise
*/
int (*notify_host_recv)(uint8_t *data, uint16_t len);
} esp_bluedroid_hci_driver_callbacks_t;
/* HCI driver operations */
typedef struct esp_bluedroid_hci_driver_operations {
/**
* @brief send data from host to controller
*
* @param[in] data pointer to data buffer
* @param[in] len length of data
*/
void (*send)(uint8_t *data, uint16_t len);
/**
* @brief host checks whether it can send data to controller
*
* @return true if host can send data, false otherwise
*/
bool (*check_send_available)(void);
/**
* @brief register host callback
*
* @param[in] callback HCI driver callbacks
*/
esp_err_t (* register_host_callback)(const esp_bluedroid_hci_driver_callbacks_t *callback);
} esp_bluedroid_hci_driver_operations_t;
/**
* @brief get the operations of HCI transport layer. This API should only be used in
* Bluedroid Host-only mode before Bluedroid initialization.
*
* @param[in] ops struct containing operations of HCI transport layer
*
* @return ESP_OK if get successfully, ESP_FAIL otherwise
*/
esp_err_t esp_bluedroid_attach_hci_driver(const esp_bluedroid_hci_driver_operations_t *ops);
/**
* @brief remove the operations of HCI transport layer. This API should only be used in
* Bluedroid Host-only mode before Bluedroid initialization.
*
* @param[in] ops struct containing operations of HCI transport layer
*
* @return ESP_OK if get successfully, ESP_FAIL otherwise
*/
esp_err_t esp_bluedroid_detach_hci_driver(void);
#ifdef __cplusplus
}
#endif
#endif /* __ESP_BLUEDROID_HCI_H__ */

View File

@@ -46,6 +46,9 @@
#if (GAP_INCLUDED == TRUE) #if (GAP_INCLUDED == TRUE)
#include "stack/gap_api.h" #include "stack/gap_api.h"
#endif #endif
#if (BT_CONTROLLER_INCLUDED == TRUE)
#include "esp_bt.h"
#endif
static void bta_dm_inq_results_cb (tBTM_INQ_RESULTS *p_inq, UINT8 *p_eir); static void bta_dm_inq_results_cb (tBTM_INQ_RESULTS *p_inq, UINT8 *p_eir);
static void bta_dm_inq_cmpl_cb (void *p_result); static void bta_dm_inq_cmpl_cb (void *p_result);
@@ -136,7 +139,6 @@ static void bta_dm_observe_discard_cb (uint32_t num_dis);
static void bta_dm_delay_role_switch_cback(TIMER_LIST_ENT *p_tle); static void bta_dm_delay_role_switch_cback(TIMER_LIST_ENT *p_tle);
extern void sdpu_uuid16_to_uuid128(UINT16 uuid16, UINT8 *p_uuid128); extern void sdpu_uuid16_to_uuid128(UINT16 uuid16, UINT8 *p_uuid128);
static void bta_dm_disable_timer_cback(TIMER_LIST_ENT *p_tle); static void bta_dm_disable_timer_cback(TIMER_LIST_ENT *p_tle);
extern int bredr_txpwr_get(int *min_power_level, int *max_power_level);
const UINT16 bta_service_id_to_uuid_lkup_tbl [BTA_MAX_SERVICE_ID] = { const UINT16 bta_service_id_to_uuid_lkup_tbl [BTA_MAX_SERVICE_ID] = {
UUID_SERVCLASS_PNP_INFORMATION, /* Reserved */ UUID_SERVCLASS_PNP_INFORMATION, /* Reserved */
@@ -4313,7 +4315,14 @@ static void bta_dm_set_eir (char *local_name)
if (p_bta_dm_eir_cfg->bta_dm_eir_included_tx_power) { if (p_bta_dm_eir_cfg->bta_dm_eir_included_tx_power) {
if (free_eir_length >= 3) { if (free_eir_length >= 3) {
int min_power_level, max_power_level; int min_power_level, max_power_level;
if (bredr_txpwr_get(&min_power_level, &max_power_level) == 0) { #if (BT_CONTROLLER_INCLUDED == TRUE)
if (esp_bredr_tx_power_get((esp_power_level_t *)&min_power_level, (esp_power_level_t *)&max_power_level) == ESP_OK) {
#else
{
min_power_level = 0;
max_power_level = 0;
UNUSED(min_power_level);
#endif
INT8 btm_tx_power[BTM_TX_POWER_LEVEL_MAX + 1] = BTM_TX_POWER; INT8 btm_tx_power[BTM_TX_POWER_LEVEL_MAX + 1] = BTM_TX_POWER;
p_bta_dm_eir_cfg->bta_dm_eir_inq_tx_power = btm_tx_power[max_power_level]; p_bta_dm_eir_cfg->bta_dm_eir_inq_tx_power = btm_tx_power[max_power_level];
UINT8_TO_STREAM(p, 2); /* Length field */ UINT8_TO_STREAM(p, 2); /* Length field */

View File

@@ -9,6 +9,7 @@
#include "osi/allocator.h" #include "osi/allocator.h"
#include "stack/bt_types.h" #include "stack/bt_types.h"
#include "common/bt_defs.h" #include "common/bt_defs.h"
#include "common/bt_target.h"
#include "bta/bta_api.h" #include "bta/bta_api.h"
#include "bta/bta_dm_co.h" #include "bta/bta_dm_co.h"
#include "btc/btc_task.h" #include "btc/btc_task.h"
@@ -23,7 +24,9 @@
#include "osi/mutex.h" #include "osi/mutex.h"
#include "osi/thread.h" #include "osi/thread.h"
#include "osi/pkt_queue.h" #include "osi/pkt_queue.h"
#if (BT_CONTROLLER_INCLUDED == TRUE)
#include "esp_bt.h" #include "esp_bt.h"
#endif
#if (BLE_INCLUDED == TRUE) #if (BLE_INCLUDED == TRUE)
#if (BLE_42_FEATURE_SUPPORT == TRUE) #if (BLE_42_FEATURE_SUPPORT == TRUE)
@@ -187,7 +190,11 @@ static void btc_to_bta_adv_data(esp_ble_adv_data_t *p_adv_data, tBTA_BLE_ADV_DAT
if (p_adv_data->include_txpower) { if (p_adv_data->include_txpower) {
mask |= BTM_BLE_AD_BIT_TX_PWR; mask |= BTM_BLE_AD_BIT_TX_PWR;
#if (BT_CONTROLLER_INCLUDED == TRUE)
bta_adv_data->tx_power = esp_ble_tx_power_get(ESP_BLE_PWR_TYPE_ADV); bta_adv_data->tx_power = esp_ble_tx_power_get(ESP_BLE_PWR_TYPE_ADV);
#else
bta_adv_data->tx_power = 0;
#endif
} }
if (p_adv_data->min_interval > 0 && p_adv_data->max_interval > 0 && if (p_adv_data->min_interval > 0 && p_adv_data->max_interval > 0 &&

View File

@@ -29,7 +29,9 @@
#include "common/bt_trace.h" #include "common/bt_trace.h"
#include "common/bt_defs.h" #include "common/bt_defs.h"
#include "device/bdaddr.h" #include "device/bdaddr.h"
#if (BT_CONTROLLER_INCLUDED == TRUE)
#include "esp_bt.h" #include "esp_bt.h"
#endif
#include "esp_hf_ag_api.h" #include "esp_hf_ag_api.h"
#include "osi/allocator.h" #include "osi/allocator.h"
@@ -328,12 +330,14 @@ bt_status_t btc_hf_init(void)
// custom initialization here // custom initialization here
hf_local_param[idx].btc_hf_cb.initialized = true; hf_local_param[idx].btc_hf_cb.initialized = true;
// set audio path // set audio path
#if (BT_CONTROLLER_INCLUDED == TRUE)
#if BTM_SCO_HCI_INCLUDED #if BTM_SCO_HCI_INCLUDED
uint8_t data_path = ESP_SCO_DATA_PATH_HCI; uint8_t data_path = ESP_SCO_DATA_PATH_HCI;
#else #else
uint8_t data_path = ESP_SCO_DATA_PATH_PCM; uint8_t data_path = ESP_SCO_DATA_PATH_PCM;
#endif #endif
esp_bredr_sco_datapath_set(data_path); esp_bredr_sco_datapath_set(data_path);
#endif
return BT_STATUS_SUCCESS; return BT_STATUS_SUCCESS;
} }

View File

@@ -25,7 +25,9 @@
#include "btc/btc_util.h" #include "btc/btc_util.h"
#include "esp_hf_client_api.h" #include "esp_hf_client_api.h"
#include "bta/bta_hf_client_api.h" #include "bta/bta_hf_client_api.h"
#if (BT_CONTROLLER_INCLUDED == TRUE)
#include "esp_bt.h" #include "esp_bt.h"
#endif
#include <assert.h> #include <assert.h>
#if BT_HF_CLIENT_BQB_INCLUDED #if BT_HF_CLIENT_BQB_INCLUDED
@@ -167,19 +169,20 @@ bt_status_t btc_hf_client_init(void)
{ {
BTC_TRACE_EVENT("%s", __FUNCTION__); BTC_TRACE_EVENT("%s", __FUNCTION__);
uint8_t data_path;
btc_dm_enable_service(BTA_HFP_HS_SERVICE_ID); btc_dm_enable_service(BTA_HFP_HS_SERVICE_ID);
clear_state(); clear_state();
hf_client_local_param.btc_hf_client_cb.initialized = true; hf_client_local_param.btc_hf_client_cb.initialized = true;
#if (BT_CONTROLLER_INCLUDED == TRUE)
#if BTM_SCO_HCI_INCLUDED #if BTM_SCO_HCI_INCLUDED
data_path = ESP_SCO_DATA_PATH_HCI; uint8_t data_path = ESP_SCO_DATA_PATH_HCI;
#else #else
data_path = ESP_SCO_DATA_PATH_PCM; uint8_t data_path = ESP_SCO_DATA_PATH_PCM;
#endif #endif
esp_bredr_sco_datapath_set(data_path); esp_bredr_sco_datapath_set(data_path);
#endif
return BT_STATUS_SUCCESS; return BT_STATUS_SUCCESS;
} }

View File

@@ -105,7 +105,7 @@
#ifdef CONFIG_BT_BLE_RPA_SUPPORTED #ifdef CONFIG_BT_BLE_RPA_SUPPORTED
#define UC_BT_BLE_RPA_SUPPORTED CONFIG_BT_BLE_RPA_SUPPORTED #define UC_BT_BLE_RPA_SUPPORTED CONFIG_BT_BLE_RPA_SUPPORTED
#else #else
#if SOC_BLE_DEVICE_PRIVACY_SUPPORTED #if (CONFIG_BT_CONTROLLER_ENABLED && SOC_BLE_DEVICE_PRIVACY_SUPPORTED)
#define UC_BT_BLE_RPA_SUPPORTED TRUE #define UC_BT_BLE_RPA_SUPPORTED TRUE
#else #else
#define UC_BT_BLE_RPA_SUPPORTED FALSE #define UC_BT_BLE_RPA_SUPPORTED FALSE

View File

@@ -51,6 +51,12 @@
#define ESP_COEX_VSC_INCLUDED FALSE #define ESP_COEX_VSC_INCLUDED FALSE
#endif #endif
#if (UC_BT_CONTROLLER_INCLUDED == TRUE)
#define BT_CONTROLLER_INCLUDED TRUE
#else
#define BT_CONTROLLER_INCLUDED FALSE
#endif
/****************************************************************************** /******************************************************************************
** **
** Classic BT features ** Classic BT features

View File

@@ -22,16 +22,20 @@
#include "hci/hci_hal.h" #include "hci/hci_hal.h"
#include "hci/hci_internals.h" #include "hci/hci_internals.h"
#include "hci/hci_layer.h" #include "hci/hci_layer.h"
#include "hci/hci_trans_int.h"
#include "osi/thread.h" #include "osi/thread.h"
#include "osi/pkt_queue.h" #include "osi/pkt_queue.h"
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) #if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
#include "osi/mutex.h" #include "osi/mutex.h"
#include "osi/alarm.h" #include "osi/alarm.h"
#endif #endif
#if (BT_CONTROLLER_INCLUDED == TRUE)
#include "esp_bt.h" #include "esp_bt.h"
#endif
#include "esp_bluedroid_hci.h"
#include "stack/hcimsgs.h" #include "stack/hcimsgs.h"
#if SOC_ESP_NIMBLE_CONTROLLER #if ((BT_CONTROLLER_INCLUDED == TRUE) && SOC_ESP_NIMBLE_CONTROLLER)
#include "nimble/ble_hci_trans.h" #include "nimble/ble_hci_trans.h"
#endif #endif
@@ -87,7 +91,7 @@ typedef struct {
static hci_hal_env_t hci_hal_env; static hci_hal_env_t hci_hal_env;
static const hci_hal_t interface; static const hci_hal_t interface;
static const esp_vhci_host_callback_t vhci_host_cb; static const esp_bluedroid_hci_driver_callbacks_t hci_host_cb;
static void host_send_pkt_available_cb(void); static void host_send_pkt_available_cb(void);
static int host_recv_pkt_cb(uint8_t *data, uint16_t len); static int host_recv_pkt_cb(uint8_t *data, uint16_t len);
@@ -167,7 +171,7 @@ static bool hal_open(const hci_hal_callbacks_t *upper_callbacks, void *task_thre
hci_hal_env_init(upper_callbacks, (osi_thread_t *)task_thread); hci_hal_env_init(upper_callbacks, (osi_thread_t *)task_thread);
//register vhci host cb //register vhci host cb
if (esp_vhci_host_register_callback(&vhci_host_cb) != ESP_OK) { if (hci_host_register_callback(&hci_host_cb) != ESP_OK) {
return false; return false;
} }
@@ -207,7 +211,7 @@ static uint16_t transmit_data(serial_data_type_t type,
BTTRC_DUMP_BUFFER("Transmit Pkt", data, length); BTTRC_DUMP_BUFFER("Transmit Pkt", data, length);
// TX Data to target // TX Data to target
esp_vhci_host_send_packet(data, length); hci_host_send_packet(data, length);
// Be nice and restore the old value of that byte // Be nice and restore the old value of that byte
*(data) = previous_byte; *(data) = previous_byte;
@@ -590,7 +594,7 @@ static int host_recv_pkt_cb(uint8_t *data, uint16_t len)
return 0; return 0;
} }
#if SOC_ESP_NIMBLE_CONTROLLER #if ((BT_CONTROLLER_INCLUDED == TRUE) && SOC_ESP_NIMBLE_CONTROLLER)
int int
ble_hs_hci_rx_evt(uint8_t *hci_ev, void *arg) ble_hs_hci_rx_evt(uint8_t *hci_ev, void *arg)
@@ -625,7 +629,7 @@ ble_hs_rx_data(struct os_mbuf *om, void *arg)
} }
#endif #endif
static const esp_vhci_host_callback_t vhci_host_cb = { static const esp_bluedroid_hci_driver_callbacks_t hci_host_cb = {
.notify_host_send_available = host_send_pkt_available_cb, .notify_host_send_available = host_send_pkt_available_cb,
.notify_host_recv = host_recv_pkt_cb, .notify_host_recv = host_recv_pkt_cb,
}; };

View File

@@ -17,7 +17,10 @@
******************************************************************************/ ******************************************************************************/
#include <string.h> #include <string.h>
#include "sdkconfig.h" #include "sdkconfig.h"
#include "common/bt_target.h"
#if (BT_CONTROLLER_INCLUDED == TRUE)
#include "esp_bt.h" #include "esp_bt.h"
#endif
#include "common/bt_defs.h" #include "common/bt_defs.h"
#include "common/bt_trace.h" #include "common/bt_trace.h"
@@ -28,6 +31,7 @@
#include "hci/hci_internals.h" #include "hci/hci_internals.h"
#include "hci/hci_hal.h" #include "hci/hci_hal.h"
#include "hci/hci_layer.h" #include "hci/hci_layer.h"
#include "hci/hci_trans_int.h"
#include "osi/allocator.h" #include "osi/allocator.h"
#include "hci/packet_fragmenter.h" #include "hci/packet_fragmenter.h"
#include "osi/list.h" #include "osi/list.h"
@@ -226,7 +230,7 @@ static void hci_downstream_data_handler(void *arg)
* All packets will be directly copied to single queue in driver layer with * All packets will be directly copied to single queue in driver layer with
* H4 type header added (1 byte). * H4 type header added (1 byte).
*/ */
while (esp_vhci_host_check_send_available()) { while (hci_host_check_send_available()) {
/*Now Target only allowed one packet per TX*/ /*Now Target only allowed one packet per TX*/
BT_HDR *pkt = packet_fragmenter->fragment_current_packet(); BT_HDR *pkt = packet_fragmenter->fragment_current_packet();
if (pkt != NULL) { if (pkt != NULL) {

View File

@@ -21,9 +21,10 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include "common/bt_target.h"
#include "osi/pkt_queue.h" #include "osi/pkt_queue.h"
#include "stack/bt_types.h" #include "stack/bt_types.h"
#if SOC_ESP_NIMBLE_CONTROLLER #if ((BT_CONTROLLER_INCLUDED == TRUE) && SOC_ESP_NIMBLE_CONTROLLER)
#include "os/os_mbuf.h" #include "os/os_mbuf.h"
#endif #endif
typedef enum { typedef enum {
@@ -85,7 +86,7 @@ typedef struct hci_hal_t {
// Gets the correct hal implementation, as compiled for. // Gets the correct hal implementation, as compiled for.
const hci_hal_t *hci_hal_h4_get_interface(void); const hci_hal_t *hci_hal_h4_get_interface(void);
#if SOC_ESP_NIMBLE_CONTROLLER #if ((BT_CONTROLLER_INCLUDED == TRUE) && SOC_ESP_NIMBLE_CONTROLLER)
int ble_hs_hci_rx_evt(uint8_t *hci_ev, void *arg); int ble_hs_hci_rx_evt(uint8_t *hci_ev, void *arg);
int ble_hs_rx_data(struct os_mbuf *om, void *arg); int ble_hs_rx_data(struct os_mbuf *om, void *arg);

View File

@@ -0,0 +1,47 @@
/*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __HCI_TRANS_INT_H__
#define __HCI_TRANS_INT_H__
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#include "esp_bluedroid_hci.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief host checks whether it can send data to controller
*
* @return true if host can send data, false otherwise
*/
bool hci_host_check_send_available(void);
/**
* @brief host sends packet to controller
*
* @param[in] data pointer to data buffer
* @param[in] len length of data in byte
*/
void hci_host_send_packet(uint8_t *data, uint16_t len);
/**
* @brief register the HCI function interface
*
* @param[in] callback HCI function interface
*
* @return ESP_OK register successfully, ESP_FAIL otherwise
*/
esp_err_t hci_host_register_callback(const esp_bluedroid_hci_driver_callbacks_t *callback);
#ifdef __cplusplus
}
#endif
#endif /* __HCI_TRANS_INT_H__ */

View File

@@ -15,7 +15,6 @@
#include "unity.h" #include "unity.h"
#include "esp_random.h" #include "esp_random.h"
#include "esp_bt.h"
#include "esp_bt_main.h" #include "esp_bt_main.h"
#include "esp_bt_device.h" #include "esp_bt_device.h"
#include "esp_gap_ble_api.h" #include "esp_gap_ble_api.h"

View File

@@ -12,7 +12,6 @@
#include "esp_hidd_private.h" #include "esp_hidd_private.h"
#include "esp_log.h" #include "esp_log.h"
#include "esp_bt.h"
#include "esp_bt_main.h" #include "esp_bt_main.h"
#include "esp_bt_defs.h" #include "esp_bt_defs.h"
#include "esp_gatts_api.h" #include "esp_gatts_api.h"

View File

@@ -11,7 +11,6 @@
#include "esp_err.h" #include "esp_err.h"
#include "esp_log.h" #include "esp_log.h"
#include "esp_bt.h"
#include "esp_bt_defs.h" #include "esp_bt_defs.h"
#include "esp_bt_main.h" #include "esp_bt_main.h"
#include "esp_gattc_api.h" #include "esp_gattc_api.h"

View File

@@ -6,7 +6,6 @@
#include "bt_hidd.h" #include "bt_hidd.h"
#if CONFIG_BT_HID_DEVICE_ENABLED #if CONFIG_BT_HID_DEVICE_ENABLED
#include "esp_bt.h"
#include "esp_bt_defs.h" #include "esp_bt_defs.h"
#include "esp_bt_main.h" #include "esp_bt_main.h"
#include "esp_hidd.h" #include "esp_hidd.h"

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -8,7 +8,9 @@
#include <freertos/FreeRTOS.h> #include <freertos/FreeRTOS.h>
#include <esp_system.h> #include <esp_system.h>
#include <esp_log.h> #include <esp_log.h>
#ifdef CONFIG_BT_CONTROLLER_ENABLED
#include "esp_bt.h" #include "esp_bt.h"
#endif
#include <esp_gap_ble_api.h> #include <esp_gap_ble_api.h>
#include <esp_gatts_api.h> #include <esp_gatts_api.h>
#include <esp_bt_main.h> #include <esp_bt_main.h>
@@ -213,6 +215,7 @@ esp_err_t simple_ble_start(simple_ble_cfg_t *cfg)
ESP_LOGD(TAG, "Free mem at start of simple_ble_init %" PRIu32, esp_get_free_heap_size()); ESP_LOGD(TAG, "Free mem at start of simple_ble_init %" PRIu32, esp_get_free_heap_size());
esp_err_t ret; esp_err_t ret;
#ifdef CONFIG_BT_CONTROLLER_ENABLED
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
ret = esp_bt_controller_init(&bt_cfg); ret = esp_bt_controller_init(&bt_cfg);
if (ret) { if (ret) {
@@ -232,6 +235,7 @@ esp_err_t simple_ble_start(simple_ble_cfg_t *cfg)
ESP_LOGE(TAG, "%s enable controller failed %d", __func__, ret); ESP_LOGE(TAG, "%s enable controller failed %d", __func__, ret);
return ret; return ret;
} }
#endif
esp_bluedroid_config_t bluedroid_cfg = BT_BLUEDROID_INIT_CONFIG_DEFAULT(); esp_bluedroid_config_t bluedroid_cfg = BT_BLUEDROID_INIT_CONFIG_DEFAULT();
ret = esp_bluedroid_init_with_cfg(&bluedroid_cfg); ret = esp_bluedroid_init_with_cfg(&bluedroid_cfg);
@@ -307,6 +311,7 @@ esp_err_t simple_ble_stop(void)
return err; return err;
} }
ESP_LOGD(TAG, "esp_bluedroid_deinit called successfully"); ESP_LOGD(TAG, "esp_bluedroid_deinit called successfully");
#ifdef CONFIG_BT_CONTROLLER_ENABLED
err = esp_bt_controller_disable(); err = esp_bt_controller_disable();
if (err != ESP_OK) { if (err != ESP_OK) {
return ESP_FAIL; return ESP_FAIL;
@@ -321,7 +326,7 @@ esp_err_t simple_ble_stop(void)
return ESP_FAIL; return ESP_FAIL;
} }
ESP_LOGD(TAG, "esp_bt_controller_deinit called successfully"); ESP_LOGD(TAG, "esp_bt_controller_deinit called successfully");
#endif
ESP_LOGD(TAG, "Free mem at end of simple_ble_stop %" PRIu32, esp_get_free_heap_size()); ESP_LOGD(TAG, "Free mem at end of simple_ble_stop %" PRIu32, esp_get_free_heap_size());
return ESP_OK; return ESP_OK;
} }

View File

@@ -142,6 +142,7 @@
#define CPU_CLK_FREQ_MHZ_BTLD (80) // The cpu clock frequency (in MHz) to set at 2nd stage bootloader system clock configuration #define CPU_CLK_FREQ_MHZ_BTLD (80) // The cpu clock frequency (in MHz) to set at 2nd stage bootloader system clock configuration
#define CPU_CLK_FREQ APB_CLK_FREQ #define CPU_CLK_FREQ APB_CLK_FREQ
#define APB_CLK_FREQ ( 40*1000000 ) #define APB_CLK_FREQ ( 40*1000000 )
#define MODEM_REQUIRED_MIN_APB_CLK_FREQ ( 80*1000000 )
#define REF_CLK_FREQ ( 1000000 ) #define REF_CLK_FREQ ( 1000000 )
#define XTAL_CLK_FREQ (40*1000000) #define XTAL_CLK_FREQ (40*1000000)
#define GPIO_MATRIX_DELAY_NS 0 #define GPIO_MATRIX_DELAY_NS 0

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -7,7 +7,9 @@
#include <string.h> #include <string.h>
#include <esp_log.h> #include <esp_log.h>
#include <esp_err.h> #include <esp_err.h>
#ifdef CONFIG_BT_CONTROLLER_ENABLED
#include "esp_bt.h" #include "esp_bt.h"
#endif
#include <protocomm.h> #include <protocomm.h>
#include <protocomm_ble.h> #include <protocomm_ble.h>
@@ -197,9 +199,10 @@ static esp_err_t set_config_endpoint(void *config, const char *endpoint_name, ui
/* Used when both BT and BLE are not needed by application */ /* Used when both BT and BLE are not needed by application */
void wifi_prov_scheme_ble_event_cb_free_btdm(void *user_data, wifi_prov_cb_event_t event, void *event_data) void wifi_prov_scheme_ble_event_cb_free_btdm(void *user_data, wifi_prov_cb_event_t event, void *event_data)
{ {
esp_err_t err;
switch (event) { switch (event) {
case WIFI_PROV_INIT: case WIFI_PROV_INIT:
#ifdef CONFIG_BT_CONTROLLER_ENABLED
esp_err_t err;
/* Release BT memory, as we need only BLE */ /* Release BT memory, as we need only BLE */
err = esp_bt_mem_release(ESP_BT_MODE_CLASSIC_BT); err = esp_bt_mem_release(ESP_BT_MODE_CLASSIC_BT);
if (err != ESP_OK) { if (err != ESP_OK) {
@@ -207,10 +210,12 @@ void wifi_prov_scheme_ble_event_cb_free_btdm(void *user_data, wifi_prov_cb_event
} else { } else {
ESP_LOGI(TAG, "BT memory released"); ESP_LOGI(TAG, "BT memory released");
} }
#endif
break; break;
case WIFI_PROV_DEINIT: case WIFI_PROV_DEINIT:
#ifndef CONFIG_WIFI_PROV_KEEP_BLE_ON_AFTER_PROV #ifndef CONFIG_WIFI_PROV_KEEP_BLE_ON_AFTER_PROV
#ifdef CONFIG_BT_CONTROLLER_ENABLED
/* Release memory used by BLE and Bluedroid host stack */ /* Release memory used by BLE and Bluedroid host stack */
err = esp_bt_mem_release(ESP_BT_MODE_BTDM); err = esp_bt_mem_release(ESP_BT_MODE_BTDM);
if (err != ESP_OK) { if (err != ESP_OK) {
@@ -218,6 +223,7 @@ void wifi_prov_scheme_ble_event_cb_free_btdm(void *user_data, wifi_prov_cb_event
} else { } else {
ESP_LOGI(TAG, "BTDM memory released"); ESP_LOGI(TAG, "BTDM memory released");
} }
#endif
#endif #endif
break; break;
@@ -229,9 +235,10 @@ void wifi_prov_scheme_ble_event_cb_free_btdm(void *user_data, wifi_prov_cb_event
/* Used when BT is not needed by application */ /* Used when BT is not needed by application */
void wifi_prov_scheme_ble_event_cb_free_bt(void *user_data, wifi_prov_cb_event_t event, void *event_data) void wifi_prov_scheme_ble_event_cb_free_bt(void *user_data, wifi_prov_cb_event_t event, void *event_data)
{ {
esp_err_t err;
switch (event) { switch (event) {
case WIFI_PROV_INIT: case WIFI_PROV_INIT:
#ifdef CONFIG_BT_CONTROLLER_ENABLED
esp_err_t err;
/* Release BT memory, as we need only BLE */ /* Release BT memory, as we need only BLE */
err = esp_bt_mem_release(ESP_BT_MODE_CLASSIC_BT); err = esp_bt_mem_release(ESP_BT_MODE_CLASSIC_BT);
if (err != ESP_OK) { if (err != ESP_OK) {
@@ -239,6 +246,7 @@ void wifi_prov_scheme_ble_event_cb_free_bt(void *user_data, wifi_prov_cb_event_t
} else { } else {
ESP_LOGI(TAG, "BT memory released"); ESP_LOGI(TAG, "BT memory released");
} }
#endif
break; break;
default: default:
@@ -249,10 +257,11 @@ void wifi_prov_scheme_ble_event_cb_free_bt(void *user_data, wifi_prov_cb_event_t
/* Used when BLE is not needed by application */ /* Used when BLE is not needed by application */
void wifi_prov_scheme_ble_event_cb_free_ble(void *user_data, wifi_prov_cb_event_t event, void *event_data) void wifi_prov_scheme_ble_event_cb_free_ble(void *user_data, wifi_prov_cb_event_t event, void *event_data)
{ {
esp_err_t err;
switch (event) { switch (event) {
case WIFI_PROV_DEINIT: case WIFI_PROV_DEINIT:
#ifndef CONFIG_WIFI_PROV_KEEP_BLE_ON_AFTER_PROV #ifndef CONFIG_WIFI_PROV_KEEP_BLE_ON_AFTER_PROV
#ifdef CONFIG_BT_CONTROLLER_ENABLED
esp_err_t err;
/* Release memory used by BLE stack */ /* Release memory used by BLE stack */
err = esp_bt_mem_release(ESP_BT_MODE_BLE); err = esp_bt_mem_release(ESP_BT_MODE_BLE);
if (err != ESP_OK) { if (err != ESP_OK) {
@@ -260,6 +269,7 @@ void wifi_prov_scheme_ble_event_cb_free_ble(void *user_data, wifi_prov_cb_event_
} else { } else {
ESP_LOGI(TAG, "BLE memory released"); ESP_LOGI(TAG, "BLE memory released");
} }
#endif
#endif #endif
break; break;

View File

@@ -0,0 +1,6 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(host_hci_uart)

View File

@@ -0,0 +1,85 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- |
ESP-IDF UART HCI Host
=====================
This is a Bluetooth Host use UART as HCI IO. This require the UART device support RTS/CTS mandatory.
It can do the configuration of UART baudrate by menuconfig.
## Example Layout
This example is modified based on [bt_discovery](../../classic_bt/bt_discovery), and all modifications are listed below:
- Removed all dependencies on controller from `main.c`.
```
#include "esp_bt.h"
...
ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_BLE));
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
if ((ret = esp_bt_controller_init(&bt_cfg)) != ESP_OK) {
ESP_LOGE(GAP_TAG, "%s initialize controller failed: %s", __func__, esp_err_to_name(ret));
return;
}
if ((ret = esp_bt_controller_enable(ESP_BT_MODE_CLASSIC_BT)) != ESP_OK) {
ESP_LOGE(GAP_TAG, "%s enable controller failed: %s", __func__, esp_err_to_name(ret));
return;
}
```
- Add support for uart driver: `uart_driver.c` and `uart_driver.h`.
- Initialize UART driver in `main.c`.
```
#include "esp_hci_api.h"
#include "uart_driver.h"
...
/* initialize HCI TRANSPORT first */
hci_uart_open();
/* get HCI driver operations */
esp_bluedroid_hci_driver_operations_t operations = {
.send = hci_uart_send,
.check_send_available = hci_check_send_available,
.register_host_callback = hci_register_host_callback,
};
esp_bluedroid_attach_hci_driver(&operations);
```
## How to use example
### Hardware Required
This example should be able to run on any commonly available ESP development board. To connect UART to another board running a Bluetooth controller. For example, [controller_hci_uart_esp32](../../../hci/controller_hci_uart_esp32).
### Configure the project
```
idf.py menuconfig
```
- UART baudrate can be configured in `Example Configuration > UART Baudrate for HCI`
### Build and Flash
Build the project and flash it to the board, then run monitor tool to view serial output:
```
idf.py -p PORT flash monitor
```
(Replace PORT with the name of the serial port to use.)
(To exit the serial monitor, type ``Ctrl-]``.)
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
## Troubleshooting

View File

@@ -0,0 +1,3 @@
idf_component_register(SRCS "main.c"
"uart_driver.c"
INCLUDE_DIRS ".")

View File

@@ -0,0 +1,8 @@
menu "Example Configuration"
config EXAMPLE_HCI_UART_BAUDRATE
int "UART Baudrate for HCI"
range 115200 921600
default 921600
help
UART Baudrate for HCI. Please use standard baudrate.
endmenu

View File

@@ -0,0 +1,306 @@
/*
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/****************************************************************************
*
* This file is for Classic Bluetooth device and service discovery Demo.
*
****************************************************************************/
#include <stdint.h>
#include <string.h>
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "esp_system.h"
#include "esp_log.h"
#include "esp_bt_main.h"
#include "esp_bt_device.h"
#include "esp_gap_bt_api.h"
#include "esp_bluedroid_hci.h"
#include "uart_driver.h"
#define GAP_TAG "GAP"
typedef enum {
APP_GAP_STATE_IDLE = 0,
APP_GAP_STATE_DEVICE_DISCOVERING,
APP_GAP_STATE_DEVICE_DISCOVER_COMPLETE,
APP_GAP_STATE_SERVICE_DISCOVERING,
APP_GAP_STATE_SERVICE_DISCOVER_COMPLETE,
} app_gap_state_t;
typedef struct {
bool dev_found;
uint8_t bdname_len;
uint8_t eir_len;
uint8_t rssi;
uint32_t cod;
uint8_t eir[ESP_BT_GAP_EIR_DATA_LEN];
uint8_t bdname[ESP_BT_GAP_MAX_BDNAME_LEN + 1];
esp_bd_addr_t bda;
app_gap_state_t state;
} app_gap_cb_t;
static app_gap_cb_t m_dev_info;
static char *bda2str(esp_bd_addr_t bda, char *str, size_t size)
{
if (bda == NULL || str == NULL || size < 18) {
return NULL;
}
uint8_t *p = bda;
sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
p[0], p[1], p[2], p[3], p[4], p[5]);
return str;
}
static char *uuid2str(esp_bt_uuid_t *uuid, char *str, size_t size)
{
if (uuid == NULL || str == NULL) {
return NULL;
}
if (uuid->len == 2 && size >= 5) {
sprintf(str, "%04x", uuid->uuid.uuid16);
} else if (uuid->len == 4 && size >= 9) {
sprintf(str, "%08"PRIx32, uuid->uuid.uuid32);
} else if (uuid->len == 16 && size >= 37) {
uint8_t *p = uuid->uuid.uuid128;
sprintf(str, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
p[15], p[14], p[13], p[12], p[11], p[10], p[9], p[8],
p[7], p[6], p[5], p[4], p[3], p[2], p[1], p[0]);
} else {
return NULL;
}
return str;
}
static bool get_name_from_eir(uint8_t *eir, uint8_t *bdname, uint8_t *bdname_len)
{
uint8_t *rmt_bdname = NULL;
uint8_t rmt_bdname_len = 0;
if (!eir) {
return false;
}
rmt_bdname = esp_bt_gap_resolve_eir_data(eir, ESP_BT_EIR_TYPE_CMPL_LOCAL_NAME, &rmt_bdname_len);
if (!rmt_bdname) {
rmt_bdname = esp_bt_gap_resolve_eir_data(eir, ESP_BT_EIR_TYPE_SHORT_LOCAL_NAME, &rmt_bdname_len);
}
if (rmt_bdname) {
if (rmt_bdname_len > ESP_BT_GAP_MAX_BDNAME_LEN) {
rmt_bdname_len = ESP_BT_GAP_MAX_BDNAME_LEN;
}
if (bdname) {
memcpy(bdname, rmt_bdname, rmt_bdname_len);
bdname[rmt_bdname_len] = '\0';
}
if (bdname_len) {
*bdname_len = rmt_bdname_len;
}
return true;
}
return false;
}
static void update_device_info(esp_bt_gap_cb_param_t *param)
{
char bda_str[18];
uint32_t cod = 0;
int32_t rssi = -129; /* invalid value */
uint8_t *bdname = NULL;
uint8_t bdname_len = 0;
uint8_t *eir = NULL;
uint8_t eir_len = 0;
esp_bt_gap_dev_prop_t *p;
ESP_LOGI(GAP_TAG, "Device found: %s", bda2str(param->disc_res.bda, bda_str, 18));
for (int i = 0; i < param->disc_res.num_prop; i++) {
p = param->disc_res.prop + i;
switch (p->type) {
case ESP_BT_GAP_DEV_PROP_COD:
cod = *(uint32_t *)(p->val);
ESP_LOGI(GAP_TAG, "--Class of Device: 0x%"PRIx32, cod);
break;
case ESP_BT_GAP_DEV_PROP_RSSI:
rssi = *(int8_t *)(p->val);
ESP_LOGI(GAP_TAG, "--RSSI: %"PRId32, rssi);
break;
case ESP_BT_GAP_DEV_PROP_BDNAME:
bdname_len = (p->len > ESP_BT_GAP_MAX_BDNAME_LEN) ? ESP_BT_GAP_MAX_BDNAME_LEN :
(uint8_t)p->len;
bdname = (uint8_t *)(p->val);
break;
case ESP_BT_GAP_DEV_PROP_EIR: {
eir_len = p->len;
eir = (uint8_t *)(p->val);
break;
}
default:
break;
}
}
/* search for device with Major device type "PHONE" or "Audio/Video" in COD */
app_gap_cb_t *p_dev = &m_dev_info;
if (p_dev->dev_found) {
return;
}
if (!esp_bt_gap_is_valid_cod(cod) ||
(!(esp_bt_gap_get_cod_major_dev(cod) == ESP_BT_COD_MAJOR_DEV_PHONE) &&
!(esp_bt_gap_get_cod_major_dev(cod) == ESP_BT_COD_MAJOR_DEV_AV))) {
return;
}
memcpy(p_dev->bda, param->disc_res.bda, ESP_BD_ADDR_LEN);
p_dev->dev_found = true;
p_dev->cod = cod;
p_dev->rssi = rssi;
if (bdname_len > 0) {
memcpy(p_dev->bdname, bdname, bdname_len);
p_dev->bdname[bdname_len] = '\0';
p_dev->bdname_len = bdname_len;
}
if (eir_len > 0) {
memcpy(p_dev->eir, eir, eir_len);
p_dev->eir_len = eir_len;
}
if (p_dev->bdname_len == 0) {
get_name_from_eir(p_dev->eir, p_dev->bdname, &p_dev->bdname_len);
}
ESP_LOGI(GAP_TAG, "Found a target device, address %s, name %s", bda_str, p_dev->bdname);
p_dev->state = APP_GAP_STATE_DEVICE_DISCOVER_COMPLETE;
ESP_LOGI(GAP_TAG, "Cancel device discovery ...");
esp_bt_gap_cancel_discovery();
}
static void bt_app_gap_init(void)
{
app_gap_cb_t *p_dev = &m_dev_info;
memset(p_dev, 0, sizeof(app_gap_cb_t));
p_dev->state = APP_GAP_STATE_IDLE;
}
static void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param)
{
app_gap_cb_t *p_dev = &m_dev_info;
char bda_str[18];
char uuid_str[37];
switch (event) {
case ESP_BT_GAP_DISC_RES_EVT: {
update_device_info(param);
break;
}
case ESP_BT_GAP_DISC_STATE_CHANGED_EVT: {
if (param->disc_st_chg.state == ESP_BT_GAP_DISCOVERY_STOPPED) {
ESP_LOGI(GAP_TAG, "Device discovery stopped.");
if ( (p_dev->state == APP_GAP_STATE_DEVICE_DISCOVER_COMPLETE ||
p_dev->state == APP_GAP_STATE_DEVICE_DISCOVERING)
&& p_dev->dev_found) {
p_dev->state = APP_GAP_STATE_SERVICE_DISCOVERING;
ESP_LOGI(GAP_TAG, "Discover services ...");
esp_bt_gap_get_remote_services(p_dev->bda);
}
} else if (param->disc_st_chg.state == ESP_BT_GAP_DISCOVERY_STARTED) {
ESP_LOGI(GAP_TAG, "Discovery started.");
}
break;
}
case ESP_BT_GAP_RMT_SRVCS_EVT: {
if (memcmp(param->rmt_srvcs.bda, p_dev->bda, ESP_BD_ADDR_LEN) == 0 &&
p_dev->state == APP_GAP_STATE_SERVICE_DISCOVERING) {
p_dev->state = APP_GAP_STATE_SERVICE_DISCOVER_COMPLETE;
if (param->rmt_srvcs.stat == ESP_BT_STATUS_SUCCESS) {
ESP_LOGI(GAP_TAG, "Services for device %s found", bda2str(p_dev->bda, bda_str, 18));
for (int i = 0; i < param->rmt_srvcs.num_uuids; i++) {
esp_bt_uuid_t *u = param->rmt_srvcs.uuid_list + i;
ESP_LOGI(GAP_TAG, "--%s", uuid2str(u, uuid_str, 37));
}
} else {
ESP_LOGI(GAP_TAG, "Services for device %s not found", bda2str(p_dev->bda, bda_str, 18));
}
}
break;
}
case ESP_BT_GAP_RMT_SRVC_REC_EVT:
default: {
ESP_LOGI(GAP_TAG, "event: %d", event);
break;
}
}
return;
}
static void bt_app_gap_start_up(void)
{
/* register GAP callback function */
esp_bt_gap_register_callback(bt_app_gap_cb);
char *dev_name = "ESP_GAP_INQRUIY";
esp_bt_dev_set_device_name(dev_name);
/* set discoverable and connectable mode, wait to be connected */
esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE);
/* inititialize device information and status */
bt_app_gap_init();
/* start to discover nearby Bluetooth devices */
app_gap_cb_t *p_dev = &m_dev_info;
p_dev->state = APP_GAP_STATE_DEVICE_DISCOVERING;
esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, 10, 0);
}
void app_main(void)
{
/* Initialize NVS — it is used to store PHY calibration data and save key-value pairs in flash memory*/
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK( ret );
/* initialize HCI TRANSPORT first */
hci_uart_open();
/* get HCI driver operations */
esp_bluedroid_hci_driver_operations_t operations = {
.send = hci_uart_send,
.check_send_available = hci_check_send_available,
.register_host_callback = hci_register_host_callback,
};
esp_bluedroid_attach_hci_driver(&operations);
esp_bluedroid_config_t bluedroid_cfg = BT_BLUEDROID_INIT_CONFIG_DEFAULT();
if ((ret = esp_bluedroid_init_with_cfg(&bluedroid_cfg)) != ESP_OK) {
ESP_LOGE(GAP_TAG, "%s initialize bluedroid failed: %s", __func__, esp_err_to_name(ret));
return;
}
if ((ret = esp_bluedroid_enable()) != ESP_OK) {
ESP_LOGE(GAP_TAG, "%s enable bluedroid failed: %s", __func__, esp_err_to_name(ret));
return;
}
bt_app_gap_start_up();
}

View File

@@ -0,0 +1,165 @@
/*
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/uart.h"
#include "esp_log.h"
#include "esp_attr.h"
#include "esp_bluedroid_hci.h"
#include "uart_driver.h"
#define TAG "UART_HCI"
#define UART_NO (1)
#define UART_BUF_SZ (1024)
#define UART_TX_PIN (5)
#define UART_RX_PIN (18)
#define UART_RTS_PIN (19)
#define UART_CTS_PIN (23)
enum {
UART_RX_TYPE = 0,
UART_RX_LEN,
UART_RX_DATA,
};
enum {
DATA_TYPE_COMMAND = 1,
DATA_TYPE_ACL = 2,
DATA_TYPE_SCO = 3,
DATA_TYPE_EVENT = 4
};
TaskHandle_t s_rx_task_hdl;
esp_bluedroid_hci_driver_callbacks_t s_callback = { 0 };
static void IRAM_ATTR hci_uart_rx_task(void *arg)
{
uint8_t buf[1026];
int len_now_read = -1;
uint32_t len_to_read = 1;
uint32_t len_total_read = 0;
uint8_t rx_st = UART_RX_TYPE;
while (1) {
len_now_read = uart_read_bytes(UART_NO, &buf[len_total_read], len_to_read, portMAX_DELAY);
assert(len_now_read == len_to_read);
len_total_read += len_now_read;
switch (rx_st) {
case UART_RX_TYPE: {
assert(buf[0] >= DATA_TYPE_ACL && buf[0] <= DATA_TYPE_EVENT);
if (buf[0] == DATA_TYPE_ACL) {
len_to_read = 4;
} else if (buf[0] == DATA_TYPE_SCO) {
len_to_read = 3;
} else if (buf[0] == DATA_TYPE_EVENT) {
len_to_read = 2;
} else {
assert(0);
}
rx_st = UART_RX_LEN;
}
break;
case UART_RX_LEN: {
if (buf[0] == DATA_TYPE_ACL) {
len_to_read = buf[3] | (buf[4] << 8);
} else if (buf[0] == DATA_TYPE_SCO) {
len_to_read = buf[3];
} else if (buf[0] == DATA_TYPE_EVENT) {
len_to_read = buf[2];
} else {
assert(0);
}
rx_st = UART_RX_DATA;
}
break;
case UART_RX_DATA: {
if (s_callback.notify_host_recv) {
s_callback.notify_host_recv(buf, len_total_read);
}
rx_st = UART_RX_TYPE;
len_to_read = 1;
len_total_read = 0;
}
break;
default: {
assert(0);
break;
}
}
}
vTaskDelete(NULL);
}
void hci_uart_send(uint8_t *buf, uint16_t len)
{
uint8_t *p = buf;
int len_write = 0;
while (len) {
len_write = uart_write_bytes(UART_NO, p, len);
assert(len_write > 0);
len -= len_write;
p += len_write;
}
}
bool hci_check_send_available(void)
{
return true;
}
esp_err_t hci_register_host_callback(const esp_bluedroid_hci_driver_callbacks_t *callback)
{
s_callback.notify_host_send_available = callback->notify_host_send_available;
s_callback.notify_host_recv = callback->notify_host_recv;
return ESP_OK;
}
void hci_uart_open(void)
{
uart_config_t uart_config = {
.baud_rate = CONFIG_EXAMPLE_HCI_UART_BAUDRATE,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS,
.source_clk = UART_SCLK_DEFAULT,
.rx_flow_ctrl_thresh = UART_HW_FIFO_LEN(UART_NO) - 1,
};
int intr_alloc_flags = 0;
#if CONFIG_UART_ISR_IN_IRAM
intr_alloc_flags = ESP_INTR_FLAG_IRAM;
#endif
ESP_ERROR_CHECK(uart_driver_install(UART_NO, UART_BUF_SZ * 2, UART_BUF_SZ * 2, 0, NULL, intr_alloc_flags));
ESP_ERROR_CHECK(uart_param_config(UART_NO, &uart_config));
ESP_ERROR_CHECK(uart_set_pin(UART_NO, UART_TX_PIN, UART_RX_PIN, UART_RTS_PIN, UART_CTS_PIN));
xTaskCreate(hci_uart_rx_task, "hci_uart_rx_task", 2048, NULL, 12, &s_rx_task_hdl);
}
void hci_uart_close(void)
{
if (s_rx_task_hdl) {
vTaskDelete(s_rx_task_hdl);
}
uart_driver_delete(UART_NO);
memset(&s_callback, 0, sizeof(esp_bluedroid_hci_driver_callbacks_t));
}

View File

@@ -0,0 +1,46 @@
/*
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#ifndef __UART_DRIVER_H__
#define __UART_DRIVER_H__
#include <stdint.h>
#include <stdbool.h>
#include "esp_bluedroid_hci.h"
/**
* @brief open HCI transport of uart
*/
void hci_uart_open(void);
/**
* @brief close HCI transport of uart
*/
void hci_uart_close(void);
/**
* @brief send data from host to HCI transport
*
* @param[in] data pointer to data buffer
* @param[in] len length of data
*/
void hci_uart_send(uint8_t *data, uint16_t len);
/**
* @brief host checks whether it can send data to HCI transport
*
* @return true if host can send data, false otherwise
*/
bool hci_check_send_available(void);
/**
* @brief register host callbacks
*
* @param[in] callback HCI driver callbacks
*/
esp_err_t hci_register_host_callback(const esp_bluedroid_hci_driver_callbacks_t *callback);
#endif /* __UART_DRIVER_H__ */

View File

@@ -0,0 +1,4 @@
CONFIG_BT_CONTROLLER_DISABLED=y
CONFIG_BT_ENABLED=y
CONFIG_BT_BLUEDROID_ENABLED=y
CONFIG_BT_CLASSIC_ENABLED=y

View File

@@ -272,7 +272,7 @@ void app_main(void)
#endif // CONFIG_BT_ENABLED #endif // CONFIG_BT_ENABLED
#endif // CONFIG_EXAMPLE_CONNECT_WIFI #endif // CONFIG_EXAMPLE_CONNECT_WIFI
#if CONFIG_BT_BLE_ENABLED || CONFIG_BT_NIMBLE_ENABLED #if CONFIG_BT_CONTROLLER_ENABLED && (CONFIG_BT_BLE_ENABLED || CONFIG_BT_NIMBLE_ENABLED)
ESP_ERROR_CHECK(esp_ble_helper_init()); ESP_ERROR_CHECK(esp_ble_helper_init());
#endif #endif

View File

@@ -6,7 +6,7 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if CONFIG_BT_BLE_ENABLED || CONFIG_BT_NIMBLE_ENABLED #if CONFIG_BT_CONTROLLER_ENABLED && (CONFIG_BT_BLE_ENABLED || CONFIG_BT_NIMBLE_ENABLED)
#include "ble_api.h" #include "ble_api.h"
#include "esp_log.h" #include "esp_log.h"

View File

@@ -9,7 +9,7 @@
#include "esp_log.h" #include "esp_log.h"
#include "string.h" #include "string.h"
#if CONFIG_BT_BLE_ENABLED #if CONFIG_BT_CONTROLLER_ENABLED && CONFIG_BT_BLE_ENABLED
static const char *TAG = "bluedroid_gatts"; static const char *TAG = "bluedroid_gatts";
static prepare_type_env_t a_prepare_write_env; static prepare_type_env_t a_prepare_write_env;

View File

@@ -12,7 +12,7 @@
extern "C" { extern "C" {
#endif #endif
#if CONFIG_BT_BLE_ENABLED || CONFIG_BT_NIMBLE_ENABLED #if CONFIG_BT_CONTROLLER_ENABLED && (CONFIG_BT_BLE_ENABLED || CONFIG_BT_NIMBLE_ENABLED)
esp_err_t esp_ble_helper_init(void); esp_err_t esp_ble_helper_init(void);
#endif #endif

View File

@@ -9,7 +9,7 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#if CONFIG_BT_BLE_ENABLED #if CONFIG_BT_CONTROLLER_ENABLED && CONFIG_BT_BLE_ENABLED
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {