Эх сурвалжийг харах

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
Jiang Jiang Jian 2 жил өмнө
parent
commit
6e0a8434a7
38 өөрчлөгдсөн 972 нэмэгдсэн , 57 устгасан
  1. 23 17
      components/bt/CMakeLists.txt
  2. 4 2
      components/bt/Kconfig
  3. 7 1
      components/bt/common/include/bt_user_config.h
  4. 8 7
      components/bt/host/bluedroid/Kconfig.in
  5. 89 0
      components/bt/host/bluedroid/api/esp_bluedroid_hci.c
  6. 5 0
      components/bt/host/bluedroid/api/esp_bt_main.c
  7. 2 0
      components/bt/host/bluedroid/api/esp_hf_ag_api.c
  8. 84 0
      components/bt/host/bluedroid/api/include/api/esp_bluedroid_hci.h
  9. 11 2
      components/bt/host/bluedroid/bta/dm/bta_dm_act.c
  10. 7 0
      components/bt/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c
  11. 4 0
      components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c
  12. 6 3
      components/bt/host/bluedroid/btc/profile/std/hf_client/btc_hf_client.c
  13. 1 1
      components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h
  14. 6 0
      components/bt/host/bluedroid/common/include/common/bt_target.h
  15. 10 6
      components/bt/host/bluedroid/hci/hci_hal_h4.c
  16. 5 1
      components/bt/host/bluedroid/hci/hci_layer.c
  17. 3 2
      components/bt/host/bluedroid/hci/include/hci/hci_hal.h
  18. 47 0
      components/bt/host/bluedroid/hci/include/hci/hci_trans_int.h
  19. 0 1
      components/bt/test_apps/main/test_smp.c
  20. 0 1
      components/esp_hid/src/ble_hidd.c
  21. 0 1
      components/esp_hid/src/ble_hidh.c
  22. 0 1
      components/esp_hid/src/bt_hidd.c
  23. 7 2
      components/protocomm/src/simple_ble/simple_ble.c
  24. 1 0
      components/soc/esp32p4/include/soc/soc.h
  25. 14 4
      components/wifi_provisioning/src/scheme_ble.c
  26. 6 0
      examples/bluetooth/bluedroid/bluedroid_host_only/bluedroid_host_only_uart/CMakeLists.txt
  27. 85 0
      examples/bluetooth/bluedroid/bluedroid_host_only/bluedroid_host_only_uart/README.md
  28. 3 0
      examples/bluetooth/bluedroid/bluedroid_host_only/bluedroid_host_only_uart/main/CMakeLists.txt
  29. 8 0
      examples/bluetooth/bluedroid/bluedroid_host_only/bluedroid_host_only_uart/main/Kconfig.projbuild
  30. 306 0
      examples/bluetooth/bluedroid/bluedroid_host_only/bluedroid_host_only_uart/main/main.c
  31. 165 0
      examples/bluetooth/bluedroid/bluedroid_host_only/bluedroid_host_only_uart/main/uart_driver.c
  32. 46 0
      examples/bluetooth/bluedroid/bluedroid_host_only/bluedroid_host_only_uart/main/uart_driver.h
  33. 4 0
      examples/bluetooth/bluedroid/bluedroid_host_only/bluedroid_host_only_uart/sdkconfig.defaults
  34. 1 1
      examples/system/ota/advanced_https_ota/main/advanced_https_ota_example.c
  35. 1 1
      examples/system/ota/advanced_https_ota/main/ble_helper/ble_api.c
  36. 1 1
      examples/system/ota/advanced_https_ota/main/ble_helper/bluedroid_gatts.c
  37. 1 1
      examples/system/ota/advanced_https_ota/main/ble_helper/include/ble_api.h
  38. 1 1
      examples/system/ota/advanced_https_ota/main/ble_helper/include/bluedroid_gatts.h

+ 23 - 17
components/bt/CMakeLists.txt

@@ -70,30 +70,35 @@ 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()
+        elseif(CONFIG_IDF_TARGET_ESP32H2)
+            list(APPEND srcs "controller/esp32h2/bt.c")
+        endif()
 
-    list(APPEND include_dirs ${target_specific_include_dirs})
+        list(APPEND include_dirs ${target_specific_include_dirs})
+
+    endif()
 
     # 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"

