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 = ¶m->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 = ¶m->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 ¶m->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 = ¶m->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, ¶m, &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