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