samples: Bluetooth: Update unicast audio samples to use bidirectional

Modified the samples such that the client will attempt to
setup 2 sink streams and 1 source stream, basically
representing a headset use case.

This also excercises both setting up a unidirectional
and a bidirectional ISO channel using the 3 audio streams.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
Emil Gydesen 2022-06-09 15:22:30 +02:00 committed by Carles Cufí
commit a757fc8c46
3 changed files with 105 additions and 23 deletions

View file

@ -40,13 +40,14 @@ static size_t configured_stream_count;
static struct bt_audio_lc3_preset codec_configuration = BT_AUDIO_LC3_UNICAST_PRESET_16_2_1; static struct bt_audio_lc3_preset codec_configuration = BT_AUDIO_LC3_UNICAST_PRESET_16_2_1;
static K_SEM_DEFINE(sem_connected, 0, 1); static K_SEM_DEFINE(sem_connected, 0, 1);
static K_SEM_DEFINE(sem_sink_discovered, 0, 1); static K_SEM_DEFINE(sem_mtu_exchanged, 0, 1);
static K_SEM_DEFINE(sem_sinks_discovered, 0, 1);
static K_SEM_DEFINE(sem_sources_discovered, 0, 1);
static K_SEM_DEFINE(sem_stream_configured, 0, 1); static K_SEM_DEFINE(sem_stream_configured, 0, 1);
static K_SEM_DEFINE(sem_stream_qos, 0, 1); static K_SEM_DEFINE(sem_stream_qos, 0, 1);
static K_SEM_DEFINE(sem_stream_enabled, 0, 1); static K_SEM_DEFINE(sem_stream_enabled, 0, 1);
static K_SEM_DEFINE(sem_stream_started, 0, 1); static K_SEM_DEFINE(sem_stream_started, 0, 1);
#if defined(CONFIG_LIBLC3CODEC) #if defined(CONFIG_LIBLC3CODEC)
#include "lc3.h" #include "lc3.h"
@ -531,7 +532,7 @@ static void add_remote_codec(struct bt_codec *codec_capabilities, int index,
} }
} }
static void discover_sink_cb(struct bt_conn *conn, static void discover_sinks_cb(struct bt_conn *conn,
struct bt_codec *codec, struct bt_codec *codec,
struct bt_audio_ep *ep, struct bt_audio_ep *ep,
struct bt_audio_discover_params *params) struct bt_audio_discover_params *params)
@ -547,20 +548,44 @@ static void discover_sink_cb(struct bt_conn *conn,
} }
if (ep != NULL) { if (ep != NULL) {
if (params->dir == BT_AUDIO_DIR_SINK) {
add_remote_sink(ep, params->num_eps); add_remote_sink(ep, params->num_eps);
} else {
add_remote_source(ep, params->num_eps);
}
return; return;
} }
printk("Discover complete: err %d\n", params->err); printk("Discover sinks complete: err %d\n", params->err);
(void)memset(params, 0, sizeof(*params)); (void)memset(params, 0, sizeof(*params));
k_sem_give(&sem_sink_discovered); k_sem_give(&sem_sinks_discovered);
}
static void discover_sources_cb(struct bt_conn *conn,
struct bt_codec *codec,
struct bt_audio_ep *ep,
struct bt_audio_discover_params *params)
{
if (params->err != 0) {
printk("Discovery failed: %d\n", params->err);
return;
}
if (codec != NULL) {
add_remote_codec(codec, params->num_caps, params->dir);
return;
}
if (ep != NULL) {
add_remote_source(ep, params->num_eps);
return;
}
printk("Discover sources complete: err %d\n", params->err);
(void)memset(params, 0, sizeof(*params));
k_sem_give(&sem_sources_discovered);
} }
static void connected(struct bt_conn *conn, uint8_t err) static void connected(struct bt_conn *conn, uint8_t err)
@ -610,6 +635,16 @@ BT_CONN_CB_DEFINE(conn_callbacks) = {
.disconnected = disconnected, .disconnected = disconnected,
}; };
static void att_mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx)
{
printk("MTU exchanged: %u/%u\n", tx, rx);
k_sem_give(&sem_mtu_exchanged);
}
static struct bt_gatt_cb gatt_callbacks = {
.att_mtu_updated = att_mtu_updated,
};
static int init(void) static int init(void)
{ {
int err; int err;
@ -624,6 +659,8 @@ static int init(void)
streams[i].ops = &stream_ops; streams[i].ops = &stream_ops;
} }
bt_gatt_cb_register(&gatt_callbacks);
#if defined(CONFIG_LIBLC3CODEC) #if defined(CONFIG_LIBLC3CODEC)
k_work_init_delayable(&audio_send_work, lc3_audio_timer_timeout); k_work_init_delayable(&audio_send_work, lc3_audio_timer_timeout);
#else #else
@ -645,26 +682,55 @@ static int scan_and_connect(void)
return err; return err;
} }
err = k_sem_take(&sem_mtu_exchanged, K_FOREVER);
if (err != 0) {
printk("failed to take sem_mtu_exchanged (err %d)\n", err);
return err;
}
return 0; return 0;
} }
static int discover_sink(void) static int discover_sinks(void)
{ {
static struct bt_audio_discover_params params; static struct bt_audio_discover_params params;
int err; int err;
params.func = discover_sink_cb; params.func = discover_sinks_cb;
params.dir = BT_AUDIO_DIR_SINK; params.dir = BT_AUDIO_DIR_SINK;
err = bt_audio_discover(default_conn, &params); err = bt_audio_discover(default_conn, &params);
if (err != 0) { if (err != 0) {
printk("Failed to discover sink: %d\n", err); printk("Failed to discover sinks: %d\n", err);
return err; return err;
} }
err = k_sem_take(&sem_sink_discovered, K_FOREVER); err = k_sem_take(&sem_sinks_discovered, K_FOREVER);
if (err != 0) { if (err != 0) {
printk("failed to take sem_sink_discovered (err %d)\n", err); printk("failed to take sem_sinks_discovered (err %d)\n", err);
return err;
}
return 0;
}
static int discover_sources(void)
{
static struct bt_audio_discover_params params;
int err;
params.func = discover_sources_cb;
params.dir = BT_AUDIO_DIR_SOURCE;
err = bt_audio_discover(default_conn, &params);
if (err != 0) {
printk("Failed to discover sources: %d\n", err);
return err;
}
err = k_sem_take(&sem_sources_discovered, K_FOREVER);
if (err != 0) {
printk("failed to take sem_sources_discovered (err %d)\n", err);
return err; return err;
} }
@ -723,7 +789,7 @@ static int configure_streams(void)
continue; continue;
} }
err = configure_stream(stream, sources[i]); err = configure_stream(stream, ep);
if (err != 0) { if (err != 0) {
printk("Could not configure source stream[%zu]: %d\n", printk("Could not configure source stream[%zu]: %d\n",
i, err); i, err);
@ -842,12 +908,19 @@ void main(void)
} }
printk("Connected\n"); printk("Connected\n");
printk("Discovering sink\n"); printk("Discovering sinks\n");
err = discover_sink(); err = discover_sinks();
if (err != 0) { if (err != 0) {
return; return;
} }
printk("Sink discovered\n"); printk("Sinks discovered\n");
printk("Discovering sources\n");
err = discover_sources();
if (err != 0) {
return;
}
printk("Sources discovered\n");
printk("Configuring streams\n"); printk("Configuring streams\n");
err = configure_streams(); err = configure_streams();

