1 /*  Bluetooth Audio Broadcast Source */
2 
3 /*
4  * Copyright (c) 2021-2025 Nordic Semiconductor ASA
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include <errno.h>
10 #include <stdbool.h>
11 #include <stddef.h>
12 #include <stdint.h>
13 #include <string.h>
14 
15 #include <zephyr/autoconf.h>
16 #include <zephyr/bluetooth/bluetooth.h>
17 #include <zephyr/bluetooth/conn.h>
18 #include <zephyr/bluetooth/crypto.h>
19 #include <zephyr/bluetooth/gatt.h>
20 #include <zephyr/bluetooth/audio/audio.h>
21 #include <zephyr/bluetooth/audio/bap.h>
22 #include <zephyr/bluetooth/hci_types.h>
23 #include <zephyr/bluetooth/iso.h>
24 #include <zephyr/bluetooth/uuid.h>
25 #include <zephyr/kernel.h>
26 #include <zephyr/logging/log.h>
27 #include <zephyr/net_buf.h>
28 #include <zephyr/sys/__assert.h>
29 #include <zephyr/sys/byteorder.h>
30 #include <zephyr/sys/check.h>
31 #include <zephyr/sys/slist.h>
32 #include <zephyr/sys/util.h>
33 #include <zephyr/sys/util_macro.h>
34 
35 LOG_MODULE_REGISTER(bt_bap_broadcast_source, CONFIG_BT_BAP_BROADCAST_SOURCE_LOG_LEVEL);
36 
37 #include "audio_internal.h"
38 #include "bap_iso.h"
39 #include "bap_endpoint.h"
40 #include "bap_stream.h"
41 
42 struct bt_bap_broadcast_subgroup {
43 	/* The streams used to create the broadcast source */
44 	sys_slist_t streams;
45 
46 	/* The codec of the subgroup */
47 	struct bt_audio_codec_cfg *codec_cfg;
48 
49 	/* List node */
50 	sys_snode_t _node;
51 };
52 
53 static struct bt_bap_ep broadcast_source_eps[CONFIG_BT_BAP_BROADCAST_SRC_COUNT]
54 					    [BROADCAST_STREAM_CNT];
55 static struct bt_bap_broadcast_subgroup
56 	broadcast_source_subgroups[CONFIG_BT_BAP_BROADCAST_SRC_COUNT]
57 				  [CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT];
58 static 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);
60 
61 /**
62  * 2 octets UUID
63  * 3 octets presentation delay
64  * 1 octet number of subgroups
65  *
66  * Each subgroup then has
67  * 1 octet of number of BIS
68  * 5 octets of Codec_ID
69  * 1 octet codec specific configuration len
70  * 0-n octets of codec specific configuration
71  * 1 octet metadata len
72  * 0-n octets of metadata
73  *
74  * For each BIS in the subgroup there is
75  * 1 octet for the BIS index
76  * 1 octet codec specific configuration len
77  * 0-n octets of codec specific configuration
78  *
79  * For a minimal BASE with 1 subgroup and 1 BIS without and other data the
80  * total comes to 16
81  */
82 #define MINIMUM_BASE_SIZE 16
83 
broadcast_source_set_ep_state(struct bt_bap_ep * ep,uint8_t state)84 static void broadcast_source_set_ep_state(struct bt_bap_ep *ep, uint8_t state)
85 {
86 	uint8_t old_state;
87 
88 	old_state = ep->status.state;
89 
90 	LOG_DBG("ep %p id 0x%02x %s -> %s", ep, ep->status.id, bt_bap_ep_state_str(old_state),
91 		bt_bap_ep_state_str(state));
92 
93 	switch (old_state) {
94 	case BT_BAP_EP_STATE_IDLE:
95 		if (state != BT_BAP_EP_STATE_QOS_CONFIGURED) {
96 			LOG_DBG("Invalid broadcast sync endpoint state transition");
97 			return;
98 		}
99 		break;
100 	case BT_BAP_EP_STATE_QOS_CONFIGURED:
101 		if (state != BT_BAP_EP_STATE_IDLE && state != BT_BAP_EP_STATE_ENABLING) {
102 			LOG_DBG("Invalid broadcast sync endpoint state transition");
103 			return;
104 		}
105 		break;
106 	case BT_BAP_EP_STATE_ENABLING:
107 		if (state != BT_BAP_EP_STATE_STREAMING && state != BT_BAP_EP_STATE_QOS_CONFIGURED) {
108 			LOG_DBG("Invalid broadcast sync endpoint state transition");
109 			return;
110 		}
111 		break;
112 	case BT_BAP_EP_STATE_STREAMING:
113 		if (state != BT_BAP_EP_STATE_QOS_CONFIGURED) {
114 			LOG_DBG("Invalid broadcast sync endpoint state transition");
115 			return;
116 		}
117 		break;
118 	default:
119 		LOG_ERR("Invalid broadcast sync endpoint state: %s",
120 			bt_bap_ep_state_str(old_state));
121 		return;
122 	}
123 
124 	ep->status.state = state;
125 }
126 
broadcast_source_set_state(struct bt_bap_broadcast_source * source,uint8_t state)127 static void broadcast_source_set_state(struct bt_bap_broadcast_source *source, uint8_t state)
128 {
129 	struct bt_bap_broadcast_subgroup *subgroup;
130 
131 	SYS_SLIST_FOR_EACH_CONTAINER(&source->subgroups, subgroup, _node) {
132 		struct bt_bap_stream *stream;
133 
134 		SYS_SLIST_FOR_EACH_CONTAINER(&subgroup->streams, stream, _node) {
135 			broadcast_source_set_ep_state(stream->ep, state);
136 		}
137 	}
138 }
139 
broadcast_source_iso_sent(struct bt_iso_chan * chan)140 static void broadcast_source_iso_sent(struct bt_iso_chan *chan)
141 {
142 	struct bt_bap_iso *iso = CONTAINER_OF(chan, struct bt_bap_iso, chan);
143 	const struct bt_bap_stream_ops *ops;
144 	struct bt_bap_stream *stream;
145 	struct bt_bap_ep *ep = iso->tx.ep;
146 
147 	if (ep == NULL) {
148 		LOG_ERR("iso %p not bound with ep", chan);
149 		return;
150 	}
151 
152 	stream = ep->stream;
153 	if (stream == NULL) {
154 		LOG_ERR("No stream for ep %p", ep);
155 		return;
156 	}
157 
158 	ops = stream->ops;
159 
160 	if (IS_ENABLED(CONFIG_BT_BAP_DEBUG_STREAM_DATA)) {
161 		LOG_DBG("stream %p ep %p", stream, stream->ep);
162 	}
163 
164 	if (ops != NULL && ops->sent != NULL) {
165 		ops->sent(stream);
166 	}
167 }
168 
broadcast_source_iso_connected(struct bt_iso_chan * chan)169 static void broadcast_source_iso_connected(struct bt_iso_chan *chan)
170 {
171 	struct bt_bap_iso *iso = CONTAINER_OF(chan, struct bt_bap_iso, chan);
172 	const struct bt_bap_stream_ops *ops;
173 	struct bt_bap_stream *stream;
174 	struct bt_bap_ep *ep = iso->tx.ep;
175 
176 	if (ep == NULL) {
177 		LOG_ERR("iso %p not bound with ep", chan);
178 		return;
179 	}
180 
181 	stream = ep->stream;
182 	if (stream == NULL) {
183 		LOG_ERR("No stream for ep %p", ep);
184 		return;
185 	}
186 
187 	LOG_DBG("stream %p ep %p", stream, ep);
188 
189 #if defined(CONFIG_BT_BAP_DEBUG_STREAM_SEQ_NUM)
190 	/* reset sequence number */
191 	stream->_prev_seq_num = 0U;
192 #endif /* CONFIG_BT_BAP_DEBUG_STREAM_SEQ_NUM */
193 
194 	/* Setup the ISO data path */
195 	bt_bap_setup_iso_data_path(stream);
196 
197 	ops = stream->ops;
198 	if (ops != NULL && ops->connected != NULL) {
199 		ops->connected(stream);
200 	}
201 
202 	broadcast_source_set_ep_state(ep, BT_BAP_EP_STATE_STREAMING);
203 
204 	if (ops != NULL && ops->started != NULL) {
205 		ops->started(stream);
206 	}
207 }
208 
broadcast_source_iso_disconnected(struct bt_iso_chan * chan,uint8_t reason)209 static void broadcast_source_iso_disconnected(struct bt_iso_chan *chan, uint8_t reason)
210 {
211 	struct bt_bap_iso *iso = CONTAINER_OF(chan, struct bt_bap_iso, chan);
212 	const struct bt_bap_stream_ops *ops;
213 	struct bt_bap_stream *stream;
214 	struct bt_bap_ep *ep = iso->tx.ep;
215 
216 	if (ep == NULL) {
217 		LOG_ERR("iso %p not bound with ep", chan);
218 		return;
219 	}
220 
221 	stream = ep->stream;
222 	if (stream == NULL) {
223 		LOG_ERR("No stream for ep %p", ep);
224 		return;
225 	}
226 
227 	LOG_DBG("stream %p ep %p reason 0x%02x", stream, stream->ep, reason);
228 
229 	ops = stream->ops;
230 	if (ops != NULL && ops->disconnected != NULL) {
231 		ops->disconnected(stream, reason);
232 	}
233 
234 	broadcast_source_set_ep_state(ep, BT_BAP_EP_STATE_QOS_CONFIGURED);
235 
236 	if (ops != NULL && ops->stopped != NULL) {
237 		ops->stopped(stream, reason);
238 	}
239 }
240 
241 static struct bt_iso_chan_ops broadcast_source_iso_ops = {
242 	.sent = broadcast_source_iso_sent,
243 	.connected = broadcast_source_iso_connected,
244 	.disconnected = broadcast_source_iso_disconnected,
245 };
246 
bt_bap_ep_is_broadcast_src(const struct bt_bap_ep * ep)247 bool bt_bap_ep_is_broadcast_src(const struct bt_bap_ep *ep)
248 {
249 	for (int i = 0; i < ARRAY_SIZE(broadcast_source_eps); i++) {
250 		if (PART_OF_ARRAY(broadcast_source_eps[i], ep)) {
251 			return true;
252 		}
253 	}
254 
255 	return false;
256 }
257 
broadcast_source_ep_init(struct bt_bap_ep * ep)258 static void broadcast_source_ep_init(struct bt_bap_ep *ep)
259 {
260 	LOG_DBG("ep %p", ep);
261 
262 	(void)memset(ep, 0, sizeof(*ep));
263 	ep->dir = BT_AUDIO_DIR_SOURCE;
264 	ep->iso = NULL;
265 }
266 
broadcast_source_new_ep(uint8_t index)267 static struct bt_bap_ep *broadcast_source_new_ep(uint8_t index)
268 {
269 	for (size_t i = 0; i < ARRAY_SIZE(broadcast_source_eps[index]); i++) {
270 		struct bt_bap_ep *ep = &broadcast_source_eps[index][i];
271 
272 		/* If ep->stream is NULL the endpoint is unallocated */
273 		if (ep->stream == NULL) {
274 			broadcast_source_ep_init(ep);
275 			return ep;
276 		}
277 	}
278 
279 	return NULL;
280 }
281 
broadcast_source_new_subgroup(uint8_t index)282 static struct bt_bap_broadcast_subgroup *broadcast_source_new_subgroup(uint8_t index)
283 {
284 	for (size_t i = 0; i < ARRAY_SIZE(broadcast_source_subgroups[index]); i++) {
285 		struct bt_bap_broadcast_subgroup *subgroup = &broadcast_source_subgroups[index][i];
286 
287 		if (sys_slist_is_empty(&subgroup->streams)) {
288 			return subgroup;
289 		}
290 	}
291 
292 	return NULL;
293 }
294 
broadcast_source_setup_stream(uint8_t index,struct bt_bap_stream * stream,struct bt_audio_codec_cfg * codec_cfg,struct bt_bap_qos_cfg * qos,struct bt_bap_broadcast_source * source)295 static int broadcast_source_setup_stream(uint8_t index, struct bt_bap_stream *stream,
296 					 struct bt_audio_codec_cfg *codec_cfg,
297 					 struct bt_bap_qos_cfg *qos,
298 					 struct bt_bap_broadcast_source *source)
299 {
300 	struct bt_bap_iso *iso;
301 	struct bt_bap_ep *ep;
302 
303 	ep = broadcast_source_new_ep(index);
304 	if (ep == NULL) {
305 		LOG_DBG("Could not allocate new broadcast endpoint");
306 		return -ENOMEM;
307 	}
308 
309 	iso = bt_bap_iso_new();
310 	if (iso == NULL) {
311 		LOG_DBG("Could not allocate iso");
312 		return -ENOMEM;
313 	}
314 
315 	bt_bap_iso_init(iso, &broadcast_source_iso_ops);
316 	bt_bap_iso_bind_ep(iso, ep);
317 	stream->iso = &iso->chan;
318 
319 	bt_bap_qos_cfg_to_iso_qos(iso->chan.qos->tx, qos);
320 
321 #if defined(CONFIG_BT_ISO_TEST_PARAMS)
322 	iso->chan.qos->num_subevents = qos->num_subevents;
323 #endif /* CONFIG_BT_ISO_TEST_PARAMS */
324 
325 	bt_bap_iso_unref(iso);
326 
327 	bt_bap_stream_attach(NULL, stream, ep, codec_cfg);
328 	stream->qos = qos;
329 	stream->group = source;
330 	ep->broadcast_source = source;
331 
332 	return 0;
333 }
334 
encode_base_subgroup(struct bt_bap_broadcast_subgroup * subgroup,struct bt_audio_broadcast_stream_data * stream_data,uint8_t * streams_encoded,struct net_buf_simple * buf)335 static bool encode_base_subgroup(struct bt_bap_broadcast_subgroup *subgroup,
336 				 struct bt_audio_broadcast_stream_data *stream_data,
337 				 uint8_t *streams_encoded, struct net_buf_simple *buf)
338 {
339 	struct bt_bap_stream *stream;
340 	const struct bt_audio_codec_cfg *codec_cfg;
341 	uint8_t stream_count;
342 	uint8_t len;
343 
344 	stream_count = 0;
345 	SYS_SLIST_FOR_EACH_CONTAINER(&subgroup->streams, stream, _node) {
346 		stream_count++;
347 	}
348 
349 	codec_cfg = subgroup->codec_cfg;
350 
351 	net_buf_simple_add_u8(buf, stream_count);
352 	net_buf_simple_add_u8(buf, codec_cfg->id);
353 	net_buf_simple_add_le16(buf, codec_cfg->cid);
354 	net_buf_simple_add_le16(buf, codec_cfg->vid);
355 
356 	net_buf_simple_add_u8(buf, codec_cfg->data_len);
357 #if CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0
358 	if ((buf->size - buf->len) < codec_cfg->data_len) {
359 		LOG_DBG("No room for config data: %zu", codec_cfg->data_len);
360 
361 		return false;
362 	}
363 	net_buf_simple_add_mem(buf, codec_cfg->data, codec_cfg->data_len);
364 #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0 */
365 
366 	if ((buf->size - buf->len) < sizeof(len)) {
367 		LOG_DBG("No room for metadata length");
368 
369 		return false;
370 	}
371 
372 	net_buf_simple_add_u8(buf, codec_cfg->meta_len);
373 
374 #if CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE > 0
375 	if ((buf->size - buf->len) < codec_cfg->meta_len) {
376 		LOG_DBG("No room for metadata data: %zu", codec_cfg->meta_len);
377 
378 		return false;
379 	}
380 
381 	net_buf_simple_add_mem(buf, codec_cfg->meta, codec_cfg->meta_len);
382 #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE > 0 */
383 
384 	/* Create BIS index bitfield */
385 	for (uint8_t i = 0U; i < stream_count; i++) {
386 		/* Set the bis_index to *streams_encoded plus 1 as the indexes start from 1 */
387 		const uint8_t bis_index = *streams_encoded + 1;
388 
389 		if ((buf->size - buf->len) < (sizeof(bis_index) + sizeof(uint8_t))) {
390 			LOG_DBG("No room for BIS[%d] index", i);
391 
392 			return false;
393 		}
394 
395 		net_buf_simple_add_u8(buf, bis_index);
396 
397 		if ((buf->size - buf->len) < sizeof(len)) {
398 			LOG_DBG("No room for bis codec config length");
399 
400 			return false;
401 		}
402 
403 		net_buf_simple_add_u8(buf, stream_data[i].data_len);
404 #if CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0
405 		if ((buf->size - buf->len) < stream_data[i].data_len) {
406 			LOG_DBG("No room for BIS[%u] data: %zu", i, stream_data[i].data_len);
407 
408 			return false;
409 		}
410 
411 		net_buf_simple_add_mem(buf, stream_data[i].data, stream_data[i].data_len);
412 #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0 */
413 
414 		(*streams_encoded)++;
415 	}
416 
417 	return true;
418 }
419 
encode_base(struct bt_bap_broadcast_source * source,struct net_buf_simple * buf)420 static bool encode_base(struct bt_bap_broadcast_source *source, struct net_buf_simple *buf)
421 {
422 	struct bt_bap_broadcast_subgroup *subgroup;
423 	uint8_t streams_encoded;
424 	uint8_t subgroup_count;
425 
426 	/* 13 is the size of the fixed size values following this check */
427 	if ((buf->size - buf->len) < MINIMUM_BASE_SIZE) {
428 		return false;
429 	}
430 
431 	subgroup_count = 0U;
432 	SYS_SLIST_FOR_EACH_CONTAINER(&source->subgroups, subgroup, _node) {
433 		subgroup_count++;
434 	}
435 
436 	net_buf_simple_add_le16(buf, BT_UUID_BASIC_AUDIO_VAL);
437 
438 	net_buf_simple_add_le24(buf, source->qos->pd);
439 	net_buf_simple_add_u8(buf, subgroup_count);
440 
441 	/* Since the `stream_data` is only stored in the broadcast source,
442 	 * we need to provide that information when encoding each subgroup
443 	 */
444 	streams_encoded = 0;
445 	SYS_SLIST_FOR_EACH_CONTAINER(&source->subgroups, subgroup, _node) {
446 		if (!encode_base_subgroup(subgroup, &source->stream_data[streams_encoded],
447 					  &streams_encoded, buf)) {
448 			return false;
449 		}
450 	}
451 
452 	return true;
453 }
454 
broadcast_source_cleanup(struct bt_bap_broadcast_source * source)455 static void broadcast_source_cleanup(struct bt_bap_broadcast_source *source)
456 {
457 	struct bt_bap_broadcast_subgroup *subgroup, *next_subgroup;
458 
459 	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&source->subgroups, subgroup, next_subgroup, _node) {
460 		struct bt_bap_stream *stream, *next_stream;
461 
462 		SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&subgroup->streams, stream, next_stream, _node) {
463 			bt_bap_iso_unbind_ep(stream->ep->iso, stream->ep);
464 			stream->iso = NULL;
465 			stream->ep->stream = NULL;
466 			stream->ep->broadcast_source = NULL;
467 			stream->ep = NULL;
468 			stream->codec_cfg = NULL;
469 			stream->qos = NULL;
470 			stream->group = NULL;
471 
472 			sys_slist_remove(&subgroup->streams, NULL, &stream->_node);
473 		}
474 		sys_slist_remove(&source->subgroups, NULL, &subgroup->_node);
475 	}
476 
477 	(void)memset(source, 0, sizeof(*source));
478 }
479 
valid_broadcast_source_param(const struct bt_bap_broadcast_source_param * param,const struct bt_bap_broadcast_source * source)480 static bool valid_broadcast_source_param(const struct bt_bap_broadcast_source_param *param,
481 					 const struct bt_bap_broadcast_source *source)
482 {
483 	const struct bt_bap_qos_cfg *qos;
484 
485 	CHECKIF(param == NULL) {
486 		LOG_DBG("param is NULL");
487 		return false;
488 	}
489 
490 	CHECKIF(!IN_RANGE(param->params_count, 1U, CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT)) {
491 		LOG_DBG("param->params_count %zu is invalid", param->params_count);
492 		return false;
493 	}
494 
495 	CHECKIF(param->packing != BT_ISO_PACKING_SEQUENTIAL &&
496 		param->packing != BT_ISO_PACKING_INTERLEAVED) {
497 		LOG_DBG("param->packing %u is invalid", param->packing);
498 		return false;
499 	}
500 
501 	qos = param->qos;
502 	CHECKIF(qos == NULL) {
503 		LOG_DBG("param->qos is NULL");
504 		return false;
505 	}
506 
507 	CHECKIF(bt_audio_verify_qos(qos) != BT_BAP_ASCS_REASON_NONE) {
508 		LOG_DBG("param->qos is invalid");
509 		return false;
510 	}
511 
512 	CHECKIF(param->qos->rtn > BT_ISO_BROADCAST_RTN_MAX) {
513 		LOG_DBG("param->qos->rtn %u invalid", param->qos->rtn);
514 		return false;
515 	}
516 
517 	CHECKIF(param->params == NULL) {
518 		LOG_DBG("param->params is NULL");
519 		return false;
520 	}
521 
522 	CHECKIF(param->params_count == 0) {
523 		LOG_DBG("param->params_count is 0");
524 		return false;
525 	}
526 
527 	for (size_t i = 0U; i < param->params_count; i++) {
528 		const struct bt_bap_broadcast_source_subgroup_param *subgroup_param;
529 
530 		subgroup_param = &param->params[i];
531 
532 		CHECKIF(subgroup_param->params == NULL) {
533 			LOG_DBG("subgroup_params[%zu].params is NULL", i);
534 			return false;
535 		}
536 
537 		CHECKIF(!IN_RANGE(subgroup_param->params_count, 1U,
538 				  CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT)) {
539 			LOG_DBG("subgroup_params[%zu].count (%zu) is invalid", i,
540 				subgroup_param->params_count);
541 			return false;
542 		}
543 
544 		CHECKIF(!bt_audio_valid_codec_cfg(subgroup_param->codec_cfg)) {
545 			LOG_DBG("subgroup_params[%zu].codec_cfg  is invalid", i);
546 			return false;
547 		}
548 
549 		for (size_t j = 0U; j < subgroup_param->params_count; j++) {
550 			const struct bt_bap_broadcast_source_stream_param *stream_param;
551 
552 			stream_param = &subgroup_param->params[j];
553 
554 			CHECKIF(stream_param->stream == NULL) {
555 				LOG_DBG("subgroup_params[%zu].stream_params[%zu]->stream is NULL",
556 					i, j);
557 				return false;
558 			}
559 
560 			CHECKIF(stream_param->stream->group != NULL &&
561 				stream_param->stream->group != source) {
562 				LOG_DBG("subgroup_params[%zu].stream_params[%zu]->stream is "
563 					"already part of group %p",
564 					i, j, stream_param->stream->group);
565 				return false;
566 			}
567 
568 #if CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0
569 			CHECKIF(stream_param->data == NULL && stream_param->data_len != 0) {
570 				LOG_DBG("subgroup_params[%zu].stream_params[%zu]->data is "
571 					"NULL with len %zu",
572 					i, j, stream_param->data_len);
573 				return false;
574 			}
575 
576 			CHECKIF(stream_param->data_len > CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE) {
577 				LOG_DBG("subgroup_params[%zu].stream_params[%zu]->data_len too "
578 					"large: %zu > %d",
579 					i, j, stream_param->data_len,
580 					CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE);
581 				return false;
582 			}
583 
584 			CHECKIF(stream_param->data != NULL &&
585 				subgroup_param->codec_cfg->id == BT_HCI_CODING_FORMAT_LC3 &&
586 				!bt_audio_valid_ltv(stream_param->data, stream_param->data_len)) {
587 				LOG_DBG("subgroup_params[%zu].stream_params[%zu]->data not valid "
588 					"LTV",
589 					i, j);
590 				return false;
591 			}
592 		}
593 #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0 */
594 	}
595 
596 	return true;
597 }
598 
599 /** Gets the "highest" state of all BIS in the broadcast source */
broadcast_source_get_state(struct bt_bap_broadcast_source * source)600 static enum bt_bap_ep_state broadcast_source_get_state(struct bt_bap_broadcast_source *source)
601 {
602 	enum bt_bap_ep_state state = BT_BAP_EP_STATE_IDLE;
603 	struct bt_bap_broadcast_subgroup *subgroup;
604 
605 	if (source == NULL) {
606 		LOG_DBG("source is NULL");
607 		return state;
608 	}
609 
610 	if (sys_slist_is_empty(&source->subgroups)) {
611 		LOG_DBG("Source does not have any streams");
612 		return state;
613 	}
614 
615 	SYS_SLIST_FOR_EACH_CONTAINER(&source->subgroups, subgroup, _node) {
616 		struct bt_bap_stream *stream;
617 
618 		SYS_SLIST_FOR_EACH_CONTAINER(&subgroup->streams, stream, _node) {
619 			if (stream->ep != NULL) {
620 				state = MAX(state, stream->ep->status.state);
621 			}
622 		}
623 	}
624 
625 	return state;
626 }
627 
merge_bis_and_subgroup_data_cb(struct bt_data * data,void * user_data)628 static bool merge_bis_and_subgroup_data_cb(struct bt_data *data, void *user_data)
629 {
630 	struct bt_audio_codec_cfg *codec_cfg = user_data;
631 	int err;
632 
633 	err = bt_audio_codec_cfg_set_val(codec_cfg, data->type, data->data, data->data_len);
634 	if (err < 0) {
635 		LOG_DBG("Failed to set type %u with len %u in codec_cfg: %d", data->type,
636 			data->data_len, err);
637 
638 		return false;
639 	}
640 
641 	return true;
642 }
643 
update_codec_cfg_data(struct bt_audio_codec_cfg * codec_cfg,const struct bt_bap_broadcast_source_stream_param * stream_param)644 static int update_codec_cfg_data(struct bt_audio_codec_cfg *codec_cfg,
645 				 const struct bt_bap_broadcast_source_stream_param *stream_param)
646 {
647 	if (stream_param->data_len > 0) {
648 		int err;
649 
650 		/* Merge subgroup codec configuration with the BIS configuration
651 		 * As per the BAP spec, if a value exist at level 2 (subgroup) and 3 (BIS), then it
652 		 * is the value at level 3 that shall be used
653 		 */
654 		if (codec_cfg->id == BT_HCI_CODING_FORMAT_LC3) {
655 			err = bt_audio_data_parse(stream_param->data, stream_param->data_len,
656 						  merge_bis_and_subgroup_data_cb, codec_cfg);
657 			if (err != 0) {
658 				LOG_DBG("Could not merge BIS and subgroup config in codec_cfg: %d",
659 					err);
660 
661 				return -EINVAL;
662 			}
663 		} else {
664 			/* If it is not LC3, then we don't know how to merge the subgroup and BIS
665 			 * codecs, so we just append them
666 			 */
667 			if (codec_cfg->data_len + stream_param->data_len >
668 			    sizeof(codec_cfg->data)) {
669 				LOG_DBG("Could not store BIS and subgroup config in codec_cfg (%u "
670 					"> %u)",
671 					codec_cfg->data_len + stream_param->data_len,
672 					sizeof(codec_cfg->data));
673 
674 				return -ENOMEM;
675 			}
676 
677 			memcpy(&codec_cfg->data[codec_cfg->data_len], stream_param->data,
678 			       stream_param->data_len);
679 			codec_cfg->data_len += stream_param->data_len;
680 		}
681 	}
682 
683 	return 0;
684 }
685 
bt_bap_broadcast_source_create(struct bt_bap_broadcast_source_param * param,struct bt_bap_broadcast_source ** out_source)686 int bt_bap_broadcast_source_create(struct bt_bap_broadcast_source_param *param,
687 				   struct bt_bap_broadcast_source **out_source)
688 {
689 	struct bt_bap_broadcast_source *source;
690 	struct bt_bap_qos_cfg *qos;
691 	size_t stream_count;
692 	uint8_t index;
693 	uint8_t bis_count;
694 	int err;
695 
696 	CHECKIF(out_source == NULL) {
697 		LOG_DBG("out_source is NULL");
698 		return -EINVAL;
699 	}
700 
701 	/* Set out_source to NULL until the source has actually been created */
702 	*out_source = NULL;
703 
704 	if (!valid_broadcast_source_param(param, NULL)) {
705 		LOG_DBG("Invalid parameters");
706 		return -EINVAL;
707 	}
708 
709 	source = NULL;
710 	for (index = 0; index < ARRAY_SIZE(broadcast_sources); index++) {
711 		if (sys_slist_is_empty(&broadcast_sources[index].subgroups)) { /* Find free entry */
712 			source = &broadcast_sources[index];
713 			break;
714 		}
715 	}
716 
717 	if (source == NULL) {
718 		LOG_DBG("Could not allocate any more broadcast sources");
719 		return -ENOMEM;
720 	}
721 
722 	stream_count = 0U;
723 	bis_count = 0U;
724 	qos = param->qos;
725 	/* Go through all subgroups and streams and setup each setup with an
726 	 * endpoint
727 	 */
728 	for (size_t i = 0U; i < param->params_count; i++) {
729 		const struct bt_bap_broadcast_source_subgroup_param *subgroup_param;
730 		struct bt_bap_broadcast_subgroup *subgroup;
731 
732 		subgroup_param = &param->params[i];
733 
734 		subgroup = broadcast_source_new_subgroup(index);
735 		if (subgroup == NULL) {
736 			LOG_DBG("Could not allocate new broadcast subgroup");
737 			broadcast_source_cleanup(source);
738 			return -ENOMEM;
739 		}
740 
741 		subgroup->codec_cfg = subgroup_param->codec_cfg;
742 		sys_slist_append(&source->subgroups, &subgroup->_node);
743 
744 		/* Check that we are not above the maximum BIS count */
745 		if (subgroup_param->params_count + stream_count > BROADCAST_STREAM_CNT) {
746 			LOG_DBG("Cannot create broadcaster with %zu streams", stream_count);
747 			broadcast_source_cleanup(source);
748 
749 			return -ENOMEM;
750 		}
751 
752 		for (size_t j = 0U; j < subgroup_param->params_count; j++) {
753 			const struct bt_bap_broadcast_source_stream_param *stream_param;
754 			struct bt_bap_stream *stream;
755 			struct bt_audio_codec_cfg *codec_cfg;
756 
757 			codec_cfg = subgroup_param->codec_cfg;
758 			stream_param = &subgroup_param->params[j];
759 			stream = stream_param->stream;
760 
761 			if (CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0) {
762 				if (bis_count >= BROADCAST_STREAM_CNT) {
763 					LOG_DBG("Stream count %d exceeded", bis_count);
764 					return -ENOMEM;
765 				}
766 
767 				codec_cfg = &source->codec_cfg[bis_count];
768 				memcpy(codec_cfg, subgroup_param->codec_cfg,
769 				       sizeof(struct bt_audio_codec_cfg));
770 
771 				err = update_codec_cfg_data(codec_cfg, stream_param);
772 				if (err != 0) {
773 					LOG_DBG("codec config update failed [%zu]: %d", i, err);
774 					broadcast_source_cleanup(source);
775 					return err;
776 				}
777 
778 				bis_count++;
779 			}
780 
781 			err = broadcast_source_setup_stream(index, stream, codec_cfg, qos, source);
782 			if (err != 0) {
783 				LOG_DBG("Failed to setup streams[%zu]: %d", i, err);
784 				broadcast_source_cleanup(source);
785 				return err;
786 			}
787 
788 			/* Store the BIS specific codec configuration data in
789 			 * the broadcast source. It is stored in the broadcast
790 			 * source, instead of the stream object, as this is
791 			 * only relevant for the broadcast source, and not used
792 			 * for unicast or broadcast sink.
793 			 */
794 			(void)memcpy(source->stream_data[stream_count].data, stream_param->data,
795 				     stream_param->data_len * sizeof(*stream_param->data));
796 			source->stream_data[stream_count].data_len = stream_param->data_len;
797 
798 			sys_slist_append(&subgroup->streams, &stream->_node);
799 			stream_count++;
800 		}
801 	}
802 
803 	/* Finalize state changes and store information */
804 	broadcast_source_set_state(source, BT_BAP_EP_STATE_QOS_CONFIGURED);
805 	source->qos = qos;
806 	source->packing = param->packing;
807 #if defined(CONFIG_BT_ISO_TEST_PARAMS)
808 	source->irc = param->irc;
809 	source->pto = param->pto;
810 	source->iso_interval = param->iso_interval;
811 #endif /* CONFIG_BT_ISO_TEST_PARAMS */
812 
813 	source->encryption = param->encryption;
814 	if (source->encryption) {
815 		(void)memcpy(source->broadcast_code, param->broadcast_code,
816 			     sizeof(source->broadcast_code));
817 	}
818 
819 	*out_source = source;
820 
821 	return 0;
822 }
823 
bt_bap_broadcast_source_reconfig(struct bt_bap_broadcast_source * source,struct bt_bap_broadcast_source_param * param)824 int bt_bap_broadcast_source_reconfig(struct bt_bap_broadcast_source *source,
825 				     struct bt_bap_broadcast_source_param *param)
826 {
827 	struct bt_bap_broadcast_subgroup *subgroup;
828 	enum bt_bap_ep_state broadcast_state;
829 	struct bt_bap_qos_cfg *qos;
830 	size_t subgroup_cnt;
831 	uint8_t bis_count;
832 
833 	CHECKIF(source == NULL) {
834 		LOG_DBG("source is NULL");
835 		return -EINVAL;
836 	}
837 
838 	if (!valid_broadcast_source_param(param, source)) {
839 		LOG_DBG("Invalid parameters");
840 		return -EINVAL;
841 	}
842 
843 	broadcast_state = broadcast_source_get_state(source);
844 	if (broadcast_source_get_state(source) != BT_BAP_EP_STATE_QOS_CONFIGURED) {
845 		LOG_DBG("Broadcast source invalid state: %u", broadcast_state);
846 		return -EBADMSG;
847 	}
848 
849 	/* Verify that the parameter counts do not exceed existing number of subgroups and streams*/
850 	subgroup_cnt = 0U;
851 	SYS_SLIST_FOR_EACH_CONTAINER(&source->subgroups, subgroup, _node) {
852 		const struct bt_bap_broadcast_source_subgroup_param *subgroup_param =
853 			&param->params[subgroup_cnt];
854 		const size_t subgroup_stream_param_cnt = subgroup_param->params_count;
855 		struct bt_bap_stream *stream;
856 		size_t subgroup_stream_cnt = 0U;
857 
858 		SYS_SLIST_FOR_EACH_CONTAINER(&subgroup->streams, stream, _node) {
859 			subgroup_stream_cnt++;
860 		}
861 
862 		/* Verify that the param stream is in the subgroup */
863 		for (size_t i = 0U; i < subgroup_param->params_count; i++) {
864 			struct bt_bap_stream *subgroup_stream;
865 			struct bt_bap_stream *param_stream;
866 			bool stream_in_subgroup = false;
867 
868 			param_stream = subgroup_param->params[i].stream;
869 
870 			SYS_SLIST_FOR_EACH_CONTAINER(&subgroup->streams, subgroup_stream, _node) {
871 				if (subgroup_stream == param_stream) {
872 					stream_in_subgroup = true;
873 					break;
874 				}
875 			}
876 
877 			if (!stream_in_subgroup) {
878 				LOG_DBG("Invalid param->params[%zu]->param[%zu].stream "
879 					"not in subgroup",
880 					subgroup_cnt, i);
881 				return -EINVAL;
882 			}
883 		}
884 
885 		if (subgroup_stream_cnt < subgroup_stream_param_cnt) {
886 			LOG_DBG("Invalid param->params[%zu]->params_count: %zu "
887 				"(only %zu streams in subgroup)",
888 				subgroup_cnt, subgroup_stream_param_cnt, subgroup_stream_cnt);
889 			return -EINVAL;
890 		}
891 
892 		subgroup_cnt++;
893 	}
894 
895 	if (subgroup_cnt < param->params_count) {
896 		LOG_DBG("Invalid param->params_count: %zu (only %zu subgroups in source)",
897 			param->params_count, subgroup_cnt);
898 		return -EINVAL;
899 	}
900 
901 	qos = param->qos;
902 	bis_count = 0U;
903 	/* We update up to the first param->params_count subgroups */
904 	for (size_t i = 0U; i < param->params_count; i++) {
905 		const struct bt_bap_broadcast_source_subgroup_param *subgroup_param;
906 		struct bt_audio_codec_cfg *codec_cfg;
907 		struct bt_bap_stream *stream;
908 
909 		if (i == 0) {
910 			subgroup =
911 				SYS_SLIST_PEEK_HEAD_CONTAINER(&source->subgroups, subgroup, _node);
912 		} else {
913 			subgroup = SYS_SLIST_PEEK_NEXT_CONTAINER(subgroup, _node);
914 		}
915 
916 		subgroup_param = &param->params[i];
917 		codec_cfg = subgroup_param->codec_cfg;
918 		subgroup->codec_cfg = codec_cfg;
919 
920 		for (size_t j = 0U; j < subgroup_param->params_count; j++) {
921 			const struct bt_bap_broadcast_source_stream_param *stream_param;
922 			struct bt_audio_broadcast_stream_data *stream_data;
923 			struct bt_bap_stream *subgroup_stream;
924 			size_t stream_idx;
925 
926 			stream_param = &subgroup_param->params[j];
927 			stream = stream_param->stream;
928 			if (CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0) {
929 				int err;
930 
931 				if (bis_count >= BROADCAST_STREAM_CNT) {
932 					LOG_DBG("Stream count %d exceeded", bis_count);
933 					return -ENOMEM;
934 				}
935 
936 				codec_cfg = &source->codec_cfg[bis_count];
937 				memcpy(codec_cfg, subgroup_param->codec_cfg,
938 				       sizeof(struct bt_audio_codec_cfg));
939 
940 				err = update_codec_cfg_data(codec_cfg, stream_param);
941 				if (err != 0) {
942 					LOG_DBG("codec config update failed [%zu]: %d", i, err);
943 					return err;
944 				}
945 
946 				bis_count++;
947 			}
948 
949 			stream_idx = 0U;
950 			SYS_SLIST_FOR_EACH_CONTAINER(&subgroup->streams, subgroup_stream, _node) {
951 				if (subgroup_stream == stream) {
952 					break;
953 				}
954 
955 				stream_idx++;
956 			}
957 
958 			/* Store the BIS specific codec configuration data in the broadcast source.
959 			 * It is stored in the broadcast* source, instead of the stream object,
960 			 * as this is only relevant for the broadcast source, and not used
961 			 * for unicast or broadcast sink.
962 			 */
963 			stream_data = &source->stream_data[stream_idx];
964 			(void)memcpy(stream_data->data, stream_param->data, stream_param->data_len);
965 			stream_data->data_len = stream_param->data_len;
966 		}
967 
968 		/* Apply the codec_cfg to all streams in the subgroup, and not just the ones in the
969 		 * params
970 		 */
971 		SYS_SLIST_FOR_EACH_CONTAINER(&subgroup->streams, stream, _node) {
972 			bt_bap_stream_attach(NULL, stream, stream->ep, codec_cfg);
973 		}
974 	}
975 
976 	/* Finally we apply the new qos and to all streams */
977 	SYS_SLIST_FOR_EACH_CONTAINER(&source->subgroups, subgroup, _node) {
978 		struct bt_bap_stream *stream;
979 
980 		SYS_SLIST_FOR_EACH_CONTAINER(&subgroup->streams, stream, _node) {
981 			struct bt_iso_chan_io_qos *iso_qos;
982 
983 			iso_qos = stream->ep->iso->chan.qos->tx;
984 			bt_bap_qos_cfg_to_iso_qos(iso_qos, qos);
985 			stream->qos = qos;
986 		}
987 	}
988 
989 	source->qos = qos;
990 
991 	return 0;
992 }
993 
bt_bap_broadcast_source_update_metadata(struct bt_bap_broadcast_source * source,const uint8_t meta[],size_t meta_len)994 int bt_bap_broadcast_source_update_metadata(struct bt_bap_broadcast_source *source,
995 					    const uint8_t meta[], size_t meta_len)
996 {
997 	struct bt_bap_broadcast_subgroup *subgroup;
998 	enum bt_bap_ep_state broadcast_state;
999 
1000 	CHECKIF(source == NULL) {
1001 		LOG_DBG("source is NULL");
1002 
1003 		return -EINVAL;
1004 	}
1005 
1006 	CHECKIF((meta == NULL && meta_len != 0) || (meta != NULL && meta_len == 0)) {
1007 		LOG_DBG("Invalid metadata combination: %p %zu", meta, meta_len);
1008 
1009 		return -EINVAL;
1010 	}
1011 
1012 	CHECKIF(meta_len > CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE) {
1013 		LOG_DBG("Invalid meta_len: %zu (max %d)", meta_len,
1014 			CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE);
1015 
1016 		return -EINVAL;
1017 	}
1018 
1019 	broadcast_state = broadcast_source_get_state(source);
1020 	if (broadcast_source_get_state(source) != BT_BAP_EP_STATE_STREAMING) {
1021 		LOG_DBG("Broadcast source invalid state: %u", broadcast_state);
1022 
1023 		return -EBADMSG;
1024 	}
1025 
1026 	/* TODO: We should probably find a way to update the metadata
1027 	 * for each subgroup individually
1028 	 */
1029 	SYS_SLIST_FOR_EACH_CONTAINER(&source->subgroups, subgroup, _node) {
1030 		memset(subgroup->codec_cfg->meta, 0, sizeof(subgroup->codec_cfg->meta));
1031 		memcpy(subgroup->codec_cfg->meta, meta, meta_len);
1032 		subgroup->codec_cfg->meta_len = meta_len;
1033 	}
1034 
1035 	return 0;
1036 }
1037 
bt_bap_broadcast_source_start(struct bt_bap_broadcast_source * source,struct bt_le_ext_adv * adv)1038 int bt_bap_broadcast_source_start(struct bt_bap_broadcast_source *source, struct bt_le_ext_adv *adv)
1039 {
1040 	struct bt_iso_chan *bis[BROADCAST_STREAM_CNT];
1041 	struct bt_iso_big_create_param param = {0};
1042 	struct bt_bap_broadcast_subgroup *subgroup;
1043 	enum bt_bap_ep_state broadcast_state;
1044 	struct bt_bap_stream *stream;
1045 	size_t bis_count;
1046 	int err;
1047 
1048 	CHECKIF(source == NULL) {
1049 		LOG_DBG("source is NULL");
1050 		return -EINVAL;
1051 	}
1052 
1053 	CHECKIF(adv == NULL) {
1054 		LOG_DBG("adv is NULL");
1055 		return -EINVAL;
1056 	}
1057 
1058 	broadcast_state = broadcast_source_get_state(source);
1059 	if (broadcast_source_get_state(source) != BT_BAP_EP_STATE_QOS_CONFIGURED) {
1060 		LOG_DBG("Broadcast source invalid state: %u", broadcast_state);
1061 		return -EBADMSG;
1062 	}
1063 
1064 	bis_count = 0;
1065 	SYS_SLIST_FOR_EACH_CONTAINER(&source->subgroups, subgroup, _node) {
1066 		SYS_SLIST_FOR_EACH_CONTAINER(&subgroup->streams, stream, _node) {
1067 			bis[bis_count++] = bt_bap_stream_iso_chan_get(stream);
1068 		}
1069 	}
1070 
1071 	/* Create BIG */
1072 	param.num_bis = bis_count;
1073 	param.bis_channels = bis;
1074 	param.framing = source->qos->framing;
1075 	param.packing = source->packing;
1076 	param.interval = source->qos->interval;
1077 	param.latency = source->qos->latency;
1078 	param.encryption = source->encryption;
1079 	if (param.encryption) {
1080 		(void)memcpy(param.bcode, source->broadcast_code, sizeof(param.bcode));
1081 	}
1082 #if defined(CONFIG_BT_ISO_TEST_PARAMS)
1083 	param.irc = source->irc;
1084 	param.pto = source->pto;
1085 	param.iso_interval = source->iso_interval;
1086 #endif /* CONFIG_BT_ISO_TEST_PARAMS */
1087 
1088 	/* Set the enabling state early in case that the BIS is connected before we can manage to
1089 	 * set it afterwards
1090 	 */
1091 	broadcast_source_set_state(source, BT_BAP_EP_STATE_ENABLING);
1092 
1093 	err = bt_iso_big_create(adv, &param, &source->big);
1094 	if (err != 0) {
1095 		LOG_DBG("Failed to create BIG: %d", err);
1096 		broadcast_source_set_state(source, BT_BAP_EP_STATE_QOS_CONFIGURED);
1097 
1098 		return err;
1099 	}
1100 
1101 	return 0;
1102 }
1103 
bt_bap_broadcast_source_stop(struct bt_bap_broadcast_source * source)1104 int bt_bap_broadcast_source_stop(struct bt_bap_broadcast_source *source)
1105 {
1106 	enum bt_bap_ep_state broadcast_state;
1107 	int err;
1108 
1109 	CHECKIF(source == NULL) {
1110 		LOG_DBG("source is NULL");
1111 		return -EINVAL;
1112 	}
1113 
1114 	broadcast_state = broadcast_source_get_state(source);
1115 	if (broadcast_state != BT_BAP_EP_STATE_STREAMING &&
1116 	    broadcast_state != BT_BAP_EP_STATE_ENABLING) {
1117 		LOG_DBG("Broadcast source invalid state: %u", broadcast_state);
1118 		return -EBADMSG;
1119 	}
1120 
1121 	if (source->big == NULL) {
1122 		LOG_DBG("Source is not started");
1123 		return -EALREADY;
1124 	}
1125 
1126 	err = bt_iso_big_terminate(source->big);
1127 	if (err) {
1128 		LOG_DBG("Failed to terminate BIG (err %d)", err);
1129 		return err;
1130 	}
1131 
1132 	return 0;
1133 }
1134 
bt_bap_broadcast_source_delete(struct bt_bap_broadcast_source * source)1135 int bt_bap_broadcast_source_delete(struct bt_bap_broadcast_source *source)
1136 {
1137 	enum bt_bap_ep_state broadcast_state;
1138 
1139 	CHECKIF(source == NULL) {
1140 		LOG_DBG("source is NULL");
1141 		return -EINVAL;
1142 	}
1143 
1144 	broadcast_state = broadcast_source_get_state(source);
1145 	if (broadcast_state != BT_BAP_EP_STATE_QOS_CONFIGURED) {
1146 		LOG_DBG("Broadcast source invalid state: %u", broadcast_state);
1147 		return -EBADMSG;
1148 	}
1149 
1150 	broadcast_source_set_state(source, BT_BAP_EP_STATE_IDLE);
1151 
1152 	/* Reset the broadcast source */
1153 	broadcast_source_cleanup(source);
1154 
1155 	return 0;
1156 }
1157 
bt_bap_broadcast_source_get_base(struct bt_bap_broadcast_source * source,struct net_buf_simple * base_buf)1158 int bt_bap_broadcast_source_get_base(struct bt_bap_broadcast_source *source,
1159 				     struct net_buf_simple *base_buf)
1160 {
1161 	enum bt_bap_ep_state broadcast_state;
1162 
1163 	CHECKIF(source == NULL) {
1164 		LOG_DBG("source is NULL");
1165 		return -EINVAL;
1166 	}
1167 
1168 	CHECKIF(base_buf == NULL) {
1169 		LOG_DBG("base_buf is NULL");
1170 		return -EINVAL;
1171 	}
1172 
1173 	broadcast_state = broadcast_source_get_state(source);
1174 	if (broadcast_state == BT_BAP_EP_STATE_IDLE) {
1175 		LOG_DBG("Broadcast source invalid state: %u", broadcast_state);
1176 		return -EBADMSG;
1177 	}
1178 
1179 	if (!encode_base(source, base_buf)) {
1180 		LOG_DBG("base_buf %p with size %u not large enough", base_buf, base_buf->size);
1181 
1182 		return -EMSGSIZE;
1183 	}
1184 
1185 	return 0;
1186 }
1187 
get_broadcast_source_by_big(const struct bt_iso_big * big)1188 static struct bt_bap_broadcast_source *get_broadcast_source_by_big(const struct bt_iso_big *big)
1189 {
1190 	for (size_t i = 0U; i < ARRAY_SIZE(broadcast_sources); i++) {
1191 		if (broadcast_sources[i].big == big) {
1192 			return &broadcast_sources[i];
1193 		}
1194 	}
1195 
1196 	return NULL;
1197 }
1198 
big_started_cb(struct bt_iso_big * big)1199 static void big_started_cb(struct bt_iso_big *big)
1200 {
1201 	struct bt_bap_broadcast_source *source = get_broadcast_source_by_big(big);
1202 	struct bt_bap_broadcast_source_cb *listener;
1203 
1204 	if (source == NULL) {
1205 		/* Not one of ours */
1206 		return;
1207 	}
1208 
1209 	SYS_SLIST_FOR_EACH_CONTAINER(&bap_broadcast_source_cbs, listener, _node) {
1210 		if (listener->started != NULL) {
1211 			listener->started(source);
1212 		}
1213 	}
1214 }
1215 
big_stopped_cb(struct bt_iso_big * big,uint8_t reason)1216 static void big_stopped_cb(struct bt_iso_big *big, uint8_t reason)
1217 {
1218 	struct bt_bap_broadcast_source *source = get_broadcast_source_by_big(big);
1219 	struct bt_bap_broadcast_source_cb *listener;
1220 
1221 	if (source == NULL) {
1222 		/* Not one of ours */
1223 		return;
1224 	}
1225 
1226 	source->big = NULL;
1227 
1228 	SYS_SLIST_FOR_EACH_CONTAINER(&bap_broadcast_source_cbs, listener, _node) {
1229 		if (listener->stopped != NULL) {
1230 			listener->stopped(source, reason);
1231 		}
1232 	}
1233 }
1234 
bt_bap_broadcast_source_register_cb(struct bt_bap_broadcast_source_cb * cb)1235 int bt_bap_broadcast_source_register_cb(struct bt_bap_broadcast_source_cb *cb)
1236 {
1237 	static bool iso_big_cb_registered;
1238 
1239 	CHECKIF(cb == NULL) {
1240 		LOG_DBG("cb is NULL");
1241 
1242 		return -EINVAL;
1243 	}
1244 
1245 	if (sys_slist_find(&bap_broadcast_source_cbs, &cb->_node, NULL)) {
1246 		LOG_DBG("cb %p is already registered", cb);
1247 
1248 		return -EEXIST;
1249 	}
1250 
1251 	if (!iso_big_cb_registered) {
1252 		static struct bt_iso_big_cb big_cb = {
1253 			.started = big_started_cb,
1254 			.stopped = big_stopped_cb,
1255 		};
1256 		const int err = bt_iso_big_register_cb(&big_cb);
1257 
1258 		if (err != 0) {
1259 			__ASSERT(false, "Failed to register ISO BIG callbacks: %d", err);
1260 		}
1261 
1262 		iso_big_cb_registered = true;
1263 	}
1264 
1265 	sys_slist_append(&bap_broadcast_source_cbs, &cb->_node);
1266 
1267 	return 0;
1268 }
1269 
bt_bap_broadcast_source_unregister_cb(struct bt_bap_broadcast_source_cb * cb)1270 int bt_bap_broadcast_source_unregister_cb(struct bt_bap_broadcast_source_cb *cb)
1271 {
1272 	CHECKIF(cb == NULL) {
1273 		LOG_DBG("cb is NULL");
1274 
1275 		return -EINVAL;
1276 	}
1277 
1278 	if (!sys_slist_find_and_remove(&bap_broadcast_source_cbs, &cb->_node)) {
1279 		LOG_DBG("cb %p is not registered", cb);
1280 
1281 		return -ENOENT;
1282 	}
1283 
1284 	return 0;
1285 }
1286 
bt_bap_broadcast_source_foreach_stream(struct bt_bap_broadcast_source * source,bt_bap_broadcast_source_foreach_stream_func_t func,void * user_data)1287 int bt_bap_broadcast_source_foreach_stream(struct bt_bap_broadcast_source *source,
1288 					   bt_bap_broadcast_source_foreach_stream_func_t func,
1289 					   void *user_data)
1290 {
1291 	struct bt_bap_broadcast_subgroup *subgroup, *next_subgroup;
1292 
1293 	if (source == NULL) {
1294 		LOG_DBG("source is NULL");
1295 		return -EINVAL;
1296 	}
1297 
1298 	if (func == NULL) {
1299 		LOG_DBG("func is NULL");
1300 		return -EINVAL;
1301 	}
1302 
1303 	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&source->subgroups, subgroup, next_subgroup, _node) {
1304 		struct bt_bap_stream *stream, *next_stream;
1305 
1306 		SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&subgroup->streams, stream, next_stream, _node) {
1307 			const bool stop = func(stream, user_data);
1308 
1309 			if (stop) {
1310 				return -ECANCELED;
1311 			}
1312 		}
1313 	}
1314 
1315 	return 0;
1316 }
1317