Skip to content

Commit 829519d

Browse files
Thalleykartben
authored andcommitted
Bluetooth: BAP: Add broadcast sink callback structs
These callbacks are trigger for changes that affect the entire broadcast sink, such as the BIG synced and terminated events. Signed-off-by: Emil Gydesen <[email protected]>
1 parent 0ae9761 commit 829519d

File tree

3 files changed

+147
-38
lines changed

3 files changed

+147
-38
lines changed

include/zephyr/bluetooth/audio/bap.h

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2292,6 +2292,22 @@ struct bt_bap_broadcast_sink_cb {
22922292
*/
22932293
void (*syncable)(struct bt_bap_broadcast_sink *sink, const struct bt_iso_biginfo *biginfo);
22942294

2295+
/**
2296+
* @brief The Broadcast Sink has started and audio data may be received from all of the
2297+
* streams
2298+
*
2299+
* @param sink The started Broadcast Sink
2300+
*/
2301+
void (*started)(struct bt_bap_broadcast_sink *sink);
2302+
2303+
/**
2304+
* @brief The Broadcast Sink has stopped and none of the streams will receive audio data
2305+
*
2306+
* @param sink The stopped Broadcast Sink
2307+
* @param reason The reason why the Broadcast Sink stopped (see the BT_HCI_ERR_* values)
2308+
*/
2309+
void (*stopped)(struct bt_bap_broadcast_sink *sink, uint8_t reason);
2310+
22952311
/** @internal Internally used list node */
22962312
sys_snode_t _node;
22972313
};
@@ -2302,11 +2318,12 @@ struct bt_bap_broadcast_sink_cb {
23022318
* It is possible to register multiple struct of callbacks, but a single struct can only be
23032319
* registered once.
23042320
* Registering the same callback multiple times is undefined behavior and may break the stack.
2305-
*
2321+
23062322
* @param cb Broadcast sink callback structure.
23072323
*
2308-
* @retval 0 in case of success
2324+
* @retval 0 on success
23092325
* @retval -EINVAL if @p cb is NULL
2326+
* @retval -EALREADY if @p cb was already registered
23102327
*/
23112328
int bt_bap_broadcast_sink_register_cb(struct bt_bap_broadcast_sink_cb *cb);
23122329

subsys/bluetooth/audio/bap_broadcast_sink.c

Lines changed: 71 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* Bluetooth Audio Broadcast Sink */
22

33
/*
4-
* Copyright (c) 2021-2023 Nordic Semiconductor ASA
4+
* Copyright (c) 2021-2024 Nordic Semiconductor ASA
55
*
66
* SPDX-License-Identifier: Apache-2.0
77
*/
@@ -402,11 +402,6 @@ static void broadcast_sink_iso_disconnected(struct bt_iso_chan *chan,
402402
if (!sys_slist_find_and_remove(&sink->streams, &stream->_node)) {
403403
LOG_DBG("Could not find and remove stream %p from sink %p", stream, sink);
404404
}
405-
406-
/* Clear sink->big if not already cleared */
407-
if (sys_slist_is_empty(&sink->streams) && sink->big) {
408-
broadcast_sink_clear_big(sink, reason);
409-
}
410405
}
411406

412407
if (ops != NULL && ops->stopped != NULL) {
@@ -449,6 +444,17 @@ static struct bt_bap_broadcast_sink *broadcast_sink_get_by_pa(struct bt_le_per_a
449444
return NULL;
450445
}
451446

447+
static struct bt_bap_broadcast_sink *broadcast_sink_get_by_big(const struct bt_iso_big *big)
448+
{
449+
for (size_t i = 0U; i < ARRAY_SIZE(broadcast_sinks); i++) {
450+
if (broadcast_sinks[i].big == big) {
451+
return &broadcast_sinks[i];
452+
}
453+
}
454+
455+
return NULL;
456+
}
457+
452458
static void broadcast_sink_add_src(struct bt_bap_broadcast_sink *sink)
453459
{
454460
struct bt_bap_scan_delegator_add_src_param add_src_param;
@@ -966,13 +972,72 @@ static uint16_t interval_to_sync_timeout(uint16_t interval)
966972
return (uint16_t)timeout;
967973
}
968974

975+
static void big_started_cb(struct bt_iso_big *big)
976+
{
977+
struct bt_bap_broadcast_sink *sink = broadcast_sink_get_by_big(big);
978+
struct bt_bap_broadcast_sink_cb *listener;
979+
980+
if (sink == NULL) {
981+
/* Not one of ours */
982+
return;
983+
}
984+
985+
SYS_SLIST_FOR_EACH_CONTAINER(&sink_cbs, listener, _node) {
986+
if (listener->started != NULL) {
987+
listener->started(sink);
988+
}
989+
}
990+
}
991+
992+
static void big_stopped_cb(struct bt_iso_big *big, uint8_t reason)
993+
{
994+
struct bt_bap_broadcast_sink *sink = broadcast_sink_get_by_big(big);
995+
struct bt_bap_broadcast_sink_cb *listener;
996+
997+
if (sink == NULL) {
998+
/* Not one of ours */
999+
return;
1000+
}
1001+
1002+
broadcast_sink_clear_big(sink, reason);
1003+
1004+
SYS_SLIST_FOR_EACH_CONTAINER(&sink_cbs, listener, _node) {
1005+
if (listener->stopped != NULL) {
1006+
listener->stopped(sink, reason);
1007+
}
1008+
}
1009+
}
1010+
9691011
int bt_bap_broadcast_sink_register_cb(struct bt_bap_broadcast_sink_cb *cb)
9701012
{
1013+
static bool iso_big_cb_registered;
1014+
9711015
CHECKIF(cb == NULL) {
9721016
LOG_DBG("cb is NULL");
1017+
9731018
return -EINVAL;
9741019
}
9751020

1021+
if (sys_slist_find(&sink_cbs, &cb->_node, NULL)) {
1022+
LOG_DBG("cb %p is already registered", cb);
1023+
1024+
return -EEXIST;
1025+
}
1026+
1027+
if (!iso_big_cb_registered) {
1028+
static struct bt_iso_big_cb big_cb = {
1029+
.started = big_started_cb,
1030+
.stopped = big_stopped_cb,
1031+
};
1032+
const int err = bt_iso_big_register_cb(&big_cb);
1033+
1034+
if (err != 0) {
1035+
__ASSERT(false, "Failed to register ISO BIG callbacks: %d", err);
1036+
}
1037+
1038+
iso_big_cb_registered = true;
1039+
}
1040+
9761041
sys_slist_append(&sink_cbs, &cb->_node);
9771042

9781043
return 0;
@@ -1314,9 +1379,6 @@ int bt_bap_broadcast_sink_stop(struct bt_bap_broadcast_sink *sink)
13141379
return err;
13151380
}
13161381

1317-
broadcast_sink_clear_big(sink, BT_HCI_ERR_LOCALHOST_TERM_CONN);
1318-
/* Channel states will be updated in the broadcast_sink_iso_disconnected function */
1319-
13201382
return 0;
13211383
}
13221384

tests/bsim/bluetooth/audio/src/bap_broadcast_sink_test.c

Lines changed: 57 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ CREATE_FLAG(flag_pa_sync_lost);
4848
CREATE_FLAG(flag_pa_request);
4949
CREATE_FLAG(flag_bis_sync_requested);
5050
CREATE_FLAG(flag_big_sync_mic_failure);
51+
CREATE_FLAG(flag_sink_started);
5152

5253
static struct bt_bap_broadcast_sink *g_sink;
5354
static struct bt_le_scan_recv_info broadcaster_info;
@@ -80,8 +81,8 @@ static const struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP_LC3(
8081
SUPPORTED_MIN_OCTETS_PER_FRAME, SUPPORTED_MAX_OCTETS_PER_FRAME,
8182
SUPPORTED_MAX_FRAMES_PER_SDU, SUPPORTED_CONTEXTS);
8283

83-
static K_SEM_DEFINE(sem_started, 0U, ARRAY_SIZE(streams));
84-
static K_SEM_DEFINE(sem_stopped, 0U, ARRAY_SIZE(streams));
84+
static K_SEM_DEFINE(sem_stream_started, 0U, ARRAY_SIZE(streams));
85+
static K_SEM_DEFINE(sem_stream_stopped, 0U, ARRAY_SIZE(streams));
8586

8687
/* Create a mask for the maximum BIS we can sync to using the number of streams
8788
* we have. We add an additional 1 since the bis indexes start from 1 and not
@@ -257,9 +258,27 @@ static void syncable_cb(struct bt_bap_broadcast_sink *sink, const struct bt_iso_
257258
SET_FLAG(flag_syncable);
258259
}
259260

261+
static void broadcast_sink_started_cb(struct bt_bap_broadcast_sink *sink)
262+
{
263+
printk("Broadcast sink %p started\n", sink);
264+
SET_FLAG(flag_sink_started);
265+
}
266+
267+
static void broadcast_sink_stopped_cb(struct bt_bap_broadcast_sink *sink, uint8_t reason)
268+
{
269+
printk("Broadcast sink %p stopped with reason 0x%02X\n", sink, reason);
270+
UNSET_FLAG(flag_sink_started);
271+
272+
if (reason == BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL) {
273+
SET_FLAG(flag_big_sync_mic_failure);
274+
}
275+
}
276+
260277
static struct bt_bap_broadcast_sink_cb broadcast_sink_cbs = {
261278
.base_recv = base_recv_cb,
262279
.syncable = syncable_cb,
280+
.started = broadcast_sink_started_cb,
281+
.stopped = broadcast_sink_stopped_cb,
263282
};
264283

265284
static bool scan_check_and_sync_broadcast(struct bt_data *data, void *user_data)
@@ -526,7 +545,7 @@ static void validate_stream_codec_cfg(const struct bt_bap_stream *stream)
526545
}
527546
}
528547

529-
static void started_cb(struct bt_bap_stream *stream)
548+
static void stream_started_cb(struct bt_bap_stream *stream)
530549
{
531550
struct audio_test_stream *test_stream = audio_test_stream_from_bap_stream(stream);
532551
struct bt_bap_ep_info info;
@@ -567,24 +586,20 @@ static void started_cb(struct bt_bap_stream *stream)
567586
}
568587

569588
printk("Stream %p started\n", stream);
570-
k_sem_give(&sem_started);
589+
k_sem_give(&sem_stream_started);
571590

572591
validate_stream_codec_cfg(stream);
573592
}
574593

575-
static void stopped_cb(struct bt_bap_stream *stream, uint8_t reason)
594+
static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason)
576595
{
577596
printk("Stream %p stopped with reason 0x%02X\n", stream, reason);
578-
k_sem_give(&sem_stopped);
579-
580-
if (reason == BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL) {
581-
SET_FLAG(flag_big_sync_mic_failure);
582-
}
597+
k_sem_give(&sem_stream_stopped);
583598
}
584599

585600
static struct bt_bap_stream_ops stream_ops = {
586-
.started = started_cb,
587-
.stopped = stopped_cb,
601+
.started = stream_started_cb,
602+
.stopped = stream_stopped_cb,
588603
.recv = bap_stream_rx_recv_cb,
589604
};
590605

@@ -707,6 +722,8 @@ static void test_broadcast_sink_create(void)
707722
FAIL("Unable to create the sink: %d\n", err);
708723
return;
709724
}
725+
726+
printk("Created broadcast sink %p\n", g_sink);
710727
}
711728

712729
static void test_broadcast_sink_create_inval(void)
@@ -736,7 +753,7 @@ static void test_broadcast_sync(const uint8_t broadcast_code[BT_ISO_BROADCAST_CO
736753
{
737754
int err;
738755

739-
printk("Syncing the sink\n");
756+
printk("Syncing sink %p\n", g_sink);
740757
err = bt_bap_broadcast_sink_sync(g_sink, bis_index_bitfield, streams, broadcast_code);
741758
if (err != 0) {
742759
FAIL("Unable to sync the sink: %d\n", err);
@@ -808,16 +825,20 @@ static void test_broadcast_stop(void)
808825
{
809826
int err;
810827

828+
printk("Stopping broadcast sink %p\n", g_sink);
829+
811830
err = bt_bap_broadcast_sink_stop(g_sink);
812831
if (err != 0) {
813832
FAIL("Unable to stop sink: %d", err);
814833
return;
815834
}
816835

817-
printk("Waiting for streams to be stopped\n");
836+
printk("Waiting for %zu streams to be stopped\n", ARRAY_SIZE(streams));
818837
for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) {
819-
k_sem_take(&sem_stopped, K_FOREVER);
838+
k_sem_take(&sem_stream_stopped, K_FOREVER);
820839
}
840+
841+
WAIT_FOR_UNSET_FLAG(flag_sink_started);
821842
}
822843

823844
static void test_broadcast_stop_inval(void)
@@ -914,10 +935,12 @@ static void test_common(void)
914935
test_broadcast_sync_inval();
915936
test_broadcast_sync(NULL);
916937

938+
WAIT_FOR_FLAG(flag_sink_started);
939+
917940
/* Wait for all to be started */
918-
printk("Waiting for streams to be started\n");
941+
printk("Waiting for %zu streams to be started\n", ARRAY_SIZE(streams));
919942
for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) {
920-
k_sem_take(&sem_started, K_FOREVER);
943+
k_sem_take(&sem_stream_started, K_FOREVER);
921944
}
922945

