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