View file

@ -4,7 +4,7 @@ CONFIG_BT_PERIPHERAL=y
CONFIG_BT_AUDIO=y CONFIG_BT_AUDIO=y
CONFIG_BT_AUDIO_UNICAST_SERVER=y CONFIG_BT_AUDIO_UNICAST_SERVER=y
CONFIG_BT_ASCS_ASE_SNK_COUNT=2 CONFIG_BT_ASCS_ASE_SNK_COUNT=2
CONFIG_BT_ASCS_ASE_SRC_COUNT=2 CONFIG_BT_ASCS_ASE_SRC_COUNT=1
# Support an ISO channel per ASE # Support an ISO channel per ASE
CONFIG_BT_ISO_MAX_CHAN=4 CONFIG_BT_ISO_MAX_CHAN=4

View file

@ -464,6 +464,15 @@ static struct bt_audio_capability caps[] = {
40000, 40000), 40000, 40000),
.codec = &lc3_codec, .codec = &lc3_codec,
.ops = &lc3_ops, .ops = &lc3_ops,
},
{
.dir = BT_AUDIO_DIR_SOURCE,
.pref = BT_AUDIO_CAPABILITY_PREF(
BT_AUDIO_CAPABILITY_UNFRAMED_SUPPORTED,
BT_GAP_LE_PHY_2M, 0x02, 10, 40000, 40000,
40000, 40000),
.codec = &lc3_codec,
.ops = &lc3_ops,
} }
}; };