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 in the QoS Configured
487 		 * or Codec Configured state, we can disconnect the CIS
488 		 */
489 		if (pair_ep == NULL || pair_ep->status.state == BT_BAP_EP_STATE_QOS_CONFIGURED ||
490 			pair_ep->status.state == BT_BAP_EP_STATE_CODEC_CONFIGURED) {
491 			return true;
492 		}
493 	}
494 
495 	return false;
496 }
497 
bt_bap_stream_is_broadcast(const struct bt_bap_stream * stream)498 static bool bt_bap_stream_is_broadcast(const struct bt_bap_stream *stream)
499 {
500 	return (IS_ENABLED(CONFIG_BT_BAP_BROADCAST_SOURCE) &&
501 		bt_bap_ep_is_broadcast_src(stream->ep)) ||
502 	       (IS_ENABLED(CONFIG_BT_BAP_BROADCAST_SINK) && bt_bap_ep_is_broadcast_snk(stream->ep));
503 }
504 
bt_bap_stream_verify_qos(const struct bt_bap_stream * stream,const struct bt_bap_qos_cfg * qos)505 enum bt_bap_ascs_reason bt_bap_stream_verify_qos(const struct bt_bap_stream *stream,
506 						 const struct bt_bap_qos_cfg *qos)
507 {
508 	const struct bt_bap_qos_cfg_pref *qos_pref = &stream->ep->qos_pref;
509 
510 	if (qos_pref->latency < qos->latency) {
511 		/* Latency is a preferred value. Print debug info but do not fail. */
512 		LOG_DBG("Latency %u higher than preferred max %u", qos->latency, qos_pref->latency);
513 	}
514 
515 	if (!IN_RANGE(qos->pd, qos_pref->pd_min, qos_pref->pd_max)) {
516 		LOG_DBG("Presentation Delay not within range: min %u max %u pd %u",
517 			qos_pref->pd_min, qos_pref->pd_max, qos->pd);
518 		return BT_BAP_ASCS_REASON_PD;
519 	}
520 
521 	return BT_BAP_ASCS_REASON_NONE;
522 }
523 
bt_bap_stream_detach(struct bt_bap_stream * stream)524 void bt_bap_stream_detach(struct bt_bap_stream *stream)
525 {
526 	const bool is_broadcast = bt_bap_stream_is_broadcast(stream);
527 
528 	LOG_DBG("stream %p conn %p ep %p", stream, (void *)stream->conn, (void *)stream->ep);
529 
530 	if (stream->conn != NULL) {
531 		bt_conn_unref(stream->conn);
532 		stream->conn = NULL;
533 	}
534 	stream->codec_cfg = NULL;
535 	stream->ep->stream = NULL;
536 	stream->ep = NULL;
537 
538 	if (!is_broadcast) {
539 		const int err = bt_bap_stream_disconnect(stream);
540 
541 		if (err != 0) {
542 			LOG_DBG("Failed to disconnect stream %p: %d", stream, err);
543 		}
544 	}
545 }
546 
bt_bap_stream_disconnect(struct bt_bap_stream * stream)547 int bt_bap_stream_disconnect(struct bt_bap_stream *stream)
548 {
549 	struct bt_iso_chan *iso_chan;
550 
551 	LOG_DBG("stream %p", stream);
552 
553 	if (stream == NULL) {
554 		return -EINVAL;
555 	}
556 
557 	iso_chan = bt_bap_stream_iso_chan_get(stream);
558 	if (iso_chan == NULL || iso_chan->iso == NULL) {
559 		LOG_DBG("Not connected");
560 
561 		return -ENOTCONN;
562 	}
563 
564 	return bt_iso_chan_disconnect(iso_chan);
565 }
566 
bt_bap_stream_reset(struct bt_bap_stream * stream)567 void bt_bap_stream_reset(struct bt_bap_stream *stream)
568 {
569 	LOG_DBG("stream %p", stream);
570 
571 	if (stream == NULL) {
572 		return;
573 	}
574 
575 	if (stream->ep != NULL && stream->ep->iso != NULL) {
576 		bt_bap_iso_unbind_ep(stream->ep->iso, stream->ep);
577 	}
578 
579 	bt_bap_stream_detach(stream);
580 }
581 
conn_get_role(const struct bt_conn * conn)582 static uint8_t conn_get_role(const struct bt_conn *conn)
583 {
584 	struct bt_conn_info info;
585 	int err;
586 
587 	err = bt_conn_get_info(conn, &info);
588 	__ASSERT(err == 0, "Failed to get conn info");
589 
590 	return info.role;
591 }
592 
593 #if defined(CONFIG_BT_BAP_UNICAST_CLIENT)
594 
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)595 int bt_bap_stream_config(struct bt_conn *conn, struct bt_bap_stream *stream, struct bt_bap_ep *ep,
596 			 struct bt_audio_codec_cfg *codec_cfg)
597 {
598 	uint8_t role;
599 	int err;
600 
601 	LOG_DBG("conn %p stream %p, ep %p codec_cfg %p codec id 0x%02x "
602 	       "codec cid 0x%04x codec vid 0x%04x", (void *)conn, stream, ep,
603 	       codec_cfg, codec_cfg ? codec_cfg->id : 0, codec_cfg ? codec_cfg->cid : 0,
604 	       codec_cfg ? codec_cfg->vid : 0);
605 
606 	CHECKIF(conn == NULL || stream == NULL || codec_cfg == NULL || ep == NULL) {
607 		LOG_DBG("NULL value(s) supplied)");
608 		return -EINVAL;
609 	}
610 
611 	if (stream->conn != NULL) {
612 		LOG_DBG("Stream already configured for conn %p", (void *)stream->conn);
613 		return -EALREADY;
614 	}
615 
616 	role = conn_get_role(conn);
617 	if (role != BT_HCI_ROLE_CENTRAL) {
618 		LOG_DBG("Invalid conn role: %u, shall be central", role);
619 		return -EINVAL;
620 	}
621 
622 	switch (ep->status.state) {
623 	/* Valid only if ASE_State field = 0x00 (Idle) */
624 	case BT_BAP_EP_STATE_IDLE:
625 		/* or 0x01 (Codec Configured) */
626 	case BT_BAP_EP_STATE_CODEC_CONFIGURED:
627 		/* or 0x02 (QoS Configured) */
628 	case BT_BAP_EP_STATE_QOS_CONFIGURED:
629 		break;
630 	default:
631 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
632 		return -EBADMSG;
633 	}
634 
635 	bt_bap_stream_attach(conn, stream, ep, codec_cfg);
636 
637 	err = bt_bap_unicast_client_config(stream, codec_cfg);
638 	if (err != 0) {
639 		LOG_DBG("Failed to configure stream: %d", err);
640 		return err;
641 	}
642 
643 	return 0;
644 }
645 
bt_bap_stream_qos(struct bt_conn * conn,struct bt_bap_unicast_group * group)646 int bt_bap_stream_qos(struct bt_conn *conn, struct bt_bap_unicast_group *group)
647 {
648 	uint8_t role;
649 	int err;
650 
651 	LOG_DBG("conn %p group %p", (void *)conn, group);
652 
653 	CHECKIF(conn == NULL) {
654 		LOG_DBG("conn is NULL");
655 		return -EINVAL;
656 	}
657 
658 	CHECKIF(group == NULL) {
659 		LOG_DBG("group is NULL");
660 		return -EINVAL;
661 	}
662 
663 	if (sys_slist_is_empty(&group->streams)) {
664 		LOG_DBG("group stream list is empty");
665 		return -ENOEXEC;
666 	}
667 
668 	role = conn_get_role(conn);
669 	if (role != BT_HCI_ROLE_CENTRAL) {
670 		LOG_DBG("Invalid conn role: %u, shall be central", role);
671 		return -EINVAL;
672 	}
673 
674 	err = bt_bap_unicast_client_qos(conn, group);
675 	if (err != 0) {
676 		LOG_DBG("Failed to configure stream: %d", err);
677 		return err;
678 	}
679 
680 	return 0;
681 }
682 
bt_bap_stream_enable(struct bt_bap_stream * stream,const uint8_t meta[],size_t meta_len)683 int bt_bap_stream_enable(struct bt_bap_stream *stream, const uint8_t meta[], size_t meta_len)
684 {
685 	uint8_t role;
686 	int err;
687 
688 	LOG_DBG("stream %p", stream);
689 
690 	if (stream == NULL || stream->ep == NULL || stream->conn == NULL) {
691 		LOG_DBG("Invalid stream");
692 		return -EINVAL;
693 	}
694 
695 	role = conn_get_role(stream->conn);
696 	if (role != BT_HCI_ROLE_CENTRAL) {
697 		LOG_DBG("Invalid conn role: %u, shall be central", role);
698 		return -EINVAL;
699 	}
700 
701 	/* Valid for an ASE only if ASE_State field = 0x02 (QoS Configured) */
702 	if (stream->ep->status.state != BT_BAP_EP_STATE_QOS_CONFIGURED) {
703 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(stream->ep->status.state));
704 		return -EBADMSG;
705 	}
706 
707 	err = bt_bap_unicast_client_enable(stream, meta, meta_len);
708 	if (err != 0) {
709 		LOG_DBG("Failed to enable stream: %d", err);
710 		return err;
711 	}
712 
713 	return 0;
714 }
715 
bt_bap_stream_stop(struct bt_bap_stream * stream)716 int bt_bap_stream_stop(struct bt_bap_stream *stream)
717 {
718 	struct bt_bap_ep *ep;
719 	uint8_t role;
720 	int err;
721 
722 	if (stream == NULL || stream->ep == NULL || stream->conn == NULL) {
723 		LOG_DBG("Invalid stream");
724 		return -EINVAL;
725 	}
726 
727 	role = conn_get_role(stream->conn);
728 	if (role != BT_HCI_ROLE_CENTRAL) {
729 		LOG_DBG("Invalid conn role: %u, shall be central", role);
730 		return -EINVAL;
731 	}
732 
733 	ep = stream->ep;
734 
735 	switch (ep->status.state) {
736 	/* Valid only if ASE_State field = 0x03 (Disabling) */
737 	case BT_BAP_EP_STATE_DISABLING:
738 		break;
739 	default:
740 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
741 		return -EBADMSG;
742 	}
743 
744 	err = bt_bap_unicast_client_stop(stream);
745 	if (err != 0) {
746 		LOG_DBG("Stopping stream failed: %d", err);
747 		return err;
748 	}
749 
750 	return 0;
751 }
752 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
753 
bt_bap_stream_reconfig(struct bt_bap_stream * stream,struct bt_audio_codec_cfg * codec_cfg)754 int bt_bap_stream_reconfig(struct bt_bap_stream *stream,
755 			     struct bt_audio_codec_cfg *codec_cfg)
756 {
757 	uint8_t state;
758 	uint8_t role;
759 	int err;
760 
761 	LOG_DBG("stream %p codec_cfg %p", stream, codec_cfg);
762 
763 	CHECKIF(stream == NULL || stream->ep == NULL || stream->conn == NULL) {
764 		LOG_DBG("Invalid stream");
765 		return -EINVAL;
766 	}
767 
768 	CHECKIF(codec_cfg == NULL) {
769 		LOG_DBG("codec_cfg is NULL");
770 		return -EINVAL;
771 	}
772 
773 	state = stream->ep->status.state;
774 	switch (state) {
775 	/* Valid only if ASE_State field = 0x00 (Idle) */
776 	case BT_BAP_EP_STATE_IDLE:
777 		/* or 0x01 (Codec Configured) */
778 	case BT_BAP_EP_STATE_CODEC_CONFIGURED:
779 		/* or 0x02 (QoS Configured) */
780 	case BT_BAP_EP_STATE_QOS_CONFIGURED:
781 		break;
782 	default:
783 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(state));
784 		return -EBADMSG;
785 	}
786 
787 	role = conn_get_role(stream->conn);
788 	if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) && role == BT_HCI_ROLE_CENTRAL) {
789 		err = bt_bap_unicast_client_config(stream, codec_cfg);
790 	} else if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER) && role == BT_HCI_ROLE_PERIPHERAL) {
791 		err = bt_bap_unicast_server_reconfig(stream, codec_cfg);
792 	} else {
793 		err = -EOPNOTSUPP;
794 	}
795 
796 	if (err != 0) {
797 		LOG_DBG("reconfiguring stream failed: %d", err);
798 	} else {
799 		stream->codec_cfg = codec_cfg;
800 	}
801 
802 	return 0;
803 }
804 
805 #if defined(CONFIG_BT_BAP_UNICAST_CLIENT)
bt_bap_stream_connect(struct bt_bap_stream * stream)806 int bt_bap_stream_connect(struct bt_bap_stream *stream)
807 {
808 	uint8_t state;
809 
810 	LOG_DBG("stream %p ep %p", stream, stream == NULL ? NULL : stream->ep);
811 
812 	CHECKIF(stream == NULL || stream->ep == NULL || stream->conn == NULL) {
813 		LOG_DBG("Invalid stream");
814 		return -EINVAL;
815 	}
816 
817 	/* Valid only after the CIS ID has been assigned in QoS configured state and while we are
818 	 * not streaming
819 	 */
820 	state = stream->ep->status.state;
821 	switch (state) {
822 	case BT_BAP_EP_STATE_QOS_CONFIGURED:
823 	case BT_BAP_EP_STATE_ENABLING:
824 		break;
825 	default:
826 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(state));
827 		return -EBADMSG;
828 	}
829 
830 	/* Only a unicast client can connect a stream */
831 	if (conn_get_role(stream->conn) == BT_HCI_ROLE_CENTRAL) {
832 		return bt_bap_unicast_client_connect(stream);
833 	} else {
834 		return -EOPNOTSUPP;
835 	}
836 }
837 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
838 
bt_bap_stream_start(struct bt_bap_stream * stream)839 int bt_bap_stream_start(struct bt_bap_stream *stream)
840 {
841 	uint8_t state;
842 	uint8_t role;
843 	int err;
844 
845 	LOG_DBG("stream %p ep %p", stream, stream == NULL ? NULL : stream->ep);
846 
847 	CHECKIF(stream == NULL || stream->ep == NULL || stream->conn == NULL) {
848 		LOG_DBG("Invalid stream");
849 		return -EINVAL;
850 	}
851 
852 	state = stream->ep->status.state;
853 	switch (state) {
854 	/* Valid only if ASE_State field = 0x03 (Enabling) */
855 	case BT_BAP_EP_STATE_ENABLING:
856 		break;
857 	default:
858 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(state));
859 		return -EBADMSG;
860 	}
861 
862 	role = conn_get_role(stream->conn);
863 	if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) && role == BT_HCI_ROLE_CENTRAL) {
864 		err = bt_bap_unicast_client_start(stream);
865 	} else if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER) && role == BT_HCI_ROLE_PERIPHERAL) {
866 		err = bt_bap_unicast_server_start(stream);
867 	} else {
868 		err = -EOPNOTSUPP;
869 	}
870 
871 	if (err != 0) {
872 		LOG_DBG("Starting stream failed: %d", err);
873 		return err;
874 	}
875 
876 	return 0;
877 }
878 
bt_bap_stream_metadata(struct bt_bap_stream * stream,const uint8_t meta[],size_t meta_len)879 int bt_bap_stream_metadata(struct bt_bap_stream *stream, const uint8_t meta[], size_t meta_len)
880 {
881 	uint8_t state;
882 	uint8_t role;
883 	int err;
884 
885 	LOG_DBG("stream %p meta_len %zu", stream, meta_len);
886 
887 	CHECKIF(stream == NULL || stream->ep == NULL || stream->conn == NULL) {
888 		LOG_DBG("Invalid stream");
889 		return -EINVAL;
890 	}
891 
892 	CHECKIF((meta == NULL && meta_len != 0U) || (meta != NULL && meta_len == 0U)) {
893 		LOG_DBG("Invalid meta (%p) or len (%zu)", meta, meta_len);
894 		return -EINVAL;
895 	}
896 
897 	state = stream->ep->status.state;
898 	switch (state) {
899 	/* Valid for an ASE only if ASE_State field = 0x03 (Enabling) */
900 	case BT_BAP_EP_STATE_ENABLING:
901 	/* or 0x04 (Streaming) */
902 	case BT_BAP_EP_STATE_STREAMING:
903 		break;
904 	default:
905 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(state));
906 		return -EBADMSG;
907 	}
908 
909 	role = conn_get_role(stream->conn);
910 	if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) && role == BT_HCI_ROLE_CENTRAL) {
911 		err = bt_bap_unicast_client_metadata(stream, meta, meta_len);
912 	} else if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER) && role == BT_HCI_ROLE_PERIPHERAL) {
913 		err = bt_bap_unicast_server_metadata(stream, meta, meta_len);
914 	} else {
915 		err = -EOPNOTSUPP;
916 	}
917 
918 	if (err != 0) {
919 		LOG_DBG("Updating metadata failed: %d", err);
920 		return err;
921 	}
922 
923 	return 0;
924 }
925 
bt_bap_stream_disable(struct bt_bap_stream * stream)926 int bt_bap_stream_disable(struct bt_bap_stream *stream)
927 {
928 	uint8_t state;
929 	uint8_t role;
930 	int err;
931 
932 	LOG_DBG("stream %p", stream);
933 
934 	CHECKIF(stream == NULL || stream->ep == NULL || stream->conn == NULL) {
935 		LOG_DBG("Invalid stream");
936 		return -EINVAL;
937 	}
938 
939 	state = stream->ep->status.state;
940 	switch (state) {
941 	/* Valid only if ASE_State field = 0x03 (Enabling) */
942 	case BT_BAP_EP_STATE_ENABLING:
943 		/* or 0x04 (Streaming) */
944 	case BT_BAP_EP_STATE_STREAMING:
945 		break;
946 	default:
947 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(state));
948 		return -EBADMSG;
949 	}
950 
951 	role = conn_get_role(stream->conn);
952 	if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) && role == BT_HCI_ROLE_CENTRAL) {
953 		err = bt_bap_unicast_client_disable(stream);
954 	} else if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER) && role == BT_HCI_ROLE_PERIPHERAL) {
955 		err = bt_bap_unicast_server_disable(stream);
956 	} else {
957 		err = -EOPNOTSUPP;
958 	}
959 
960 	if (err != 0) {
961 		LOG_DBG("Disabling stream failed: %d", err);
962 		return err;
963 	}
964 
965 	return 0;
966 }
967 
bt_bap_stream_release(struct bt_bap_stream * stream)968 int bt_bap_stream_release(struct bt_bap_stream *stream)
969 {
970 	uint8_t state;
971 	uint8_t role;
972 	int err;
973 
974 	LOG_DBG("stream %p", stream);
975 
976 	CHECKIF(stream == NULL || stream->ep == NULL || stream->conn == NULL) {
977 		LOG_DBG("Invalid stream (ep %p, conn %p)", stream->ep, (void *)stream->conn);
978 		return -EINVAL;
979 	}
980 
981 	state = stream->ep->status.state;
982 	switch (state) {
983 	/* Valid only if ASE_State field = 0x01 (Codec Configured) */
984 	case BT_BAP_EP_STATE_CODEC_CONFIGURED:
985 		/* or 0x02 (QoS Configured) */
986 	case BT_BAP_EP_STATE_QOS_CONFIGURED:
987 		/* or 0x03 (Enabling) */
988 	case BT_BAP_EP_STATE_ENABLING:
989 		/* or 0x04 (Streaming) */
990 	case BT_BAP_EP_STATE_STREAMING:
991 		/* or 0x04 (Disabling) */
992 	case BT_BAP_EP_STATE_DISABLING:
993 		break;
994 	default:
995 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(state));
996 		return -EBADMSG;
997 	}
998 
999 	role = conn_get_role(stream->conn);
1000 	if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) && role == BT_HCI_ROLE_CENTRAL) {
1001 		err = bt_bap_unicast_client_release(stream);
1002 	} else if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER) && role == BT_HCI_ROLE_PERIPHERAL) {
1003 		err = bt_bap_unicast_server_release(stream);
1004 	} else {
1005 		err = -EOPNOTSUPP;
1006 	}
1007 
1008 	if (err != 0) {
1009 		LOG_DBG("Releasing stream failed: %d", err);
1010 		return err;
1011 	}
1012 
1013 	return 0;
1014 }
1015 #endif /* CONFIG_BT_BAP_UNICAST */
1016