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/gatt.h>
20 #include <zephyr/bluetooth/hci.h>
21 #include <zephyr/bluetooth/hci_types.h>
22 #include <zephyr/bluetooth/iso.h>
23 #include <zephyr/bluetooth/audio/audio.h>
24 #include <zephyr/bluetooth/audio/bap.h>
25 #include <zephyr/kernel.h>
26 #include <zephyr/logging/log.h>
27 #include <zephyr/net/buf.h>
28 #include <zephyr/sys/__assert.h>
29 #include <zephyr/sys/byteorder.h>
30 #include <zephyr/sys/check.h>
31 #include <zephyr/sys/slist.h>
32 #include <zephyr/sys/util.h>
33 #include <zephyr/sys/util_macro.h>
34 
35 #include "../host/iso_internal.h"
36 
37 #include "audio_internal.h"
38 #include "bap_iso.h"
39 #include "bap_endpoint.h"
40 #include "bap_unicast_client_internal.h"
41 #include "bap_unicast_server.h"
42 
43 LOG_MODULE_REGISTER(bt_bap_stream, CONFIG_BT_BAP_STREAM_LOG_LEVEL);
44 
45 #if defined(CONFIG_BT_BAP_UNICAST_CLIENT) || defined(CONFIG_BT_BAP_BROADCAST_SOURCE) ||            \
46 	defined(CONFIG_BT_BAP_BROADCAST_SINK)
bt_audio_codec_qos_to_iso_qos(struct bt_iso_chan_io_qos * io,const struct bt_audio_codec_qos * codec_qos)47 void bt_audio_codec_qos_to_iso_qos(struct bt_iso_chan_io_qos *io,
48 				   const struct bt_audio_codec_qos *codec_qos)
49 {
50 	io->sdu = codec_qos->sdu;
51 	io->phy = codec_qos->phy;
52 	io->rtn = codec_qos->rtn;
53 #if defined(CONFIG_BT_ISO_TEST_PARAMS)
54 	io->burst_number = codec_qos->burst_number;
55 	io->max_pdu = codec_qos->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_audio_codec_qos * qos)169 enum bt_bap_ascs_reason bt_audio_verify_qos(const struct bt_audio_codec_qos *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_AUDIO_CODEC_QOS_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_AUDIO_CODEC_QOS_1M &&
184 	    qos->phy != BT_AUDIO_CODEC_QOS_2M &&
185 	    qos->phy != BT_AUDIO_CODEC_QOS_CODED) {
186 		LOG_DBG("Invalid PHY 0x%02x", qos->phy);
187 		return BT_BAP_ASCS_REASON_PHY;
188 	}
189 
190 	if (qos->sdu > BT_ISO_MAX_SDU) {
191 		LOG_DBG("Invalid SDU %u", qos->sdu);
192 		return BT_BAP_ASCS_REASON_SDU;
193 	}
194 
195 #if defined(CONFIG_BT_BAP_BROADCAST_SOURCE) || defined(CONFIG_BT_BAP_UNICAST)
196 	if (qos->latency < BT_ISO_LATENCY_MIN ||
197 	    qos->latency > BT_ISO_LATENCY_MAX) {
198 		LOG_DBG("Invalid Latency %u", qos->latency);
199 		return BT_BAP_ASCS_REASON_LATENCY;
200 	}
201 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE || CONFIG_BT_BAP_UNICAST */
202 
203 	if (qos->pd > BT_AUDIO_PD_MAX) {
204 		LOG_DBG("Invalid presentation delay %u", qos->pd);
205 		return BT_BAP_ASCS_REASON_PD;
206 	}
207 
208 	return BT_BAP_ASCS_REASON_NONE;
209 }
210 
valid_ltv_cb(struct bt_data * data,void * user_data)211 static bool valid_ltv_cb(struct bt_data *data, void *user_data)
212 {
213 	/* just return true to continue parsing as bt_data_parse will validate for us */
214 	return true;
215 }
216 
bt_audio_valid_ltv(const uint8_t * data,uint8_t data_len)217 bool bt_audio_valid_ltv(const uint8_t *data, uint8_t data_len)
218 {
219 	return bt_audio_data_parse(data, data_len, valid_ltv_cb, NULL) == 0;
220 }
221 
bt_audio_valid_codec_cfg(const struct bt_audio_codec_cfg * codec_cfg)222 bool bt_audio_valid_codec_cfg(const struct bt_audio_codec_cfg *codec_cfg)
223 {
224 	if (codec_cfg == NULL) {
225 		LOG_DBG("codec is NULL");
226 		return false;
227 	}
228 
229 	if (codec_cfg->id == BT_HCI_CODING_FORMAT_LC3) {
230 		if (codec_cfg->cid != 0U) {
231 			LOG_DBG("codec_cfg->cid (%u) is invalid", codec_cfg->cid);
232 			return false;
233 		}
234 
235 		if (codec_cfg->vid != 0U) {
236 			LOG_DBG("codec_cfg->vid (%u) is invalid", codec_cfg->vid);
237 			return false;
238 		}
239 	}
240 
241 #if CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0
242 	/* Verify that codec configuration length is 0 when using
243 	 * BT_HCI_CODING_FORMAT_TRANSPARENT as per the core spec, 5.4, Vol 4, Part E, 7.8.109
244 	 */
245 	if (codec_cfg->id == BT_HCI_CODING_FORMAT_TRANSPARENT && codec_cfg->data_len != 0) {
246 		LOG_DBG("Invalid data_len %zu for codec_id %u", codec_cfg->data_len, codec_cfg->id);
247 		return false;
248 	}
249 
250 	if (codec_cfg->data_len > CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE) {
251 		LOG_DBG("codec_cfg->data_len (%zu) is invalid", codec_cfg->data_len);
252 		return false;
253 	}
254 
255 	if (codec_cfg->id == BT_HCI_CODING_FORMAT_LC3 &&
256 	    !bt_audio_valid_ltv(codec_cfg->data, codec_cfg->data_len)) {
257 		LOG_DBG("codec_cfg->data not valid LTV");
258 		return false;
259 	}
260 #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0 */
261 
262 #if CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE > 0
263 	if (codec_cfg->meta_len > CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE) {
264 		LOG_DBG("codec_cfg->meta_len (%zu) is invalid", codec_cfg->meta_len);
265 		return false;
266 	}
267 
268 	if (codec_cfg->id == BT_HCI_CODING_FORMAT_LC3 &&
269 	    !bt_audio_valid_ltv(codec_cfg->data, codec_cfg->data_len)) {
270 		LOG_DBG("codec_cfg->meta not valid LTV");
271 		return false;
272 	}
273 #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE > 0 */
274 
275 	return true;
276 }
277 
278 #if defined(CONFIG_BT_AUDIO_TX)
bt_bap_stream_can_send(const struct bt_bap_stream * stream)279 static bool bt_bap_stream_can_send(const struct bt_bap_stream *stream)
280 {
281 	struct bt_bap_ep_info info;
282 	int err;
283 
284 	if (stream == NULL || stream->ep == NULL) {
285 		return false;
286 	}
287 
288 	err = bt_bap_ep_get_info(stream->ep, &info);
289 	if (err != 0) {
290 		return false;
291 	}
292 
293 	return info.can_send;
294 }
295 
bap_stream_send(struct bt_bap_stream * stream,struct net_buf * buf,uint16_t seq_num,uint32_t ts,bool has_ts)296 static int bap_stream_send(struct bt_bap_stream *stream, struct net_buf *buf, uint16_t seq_num,
297 			   uint32_t ts, bool has_ts)
298 {
299 	struct bt_iso_chan *iso_chan;
300 	struct bt_bap_ep *ep;
301 	int ret;
302 
303 	if (stream == NULL || stream->ep == NULL) {
304 		return -EINVAL;
305 	}
306 
307 	if (!bt_bap_stream_can_send(stream)) {
308 		LOG_DBG("Stream is not configured for TX");
309 
310 		return -EINVAL;
311 	}
312 
313 	ep = stream->ep;
314 
315 	if (ep->status.state != BT_BAP_EP_STATE_STREAMING) {
316 		LOG_DBG("Channel %p not ready for streaming (state: %s)", stream,
317 			bt_bap_ep_state_str(ep->status.state));
318 		return -EBADMSG;
319 	}
320 
321 	iso_chan = bt_bap_stream_iso_chan_get(stream);
322 
323 	if (has_ts) {
324 		ret = bt_iso_chan_send_ts(iso_chan, buf, seq_num, ts);
325 	} else {
326 		ret = bt_iso_chan_send(iso_chan, buf, seq_num);
327 	}
328 
329 	if (ret < 0) {
330 		return ret;
331 	}
332 
333 #if defined(CONFIG_BT_BAP_DEBUG_STREAM_SEQ_NUM)
334 	if (stream->_prev_seq_num != 0U && seq_num != 0U &&
335 	    (stream->_prev_seq_num + 1U) != seq_num) {
336 		LOG_WRN("Unexpected seq_num diff between %u and %u for %p", stream->_prev_seq_num,
337 			seq_num, stream);
338 	}
339 
340 	stream->_prev_seq_num = seq_num;
341 #endif /* CONFIG_BT_BAP_DEBUG_STREAM_SEQ_NUM */
342 
343 	return ret;
344 }
345 
bt_bap_stream_send(struct bt_bap_stream * stream,struct net_buf * buf,uint16_t seq_num)346 int bt_bap_stream_send(struct bt_bap_stream *stream, struct net_buf *buf, uint16_t seq_num)
347 {
348 	return bap_stream_send(stream, buf, seq_num, 0, false);
349 }
350 
bt_bap_stream_send_ts(struct bt_bap_stream * stream,struct net_buf * buf,uint16_t seq_num,uint32_t ts)351 int bt_bap_stream_send_ts(struct bt_bap_stream *stream, struct net_buf *buf, uint16_t seq_num,
352 			  uint32_t ts)
353 {
354 	return bap_stream_send(stream, buf, seq_num, ts, true);
355 }
356 
bt_bap_stream_get_tx_sync(struct bt_bap_stream * stream,struct bt_iso_tx_info * info)357 int bt_bap_stream_get_tx_sync(struct bt_bap_stream *stream, struct bt_iso_tx_info *info)
358 {
359 	struct bt_iso_chan *iso_chan;
360 
361 	CHECKIF(stream == NULL) {
362 		LOG_DBG("stream is null");
363 
364 		return -EINVAL;
365 	}
366 
367 	CHECKIF(info == NULL) {
368 		LOG_DBG("info is null");
369 
370 		return -EINVAL;
371 	}
372 
373 	if (!bt_bap_stream_can_send(stream)) {
374 		LOG_DBG("Stream is not configured for TX");
375 
376 		return -EINVAL;
377 	}
378 
379 	iso_chan = bt_bap_stream_iso_chan_get(stream);
380 	if (iso_chan == NULL) {
381 		LOG_DBG("Could not get iso channel from stream %p", stream);
382 		return -EINVAL;
383 	}
384 
385 	return bt_iso_chan_get_tx_sync(iso_chan, info);
386 }
387 #endif /* CONFIG_BT_AUDIO_TX */
388 
389 #if defined(CONFIG_BT_BAP_UNICAST)
390 
391 /** Checks if the stream can terminate the CIS
392  *
393  * If the CIS is used for another stream, or if the CIS is not in the connected
394  * state it will return false.
395  */
bt_bap_stream_can_disconnect(const struct bt_bap_stream * stream)396 bool bt_bap_stream_can_disconnect(const struct bt_bap_stream *stream)
397 {
398 	const struct bt_bap_ep *stream_ep;
399 	enum bt_iso_state iso_state;
400 
401 	if (stream == NULL) {
402 		return false;
403 	}
404 
405 	stream_ep = stream->ep;
406 
407 	if (stream_ep == NULL || stream_ep->iso == NULL) {
408 		return false;
409 	}
410 
411 	iso_state = stream_ep->iso->chan.state;
412 
413 	if (iso_state == BT_ISO_STATE_CONNECTED || iso_state == BT_ISO_STATE_CONNECTING) {
414 		const struct bt_bap_ep *pair_ep;
415 
416 		pair_ep = bt_bap_iso_get_paired_ep(stream_ep);
417 
418 		/* If there are no paired endpoint, or the paired endpoint is
419 		 * not in the streaming state, we can disconnect the CIS
420 		 */
421 		if (pair_ep == NULL || pair_ep->status.state != BT_BAP_EP_STATE_STREAMING) {
422 			return true;
423 		}
424 	}
425 
426 	return false;
427 }
428 
bt_bap_stream_is_broadcast(const struct bt_bap_stream * stream)429 static bool bt_bap_stream_is_broadcast(const struct bt_bap_stream *stream)
430 {
431 	return (IS_ENABLED(CONFIG_BT_BAP_BROADCAST_SOURCE) &&
432 		bt_bap_ep_is_broadcast_src(stream->ep)) ||
433 	       (IS_ENABLED(CONFIG_BT_BAP_BROADCAST_SINK) && bt_bap_ep_is_broadcast_snk(stream->ep));
434 }
435 
bt_bap_stream_verify_qos(const struct bt_bap_stream * stream,const struct bt_audio_codec_qos * qos)436 enum bt_bap_ascs_reason bt_bap_stream_verify_qos(const struct bt_bap_stream *stream,
437 						 const struct bt_audio_codec_qos *qos)
438 {
439 	const struct bt_audio_codec_qos_pref *qos_pref = &stream->ep->qos_pref;
440 
441 	if (qos_pref->latency < qos->latency) {
442 		/* Latency is a preferred value. Print debug info but do not fail. */
443 		LOG_DBG("Latency %u higher than preferred max %u", qos->latency, qos_pref->latency);
444 	}
445 
446 	if (!IN_RANGE(qos->pd, qos_pref->pd_min, qos_pref->pd_max)) {
447 		LOG_DBG("Presentation Delay not within range: min %u max %u pd %u",
448 			qos_pref->pd_min, qos_pref->pd_max, qos->pd);
449 		return BT_BAP_ASCS_REASON_PD;
450 	}
451 
452 	return BT_BAP_ASCS_REASON_NONE;
453 }
454 
bt_bap_stream_detach(struct bt_bap_stream * stream)455 void bt_bap_stream_detach(struct bt_bap_stream *stream)
456 {
457 	const bool is_broadcast = bt_bap_stream_is_broadcast(stream);
458 
459 	LOG_DBG("stream %p", stream);
460 
461 	if (stream->conn != NULL) {
462 		bt_conn_unref(stream->conn);
463 		stream->conn = NULL;
464 	}
465 	stream->codec_cfg = NULL;
466 	stream->ep->stream = NULL;
467 	stream->ep = NULL;
468 
469 	if (!is_broadcast) {
470 		const int err = bt_bap_stream_disconnect(stream);
471 
472 		if (err != 0) {
473 			LOG_DBG("Failed to disconnect stream %p: %d", stream, err);
474 		}
475 	}
476 }
477 
bt_bap_stream_disconnect(struct bt_bap_stream * stream)478 int bt_bap_stream_disconnect(struct bt_bap_stream *stream)
479 {
480 	struct bt_iso_chan *iso_chan;
481 
482 	LOG_DBG("stream %p", stream);
483 
484 	if (stream == NULL) {
485 		return -EINVAL;
486 	}
487 
488 	iso_chan = bt_bap_stream_iso_chan_get(stream);
489 	if (iso_chan == NULL || iso_chan->iso == NULL) {
490 		LOG_DBG("Not connected");
491 
492 		return -ENOTCONN;
493 	}
494 
495 	return bt_iso_chan_disconnect(iso_chan);
496 }
497 
bt_bap_stream_reset(struct bt_bap_stream * stream)498 void bt_bap_stream_reset(struct bt_bap_stream *stream)
499 {
500 	LOG_DBG("stream %p", stream);
501 
502 	if (stream == NULL) {
503 		return;
504 	}
505 
506 	if (stream->ep != NULL && stream->ep->iso != NULL) {
507 		bt_bap_iso_unbind_ep(stream->ep->iso, stream->ep);
508 	}
509 
510 	bt_bap_stream_detach(stream);
511 }
512 
conn_get_role(const struct bt_conn * conn)513 static uint8_t conn_get_role(const struct bt_conn *conn)
514 {
515 	struct bt_conn_info info;
516 	int err;
517 
518 	err = bt_conn_get_info(conn, &info);
519 	__ASSERT(err == 0, "Failed to get conn info");
520 
521 	return info.role;
522 }
523 
524 #if defined(CONFIG_BT_BAP_UNICAST_CLIENT)
525 
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)526 int bt_bap_stream_config(struct bt_conn *conn, struct bt_bap_stream *stream, struct bt_bap_ep *ep,
527 			 struct bt_audio_codec_cfg *codec_cfg)
528 {
529 	uint8_t role;
530 	int err;
531 
532 	LOG_DBG("conn %p stream %p, ep %p codec_cfg %p codec id 0x%02x "
533 	       "codec cid 0x%04x codec vid 0x%04x", (void *)conn, stream, ep,
534 	       codec_cfg, codec_cfg ? codec_cfg->id : 0, codec_cfg ? codec_cfg->cid : 0,
535 	       codec_cfg ? codec_cfg->vid : 0);
536 
537 	CHECKIF(conn == NULL || stream == NULL || codec_cfg == NULL) {
538 		LOG_DBG("NULL value(s) supplied)");
539 		return -EINVAL;
540 	}
541 
542 	if (stream->conn != NULL) {
543 		LOG_DBG("Stream already configured for conn %p", (void *)stream->conn);
544 		return -EALREADY;
545 	}
546 
547 	role = conn_get_role(conn);
548 	if (role != BT_HCI_ROLE_CENTRAL) {
549 		LOG_DBG("Invalid conn role: %u, shall be central", role);
550 		return -EINVAL;
551 	}
552 
553 	switch (ep->status.state) {
554 	/* Valid only if ASE_State field = 0x00 (Idle) */
555 	case BT_BAP_EP_STATE_IDLE:
556 		/* or 0x01 (Codec Configured) */
557 	case BT_BAP_EP_STATE_CODEC_CONFIGURED:
558 		/* or 0x02 (QoS Configured) */
559 	case BT_BAP_EP_STATE_QOS_CONFIGURED:
560 		break;
561 	default:
562 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
563 		return -EBADMSG;
564 	}
565 
566 	bt_bap_stream_attach(conn, stream, ep, codec_cfg);
567 
568 	err = bt_bap_unicast_client_config(stream, codec_cfg);
569 	if (err != 0) {
570 		LOG_DBG("Failed to configure stream: %d", err);
571 		return err;
572 	}
573 
574 	return 0;
575 }
576 
bt_bap_stream_qos(struct bt_conn * conn,struct bt_bap_unicast_group * group)577 int bt_bap_stream_qos(struct bt_conn *conn, struct bt_bap_unicast_group *group)
578 {
579 	uint8_t role;
580 	int err;
581 
582 	LOG_DBG("conn %p group %p", (void *)conn, group);
583 
584 	CHECKIF(conn == NULL) {
585 		LOG_DBG("conn is NULL");
586 		return -EINVAL;
587 	}
588 
589 	CHECKIF(group == NULL) {
590 		LOG_DBG("group is NULL");
591 		return -EINVAL;
592 	}
593 
594 	if (sys_slist_is_empty(&group->streams)) {
595 		LOG_DBG("group stream list is empty");
596 		return -ENOEXEC;
597 	}
598 
599 	role = conn_get_role(conn);
600 	if (role != BT_HCI_ROLE_CENTRAL) {
601 		LOG_DBG("Invalid conn role: %u, shall be central", role);
602 		return -EINVAL;
603 	}
604 
605 	err = bt_bap_unicast_client_qos(conn, group);
606 	if (err != 0) {
607 		LOG_DBG("Failed to configure stream: %d", err);
608 		return err;
609 	}
610 
611 	return 0;
612 }
613 
bt_bap_stream_enable(struct bt_bap_stream * stream,const uint8_t meta[],size_t meta_len)614 int bt_bap_stream_enable(struct bt_bap_stream *stream, const uint8_t meta[], size_t meta_len)
615 {
616 	uint8_t role;
617 	int err;
618 
619 	LOG_DBG("stream %p", stream);
620 
621 	if (stream == NULL || stream->ep == NULL || stream->conn == NULL) {
622 		LOG_DBG("Invalid stream");
623 		return -EINVAL;
624 	}
625 
626 	role = conn_get_role(stream->conn);
627 	if (role != BT_HCI_ROLE_CENTRAL) {
628 		LOG_DBG("Invalid conn role: %u, shall be central", role);
629 		return -EINVAL;
630 	}
631 
632 	/* Valid for an ASE only if ASE_State field = 0x02 (QoS Configured) */
633 	if (stream->ep->status.state != BT_BAP_EP_STATE_QOS_CONFIGURED) {
634 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(stream->ep->status.state));
635 		return -EBADMSG;
636 	}
637 
638 	err = bt_bap_unicast_client_enable(stream, meta, meta_len);
639 	if (err != 0) {
640 		LOG_DBG("Failed to enable stream: %d", err);
641 		return err;
642 	}
643 
644 	return 0;
645 }
646 
bt_bap_stream_stop(struct bt_bap_stream * stream)647 int bt_bap_stream_stop(struct bt_bap_stream *stream)
648 {
649 	struct bt_bap_ep *ep;
650 	uint8_t role;
651 	int err;
652 
653 	if (stream == NULL || stream->ep == NULL || stream->conn == NULL) {
654 		LOG_DBG("Invalid stream");
655 		return -EINVAL;
656 	}
657 
658 	role = conn_get_role(stream->conn);
659 	if (role != BT_HCI_ROLE_CENTRAL) {
660 		LOG_DBG("Invalid conn role: %u, shall be central", role);
661 		return -EINVAL;
662 	}
663 
664 	ep = stream->ep;
665 
666 	switch (ep->status.state) {
667 	/* Valid only if ASE_State field = 0x03 (Disabling) */
668 	case BT_BAP_EP_STATE_DISABLING:
669 		break;
670 	default:
671 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
672 		return -EBADMSG;
673 	}
674 
675 	err = bt_bap_unicast_client_stop(stream);
676 	if (err != 0) {
677 		LOG_DBG("Stopping stream failed: %d", err);
678 		return err;
679 	}
680 
681 	return 0;
682 }
683 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
684 
bt_bap_stream_reconfig(struct bt_bap_stream * stream,struct bt_audio_codec_cfg * codec_cfg)685 int bt_bap_stream_reconfig(struct bt_bap_stream *stream,
686 			     struct bt_audio_codec_cfg *codec_cfg)
687 {
688 	uint8_t state;
689 	uint8_t role;
690 	int err;
691 
692 	LOG_DBG("stream %p codec_cfg %p", stream, codec_cfg);
693 
694 	CHECKIF(stream == NULL || stream->ep == NULL || stream->conn == NULL) {
695 		LOG_DBG("Invalid stream");
696 		return -EINVAL;
697 	}
698 
699 	CHECKIF(codec_cfg == NULL) {
700 		LOG_DBG("codec_cfg is NULL");
701 		return -EINVAL;
702 	}
703 
704 	state = stream->ep->status.state;
705 	switch (state) {
706 	/* Valid only if ASE_State field = 0x00 (Idle) */
707 	case BT_BAP_EP_STATE_IDLE:
708 		/* or 0x01 (Codec Configured) */
709 	case BT_BAP_EP_STATE_CODEC_CONFIGURED:
710 		/* or 0x02 (QoS Configured) */
711 	case BT_BAP_EP_STATE_QOS_CONFIGURED:
712 		break;
713 	default:
714 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(state));
715 		return -EBADMSG;
716 	}
717 
718 	role = conn_get_role(stream->conn);
719 	if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) && role == BT_HCI_ROLE_CENTRAL) {
720 		err = bt_bap_unicast_client_config(stream, codec_cfg);
721 	} else if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER) && role == BT_HCI_ROLE_PERIPHERAL) {
722 		err = bt_bap_unicast_server_reconfig(stream, codec_cfg);
723 	} else {
724 		err = -EOPNOTSUPP;
725 	}
726 
727 	if (err != 0) {
728 		LOG_DBG("reconfiguring stream failed: %d", err);
729 	} else {
730 		stream->codec_cfg = codec_cfg;
731 	}
732 
733 	return 0;
734 }
735 
736 #if defined(CONFIG_BT_BAP_UNICAST_CLIENT)
bt_bap_stream_connect(struct bt_bap_stream * stream)737 int bt_bap_stream_connect(struct bt_bap_stream *stream)
738 {
739 	uint8_t state;
740 
741 	LOG_DBG("stream %p ep %p", stream, stream == NULL ? NULL : stream->ep);
742 
743 	CHECKIF(stream == NULL || stream->ep == NULL || stream->conn == NULL) {
744 		LOG_DBG("Invalid stream");
745 		return -EINVAL;
746 	}
747 
748 	/* Valid only after the CIS ID has been assigned in QoS configured state and while we are
749 	 * not streaming
750 	 */
751 	state = stream->ep->status.state;
752 	switch (state) {
753 	case BT_BAP_EP_STATE_QOS_CONFIGURED:
754 	case BT_BAP_EP_STATE_ENABLING:
755 		break;
756 	default:
757 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(state));
758 		return -EBADMSG;
759 	}
760 
761 	/* Only a unicast client can connect a stream */
762 	if (conn_get_role(stream->conn) == BT_HCI_ROLE_CENTRAL) {
763 		return bt_bap_unicast_client_connect(stream);
764 	} else {
765 		return -EOPNOTSUPP;
766 	}
767 }
768 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
769 
bt_bap_stream_start(struct bt_bap_stream * stream)770 int bt_bap_stream_start(struct bt_bap_stream *stream)
771 {
772 	uint8_t state;
773 	uint8_t role;
774 	int err;
775 
776 	LOG_DBG("stream %p ep %p", stream, stream == NULL ? NULL : stream->ep);
777 
778 	CHECKIF(stream == NULL || stream->ep == NULL || stream->conn == NULL) {
779 		LOG_DBG("Invalid stream");
780 		return -EINVAL;
781 	}
782 
783 	state = stream->ep->status.state;
784 	switch (state) {
785 	/* Valid only if ASE_State field = 0x03 (Enabling) */
786 	case BT_BAP_EP_STATE_ENABLING:
787 		break;
788 	default:
789 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(state));
790 		return -EBADMSG;
791 	}
792 
793 	role = conn_get_role(stream->conn);
794 	if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) && role == BT_HCI_ROLE_CENTRAL) {
795 		err = bt_bap_unicast_client_start(stream);
796 	} else if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER) && role == BT_HCI_ROLE_PERIPHERAL) {
797 		err = bt_bap_unicast_server_start(stream);
798 	} else {
799 		err = -EOPNOTSUPP;
800 	}
801 
802 	if (err != 0) {
803 		LOG_DBG("Starting stream failed: %d", err);
804 		return err;
805 	}
806 
807 	return 0;
808 }
809 
bt_bap_stream_metadata(struct bt_bap_stream * stream,const uint8_t meta[],size_t meta_len)810 int bt_bap_stream_metadata(struct bt_bap_stream *stream, const uint8_t meta[], size_t meta_len)
811 {
812 	uint8_t state;
813 	uint8_t role;
814 	int err;
815 
816 	LOG_DBG("stream %p meta_len %zu", stream, meta_len);
817 
818 	CHECKIF(stream == NULL || stream->ep == NULL || stream->conn == NULL) {
819 		LOG_DBG("Invalid stream");
820 		return -EINVAL;
821 	}
822 
823 	CHECKIF((meta == NULL && meta_len != 0U) || (meta != NULL && meta_len == 0U)) {
824 		LOG_DBG("Invalid meta (%p) or len (%zu)", meta, meta_len);
825 		return -EINVAL;
826 	}
827 
828 	state = stream->ep->status.state;
829 	switch (state) {
830 	/* Valid for an ASE only if ASE_State field = 0x03 (Enabling) */
831 	case BT_BAP_EP_STATE_ENABLING:
832 	/* or 0x04 (Streaming) */
833 	case BT_BAP_EP_STATE_STREAMING:
834 		break;
835 	default:
836 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(state));
837 		return -EBADMSG;
838 	}
839 
840 	role = conn_get_role(stream->conn);
841 	if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) && role == BT_HCI_ROLE_CENTRAL) {
842 		err = bt_bap_unicast_client_metadata(stream, meta, meta_len);
843 	} else if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER) && role == BT_HCI_ROLE_PERIPHERAL) {
844 		err = bt_bap_unicast_server_metadata(stream, meta, meta_len);
845 	} else {
846 		err = -EOPNOTSUPP;
847 	}
848 
849 	if (err != 0) {
850 		LOG_DBG("Updating metadata failed: %d", err);
851 		return err;
852 	}
853 
854 	return 0;
855 }
856 
bt_bap_stream_disable(struct bt_bap_stream * stream)857 int bt_bap_stream_disable(struct bt_bap_stream *stream)
858 {
859 	uint8_t state;
860 	uint8_t role;
861 	int err;
862 
863 	LOG_DBG("stream %p", stream);
864 
865 	CHECKIF(stream == NULL || stream->ep == NULL || stream->conn == NULL) {
866 		LOG_DBG("Invalid stream");
867 		return -EINVAL;
868 	}
869 
870 	state = stream->ep->status.state;
871 	switch (state) {
872 	/* Valid only if ASE_State field = 0x03 (Enabling) */
873 	case BT_BAP_EP_STATE_ENABLING:
874 		/* or 0x04 (Streaming) */
875 	case BT_BAP_EP_STATE_STREAMING:
876 		break;
877 	default:
878 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(state));
879 		return -EBADMSG;
880 	}
881 
882 	role = conn_get_role(stream->conn);
883 	if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) && role == BT_HCI_ROLE_CENTRAL) {
884 		err = bt_bap_unicast_client_disable(stream);
885 	} else if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER) && role == BT_HCI_ROLE_PERIPHERAL) {
886 		err = bt_bap_unicast_server_disable(stream);
887 	} else {
888 		err = -EOPNOTSUPP;
889 	}
890 
891 	if (err != 0) {
892 		LOG_DBG("Disabling stream failed: %d", err);
893 		return err;
894 	}
895 
896 	return 0;
897 }
898 
bt_bap_stream_release(struct bt_bap_stream * stream)899 int bt_bap_stream_release(struct bt_bap_stream *stream)
900 {
901 	uint8_t state;
902 	uint8_t role;
903 	int err;
904 
905 	LOG_DBG("stream %p", stream);
906 
907 	CHECKIF(stream == NULL || stream->ep == NULL || stream->conn == NULL) {
908 		LOG_DBG("Invalid stream (ep %p, conn %p)", stream->ep, (void *)stream->conn);
909 		return -EINVAL;
910 	}
911 
912 	state = stream->ep->status.state;
913 	switch (state) {
914 	/* Valid only if ASE_State field = 0x01 (Codec Configured) */
915 	case BT_BAP_EP_STATE_CODEC_CONFIGURED:
916 		/* or 0x02 (QoS Configured) */
917 	case BT_BAP_EP_STATE_QOS_CONFIGURED:
918 		/* or 0x03 (Enabling) */
919 	case BT_BAP_EP_STATE_ENABLING:
920 		/* or 0x04 (Streaming) */
921 	case BT_BAP_EP_STATE_STREAMING:
922 		/* or 0x04 (Disabling) */
923 	case BT_BAP_EP_STATE_DISABLING:
924 		break;
925 	default:
926 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(state));
927 		return -EBADMSG;
928 	}
929 
930 	role = conn_get_role(stream->conn);
931 	if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT) && role == BT_HCI_ROLE_CENTRAL) {
932 		err = bt_bap_unicast_client_release(stream);
933 	} else if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER) && role == BT_HCI_ROLE_PERIPHERAL) {
934 		err = bt_bap_unicast_server_release(stream);
935 	} else {
936 		err = -EOPNOTSUPP;
937 	}
938 
939 	if (err != 0) {
940 		LOG_DBG("Releasing stream failed: %d", err);
941 		return err;
942 	}
943 
944 	return 0;
945 }
946 #endif /* CONFIG_BT_BAP_UNICAST */
947