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