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