923946
printk("Waiting for data\n");
@@ -944,10 +967,11 @@ static void test_main(void)
944967
printk("Waiting for PA disconnected\n");
945968
WAIT_FOR_FLAG(flag_pa_sync_lost);
946969

947-
printk("Waiting for streams to be stopped\n");
970+
printk("Waiting for %zu streams to be stopped\n", ARRAY_SIZE(streams));
948971
for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) {
949-
k_sem_take(&sem_stopped, K_FOREVER);
972+
k_sem_take(&sem_stream_stopped, K_FOREVER);
950973
}
974+
WAIT_FOR_UNSET_FLAG(flag_sink_started);
951975

952976
PASS("Broadcast sink passed\n");
953977
}
@@ -962,10 +986,12 @@ static void test_sink_disconnect(void)
962986
/* Retry sync*/
963987
test_broadcast_sync(NULL);
964988

989+
WAIT_FOR_FLAG(flag_sink_started);
990+
965991
/* Wait for all to be started */
966-
printk("Waiting for streams to be started\n");
992+
printk("Waiting for %zu streams to be started\n", ARRAY_SIZE(streams));
967993
for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) {
968-
k_sem_take(&sem_started, K_FOREVER);
994+
k_sem_take(&sem_stream_started, K_FOREVER);
969995
}
970996