+ 4 - 2
components/bt/Kconfig

@@ -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

+ 7 - 1
components/bt/common/include/bt_user_config.h

@@ -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
  **********************************************************/

+ 8 - 7
components/bt/host/bluedroid/Kconfig.in

@@ -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

+ 89 - 0
components/bt/host/bluedroid/api/esp_bluedroid_hci.c

@@ -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;
+}

+ 5 - 0
components/bt/host/bluedroid/api/esp_bt_main.c

@@ -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");

+ 2 - 0
components/bt/host/bluedroid/api/esp_hf_ag_api.c

@@ -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"

+ 84 - 0
components/bt/host/bluedroid/api/include/api/esp_bluedroid_hci.h

@@ -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__ */

+ 11 - 2
components/bt/host/bluedroid/bta/dm/bta_dm_act.c

@@ -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 */

+ 7 - 0
components/bt/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c

@@ -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 &&

+ 4 - 0
components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c

@@ -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;
 }
 

+ 6 - 3
components/bt/host/bluedroid/btc/profile/std/hf_client/btc_hf_client.c

@@ -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;
 }
 

+ 1 - 1
components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h

@@ -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

+ 6 - 0
components/bt/host/bluedroid/common/include/common/bt_target.h

@@ -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

+ 10 - 6
components/bt/host/bluedroid/hci/hci_hal_h4.c

@@ -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,
 };

+ 5 - 1
components/bt/host/bluedroid/hci/hci_layer.c

@@ -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) {

+ 3 - 2
components/bt/host/bluedroid/hci/include/hci/hci_hal.h

@@ -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);

+ 47 - 0
components/bt/host/bluedroid/hci/include/hci/hci_trans_int.h

@@ -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__ */

+ 0 - 1
components/bt/test_apps/main/test_smp.c

@@ -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"

+ 0 - 1
components/esp_hid/src/ble_hidd.c

@@ -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"

+ 0 - 1
components/esp_hid/src/ble_hidh.c

@@ -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"

+ 0 - 1
components/esp_hid/src/bt_hidd.c

@@ -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"

+ 7 - 2
components/protocomm/src/simple_ble/simple_ble.c

@@ -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;
 }

+ 1 - 0
components/soc/esp32p4/include/soc/soc.h

@@ -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

+ 14 - 4
components/wifi_provisioning/src/scheme_ble.c

@@ -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;
 

+ 6 - 0
examples/bluetooth/bluedroid/bluedroid_host_only/bluedroid_host_only_uart/CMakeLists.txt

@@ -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)

+ 85 - 0
examples/bluetooth/bluedroid/bluedroid_host_only/bluedroid_host_only_uart/README.md

@@ -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

+ 3 - 0
examples/bluetooth/bluedroid/bluedroid_host_only/bluedroid_host_only_uart/main/CMakeLists.txt

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

+ 8 - 0
examples/bluetooth/bluedroid/bluedroid_host_only/bluedroid_host_only_uart/main/Kconfig.projbuild

@@ -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

+ 306 - 0
examples/bluetooth/bluedroid/bluedroid_host_only/bluedroid_host_only_uart/main/main.c

@@ -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();
+}

+ 165 - 0
examples/bluetooth/bluedroid/bluedroid_host_only/bluedroid_host_only_uart/main/uart_driver.c

@@ -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));
+}

+ 46 - 0
examples/bluetooth/bluedroid/bluedroid_host_only/bluedroid_host_only_uart/main/uart_driver.h

@@ -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__ */

+ 4 - 0
examples/bluetooth/bluedroid/bluedroid_host_only/bluedroid_host_only_uart/sdkconfig.defaults

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

+ 1 - 1
examples/system/ota/advanced_https_ota/main/advanced_https_ota_example.c

@@ -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
 

+ 1 - 1
examples/system/ota/advanced_https_ota/main/ble_helper/ble_api.c

@@ -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"

+ 1 - 1
examples/system/ota/advanced_https_ota/main/ble_helper/bluedroid_gatts.c

@@ -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;

+ 1 - 1
examples/system/ota/advanced_https_ota/main/ble_helper/include/ble_api.h

@@ -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
 

+ 1 - 1
examples/system/ota/advanced_https_ota/main/ble_helper/include/bluedroid_gatts.h

@@ -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" {