Merge branch 'bt/add_host_only_mode' into 'master'

bt: Added BlueDroid-Only mode to use BlueDroid host only without Bluetooth Controller

See merge request espressif/esp-idf!25319
This commit is contained in:
Jiang Jiang Jian 2023-11-02 10:58:32 +08:00
commit 6e0a8434a7
38 changed files with 972 additions and 57 deletions

View File

@ -70,31 +70,36 @@ if(CONFIG_BT_ENABLED)
set(srcs "")
set(include_dirs "")
set(ldfragments "linker.lf")
if(CONFIG_BT_CONTROLLER_ENABLED)
if(CONFIG_IDF_TARGET_ESP32)
list(APPEND srcs "controller/esp32/bt.c"
"controller/esp32/hli_api.c"
"controller/esp32/hli_vectors.S")
if(CONFIG_IDF_TARGET_ESP32)
list(APPEND srcs "controller/esp32/bt.c"
"controller/esp32/hli_api.c"
"controller/esp32/hli_vectors.S")
elseif(CONFIG_IDF_TARGET_ESP32C3)
list(APPEND srcs "controller/esp32c3/bt.c")
elseif(CONFIG_IDF_TARGET_ESP32C3)
list(APPEND srcs "controller/esp32c3/bt.c")
elseif(CONFIG_IDF_TARGET_ESP32S3)
list(APPEND srcs "controller/esp32c3/bt.c")
elseif(CONFIG_IDF_TARGET_ESP32S3)
list(APPEND srcs "controller/esp32c3/bt.c")
elseif(CONFIG_IDF_TARGET_ESP32C2)
list(APPEND srcs "controller/esp32c2/bt.c")
elseif(CONFIG_IDF_TARGET_ESP32C2)
set(ldfragments "linker.lf.esp32c2")
list(APPEND srcs "controller/esp32c2/bt.c")
elseif(CONFIG_IDF_TARGET_ESP32C2)
set(ldfragments "linker.lf.esp32c2")
list(APPEND srcs "controller/esp32c2/bt.c")
elseif(CONFIG_IDF_TARGET_ESP32C6)
list(APPEND srcs "controller/esp32c6/bt.c")
elseif(CONFIG_IDF_TARGET_ESP32C6)
list(APPEND srcs "controller/esp32c6/bt.c")
elseif(CONFIG_IDF_TARGET_ESP32H2)
list(APPEND srcs "controller/esp32h2/bt.c")
endif()
list(APPEND include_dirs ${target_specific_include_dirs})
elseif(CONFIG_IDF_TARGET_ESP32H2)
list(APPEND srcs "controller/esp32h2/bt.c")
endif()
list(APPEND include_dirs ${target_specific_include_dirs})
# Common
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"
"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_main.c"
"host/bluedroid/api/esp_gap_ble_api.c"

View File

@ -1,9 +1,8 @@
menu "Bluetooth"
visible if SOC_BT_SUPPORTED
config BT_ENABLED
bool "Bluetooth"
depends on SOC_BT_SUPPORTED && !APP_NO_BLOBS
depends on !APP_NO_BLOBS
help
Select this option to enable Bluetooth and show the submenu with Bluetooth configuration choices.
@ -22,10 +21,12 @@ menu "Bluetooth"
config BT_NIMBLE_ENABLED
bool "NimBLE - BLE only"
depends on BT_CONTROLLER_ENABLED
help
This option is recommended for BLE only usecases to save on memory
config BT_CONTROLLER_ONLY
depends on SOC_BT_SUPPORTED
bool "Disabled"
help
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
config BT_CONTROLLER_ENABLED
depends on SOC_BT_SUPPORTED
bool "Enabled"
help
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
*/
@ -29,6 +29,12 @@
#define UC_BT_STACK_NO_LOG FALSE
#endif
#ifdef CONFIG_BT_CONTROLLER_ENABLED
#define UC_BT_CONTROLLER_INCLUDED TRUE
#else
#define UC_BT_CONTROLLER_INCLUDED FALSE
#endif
/**********************************************************
* Thread/Task reference
**********************************************************/

View File