971997
test_broadcast_stop();
@@ -1001,10 +1027,12 @@ static void test_sink_encrypted(void)
10011027

10021028
test_broadcast_sync(BROADCAST_CODE);
10031029

1030+
WAIT_FOR_FLAG(flag_sink_started);
1031+
10041032
/* Wait for all to be started */
1005-
printk("Waiting for streams to be started\n");
1033+
printk("Waiting for %zu streams to be started\n", ARRAY_SIZE(streams));
10061034
for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) {
1007-
k_sem_take(&sem_started, K_FOREVER);
1035+
k_sem_take(&sem_stream_started, K_FOREVER);
10081036
}
10091037

10101038
printk("Waiting for data\n");
@@ -1021,9 +1049,9 @@ static void test_sink_encrypted(void)
10211049
printk("Waiting for PA disconnected\n");
10221050
WAIT_FOR_FLAG(flag_pa_sync_lost);
10231051

1024-
printk("Waiting for streams to be stopped\n");
1052+
printk("Waiting for %zu streams to be stopped\n", ARRAY_SIZE(streams));
10251053
for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) {
1026-
k_sem_take(&sem_stopped, K_FOREVER);
1054+
k_sem_take(&sem_stream_stopped, K_FOREVER);
10271055
}
10281056

10291057
PASS("Broadcast sink encrypted passed\n");
@@ -1090,10 +1118,12 @@ static void broadcast_sink_with_assistant(void)
10901118
WAIT_FOR_FLAG(flag_bis_sync_requested);
10911119
test_broadcast_sync(NULL);
10921120

1121+
WAIT_FOR_FLAG(flag_sink_started);
1122+
10931123
/* Wait for all to be started */
1094-
printk("Waiting for streams to be started\n");
1124+
printk("Waiting for %zu streams to be started\n", ARRAY_SIZE(streams));
10951125
for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) {
1096-
k_sem_take(&sem_started, K_FOREVER);
1126+
k_sem_take(&sem_stream_started, K_FOREVER);
10971127
}
10981128

10991129
printk("Waiting for data\n");

0 commit comments

Comments
 (0)