feat(ble_audio): Support running ISO & LE Audio with Bluedroid Host

This commit is contained in:
Liu Linyan
2026-05-29 17:24:54 +08:00
parent 6cd0e56ae2
commit 8dbef3bad4
223 changed files with 14714 additions and 2347 deletions
@@ -9,7 +9,7 @@
This example takes the **TMAP Call Gateway (CG)** and **Unicast Media Sender (UMS)** roles, registered together via `esp_ble_audio_tmap_register(ESP_BLE_AUDIO_TMAP_ROLE_CG | ESP_BLE_AUDIO_TMAP_ROLE_UMS)`. It scans for connectable extended advertising that carries TMAS service data with the **UMR** role bit set, connects to the first match, pairs, exchanges MTU, and then drives TMAP and VCP discovery before bringing up unicast audio.
The host stack is NimBLE. The example uses the ESP-BLE-AUDIO library pieces for: CAP initiator with the BAP Unicast Client (LC3 preset 48_2_1, sink direction, FRONT_LEFT, MEDIA context), VCP Volume Controller, MCP server backed by the media proxy player, and CCP server registering a single GTBS bearer (`Generic TBS`, UCI `un000`, `tel,wechat` URI schemes, 5G technology). A periodic TX scheduler in the ISO task feeds dummy ISO SDUs filled with the sequence number. Device name is set to `TMAP Central`.
The example uses the ESP-BLE-AUDIO library pieces for: CAP initiator with the BAP Unicast Client (LC3 preset 48_2_1, sink direction, FRONT_LEFT, MEDIA context), VCP Volume Controller, MCP server backed by the media proxy player, and CCP server registering a single GTBS bearer (`Generic TBS`, UCI `un000`, `tel,wechat` URI schemes, 5G technology). A periodic TX scheduler in the ISO task feeds dummy ISO SDUs filled with the sequence number. Device name is set to `TMAP Central`.
## Requirements
@@ -30,11 +30,24 @@ Just-Works pairing (LE Secure Connections, no MITM, no I/O capability) with bond
## Build & Flash
The base `sdkconfig.defaults` defaults to the **Bluedroid** host; idf.py automatically merges the per-target overlay (`sdkconfig.defaults.$IDF_TARGET`). To build with **NimBLE** host instead, layer `sdkconfig.defaults.nimble` on top via `-DSDKCONFIG_DEFAULTS`.
### Bluedroid host (default)
```bash
idf.py set-target esp32h4
idf.py -p PORT flash monitor
```
### NimBLE host
```bash
idf.py set-target esp32h4
idf.py -DSDKCONFIG_DEFAULTS="sdkconfig.defaults;sdkconfig.defaults.esp32h4;sdkconfig.defaults.nimble" -p PORT flash monitor
```
For `esp32s31`, replace the chip overlay accordingly.
(Exit serial monitor with `Ctrl-]`.)
## Example Flow
@@ -4,5 +4,12 @@ set(srcs "cap_initiator.c"
"vcp_vol_ctlr.c"
"main.c")
if(CONFIG_BT_BLUEDROID_ENABLED)
list(APPEND srcs "bluedroid/central.c")
else()
list(APPEND srcs "nimble/central.c")
endif()
idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS "."
REQUIRES bt nvs_flash)
@@ -0,0 +1,193 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "esp_log.h"
#include "esp_err.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "esp_gap_ble_api.h"
#include "esp_gattc_api.h"
#include "esp_ble_audio_common_api.h"
#include "tmap_central.h"
static SemaphoreHandle_t scan_sem;
/* Controller status latched by gap_event_handler for EXAMPLE_WAIT_API_CHECK. */
static esp_bt_status_t scan_op_status;
#define WAIT_API(_call) EXAMPLE_WAIT_API_CHECK(_call, scan_sem, portMAX_DELAY, scan_op_status)
/* Cached peer address. Bluedroid's pairing and disconnect APIs key off
* bd_addr rather than conn_handle, so we stash the addr at conn_create
* time and reuse it in pairing_start / security_failed_recover. */
static esp_bd_addr_t peer_bda;
static esp_ble_ext_scan_params_t ext_scan_params = {
.own_addr_type = BLE_ADDR_TYPE_PUBLIC,
.filter_policy = BLE_SCAN_FILTER_ALLOW_ALL,
.scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE,
.cfg_mask = ESP_BLE_GAP_EXT_SCAN_CFG_UNCODE_MASK,
.uncoded_cfg = {
.scan_type = BLE_SCAN_TYPE_PASSIVE,
.scan_interval = SCAN_INTERVAL,
.scan_window = SCAN_WINDOW,
},
};
static void gap_event_handler(esp_gap_ble_cb_event_t event,
esp_ble_gap_cb_param_t *param)
{
switch (event) {
case ESP_GAP_BLE_SET_EXT_SCAN_PARAMS_COMPLETE_EVT:
scan_op_status = param->set_ext_scan_params.status;
xSemaphoreGive(scan_sem);
break;
case ESP_GAP_BLE_EXT_SCAN_START_COMPLETE_EVT:
scan_op_status = param->ext_scan_start.status;
xSemaphoreGive(scan_sem);
break;
case ESP_GAP_BLE_EXT_SCAN_STOP_COMPLETE_EVT:
scan_op_status = param->ext_scan_stop.status;
xSemaphoreGive(scan_sem);
break;
/* SMP request handling for Just Works pairing (IO_CAP=NONE). NC_REQ
* still fires under LE Secure Connections — auto-accept. We never get
* SEC_REQ here because the central initiates via esp_ble_set_encryption. */
case ESP_GAP_BLE_NC_REQ_EVT:
esp_ble_confirm_reply(param->ble_security.ble_req.bd_addr, true);
break;
/* AUTH_CMPL has no BTA channel — app must forward it. EXT_ADV_REPORT
* is forwarded by adapter's BTA path, don't re-post here. */
case ESP_GAP_BLE_AUTH_CMPL_EVT:
esp_ble_audio_gap_app_post_event(event, param);
break;
default:
break;
}
}
int app_host_init(void)
{
esp_err_t err;
scan_sem = xSemaphoreCreateBinary();
if (scan_sem == NULL) {
ESP_LOGE(TAG, "Failed to create scan semaphore");
return -1;
}
err = esp_ble_gap_register_callback(gap_event_handler);
if (err) {
ESP_LOGE(TAG, "Failed to register GAP callback, err %d", err);
vSemaphoreDelete(scan_sem);
return err;
}
return 0;
}
int set_device_name(void)
{
return esp_ble_gap_set_device_name(LOCAL_DEVICE_NAME);
}
int ext_scan_start(void)
{
WAIT_API(esp_ble_gap_set_ext_scan_params(&ext_scan_params));
WAIT_API(esp_ble_gap_start_ext_scan(0, 0));
ESP_LOGI(TAG, "Scanning for peripheral...");
return 0;
}
int ext_scan_stop(void)
{
WAIT_API(esp_ble_gap_stop_ext_scan());
return 0;
}
int conn_create(uint8_t addr_type, const uint8_t addr[6])
{
/* Values shared with NimBLE side via tmap_central.h for behavioral parity.
* Without prefer_ext_connect_params_set, L2CAP falls back to defaults
* and logs "No extend connection parameters set". */
const esp_ble_gap_conn_params_t conn_params = {
.scan_interval = INIT_SCAN_INTERVAL,
.scan_window = INIT_SCAN_WINDOW,
.interval_min = CONN_INTERVAL,
.interval_max = CONN_INTERVAL,
.latency = CONN_LATENCY,
.supervision_timeout = CONN_TIMEOUT,
.min_ce_len = CONN_MIN_CE_LEN,
.max_ce_len = CONN_MAX_CE_LEN,
};
esp_gatt_if_t gattc_if;
esp_err_t err;
memcpy(peer_bda, addr, sizeof(peer_bda));
err = esp_ble_gap_prefer_ext_connect_params_set(
peer_bda, ESP_BLE_GAP_PHY_1M_PREF_MASK, &conn_params, NULL, NULL);
if (err) {
ESP_LOGE(TAG, "Failed to set ext conn params, err %d", err);
return err;
}
/* Use the audio engine's GATTC if so OPEN/CONNECT events route back to
* the engine. aux_open initiates an ACL against an extended advertiser.
*
* engine returns ESP_GATT_IF_NONE (0xFF) when GATTC is not yet registered;
* feeding that into aux_open silently no-ops in BTC and no acl_connect
* event ever fires, leaving the caller in a no-scan / no-conn dead state. */
gattc_if = esp_ble_audio_bluedroid_get_gattc_if();
if (gattc_if == ESP_GATT_IF_NONE) {
ESP_LOGE(TAG, "GATTC not registered");
return ESP_ERR_INVALID_STATE;
}
return esp_ble_gattc_aux_open(gattc_if, peer_bda,
(esp_ble_addr_type_t)addr_type, true);
}
int pairing_start(uint16_t conn_handle)
{
(void)conn_handle;
return esp_ble_set_encryption(peer_bda, ESP_BLE_SEC_ENCRYPT_NO_MITM);
}
int exchange_mtu(uint16_t conn_handle)
{
(void)conn_handle;
/* The Bluedroid GATTC adapter exchanges MTU automatically when aux_open
* brings up the ACL — the MTU_UPDATED event arrives without an explicit
* kick-off. NimBLE has no such auto-exchange, so this wrapper is a no-op
* on bluedroid and a real ble_gattc_exchange_mtu on nimble. */
return 0;
}
void security_failed_recover(uint16_t conn_handle, uint8_t status)
{
(void)conn_handle;
/* Asymmetric bond state: we still hold an LTK for this peer but it
* cleared its side, so encrypt-with-cached-key times out. Drop the bond
* and tear down the link; the next reconnect runs fresh pairing. */
ESP_LOGE(TAG, "Security change failed, status %u, clearing local bond and reconnecting", status);
esp_ble_remove_bond_device(peer_bda);
esp_ble_gap_disconnect(peer_bda);
}
@@ -11,8 +11,6 @@
#include <stdio.h>
#include <stdlib.h>
#include "esp_timer.h"
#include "esp_ble_audio_bap_lc3_preset_defs.h"
#include "tmap_central.h"
@@ -7,8 +7,6 @@
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "tmap_central.h"
@@ -7,36 +7,14 @@
*/
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "nvs_flash.h"
#include "esp_system.h"
#include "esp_timer.h"
#include "host/ble_hs.h"
#include "services/gap/ble_svc_gap.h"
#include "tmap_central.h"
#include "ble_audio_example_init.h"
#include "ble_audio_example_utils.h"
#define SCAN_INTERVAL 160 /* 100ms */
#define SCAN_WINDOW 160 /* 100ms */
#define INIT_SCAN_INTERVAL 16 /* 10ms */
#define INIT_SCAN_WINDOW 16 /* 10ms */
#define CONN_INTERVAL 64 /* 64 * 1.25 = 80ms */
#define CONN_LATENCY 0
#define CONN_TIMEOUT 500 /* 500 * 10ms = 5s */
#define CONN_MAX_CE_LEN 0xFFFF
#define CONN_MIN_CE_LEN 0xFFFF
#define CONN_DURATION 10000 /* 10s */
static uint16_t default_conn_handle = CONN_HANDLE_INIT;
static bool disc_completed;
static bool disc_cancelled;
static bool mtu_exchanged;
uint16_t default_conn_handle_get(void)
@@ -68,80 +46,10 @@ static esp_ble_audio_tmap_cb_t tmap_callbacks = {
.discovery_complete = tmap_discovery_complete,
};
static void ext_scan_start(void)
{
struct ble_gap_disc_params params = {0};
uint8_t own_addr_type;
int err;
err = ble_hs_id_infer_auto(0, &own_addr_type);
if (err) {
ESP_LOGE(TAG, "Failed to determine own addr type, err %d", err);
return;
}
params.passive = 1;
params.itvl = SCAN_INTERVAL;
params.window = SCAN_WINDOW;
err = ble_gap_disc(own_addr_type, BLE_HS_FOREVER, &params,
example_audio_gap_event_cb, NULL);
if (err) {
ESP_LOGE(TAG, "Failed to start scanning, err %d", err);
return;
}
ESP_LOGI(TAG, "Scanning for peripheral...");
}
static int conn_create(ble_addr_t *dst)
{
struct ble_gap_conn_params params = {0};
uint8_t own_addr_type = 0;
int err;
err = ble_hs_id_infer_auto(0, &own_addr_type);
if (err) {
ESP_LOGE(TAG, "Failed to determine address type, err %d", err);
return err;
}
err = ble_gap_disc_cancel();
if (err) {
ESP_LOGE(TAG, "Failed to stop scanning, err %d", err);
return err;
}
disc_cancelled = true;
params.scan_itvl = INIT_SCAN_INTERVAL;
params.scan_window = INIT_SCAN_WINDOW;
params.itvl_min = CONN_INTERVAL;
params.itvl_max = CONN_INTERVAL;
params.latency = CONN_LATENCY;
params.supervision_timeout = CONN_TIMEOUT;
params.max_ce_len = CONN_MAX_CE_LEN;
params.min_ce_len = CONN_MIN_CE_LEN;
return ble_gap_connect(own_addr_type, dst, CONN_DURATION, &params,
example_audio_gap_event_cb, NULL);
}
static int pairing_start(uint16_t conn_handle)
{
return ble_gap_security_initiate(conn_handle);
}
static int exchange_mtu(uint16_t conn_handle)
{
return ble_gattc_exchange_mtu(conn_handle, NULL, NULL);
}
static bool check_and_connect(uint8_t type, const uint8_t *data,
uint8_t data_len, void *user_data)
{
esp_ble_audio_gap_app_event_t *event;
ble_addr_t dst = {0};
uint16_t tmap_role;
uint16_t uuid_val;
int err;
@@ -179,17 +87,17 @@ static bool check_and_connect(uint8_t type, const uint8_t *data,
return false; /* Stop parsing */
}
dst.type = event->ext_scan_recv.addr.type;
memcpy(dst.val, event->ext_scan_recv.addr.val, sizeof(dst.val));
err = ext_scan_stop();
if (err) {
ESP_LOGE(TAG, "Failed to stop scanning, err %d", err);
return false;
}
err = conn_create(&dst);
err = conn_create(event->ext_scan_recv.addr.type,
event->ext_scan_recv.addr.val);
if (err) {
ESP_LOGE(TAG, "Failed to create conn, err %d", err);
if (disc_cancelled) {
disc_cancelled = false;
ext_scan_start();
}
ext_scan_start();
}
return false; /* Stop parsing */
@@ -220,9 +128,7 @@ static void acl_connect(esp_ble_audio_gap_app_event_t *event)
ESP_LOGI(TAG, "Connected: handle %u role %u peer %02x:%02x:%02x:%02x:%02x:%02x",
event->acl_connect.conn_handle, event->acl_connect.role,
event->acl_connect.dst.val[5], event->acl_connect.dst.val[4],
event->acl_connect.dst.val[3], event->acl_connect.dst.val[2],
event->acl_connect.dst.val[1], event->acl_connect.dst.val[0]);
EXAMPLE_BT_ADDR_PRINT_ARGS(event->acl_connect.dst.val));
default_conn_handle = event->acl_connect.conn_handle;
@@ -240,7 +146,6 @@ static void acl_disconnect(esp_ble_audio_gap_app_event_t *event)
default_conn_handle = CONN_HANDLE_INIT;
disc_completed = false;
disc_cancelled = false;
mtu_exchanged = false;
unicast_group_delete();
@@ -253,8 +158,8 @@ static void security_change(esp_ble_iso_gap_app_event_t *event)
int err;
if (event->security_change.status) {
example_audio_security_failed_recover(TAG, event->security_change.conn_handle,
event->security_change.status);
security_failed_recover(event->security_change.conn_handle,
event->security_change.status);
return;
}
@@ -393,6 +298,12 @@ void app_main(void)
return;
}
err = app_host_init();
if (err) {
ESP_LOGE(TAG, "Failed to init host, err %d", err);
return;
}
err = esp_ble_audio_common_init(&init_info);
if (err) {
ESP_LOGE(TAG, "Failed to initialize audio, err %d", err);
@@ -431,7 +342,7 @@ void app_main(void)
return;
}
err = ble_svc_gap_device_name_set("TMAP Central");
err = set_device_name();
if (err) {
ESP_LOGE(TAG, "Failed to set device name, err %d", err);
return;
@@ -5,9 +5,6 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdlib.h>
#include <stdio.h>
#include "tmap_central.h"
int mcp_server_init(void)
@@ -0,0 +1,149 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <string.h>
#include "esp_log.h"
#include "host/ble_gap.h"
#include "host/ble_hs.h"
#include "host/ble_store.h"
#include "services/gap/ble_svc_gap.h"
#include "esp_ble_audio_common_api.h"
#include "tmap_central.h"
/* Init/conn parameters are shared with the bluedroid wrapper via tmap_central.h.
* CONN_DURATION is NimBLE-specific (ble_gap_connect's discovery timeout). */
#define CONN_DURATION 10000 /* 10s */
static int gap_event_cb(struct ble_gap_event *event, void *arg)
{
switch (event->type) {
case BLE_GAP_EVENT_EXT_DISC:
case BLE_GAP_EVENT_CONNECT:
case BLE_GAP_EVENT_DISCONNECT:
case BLE_GAP_EVENT_ENC_CHANGE:
esp_ble_audio_gap_app_post_event(event->type, event);
break;
case BLE_GAP_EVENT_MTU:
case BLE_GAP_EVENT_NOTIFY_RX:
case BLE_GAP_EVENT_NOTIFY_TX:
case BLE_GAP_EVENT_SUBSCRIBE:
esp_ble_audio_gatt_app_post_event(event->type, event);
break;
case BLE_GAP_EVENT_REPEAT_PAIRING: {
struct ble_gap_conn_desc desc = {0};
int rc = ble_gap_conn_find(event->repeat_pairing.conn_handle, &desc);
if (rc == 0) {
ble_store_util_delete_peer(&desc.peer_id_addr);
}
return BLE_GAP_REPEAT_PAIRING_RETRY;
}
default:
break;
}
return 0;
}
int app_host_init(void)
{
return 0;
}
int set_device_name(void)
{
return ble_svc_gap_device_name_set(LOCAL_DEVICE_NAME);
}
int ext_scan_start(void)
{
struct ble_gap_disc_params params = {0};
uint8_t own_addr_type;
int err;
err = ble_hs_id_infer_auto(0, &own_addr_type);
if (err) {
ESP_LOGE(TAG, "Failed to determine address type, err %d", err);
return err;
}
params.passive = 1;
params.itvl = SCAN_INTERVAL;
params.window = SCAN_WINDOW;
err = ble_gap_disc(own_addr_type, BLE_HS_FOREVER, &params,
gap_event_cb, NULL);
if (err) {
ESP_LOGE(TAG, "Failed to start scanning, err %d", err);
return err;
}
ESP_LOGI(TAG, "Scanning for peripheral...");
return 0;
}
int ext_scan_stop(void)
{
return ble_gap_disc_cancel();
}
int conn_create(uint8_t addr_type, const uint8_t addr[6])
{
struct ble_gap_conn_params params = {0};
uint8_t own_addr_type = 0;
ble_addr_t dst = {0};
int err;
err = ble_hs_id_infer_auto(0, &own_addr_type);
if (err) {
ESP_LOGE(TAG, "Failed to determine address type, err %d", err);
return err;
}
params.scan_itvl = INIT_SCAN_INTERVAL;
params.scan_window = INIT_SCAN_WINDOW;
params.itvl_min = CONN_INTERVAL;
params.itvl_max = CONN_INTERVAL;
params.latency = CONN_LATENCY;
params.supervision_timeout = CONN_TIMEOUT;
params.max_ce_len = CONN_MAX_CE_LEN;
params.min_ce_len = CONN_MIN_CE_LEN;
dst.type = addr_type;
memcpy(dst.val, addr, sizeof(dst.val));
return ble_gap_connect(own_addr_type, &dst, CONN_DURATION,
&params, gap_event_cb, NULL);
}
int pairing_start(uint16_t conn_handle)
{
return ble_gap_security_initiate(conn_handle);
}
int exchange_mtu(uint16_t conn_handle)
{
return ble_gattc_exchange_mtu(conn_handle, NULL, NULL);
}
void security_failed_recover(uint16_t conn_handle, uint8_t status)
{
struct ble_gap_conn_desc desc = {0};
int rc;
ESP_LOGE(TAG, "Security change failed, status %u, clearing local bond and reconnecting", status);
rc = ble_gap_conn_find(conn_handle, &desc);
if (rc == 0) {
ble_store_util_delete_peer(&desc.peer_id_addr);
}
ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
}
@@ -6,6 +6,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <assert.h>
#include <errno.h>
@@ -27,11 +28,42 @@
#include "esp_ble_audio_vocs_api.h"
#include "esp_ble_audio_tbs_api.h"
#include "ble_audio_example_init.h"
#include "ble_audio_example_utils.h"
#define TAG "TMAP_CEN"
#define CONN_HANDLE_INIT 0xFFFF
#define CONN_HANDLE_INIT 0xFFFF
#define LOCAL_DEVICE_NAME "TMAP Central"
#define SCAN_INTERVAL 160 /* 100ms */
#define SCAN_WINDOW 160 /* 100ms */
/* ACL init parameters shared between bluedroid and nimble host wrappers.
* Raw HCI units (scan: 0.625ms; conn interval: 1.25ms; timeout: 10ms). */
#define INIT_SCAN_INTERVAL 16 /* 10ms */
#define INIT_SCAN_WINDOW 16 /* 10ms */
#define CONN_INTERVAL 24 /* 30ms */
#define CONN_LATENCY 0
#define CONN_TIMEOUT 500 /* 5s */
#define CONN_MIN_CE_LEN 0xFFFF
#define CONN_MAX_CE_LEN 0xFFFF
int app_host_init(void);
int set_device_name(void);
int ext_scan_start(void);
int ext_scan_stop(void);
int conn_create(uint8_t addr_type, const uint8_t addr[6]);
int pairing_start(uint16_t conn_handle);
int exchange_mtu(uint16_t conn_handle);
void security_failed_recover(uint16_t conn_handle, uint8_t status);
uint16_t default_conn_handle_get(void);
@@ -7,7 +7,6 @@
*/
#include <errno.h>
#include <stddef.h>
#include <stdint.h>
#include "tmap_central.h"
@@ -2,18 +2,17 @@
# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
#
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_BT_ENABLED=y
CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_EXT_ADV=y
CONFIG_BT_NIMBLE_NVS_PERSIST=y
CONFIG_BT_NIMBLE_MAX_CONNECTIONS=1
CONFIG_BT_NIMBLE_MAX_CCCDS=40
CONFIG_BT_NIMBLE_ISO=y
CONFIG_BT_NIMBLE_LOG_LEVEL_WARNING=y
CONFIG_BT_NIMBLE_ENABLED=n
CONFIG_BT_BLUEDROID_ENABLED=y
CONFIG_BT_CLASSIC_ENABLED=n
CONFIG_BT_CONTROLLER_ENABLED=y
CONFIG_BT_BLE_ENABLED=y
CONFIG_BT_BLE_50_FEATURES_SUPPORTED=y
CONFIG_BT_ACL_CONNECTIONS=1
CONFIG_BT_GATT_MAX_SR_PROFILES=12
CONFIG_BT_GATTC_NOTIF_REG_MAX=64
CONFIG_BT_BLE_FEAT_ISO_EN=y
CONFIG_BT_ISO_MAX_CHAN=2
@@ -32,4 +31,6 @@ CONFIG_BT_MCTL_LOCAL_PLAYER_REMOTE_CONTROL=y
CONFIG_BT_TBS=y
CONFIG_BT_TBS_SUPPORTED_FEATURES=3
CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y
CONFIG_FREERTOS_HZ=1000
@@ -0,0 +1,12 @@
# NimBLE host overlay for this example.
# Use with:
# idf.py -DSDKCONFIG_DEFAULTS="sdkconfig.defaults;sdkconfig.defaults.$IDF_TARGET;sdkconfig.defaults.nimble" build
CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_EXT_ADV=y
CONFIG_BT_NIMBLE_NVS_PERSIST=y
CONFIG_BT_NIMBLE_MAX_CONNECTIONS=1
CONFIG_BT_NIMBLE_MAX_CCCDS=64
CONFIG_BT_NIMBLE_ISO=y
CONFIG_BT_NIMBLE_LOG_LEVEL_WARNING=y