@ -49,7 +49,7 @@ config BT_BLUEDROID_ESP_COEX_VSC
config BT_CLASSIC_ENABLED
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
help
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
bool "Update RPA to Controller"
depends on BT_BLUEDROID_ENABLED && !SOC_BLE_DEVICE_PRIVACY_SUPPORTED
default n
depends on (BT_BLUEDROID_ENABLED && ((BT_CONTROLLER_ENABLED && !SOC_BLE_DEVICE_PRIVACY_SUPPORTED) || BT_CONTROLLER_DISABLED))
default n if (BT_CONTROLLER_ENABLED && !SOC_BLE_DEVICE_PRIVACY_SUPPORTED)
default y if BT_CONTROLLER_DISABLED
help
This enables controller RPA list function.
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
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
help
This enables BLE 5.0 features, this option only support esp32c3/esp32s3 chip
config BT_BLE_42_FEATURES_SUPPORTED
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
help
This enables BLE 4.2 features.
config BT_BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER
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
help
This enables BLE periodic advertising sync transfer feature
config BT_BLE_FEAT_PERIODIC_ADV_ENH
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
help
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 "btc/btc_task.h"
#include "btc/btc_main.h"
#if (BT_CONTROLLER_INCLUDED == TRUE)
#include "esp_bt.h"
#endif
#include "osi/future.h"
#include "osi/allocator.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;
}
#if (BT_CONTROLLER_INCLUDED == TRUE)
if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) {
LOG_ERROR("Controller not initialised\n");
return ESP_ERR_INVALID_STATE;
}
#endif
if (bd_already_init) {
LOG_ERROR("Bluedroid already initialised\n");

View File

@ -21,7 +21,9 @@
#include "common/bt_target.h"
#include "common/bt_defs.h"
#include "device/bdaddr.h"
#if (BT_CONTROLLER_INCLUDED == TRUE)
#include "esp_bt.h"
#endif
#include "esp_hf_ag_api.h"
#include "esp_err.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)
#include "stack/gap_api.h"
#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_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);
extern void sdpu_uuid16_to_uuid128(UINT16 uuid16, UINT8 *p_uuid128);
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] = {
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 (free_eir_length >= 3) {
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;
p_bta_dm_eir_cfg->bta_dm_eir_inq_tx_power = btm_tx_power[max_power_level];
UINT8_TO_STREAM(p, 2); /* Length field */

View File

@ -9,6 +9,7 @@
#include "osi/allocator.h"
#include "stack/bt_types.h"
#include "common/bt_defs.h"
#include "common/bt_target.h"
#include "bta/bta_api.h"
#include "bta/bta_dm_co.h"
#include "btc/btc_task.h"
@ -23,7 +24,9 @@
#include "osi/mutex.h"
#include "osi/thread.h"
#include "osi/pkt_queue.h"
#if (BT_CONTROLLER_INCLUDED == TRUE)
#include "esp_bt.h"
#endif
#if (BLE_INCLUDED == 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) {
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);
#else
bta_adv_data->tx_power = 0;
#endif
}
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_defs.h"
#include "device/bdaddr.h"
#if (BT_CONTROLLER_INCLUDED == TRUE)
#include "esp_bt.h"
#endif
#include "esp_hf_ag_api.h"
#include "osi/allocator.h"
@ -328,12 +330,14 @@ bt_status_t btc_hf_init(void)
// custom initialization here
hf_local_param[idx].btc_hf_cb.initialized = true;
// set audio path
#if (BT_CONTROLLER_INCLUDED == TRUE)
#if BTM_SCO_HCI_INCLUDED
uint8_t data_path = ESP_SCO_DATA_PATH_HCI;
#else
uint8_t data_path = ESP_SCO_DATA_PATH_PCM;
#endif
esp_bredr_sco_datapath_set(data_path);
#endif
return BT_STATUS_SUCCESS;
}

View File

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

View File

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

View File

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

View File

@ -22,16 +22,20 @@
#include "hci/hci_hal.h"
#include "hci/hci_internals.h"
#include "hci/hci_layer.h"
#include "hci/hci_trans_int.h"
#include "osi/thread.h"
#include "osi/pkt_queue.h"
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
#include "osi/mutex.h"
#include "osi/alarm.h"
#endif
#if (BT_CONTROLLER_INCLUDED == TRUE)
#include "esp_bt.h"
#endif
#include "esp_bluedroid_hci.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"
#endif
@ -87,7 +91,7 @@ typedef struct {
static hci_hal_env_t hci_hal_env;
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 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);
//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;
}
@ -207,7 +211,7 @@ static uint16_t transmit_data(serial_data_type_t type,
BTTRC_DUMP_BUFFER("Transmit Pkt", data, length);
// 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
*(data) = previous_byte;
@ -590,7 +594,7 @@ static int host_recv_pkt_cb(uint8_t *data, uint16_t len)
return 0;
}
#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)
@ -625,7 +629,7 @@ ble_hs_rx_data(struct os_mbuf *om, void *arg)
}
#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_recv = host_recv_pkt_cb,
};

View File

