1 /* Bluetooth Audio Stream */
2
3 /*
4 * Copyright (c) 2020 Intel Corporation
5 * Copyright (c) 2021-2024 Nordic Semiconductor ASA
6 *
7 * SPDX-License-Identifier: Apache-2.0
8 */
9
10 #include <errno.h>
11 #include <stdbool.h>
12 #include <stddef.h>
13 #include <stdint.h>
14 #include <string.h>
15
16 #include <zephyr/autoconf.h>
17 #include <zephyr/bluetooth/bluetooth.h>
18 #include <zephyr/bluetooth/conn.h>
19 #include <zephyr/bluetooth/gap.h>
20 #include <zephyr/bluetooth/gatt.h>
21 #include <zephyr/bluetooth/hci.h>
22 #include <zephyr/bluetooth/hci_types.h>
23 #include <zephyr/bluetooth/iso.h>
24 #include <zephyr/bluetooth/audio/audio.h>
25 #include <zephyr/bluetooth/audio/bap.h>
26 #include <zephyr/kernel.h>
27 #include <zephyr/logging/log.h>
28 #include <zephyr/net_buf.h>
29 #include <zephyr/sys/__assert.h>
30 #include <zephyr/sys/byteorder.h>
31 #include <zephyr/sys/check.h>
32 #include <zephyr/sys/slist.h>
33 #include <zephyr/sys/util.h>
34 #include <zephyr/sys/util_macro.h>
35
36 #include "../host/iso_internal.h"
37
38 #include "audio_internal.h"
39 #include "bap_iso.h"
40 #include "bap_endpoint.h"
41 #include "bap_unicast_client_internal.h"
42 #include "bap_unicast_server.h"
43
44 LOG_MODULE_REGISTER(bt_bap_stream, CONFIG_BT_BAP_STREAM_LOG_LEVEL);
45
46 #if defined(CONFIG_BT_BAP_UNICAST_CLIENT) || defined(CONFIG_BT_BAP_BROADCAST_SOURCE) || \
47 defined(CONFIG_BT_BAP_BROADCAST_SINK)
bt_bap_qos_cfg_to_iso_qos(struct bt_iso_chan_io_qos * io,const struct bt_bap_qos_cfg * qos_cfg)48 void bt_bap_qos_cfg_to_iso_qos(struct bt_iso_chan_io_qos *io, const struct bt_bap_qos_cfg *qos_cfg)
49 {
50 io->sdu = qos_cfg->sdu;
51 io->phy = qos_cfg->phy;
52 io->rtn = qos_cfg->rtn;
53 #if defined(CONFIG_BT_ISO_TEST_PARAMS)
54 io->burst_number = qos_cfg->burst_number;
55 io->max_pdu = qos_cfg->max_pdu;
56 #endif /* CONFIG_BT_ISO_TEST_PARAMS */
57 }
58 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT || \
59 * CONFIG_BT_BAP_BROADCAST_SOURCE || \
60 * CONFIG_BT_BAP_BROADCAST_SINK \
61 */
62
bt_bap_stream_init(struct bt_bap_stream * stream)63 void bt_bap_stream_init(struct bt_bap_stream *stream)
64 {
65 struct bt_bap_stream_ops *ops;
66 void *user_data;
67
68 /* Save the stream->ops and stream->user_data owned by API user */
69 ops = stream->ops;
70 user_data = stream->user_data;
71
72 memset(stream, 0, sizeof(*stream));
73
74 /* Restore */
75 stream->ops = ops;
76 stream->user_data = user_data;
77 }
78
bt_bap_stream_attach(struct bt_conn * conn,struct bt_bap_stream * stream,struct bt_bap_ep * ep,struct bt_audio_codec_cfg * codec_cfg)79 void bt_bap_stream_attach(struct bt_conn *conn, struct bt_bap_stream *stream, struct bt_bap_ep *ep,
80 struct bt_audio_codec_cfg *codec_cfg)
81 {
82 LOG_DBG("conn %p stream %p ep %p codec_cfg %p", (void *)conn, stream, ep, codec_cfg);
83
84 if (conn != NULL) {
85 __ASSERT(stream->conn == NULL || stream->conn == conn,
86 "stream->conn %p already attached", (void *)stream->conn);
87 if (stream->conn == NULL) {
88 stream->conn = bt_conn_ref(conn);
89 }
90 }
91 stream->codec_cfg = codec_cfg;
92 stream->ep = ep;
93 ep->stream = stream;
94 }
95
bt_bap_stream_iso_chan_get(struct bt_bap_stream * stream)96 struct bt_iso_chan *bt_bap_stream_iso_chan_get(struct bt_bap_stream *stream)
97 {
98 if (stream != NULL && stream->ep != NULL && stream->ep->iso != NULL) {
99 return &stream->ep->iso->chan;
100 }
101
102 return NULL;
103 }
104
bt_bap_stream_cb_register(struct bt_bap_stream * stream,struct bt_bap_stream_ops * ops)105 void bt_bap_stream_cb_register(struct bt_bap_stream *stream,
106 struct bt_bap_stream_ops *ops)
107 {
108 stream->ops = ops;
109 }
110
bt_bap_ep_get_info(const struct bt_bap_ep * ep,struct bt_bap_ep_info * info)111 int bt_bap_ep_get_info(const struct bt_bap_ep *ep, struct bt_bap_ep_info *info)
112 {
113 enum bt_audio_dir dir;
114
115 CHECKIF(ep == NULL) {
116 LOG_DBG("ep is NULL");
117
118 return -EINVAL;
119 }
120
121 CHECKIF(info == NULL) {
122 LOG_DBG("info is NULL");
123
124 return -EINVAL;
125 }
126
127 dir = ep->dir;
128
129 info->id = ep->status.id;
130 info->state = ep->status.state;
131 info->dir = dir;
132 info->qos_pref = &ep->qos_pref;
133
134 if (ep->iso == NULL) {
135 info->paired_ep = NULL;
136 info->iso_chan = NULL;
137 } else {
138 info->paired_ep = bt_bap_iso_get_paired_ep(ep);
139 info->iso_chan = &ep->iso->chan;
140 }
141
142 info->can_send = false;
143 info->can_recv = false;
144 if (IS_ENABLED(CONFIG_BT_AUDIO_TX) && ep->stream != NULL) {
145 if (IS_ENABLED(CONFIG_BT_BAP_BROADCAST_SOURCE) && bt_bap_ep_is_broadcast_src(ep)) {
146 info->can_send = true;
147 } else if (IS_ENABLED(CONFIG_BT_BAP_BROADCAST_SINK) &&
148 bt_bap_ep_is_broadcast_snk(ep)) {
149 info->can_recv = true;
150 } else if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) &&
151 bt_bap_ep_is_unicast_client(ep)) {
152 /* dir is not initialized before the connection is set */
153 if (ep->stream->conn != NULL) {
154 info->can_send = dir == BT_AUDIO_DIR_SINK;
155 info->can_recv = dir == BT_AUDIO_DIR_SOURCE;
156 }
157 } else if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER)) {
158 /* dir is not initialized before the connection is set */
159 if (ep->stream->conn != NULL) {
160 info->can_send = dir == BT_AUDIO_DIR_SOURCE;
161 info->can_recv = dir == BT_AUDIO_DIR_SINK;
162 }
163 }
164 }
165
166 return 0;
167 }
168
bt_audio_verify_qos(const struct bt_bap_qos_cfg * qos)169 enum bt_bap_ascs_reason bt_audio_verify_qos(const struct bt_bap_qos_cfg *qos)
170 {
171 if (qos->interval < BT_ISO_SDU_INTERVAL_MIN ||
172 qos->interval > BT_ISO_SDU_INTERVAL_MAX) {
173 LOG_DBG("Interval not within allowed range: %u (%u-%u)", qos->interval,
174 BT_ISO_SDU_INTERVAL_MIN, BT_ISO_SDU_INTERVAL_MAX);
175 return BT_BAP_ASCS_REASON_INTERVAL;
176 }
177
178 if (qos->framing > BT_BAP_QOS_CFG_FRAMING_FRAMED) {
179 LOG_DBG("Invalid Framing 0x%02x", qos->framing);
180 return BT_BAP_ASCS_REASON_FRAMING;
181 }
182
183 if (qos->phy != BT_BAP_QOS_CFG_1M && qos->phy != BT_BAP_QOS_CFG_2M &&
184 qos->phy != BT_BAP_QOS_CFG_CODED) {
185 LOG_DBG("Invalid PHY 0x%02x", qos->phy);
186 return BT_BAP_ASCS_REASON_PHY;
187 }
188
189 if (qos->sdu > BT_ISO_MAX_SDU) {
190 LOG_DBG("Invalid SDU %u", qos->sdu);
191 return BT_BAP_ASCS_REASON_SDU;
192 }
193
194 #if defined(CONFIG_BT_BAP_BROADCAST_SOURCE) || defined(CONFIG_BT_BAP_UNICAST)
195 if (qos->latency < BT_ISO_LATENCY_MIN ||
196 qos->latency > BT_ISO_LATENCY_MAX) {
197 LOG_DBG("Invalid Latency %u", qos->latency);
198 return BT_BAP_ASCS_REASON_LATENCY;
199 }
200 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE || CONFIG_BT_BAP_UNICAST */
201
202 if (qos->pd > BT_AUDIO_PD_MAX) {
203 LOG_DBG("Invalid presentation delay %u", qos->pd);
204 return BT_BAP_ASCS_REASON_PD;
205 }
206
207 return BT_BAP_ASCS_REASON_NONE;
208 }
209
bt_audio_valid_codec_cfg(const struct bt_audio_codec_cfg * codec_cfg)210 bool bt_audio_valid_codec_cfg(const struct bt_audio_codec_cfg *codec_cfg)
211 {
212 if (codec_cfg == NULL) {
213 LOG_DBG("codec is NULL");
214 return false;
215 }
216
217 if (codec_cfg->id == BT_HCI_CODING_FORMAT_LC3) {
218 if (codec_cfg->cid != 0U) {
219 LOG_DBG("codec_cfg->cid (%u) is invalid", codec_cfg->cid);
220 return false;
221 }
222
223 if (codec_cfg->vid != 0U) {
224 LOG_DBG("codec_cfg->vid (%u) is invalid", codec_cfg->vid);
225 return false;
226 }
227 }
228
229 #if CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0
230 /* Verify that codec configuration length is 0 when using
231 * BT_HCI_CODING_FORMAT_TRANSPARENT as per the core spec, 5.4, Vol 4, Part E, 7.8.109
232 */
233 if (codec_cfg->id == BT_HCI_CODING_FORMAT_TRANSPARENT && codec_cfg->data_len != 0) {
234 LOG_DBG("Invalid data_len %zu for codec_id %u", codec_cfg->data_len, codec_cfg->id);
235 return false;
236 }
237
238 if (codec_cfg->data_len > CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE) {
239 LOG_DBG("codec_cfg->data_len (%zu) is invalid", codec_cfg->data_len);
240 return false;
241 }
242
243 if (codec_cfg->id == BT_HCI_CODING_FORMAT_LC3 &&
244 !bt_audio_valid_ltv(codec_cfg->data, codec_cfg->data_len)) {
245 LOG_DBG("codec_cfg->data not valid LTV");
246 return false;
247 }
248 #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0 */
249
250 #if CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE > 0
251 if (codec_cfg->meta_len > CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE) {
252 LOG_DBG("codec_cfg->meta_len (%zu) is invalid", codec_cfg->meta_len);
253 return false;
254 }
255
256 if (codec_cfg->id == BT_HCI_CODING_FORMAT_LC3 &&
257 !bt_audio_valid_ltv(codec_cfg->data, codec_cfg->data_len)) {
258 LOG_DBG("codec_cfg->meta not valid LTV");
259 return false;
260 }
261 #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE > 0 */
262
263 return true;
264 }
265
bt_bap_valid_qos_pref(const struct bt_bap_qos_cfg_pref * qos_pref)266 bool bt_bap_valid_qos_pref(const struct bt_bap_qos_cfg_pref *qos_pref)
267 {
268 const uint8_t phy_mask = BT_GAP_LE_PHY_1M | BT_GAP_LE_PHY_2M | BT_GAP_LE_PHY_CODED;
269
270 if ((qos_pref->phy & (~phy_mask)) != 0U) {
271 LOG_DBG("Invalid phy: %u", qos_pref->phy);
272
273 return false;
274 }
275
276 if (!IN_RANGE(qos_pref->latency, BT_ISO_LATENCY_MIN, BT_ISO_LATENCY_MAX)) {
277 LOG_DBG("Invalid latency: %u", qos_pref->latency);
278
279 return false;
280 }
281
282 if (qos_pref->pd_min > BT_AUDIO_PD_MAX) {
283 LOG_DBG("Invalid pd_min: %u", qos_pref->pd_min);
284
285 return false;
286 }
287
288 if (qos_pref->pd_max > BT_AUDIO_PD_MAX) {
289 LOG_DBG("Invalid pd_min: %u", qos_pref->pd_min);
290
291 return false;
292 }
293
294 if (qos_pref->pd_max < qos_pref->pd_min) {
295 LOG_DBG("Invalid combination of pd_min %u and pd_max: %u", qos_pref->pd_min,
296 qos_pref->pd_max);
297
298 return false;
299 }
300
301 if (qos_pref->pref_pd_min != BT_AUDIO_PD_PREF_NONE) {
302 /* If pref_pd_min != BT_AUDIO_PD_PREF_NONE then pd_min <= pref_pd_min <= pd_max */
303 if (!IN_RANGE(qos_pref->pref_pd_min, qos_pref->pd_min, qos_pref->pd_max)) {
304 LOG_DBG("Invalid combination of pref_pd_min %u, pd_min %u and pd_max: %u",
305 qos_pref->pref_pd_min, qos_pref->pd_min, qos_pref->pd_max);
306
307 return false;
308 }
309 }
310
311 if (qos_pref->pref_pd_max != BT_AUDIO_PD_PREF_NONE) {
312 /* If pref_pd_min == BT_AUDIO_PD_PREF_NONE then pd_min <= pref_pd_max <= pd_max
313 *
314 * If pref_pd_min != BT_AUDIO_PD_PREF_NONE then
315 * pd_min <= pref_pd_min <= pref_pd_max <= pd_max
316 */
317 if (qos_pref->pref_pd_min == BT_AUDIO_PD_PREF_NONE) {
318 if (!IN_RANGE(qos_pref->pref_pd_max, qos_pref->pd_min, qos_pref->pd_max)) {
319 LOG_DBG("Invalid combination of pref_pd_max %u, pd_min %u and "
320 "pd_max: %u",
321 qos_pref->pref_pd_max, qos_pref->pd_min, qos_pref->pd_max);
322
323 return false;
324 }
325 } else {
326 if (!IN_RANGE(qos_pref->pref_pd_max, qos_pref->pref_pd_min,
327 qos_pref->pd_max)) {
328 LOG_DBG("Invalid combination of pref_pd_max %u, pref_pd_min %u and "
329 "pd_max: %u",
330 qos_pref->pref_pd_max, qos_pref->pd_min, qos_pref->pd_max);
331
332 return false;
333 }
334 }
335 }
336
337 return true;
338 }
339
340 #if defined(CONFIG_BT_AUDIO_TX)
bt_bap_stream_can_send(const struct bt_bap_stream * stream)341 static bool bt_bap_stream_can_send(const struct bt_bap_stream *stream)
342 {
343 struct bt_bap_ep_info info;
344 int err;
345
346 if (stream == NULL || stream->ep == NULL) {
347 return false;
348 }
349
350 err = bt_bap_ep_get_info(stream->ep, &info);
351 if (err != 0) {
352 return false;
353 }
354
355 return info.can_send;
356 }
357
bap_stream_send(struct bt_bap_stream * stream,struct net_buf * buf,uint16_t seq_num,uint32_t ts,bool has_ts)358 static int bap_stream_send(struct bt_bap_stream *stream, struct net_buf *buf, uint16_t seq_num,
359 uint32_t ts, bool has_ts)
360 {
361 struct bt_iso_chan *iso_chan;
362 struct bt_bap_ep *ep;
363 int ret;
364
365 if (stream == NULL) {
366 LOG_DBG("stream is NULL");
367 return -EINVAL;
368 }
369
370 if (stream->ep == NULL) {
371 LOG_DBG("stream->ep %p is NULL", stream);
372 return -EINVAL;
373 }
374
375 if (!bt_bap_stream_can_send(stream)) {
376 LOG_DBG("Stream is not configured for TX");
377
378 return -EINVAL;
379 }
380
381 ep = stream->ep;
382
383 if (ep->status.state != BT_BAP_EP_STATE_STREAMING) {
384 LOG_DBG("Channel %p not ready for streaming (state: %s)", stream,
385 bt_bap_ep_state_str(ep->status.state));
386 return -EBADMSG;
387 }
388
389 iso_chan = bt_bap_stream_iso_chan_get(stream);
390
391 if (has_ts) {
392 ret = bt_iso_chan_send_ts(iso_chan, buf, seq_num, ts);
393 } else {
394 ret = bt_iso_chan_send(iso_chan, buf, seq_num);
395 }
396
397 if (ret < 0) {
398 return ret;
399 }
400
401 #if defined(CONFIG_BT_BAP_DEBUG_STREAM_SEQ_NUM)
402 if (stream->_prev_seq_num != 0U && seq_num != 0U &&
403 (stream->_prev_seq_num + 1U) != seq_num) {
404 LOG_WRN("Unexpected seq_num diff between %u and %u for %p", stream->_prev_seq_num,
405 seq_num, stream);
406 }
407
408 stream->_prev_seq_num = seq_num;
409 #endif /* CONFIG_BT_BAP_DEBUG_STREAM_SEQ_NUM */
410
411 return ret;
412 }
413
bt_bap_stream_send(struct bt_bap_stream * stream,struct net_buf * buf,uint16_t seq_num)414 int bt_bap_stream_send(struct bt_bap_stream *stream, struct net_buf *buf, uint16_t seq_num)
415 {
416 return bap_stream_send(stream, buf, seq_num, 0, false);
417 }
418
bt_bap_stream_send_ts(struct bt_bap_stream * stream,struct net_buf * buf,uint16_t seq_num,uint32_t ts)419 int bt_bap_stream_send_ts(struct bt_bap_stream *stream, struct net_buf *buf, uint16_t seq_num,
420 uint32_t ts)
421 {
422 return bap_stream_send(stream, buf, seq_num, ts, true);
423 }
424
bt_bap_stream_get_tx_sync(struct bt_bap_stream * stream,struct bt_iso_tx_info * info)425 int bt_bap_stream_get_tx_sync(struct bt_bap_stream *stream, struct bt_iso_tx_info *info)
426 {
427 struct bt_iso_chan *iso_chan;
428
429 CHECKIF(stream == NULL) {
430 LOG_DBG("stream is null");
431
432 return -EINVAL;
433 }
434
435 CHECKIF(info == NULL) {
436 LOG_DBG("info is null");
437
438 return -EINVAL;
439 }
440
441 if (!bt_bap_stream_can_send(stream)) {
442 LOG_DBG("Stream is not configured for TX");
443
444 return -EINVAL;
445 }
446
447 iso_chan = bt_bap_stream_iso_chan_get(stream);
448 if (iso_chan == NULL) {
449 LOG_DBG("Could not get iso channel from stream %p", stream);
450 return -EINVAL;
451 }
452
453 return bt_iso_chan_get_tx_sync(iso_chan, info);
454 }
455 #endif /* CONFIG_BT_AUDIO_TX */
456
457 #if defined(CONFIG_BT_BAP_UNICAST)
458
459 /** Checks if the stream can terminate the CIS
460 *
461 * If the CIS is used for another stream, or if the CIS is not in the connected
462 * state it will return false.
463 */
bt_bap_stream_can_disconnect(const struct bt_bap_stream * stream)464 bool bt_bap_stream_can_disconnect(const struct bt_bap_stream *stream)
465 {
466 const struct bt_bap_ep *stream_ep;
467 enum bt_iso_state iso_state;
468
469 if (stream == NULL) {
470 return false;
471 }
472
473 stream_ep = stream->ep;
474
475 if (stream_ep == NULL || stream_ep->iso == NULL) {
476 return false;
477 }
478
479 iso_state = stream_ep->iso->chan.state;
480
481 if (iso_state == BT_ISO_STATE_CONNECTED || iso_state == BT_ISO_STATE_CONNECTING) {
482 const struct bt_bap_ep *pair_ep;
483
484 pair_ep = bt_bap_iso_get_paired_ep(stream_ep);
485
486 /* If there are no paired endpoint, or the paired endpoint is
487 * not in the streaming state, we can disconnect the CIS
488 */
489 if (pair_ep == NULL || pair_ep->status.state != BT_BAP_EP_STATE_STREAMING) {
490 return true;
491 }
492 }
493
494 return false;
495 }
496
bt_bap_stream_is_broadcast(const struct bt_bap_stream * stream)497 static bool bt_bap_stream_is_broadcast(const struct bt_bap_stream *stream)
498 {
499 return (IS_ENABLED(CONFIG_BT_BAP_BROADCAST_SOURCE) &&
500 bt_bap_ep_is_broadcast_src(stream->ep)) ||
501 (IS_ENABLED(CONFIG_BT_BAP_BROADCAST_SINK) && bt_bap_ep_is_broadcast_snk(stream->ep));
502 }
503
bt_bap_stream_verify_qos(const struct bt_bap_stream * stream,const struct bt_bap_qos_cfg * qos)504 enum bt_bap_ascs_reason bt_bap_stream_verify_qos(const struct bt_bap_stream *stream,
505 const struct bt_bap_qos_cfg *qos)
506 {
507 const struct bt_bap_qos_cfg_pref *qos_pref = &stream->ep->qos_pref;
508
509 if (qos_pref->latency < qos->latency) {
510 /* Latency is a preferred value. Print debug info but do not fail. */
511 LOG_DBG("Latency %u higher than preferred max %u", qos->latency, qos_pref->latency);
512 }
513
514 if (!IN_RANGE(qos->pd, qos_pref->pd_min, qos_pref->pd_max)) {
515 LOG_DBG("Presentation Delay not within range: min %u max %u pd %u",
516 qos_pref->pd_min, qos_pref->pd_max, qos->pd);
517 return BT_BAP_ASCS_REASON_PD;
518 }
519
520 return BT_BAP_ASCS_REASON_NONE;
521 }
522
bt_bap_stream_detach(struct bt_bap_stream * stream)523 void bt_bap_stream_detach(struct bt_bap_stream *stream)
524 {
525 const bool is_broadcast = bt_bap_stream_is_broadcast(stream);
526
527 LOG_DBG("stream %p conn %p ep %p", stream, (void *)stream->conn, (void *)stream->ep);
528
529 if (stream->conn != NULL) {
530 bt_conn_unref(stream->conn);
531 stream->conn = NULL;
532 }
533 stream->codec_cfg = NULL;
534 stream->ep->stream = NULL;
535 stream->ep = NULL;
536
537 if (!is_broadcast) {
538 const int err = bt_bap_stream_disconnect(stream);
539
540 if (err != 0) {
541 LOG_DBG("Failed to disconnect stream %p: %d", stream, err);
542 }
543 }
544 }
545
bt_bap_stream_disconnect(struct bt_bap_stream * stream)546 int bt_bap_stream_disconnect(struct bt_bap_stream *stream)
547 {
548 struct bt_iso_chan *iso_chan;
549
550 LOG_DBG("stream %p", stream);
551
552 if (stream == NULL) {
553 return -EINVAL;
554 }
555
556 iso_chan = bt_bap_stream_iso_chan_get(stream);
557 if (iso_chan == NULL || iso_chan->iso == NULL) {
558 LOG_DBG("Not connected");
559
560 return -ENOTCONN;
561 }
562
563 return bt_iso_chan_disconnect(iso_chan);
564 }
565
bt_bap_stream_reset(struct bt_bap_stream * stream)566 void bt_bap_stream_reset(struct bt_bap_stream *stream)
567 {
568 LOG_DBG("stream %p", stream);
569
570 if (stream == NULL) {
571 return;
572 }
573
574 if (stream->ep != NULL && stream->ep->iso != NULL) {
575 bt_bap_iso_unbind_ep(stream->ep->iso, stream->ep);
576 }
577
578 bt_bap_stream_detach(stream);
579 }
580
conn_get_role(const struct bt_conn * conn)581 static uint8_t conn_get_role(const struct bt_conn *conn)
582 {
583 struct bt_conn_info info;
584 int err;
585
586 err = bt_conn_get_info(conn, &info);
587 __ASSERT(err == 0, "Failed to get conn info");
588
589 return info.role;
590 }
591
592 #if defined(CONFIG_BT_BAP_UNICAST_CLIENT)
593
bt_bap_stream_config(struct bt_conn * conn,struct bt_bap_stream * stream,struct bt_bap_ep * ep,struct bt_audio_codec_cfg * codec_cfg)594 int bt_bap_stream_config(struct bt_conn *conn, struct bt_bap_stream *stream, struct bt_bap_ep *ep,
595 struct bt_audio_codec_cfg *codec_cfg)
596 {
597 uint8_t role;
598 int err;
599
600 LOG_DBG("conn %p stream %p, ep %p codec_cfg %p codec id 0x%02x "
601 "codec cid 0x%04x codec vid 0x%04x", (void *)conn, stream, ep,
602 codec_cfg, codec_cfg ? codec_cfg->id : 0, codec_cfg ? codec_cfg->cid : 0,
603 codec_cfg ? codec_cfg->vid : 0);
604
605 CHECKIF(conn == NULL || stream == NULL || codec_cfg == NULL || ep == NULL) {
606 LOG_DBG("NULL value(s) supplied)");
607 return -EINVAL;
608 }
609
610 if (stream->conn != NULL) {
611 LOG_DBG("Stream already configured for conn %p", (void *)stream->conn);
612 return -EALREADY;
613 }
614
615 role = conn_get_role(conn);
616 if (role != BT_HCI_ROLE_CENTRAL) {
617 LOG_DBG("Invalid conn role: %u, shall be central", role);
618 return -EINVAL;
619 }
620
621 switch (ep->status.state) {
622 /* Valid only if ASE_State field = 0x00 (Idle) */
623 case BT_BAP_EP_STATE_IDLE:
624 /* or 0x01 (Codec Configured) */
625 case BT_BAP_EP_STATE_CODEC_CONFIGURED:
626 /* or 0x02 (QoS Configured) */
627 case BT_BAP_EP_STATE_QOS_CONFIGURED:
628 break;
629 default:
630 LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
631 return -EBADMSG;
632 }
633
634 bt_bap_stream_attach(conn, stream, ep, codec_cfg);
635
636 err = bt_bap_unicast_client_config(stream, codec_cfg);
637 if (err != 0) {
638 LOG_DBG("Failed to configure stream: %d", err);
639 return err;
640 }
641
642 return 0;
643 }
644
bt_bap_stream_qos(struct bt_conn * conn,struct bt_bap_unicast_group * group)645 int bt_bap_stream_qos(struct bt_conn *conn, struct bt_bap_unicast_group *group)
646 {
647 uint8_t role;
648 int err;
649
650 LOG_DBG("conn %p group %p", (void *)conn, group);
651
652 CHECKIF(conn == NULL) {
653 LOG_DBG("conn is NULL");
654 return -EINVAL;
655 }
656
657 CHECKIF(group == NULL) {
658 LOG_DBG("group is NULL");
659 return -EINVAL;
660 }
661
662 if (sys_slist_is_empty(&group->streams)) {
663 LOG_DBG("group stream list is empty");
664 return -ENOEXEC;
665 }
666
667 role = conn_get_role(conn);
668 if (role != BT_HCI_ROLE_CENTRAL) {
669 LOG_DBG("Invalid conn role: %u, shall be central", role);
670 return -EINVAL;
671 }
672
673 err = bt_bap_unicast_client_qos(conn, group);
674 if (err != 0) {
675 LOG_DBG("Failed to configure stream: %d", err);
676 return err;
677 }
678
679 return 0;
680 }
681
bt_bap_stream_enable(struct bt_bap_stream * stream,const uint8_t meta[],size_t meta_len)682 int bt_bap_stream_enable(struct bt_bap_stream *stream, const uint8_t meta[], size_t meta_len)
683 {
684 uint8_t role;
685 int err;
686
687 LOG_DBG("stream %p", stream);
688
689 if (stream == NULL || stream->ep == NULL || stream->conn == NULL) {
690 LOG_DBG("Invalid stream");
691 return -EINVAL;
692 }
693
694 role = conn_get_role(stream->conn);
695 if (role != BT_HCI_ROLE_CENTRAL) {
696 LOG_DBG("Invalid conn role: %u, shall be central", role);
697 return -EINVAL;
698 }
699
700 /* Valid for an ASE only if ASE_State field = 0x02 (QoS Configured) */
701 if (stream->ep->status.state != BT_BAP_EP_STATE_QOS_CONFIGURED) {
702 LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(stream->ep->status.state));
703 return -EBADMSG;
704 }
705
706 err = bt_bap_unicast_client_enable(stream, meta, meta_len);
707 if (err != 0) {
708 LOG_DBG("Failed to enable stream: %d", err);
709 return err;
710 }
711
712 return 0;
713 }
714
bt_bap_stream_stop(struct bt_bap_stream * stream)715 int bt_bap_stream_stop(struct bt_bap_stream *stream)
716 {
717 struct bt_bap_ep *ep;
718 uint8_t role;
719 int err;
720
721 if (stream == NULL || stream->ep == NULL || stream->conn == NULL) {
722 LOG_DBG("Invalid stream");
723 return -EINVAL;
724 }
725
726 role = conn_get_role(stream->conn);
727 if (role != BT_HCI_ROLE_CENTRAL) {
728 LOG_DBG("Invalid conn role: %u, shall be central", role);
729 return -EINVAL;
730 }
731
732 ep = stream->ep;
733
734 switch (ep->status.state) {
735 /* Valid only if ASE_State field = 0x03 (Disabling) */
736 case BT_BAP_EP_STATE_DISABLING:
737 break;
738 default:
739 LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
740 return -EBADMSG;
741 }
742
743 err = bt_bap_unicast_client_stop(stream);
744 if (err != 0) {
745 LOG_DBG("Stopping stream failed: %d", err);
746 return err;
747 }
748
749 return 0;
750 }
751 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
752
bt_bap_stream_reconfig(struct bt_bap_stream * stream,struct bt_audio_codec_cfg * codec_cfg)753 int bt_bap_stream_reconfig(struct bt_bap_stream *stream,
754 struct bt_audio_codec_cfg *codec_cfg)
755 {
756 uint8_t state;
757 uint8_t role;
758 int err;
759
760 LOG_DBG("stream %p codec_cfg %p", stream, codec_cfg);
761
762 CHECKIF(stream == NULL || stream->ep == NULL || stream->conn == NULL) {
763 LOG_DBG("Invalid stream");
764 return -EINVAL;
765 }
766
767 CHECKIF(codec_cfg == NULL) {
768 LOG_DBG("codec_cfg is NULL");
769 return -EINVAL;
770 }
771
772 state = stream->ep->status.state;
773 switch (state) {
774 /* Valid only if ASE_State field = 0x00 (Idle) */
775 case BT_BAP_EP_STATE_IDLE:
776 /* or 0x01 (Codec Configured) */
777 case BT_BAP_EP_STATE_CODEC_CONFIGURED:
778 /* or 0x02 (QoS Configured) */
779 case BT_BAP_EP_STATE_QOS_CONFIGURED:
780 break;
781 default:
782 LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(state));
783 return -EBADMSG;
784 }
785
786 role = conn_get_role(stream->conn);
787 if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) && role == BT_HCI_ROLE_CENTRAL) {
788 err = bt_bap_unicast_client_config(stream, codec_cfg);
789 } else if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER) && role == BT_HCI_ROLE_PERIPHERAL) {
790 err = bt_bap_unicast_server_reconfig(stream, codec_cfg);
791 } else {
792 err = -EOPNOTSUPP;
793 }
794
795 if (err != 0) {
796 LOG_DBG("reconfiguring stream failed: %d", err);
797 } else {
798 stream->codec_cfg = codec_cfg;
799 }
800
801 return 0;
802 }
803
804 #if defined(CONFIG_BT_BAP_UNICAST_CLIENT)
bt_bap_stream_connect(struct bt_bap_stream * stream)805 int bt_bap_stream_connect(struct bt_bap_stream *stream)
806 {
807 uint8_t state;
808
809 LOG_DBG("stream %p ep %p", stream, stream == NULL ? NULL : stream->ep);
810
811 CHECKIF(stream == NULL || stream->ep == NULL || stream->conn == NULL) {
812 LOG_DBG("Invalid stream");
813 return -EINVAL;
814 }
815
816 /* Valid only after the CIS ID has been assigned in QoS configured state and while we are
817 * not streaming
818 */
819 state = stream->ep->status.state;
820 switch (state) {
821 case BT_BAP_EP_STATE_QOS_CONFIGURED:
822 case BT_BAP_EP_STATE_ENABLING:
823 break;
824 default:
825 LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(state));
826 return -EBADMSG;
827 }
828
829 /* Only a unicast client can connect a stream */
830 if (conn_get_role(stream->conn) == BT_HCI_ROLE_CENTRAL) {
831 return bt_bap_unicast_client_connect(stream);
832 } else {
833 return -EOPNOTSUPP;
834 }
835 }
836 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
837
bt_bap_stream_start(struct bt_bap_stream * stream)838 int bt_bap_stream_start(struct bt_bap_stream *stream)
839 {
840 uint8_t state;
841 uint8_t role;
842 int err;
843
844 LOG_DBG("stream %p ep %p", stream, stream == NULL ? NULL : stream->ep);
845
846 CHECKIF(stream == NULL || stream->ep == NULL || stream->conn == NULL) {
847 LOG_DBG("Invalid stream");
848 return -EINVAL;
849 }
850
851 state = stream->ep->status.state;
852 switch (state) {
853 /* Valid only if ASE_State field = 0x03 (Enabling) */
854 case BT_BAP_EP_STATE_ENABLING:
855 break;
856 default:
857 LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(state));
858 return -EBADMSG;
859 }
860
861 role = conn_get_role(stream->conn);
862 if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) && role == BT_HCI_ROLE_CENTRAL) {
863 err = bt_bap_unicast_client_start(stream);
864 } else if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER) && role == BT_HCI_ROLE_PERIPHERAL) {
865 err = bt_bap_unicast_server_start(stream);
866 } else {
867 err = -EOPNOTSUPP;
868 }
869
870 if (err != 0) {
871 LOG_DBG("Starting stream failed: %d", err);
872 return err;
873 }
874
875 return 0;
876 }
877
bt_bap_stream_metadata(struct bt_bap_stream * stream,const uint8_t meta[],size_t meta_len)878 int bt_bap_stream_metadata(struct bt_bap_stream *stream, const uint8_t meta[], size_t meta_len)
879 {
880 uint8_t state;
881 uint8_t role;
882 int err;
883
884 LOG_DBG("stream %p meta_len %zu", stream, meta_len);
885
886 CHECKIF(stream == NULL || stream->ep == NULL || stream->conn == NULL) {
887 LOG_DBG("Invalid stream");
888 return -EINVAL;
889 }
890
891 CHECKIF((meta == NULL && meta_len != 0U) || (meta != NULL && meta_len == 0U)) {
892 LOG_DBG("Invalid meta (%p) or len (%zu)", meta, meta_len);
893 return -EINVAL;
894 }
895
896 state = stream->ep->status.state;
897 switch (state) {
898 /* Valid for an ASE only if ASE_State field = 0x03 (Enabling) */
899 case BT_BAP_EP_STATE_ENABLING:
900 /* or 0x04 (Streaming) */
901 case BT_BAP_EP_STATE_STREAMING:
902 break;
903 default:
904 LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(state));
905 return -EBADMSG;
906 }
907
908 role = conn_get_role(stream->conn);
909 if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) && role == BT_HCI_ROLE_CENTRAL) {
910 err = bt_bap_unicast_client_metadata(stream, meta, meta_len);
911 } else if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER) && role == BT_HCI_ROLE_PERIPHERAL) {
912 err = bt_bap_unicast_server_metadata(stream, meta, meta_len);
913 } else {
914 err = -EOPNOTSUPP;
915 }
916
917 if (err != 0) {
918 LOG_DBG("Updating metadata failed: %d", err);
919 return err;
920 }
921
922 return 0;
923 }
924
bt_bap_stream_disable(struct bt_bap_stream * stream)925 int bt_bap_stream_disable(struct bt_bap_stream *stream)
926 {
927 uint8_t state;
928 uint8_t role;
929 int err;
930
931 LOG_DBG("stream %p", stream);
932
933 CHECKIF(stream == NULL || stream->ep == NULL || stream->conn == NULL) {
934 LOG_DBG("Invalid stream");
935 return -EINVAL;
936 }
937
938 state = stream->ep->status.state;
939 switch (state) {
940 /* Valid only if ASE_State field = 0x03 (Enabling) */
941 case BT_BAP_EP_STATE_ENABLING:
942 /* or 0x04 (Streaming) */
943 case BT_BAP_EP_STATE_STREAMING:
944 break;
945 default:
946 LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(state));
947 return -EBADMSG;
948 }
949
950 role = conn_get_role(stream->conn);
951 if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) && role == BT_HCI_ROLE_CENTRAL) {
952 err = bt_bap_unicast_client_disable(stream);
953 } else if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER) && role == BT_HCI_ROLE_PERIPHERAL) {
954 err = bt_bap_unicast_server_disable(stream);
955 } else {
956 err = -EOPNOTSUPP;
957 }
958
959 if (err != 0) {
960 LOG_DBG("Disabling stream failed: %d", err);
961 return err;
962 }
963
964 return 0;
965 }
966
bt_bap_stream_release(struct bt_bap_stream * stream)967 int bt_bap_stream_release(struct bt_bap_stream *stream)
968 {
969 uint8_t state;
970 uint8_t role;
971 int err;
972
973 LOG_DBG("stream %p", stream);
974
975 CHECKIF(stream == NULL || stream->ep == NULL || stream->conn == NULL) {
976 LOG_DBG("Invalid stream (ep %p, conn %p)", stream->ep, (void *)stream->conn);
977 return -EINVAL;
978 }
979
980 state = stream->ep->status.state;
981 switch (state) {
982 /* Valid only if ASE_State field = 0x01 (Codec Configured) */
983 case BT_BAP_EP_STATE_CODEC_CONFIGURED:
984 /* or 0x02 (QoS Configured) */
985 case BT_BAP_EP_STATE_QOS_CONFIGURED:
986 /* or 0x03 (Enabling) */
987 case BT_BAP_EP_STATE_ENABLING:
988 /* or 0x04 (Streaming) */
989 case BT_BAP_EP_STATE_STREAMING:
990 /* or 0x04 (Disabling) */
991 case BT_BAP_EP_STATE_DISABLING:
992 break;
993 default:
994 LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(state));
995 return -EBADMSG;
996 }
997
998 role = conn_get_role(stream->conn);
999 if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) && role == BT_HCI_ROLE_CENTRAL) {
1000 err = bt_bap_unicast_client_release(stream);
1001 } else if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER) && role == BT_HCI_ROLE_PERIPHERAL) {
1002 err = bt_bap_unicast_server_release(stream);
1003 } else {
1004 err = -EOPNOTSUPP;
1005 }
1006
1007 if (err != 0) {
1008 LOG_DBG("Releasing stream failed: %d", err);
1009 return err;
1010 }
1011
1012 return 0;
1013 }
1014 #endif /* CONFIG_BT_BAP_UNICAST */
1015