1 /*  Bluetooth Audio Broadcast Source */
2 
3 /*
4  * Copyright (c) 2021-2024 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 	ops = stream->ops;
195 	if (ops != NULL && ops->connected != NULL) {
196 		ops->connected(stream);
197 	}
198 
199 	broadcast_source_set_ep_state(ep, BT_BAP_EP_STATE_STREAMING);
200 
201 	if (ops != NULL && ops->started != NULL) {
202 		ops->started(stream);
203 	} else {
204 		LOG_WRN("No callback for started set");
205 	}
206 }
207 
broadcast_source_iso_disconnected(struct bt_iso_chan * chan,uint8_t reason)208 static void broadcast_source_iso_disconnected(struct bt_iso_chan *chan, uint8_t reason)
209 {
210 	struct bt_bap_iso *iso = CONTAINER_OF(chan, struct bt_bap_iso, chan);
211 	const struct bt_bap_stream_ops *ops;
212 	struct bt_bap_stream *stream;
213 	struct bt_bap_ep *ep = iso->tx.ep;
214 
215 	if (ep == NULL) {
216 		LOG_ERR("iso %p not bound with ep", chan);
217 		return;
218 	}
219 
220 	stream = ep->stream;
221 	if (stream == NULL) {
222 		LOG_ERR("No stream for ep %p", ep);
223 		return;
224 	}
225 
226 	LOG_DBG("stream %p ep %p reason 0x%02x", stream, stream->ep, reason);
227 
228 	ops = stream->ops;
229 	if (ops != NULL && ops->disconnected != NULL) {
230 		ops->disconnected(stream, reason);
231 	}
232 
233 	broadcast_source_set_ep_state(ep, BT_BAP_EP_STATE_QOS_CONFIGURED);
234 
235 	if (ops != NULL && ops->stopped != NULL) {
236 		ops->stopped(stream, reason);
237 	} else {
238 		LOG_WRN("No callback for stopped set");
239 	}
240 }
241 
242 static struct bt_iso_chan_ops broadcast_source_iso_ops = {
243 	.sent = broadcast_source_iso_sent,
244 	.connected = broadcast_source_iso_connected,
245 	.disconnected = broadcast_source_iso_disconnected,
246 };
247 
bt_bap_ep_is_broadcast_src(const struct bt_bap_ep * ep)248 bool bt_bap_ep_is_broadcast_src(const struct bt_bap_ep *ep)
249 {
250 	for (int i = 0; i < ARRAY_SIZE(broadcast_source_eps); i++) {
251 		if (PART_OF_ARRAY(broadcast_source_eps[i], ep)) {
252 			return true;
253 		}
254 	}
255 
256 	return false;
257 }
258 
broadcast_source_ep_init(struct bt_bap_ep * ep)259 static void broadcast_source_ep_init(struct bt_bap_ep *ep)
260 {
261 	LOG_DBG("ep %p", ep);
262 
263 	(void)memset(ep, 0, sizeof(*ep));
264 	ep->dir = BT_AUDIO_DIR_SOURCE;
265 	ep->iso = NULL;
266 }
267 
broadcast_source_new_ep(uint8_t index)268 static struct bt_bap_ep *broadcast_source_new_ep(uint8_t index)
269 {
270 	for (size_t i = 0; i < ARRAY_SIZE(broadcast_source_eps[index]); i++) {
271 		struct bt_bap_ep *ep = &broadcast_source_eps[index][i];
272 
273 		/* If ep->stream is NULL the endpoint is unallocated */
274 		if (ep->stream == NULL) {
275 			broadcast_source_ep_init(ep);
276 			return ep;
277 		}
278 	}
279 
280 	return NULL;
281 }
282 
broadcast_source_new_subgroup(uint8_t index)283 static struct bt_bap_broadcast_subgroup *broadcast_source_new_subgroup(uint8_t index)
284 {
285 	for (size_t i = 0; i < ARRAY_SIZE(broadcast_source_subgroups[index]); i++) {
286 		struct bt_bap_broadcast_subgroup *subgroup = &broadcast_source_subgroups[index][i];
287 
288 		if (sys_slist_is_empty(&subgroup->streams)) {
289 			return subgroup;
290 		}
291 	}
292 
293 	return NULL;
294 }
295 
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)296 static int broadcast_source_setup_stream(uint8_t index, struct bt_bap_stream *stream,
297 					 struct bt_audio_codec_cfg *codec_cfg,
298 					 struct bt_bap_qos_cfg *qos,
299 					 struct bt_bap_broadcast_source *source)
300 {
301 	struct bt_bap_iso *iso;
302 	struct bt_bap_ep *ep;
303 
304 	ep = broadcast_source_new_ep(index);
305 	if (ep == NULL) {
306 		LOG_DBG("Could not allocate new broadcast endpoint");
307 		return -ENOMEM;
308 	}
309 
310 	iso = bt_bap_iso_new();
311 	if (iso == NULL) {
312 		LOG_DBG("Could not allocate iso");
313 		return -ENOMEM;
314 	}
315 
316 	bt_bap_iso_init(iso, &broadcast_source_iso_ops);
317 	bt_bap_iso_bind_ep(iso, ep);
318 
319 	bt_bap_qos_cfg_to_iso_qos(iso->chan.qos->tx, qos);
320 	bt_bap_iso_configure_data_path(ep, codec_cfg);
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 	ep->broadcast_source = source;
330 
331 	return 0;
332 }
333 
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)334 static bool encode_base_subgroup(struct bt_bap_broadcast_subgroup *subgroup,
335 				 struct bt_audio_broadcast_stream_data *stream_data,
336 				 uint8_t *streams_encoded, struct net_buf_simple *buf)
337 {
338 	struct bt_bap_stream *stream;
339 	const struct bt_audio_codec_cfg *codec_cfg;
340 	uint8_t stream_count;
341 	uint8_t len;
342 
343 	stream_count = 0;
344 	SYS_SLIST_FOR_EACH_CONTAINER(&subgroup->streams, stream, _node) {
345 		stream_count++;
346 	}
347 
348 	codec_cfg = subgroup->codec_cfg;
349 
350 	net_buf_simple_add_u8(buf, stream_count);
351 	net_buf_simple_add_u8(buf, codec_cfg->id);
352 	net_buf_simple_add_le16(buf, codec_cfg->cid);
353 	net_buf_simple_add_le16(buf, codec_cfg->vid);
354 
355 	net_buf_simple_add_u8(buf, codec_cfg->data_len);
356 #if CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0
357 	if ((buf->size - buf->len) < codec_cfg->data_len) {
358 		LOG_DBG("No room for config data: %zu", codec_cfg->data_len);
359 
360 		return false;
361 	}
362 	net_buf_simple_add_mem(buf, codec_cfg->data, codec_cfg->data_len);
363 #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0 */
364 
365 	if ((buf->size - buf->len) < sizeof(len)) {
366 		LOG_DBG("No room for metadata length");
367 
368 		return false;
369 	}
370 
371 	net_buf_simple_add_u8(buf, codec_cfg->meta_len);
372 
373 #if CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE > 0
374 	if ((buf->size - buf->len) < codec_cfg->meta_len) {
375 		LOG_DBG("No room for metadata data: %zu", codec_cfg->meta_len);
376 
377 		return false;
378 	}
379 
380 	net_buf_simple_add_mem(buf, codec_cfg->meta, codec_cfg->meta_len);
381 #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE > 0 */
382 
383 	/* Create BIS index bitfield */
384 	for (uint8_t i = 0U; i < stream_count; i++) {
385 		/* Set the bis_index to *streams_encoded plus 1 as the indexes start from 1 */
386 		const uint8_t bis_index = *streams_encoded + 1;
387 
388 		if ((buf->size - buf->len) < (sizeof(bis_index) + sizeof(uint8_t))) {
389 			LOG_DBG("No room for BIS[%d] index", i);
390 
391 			return false;
392 		}
393 
394 		net_buf_simple_add_u8(buf, bis_index);
395 
396 		if ((buf->size - buf->len) < sizeof(len)) {
397 			LOG_DBG("No room for bis codec config length");
398 
399 			return false;
400 		}
401 
402 		net_buf_simple_add_u8(buf, stream_data[i].data_len);
403 #if CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0
404 		if ((buf->size - buf->len) < stream_data[i].data_len) {
405 			LOG_DBG("No room for BIS[%u] data: %zu", i, stream_data[i].data_len);
406 
407 			return false;
408 		}
409 
410 		net_buf_simple_add_mem(buf, stream_data[i].data, stream_data[i].data_len);
411 #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0 */
412 
413 		(*streams_encoded)++;
414 	}
415 
416 	return true;
417 }
418 
encode_base(struct bt_bap_broadcast_source * source,struct net_buf_simple * buf)419 static bool encode_base(struct bt_bap_broadcast_source *source, struct net_buf_simple *buf)
420 {
421 	struct bt_bap_broadcast_subgroup *subgroup;
422 	uint8_t streams_encoded;
423 	uint8_t subgroup_count;
424 
425 	/* 13 is the size of the fixed size values following this check */
426 	if ((buf->size - buf->len) < MINIMUM_BASE_SIZE) {
427 		return false;
428 	}
429 
430 	subgroup_count = 0U;
431 	SYS_SLIST_FOR_EACH_CONTAINER(&source->subgroups, subgroup, _node) {
432 		subgroup_count++;
433 	}
434 
435 	net_buf_simple_add_le16(buf, BT_UUID_BASIC_AUDIO_VAL);
436 
437 	net_buf_simple_add_le24(buf, source->qos->pd);
438 	net_buf_simple_add_u8(buf, subgroup_count);
439 
440 	/* Since the `stream_data` is only stored in the broadcast source,
441 	 * we need to provide that information when encoding each subgroup
442 	 */
443 	streams_encoded = 0;
444 	SYS_SLIST_FOR_EACH_CONTAINER(&source->subgroups, subgroup, _node) {
445 		if (!encode_base_subgroup(subgroup, &source->stream_data[streams_encoded],
446 					  &streams_encoded, buf)) {
447 			return false;
448 		}
449 	}
450 
451 	return true;
452 }
453 
broadcast_source_cleanup(struct bt_bap_broadcast_source * source)454 static void broadcast_source_cleanup(struct bt_bap_broadcast_source *source)
455 {
456 	struct bt_bap_broadcast_subgroup *subgroup, *next_subgroup;
457 
458 	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&source->subgroups, subgroup, next_subgroup, _node) {
459 		struct bt_bap_stream *stream, *next_stream;
460 
461 		SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&subgroup->streams, stream, next_stream, _node) {
462 			bt_bap_iso_unbind_ep(stream->ep->iso, stream->ep);
463 			stream->ep->stream = NULL;
464 			stream->ep = NULL;
465 			stream->codec_cfg = NULL;
466 			stream->qos = NULL;
467 			stream->group = NULL;
468 
469 			sys_slist_remove(&subgroup->streams, NULL, &stream->_node);
470 		}
471 		sys_slist_remove(&source->subgroups, NULL, &subgroup->_node);
472 	}
473 
474 	(void)memset(source, 0, sizeof(*source));
475 }
476 
valid_broadcast_source_param(const struct bt_bap_broadcast_source_param * param,const struct bt_bap_broadcast_source * source)477 static bool valid_broadcast_source_param(const struct bt_bap_broadcast_source_param *param,
478 					 const struct bt_bap_broadcast_source *source)
479 {
480 	const struct bt_bap_qos_cfg *qos;
481 
482 	CHECKIF(param == NULL) {
483 		LOG_DBG("param is NULL");
484 		return false;
485 	}
486 
487 	CHECKIF(!IN_RANGE(param->params_count, 1U, CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT)) {
488 		LOG_DBG("param->params_count %zu is invalid", param->params_count);
489 		return false;
490 	}
491 
492 	CHECKIF(param->packing != BT_ISO_PACKING_SEQUENTIAL &&
493 		param->packing != BT_ISO_PACKING_INTERLEAVED) {
494 		LOG_DBG("param->packing %u is invalid", param->packing);
495 		return false;
496 	}
497 
498 	qos = param->qos;
499 	CHECKIF(qos == NULL) {
500 		LOG_DBG("param->qos is NULL");
501 		return false;
502 	}
503 
504 	CHECKIF(bt_audio_verify_qos(qos) != BT_BAP_ASCS_REASON_NONE) {
505 		LOG_DBG("param->qos is invalid");
506 		return false;
507 	}
508 
509 	CHECKIF(param->qos->rtn > BT_ISO_BROADCAST_RTN_MAX) {
510 		LOG_DBG("param->qos->rtn %u invalid", param->qos->rtn);
511 		return false;
512 	}
513 
514 	CHECKIF(param->params == NULL) {
515 		LOG_DBG("param->params is NULL");
516 		return false;
517 	}
518 
519 	CHECKIF(param->params_count == 0) {
520 		LOG_DBG("param->params_count is 0");
521 		return false;
522 	}
523 
524 	for (size_t i = 0U; i < param->params_count; i++) {
525 		const struct bt_bap_broadcast_source_subgroup_param *subgroup_param;
526 
527 		subgroup_param = &param->params[i];
528 
529 		CHECKIF(subgroup_param->params == NULL) {
530 			LOG_DBG("subgroup_params[%zu].params is NULL", i);
531 			return false;
532 		}
533 
534 		CHECKIF(!IN_RANGE(subgroup_param->params_count, 1U,
535 				  CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT)) {
536 			LOG_DBG("subgroup_params[%zu].count (%zu) is invalid", i,
537 				subgroup_param->params_count);
538 			return false;
539 		}
540 
541 		CHECKIF(!bt_audio_valid_codec_cfg(subgroup_param->codec_cfg)) {
542 			LOG_DBG("subgroup_params[%zu].codec_cfg  is invalid", i);
543 			return false;
544 		}
545 
546 		for (size_t j = 0U; j < subgroup_param->params_count; j++) {
547 			const struct bt_bap_broadcast_source_stream_param *stream_param;
548 
549 			stream_param = &subgroup_param->params[j];
550 
551 			CHECKIF(stream_param->stream == NULL) {
552 				LOG_DBG("subgroup_params[%zu].stream_params[%zu]->stream is NULL",
553 					i, j);
554 				return false;
555 			}
556 
557 			CHECKIF(stream_param->stream->group != NULL &&
558 				stream_param->stream->group != source) {
559 				LOG_DBG("subgroup_params[%zu].stream_params[%zu]->stream is "
560 					"already part of group %p",
561 					i, j, stream_param->stream->group);
562 				return false;
563 			}
564 
565 #if CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0
566 			CHECKIF(stream_param->data == NULL && stream_param->data_len != 0) {
567 				LOG_DBG("subgroup_params[%zu].stream_params[%zu]->data is "
568 					"NULL with len %zu",
569 					i, j, stream_param->data_len);
570 				return false;
571 			}
572 
573 			CHECKIF(stream_param->data_len > CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE) {
574 				LOG_DBG("subgroup_params[%zu].stream_params[%zu]->data_len too "
575 					"large: %zu > %d",
576 					i, j, stream_param->data_len,
577 					CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE);
578 				return false;
579 			}
580 
581 			CHECKIF(stream_param->data != NULL &&
582 				subgroup_param->codec_cfg->id == BT_HCI_CODING_FORMAT_LC3 &&
583 				!bt_audio_valid_ltv(stream_param->data, stream_param->data_len)) {
584 				LOG_DBG("subgroup_params[%zu].stream_params[%zu]->data not valid "
585 					"LTV",
586 					i, j);
587 				return false;
588 			}
589 		}
590 #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0 */
591 	}
592 
593 	return true;
594 }
595 
596 /** Gets the "highest" state of all BIS in the broadcast source */
broadcast_source_get_state(struct bt_bap_broadcast_source * source)597 static enum bt_bap_ep_state broadcast_source_get_state(struct bt_bap_broadcast_source *source)
598 {
599 	enum bt_bap_ep_state state = BT_BAP_EP_STATE_IDLE;
600 	struct bt_bap_broadcast_subgroup *subgroup;
601 
602 	if (source == NULL) {
603 		LOG_DBG("source is NULL");
604 		return state;
605 	}
606 
607 	if (sys_slist_is_empty(&source->subgroups)) {
608 		LOG_DBG("Source does not have any streams");
609 		return state;
610 	}
611 
612 	SYS_SLIST_FOR_EACH_CONTAINER(&source->subgroups, subgroup, _node) {
613 		struct bt_bap_stream *stream;
614 
615 		SYS_SLIST_FOR_EACH_CONTAINER(&subgroup->streams, stream, _node) {
616 			if (stream->ep != NULL) {
617 				state = MAX(state, stream->ep->status.state);
618 			}
619 		}
620 	}
621 
622 	return state;
623 }
624 
merge_bis_and_subgroup_data_cb(struct bt_data * data,void * user_data)625 static bool merge_bis_and_subgroup_data_cb(struct bt_data *data, void *user_data)
626 {
627 	struct bt_audio_codec_cfg *codec_cfg = user_data;
628 	int err;
629 
630 	err = bt_audio_codec_cfg_set_val(codec_cfg, data->type, data->data, data->data_len);
631 	if (err < 0) {
632 		LOG_DBG("Failed to set type %u with len %u in codec_cfg: %d", data->type,
633 			data->data_len, err);
634 
635 		return false;
636 	}
637 
638 	return true;
639 }
640 
update_codec_cfg_data(struct bt_audio_codec_cfg * codec_cfg,const struct bt_bap_broadcast_source_stream_param * stream_param)641 static int update_codec_cfg_data(struct bt_audio_codec_cfg *codec_cfg,
642 				 const struct bt_bap_broadcast_source_stream_param *stream_param)
643 {
644 	if (stream_param->data_len > 0) {
645 		int err;
646 
647 		/* Merge subgroup codec configuration with the BIS configuration
648 		 * As per the BAP spec, if a value exist at level 2 (subgroup) and 3 (BIS), then it
649 		 * is the value at level 3 that shall be used
650 		 */
651 		if (codec_cfg->id == BT_HCI_CODING_FORMAT_LC3) {
652 			err = bt_audio_data_parse(stream_param->data, stream_param->data_len,
653 						  merge_bis_and_subgroup_data_cb, codec_cfg);
654 			if (err != 0) {
655 				LOG_DBG("Could not merge BIS and subgroup config in codec_cfg: %d",
656 					err);
657 
658 				return -EINVAL;
659 			}
660 		} else {
661 			/* If it is not LC3, then we don't know how to merge the subgroup and BIS
662 			 * codecs, so we just append them
663 			 */
664 			if (codec_cfg->data_len + stream_param->data_len >
665 			    sizeof(codec_cfg->data)) {
666 				LOG_DBG("Could not store BIS and subgroup config in codec_cfg (%u "
667 					"> %u)",
668 					codec_cfg->data_len + stream_param->data_len,
669 					sizeof(codec_cfg->data));
670 
671 				return -ENOMEM;
672 			}
673 
674 			memcpy(&codec_cfg->data[codec_cfg->data_len], stream_param->data,
675 			       stream_param->data_len);
676 			codec_cfg->data_len += stream_param->data_len;
677 		}
678 	}
679 
680 	return 0;
681 }
682 
bt_bap_broadcast_source_create(struct bt_bap_broadcast_source_param * param,struct bt_bap_broadcast_source ** out_source)683 int bt_bap_broadcast_source_create(struct bt_bap_broadcast_source_param *param,
684 				   struct bt_bap_broadcast_source **out_source)
685 {
686 	struct bt_bap_broadcast_source *source;
687 	struct bt_bap_qos_cfg *qos;
688 	size_t stream_count;
689 	uint8_t index;
690 	uint8_t bis_count;
691 	int err;
692 
693 	CHECKIF(out_source == NULL) {
694 		LOG_DBG("out_source is NULL");
695 		return -EINVAL;
696 	}
697 
698 	/* Set out_source to NULL until the source has actually been created */
699 	*out_source = NULL;
700 
701 	if (!valid_broadcast_source_param(param, NULL)) {
702 		LOG_DBG("Invalid parameters");
703 		return -EINVAL;
704 	}
705 
706 	source = NULL;
707 	for (index = 0; index < ARRAY_SIZE(broadcast_sources); index++) {
708 		if (sys_slist_is_empty(&broadcast_sources[index].subgroups)) { /* Find free entry */
709 			source = &broadcast_sources[index];
710 			break;
711 		}
712 	}
713 
714 	if (source == NULL) {
715 		LOG_DBG("Could not allocate any more broadcast sources");
716 		return -ENOMEM;
717 	}
718 
719 	stream_count = 0U;
720 	bis_count = 0U;
721 	qos = param->qos;
722 	/* Go through all subgroups and streams and setup each setup with an
723 	 * endpoint
724 	 */
725 	for (size_t i = 0U; i < param->params_count; i++) {
726 		const struct bt_bap_broadcast_source_subgroup_param *subgroup_param;
727 		struct bt_bap_broadcast_subgroup *subgroup;
728 
729 		subgroup_param = &param->params[i];
730 
731 		subgroup = broadcast_source_new_subgroup(index);
732 		if (subgroup == NULL) {
733 			LOG_DBG("Could not allocate new broadcast subgroup");
734 			broadcast_source_cleanup(source);
735 			return -ENOMEM;
736 		}
737 
738 		subgroup->codec_cfg = subgroup_param->codec_cfg;
739 		sys_slist_append(&source->subgroups, &subgroup->_node);
740 
741 		/* Check that we are not above the maximum BIS count */
742 		if (subgroup_param->params_count + stream_count > BROADCAST_STREAM_CNT) {
743 			LOG_DBG("Cannot create broadcaster with %zu streams", stream_count);
744 			broadcast_source_cleanup(source);
745 
746 			return -ENOMEM;
747 		}
748 
749 		for (size_t j = 0U; j < subgroup_param->params_count; j++) {
750 			const struct bt_bap_broadcast_source_stream_param *stream_param;
751 			struct bt_bap_stream *stream;
752 			struct bt_audio_codec_cfg *codec_cfg;
753 
754 			codec_cfg = subgroup_param->codec_cfg;
755 			stream_param = &subgroup_param->params[j];
756 			stream = stream_param->stream;
757 
758 			if (CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0) {
759 				if (bis_count >= BROADCAST_STREAM_CNT) {
760 					LOG_DBG("Stream count %d exceeded", bis_count);
761 					return -ENOMEM;
762 				}
763 
764 				codec_cfg = &source->codec_cfg[bis_count];
765 				memcpy(codec_cfg, subgroup_param->codec_cfg,
766 				       sizeof(struct bt_audio_codec_cfg));
767 
768 				err = update_codec_cfg_data(codec_cfg, stream_param);
769 				if (err != 0) {
770 					LOG_DBG("codec config update failed [%zu]: %d", i, err);
771 					broadcast_source_cleanup(source);
772 					return err;
773 				}
774 
775 				bis_count++;
776 			}
777 
778 			err = broadcast_source_setup_stream(index, stream, codec_cfg, qos, source);
779 			if (err != 0) {
780 				LOG_DBG("Failed to setup streams[%zu]: %d", i, err);
781 				broadcast_source_cleanup(source);
782 				return err;
783 			}
784 
785 			/* Store the BIS specific codec configuration data in
786 			 * the broadcast source. It is stored in the broadcast
787 			 * source, instead of the stream object, as this is
788 			 * only relevant for the broadcast source, and not used
789 			 * for unicast or broadcast sink.
790 			 */
791 			(void)memcpy(source->stream_data[stream_count].data, stream_param->data,
792 				     stream_param->data_len * sizeof(*stream_param->data));
793 			source->stream_data[stream_count].data_len = stream_param->data_len;
794 
795 			sys_slist_append(&subgroup->streams, &stream->_node);
796 			stream_count++;
797 		}
798 	}
799 
800 	/* Finalize state changes and store information */
801 	broadcast_source_set_state(source, BT_BAP_EP_STATE_QOS_CONFIGURED);
802 	source->qos = qos;
803 	source->packing = param->packing;
804 #if defined(CONFIG_BT_ISO_TEST_PARAMS)
805 	source->irc = param->irc;
806 	source->pto = param->pto;
807 	source->iso_interval = param->iso_interval;
808 #endif /* CONFIG_BT_ISO_TEST_PARAMS */
809 
810 	source->encryption = param->encryption;
811 	if (source->encryption) {
812 		(void)memcpy(source->broadcast_code, param->broadcast_code,
813 			     sizeof(source->broadcast_code));
814 	}
815 
816 	*out_source = source;
817 
818 	return 0;
819 }
820 
bt_bap_broadcast_source_reconfig(struct bt_bap_broadcast_source * source,struct bt_bap_broadcast_source_param * param)821 int bt_bap_broadcast_source_reconfig(struct bt_bap_broadcast_source *source,
822 				     struct bt_bap_broadcast_source_param *param)
823 {
824 	struct bt_bap_broadcast_subgroup *subgroup;
825 	enum bt_bap_ep_state broadcast_state;
826 	struct bt_bap_qos_cfg *qos;
827 	size_t subgroup_cnt;
828 	uint8_t bis_count;
829 
830 	CHECKIF(source == NULL) {
831 		LOG_DBG("source is NULL");
832 		return -EINVAL;
833 	}
834 
835 	if (!valid_broadcast_source_param(param, source)) {
836 		LOG_DBG("Invalid parameters");
837 		return -EINVAL;
838 	}
839 
840 	broadcast_state = broadcast_source_get_state(source);
841 	if (broadcast_source_get_state(source) != BT_BAP_EP_STATE_QOS_CONFIGURED) {
842 		LOG_DBG("Broadcast source invalid state: %u", broadcast_state);
843 		return -EBADMSG;
844 	}
845 
846 	/* Verify that the parameter counts do not exceed existing number of subgroups and streams*/
847 	subgroup_cnt = 0U;
848 	SYS_SLIST_FOR_EACH_CONTAINER(&source->subgroups, subgroup, _node) {
849 		const struct bt_bap_broadcast_source_subgroup_param *subgroup_param =
850 			&param->params[subgroup_cnt];
851 		const size_t subgroup_stream_param_cnt = subgroup_param->params_count;
852 		struct bt_bap_stream *stream;
853 		size_t subgroup_stream_cnt = 0U;
854 
855 		SYS_SLIST_FOR_EACH_CONTAINER(&subgroup->streams, stream, _node) {
856 			subgroup_stream_cnt++;
857 		}
858 
859 		/* Verify that the param stream is in the subgroup */
860 		for (size_t i = 0U; i < subgroup_param->params_count; i++) {
861 			struct bt_bap_stream *subgroup_stream;
862 			struct bt_bap_stream *param_stream;
863 			bool stream_in_subgroup = false;
864 
865 			param_stream = subgroup_param->params[i].stream;
866 
867 			SYS_SLIST_FOR_EACH_CONTAINER(&subgroup->streams, subgroup_stream, _node) {
868 				if (subgroup_stream == param_stream) {
869 					stream_in_subgroup = true;
870 					break;
871 				}
872 			}
873 
874 			if (!stream_in_subgroup) {
875 				LOG_DBG("Invalid param->params[%zu]->param[%zu].stream "
876 					"not in subgroup",
877 					subgroup_cnt, i);
878 				return -EINVAL;
879 			}
880 		}
881 
882 		if (subgroup_stream_cnt < subgroup_stream_param_cnt) {
883 			LOG_DBG("Invalid param->params[%zu]->params_count: %zu "
884 				"(only %zu streams in subgroup)",
885 				subgroup_cnt, subgroup_stream_param_cnt, subgroup_stream_cnt);
886 			return -EINVAL;
887 		}
888 
889 		subgroup_cnt++;
890 	}
891 
892 	if (subgroup_cnt < param->params_count) {
893 		LOG_DBG("Invalid param->params_count: %zu (only %zu subgroups in source)",
894 			param->params_count, subgroup_cnt);
895 		return -EINVAL;
896 	}
897 
898 	qos = param->qos;
899 	bis_count = 0U;
900 	/* We update up to the first param->params_count subgroups */
901 	for (size_t i = 0U; i < param->params_count; i++) {
902 		const struct bt_bap_broadcast_source_subgroup_param *subgroup_param;
903 		struct bt_audio_codec_cfg *codec_cfg;
904 		struct bt_bap_stream *stream;
905 
906 		if (i == 0) {
907 			subgroup =
908 				SYS_SLIST_PEEK_HEAD_CONTAINER(&source->subgroups, subgroup, _node);
909 		} else {
910 			subgroup = SYS_SLIST_PEEK_NEXT_CONTAINER(subgroup, _node);
911 		}
912 
913 		subgroup_param = &param->params[i];
914 		codec_cfg = subgroup_param->codec_cfg;
915 		subgroup->codec_cfg = codec_cfg;
916 
917 		for (size_t j = 0U; j < subgroup_param->params_count; j++) {
918 			const struct bt_bap_broadcast_source_stream_param *stream_param;
919 			struct bt_audio_broadcast_stream_data *stream_data;
920 			struct bt_bap_stream *subgroup_stream;
921 			size_t stream_idx;
922 
923 			stream_param = &subgroup_param->params[j];
924 			stream = stream_param->stream;
925 			if (CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0) {
926 				int err;
927 
928 				if (bis_count >= BROADCAST_STREAM_CNT) {
929 					LOG_DBG("Stream count %d exceeded", bis_count);
930 					return -ENOMEM;
931 				}
932 
933 				codec_cfg = &source->codec_cfg[bis_count];
934 				memcpy(codec_cfg, subgroup_param->codec_cfg,
935 				       sizeof(struct bt_audio_codec_cfg));
936 
937 				err = update_codec_cfg_data(codec_cfg, stream_param);
938 				if (err != 0) {
939 					LOG_DBG("codec config update failed [%zu]: %d", i, err);
940 					return err;
941 				}
942 
943 				bis_count++;
944 			}
945 
946 			stream_idx = 0U;
947 			SYS_SLIST_FOR_EACH_CONTAINER(&subgroup->streams, subgroup_stream, _node) {
948 				if (subgroup_stream == stream) {
949 					break;
950 				}
951 
952 				stream_idx++;
953 			}
954 
955 			/* Store the BIS specific codec configuration data in the broadcast source.
956 			 * It is stored in the broadcast* source, instead of the stream object,
957 			 * as this is only relevant for the broadcast source, and not used
958 			 * for unicast or broadcast sink.
959 			 */
960 			stream_data = &source->stream_data[stream_idx];
961 			(void)memcpy(stream_data->data, stream_param->data, stream_param->data_len);
962 			stream_data->data_len = stream_param->data_len;
963 		}
964 
965 		/* Apply the codec_cfg to all streams in the subgroup, and not just the ones in the
966 		 * params
967 		 */
968 		SYS_SLIST_FOR_EACH_CONTAINER(&subgroup->streams, stream, _node) {
969 			bt_bap_stream_attach(NULL, stream, stream->ep, codec_cfg);
970 			bt_bap_iso_configure_data_path(stream->ep, codec_cfg);
971 		}
972 	}
973 
974 	/* Finally we apply the new qos and to all streams */
975 	SYS_SLIST_FOR_EACH_CONTAINER(&source->subgroups, subgroup, _node) {
976 		struct bt_bap_stream *stream;
977 
978 		SYS_SLIST_FOR_EACH_CONTAINER(&subgroup->streams, stream, _node) {
979 			struct bt_iso_chan_io_qos *iso_qos;
980 
981 			iso_qos = stream->ep->iso->chan.qos->tx;
982 			bt_bap_qos_cfg_to_iso_qos(iso_qos, qos);
983 			stream->qos = qos;
984 		}
985 	}
986 
987 	source->qos = qos;
988 
989 	return 0;
990 }
991 
bt_bap_broadcast_source_update_metadata(struct bt_bap_broadcast_source * source,const uint8_t meta[],size_t meta_len)992 int bt_bap_broadcast_source_update_metadata(struct bt_bap_broadcast_source *source,
993 					    const uint8_t meta[], size_t meta_len)
994 {
995 	struct bt_bap_broadcast_subgroup *subgroup;
996 	enum bt_bap_ep_state broadcast_state;
997 
998 	CHECKIF(source == NULL) {
999 		LOG_DBG("source is NULL");
1000 
1001 		return -EINVAL;
1002 	}
1003 
1004 	CHECKIF((meta == NULL && meta_len != 0) || (meta != NULL && meta_len == 0)) {
1005 		LOG_DBG("Invalid metadata combination: %p %zu", meta, meta_len);
1006 
1007 		return -EINVAL;
1008 	}
1009 
1010 	CHECKIF(meta_len > CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE) {
1011 		LOG_DBG("Invalid meta_len: %zu (max %d)", meta_len,
1012 			CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE);
1013 
1014 		return -EINVAL;
1015 	}
1016 
1017 	broadcast_state = broadcast_source_get_state(source);
1018 	if (broadcast_source_get_state(source) != BT_BAP_EP_STATE_STREAMING) {
1019 		LOG_DBG("Broadcast source invalid state: %u", broadcast_state);
1020 
1021 		return -EBADMSG;
1022 	}
1023 
1024 	/* TODO: We should probably find a way to update the metadata
1025 	 * for each subgroup individually
1026 	 */
1027 	SYS_SLIST_FOR_EACH_CONTAINER(&source->subgroups, subgroup, _node) {
1028 		memset(subgroup->codec_cfg->meta, 0, sizeof(subgroup->codec_cfg->meta));
1029 		memcpy(subgroup->codec_cfg->meta, meta, meta_len);
1030 		subgroup->codec_cfg->meta_len = meta_len;
1031 	}
1032 
1033 	return 0;
1034 }
1035 
bt_bap_broadcast_source_start(struct bt_bap_broadcast_source * source,struct bt_le_ext_adv * adv)1036 int bt_bap_broadcast_source_start(struct bt_bap_broadcast_source *source, struct bt_le_ext_adv *adv)
1037 {
1038 	struct bt_iso_chan *bis[BROADCAST_STREAM_CNT];
1039 	struct bt_iso_big_create_param param = {0};
1040 	struct bt_bap_broadcast_subgroup *subgroup;
1041 	enum bt_bap_ep_state broadcast_state;
1042 	struct bt_bap_stream *stream;
1043 	size_t bis_count;
1044 	int err;
1045 
1046 	CHECKIF(source == NULL) {
1047 		LOG_DBG("source is NULL");
1048 		return -EINVAL;
1049 	}
1050 
1051 	CHECKIF(adv == NULL) {
1052 		LOG_DBG("adv is NULL");
1053 		return -EINVAL;
1054 	}
1055 
1056 	broadcast_state = broadcast_source_get_state(source);
1057 	if (broadcast_source_get_state(source) != BT_BAP_EP_STATE_QOS_CONFIGURED) {
1058 		LOG_DBG("Broadcast source invalid state: %u", broadcast_state);
1059 		return -EBADMSG;
1060 	}
1061 
1062 	bis_count = 0;
1063 	SYS_SLIST_FOR_EACH_CONTAINER(&source->subgroups, subgroup, _node) {
1064 		SYS_SLIST_FOR_EACH_CONTAINER(&subgroup->streams, stream, _node) {
1065 			bis[bis_count++] = bt_bap_stream_iso_chan_get(stream);
1066 		}
1067 	}
1068 
1069 	/* Create BIG */
1070 	param.num_bis = bis_count;
1071 	param.bis_channels = bis;
1072 	param.framing = source->qos->framing;
1073 	param.packing = source->packing;
1074 	param.interval = source->qos->interval;
1075 	param.latency = source->qos->latency;
1076 	param.encryption = source->encryption;
1077 	if (param.encryption) {
1078 		(void)memcpy(param.bcode, source->broadcast_code, sizeof(param.bcode));
1079 	}
1080 #if defined(CONFIG_BT_ISO_TEST_PARAMS)
1081 	param.irc = source->irc;
1082 	param.pto = source->pto;
1083 	param.iso_interval = source->iso_interval;
1084 #endif /* CONFIG_BT_ISO_TEST_PARAMS */
1085 
1086 	/* Set the enabling state early in case that the BIS is connected before we can manage to
1087 	 * set it afterwards
1088 	 */
1089 	broadcast_source_set_state(source, BT_BAP_EP_STATE_ENABLING);
1090 
1091 	err = bt_iso_big_create(adv, &param, &source->big);
1092 	if (err != 0) {
1093 		LOG_DBG("Failed to create BIG: %d", err);
1094 		broadcast_source_set_state(source, BT_BAP_EP_STATE_QOS_CONFIGURED);
1095 
1096 		return err;
1097 	}
1098 
1099 	return 0;
1100 }
1101 
bt_bap_broadcast_source_stop(struct bt_bap_broadcast_source * source)1102 int bt_bap_broadcast_source_stop(struct bt_bap_broadcast_source *source)
1103 {
1104 	enum bt_bap_ep_state broadcast_state;
1105 	int err;
1106 
1107 	CHECKIF(source == NULL) {
1108 		LOG_DBG("source is NULL");
1109 		return -EINVAL;
1110 	}
1111 
1112 	broadcast_state = broadcast_source_get_state(source);
1113 	if (broadcast_state != BT_BAP_EP_STATE_STREAMING &&
1114 	    broadcast_state != BT_BAP_EP_STATE_ENABLING) {
1115 		LOG_DBG("Broadcast source invalid state: %u", broadcast_state);
1116 		return -EBADMSG;
1117 	}
1118 
1119 	if (source->big == NULL) {
1120 		LOG_DBG("Source is not started");
1121 		return -EALREADY;
1122 	}
1123 
1124 	err = bt_iso_big_terminate(source->big);
1125 	if (err) {
1126 		LOG_DBG("Failed to terminate BIG (err %d)", err);
1127 		return err;
1128 	}
1129 
1130 	return 0;
1131 }
1132 
bt_bap_broadcast_source_delete(struct bt_bap_broadcast_source * source)1133 int bt_bap_broadcast_source_delete(struct bt_bap_broadcast_source *source)
1134 {
1135 	enum bt_bap_ep_state broadcast_state;
1136 
1137 	CHECKIF(source == NULL) {
1138 		LOG_DBG("source is NULL");
1139 		return -EINVAL;
1140 	}
1141 
1142 	broadcast_state = broadcast_source_get_state(source);
1143 	if (broadcast_state != BT_BAP_EP_STATE_QOS_CONFIGURED) {
1144 		LOG_DBG("Broadcast source invalid state: %u", broadcast_state);
1145 		return -EBADMSG;
1146 	}
1147 
1148 	broadcast_source_set_state(source, BT_BAP_EP_STATE_IDLE);
1149 
1150 	/* Reset the broadcast source */
1151 	broadcast_source_cleanup(source);
1152 
1153 	return 0;
1154 }
1155 
bt_bap_broadcast_source_get_base(struct bt_bap_broadcast_source * source,struct net_buf_simple * base_buf)1156 int bt_bap_broadcast_source_get_base(struct bt_bap_broadcast_source *source,
1157 				     struct net_buf_simple *base_buf)
1158 {
1159 	enum bt_bap_ep_state broadcast_state;
1160 
1161 	CHECKIF(source == NULL) {
1162 		LOG_DBG("source is NULL");
1163 		return -EINVAL;
1164 	}
1165 
1166 	CHECKIF(base_buf == NULL) {
1167 		LOG_DBG("base_buf is NULL");
1168 		return -EINVAL;
1169 	}
1170 
1171 	broadcast_state = broadcast_source_get_state(source);
1172 	if (broadcast_state == BT_BAP_EP_STATE_IDLE) {
1173 		LOG_DBG("Broadcast source invalid state: %u", broadcast_state);
1174 		return -EBADMSG;
1175 	}
1176 
1177 	if (!encode_base(source, base_buf)) {
1178 		LOG_DBG("base_buf %p with size %u not large enough", base_buf, base_buf->size);
1179 
1180 		return -EMSGSIZE;
1181 	}
1182 
1183 	return 0;
1184 }
1185 
get_broadcast_source_by_big(const struct bt_iso_big * big)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 
big_started_cb(struct bt_iso_big * big)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 
big_stopped_cb(struct bt_iso_big * big,uint8_t reason)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 
bt_bap_broadcast_source_register_cb(struct bt_bap_broadcast_source_cb * cb)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 
bt_bap_broadcast_source_unregister_cb(struct bt_bap_broadcast_source_cb * cb)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 }
1284