11/* Bluetooth Audio Broadcast Source */
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 */
2525#include <zephyr/kernel.h>
2626#include <zephyr/logging/log.h>
2727#include <zephyr/net_buf.h>
28+ #include <zephyr/sys/__assert.h>
2829#include <zephyr/sys/byteorder.h>
2930#include <zephyr/sys/check.h>
3031#include <zephyr/sys/slist.h>
@@ -55,6 +56,7 @@ static struct bt_bap_broadcast_subgroup
5556 broadcast_source_subgroups [CONFIG_BT_BAP_BROADCAST_SRC_COUNT ]
5657 [CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT ];
5758static struct bt_bap_broadcast_source broadcast_sources [CONFIG_BT_BAP_BROADCAST_SRC_COUNT ];
59+ static sys_slist_t bap_broadcast_source_cbs = SYS_SLIST_STATIC_INIT (& bap_broadcast_source_cbs );
5860
5961/**
6062 * 2 octets UUID
@@ -238,9 +240,9 @@ static void broadcast_source_iso_disconnected(struct bt_iso_chan *chan, uint8_t
238240}
239241
240242static struct bt_iso_chan_ops broadcast_source_iso_ops = {
241- .sent = broadcast_source_iso_sent ,
242- .connected = broadcast_source_iso_connected ,
243- .disconnected = broadcast_source_iso_disconnected ,
243+ .sent = broadcast_source_iso_sent ,
244+ .connected = broadcast_source_iso_connected ,
245+ .disconnected = broadcast_source_iso_disconnected ,
244246};
245247
246248bool bt_bap_ep_is_broadcast_src (const struct bt_bap_ep * ep )
@@ -440,8 +442,7 @@ static bool encode_base(struct bt_bap_broadcast_source *source, struct net_buf_s
440442 */
441443 streams_encoded = 0 ;
442444 SYS_SLIST_FOR_EACH_CONTAINER (& source -> subgroups , subgroup , _node ) {
443- if (!encode_base_subgroup (subgroup ,
444- & source -> stream_data [streams_encoded ],
445+ if (!encode_base_subgroup (subgroup , & source -> stream_data [streams_encoded ],
445446 & streams_encoded , buf )) {
446447 return false;
447448 }
@@ -454,21 +455,18 @@ static void broadcast_source_cleanup(struct bt_bap_broadcast_source *source)
454455{
455456 struct bt_bap_broadcast_subgroup * subgroup , * next_subgroup ;
456457
457- SYS_SLIST_FOR_EACH_CONTAINER_SAFE (& source -> subgroups , subgroup ,
458- next_subgroup , _node ) {
458+ SYS_SLIST_FOR_EACH_CONTAINER_SAFE (& source -> subgroups , subgroup , next_subgroup , _node ) {
459459 struct bt_bap_stream * stream , * next_stream ;
460460
461- SYS_SLIST_FOR_EACH_CONTAINER_SAFE (& subgroup -> streams , stream ,
462- next_stream , _node ) {
461+ SYS_SLIST_FOR_EACH_CONTAINER_SAFE (& subgroup -> streams , stream , next_stream , _node ) {
463462 bt_bap_iso_unbind_ep (stream -> ep -> iso , stream -> ep );
464463 stream -> ep -> stream = NULL ;
465464 stream -> ep = NULL ;
466465 stream -> codec_cfg = NULL ;
467466 stream -> qos = NULL ;
468467 stream -> group = NULL ;
469468
470- sys_slist_remove (& subgroup -> streams , NULL ,
471- & stream -> _node );
469+ sys_slist_remove (& subgroup -> streams , NULL , & stream -> _node );
472470 }
473471 sys_slist_remove (& source -> subgroups , NULL , & subgroup -> _node );
474472 }
@@ -777,8 +775,7 @@ int bt_bap_broadcast_source_create(struct bt_bap_broadcast_source_param *param,
777775 bis_count ++ ;
778776 }
779777
780- err = broadcast_source_setup_stream (index , stream ,
781- codec_cfg , qos , source );
778+ err = broadcast_source_setup_stream (index , stream , codec_cfg , qos , source );
782779 if (err != 0 ) {
783780 LOG_DBG ("Failed to setup streams[%zu]: %d" , i , err );
784781 broadcast_source_cleanup (source );
@@ -1039,7 +1036,7 @@ int bt_bap_broadcast_source_update_metadata(struct bt_bap_broadcast_source *sour
10391036int bt_bap_broadcast_source_start (struct bt_bap_broadcast_source * source , struct bt_le_ext_adv * adv )
10401037{
10411038 struct bt_iso_chan * bis [BROADCAST_STREAM_CNT ];
1042- struct bt_iso_big_create_param param = { 0 };
1039+ struct bt_iso_big_create_param param = {0 };
10431040 struct bt_bap_broadcast_subgroup * subgroup ;
10441041 enum bt_bap_ep_state broadcast_state ;
10451042 struct bt_bap_stream * stream ;
@@ -1078,8 +1075,7 @@ int bt_bap_broadcast_source_start(struct bt_bap_broadcast_source *source, struct
10781075 param .latency = source -> qos -> latency ;
10791076 param .encryption = source -> encryption ;
10801077 if (param .encryption ) {
1081- (void )memcpy (param .bcode , source -> broadcast_code ,
1082- sizeof (param .bcode ));
1078+ (void )memcpy (param .bcode , source -> broadcast_code , sizeof (param .bcode ));
10831079 }
10841080#if defined(CONFIG_BT_ISO_TEST_PARAMS )
10851081 param .irc = source -> irc ;
@@ -1125,14 +1121,12 @@ int bt_bap_broadcast_source_stop(struct bt_bap_broadcast_source *source)
11251121 return - EALREADY ;
11261122 }
11271123
1128- err = bt_iso_big_terminate (source -> big );
1124+ err = bt_iso_big_terminate (source -> big );
11291125 if (err ) {
11301126 LOG_DBG ("Failed to terminate BIG (err %d)" , err );
11311127 return err ;
11321128 }
11331129
1134- source -> big = NULL ;
1135-
11361130 return 0 ;
11371131}
11381132
@@ -1188,3 +1182,102 @@ int bt_bap_broadcast_source_get_base(struct bt_bap_broadcast_source *source,
11881182
11891183 return 0 ;
11901184}
1185+
1186+ static struct bt_bap_broadcast_source * get_broadcast_source_by_big (const struct bt_iso_big * big )
1187+ {
1188+ for (size_t i = 0U ; i < ARRAY_SIZE (broadcast_sources ); i ++ ) {
1189+ if (broadcast_sources [i ].big == big ) {
1190+ return & broadcast_sources [i ];
1191+ }
1192+ }
1193+
1194+ return NULL ;
1195+ }
1196+
1197+ static void big_started_cb (struct bt_iso_big * big )
1198+ {
1199+ struct bt_bap_broadcast_source * source = get_broadcast_source_by_big (big );
1200+ struct bt_bap_broadcast_source_cb * listener ;
1201+
1202+ if (source == NULL ) {
1203+ /* Not one of ours */
1204+ return ;
1205+ }
1206+
1207+ SYS_SLIST_FOR_EACH_CONTAINER (& bap_broadcast_source_cbs , listener , _node ) {
1208+ if (listener -> started != NULL ) {
1209+ listener -> started (source );
1210+ }
1211+ }
1212+ }
1213+
1214+ static void big_stopped_cb (struct bt_iso_big * big , uint8_t reason )
1215+ {
1216+ struct bt_bap_broadcast_source * source = get_broadcast_source_by_big (big );
1217+ struct bt_bap_broadcast_source_cb * listener ;
1218+
1219+ if (source == NULL ) {
1220+ /* Not one of ours */
1221+ return ;
1222+ }
1223+
1224+ source -> big = NULL ;
1225+
1226+ SYS_SLIST_FOR_EACH_CONTAINER (& bap_broadcast_source_cbs , listener , _node ) {
1227+ if (listener -> stopped != NULL ) {
1228+ listener -> stopped (source , reason );
1229+ }
1230+ }
1231+ }
1232+
1233+ int bt_bap_broadcast_source_register_cb (struct bt_bap_broadcast_source_cb * cb )
1234+ {
1235+ static bool iso_big_cb_registered ;
1236+
1237+ CHECKIF (cb == NULL ) {
1238+ LOG_DBG ("cb is NULL" );
1239+
1240+ return - EINVAL ;
1241+ }
1242+
1243+ if (sys_slist_find (& bap_broadcast_source_cbs , & cb -> _node , NULL )) {
1244+ LOG_DBG ("cb %p is already registered" , cb );
1245+
1246+ return - EEXIST ;
1247+ }
1248+
1249+ if (!iso_big_cb_registered ) {
1250+ static struct bt_iso_big_cb big_cb = {
1251+ .started = big_started_cb ,
1252+ .stopped = big_stopped_cb ,
1253+ };
1254+ const int err = bt_iso_big_register_cb (& big_cb );
1255+
1256+ if (err != 0 ) {
1257+ __ASSERT (false, "Failed to register ISO BIG callbacks: %d" , err );
1258+ }
1259+
1260+ iso_big_cb_registered = true;
1261+ }
1262+
1263+ sys_slist_append (& bap_broadcast_source_cbs , & cb -> _node );
1264+
1265+ return 0 ;
1266+ }
1267+
1268+ int bt_bap_broadcast_source_unregister_cb (struct bt_bap_broadcast_source_cb * cb )
1269+ {
1270+ CHECKIF (cb == NULL ) {
1271+ LOG_DBG ("cb is NULL" );
1272+
1273+ return - EINVAL ;
1274+ }
1275+
1276+ if (!sys_slist_find_and_remove (& bap_broadcast_source_cbs , & cb -> _node )) {
1277+ LOG_DBG ("cb %p is not registered" , cb );
1278+
1279+ return - ENOENT ;
1280+ }
1281+
1282+ return 0 ;
1283+ }
0 commit comments