@ -17,7 +17,10 @@
******************************************************************************/
#include <string.h>
#include "sdkconfig.h"
#include "common/bt_target.h"
#if (BT_CONTROLLER_INCLUDED == TRUE)
#include "esp_bt.h"
#endif
#include "common/bt_defs.h"
#include "common/bt_trace.h"
@ -28,6 +31,7 @@
#include "hci/hci_internals.h"
#include "hci/hci_hal.h"
#include "hci/hci_layer.h"
#include "hci/hci_trans_int.h"
#include "osi/allocator.h"
#include "hci/packet_fragmenter.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
* 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*/
BT_HDR *pkt = packet_fragmenter->fragment_current_packet();
if (pkt != NULL) {

View File

@ -21,9 +21,10 @@
#include <stdbool.h>
#include <stdint.h>
#include "common/bt_target.h"
#include "osi/pkt_queue.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"
#endif
typedef enum {
@ -85,7 +86,7 @@ typedef struct hci_hal_t {
// Gets the correct hal implementation, as compiled for.
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_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 "esp_random.h"
#include "esp_bt.h"
#include "esp_bt_main.h"
#include "esp_bt_device.h"
#include "esp_gap_ble_api.h"

View File

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

View File

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

View File

@ -6,7 +6,6 @@
#include "bt_hidd.h"
#if CONFIG_BT_HID_DEVICE_ENABLED
#include "esp_bt.h"
#include "esp_bt_defs.h"
#include "esp_bt_main.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
*/
@ -8,7 +8,9 @@
#include <freertos/FreeRTOS.h>
#include <esp_system.h>
#include <esp_log.h>
#ifdef CONFIG_BT_CONTROLLER_ENABLED
#include "esp_bt.h"
#endif
#include <esp_gap_ble_api.h>
#include <esp_gatts_api.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_err_t ret;
#ifdef CONFIG_BT_CONTROLLER_ENABLED
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
ret = esp_bt_controller_init(&bt_cfg);
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);
return ret;
}
#endif
esp_bluedroid_config_t bluedroid_cfg = BT_BLUEDROID_INIT_CONFIG_DEFAULT();
ret = esp_bluedroid_init_with_cfg(&bluedroid_cfg);
@ -307,6 +311,7 @@ esp_err_t simple_ble_stop(void)
return err;
}
ESP_LOGD(TAG, "esp_bluedroid_deinit called successfully");
#ifdef CONFIG_BT_CONTROLLER_ENABLED
err = esp_bt_controller_disable();
if (err != ESP_OK) {
return ESP_FAIL;
@ -321,7 +326,7 @@ esp_err_t simple_ble_stop(void)
return ESP_FAIL;
}
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());
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 APB_CLK_FREQ
#define APB_CLK_FREQ ( 40*1000000 )
#define MODEM_REQUIRED_MIN_APB_CLK_FREQ ( 80*1000000 )
#define REF_CLK_FREQ ( 1000000 )
#define XTAL_CLK_FREQ (40*1000000)
#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
*/
@ -7,7 +7,9 @@
#include <string.h>
#include <esp_log.h>
#include <esp_err.h>
#ifdef CONFIG_BT_CONTROLLER_ENABLED
#include "esp_bt.h"
#endif
#include <protocomm.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 */
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) {
case WIFI_PROV_INIT:
#ifdef CONFIG_BT_CONTROLLER_ENABLED
esp_err_t err;
/* Release BT memory, as we need only BLE */
err = esp_bt_mem_release(ESP_BT_MODE_CLASSIC_BT);
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 {
ESP_LOGI(TAG, "BT memory released");
}
#endif
break;
case WIFI_PROV_DEINIT:
#ifndef CONFIG_WIFI_PROV_KEEP_BLE_ON_AFTER_PROV
#ifdef CONFIG_BT_CONTROLLER_ENABLED
/* Release memory used by BLE and Bluedroid host stack */
err = esp_bt_mem_release(ESP_BT_MODE_BTDM);
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 {
ESP_LOGI(TAG, "BTDM memory released");
}
#endif
#endif
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 */
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) {
case WIFI_PROV_INIT:
#ifdef CONFIG_BT_CONTROLLER_ENABLED
esp_err_t err;
/* Release BT memory, as we need only BLE */
err = esp_bt_mem_release(ESP_BT_MODE_CLASSIC_BT);
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 {
ESP_LOGI(TAG, "BT memory released");
}
#endif
break;
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 */
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) {
case WIFI_PROV_DEINIT:
#ifndef CONFIG_WIFI_PROV_KEEP_BLE_ON_AFTER_PROV
#ifdef CONFIG_BT_CONTROLLER_ENABLED
esp_err_t err;
/* Release memory used by BLE stack */
err = esp_bt_mem_release(ESP_BT_MODE_BLE);
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 {
ESP_LOGI(TAG, "BLE memory released");
}
#endif
#endif
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_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());
#endif

View File

@ -6,7 +6,7 @@
#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 "esp_log.h"

View File

@ -9,7 +9,7 @@
#include "esp_log.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 prepare_type_env_t a_prepare_write_env;

View File

@ -12,7 +12,7 @@
extern "C" {
#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);
#endif

View File

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