1 /* @file
2  * @brief Bluetooth Unicast Client
3  */
4 
5 /*
6  * Copyright (c) 2020 Intel Corporation
7  * Copyright (c) 2022-2023 Nordic Semiconductor ASA
8  *
9  * SPDX-License-Identifier: Apache-2.0
10  */
11 
12 #include <errno.h>
13 #include <stdbool.h>
14 #include <stddef.h>
15 #include <stdint.h>
16 #include <string.h>
17 
18 #include <zephyr/autoconf.h>
19 #include <zephyr/bluetooth/att.h>
20 #include <zephyr/bluetooth/bluetooth.h>
21 #include <zephyr/bluetooth/conn.h>
22 #include <zephyr/bluetooth/gap.h>
23 #include <zephyr/bluetooth/gatt.h>
24 #include <zephyr/bluetooth/hci.h>
25 #include <zephyr/bluetooth/audio/audio.h>
26 #include <zephyr/bluetooth/audio/bap.h>
27 #include <zephyr/bluetooth/hci_types.h>
28 #include <zephyr/bluetooth/iso.h>
29 #include <zephyr/bluetooth/uuid.h>
30 #include <zephyr/kernel.h>
31 #include <zephyr/logging/log.h>
32 #include <zephyr/net_buf.h>
33 #include <zephyr/sys/__assert.h>
34 #include <zephyr/sys/atomic.h>
35 #include <zephyr/sys/byteorder.h>
36 #include <zephyr/sys/check.h>
37 #include <zephyr/sys/slist.h>
38 #include <zephyr/sys/util.h>
39 #include <zephyr/sys/util_macro.h>
40 #include <zephyr/toolchain.h>
41 
42 #include "../host/hci_core.h"
43 #include "../host/conn_internal.h"
44 #include "../host/iso_internal.h"
45 
46 #include "ascs_internal.h"
47 #include "audio_internal.h"
48 #include "bap_iso.h"
49 #include "bap_endpoint.h"
50 #include "bap_unicast_client_internal.h"
51 #include "pacs_internal.h"
52 
53 BUILD_ASSERT(CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 ||
54 		     CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0,
55 	     "CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT or "
56 	     "CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT shall be non-zero");
57 
58 BUILD_ASSERT(CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT == 0 ||
59 		     CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 1,
60 	     "CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT shall be either 0 or > 1");
61 
62 BUILD_ASSERT(CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT == 0 ||
63 		     CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 1,
64 	     "CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT shall be either 0 or > 1");
65 
66 LOG_MODULE_REGISTER(bt_bap_unicast_client, CONFIG_BT_BAP_UNICAST_CLIENT_LOG_LEVEL);
67 
68 #define PAC_DIR_UNUSED(dir) ((dir) != BT_AUDIO_DIR_SINK && (dir) != BT_AUDIO_DIR_SOURCE)
69 #define BAP_HANDLE_UNUSED   0x0000U
70 struct bt_bap_unicast_client_ep {
71 	uint16_t handle;
72 	uint16_t cp_handle;
73 	struct bt_gatt_subscribe_params subscribe;
74 	struct bt_gatt_discover_params discover;
75 	struct bt_bap_ep ep;
76 	struct k_work_delayable ase_read_work;
77 
78 	/* Bool to help handle different order of CP and ASE notification when releasing */
79 	bool release_requested;
80 	bool cp_ntf_pending;
81 };
82 
83 static const struct bt_uuid *snk_uuid = BT_UUID_PACS_SNK;
84 static const struct bt_uuid *src_uuid = BT_UUID_PACS_SRC;
85 static const struct bt_uuid *pacs_context_uuid = BT_UUID_PACS_SUPPORTED_CONTEXT;
86 static const struct bt_uuid *pacs_snk_loc_uuid = BT_UUID_PACS_SNK_LOC;
87 static const struct bt_uuid *pacs_src_loc_uuid = BT_UUID_PACS_SRC_LOC;
88 static const struct bt_uuid *pacs_avail_ctx_uuid = BT_UUID_PACS_AVAILABLE_CONTEXT;
89 static const struct bt_uuid *ase_snk_uuid = BT_UUID_ASCS_ASE_SNK;
90 static const struct bt_uuid *ase_src_uuid = BT_UUID_ASCS_ASE_SRC;
91 static const struct bt_uuid *cp_uuid = BT_UUID_ASCS_ASE_CP;
92 
93 static struct bt_bap_unicast_group unicast_groups[UNICAST_GROUP_CNT];
94 
95 enum unicast_client_flag {
96 	UNICAST_CLIENT_FLAG_BUSY,
97 
98 	UNICAST_CLIENT_FLAG_NUM_FLAGS, /* keep as last */
99 };
100 
101 static struct unicast_client {
102 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
103 	struct bt_bap_unicast_client_ep snks[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT];
104 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
105 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
106 	struct bt_bap_unicast_client_ep srcs[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT];
107 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
108 
109 	struct bt_gatt_subscribe_params cp_subscribe;
110 	struct bt_gatt_subscribe_params snk_loc_subscribe;
111 	struct bt_gatt_subscribe_params src_loc_subscribe;
112 	struct bt_gatt_subscribe_params avail_ctx_subscribe;
113 
114 	/* TODO: We should be able to reduce the number of discover params for
115 	 * CCCD discovery, but requires additional work if it is to support an
116 	 * arbitrary number of EATT bearers, as control point and location CCCD
117 	 * discovery needs to be done in serial to avoid using the same discover
118 	 * parameters twice
119 	 */
120 	struct bt_gatt_discover_params loc_cc_disc;
121 	struct bt_gatt_discover_params avail_ctx_cc_disc;
122 
123 	/* Discovery parameters */
124 	enum bt_audio_dir dir;
125 	union {
126 		struct bt_gatt_read_params read_params;
127 		struct bt_gatt_discover_params disc_params;
128 		struct bt_gatt_write_params write_params;
129 	};
130 
131 	/* The att_buf needs to use the maximum ATT attribute size as a single
132 	 * PAC record may use the full size
133 	 */
134 	uint8_t att_buf[BT_ATT_MAX_ATTRIBUTE_LEN];
135 	struct net_buf_simple net_buf;
136 
137 	ATOMIC_DEFINE(flags, UNICAST_CLIENT_FLAG_NUM_FLAGS);
138 } uni_cli_insts[CONFIG_BT_MAX_CONN];
139 
140 static sys_slist_t unicast_client_cbs = SYS_SLIST_STATIC_INIT(&unicast_client_cbs);
141 
142 /* TODO: Move the functions to avoid these prototypes */
143 static int unicast_client_ep_set_metadata(struct bt_bap_ep *ep, void *data, uint8_t len,
144 					  struct bt_audio_codec_cfg *codec_cfg);
145 
146 static int unicast_client_ep_set_codec_cfg(struct bt_bap_ep *ep, uint8_t id, uint16_t cid,
147 					   uint16_t vid, void *data, uint8_t len,
148 					   struct bt_audio_codec_cfg *codec_cfg);
149 static int unicast_client_ep_start(struct bt_bap_ep *ep,
150 				   struct net_buf_simple *buf);
151 
152 static int unicast_client_ase_discover(struct bt_conn *conn, uint16_t start_handle);
153 
154 static void unicast_client_reset(struct bt_bap_ep *ep, uint8_t reason);
155 
156 static void delayed_ase_read_handler(struct k_work *work);
157 static void unicast_client_ep_set_status(struct bt_bap_ep *ep, struct net_buf_simple *buf);
158 
unicast_client_send_start(struct bt_bap_ep * ep)159 static int unicast_client_send_start(struct bt_bap_ep *ep)
160 {
161 	if (ep->receiver_ready != true || ep->dir != BT_AUDIO_DIR_SOURCE) {
162 		LOG_DBG("Invalid ep %p %u %s",
163 			ep, ep->receiver_ready, bt_audio_dir_str(ep->dir));
164 
165 		return -EINVAL;
166 	}
167 
168 	struct bt_ascs_start_op *req;
169 	struct net_buf_simple *buf;
170 	int err;
171 
172 	buf = bt_bap_unicast_client_ep_create_pdu(ep->stream->conn, BT_ASCS_START_OP);
173 	if (buf == NULL) {
174 		LOG_DBG("Could not create PDU");
175 		return -EBUSY;
176 	}
177 
178 	req = net_buf_simple_add(buf, sizeof(*req));
179 	req->num_ases = 1U;
180 
181 	err = unicast_client_ep_start(ep, buf);
182 	if (err != 0) {
183 		LOG_DBG("unicast_client_ep_start failed: %d",
184 			err);
185 
186 		return err;
187 	}
188 
189 	err = bt_bap_unicast_client_ep_send(ep->stream->conn, ep, buf);
190 	if (err != 0) {
191 		LOG_DBG("bt_bap_unicast_client_ep_send failed: %d", err);
192 
193 		return err;
194 	}
195 
196 	return 0;
197 }
198 
199 static void unicast_client_ep_idle_state(struct bt_bap_ep *ep);
200 
audio_stream_by_ep_id(const struct bt_conn * conn,uint8_t id)201 static struct bt_bap_stream *audio_stream_by_ep_id(const struct bt_conn *conn,
202 						     uint8_t id)
203 {
204 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 || CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
205 	const uint8_t conn_index = bt_conn_index(conn);
206 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 ||                                        \
207 	* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0                                           \
208 	*/
209 
210 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
211 	for (size_t i = 0U; i < ARRAY_SIZE(uni_cli_insts[conn_index].snks); i++) {
212 		const struct bt_bap_unicast_client_ep *client_ep =
213 			&uni_cli_insts[conn_index].snks[i];
214 
215 		if (client_ep->ep.status.id == id) {
216 			return client_ep->ep.stream;
217 		}
218 	}
219 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
220 
221 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
222 	for (size_t i = 0U; i < ARRAY_SIZE(uni_cli_insts[conn_index].srcs); i++) {
223 		const struct bt_bap_unicast_client_ep *client_ep =
224 			&uni_cli_insts[conn_index].srcs[i];
225 
226 		if (client_ep->ep.status.id == id) {
227 			return client_ep->ep.stream;
228 		}
229 	}
230 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
231 
232 	return NULL;
233 }
234 
reset_att_buf(struct unicast_client * client)235 static void reset_att_buf(struct unicast_client *client)
236 {
237 	net_buf_simple_init_with_data(&client->net_buf, &client->att_buf, sizeof(client->att_buf));
238 	net_buf_simple_reset(&client->net_buf);
239 }
240 
241 #if defined(CONFIG_BT_AUDIO_RX)
unicast_client_ep_iso_recv(struct bt_iso_chan * chan,const struct bt_iso_recv_info * info,struct net_buf * buf)242 static void unicast_client_ep_iso_recv(struct bt_iso_chan *chan,
243 				       const struct bt_iso_recv_info *info, struct net_buf *buf)
244 {
245 	struct bt_bap_iso *iso = CONTAINER_OF(chan, struct bt_bap_iso, chan);
246 	const struct bt_bap_stream_ops *ops;
247 	struct bt_bap_stream *stream;
248 	struct bt_bap_ep *ep = iso->rx.ep;
249 
250 	if (ep == NULL) {
251 		/* In the case that the CIS has been setup as bidirectional, and
252 		 * only one of the directions have an ASE configured yet,
253 		 * we should only care about valid ISO packets when doing this
254 		 * check. The reason is that some controllers send HCI ISO data
255 		 * packets to the host, even if no SDU was sent on the remote
256 		 * side. This basically means that empty PDUs are sent to the
257 		 * host as HCI ISO data packets, which we should just ignore
258 		 */
259 		if ((info->flags & BT_ISO_FLAGS_VALID) != 0) {
260 			LOG_DBG("Valid ISO packet of len %zu received for iso %p not bound with ep",
261 				net_buf_frags_len(buf), chan);
262 		}
263 
264 		return;
265 	}
266 
267 	if (ep->status.state != BT_BAP_EP_STATE_STREAMING) {
268 		if (IS_ENABLED(CONFIG_BT_BAP_DEBUG_STREAM_DATA)) {
269 			LOG_DBG("ep %p is not in the streaming state: %s", ep,
270 				bt_bap_ep_state_str(ep->status.state));
271 		}
272 
273 		return;
274 	}
275 
276 	stream = ep->stream;
277 	if (stream == NULL) {
278 		LOG_ERR("No stream for ep %p", ep);
279 		return;
280 	}
281 
282 	ops = stream->ops;
283 
284 	if (IS_ENABLED(CONFIG_BT_BAP_DEBUG_STREAM_DATA)) {
285 		LOG_DBG("stream %p ep %p len %zu", stream, ep, net_buf_frags_len(buf));
286 	}
287 
288 	if (ops != NULL && ops->recv != NULL) {
289 		ops->recv(stream, info, buf);
290 	} else {
291 		LOG_WRN("No callback for recv set");
292 	}
293 }
294 #endif /* CONFIG_BT_AUDIO_RX */
295 
296 #if defined(CONFIG_BT_AUDIO_TX)
unicast_client_ep_iso_sent(struct bt_iso_chan * chan)297 static void unicast_client_ep_iso_sent(struct bt_iso_chan *chan)
298 {
299 	struct bt_bap_iso *iso = CONTAINER_OF(chan, struct bt_bap_iso, chan);
300 	struct bt_bap_stream *stream;
301 	struct bt_bap_ep *ep = iso->tx.ep;
302 
303 	if (ep == NULL) {
304 		LOG_ERR("iso %p not bound with ep", chan);
305 		return;
306 	}
307 
308 	stream = ep->stream;
309 	if (stream == NULL) {
310 		LOG_ERR("No stream for ep %p", ep);
311 		return;
312 	}
313 
314 	if (IS_ENABLED(CONFIG_BT_BAP_DEBUG_STREAM_DATA)) {
315 		LOG_DBG("stream %p ep %p", stream, ep);
316 	}
317 
318 	if (stream->ops != NULL && stream->ops->sent != NULL) {
319 		stream->ops->sent(stream);
320 	}
321 }
322 #endif /* CONFIG_BT_AUDIO_TX */
323 
unicast_client_ep_iso_connected(struct bt_bap_ep * ep)324 static void unicast_client_ep_iso_connected(struct bt_bap_ep *ep)
325 {
326 	const struct bt_bap_stream_ops *stream_ops;
327 	struct bt_bap_stream *stream;
328 
329 	if (ep->unicast_group != NULL) {
330 		ep->unicast_group->has_been_connected = true;
331 	}
332 
333 	if (ep->status.state != BT_BAP_EP_STATE_ENABLING) {
334 		LOG_DBG("endpoint not in enabling state: %s",
335 			bt_bap_ep_state_str(ep->status.state));
336 		return;
337 	}
338 
339 	stream = ep->stream;
340 	if (stream == NULL) {
341 		LOG_ERR("No stream for ep %p", ep);
342 		return;
343 	}
344 
345 	LOG_DBG("stream %p ep %p dir %s receiver_ready %u",
346 		stream, ep, bt_audio_dir_str(ep->dir), ep->receiver_ready);
347 
348 #if defined(CONFIG_BT_BAP_DEBUG_STREAM_SEQ_NUM)
349 	/* reset sequence number */
350 	stream->_prev_seq_num = 0U;
351 #endif /* CONFIG_BT_BAP_DEBUG_STREAM_SEQ_NUM */
352 
353 	stream_ops = stream->ops;
354 	if (stream_ops != NULL && stream_ops->connected != NULL) {
355 		stream_ops->connected(stream);
356 	}
357 }
358 
unicast_client_iso_connected(struct bt_iso_chan * chan)359 static void unicast_client_iso_connected(struct bt_iso_chan *chan)
360 {
361 	struct bt_bap_iso *iso = CONTAINER_OF(chan, struct bt_bap_iso, chan);
362 
363 	if (iso->rx.ep == NULL && iso->tx.ep == NULL) {
364 		LOG_ERR("iso %p not bound with ep", chan);
365 		return;
366 	}
367 
368 	if (iso->rx.ep != NULL) {
369 		unicast_client_ep_iso_connected(iso->rx.ep);
370 	}
371 
372 	if (iso->tx.ep != NULL) {
373 		unicast_client_ep_iso_connected(iso->tx.ep);
374 	}
375 }
376 
unicast_client_ep_iso_disconnected(struct bt_bap_ep * ep,uint8_t reason)377 static void unicast_client_ep_iso_disconnected(struct bt_bap_ep *ep, uint8_t reason)
378 {
379 	const struct bt_bap_stream_ops *stream_ops;
380 	struct bt_bap_stream *stream;
381 
382 	stream = ep->stream;
383 	if (stream == NULL) {
384 		LOG_ERR("Stream not associated with an ep");
385 		return;
386 	}
387 
388 	LOG_DBG("stream %p ep %p reason 0x%02x", stream, ep, reason);
389 	ep->reason = reason;
390 
391 	stream_ops = stream->ops;
392 	if (stream_ops != NULL && stream_ops->disconnected != NULL) {
393 		stream_ops->disconnected(stream, reason);
394 	}
395 
396 	/* If we were in the idle state when we started the ISO disconnection
397 	 * then we need to call unicast_client_ep_idle_state again when
398 	 * the ISO has finalized the disconnection
399 	 */
400 	if (ep->status.state == BT_BAP_EP_STATE_IDLE) {
401 
402 		unicast_client_ep_idle_state(ep);
403 
404 		if (stream->conn != NULL) {
405 			struct bt_conn_info conn_info;
406 			int err;
407 
408 			err = bt_conn_get_info(stream->conn, &conn_info);
409 			if (err != 0 || conn_info.state == BT_CONN_STATE_DISCONNECTED) {
410 				/* Retrigger the reset of the EP if the ACL is disconnected before
411 				 * the ISO is disconnected
412 				 */
413 				unicast_client_reset(ep, reason);
414 			}
415 		}
416 	}
417 }
418 
unicast_client_iso_disconnected(struct bt_iso_chan * chan,uint8_t reason)419 static void unicast_client_iso_disconnected(struct bt_iso_chan *chan, uint8_t reason)
420 {
421 	struct bt_bap_iso *iso = CONTAINER_OF(chan, struct bt_bap_iso, chan);
422 
423 	if (iso->rx.ep == NULL && iso->tx.ep == NULL) {
424 		LOG_ERR("iso %p not bound with ep", chan);
425 		return;
426 	}
427 
428 	if (iso->rx.ep != NULL) {
429 		unicast_client_ep_iso_disconnected(iso->rx.ep, reason);
430 	}
431 
432 	if (iso->tx.ep != NULL) {
433 		unicast_client_ep_iso_disconnected(iso->tx.ep, reason);
434 	}
435 }
436 
437 static struct bt_iso_chan_ops unicast_client_iso_ops = {
438 #if defined(CONFIG_BT_AUDIO_RX)
439 	.recv = unicast_client_ep_iso_recv,
440 #endif /* CONFIG_BT_AUDIO_RX */
441 #if defined(CONFIG_BT_AUDIO_TX)
442 	.sent = unicast_client_ep_iso_sent,
443 #endif /* CONFIG_BT_AUDIO_TX */
444 	.connected = unicast_client_iso_connected,
445 	.disconnected = unicast_client_iso_disconnected,
446 };
447 
bt_bap_ep_is_unicast_client(const struct bt_bap_ep * ep)448 bool bt_bap_ep_is_unicast_client(const struct bt_bap_ep *ep)
449 {
450 	for (size_t i = 0U; i < ARRAY_SIZE(uni_cli_insts); i++) {
451 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
452 		if (PART_OF_ARRAY(uni_cli_insts[i].snks, ep)) {
453 			return true;
454 		}
455 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
456 
457 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
458 		if (PART_OF_ARRAY(uni_cli_insts[i].srcs, ep)) {
459 			return true;
460 		}
461 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
462 	}
463 
464 	return false;
465 }
466 
unicast_client_ep_init(struct bt_bap_ep * ep,uint16_t handle,uint8_t dir)467 static void unicast_client_ep_init(struct bt_bap_ep *ep, uint16_t handle, uint8_t dir)
468 {
469 	struct bt_bap_unicast_client_ep *client_ep;
470 
471 	LOG_DBG("ep %p dir %s handle 0x%04x", ep, bt_audio_dir_str(dir), handle);
472 
473 	client_ep = CONTAINER_OF(ep, struct bt_bap_unicast_client_ep, ep);
474 
475 	(void)memset(ep, 0, sizeof(*ep));
476 	client_ep->handle = handle;
477 	ep->status.id = 0U;
478 	ep->dir = dir;
479 	ep->reason = BT_HCI_ERR_SUCCESS;
480 	k_work_init_delayable(&client_ep->ase_read_work, delayed_ase_read_handler);
481 }
482 
unicast_client_ep_find(struct bt_conn * conn,uint16_t handle)483 static struct bt_bap_ep *unicast_client_ep_find(struct bt_conn *conn, uint16_t handle)
484 {
485 	uint8_t index;
486 
487 	index = bt_conn_index(conn);
488 
489 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
490 	for (size_t i = 0U; i < ARRAY_SIZE(uni_cli_insts[index].snks); i++) {
491 		struct bt_bap_unicast_client_ep *client_ep = &uni_cli_insts[index].snks[i];
492 
493 		if ((handle && client_ep->handle == handle) || (!handle && client_ep->handle)) {
494 			return &client_ep->ep;
495 		}
496 	}
497 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
498 
499 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
500 	for (size_t i = 0U; i < ARRAY_SIZE(uni_cli_insts[index].srcs); i++) {
501 		struct bt_bap_unicast_client_ep *client_ep = &uni_cli_insts[index].srcs[i];
502 
503 		if ((handle && client_ep->handle == handle) || (!handle && client_ep->handle)) {
504 			return &client_ep->ep;
505 		}
506 	}
507 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
508 
509 	return NULL;
510 }
511 
bt_bap_unicast_client_new_audio_iso(void)512 struct bt_bap_iso *bt_bap_unicast_client_new_audio_iso(void)
513 {
514 	struct bt_bap_iso *bap_iso;
515 
516 	bap_iso = bt_bap_iso_new();
517 	if (bap_iso == NULL) {
518 		return NULL;
519 	}
520 
521 	bt_bap_iso_init(bap_iso, &unicast_client_iso_ops);
522 
523 	LOG_DBG("New bap_iso %p", bap_iso);
524 
525 	return bap_iso;
526 }
527 
unicast_client_ep_new(struct bt_conn * conn,enum bt_audio_dir dir,uint16_t handle)528 static struct bt_bap_ep *unicast_client_ep_new(struct bt_conn *conn, enum bt_audio_dir dir,
529 					       uint16_t handle)
530 {
531 	size_t i, size;
532 	uint8_t index;
533 	struct bt_bap_unicast_client_ep *cache;
534 
535 	index = bt_conn_index(conn);
536 
537 	switch (dir) {
538 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
539 	case BT_AUDIO_DIR_SINK:
540 		cache = uni_cli_insts[index].snks;
541 		size = ARRAY_SIZE(uni_cli_insts[index].snks);
542 		break;
543 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
544 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
545 	case BT_AUDIO_DIR_SOURCE:
546 		cache = uni_cli_insts[index].srcs;
547 		size = ARRAY_SIZE(uni_cli_insts[index].srcs);
548 		break;
549 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
550 	default:
551 		return NULL;
552 	}
553 
554 	for (i = 0; i < size; i++) {
555 		struct bt_bap_unicast_client_ep *client_ep = &cache[i];
556 
557 		if (!client_ep->handle) {
558 			unicast_client_ep_init(&client_ep->ep, handle, dir);
559 			return &client_ep->ep;
560 		}
561 	}
562 
563 	return NULL;
564 }
565 
unicast_client_ep_get(struct bt_conn * conn,enum bt_audio_dir dir,uint16_t handle)566 static struct bt_bap_ep *unicast_client_ep_get(struct bt_conn *conn, enum bt_audio_dir dir,
567 					       uint16_t handle)
568 {
569 	struct bt_bap_ep *ep;
570 
571 	ep = unicast_client_ep_find(conn, handle);
572 	if (ep || !handle) {
573 		return ep;
574 	}
575 
576 	return unicast_client_ep_new(conn, dir, handle);
577 }
578 
unicast_client_ep_set_local_idle_state(struct bt_bap_ep * ep)579 static void unicast_client_ep_set_local_idle_state(struct bt_bap_ep *ep)
580 {
581 	struct bt_ascs_ase_status status = {
582 		.id = ep->status.id,
583 		.state = BT_BAP_EP_STATE_IDLE,
584 	};
585 	struct net_buf_simple buf;
586 
587 	net_buf_simple_init_with_data(&buf, &status, sizeof(status));
588 
589 	unicast_client_ep_set_status(ep, &buf);
590 }
591 
unicast_client_notify_location(struct bt_conn * conn,enum bt_audio_dir dir,enum bt_audio_location loc)592 static void unicast_client_notify_location(struct bt_conn *conn, enum bt_audio_dir dir,
593 					   enum bt_audio_location loc)
594 {
595 	struct bt_bap_unicast_client_cb *listener, *next;
596 
597 	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&unicast_client_cbs, listener, next, _node) {
598 		if (listener->location != NULL) {
599 			listener->location(conn, dir, loc);
600 		}
601 	}
602 }
603 
unicast_client_notify_available_contexts(struct bt_conn * conn,enum bt_audio_context snk_ctx,enum bt_audio_context src_ctx)604 static void unicast_client_notify_available_contexts(struct bt_conn *conn,
605 						     enum bt_audio_context snk_ctx,
606 						     enum bt_audio_context src_ctx)
607 {
608 	struct bt_bap_unicast_client_cb *listener, *next;
609 
610 	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&unicast_client_cbs, listener, next, _node) {
611 		if (listener->available_contexts != NULL) {
612 			listener->available_contexts(conn, snk_ctx, src_ctx);
613 		}
614 	}
615 }
616 
unicast_client_notify_pac_record(struct bt_conn * conn,const struct bt_audio_codec_cap * codec_cap)617 static void unicast_client_notify_pac_record(struct bt_conn *conn,
618 					     const struct bt_audio_codec_cap *codec_cap)
619 {
620 	const struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
621 	struct bt_bap_unicast_client_cb *listener, *next;
622 	const enum bt_audio_dir dir = client->dir;
623 
624 	/* TBD: Since the PAC records are optionally notifiable we may want to supply the
625 	 * index and total count of records in the callback, so that it easier for the
626 	 * upper layers to determine when a new set of PAC records is being reported.
627 	 */
628 
629 	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&unicast_client_cbs, listener, next, _node) {
630 		if (listener->pac_record != NULL) {
631 			listener->pac_record(conn, dir, codec_cap);
632 		}
633 	}
634 }
635 
unicast_client_notify_endpoint(struct bt_conn * conn,struct bt_bap_ep * ep)636 static void unicast_client_notify_endpoint(struct bt_conn *conn, struct bt_bap_ep *ep)
637 {
638 	const struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
639 	struct bt_bap_unicast_client_cb *listener, *next;
640 	const enum bt_audio_dir dir = client->dir;
641 
642 	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&unicast_client_cbs, listener, next, _node) {
643 		if (listener->endpoint != NULL) {
644 			listener->endpoint(conn, dir, ep);
645 		}
646 	}
647 }
648 
unicast_client_discover_complete(struct bt_conn * conn,int err)649 static void unicast_client_discover_complete(struct bt_conn *conn, int err)
650 {
651 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
652 	struct bt_bap_unicast_client_cb *listener, *next;
653 	const enum bt_audio_dir dir = client->dir;
654 
655 	/* Discover complete - Reset discovery values */
656 	client->dir = 0U;
657 	reset_att_buf(client);
658 	atomic_clear_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY);
659 
660 	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&unicast_client_cbs, listener, next, _node) {
661 		if (listener->discover != NULL) {
662 			listener->discover(conn, err, dir);
663 		}
664 	}
665 }
666 
unicast_client_notify_ep_config(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)667 static void unicast_client_notify_ep_config(struct bt_bap_stream *stream,
668 					    enum bt_bap_ascs_rsp_code rsp_code,
669 					    enum bt_bap_ascs_reason reason)
670 {
671 	struct bt_bap_unicast_client_cb *listener, *next;
672 
673 	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&unicast_client_cbs, listener, next, _node) {
674 		if (listener->config != NULL) {
675 			listener->config(stream, rsp_code, reason);
676 		}
677 	}
678 }
679 
unicast_client_notify_ep_qos(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)680 static void unicast_client_notify_ep_qos(struct bt_bap_stream *stream,
681 					 enum bt_bap_ascs_rsp_code rsp_code,
682 					 enum bt_bap_ascs_reason reason)
683 {
684 	struct bt_bap_unicast_client_cb *listener, *next;
685 
686 	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&unicast_client_cbs, listener, next, _node) {
687 		if (listener->qos != NULL) {
688 			listener->qos(stream, rsp_code, reason);
689 		}
690 	}
691 }
692 
unicast_client_notify_ep_enable(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)693 static void unicast_client_notify_ep_enable(struct bt_bap_stream *stream,
694 					    enum bt_bap_ascs_rsp_code rsp_code,
695 					    enum bt_bap_ascs_reason reason)
696 {
697 	struct bt_bap_unicast_client_cb *listener, *next;
698 
699 	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&unicast_client_cbs, listener, next, _node) {
700 		if (listener->enable != NULL) {
701 			listener->enable(stream, rsp_code, reason);
702 		}
703 	}
704 }
705 
unicast_client_notify_ep_start(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)706 static void unicast_client_notify_ep_start(struct bt_bap_stream *stream,
707 					   enum bt_bap_ascs_rsp_code rsp_code,
708 					   enum bt_bap_ascs_reason reason)
709 {
710 	struct bt_bap_unicast_client_cb *listener, *next;
711 
712 	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&unicast_client_cbs, listener, next, _node) {
713 		if (listener->start != NULL) {
714 			listener->start(stream, rsp_code, reason);
715 		}
716 	}
717 }
718 
unicast_client_notify_ep_stop(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)719 static void unicast_client_notify_ep_stop(struct bt_bap_stream *stream,
720 					  enum bt_bap_ascs_rsp_code rsp_code,
721 					  enum bt_bap_ascs_reason reason)
722 {
723 	struct bt_bap_unicast_client_cb *listener, *next;
724 
725 	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&unicast_client_cbs, listener, next, _node) {
726 		if (listener->stop != NULL) {
727 			listener->stop(stream, rsp_code, reason);
728 		}
729 	}
730 }
731 
unicast_client_notify_ep_disable(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)732 static void unicast_client_notify_ep_disable(struct bt_bap_stream *stream,
733 					     enum bt_bap_ascs_rsp_code rsp_code,
734 					     enum bt_bap_ascs_reason reason)
735 {
736 	struct bt_bap_unicast_client_cb *listener, *next;
737 
738 	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&unicast_client_cbs, listener, next, _node) {
739 		if (listener->disable != NULL) {
740 			listener->disable(stream, rsp_code, reason);
741 		}
742 	}
743 }
744 
unicast_client_notify_ep_metadata(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)745 static void unicast_client_notify_ep_metadata(struct bt_bap_stream *stream,
746 					      enum bt_bap_ascs_rsp_code rsp_code,
747 					      enum bt_bap_ascs_reason reason)
748 {
749 	struct bt_bap_unicast_client_cb *listener, *next;
750 
751 	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&unicast_client_cbs, listener, next, _node) {
752 		if (listener->metadata != NULL) {
753 			listener->metadata(stream, rsp_code, reason);
754 		}
755 	}
756 }
757 
unicast_client_notify_ep_released(struct bt_bap_stream * stream,enum bt_bap_ascs_rsp_code rsp_code,enum bt_bap_ascs_reason reason)758 static void unicast_client_notify_ep_released(struct bt_bap_stream *stream,
759 					      enum bt_bap_ascs_rsp_code rsp_code,
760 					      enum bt_bap_ascs_reason reason)
761 {
762 	struct bt_bap_unicast_client_cb *listener, *next;
763 
764 	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&unicast_client_cbs, listener, next, _node) {
765 		if (listener->release != NULL) {
766 			listener->release(stream, rsp_code, reason);
767 		}
768 	}
769 }
770 
unicast_client_ep_idle_state(struct bt_bap_ep * ep)771 static void unicast_client_ep_idle_state(struct bt_bap_ep *ep)
772 {
773 	struct bt_bap_unicast_client_ep *client_ep =
774 		CONTAINER_OF(ep, struct bt_bap_unicast_client_ep, ep);
775 	struct bt_bap_stream *stream = ep->stream;
776 	const struct bt_bap_stream_ops *ops;
777 
778 	ep->receiver_ready = false;
779 
780 	if (stream == NULL) {
781 		return;
782 	}
783 
784 	/* If CIS is connected, disconnect and wait for CIS disconnection */
785 	if (bt_bap_stream_can_disconnect(stream)) {
786 		int err;
787 
788 		LOG_DBG("Disconnecting stream");
789 		err = bt_bap_stream_disconnect(stream);
790 
791 		if (err != 0) {
792 			LOG_ERR("Failed to disconnect stream: %d", err);
793 		}
794 
795 		return;
796 	} else if (ep->iso != NULL && ep->iso->chan.state == BT_ISO_STATE_DISCONNECTING) {
797 		/* Wait for disconnection */
798 		return;
799 	}
800 
801 	bt_bap_stream_reset(stream);
802 
803 	/* Notify upper layer */
804 	if (client_ep->release_requested) {
805 		client_ep->release_requested = false;
806 
807 		if (client_ep->cp_ntf_pending) {
808 			/* In case that we get the idle state notification before the CP
809 			 * notification we trigger the CP callback now, as after this we won't be
810 			 * able to find the stream by the ASE ID
811 			 */
812 			client_ep->cp_ntf_pending = false;
813 
814 			unicast_client_notify_ep_released(stream, BT_BAP_ASCS_RSP_CODE_SUCCESS,
815 							  BT_BAP_ASCS_REASON_NONE);
816 		}
817 	}
818 
819 	ops = stream->ops;
820 	if (ops != NULL && ops->released != NULL) {
821 		ops->released(stream);
822 	} else {
823 		LOG_WRN("No callback for released set");
824 	}
825 }
826 
unicast_client_ep_qos_update(struct bt_bap_ep * ep,const struct bt_ascs_ase_status_qos * qos)827 static void unicast_client_ep_qos_update(struct bt_bap_ep *ep,
828 					 const struct bt_ascs_ase_status_qos *qos)
829 {
830 	struct bt_iso_chan_io_qos *iso_io_qos;
831 
832 	LOG_DBG("ep %p dir %s bap_iso %p", ep, bt_audio_dir_str(ep->dir), ep->iso);
833 
834 	if (ep->dir == BT_AUDIO_DIR_SOURCE) {
835 		/* If the endpoint is a source, then we need to
836 		 * reset our RX parameters
837 		 */
838 		iso_io_qos = &ep->iso->rx.qos;
839 	} else if (ep->dir == BT_AUDIO_DIR_SINK) {
840 		/* If the endpoint is a sink, then we need to
841 		 * reset our TX parameters
842 		 */
843 		iso_io_qos = &ep->iso->tx.qos;
844 	} else {
845 		__ASSERT(false, "Invalid ep->dir: %u", ep->dir);
846 		return;
847 	}
848 
849 	iso_io_qos->phy = qos->phy;
850 	iso_io_qos->sdu = sys_le16_to_cpu(qos->sdu);
851 	iso_io_qos->rtn = qos->rtn;
852 }
853 
unicast_client_ep_config_state(struct bt_bap_ep * ep,struct net_buf_simple * buf)854 static void unicast_client_ep_config_state(struct bt_bap_ep *ep, struct net_buf_simple *buf)
855 {
856 	struct bt_bap_unicast_client_ep *client_ep =
857 		CONTAINER_OF(ep, struct bt_bap_unicast_client_ep, ep);
858 	struct bt_ascs_ase_status_config *cfg;
859 	struct bt_bap_qos_cfg_pref *pref;
860 	struct bt_bap_stream *stream;
861 	void *cc;
862 
863 	ep->receiver_ready = false;
864 
865 	if (client_ep->release_requested) {
866 		LOG_DBG("Released was requested, change local state to idle");
867 		ep->reason = BT_HCI_ERR_LOCALHOST_TERM_CONN;
868 		unicast_client_ep_set_local_idle_state(ep);
869 		return;
870 	}
871 
872 	if (buf->len < sizeof(*cfg)) {
873 		LOG_ERR("Config status too short");
874 		return;
875 	}
876 
877 	stream = ep->stream;
878 	if (stream == NULL) {
879 		LOG_WRN("No stream active for endpoint");
880 		return;
881 	}
882 
883 	cfg = net_buf_simple_pull_mem(buf, sizeof(*cfg));
884 
885 	if (stream->codec_cfg == NULL) {
886 		LOG_ERR("Stream %p does not have a codec configured", stream);
887 		return;
888 	} else if (stream->codec_cfg->id != cfg->codec.id) {
889 		LOG_ERR("Codec configuration mismatched: %u, %u", stream->codec_cfg->id,
890 			cfg->codec.id);
891 		/* TODO: Release the stream? */
892 		return;
893 	}
894 
895 	if (buf->len < cfg->cc_len) {
896 		LOG_ERR("Malformed ASE Config status: buf->len %u < %u cc_len", buf->len,
897 			cfg->cc_len);
898 		return;
899 	}
900 
901 	cc = net_buf_simple_pull_mem(buf, cfg->cc_len);
902 
903 	pref = &stream->ep->qos_pref;
904 
905 	/* Convert to interval representation so they can be matched by QoS */
906 	pref->unframed_supported = cfg->framing == BT_ASCS_QOS_FRAMING_UNFRAMED;
907 	pref->phy = cfg->phy;
908 	pref->rtn = cfg->rtn;
909 	pref->latency = sys_le16_to_cpu(cfg->latency);
910 	pref->pd_min = sys_get_le24(cfg->pd_min);
911 	pref->pd_max = sys_get_le24(cfg->pd_max);
912 	pref->pref_pd_min = sys_get_le24(cfg->prefer_pd_min);
913 	pref->pref_pd_max = sys_get_le24(cfg->prefer_pd_max);
914 
915 	LOG_DBG("dir %s unframed_supported 0x%02x phy 0x%02x rtn %u "
916 		"latency %u pd_min %u pd_max %u pref_pd_min %u pref_pd_max %u codec 0x%02x ",
917 		bt_audio_dir_str(ep->dir), pref->unframed_supported, pref->phy, pref->rtn,
918 		pref->latency, pref->pd_min, pref->pd_max, pref->pref_pd_min, pref->pref_pd_max,
919 		stream->codec_cfg->id);
920 
921 	if (!bt_bap_valid_qos_pref(pref)) {
922 		LOG_DBG("Invalid QoS preferences");
923 		memset(pref, 0, sizeof(*pref));
924 
925 		/* If the sever provide an invalid QoS preferences we treat it as an error and do
926 		 * nothing
927 		 */
928 		return;
929 	}
930 
931 	unicast_client_ep_set_codec_cfg(ep, cfg->codec.id, sys_le16_to_cpu(cfg->codec.cid),
932 					sys_le16_to_cpu(cfg->codec.vid), cc, cfg->cc_len, NULL);
933 
934 	/* Notify upper layer */
935 	if (stream->ops != NULL && stream->ops->configured != NULL) {
936 		stream->ops->configured(stream, pref);
937 	} else {
938 		LOG_WRN("No callback for configured set");
939 	}
940 }
941 
unicast_client_ep_qos_state(struct bt_bap_ep * ep,struct net_buf_simple * buf,uint8_t old_state)942 static void unicast_client_ep_qos_state(struct bt_bap_ep *ep, struct net_buf_simple *buf,
943 					uint8_t old_state)
944 {
945 	const struct bt_bap_stream_ops *ops;
946 	struct bt_ascs_ase_status_qos *qos;
947 	struct bt_bap_stream *stream;
948 
949 	ep->receiver_ready = false;
950 
951 	if (buf->len < sizeof(*qos)) {
952 		LOG_ERR("QoS status too short");
953 		return;
954 	}
955 
956 	stream = ep->stream;
957 	if (stream == NULL) {
958 		LOG_ERR("No stream active for endpoint");
959 		return;
960 	}
961 	ops = stream->ops;
962 
963 	if (ops != NULL) {
964 		if (ep->dir == BT_AUDIO_DIR_SINK && ops->disabled != NULL) {
965 			/* If the old state was enabling or streaming, then the sink
966 			 * ASE has been disabled. Since the sink ASE does not have a
967 			 * disabling state, we can check if by comparing the old_state
968 			 */
969 			const bool disabled = old_state == BT_BAP_EP_STATE_ENABLING ||
970 					      old_state == BT_BAP_EP_STATE_STREAMING;
971 
972 			if (disabled) {
973 				ops->disabled(stream);
974 			}
975 		} else if (ep->dir == BT_AUDIO_DIR_SOURCE &&
976 			   old_state == BT_BAP_EP_STATE_DISABLING && ops->stopped != NULL) {
977 			/* We left the disabling state, let the upper layers know that the stream is
978 			 * stopped
979 			 */
980 			uint8_t reason = ep->reason;
981 
982 			if (reason == BT_HCI_ERR_SUCCESS) {
983 				/* Default to BT_HCI_ERR_UNSPECIFIED if no other reason is set */
984 				reason = BT_HCI_ERR_UNSPECIFIED;
985 			} else {
986 				/* Reset reason */
987 				ep->reason = BT_HCI_ERR_SUCCESS;
988 			}
989 
990 			ops->stopped(stream, reason);
991 		}
992 	}
993 
994 	qos = net_buf_simple_pull_mem(buf, sizeof(*qos));
995 
996 	/* Update existing QoS configuration */
997 	unicast_client_ep_qos_update(ep, qos);
998 
999 	ep->cig_id = qos->cig_id;
1000 	ep->cis_id = qos->cis_id;
1001 	(void)memcpy(&stream->qos->interval, sys_le24_to_cpu(qos->interval), sizeof(qos->interval));
1002 	stream->qos->framing = qos->framing;
1003 	stream->qos->phy = qos->phy;
1004 	stream->qos->sdu = sys_le16_to_cpu(qos->sdu);
1005 	stream->qos->rtn = qos->rtn;
1006 	stream->qos->latency = sys_le16_to_cpu(qos->latency);
1007 	(void)memcpy(&stream->qos->pd, sys_le24_to_cpu(qos->pd), sizeof(qos->pd));
1008 
1009 	LOG_DBG("dir %s cig 0x%02x cis 0x%02x codec 0x%02x interval %u "
1010 		"framing 0x%02x phy 0x%02x rtn %u latency %u pd %u",
1011 		bt_audio_dir_str(ep->dir), ep->cig_id, ep->cis_id, stream->codec_cfg->id,
1012 		stream->qos->interval, stream->qos->framing, stream->qos->phy, stream->qos->rtn,
1013 		stream->qos->latency, stream->qos->pd);
1014 
1015 	/* Disconnect ISO if connected */
1016 	if (bt_bap_stream_can_disconnect(stream)) {
1017 		const int err = bt_bap_stream_disconnect(stream);
1018 
1019 		if (err != 0) {
1020 			LOG_ERR("Failed to disconnect stream: %d", err);
1021 		}
1022 	} else {
1023 		/* We setup the data path here, as this is the earliest where
1024 		 * we have the ISO <-> EP coupling completed (due to setting
1025 		 * the CIS ID in the QoS procedure).
1026 		 */
1027 
1028 		bt_bap_iso_configure_data_path(ep, stream->codec_cfg);
1029 	}
1030 
1031 	/* Notify upper layer */
1032 	if (stream->ops != NULL && stream->ops->qos_set != NULL) {
1033 		stream->ops->qos_set(stream);
1034 	} else {
1035 		LOG_WRN("No callback for qos_set set");
1036 	}
1037 }
1038 
unicast_client_ep_enabling_state(struct bt_bap_ep * ep,struct net_buf_simple * buf,bool state_changed)1039 static void unicast_client_ep_enabling_state(struct bt_bap_ep *ep, struct net_buf_simple *buf,
1040 					     bool state_changed)
1041 {
1042 	struct bt_ascs_ase_status_enable *enable;
1043 	struct bt_bap_stream *stream;
1044 	void *metadata;
1045 
1046 	if (buf->len < sizeof(*enable)) {
1047 		LOG_ERR("Enabling status too short");
1048 		return;
1049 	}
1050 
1051 	stream = ep->stream;
1052 	if (stream == NULL) {
1053 		LOG_ERR("No stream active for endpoint");
1054 		return;
1055 	}
1056 
1057 	enable = net_buf_simple_pull_mem(buf, sizeof(*enable));
1058 
1059 	if (buf->len < enable->metadata_len) {
1060 		LOG_ERR("Malformed PDU: remaining len %u expected %u", buf->len,
1061 			enable->metadata_len);
1062 		return;
1063 	}
1064 
1065 	metadata = net_buf_simple_pull_mem(buf, enable->metadata_len);
1066 
1067 	LOG_DBG("dir %s cig 0x%02x cis 0x%02x", bt_audio_dir_str(ep->dir), ep->cig_id, ep->cis_id);
1068 
1069 	unicast_client_ep_set_metadata(ep, metadata, enable->metadata_len, NULL);
1070 
1071 	/* Notify upper layer
1072 	 *
1073 	 * If the state did not change then only the metadata was changed
1074 	 */
1075 	if (state_changed) {
1076 		if (stream->ops != NULL && stream->ops->enabled != NULL) {
1077 			stream->ops->enabled(stream);
1078 		} else {
1079 			LOG_WRN("No callback for enabled set");
1080 		}
1081 	} else {
1082 		if (stream->ops != NULL && stream->ops->metadata_updated != NULL) {
1083 			stream->ops->metadata_updated(stream);
1084 		} else {
1085 			LOG_WRN("No callback for metadata_updated set");
1086 		}
1087 	}
1088 }
1089 
unicast_client_ep_streaming_state(struct bt_bap_ep * ep,struct net_buf_simple * buf,bool state_changed)1090 static void unicast_client_ep_streaming_state(struct bt_bap_ep *ep, struct net_buf_simple *buf,
1091 					      bool state_changed)
1092 {
1093 	struct bt_ascs_ase_status_stream *stream_status;
1094 	struct bt_bap_stream *stream;
1095 
1096 	if (buf->len < sizeof(*stream_status)) {
1097 		LOG_ERR("Streaming status too short");
1098 		return;
1099 	}
1100 
1101 	stream = ep->stream;
1102 	if (stream == NULL) {
1103 		LOG_ERR("No stream active for endpoint");
1104 		return;
1105 	}
1106 
1107 	stream_status = net_buf_simple_pull_mem(buf, sizeof(*stream_status));
1108 
1109 	LOG_DBG("dir %s cig 0x%02x cis 0x%02x", bt_audio_dir_str(ep->dir), ep->cig_id, ep->cis_id);
1110 
1111 	/* Notify upper layer
1112 	 *
1113 	 * If the state did not change then only the metadata was changed
1114 	 */
1115 	if (state_changed) {
1116 		if (stream->ops != NULL && stream->ops->started != NULL) {
1117 			stream->ops->started(stream);
1118 		} else {
1119 			LOG_WRN("No callback for started set");
1120 		}
1121 	} else {
1122 		if (stream->ops != NULL && stream->ops->metadata_updated != NULL) {
1123 			stream->ops->metadata_updated(stream);
1124 		} else {
1125 			LOG_WRN("No callback for metadata_updated set");
1126 		}
1127 	}
1128 }
1129 
unicast_client_ep_disabling_state(struct bt_bap_ep * ep,struct net_buf_simple * buf)1130 static void unicast_client_ep_disabling_state(struct bt_bap_ep *ep, struct net_buf_simple *buf)
1131 {
1132 	struct bt_ascs_ase_status_disable *disable;
1133 	struct bt_bap_stream *stream;
1134 
1135 	ep->receiver_ready = false;
1136 
1137 	if (buf->len < sizeof(*disable)) {
1138 		LOG_ERR("Disabling status too short");
1139 		return;
1140 	}
1141 
1142 	stream = ep->stream;
1143 	if (stream == NULL) {
1144 		LOG_ERR("No stream active for endpoint");
1145 		return;
1146 	}
1147 
1148 	disable = net_buf_simple_pull_mem(buf, sizeof(*disable));
1149 
1150 	LOG_DBG("dir %s cig 0x%02x cis 0x%02x", bt_audio_dir_str(ep->dir), ep->cig_id, ep->cis_id);
1151 
1152 	/* Notify upper layer */
1153 	if (stream->ops != NULL && stream->ops->disabled != NULL) {
1154 		stream->ops->disabled(stream);
1155 	} else {
1156 		LOG_WRN("No callback for disabled set");
1157 	}
1158 }
1159 
unicast_client_ep_releasing_state(struct bt_bap_ep * ep,struct net_buf_simple * buf)1160 static void unicast_client_ep_releasing_state(struct bt_bap_ep *ep, struct net_buf_simple *buf)
1161 {
1162 	struct bt_bap_stream *stream;
1163 
1164 	ep->receiver_ready = false;
1165 
1166 	stream = ep->stream;
1167 	if (stream == NULL) {
1168 		LOG_ERR("No stream active for endpoint");
1169 		return;
1170 	}
1171 
1172 	LOG_DBG("dir %s", bt_audio_dir_str(ep->dir));
1173 
1174 	if (bt_bap_stream_can_disconnect(stream)) {
1175 		/* The Unicast Client shall terminate any CIS established for
1176 		 * that ASE by following the Connected Isochronous Stream
1177 		 * Terminate procedure defined in Volume 3, Part C,
1178 		 * Section 9.3.15 in when the Unicast Client has determined
1179 		 * that the ASE is in the Releasing state.
1180 		 */
1181 		const int err = bt_bap_stream_disconnect(stream);
1182 
1183 		if (err != 0) {
1184 			LOG_ERR("Failed to disconnect stream: %d", err);
1185 		}
1186 	}
1187 }
1188 
unicast_client_ep_set_status(struct bt_bap_ep * ep,struct net_buf_simple * buf)1189 static void unicast_client_ep_set_status(struct bt_bap_ep *ep, struct net_buf_simple *buf)
1190 {
1191 	struct bt_ascs_ase_status *status;
1192 	struct bt_bap_unicast_client_ep *client_ep;
1193 	bool state_changed;
1194 	uint8_t old_state;
1195 
1196 	if (!ep) {
1197 		return;
1198 	}
1199 
1200 	client_ep = CONTAINER_OF(ep, struct bt_bap_unicast_client_ep, ep);
1201 
1202 	status = net_buf_simple_pull_mem(buf, sizeof(*status));
1203 
1204 	old_state = ep->status.state;
1205 	ep->status = *status;
1206 	state_changed = old_state != ep->status.state;
1207 
1208 	if (state_changed && old_state == BT_BAP_EP_STATE_STREAMING) {
1209 		/* We left the streaming state, let the upper layers know that the stream is stopped
1210 		 */
1211 		struct bt_bap_stream *stream = ep->stream;
1212 
1213 		if (stream != NULL) {
1214 			struct bt_bap_stream_ops *ops = stream->ops;
1215 			uint8_t reason = ep->reason;
1216 
1217 			if (reason == BT_HCI_ERR_SUCCESS) {
1218 				/* Default to BT_HCI_ERR_UNSPECIFIED if no other reason is set */
1219 				reason = BT_HCI_ERR_UNSPECIFIED;
1220 			} else {
1221 				/* Reset reason */
1222 				ep->reason = BT_HCI_ERR_SUCCESS;
1223 			}
1224 
1225 			if (ops != NULL && ops->stopped != NULL) {
1226 				ops->stopped(stream, reason);
1227 			} else {
1228 				LOG_WRN("No callback for stopped set");
1229 			}
1230 		}
1231 	}
1232 
1233 	LOG_DBG("ep %p handle 0x%04x id 0x%02x dir %s state %s -> %s", ep, client_ep->handle,
1234 		status->id, bt_audio_dir_str(ep->dir), bt_bap_ep_state_str(old_state),
1235 		bt_bap_ep_state_str(status->state));
1236 
1237 	switch (status->state) {
1238 	case BT_BAP_EP_STATE_IDLE:
1239 		unicast_client_ep_idle_state(ep);
1240 		break;
1241 	case BT_BAP_EP_STATE_CODEC_CONFIGURED:
1242 		switch (old_state) {
1243 		/* Valid only if ASE_State field = 0x00 (Idle) */
1244 		case BT_BAP_EP_STATE_IDLE:
1245 			/* or 0x01 (Codec Configured) */
1246 		case BT_BAP_EP_STATE_CODEC_CONFIGURED:
1247 			/* or 0x02 (QoS Configured) */
1248 		case BT_BAP_EP_STATE_QOS_CONFIGURED:
1249 			/* or 0x06 (Releasing) */
1250 		case BT_BAP_EP_STATE_RELEASING:
1251 			break;
1252 		default:
1253 			LOG_WRN("Invalid state transition: %s -> %s",
1254 				bt_bap_ep_state_str(old_state),
1255 				bt_bap_ep_state_str(ep->status.state));
1256 			return;
1257 		}
1258 
1259 		unicast_client_ep_config_state(ep, buf);
1260 		break;
1261 	case BT_BAP_EP_STATE_QOS_CONFIGURED:
1262 		/* QoS configured have different allowed states depending on the endpoint type */
1263 		if (ep->dir == BT_AUDIO_DIR_SOURCE) {
1264 			switch (old_state) {
1265 			/* Valid only if ASE_State field = 0x01 (Codec Configured) */
1266 			case BT_BAP_EP_STATE_CODEC_CONFIGURED:
1267 			/* or 0x02 (QoS Configured) */
1268 			case BT_BAP_EP_STATE_QOS_CONFIGURED:
1269 			/* or 0x04 (Streaming) if there is a disconnect */
1270 			case BT_BAP_EP_STATE_STREAMING:
1271 			/* or 0x05 (Disabling) */
1272 			case BT_BAP_EP_STATE_DISABLING:
1273 				break;
1274 			default:
1275 				LOG_WRN("Invalid state transition: %s -> %s",
1276 					bt_bap_ep_state_str(old_state),
1277 					bt_bap_ep_state_str(ep->status.state));
1278 				return;
1279 			}
1280 		} else {
1281 			switch (old_state) {
1282 			/* Valid only if ASE_State field = 0x01 (Codec Configured) */
1283 			case BT_BAP_EP_STATE_CODEC_CONFIGURED:
1284 			/* or 0x02 (QoS Configured) */
1285 			case BT_BAP_EP_STATE_QOS_CONFIGURED:
1286 			/* or 0x03 (Enabling) */
1287 			case BT_BAP_EP_STATE_ENABLING:
1288 			/* or 0x04 (Streaming)*/
1289 			case BT_BAP_EP_STATE_STREAMING:
1290 				break;
1291 			default:
1292 				LOG_WRN("Invalid state transition: %s -> %s",
1293 					bt_bap_ep_state_str(old_state),
1294 					bt_bap_ep_state_str(ep->status.state));
1295 				return;
1296 			}
1297 		}
1298 
1299 		unicast_client_ep_qos_state(ep, buf, old_state);
1300 		break;
1301 	case BT_BAP_EP_STATE_ENABLING:
1302 		switch (old_state) {
1303 		/* Valid only if ASE_State field = 0x02 (QoS Configured) */
1304 		case BT_BAP_EP_STATE_QOS_CONFIGURED:
1305 			/* or 0x03 (Enabling) */
1306 		case BT_BAP_EP_STATE_ENABLING:
1307 			break;
1308 		default:
1309 			LOG_WRN("Invalid state transition: %s -> %s",
1310 				bt_bap_ep_state_str(old_state),
1311 				bt_bap_ep_state_str(ep->status.state));
1312 			return;
1313 		}
1314 
1315 		unicast_client_ep_enabling_state(ep, buf, state_changed);
1316 		break;
1317 	case BT_BAP_EP_STATE_STREAMING:
1318 		switch (old_state) {
1319 		/* Valid only if ASE_State field = 0x03 (Enabling)*/
1320 		case BT_BAP_EP_STATE_ENABLING:
1321 			/* or 0x04 (Streaming)*/
1322 		case BT_BAP_EP_STATE_STREAMING:
1323 			break;
1324 		default:
1325 			LOG_WRN("Invalid state transition: %s -> %s",
1326 				bt_bap_ep_state_str(old_state),
1327 				bt_bap_ep_state_str(ep->status.state));
1328 			return;
1329 		}
1330 
1331 		unicast_client_ep_streaming_state(ep, buf, state_changed);
1332 		break;
1333 	case BT_BAP_EP_STATE_DISABLING:
1334 		if (ep->dir == BT_AUDIO_DIR_SOURCE) {
1335 			switch (old_state) {
1336 			/* Valid only if ASE_State field = 0x03 (Enabling) */
1337 			case BT_BAP_EP_STATE_ENABLING:
1338 			/* or 0x04 (Streaming) */
1339 			case BT_BAP_EP_STATE_STREAMING:
1340 				break;
1341 			default:
1342 				LOG_WRN("Invalid state transition: %s -> %s",
1343 					bt_bap_ep_state_str(old_state),
1344 					bt_bap_ep_state_str(ep->status.state));
1345 				return;
1346 			}
1347 		} else {
1348 			/* Sinks cannot go into the disabling state */
1349 			LOG_WRN("Invalid state transition: %s -> %s",
1350 				bt_bap_ep_state_str(old_state),
1351 				bt_bap_ep_state_str(ep->status.state));
1352 			return;
1353 		}
1354 
1355 		unicast_client_ep_disabling_state(ep, buf);
1356 		break;
1357 	case BT_BAP_EP_STATE_RELEASING:
1358 		switch (old_state) {
1359 		/* Valid only if ASE_State field = 0x01 (Codec Configured) */
1360 		case BT_BAP_EP_STATE_CODEC_CONFIGURED:
1361 			/* or 0x02 (QoS Configured) */
1362 		case BT_BAP_EP_STATE_QOS_CONFIGURED:
1363 			/* or 0x03 (Enabling) */
1364 		case BT_BAP_EP_STATE_ENABLING:
1365 			/* or 0x04 (Streaming) */
1366 		case BT_BAP_EP_STATE_STREAMING:
1367 			break;
1368 			/* or 0x04 (Disabling) */
1369 		case BT_BAP_EP_STATE_DISABLING:
1370 			if (ep->dir == BT_AUDIO_DIR_SOURCE) {
1371 				break;
1372 			} /* else fall through for sink */
1373 
1374 			/* fall through */
1375 		default:
1376 			LOG_WRN("Invalid state transition: %s -> %s",
1377 				bt_bap_ep_state_str(old_state),
1378 				bt_bap_ep_state_str(ep->status.state));
1379 			return;
1380 		}
1381 
1382 		unicast_client_ep_releasing_state(ep, buf);
1383 		break;
1384 	}
1385 }
1386 
valid_ltv_cb(struct bt_data * data,void * user_data)1387 static bool valid_ltv_cb(struct bt_data *data, void *user_data)
1388 {
1389 	/* just return true to continue parsing as bt_data_parse will validate for us */
1390 	return true;
1391 }
1392 
unicast_client_ep_set_codec_cfg(struct bt_bap_ep * ep,uint8_t id,uint16_t cid,uint16_t vid,void * data,uint8_t len,struct bt_audio_codec_cfg * codec_cfg)1393 static int unicast_client_ep_set_codec_cfg(struct bt_bap_ep *ep, uint8_t id, uint16_t cid,
1394 					   uint16_t vid, void *data, uint8_t len,
1395 					   struct bt_audio_codec_cfg *codec_cfg)
1396 {
1397 	if (!ep && !codec_cfg) {
1398 		return -EINVAL;
1399 	}
1400 
1401 	LOG_DBG("ep %p codec id 0x%02x cid 0x%04x vid 0x%04x len %u", ep, id, cid, vid, len);
1402 
1403 	if (!codec_cfg) {
1404 		codec_cfg = &ep->codec_cfg;
1405 	}
1406 
1407 	if (len > sizeof(codec_cfg->data)) {
1408 		LOG_DBG("Cannot store %u octets of codec data", len);
1409 
1410 		return -ENOMEM;
1411 	}
1412 
1413 	codec_cfg->id = id;
1414 	codec_cfg->cid = cid;
1415 	codec_cfg->vid = vid;
1416 
1417 	codec_cfg->data_len = len;
1418 	memcpy(codec_cfg->data, data, len);
1419 
1420 	return 0;
1421 }
1422 
unicast_client_set_codec_cap(uint8_t id,uint16_t cid,uint16_t vid,void * data,uint8_t data_len,void * meta,uint8_t meta_len,struct bt_audio_codec_cap * codec_cap)1423 static int unicast_client_set_codec_cap(uint8_t id, uint16_t cid, uint16_t vid, void *data,
1424 					uint8_t data_len, void *meta, uint8_t meta_len,
1425 					struct bt_audio_codec_cap *codec_cap)
1426 {
1427 	struct net_buf_simple buf;
1428 
1429 	if (!codec_cap) {
1430 		return -EINVAL;
1431 	}
1432 
1433 	LOG_DBG("codec id 0x%02x cid 0x%04x vid 0x%04x data_len %u meta_len %u", id, cid, vid,
1434 		data_len, meta_len);
1435 
1436 	/* Reset current data */
1437 	(void)memset(codec_cap, 0, sizeof(*codec_cap));
1438 
1439 	codec_cap->id = id;
1440 	codec_cap->cid = cid;
1441 	codec_cap->vid = vid;
1442 
1443 	if (data_len > 0U) {
1444 		if (data_len > sizeof(codec_cap->data)) {
1445 			return -ENOMEM;
1446 		}
1447 
1448 		net_buf_simple_init_with_data(&buf, data, data_len);
1449 
1450 		/* If codec is LC3, then it shall be LTV encoded - We verify this before storing the
1451 		 * data For any non-LC3 codecs, we cannot verify anything
1452 		 */
1453 		if (id == BT_HCI_CODING_FORMAT_LC3) {
1454 			bt_data_parse(&buf, valid_ltv_cb, NULL);
1455 
1456 			/* Check if all entries could be parsed */
1457 			if (buf.len) {
1458 				LOG_ERR("Unable to parse Codec capabilities: len %u", buf.len);
1459 				return -EINVAL;
1460 			}
1461 		}
1462 		memcpy(codec_cap->data, data, data_len);
1463 		codec_cap->data_len = data_len;
1464 	}
1465 
1466 	if (meta_len > 0U) {
1467 		if (meta_len > sizeof(codec_cap->meta)) {
1468 			return -ENOMEM;
1469 		}
1470 
1471 		net_buf_simple_init_with_data(&buf, meta, meta_len);
1472 
1473 		bt_data_parse(&buf, valid_ltv_cb, NULL);
1474 
1475 		/* Check if all entries could be parsed */
1476 		if (buf.len) {
1477 			LOG_ERR("Unable to parse Codec metadata: len %u", buf.len);
1478 			return -EINVAL;
1479 		}
1480 
1481 		memcpy(codec_cap->meta, meta, meta_len);
1482 		codec_cap->meta_len = meta_len;
1483 	}
1484 
1485 	return 0;
1486 }
1487 
unicast_client_ep_set_metadata(struct bt_bap_ep * ep,void * data,uint8_t len,struct bt_audio_codec_cfg * codec_cfg)1488 static int unicast_client_ep_set_metadata(struct bt_bap_ep *ep, void *data, uint8_t len,
1489 					  struct bt_audio_codec_cfg *codec_cfg)
1490 {
1491 	if (!ep && !codec_cfg) {
1492 		return -EINVAL;
1493 	}
1494 
1495 	LOG_DBG("ep %p len %u codec_cfg %p", ep, len, codec_cfg);
1496 
1497 	if (!codec_cfg) {
1498 		codec_cfg = &ep->codec_cfg;
1499 	}
1500 
1501 	if (len > sizeof(codec_cfg->meta)) {
1502 		LOG_DBG("Cannot store %u octets of metadata", len);
1503 
1504 		return -ENOMEM;
1505 	}
1506 
1507 	/* Reset current metadata */
1508 	codec_cfg->meta_len = len;
1509 	(void)memcpy(codec_cfg->meta, data, len);
1510 
1511 	return 0;
1512 }
1513 
unicast_client_cp_notify(struct bt_conn * conn,struct bt_gatt_subscribe_params * params,const void * data,uint16_t length)1514 static uint8_t unicast_client_cp_notify(struct bt_conn *conn,
1515 					struct bt_gatt_subscribe_params *params, const void *data,
1516 					uint16_t length)
1517 {
1518 	struct bt_ascs_cp_rsp *rsp;
1519 	struct net_buf_simple buf;
1520 
1521 	LOG_DBG("conn %p len %u", conn, length);
1522 
1523 	if (!data) {
1524 		LOG_DBG("Unsubscribed");
1525 		params->value_handle = BAP_HANDLE_UNUSED;
1526 		return BT_GATT_ITER_STOP;
1527 	}
1528 
1529 	net_buf_simple_init_with_data(&buf, (void *)data, length);
1530 
1531 	if (buf.len < sizeof(*rsp)) {
1532 		LOG_ERR("Control Point Notification too small");
1533 		return BT_GATT_ITER_STOP;
1534 	}
1535 
1536 	rsp = net_buf_simple_pull_mem(&buf, sizeof(*rsp));
1537 
1538 	if (rsp->num_ase == BT_ASCS_UNSUPP_OR_LENGTH_ERR_NUM_ASE) {
1539 		/* This is a special case where num_ase == BT_ASCS_UNSUPP_OR_LENGTH_ERR_NUM_ASE
1540 		 * but really there is only one ASE response
1541 		 */
1542 		rsp->num_ase = 1U;
1543 	}
1544 
1545 	for (uint8_t i = 0U; i < rsp->num_ase; i++) {
1546 		struct bt_bap_unicast_client_ep *client_ep = NULL;
1547 		struct bt_ascs_cp_ase_rsp *ase_rsp;
1548 		struct bt_bap_stream *stream;
1549 
1550 		if (buf.len < sizeof(*ase_rsp)) {
1551 			LOG_ERR("Control Point Notification too small: %u", buf.len);
1552 			return BT_GATT_ITER_STOP;
1553 		}
1554 
1555 		ase_rsp = net_buf_simple_pull_mem(&buf, sizeof(*ase_rsp));
1556 
1557 		LOG_DBG("op %s (0x%02x) id 0x%02x code %s (0x%02x) "
1558 			"reason %s (0x%02x)", bt_ascs_op_str(rsp->op), rsp->op,
1559 			ase_rsp->id, bt_ascs_rsp_str(ase_rsp->code),
1560 			ase_rsp->code, bt_ascs_reason_str(ase_rsp->reason),
1561 			ase_rsp->reason);
1562 
1563 		stream = audio_stream_by_ep_id(conn, ase_rsp->id);
1564 		if (stream == NULL) {
1565 			LOG_DBG("Could not find stream by id %u", ase_rsp->id);
1566 		} else {
1567 			client_ep = CONTAINER_OF(stream->ep, struct bt_bap_unicast_client_ep, ep);
1568 			client_ep->cp_ntf_pending = false;
1569 		}
1570 
1571 		switch (rsp->op) {
1572 		case BT_ASCS_CONFIG_OP:
1573 			unicast_client_notify_ep_config(stream, ase_rsp->code, ase_rsp->reason);
1574 			break;
1575 		case BT_ASCS_QOS_OP:
1576 			unicast_client_notify_ep_qos(stream, ase_rsp->code, ase_rsp->reason);
1577 			break;
1578 		case BT_ASCS_ENABLE_OP:
1579 			unicast_client_notify_ep_enable(stream, ase_rsp->code, ase_rsp->reason);
1580 			break;
1581 		case BT_ASCS_START_OP:
1582 			unicast_client_notify_ep_start(stream, ase_rsp->code, ase_rsp->reason);
1583 			break;
1584 		case BT_ASCS_DISABLE_OP:
1585 			unicast_client_notify_ep_disable(stream, ase_rsp->code, ase_rsp->reason);
1586 			break;
1587 		case BT_ASCS_STOP_OP:
1588 			unicast_client_notify_ep_stop(stream, ase_rsp->code, ase_rsp->reason);
1589 			break;
1590 		case BT_ASCS_METADATA_OP:
1591 			unicast_client_notify_ep_metadata(stream, ase_rsp->code, ase_rsp->reason);
1592 			break;
1593 		case BT_ASCS_RELEASE_OP:
1594 			/* client_ep->release_requested is set to false if handled by the
1595 			 * endpoint notification handler
1596 			 */
1597 			if (client_ep != NULL && client_ep->release_requested) {
1598 				/* If request was reject, do not expect endpoint notifications */
1599 				if (ase_rsp->code != BT_BAP_ASCS_RSP_CODE_SUCCESS) {
1600 					client_ep->cp_ntf_pending = false;
1601 					client_ep->release_requested = false;
1602 				}
1603 
1604 				unicast_client_notify_ep_released(stream, ase_rsp->code,
1605 								  ase_rsp->reason);
1606 			}
1607 			break;
1608 		default:
1609 			break;
1610 		}
1611 	}
1612 
1613 	return BT_GATT_ITER_CONTINUE;
1614 }
1615 
unicast_client_ase_ntf_read_func(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * read,const void * data,uint16_t length)1616 static uint8_t unicast_client_ase_ntf_read_func(struct bt_conn *conn, uint8_t err,
1617 						struct bt_gatt_read_params *read, const void *data,
1618 						uint16_t length)
1619 {
1620 	uint16_t handle = read->single.handle;
1621 	struct net_buf_simple buf_clone;
1622 	struct unicast_client *client;
1623 	struct net_buf_simple *buf;
1624 	struct bt_bap_ep *ep;
1625 
1626 	LOG_DBG("conn %p err 0x%02x len %u", conn, err, length);
1627 
1628 	if (err) {
1629 		LOG_DBG("Failed to read ASE: %u", err);
1630 
1631 		return BT_GATT_ITER_STOP;
1632 	}
1633 
1634 	LOG_DBG("handle 0x%04x", handle);
1635 
1636 	client = &uni_cli_insts[bt_conn_index(conn)];
1637 	buf = &client->net_buf;
1638 
1639 	if (data != NULL) {
1640 		if (net_buf_simple_tailroom(buf) < length) {
1641 			LOG_DBG("Buffer full, invalid server response of size %u",
1642 				length + client->net_buf.len);
1643 			reset_att_buf(client);
1644 			atomic_clear_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY);
1645 
1646 			return BT_GATT_ITER_STOP;
1647 		}
1648 
1649 		/* store data*/
1650 		net_buf_simple_add_mem(buf, data, length);
1651 
1652 		return BT_GATT_ITER_CONTINUE;
1653 	}
1654 
1655 	memset(read, 0, sizeof(*read));
1656 
1657 	if (buf->len < sizeof(struct bt_ascs_ase_status)) {
1658 		LOG_DBG("Read response too small (%u)", buf->len);
1659 		reset_att_buf(client);
1660 		atomic_clear_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY);
1661 
1662 		return BT_GATT_ITER_STOP;
1663 	}
1664 
1665 	/* Clone the buffer so that we can reset it while still providing the data to the upper
1666 	 * layers
1667 	 */
1668 	net_buf_simple_clone(buf, &buf_clone);
1669 	reset_att_buf(client);
1670 	atomic_clear_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY);
1671 
1672 	ep = unicast_client_ep_get(conn, client->dir, handle);
1673 	if (!ep) {
1674 		LOG_DBG("Unknown %s ep for handle 0x%04X", bt_audio_dir_str(client->dir), handle);
1675 	} else {
1676 		/* Set reason in case this exits the streaming state, unless already set */
1677 		if (ep->reason == BT_HCI_ERR_SUCCESS) {
1678 			ep->reason = BT_HCI_ERR_REMOTE_USER_TERM_CONN;
1679 		}
1680 
1681 		unicast_client_ep_set_status(ep, &buf_clone);
1682 	}
1683 
1684 	return BT_GATT_ITER_STOP;
1685 }
1686 
long_ase_read(struct bt_bap_unicast_client_ep * client_ep)1687 static void long_ase_read(struct bt_bap_unicast_client_ep *client_ep)
1688 {
1689 	/* Perform long read if notification is maximum size */
1690 	struct bt_conn *conn = client_ep->ep.stream->conn;
1691 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
1692 	struct net_buf_simple *long_read_buf = &client->net_buf;
1693 	int err;
1694 
1695 	LOG_DBG("conn %p ep %p 0x%04X", conn, &client_ep->ep, client_ep->handle);
1696 
1697 	if (atomic_test_and_set_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY)) {
1698 		/* If the client is busy reading or writing something else, reschedule the
1699 		 * long read.
1700 		 */
1701 		struct bt_conn_info conn_info;
1702 
1703 		err = bt_conn_get_info(conn, &conn_info);
1704 		if (err != 0) {
1705 			LOG_DBG("Failed to get conn info, use default interval");
1706 
1707 			conn_info.le.interval = BT_GAP_INIT_CONN_INT_MIN;
1708 		}
1709 
1710 		/* Wait a connection interval to retry */
1711 		err = k_work_reschedule(&client_ep->ase_read_work,
1712 					K_USEC(BT_CONN_INTERVAL_TO_US(conn_info.le.interval)));
1713 		if (err < 0) {
1714 			LOG_DBG("Failed to reschedule ASE long read work: %d", err);
1715 		}
1716 
1717 		return;
1718 	}
1719 
1720 	client->read_params.func = unicast_client_ase_ntf_read_func;
1721 	client->read_params.handle_count = 1U;
1722 	client->read_params.single.handle = client_ep->handle;
1723 	client->read_params.single.offset = long_read_buf->len;
1724 
1725 	err = bt_gatt_read(conn, &client->read_params);
1726 	if (err != 0) {
1727 		LOG_DBG("Failed to read ASE: %d", err);
1728 		atomic_clear_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY);
1729 	}
1730 }
1731 
delayed_ase_read_handler(struct k_work * work)1732 static void delayed_ase_read_handler(struct k_work *work)
1733 {
1734 	struct k_work_delayable *dwork = k_work_delayable_from_work(work);
1735 	struct bt_bap_unicast_client_ep *client_ep =
1736 		CONTAINER_OF(dwork, struct bt_bap_unicast_client_ep, ase_read_work);
1737 
1738 	LOG_DBG("ep %p 0x%04X", &client_ep->ep, client_ep->handle);
1739 
1740 	/* Try reading again */
1741 	long_ase_read(client_ep);
1742 }
1743 
unicast_client_ep_notify(struct bt_conn * conn,struct bt_gatt_subscribe_params * params,const void * data,uint16_t length)1744 static uint8_t unicast_client_ep_notify(struct bt_conn *conn,
1745 					struct bt_gatt_subscribe_params *params, const void *data,
1746 					uint16_t length)
1747 {
1748 	struct net_buf_simple buf;
1749 	struct bt_bap_unicast_client_ep *client_ep;
1750 	const uint8_t att_ntf_header_size = 3; /* opcode (1) + handle (2) */
1751 	uint16_t max_ntf_size;
1752 	struct bt_bap_ep *ep;
1753 
1754 	client_ep = CONTAINER_OF(params, struct bt_bap_unicast_client_ep, subscribe);
1755 	ep = &client_ep->ep;
1756 
1757 	LOG_DBG("conn %p ep %p len %u", conn, ep, length);
1758 
1759 	/* Cancel any pending long reads for the endpoint */
1760 	(void)k_work_cancel_delayable(&client_ep->ase_read_work);
1761 
1762 	if (!data) {
1763 		LOG_DBG("Unsubscribed");
1764 		params->value_handle = BAP_HANDLE_UNUSED;
1765 		return BT_GATT_ITER_STOP;
1766 	}
1767 
1768 	max_ntf_size = bt_gatt_get_mtu(conn) - att_ntf_header_size;
1769 
1770 	if (length == max_ntf_size) {
1771 		struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
1772 
1773 		if (!atomic_test_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY)) {
1774 			struct net_buf_simple *long_read_buf = &client->net_buf;
1775 
1776 			/* store data*/
1777 			net_buf_simple_add_mem(long_read_buf, data, length);
1778 		}
1779 
1780 		long_ase_read(client_ep);
1781 
1782 		return BT_GATT_ITER_CONTINUE;
1783 	}
1784 
1785 	net_buf_simple_init_with_data(&buf, (void *)data, length);
1786 
1787 	if (buf.len < sizeof(struct bt_ascs_ase_status)) {
1788 		LOG_ERR("Notification too small");
1789 		return BT_GATT_ITER_STOP;
1790 	}
1791 
1792 	/* Set reason in case this exits the streaming state, unless already set */
1793 	if (ep->reason == BT_HCI_ERR_SUCCESS) {
1794 		ep->reason = BT_HCI_ERR_REMOTE_USER_TERM_CONN;
1795 	}
1796 
1797 	unicast_client_ep_set_status(ep, &buf);
1798 
1799 	return BT_GATT_ITER_CONTINUE;
1800 }
1801 
unicast_client_ep_subscribe(struct bt_conn * conn,struct bt_bap_ep * ep)1802 static int unicast_client_ep_subscribe(struct bt_conn *conn, struct bt_bap_ep *ep)
1803 {
1804 	struct bt_bap_unicast_client_ep *client_ep;
1805 	int err;
1806 
1807 	client_ep = CONTAINER_OF(ep, struct bt_bap_unicast_client_ep, ep);
1808 
1809 	LOG_DBG("ep %p handle 0x%02x", ep, client_ep->handle);
1810 
1811 	if (client_ep->subscribe.value_handle) {
1812 		return 0;
1813 	}
1814 
1815 	client_ep->subscribe.value_handle = client_ep->handle;
1816 	client_ep->subscribe.ccc_handle = BT_GATT_AUTO_DISCOVER_CCC_HANDLE;
1817 	client_ep->subscribe.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
1818 	client_ep->subscribe.disc_params = &client_ep->discover;
1819 	client_ep->subscribe.notify = unicast_client_ep_notify;
1820 	client_ep->subscribe.value = BT_GATT_CCC_NOTIFY;
1821 	atomic_set_bit(client_ep->subscribe.flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
1822 
1823 	err = bt_gatt_subscribe(conn, &client_ep->subscribe);
1824 	if (err != 0 && err != -EALREADY) {
1825 		return err;
1826 	}
1827 
1828 	return 0;
1829 }
1830 
unicast_client_cp_sub_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_subscribe_params * sub_params)1831 static void unicast_client_cp_sub_cb(struct bt_conn *conn, uint8_t err,
1832 				     struct bt_gatt_subscribe_params *sub_params)
1833 {
1834 
1835 	LOG_DBG("conn %p err %u", conn, err);
1836 
1837 	unicast_client_discover_complete(conn, err);
1838 }
1839 
unicast_client_ep_set_cp(struct bt_conn * conn,uint16_t handle)1840 static void unicast_client_ep_set_cp(struct bt_conn *conn, uint16_t handle)
1841 {
1842 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
1843 
1844 	LOG_DBG("conn %p 0x%04x", conn, handle);
1845 
1846 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
1847 	for (size_t i = 0U; i < ARRAY_SIZE(client->snks); i++) {
1848 		struct bt_bap_unicast_client_ep *client_ep = &client->snks[i];
1849 
1850 		if (client_ep->handle) {
1851 			client_ep->cp_handle = handle;
1852 		}
1853 	}
1854 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
1855 
1856 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
1857 	for (size_t i = 0U; i < ARRAY_SIZE(client->srcs); i++) {
1858 		struct bt_bap_unicast_client_ep *client_ep = &client->srcs[i];
1859 
1860 		if (client_ep->handle) {
1861 			client_ep->cp_handle = handle;
1862 		}
1863 	}
1864 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
1865 
1866 	if (!client->cp_subscribe.value_handle) {
1867 		int err;
1868 
1869 		client->cp_subscribe.value_handle = handle;
1870 		client->cp_subscribe.ccc_handle = BT_GATT_AUTO_DISCOVER_CCC_HANDLE;
1871 		client->cp_subscribe.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
1872 		client->cp_subscribe.disc_params = &client->disc_params;
1873 		client->cp_subscribe.notify = unicast_client_cp_notify;
1874 		client->cp_subscribe.value = BT_GATT_CCC_NOTIFY;
1875 		client->cp_subscribe.subscribe = unicast_client_cp_sub_cb;
1876 		atomic_set_bit(client->cp_subscribe.flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
1877 
1878 		err = bt_gatt_subscribe(conn, &client->cp_subscribe);
1879 		if (err != 0 && err != -EALREADY) {
1880 			LOG_DBG("Failed to subscribe: %d", err);
1881 
1882 			unicast_client_discover_complete(conn, err);
1883 
1884 			return;
1885 		}
1886 	} else { /* already subscribed */
1887 		unicast_client_discover_complete(conn, 0);
1888 	}
1889 }
1890 
bt_bap_unicast_client_ep_create_pdu(struct bt_conn * conn,uint8_t op)1891 struct net_buf_simple *bt_bap_unicast_client_ep_create_pdu(struct bt_conn *conn, uint8_t op)
1892 {
1893 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
1894 	struct bt_ascs_ase_cp *hdr;
1895 
1896 	if (atomic_test_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY)) {
1897 		return NULL;
1898 	}
1899 
1900 	hdr = net_buf_simple_add(&client->net_buf, sizeof(*hdr));
1901 	hdr->op = op;
1902 
1903 	return &client->net_buf;
1904 }
1905 
unicast_client_ep_config(struct bt_bap_ep * ep,struct net_buf_simple * buf,const struct bt_audio_codec_cfg * codec_cfg)1906 static int unicast_client_ep_config(struct bt_bap_ep *ep, struct net_buf_simple *buf,
1907 				    const struct bt_audio_codec_cfg *codec_cfg)
1908 {
1909 	struct bt_ascs_config *req;
1910 
1911 	LOG_DBG("ep %p buf %p codec %p", ep, buf, codec_cfg);
1912 
1913 	if (!ep) {
1914 		return -EINVAL;
1915 	}
1916 
1917 	switch (ep->status.state) {
1918 	/* Valid only if ASE_State field = 0x00 (Idle) */
1919 	case BT_BAP_EP_STATE_IDLE:
1920 		/* or 0x01 (Codec Configured) */
1921 	case BT_BAP_EP_STATE_CODEC_CONFIGURED:
1922 		/* or 0x02 (QoS Configured) */
1923 	case BT_BAP_EP_STATE_QOS_CONFIGURED:
1924 		break;
1925 	default:
1926 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
1927 		return -EINVAL;
1928 	}
1929 
1930 	LOG_DBG("id 0x%02x dir %s codec 0x%02x", ep->status.id, bt_audio_dir_str(ep->dir),
1931 		codec_cfg->id);
1932 
1933 	req = net_buf_simple_add(buf, sizeof(*req));
1934 	req->ase = ep->status.id;
1935 	req->latency = 0x02; /* TODO: Select target latency based on additional input? */
1936 	req->phy = 0x02;     /* TODO: Select target PHY based on additional input? */
1937 	req->codec.id = codec_cfg->id;
1938 	req->codec.cid = codec_cfg->cid;
1939 	req->codec.vid = codec_cfg->vid;
1940 
1941 	req->cc_len = codec_cfg->data_len;
1942 	net_buf_simple_add_mem(buf, codec_cfg->data, codec_cfg->data_len);
1943 
1944 	return 0;
1945 }
1946 
bt_bap_unicast_client_ep_qos(struct bt_bap_ep * ep,struct net_buf_simple * buf,struct bt_bap_qos_cfg * qos)1947 int bt_bap_unicast_client_ep_qos(struct bt_bap_ep *ep, struct net_buf_simple *buf,
1948 				 struct bt_bap_qos_cfg *qos)
1949 {
1950 	struct bt_ascs_qos *req;
1951 	struct bt_conn_iso *conn_iso;
1952 
1953 	LOG_DBG("ep %p buf %p qos %p", ep, buf, qos);
1954 
1955 	if (!ep) {
1956 		return -EINVAL;
1957 	}
1958 
1959 	switch (ep->status.state) {
1960 	/* Valid only if ASE_State field = 0x01 (Codec Configured) */
1961 	case BT_BAP_EP_STATE_CODEC_CONFIGURED:
1962 		/* or 0x02 (QoS Configured) */
1963 	case BT_BAP_EP_STATE_QOS_CONFIGURED:
1964 		break;
1965 	default:
1966 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
1967 		return -EINVAL;
1968 	}
1969 
1970 	conn_iso = &ep->iso->chan.iso->iso;
1971 
1972 	LOG_DBG("id 0x%02x cig 0x%02x cis 0x%02x interval %u framing 0x%02x "
1973 		"phy 0x%02x sdu %u rtn %u latency %u pd %u",
1974 		ep->status.id, conn_iso->cig_id, conn_iso->cis_id, qos->interval, qos->framing,
1975 		qos->phy, qos->sdu, qos->rtn, qos->latency, qos->pd);
1976 
1977 	req = net_buf_simple_add(buf, sizeof(*req));
1978 	req->ase = ep->status.id;
1979 	/* TODO: don't hardcode CIG and CIS, they should come from ISO */
1980 	req->cig = conn_iso->cig_id;
1981 	req->cis = conn_iso->cis_id;
1982 	sys_put_le24(qos->interval, req->interval);
1983 	req->framing = qos->framing;
1984 	req->phy = qos->phy;
1985 	req->sdu = qos->sdu;
1986 	req->rtn = qos->rtn;
1987 	req->latency = sys_cpu_to_le16(qos->latency);
1988 	sys_put_le24(qos->pd, req->pd);
1989 
1990 	return 0;
1991 }
1992 
unicast_client_ep_enable(struct bt_bap_ep * ep,struct net_buf_simple * buf,const uint8_t meta[],size_t meta_len)1993 static int unicast_client_ep_enable(struct bt_bap_ep *ep, struct net_buf_simple *buf,
1994 				    const uint8_t meta[], size_t meta_len)
1995 {
1996 	struct bt_ascs_metadata *req;
1997 
1998 	LOG_DBG("ep %p buf %p meta_len %zu", ep, buf, meta_len);
1999 
2000 	if (!ep) {
2001 		return -EINVAL;
2002 	}
2003 
2004 	if (ep->status.state != BT_BAP_EP_STATE_QOS_CONFIGURED) {
2005 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
2006 		return -EINVAL;
2007 	}
2008 
2009 	LOG_DBG("id 0x%02x", ep->status.id);
2010 
2011 	req = net_buf_simple_add(buf, sizeof(*req));
2012 	req->ase = ep->status.id;
2013 
2014 	req->len = meta_len;
2015 	net_buf_simple_add_mem(buf, meta, meta_len);
2016 
2017 	return 0;
2018 }
2019 
unicast_client_ep_metadata(struct bt_bap_ep * ep,struct net_buf_simple * buf,const uint8_t meta[],size_t meta_len)2020 static int unicast_client_ep_metadata(struct bt_bap_ep *ep, struct net_buf_simple *buf,
2021 				      const uint8_t meta[], size_t meta_len)
2022 {
2023 	struct bt_ascs_metadata *req;
2024 
2025 	LOG_DBG("ep %p buf %p meta_len %zu", ep, buf, meta_len);
2026 
2027 	if (!ep) {
2028 		return -EINVAL;
2029 	}
2030 
2031 	switch (ep->status.state) {
2032 	/* Valid for an ASE only if ASE_State field = 0x03 (Enabling) */
2033 	case BT_BAP_EP_STATE_ENABLING:
2034 	/* or 0x04 (Streaming) */
2035 	case BT_BAP_EP_STATE_STREAMING:
2036 		break;
2037 	default:
2038 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
2039 		return -EINVAL;
2040 	}
2041 
2042 	LOG_DBG("id 0x%02x", ep->status.id);
2043 
2044 	req = net_buf_simple_add(buf, sizeof(*req));
2045 	req->ase = ep->status.id;
2046 
2047 	req->len = meta_len;
2048 	net_buf_simple_add_mem(buf, meta, meta_len);
2049 
2050 	return 0;
2051 }
2052 
unicast_client_ep_start(struct bt_bap_ep * ep,struct net_buf_simple * buf)2053 static int unicast_client_ep_start(struct bt_bap_ep *ep, struct net_buf_simple *buf)
2054 {
2055 	LOG_DBG("ep %p buf %p", ep, buf);
2056 
2057 	if (!ep) {
2058 		return -EINVAL;
2059 	}
2060 
2061 	if (ep->status.state != BT_BAP_EP_STATE_ENABLING &&
2062 	    ep->status.state != BT_BAP_EP_STATE_DISABLING) {
2063 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
2064 		return -EINVAL;
2065 	}
2066 
2067 	LOG_DBG("id 0x%02x", ep->status.id);
2068 
2069 	net_buf_simple_add_u8(buf, ep->status.id);
2070 
2071 	return 0;
2072 }
2073 
unicast_client_ep_disable(struct bt_bap_ep * ep,struct net_buf_simple * buf)2074 static int unicast_client_ep_disable(struct bt_bap_ep *ep, struct net_buf_simple *buf)
2075 {
2076 	LOG_DBG("ep %p buf %p", ep, buf);
2077 
2078 	if (!ep) {
2079 		return -EINVAL;
2080 	}
2081 
2082 	switch (ep->status.state) {
2083 	/* Valid only if ASE_State field = 0x03 (Enabling) */
2084 	case BT_BAP_EP_STATE_ENABLING:
2085 		/* or 0x04 (Streaming) */
2086 	case BT_BAP_EP_STATE_STREAMING:
2087 		break;
2088 	default:
2089 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
2090 		return -EINVAL;
2091 	}
2092 
2093 	LOG_DBG("id 0x%02x", ep->status.id);
2094 
2095 	net_buf_simple_add_u8(buf, ep->status.id);
2096 
2097 	return 0;
2098 }
2099 
unicast_client_ep_stop(struct bt_bap_ep * ep,struct net_buf_simple * buf)2100 static int unicast_client_ep_stop(struct bt_bap_ep *ep, struct net_buf_simple *buf)
2101 {
2102 	LOG_DBG("ep %p buf %p", ep, buf);
2103 
2104 	if (!ep) {
2105 		return -EINVAL;
2106 	}
2107 
2108 	/* Valid only if ASE_State field value = 0x05 (Disabling). */
2109 	if (ep->status.state != BT_BAP_EP_STATE_DISABLING) {
2110 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
2111 		return -EINVAL;
2112 	}
2113 
2114 	LOG_DBG("id 0x%02x", ep->status.id);
2115 
2116 	net_buf_simple_add_u8(buf, ep->status.id);
2117 
2118 	return 0;
2119 }
2120 
unicast_client_ep_release(struct bt_bap_ep * ep,struct net_buf_simple * buf)2121 static int unicast_client_ep_release(struct bt_bap_ep *ep, struct net_buf_simple *buf)
2122 {
2123 	LOG_DBG("ep %p buf %p", ep, buf);
2124 
2125 	if (!ep) {
2126 		return -EINVAL;
2127 	}
2128 
2129 	switch (ep->status.state) {
2130 	/* Valid only if ASE_State field = 0x01 (Codec Configured) */
2131 	case BT_BAP_EP_STATE_CODEC_CONFIGURED:
2132 		/* or 0x02 (QoS Configured) */
2133 	case BT_BAP_EP_STATE_QOS_CONFIGURED:
2134 		/* or 0x03 (Enabling) */
2135 	case BT_BAP_EP_STATE_ENABLING:
2136 		/* or 0x04 (Streaming) */
2137 	case BT_BAP_EP_STATE_STREAMING:
2138 		/* or 0x05 (Disabling) */
2139 	case BT_BAP_EP_STATE_DISABLING:
2140 		break;
2141 	default:
2142 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
2143 		return -EINVAL;
2144 	}
2145 
2146 	LOG_DBG("id 0x%02x", ep->status.id);
2147 
2148 	net_buf_simple_add_u8(buf, ep->status.id);
2149 
2150 	return 0;
2151 }
2152 
gatt_write_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_write_params * params)2153 static void gatt_write_cb(struct bt_conn *conn, uint8_t err, struct bt_gatt_write_params *params)
2154 {
2155 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
2156 
2157 	LOG_DBG("conn %p err %u", conn, err);
2158 
2159 	memset(params, 0, sizeof(*params));
2160 	reset_att_buf(client);
2161 	atomic_clear_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY);
2162 
2163 	/* TBD: Should we do anything in case of error here? */
2164 }
2165 
bt_bap_unicast_client_ep_send(struct bt_conn * conn,struct bt_bap_ep * ep,struct net_buf_simple * buf)2166 int bt_bap_unicast_client_ep_send(struct bt_conn *conn, struct bt_bap_ep *ep,
2167 				  struct net_buf_simple *buf)
2168 {
2169 	const uint8_t att_write_header_size = 3; /* opcode (1) + handle (2) */
2170 	const uint16_t max_write_size = bt_gatt_get_mtu(conn) - att_write_header_size;
2171 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
2172 	struct bt_bap_unicast_client_ep *client_ep =
2173 		CONTAINER_OF(ep, struct bt_bap_unicast_client_ep, ep);
2174 	int err;
2175 
2176 	LOG_DBG("conn %p ep %p buf %p len %u", conn, ep, buf, buf->len);
2177 
2178 	if (buf->len > max_write_size) {
2179 		if (atomic_test_and_set_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY)) {
2180 			LOG_DBG("Client connection is busy");
2181 			return -EBUSY;
2182 		}
2183 
2184 		client->write_params.func = gatt_write_cb;
2185 		client->write_params.handle = client_ep->cp_handle;
2186 		client->write_params.offset = 0U;
2187 		client->write_params.data = buf->data;
2188 		client->write_params.length = buf->len;
2189 #if defined(CONFIG_BT_EATT)
2190 		client->write_params.chan_opt = BT_ATT_CHAN_OPT_NONE;
2191 #endif /* CONFIG_BT_EATT */
2192 
2193 		err = bt_gatt_write(conn, &client->write_params);
2194 		if (err != 0) {
2195 			LOG_DBG("bt_gatt_write failed: %d", err);
2196 			atomic_clear_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY);
2197 		}
2198 	} else {
2199 		err = bt_gatt_write_without_response(conn, client_ep->cp_handle, buf->data,
2200 						     buf->len, false);
2201 		if (err != 0) {
2202 			LOG_DBG("bt_gatt_write_without_response failed: %d", err);
2203 		}
2204 
2205 		/* No callback for writing without response, so reset the buffer here */
2206 		reset_att_buf(client);
2207 	}
2208 
2209 	if (err == 0) {
2210 		client_ep->cp_ntf_pending = true;
2211 	}
2212 
2213 	return err;
2214 }
2215 
unicast_client_reset(struct bt_bap_ep * ep,uint8_t reason)2216 static void unicast_client_reset(struct bt_bap_ep *ep, uint8_t reason)
2217 {
2218 	struct bt_bap_unicast_client_ep *client_ep =
2219 		CONTAINER_OF(ep, struct bt_bap_unicast_client_ep, ep);
2220 
2221 	LOG_DBG("ep %p", ep);
2222 	ep->reason = reason;
2223 
2224 	/* Pretend we received an idle state notification from the server to trigger all cleanup */
2225 	unicast_client_ep_set_local_idle_state(ep);
2226 
2227 	if (ep->iso != NULL && ep->iso->chan.state == BT_ISO_STATE_DISCONNECTING) {
2228 		/* Wait for ISO disconnected event */
2229 		return;
2230 	}
2231 
2232 	(void)k_work_cancel_delayable(&client_ep->ase_read_work);
2233 	(void)memset(ep, 0, sizeof(*ep));
2234 
2235 	client_ep->cp_handle = BAP_HANDLE_UNUSED;
2236 	client_ep->handle = BAP_HANDLE_UNUSED;
2237 	(void)memset(&client_ep->discover, 0, sizeof(client_ep->discover));
2238 	client_ep->release_requested = false;
2239 	client_ep->cp_ntf_pending = false;
2240 	/* Need to keep the subscribe params intact for the callback */
2241 }
2242 
unicast_client_ep_reset(struct bt_conn * conn,uint8_t reason)2243 static void unicast_client_ep_reset(struct bt_conn *conn, uint8_t reason)
2244 {
2245 	struct unicast_client *client;
2246 	uint8_t index;
2247 
2248 	LOG_DBG("conn %p", conn);
2249 
2250 	index = bt_conn_index(conn);
2251 
2252 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
2253 	for (size_t i = 0U; i < ARRAY_SIZE(uni_cli_insts[index].snks); i++) {
2254 		struct bt_bap_ep *ep = &uni_cli_insts[index].snks[i].ep;
2255 
2256 		unicast_client_reset(ep, reason);
2257 	}
2258 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
2259 
2260 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
2261 	for (size_t i = 0U; i < ARRAY_SIZE(uni_cli_insts[index].srcs); i++) {
2262 		struct bt_bap_ep *ep = &uni_cli_insts[index].srcs[i].ep;
2263 
2264 		unicast_client_reset(ep, reason);
2265 	}
2266 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
2267 
2268 	client = &uni_cli_insts[index];
2269 	atomic_clear_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY);
2270 	client->dir = 0U;
2271 	reset_att_buf(client);
2272 }
2273 
bt_bap_qos_cfg_to_cig_param(struct bt_iso_cig_param * cig_param,const struct bt_bap_unicast_group * group)2274 static void bt_bap_qos_cfg_to_cig_param(struct bt_iso_cig_param *cig_param,
2275 					    const struct bt_bap_unicast_group *group)
2276 {
2277 	cig_param->framing = group->cig_param.framing;
2278 	cig_param->c_to_p_interval = group->cig_param.c_to_p_interval;
2279 	cig_param->p_to_c_interval = group->cig_param.p_to_c_interval;
2280 	cig_param->c_to_p_latency = group->cig_param.c_to_p_latency;
2281 	cig_param->p_to_c_latency = group->cig_param.p_to_c_latency;
2282 	cig_param->packing = group->cig_param.packing;
2283 	cig_param->sca = BT_GAP_SCA_UNKNOWN;
2284 
2285 	IF_ENABLED(CONFIG_BT_ISO_TEST_PARAMS, ({
2286 		cig_param->c_to_p_ft = group->cig_param.c_to_p_ft;
2287 		cig_param->p_to_c_ft = group->cig_param.p_to_c_ft;
2288 		cig_param->iso_interval = group->cig_param.iso_interval;
2289 	}));
2290 
2291 	/* In the case that we only setup a single direction, we still need
2292 	 * (as per section 7.8.97 LE Set CIG Parameters command) to set the interval and latency on
2293 	 * both sides. The value shall be ignored, but the value may not always be ignored correctly
2294 	 * by all controllers, so we always set it here.
2295 	 * If it is at this point unset, then we set the opposing direction to the same value.
2296 	 */
2297 	if (cig_param->c_to_p_interval == 0U) {
2298 		cig_param->c_to_p_interval = cig_param->p_to_c_interval;
2299 	} else if (cig_param->p_to_c_interval == 0U) {
2300 		cig_param->p_to_c_interval = cig_param->c_to_p_interval;
2301 	}
2302 
2303 	if (cig_param->c_to_p_latency == 0U) {
2304 		cig_param->c_to_p_latency = cig_param->p_to_c_latency;
2305 	} else if (cig_param->p_to_c_latency == 0U) {
2306 		cig_param->p_to_c_latency = cig_param->c_to_p_latency;
2307 	}
2308 }
2309 
unicast_group_get_cis_count(const struct bt_bap_unicast_group * unicast_group)2310 static uint8_t unicast_group_get_cis_count(const struct bt_bap_unicast_group *unicast_group)
2311 {
2312 	uint8_t cis_count = 0U;
2313 
2314 	for (size_t i = 0U; i < ARRAY_SIZE(unicast_group->cis); i++) {
2315 		if (unicast_group->cis[i] == NULL) {
2316 			/* A NULL CIS acts as a NULL terminator */
2317 			break;
2318 		}
2319 
2320 		cis_count++;
2321 	}
2322 
2323 	return cis_count;
2324 }
2325 
bt_audio_cig_create(struct bt_bap_unicast_group * group)2326 static int bt_audio_cig_create(struct bt_bap_unicast_group *group)
2327 {
2328 	struct bt_iso_cig_param param = {0};
2329 	int err;
2330 
2331 	LOG_DBG("group %p", group);
2332 
2333 	param.num_cis = unicast_group_get_cis_count(group);
2334 	param.cis_channels = group->cis;
2335 	bt_bap_qos_cfg_to_cig_param(&param, group);
2336 
2337 	err = bt_iso_cig_create(&param, &group->cig);
2338 	if (err != 0) {
2339 		LOG_ERR("bt_iso_cig_create failed: %d", err);
2340 		return err;
2341 	}
2342 
2343 	return 0;
2344 }
2345 
bt_audio_cig_reconfigure(struct bt_bap_unicast_group * group)2346 static int bt_audio_cig_reconfigure(struct bt_bap_unicast_group *group)
2347 {
2348 	struct bt_iso_cig_param param;
2349 	uint8_t cis_count;
2350 	int err;
2351 
2352 	LOG_DBG("group %p ", group);
2353 
2354 	cis_count = 0U;
2355 	for (size_t i = 0U; i < ARRAY_SIZE(group->cis); i++) {
2356 		if (group->cis[i] == NULL) {
2357 			/* A NULL CIS acts as a NULL terminator */
2358 			break;
2359 		}
2360 
2361 		cis_count++;
2362 	}
2363 
2364 	param.num_cis = cis_count;
2365 	param.cis_channels = group->cis;
2366 	bt_bap_qos_cfg_to_cig_param(&param, group);
2367 
2368 	err = bt_iso_cig_reconfigure(group->cig, &param);
2369 	if (err != 0) {
2370 		LOG_ERR("bt_iso_cig_create failed: %d", err);
2371 		return err;
2372 	}
2373 
2374 	return 0;
2375 }
2376 
audio_stream_qos_cleanup(const struct bt_conn * conn,struct bt_bap_unicast_group * group)2377 static void audio_stream_qos_cleanup(const struct bt_conn *conn,
2378 				     struct bt_bap_unicast_group *group)
2379 {
2380 	struct bt_bap_stream *stream;
2381 
2382 	SYS_SLIST_FOR_EACH_CONTAINER(&group->streams, stream, _node) {
2383 		if (stream->conn != conn) {
2384 			/* Channel not part of this ACL, skip */
2385 			continue;
2386 		}
2387 
2388 		if (stream->ep == NULL) {
2389 			/* Stream did not have a endpoint configured yet */
2390 			continue;
2391 		}
2392 
2393 		bt_bap_iso_unbind_ep(stream->ep->iso, stream->ep);
2394 	}
2395 }
2396 
unicast_client_cig_terminate(struct bt_bap_unicast_group * group)2397 static int unicast_client_cig_terminate(struct bt_bap_unicast_group *group)
2398 {
2399 	LOG_DBG("group %p", group);
2400 
2401 	return bt_iso_cig_terminate(group->cig);
2402 }
2403 
unicast_group_add_iso(struct bt_bap_unicast_group * group,struct bt_bap_iso * iso)2404 static int unicast_group_add_iso(struct bt_bap_unicast_group *group, struct bt_bap_iso *iso)
2405 {
2406 	struct bt_iso_chan **chan_slot = NULL;
2407 
2408 	__ASSERT_NO_MSG(group != NULL);
2409 	__ASSERT_NO_MSG(iso != NULL);
2410 
2411 	/* Append iso channel to the group->cis array */
2412 	for (size_t i = 0U; i < ARRAY_SIZE(group->cis); i++) {
2413 		/* Return if already there */
2414 		if (group->cis[i] == &iso->chan) {
2415 			return 0;
2416 		}
2417 
2418 		if (chan_slot == NULL && group->cis[i] == NULL) {
2419 			chan_slot = &group->cis[i];
2420 		}
2421 	}
2422 
2423 	if (chan_slot == NULL) {
2424 		return -ENOMEM;
2425 	}
2426 
2427 	*chan_slot = &iso->chan;
2428 
2429 	return 0;
2430 }
2431 
unicast_group_del_iso(struct bt_bap_unicast_group * group,struct bt_bap_iso * iso)2432 static void unicast_group_del_iso(struct bt_bap_unicast_group *group, struct bt_bap_iso *iso)
2433 {
2434 	struct bt_bap_stream *stream;
2435 
2436 	__ASSERT_NO_MSG(group != NULL);
2437 	__ASSERT_NO_MSG(iso != NULL);
2438 
2439 	SYS_SLIST_FOR_EACH_CONTAINER(&group->streams, stream, _node) {
2440 		if (stream->ep->iso == iso) {
2441 			/* still in use by some other stream */
2442 			return;
2443 		}
2444 	}
2445 
2446 	for (size_t i = 0U; i < ARRAY_SIZE(group->cis); i++) {
2447 		if (group->cis[i] == &iso->chan) {
2448 			group->cis[i] = NULL;
2449 			return;
2450 		}
2451 	}
2452 }
2453 
unicast_client_qos_cfg_to_iso_qos(struct bt_bap_iso * iso,const struct bt_bap_qos_cfg * qos,enum bt_audio_dir dir)2454 static void unicast_client_qos_cfg_to_iso_qos(struct bt_bap_iso *iso,
2455 					      const struct bt_bap_qos_cfg *qos,
2456 					      enum bt_audio_dir dir)
2457 {
2458 	struct bt_iso_chan_io_qos *io_qos;
2459 	struct bt_iso_chan_io_qos *other_io_qos;
2460 
2461 	if (dir == BT_AUDIO_DIR_SINK) {
2462 		/* If the endpoint is a sink, then we need to
2463 		 * configure our TX parameters
2464 		 */
2465 		io_qos = iso->chan.qos->tx;
2466 		if (bt_bap_iso_get_ep(true, iso, BT_AUDIO_DIR_SOURCE) == NULL) {
2467 			other_io_qos = iso->chan.qos->rx;
2468 		} else {
2469 			other_io_qos = NULL;
2470 		}
2471 	} else {
2472 		/* If the endpoint is a source, then we need to
2473 		 * configure our RX parameters
2474 		 */
2475 		io_qos = iso->chan.qos->rx;
2476 		if (bt_bap_iso_get_ep(true, iso, BT_AUDIO_DIR_SINK) == NULL) {
2477 			other_io_qos = iso->chan.qos->tx;
2478 		} else {
2479 			other_io_qos = NULL;
2480 		}
2481 	}
2482 
2483 	bt_bap_qos_cfg_to_iso_qos(io_qos, qos);
2484 #if defined(CONFIG_BT_ISO_TEST_PARAMS)
2485 	iso->chan.qos->num_subevents = qos->num_subevents;
2486 #endif /* CONFIG_BT_ISO_TEST_PARAMS */
2487 
2488 	if (other_io_qos != NULL) {
2489 		/* If the opposing ASE of the CIS is not yet configured, we
2490 		 * still need to set the PHY value when creating the CIG.
2491 		 */
2492 		other_io_qos->phy = io_qos->phy;
2493 	}
2494 }
2495 
unicast_group_set_iso_stream_param(struct bt_bap_unicast_group * group,struct bt_bap_iso * iso,struct bt_bap_qos_cfg * qos,enum bt_audio_dir dir)2496 static void unicast_group_set_iso_stream_param(struct bt_bap_unicast_group *group,
2497 					       struct bt_bap_iso *iso,
2498 					       struct bt_bap_qos_cfg *qos,
2499 					       enum bt_audio_dir dir)
2500 {
2501 	/* Store the stream Codec QoS in the bap_iso */
2502 	unicast_client_qos_cfg_to_iso_qos(iso, qos, dir);
2503 
2504 	/* Store the group Codec QoS in the group - This assume thats the parameters have been
2505 	 * verified first
2506 	 */
2507 	group->cig_param.framing = qos->framing;
2508 	if (dir == BT_AUDIO_DIR_SOURCE) {
2509 		group->cig_param.p_to_c_interval = qos->interval;
2510 		group->cig_param.p_to_c_latency = qos->latency;
2511 	} else {
2512 		group->cig_param.c_to_p_interval = qos->interval;
2513 		group->cig_param.c_to_p_latency = qos->latency;
2514 	}
2515 }
2516 
unicast_group_add_stream(struct bt_bap_unicast_group * group,struct bt_bap_unicast_group_stream_param * param,struct bt_bap_iso * iso,enum bt_audio_dir dir)2517 static void unicast_group_add_stream(struct bt_bap_unicast_group *group,
2518 				     struct bt_bap_unicast_group_stream_param *param,
2519 				     struct bt_bap_iso *iso, enum bt_audio_dir dir)
2520 {
2521 	struct bt_bap_stream *stream = param->stream;
2522 	struct bt_bap_qos_cfg *qos = param->qos;
2523 
2524 	LOG_DBG("group %p stream %p qos %p iso %p dir %u", group, stream, qos, iso, dir);
2525 
2526 	__ASSERT_NO_MSG(stream->ep == NULL || (stream->ep != NULL && stream->ep->iso == NULL));
2527 
2528 	stream->qos = qos;
2529 	stream->group = group;
2530 
2531 	/* iso initialized already */
2532 	bt_bap_iso_bind_stream(iso, stream, dir);
2533 	if (stream->ep != NULL) {
2534 		bt_bap_iso_bind_ep(iso, stream->ep);
2535 	}
2536 
2537 	unicast_group_set_iso_stream_param(group, iso, qos, dir);
2538 
2539 	sys_slist_append(&group->streams, &stream->_node);
2540 }
2541 
unicast_group_add_stream_pair(struct bt_bap_unicast_group * group,struct bt_bap_unicast_group_stream_pair_param * param)2542 static int unicast_group_add_stream_pair(struct bt_bap_unicast_group *group,
2543 					 struct bt_bap_unicast_group_stream_pair_param *param)
2544 {
2545 	struct bt_bap_iso *iso;
2546 	int err;
2547 
2548 	__ASSERT_NO_MSG(group != NULL);
2549 	__ASSERT_NO_MSG(param != NULL);
2550 	__ASSERT_NO_MSG(param->rx_param != NULL || param->tx_param != NULL);
2551 
2552 	iso = bt_bap_unicast_client_new_audio_iso();
2553 	if (iso == NULL) {
2554 		return -ENOMEM;
2555 	}
2556 
2557 	err = unicast_group_add_iso(group, iso);
2558 	if (err < 0) {
2559 		bt_bap_iso_unref(iso);
2560 		return err;
2561 	}
2562 
2563 	if (param->rx_param != NULL) {
2564 		unicast_group_add_stream(group, param->rx_param, iso, BT_AUDIO_DIR_SOURCE);
2565 	}
2566 
2567 	if (param->tx_param != NULL) {
2568 		unicast_group_add_stream(group, param->tx_param, iso, BT_AUDIO_DIR_SINK);
2569 	}
2570 
2571 	bt_bap_iso_unref(iso);
2572 
2573 	return 0;
2574 }
2575 
unicast_group_del_stream(struct bt_bap_unicast_group * group,struct bt_bap_stream * stream,enum bt_audio_dir dir)2576 static void unicast_group_del_stream(struct bt_bap_unicast_group *group,
2577 				     struct bt_bap_stream *stream, enum bt_audio_dir dir)
2578 {
2579 	__ASSERT_NO_MSG(group != NULL);
2580 	__ASSERT_NO_MSG(stream != NULL);
2581 
2582 	if (sys_slist_find_and_remove(&group->streams, &stream->_node)) {
2583 		struct bt_bap_ep *ep = stream->ep;
2584 
2585 		if (stream->bap_iso != NULL) {
2586 			bt_bap_iso_unbind_stream(stream->bap_iso, stream, dir);
2587 		}
2588 
2589 		if (ep != NULL && ep->iso != NULL) {
2590 			unicast_group_del_iso(group, ep->iso);
2591 
2592 			bt_bap_iso_unbind_ep(ep->iso, ep);
2593 		}
2594 
2595 		stream->group = NULL;
2596 	}
2597 }
2598 
unicast_group_del_stream_pair(struct bt_bap_unicast_group * group,struct bt_bap_unicast_group_stream_pair_param * param)2599 static void unicast_group_del_stream_pair(struct bt_bap_unicast_group *group,
2600 					  struct bt_bap_unicast_group_stream_pair_param *param)
2601 {
2602 	__ASSERT_NO_MSG(group != NULL);
2603 	__ASSERT_NO_MSG(param != NULL);
2604 	__ASSERT_NO_MSG(param->rx_param != NULL || param->tx_param != NULL);
2605 
2606 	if (param->rx_param != NULL) {
2607 		__ASSERT_NO_MSG(param->rx_param->stream);
2608 		unicast_group_del_stream(group, param->rx_param->stream, BT_AUDIO_DIR_SOURCE);
2609 	}
2610 
2611 	if (param->tx_param != NULL) {
2612 		__ASSERT_NO_MSG(param->tx_param->stream);
2613 		unicast_group_del_stream(group, param->tx_param->stream, BT_AUDIO_DIR_SINK);
2614 	}
2615 }
2616 
unicast_group_alloc(void)2617 static struct bt_bap_unicast_group *unicast_group_alloc(void)
2618 {
2619 	struct bt_bap_unicast_group *group = NULL;
2620 
2621 	for (size_t i = 0U; i < ARRAY_SIZE(unicast_groups); i++) {
2622 		if (!unicast_groups[i].allocated) {
2623 			group = &unicast_groups[i];
2624 
2625 			(void)memset(group, 0, sizeof(*group));
2626 
2627 			group->allocated = true;
2628 			group->index = i;
2629 
2630 			break;
2631 		}
2632 	}
2633 
2634 	return group;
2635 }
2636 
unicast_group_free(struct bt_bap_unicast_group * group)2637 static void unicast_group_free(struct bt_bap_unicast_group *group)
2638 {
2639 	struct bt_bap_stream *stream, *next;
2640 
2641 	__ASSERT_NO_MSG(group != NULL);
2642 
2643 	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&group->streams, stream, next, _node) {
2644 		struct bt_bap_iso *bap_iso = stream->bap_iso;
2645 		struct bt_bap_ep *ep = stream->ep;
2646 
2647 		stream->group = NULL;
2648 		if (bap_iso != NULL) {
2649 			if (bap_iso->rx.stream == stream) {
2650 				bt_bap_iso_unbind_stream(stream->bap_iso, stream,
2651 							 BT_AUDIO_DIR_SOURCE);
2652 			} else if (bap_iso->tx.stream == stream) {
2653 				bt_bap_iso_unbind_stream(stream->bap_iso, stream,
2654 							 BT_AUDIO_DIR_SINK);
2655 			} else {
2656 				__ASSERT_PRINT("stream %p has invalid bap_iso %p", stream, bap_iso);
2657 			}
2658 		}
2659 
2660 		if (ep != NULL && ep->iso != NULL) {
2661 			bt_bap_iso_unbind_ep(ep->iso, ep);
2662 		}
2663 
2664 		sys_slist_remove(&group->streams, NULL, &stream->_node);
2665 	}
2666 
2667 	group->allocated = false;
2668 }
2669 
stream_param_check(const struct bt_bap_unicast_group_stream_param * param)2670 static int stream_param_check(const struct bt_bap_unicast_group_stream_param *param)
2671 {
2672 	CHECKIF(param->stream == NULL)
2673 	{
2674 		LOG_DBG("param->stream is NULL");
2675 		return -EINVAL;
2676 	}
2677 
2678 	CHECKIF(param->qos == NULL)
2679 	{
2680 		LOG_DBG("param->qos is NULL");
2681 		return -EINVAL;
2682 	}
2683 
2684 	if (param->stream != NULL && param->stream->group != NULL) {
2685 		LOG_DBG("stream %p already part of group %p", param->stream, param->stream->group);
2686 		return -EALREADY;
2687 	}
2688 
2689 	CHECKIF(bt_audio_verify_qos(param->qos) != BT_BAP_ASCS_REASON_NONE)
2690 	{
2691 		LOG_DBG("Invalid QoS");
2692 		return -EINVAL;
2693 	}
2694 
2695 	return 0;
2696 }
2697 
stream_pair_param_check(const struct bt_bap_unicast_group_stream_pair_param * param)2698 static int stream_pair_param_check(const struct bt_bap_unicast_group_stream_pair_param *param)
2699 {
2700 	int err;
2701 
2702 	CHECKIF(param->rx_param == NULL && param->tx_param == NULL)
2703 	{
2704 		LOG_DBG("Invalid stream parameters");
2705 		return -EINVAL;
2706 	}
2707 
2708 	if (param->rx_param != NULL) {
2709 		err = stream_param_check(param->rx_param);
2710 		if (err < 0) {
2711 			return err;
2712 		}
2713 	}
2714 
2715 	if (param->tx_param != NULL) {
2716 		err = stream_param_check(param->tx_param);
2717 		if (err < 0) {
2718 			return err;
2719 		}
2720 	}
2721 
2722 	return 0;
2723 }
2724 
2725 /** Validates that the stream parameter does not contain invalid values  */
valid_unicast_group_stream_param(const struct bt_bap_unicast_group * unicast_group,const struct bt_bap_unicast_group_stream_param * param,struct bt_bap_unicast_group_cig_param * cig_param,enum bt_audio_dir dir)2726 static bool valid_unicast_group_stream_param(const struct bt_bap_unicast_group *unicast_group,
2727 					     const struct bt_bap_unicast_group_stream_param *param,
2728 					     struct bt_bap_unicast_group_cig_param *cig_param,
2729 					     enum bt_audio_dir dir)
2730 {
2731 	const struct bt_bap_qos_cfg *qos;
2732 
2733 	CHECKIF(param->stream == NULL) {
2734 		LOG_DBG("param->stream is NULL");
2735 		return -EINVAL;
2736 	}
2737 
2738 	CHECKIF(param->qos == NULL) {
2739 		LOG_DBG("param->qos is NULL");
2740 		return -EINVAL;
2741 	}
2742 
2743 	if (param->stream != NULL && param->stream->group != NULL) {
2744 		if (unicast_group != NULL && param->stream->group != unicast_group) {
2745 			LOG_DBG("stream %p not part of group %p (%p)", param->stream, unicast_group,
2746 				param->stream->group);
2747 		} else {
2748 			LOG_DBG("stream %p already part of group %p", param->stream,
2749 				param->stream->group);
2750 		}
2751 		return -EALREADY;
2752 	}
2753 
2754 	CHECKIF(bt_audio_verify_qos(param->qos) != BT_BAP_ASCS_REASON_NONE) {
2755 		LOG_DBG("Invalid QoS");
2756 		return -EINVAL;
2757 	}
2758 
2759 	qos = param->qos;
2760 
2761 	/* If unset we set the interval else we verify that all streams use the same interval and
2762 	 * latency in the same direction, as that is required when creating a CIG
2763 	 */
2764 	if (dir == BT_AUDIO_DIR_SINK) {
2765 		if (cig_param->c_to_p_interval == 0) {
2766 			cig_param->c_to_p_interval = qos->interval;
2767 		} else if (cig_param->c_to_p_interval != qos->interval) {
2768 			return false;
2769 		}
2770 
2771 		if (cig_param->c_to_p_latency == 0) {
2772 			cig_param->c_to_p_latency = qos->latency;
2773 		} else if (cig_param->c_to_p_latency != qos->latency) {
2774 			return false;
2775 		}
2776 	} else {
2777 		if (cig_param->p_to_c_interval == 0) {
2778 			cig_param->p_to_c_interval = qos->interval;
2779 		} else if (cig_param->p_to_c_interval != qos->interval) {
2780 			return false;
2781 		}
2782 
2783 		if (cig_param->p_to_c_latency == 0) {
2784 			cig_param->p_to_c_latency = qos->latency;
2785 		} else if (cig_param->p_to_c_latency != qos->latency) {
2786 			return false;
2787 		}
2788 	}
2789 
2790 	if (cig_param->framing == 0) {
2791 		if (qos->framing == BT_BAP_QOS_CFG_FRAMING_UNFRAMED) {
2792 			cig_param->framing = BT_ISO_FRAMING_UNFRAMED;
2793 		} else if (qos->framing == BT_BAP_QOS_CFG_FRAMING_FRAMED) {
2794 			cig_param->framing = BT_ISO_FRAMING_FRAMED;
2795 		}
2796 	} else if ((qos->framing == BT_BAP_QOS_CFG_FRAMING_UNFRAMED &&
2797 		    cig_param->framing != BT_ISO_FRAMING_UNFRAMED) ||
2798 		   (qos->framing == BT_BAP_QOS_CFG_FRAMING_FRAMED &&
2799 		    cig_param->framing != BT_ISO_FRAMING_FRAMED)) {
2800 		return false;
2801 	}
2802 
2803 	return true;
2804 }
2805 
2806 static bool
valid_group_stream_pair_param(const struct bt_bap_unicast_group * unicast_group,const struct bt_bap_unicast_group_stream_pair_param * pair_param)2807 valid_group_stream_pair_param(const struct bt_bap_unicast_group *unicast_group,
2808 			      const struct bt_bap_unicast_group_stream_pair_param *pair_param)
2809 {
2810 	struct bt_bap_unicast_group_cig_param cig_param = {0};
2811 
2812 	CHECKIF(pair_param == NULL) {
2813 		LOG_DBG("pair_param is NULL");
2814 		return false;
2815 	}
2816 
2817 	if (pair_param->rx_param != NULL) {
2818 		if (!valid_unicast_group_stream_param(unicast_group, pair_param->rx_param,
2819 						      &cig_param, BT_AUDIO_DIR_SOURCE)) {
2820 			return false;
2821 		}
2822 	}
2823 
2824 	if (pair_param->tx_param != NULL) {
2825 		if (!valid_unicast_group_stream_param(unicast_group, pair_param->tx_param,
2826 						      &cig_param, BT_AUDIO_DIR_SINK)) {
2827 			return false;
2828 		}
2829 	}
2830 
2831 	return true;
2832 }
2833 
valid_unicast_group_param(struct bt_bap_unicast_group * unicast_group,const struct bt_bap_unicast_group_param * param)2834 static bool valid_unicast_group_param(struct bt_bap_unicast_group *unicast_group,
2835 				      const struct bt_bap_unicast_group_param *param)
2836 {
2837 	CHECKIF(param == NULL) {
2838 		LOG_DBG("streams is NULL");
2839 		return false;
2840 	}
2841 
2842 	CHECKIF(param->params_count > UNICAST_GROUP_STREAM_CNT) {
2843 		LOG_DBG("Too many streams provided: %u/%u", param->params_count,
2844 			UNICAST_GROUP_STREAM_CNT);
2845 		return false;
2846 	}
2847 
2848 	if (unicast_group != NULL) {
2849 		const size_t group_cis_cnt = unicast_group_get_cis_count(unicast_group);
2850 
2851 		if (param->params_count != group_cis_cnt) {
2852 			LOG_DBG("Mismatch between group CIS count (%zu) and params_count (%zu)",
2853 				group_cis_cnt, param->params_count);
2854 
2855 			return false;
2856 		}
2857 	}
2858 
2859 	for (size_t i = 0U; i < param->params_count; i++) {
2860 		if (!valid_group_stream_pair_param(unicast_group, &param->params[i])) {
2861 			return false;
2862 		}
2863 	}
2864 
2865 	return true;
2866 }
2867 
bt_bap_unicast_group_create(struct bt_bap_unicast_group_param * param,struct bt_bap_unicast_group ** out_unicast_group)2868 int bt_bap_unicast_group_create(struct bt_bap_unicast_group_param *param,
2869 				  struct bt_bap_unicast_group **out_unicast_group)
2870 {
2871 	struct bt_bap_unicast_group *unicast_group;
2872 	int err;
2873 
2874 	CHECKIF(out_unicast_group == NULL)
2875 	{
2876 		LOG_DBG("out_unicast_group is NULL");
2877 		return -EINVAL;
2878 	}
2879 	/* Set out_unicast_group to NULL until the source has actually been created */
2880 	*out_unicast_group = NULL;
2881 
2882 	unicast_group = unicast_group_alloc();
2883 	if (unicast_group == NULL) {
2884 		LOG_DBG("Could not allocate any more unicast groups");
2885 		return -ENOMEM;
2886 	}
2887 
2888 	if (!valid_unicast_group_param(NULL, param)) {
2889 		unicast_group_free(unicast_group);
2890 
2891 		return -EINVAL;
2892 	}
2893 
2894 	for (size_t i = 0U; i < param->params_count; i++) {
2895 		struct bt_bap_unicast_group_stream_pair_param *stream_param;
2896 
2897 		stream_param = &param->params[i];
2898 
2899 		unicast_group->cig_param.packing = param->packing;
2900 		IF_ENABLED(CONFIG_BT_ISO_TEST_PARAMS, ({
2901 			unicast_group->cig_param.c_to_p_ft = param->c_to_p_ft;
2902 			unicast_group->cig_param.p_to_c_ft = param->p_to_c_ft;
2903 			unicast_group->cig_param.iso_interval = param->iso_interval;
2904 		}));
2905 
2906 		err = unicast_group_add_stream_pair(unicast_group, stream_param);
2907 		if (err < 0) {
2908 			LOG_DBG("unicast_group_add_stream failed: %d", err);
2909 			unicast_group_free(unicast_group);
2910 
2911 			return err;
2912 		}
2913 	}
2914 
2915 	err = bt_audio_cig_create(unicast_group);
2916 	if (err != 0) {
2917 		LOG_DBG("bt_audio_cig_create failed: %d", err);
2918 		unicast_group_free(unicast_group);
2919 
2920 		return err;
2921 	}
2922 
2923 	*out_unicast_group = unicast_group;
2924 
2925 	return 0;
2926 }
2927 
bt_bap_unicast_group_reconfig(struct bt_bap_unicast_group * unicast_group,const struct bt_bap_unicast_group_param * param)2928 int bt_bap_unicast_group_reconfig(struct bt_bap_unicast_group *unicast_group,
2929 				  const struct bt_bap_unicast_group_param *param)
2930 {
2931 	struct bt_iso_chan_io_qos rx_io_qos_backup[UNICAST_GROUP_STREAM_CNT];
2932 	struct bt_iso_chan_io_qos tx_io_qos_backup[UNICAST_GROUP_STREAM_CNT];
2933 	struct bt_bap_unicast_group_cig_param cig_param_backup;
2934 	struct bt_bap_stream *tmp_stream;
2935 	size_t idx;
2936 	int err;
2937 
2938 	IF_ENABLED(CONFIG_BT_ISO_TEST_PARAMS,
2939 		   (uint8_t num_subevents_backup[UNICAST_GROUP_STREAM_CNT]));
2940 
2941 	CHECKIF(unicast_group == NULL) {
2942 		LOG_DBG("unicast_group is NULL");
2943 		return -EINVAL;
2944 	}
2945 
2946 	if (unicast_group->has_been_connected) {
2947 		LOG_DBG("Cannot modify a unicast_group where a CIS has been connected");
2948 		return -EINVAL;
2949 	}
2950 
2951 	if (!valid_unicast_group_param(unicast_group, param)) {
2952 		return -EINVAL;
2953 	}
2954 
2955 	/* Make backups of the values in case that the reconfigure request is rejected by e.g. the
2956 	 * controller
2957 	 */
2958 	idx = 0U;
2959 	SYS_SLIST_FOR_EACH_CONTAINER(&unicast_group->streams, tmp_stream, _node) {
2960 		memcpy(&rx_io_qos_backup[idx], tmp_stream->bap_iso->chan.qos->rx,
2961 		       sizeof(rx_io_qos_backup[idx]));
2962 		memcpy(&tx_io_qos_backup[idx], tmp_stream->bap_iso->chan.qos->tx,
2963 		       sizeof(tx_io_qos_backup[idx]));
2964 		IF_ENABLED(
2965 			CONFIG_BT_ISO_TEST_PARAMS,
2966 			(num_subevents_backup[idx] = tmp_stream->bap_iso->chan.qos->num_subevents));
2967 		idx++;
2968 	}
2969 	memcpy(&cig_param_backup, &unicast_group->cig_param, sizeof(cig_param_backup));
2970 
2971 	/* Update the stream and group parameters */
2972 	for (size_t i = 0U; i < param->params_count; i++) {
2973 		struct bt_bap_unicast_group_stream_pair_param *stream_param = &param->params[i];
2974 		struct bt_bap_unicast_group_stream_param *rx_param = stream_param->rx_param;
2975 		struct bt_bap_unicast_group_stream_param *tx_param = stream_param->tx_param;
2976 
2977 		if (rx_param != NULL) {
2978 			unicast_group_set_iso_stream_param(unicast_group, rx_param->stream->bap_iso,
2979 							   rx_param->qos, BT_AUDIO_DIR_SOURCE);
2980 		}
2981 
2982 		if (tx_param != NULL) {
2983 			unicast_group_set_iso_stream_param(unicast_group, tx_param->stream->bap_iso,
2984 							   tx_param->qos, BT_AUDIO_DIR_SOURCE);
2985 		}
2986 	}
2987 
2988 	/* Reconfigure the CIG based on the above new values */
2989 	err = bt_audio_cig_reconfigure(unicast_group);
2990 	if (err != 0) {
2991 		LOG_DBG("bt_audio_cig_reconfigure failed: %d", err);
2992 
2993 		/* Revert any changes above */
2994 		memcpy(&unicast_group->cig_param, &cig_param_backup, sizeof(cig_param_backup));
2995 		idx = 0U;
2996 		SYS_SLIST_FOR_EACH_CONTAINER(&unicast_group->streams, tmp_stream, _node) {
2997 			memcpy(tmp_stream->bap_iso->chan.qos->rx, &rx_io_qos_backup[idx],
2998 			       sizeof(rx_io_qos_backup[idx]));
2999 			memcpy(tmp_stream->bap_iso->chan.qos->tx, &tx_io_qos_backup[idx],
3000 			       sizeof(tx_io_qos_backup[idx]));
3001 			IF_ENABLED(CONFIG_BT_ISO_TEST_PARAMS,
3002 				   (tmp_stream->bap_iso->chan.qos->num_subevents =
3003 					    num_subevents_backup[idx]));
3004 			idx++;
3005 		}
3006 
3007 		return err;
3008 	}
3009 
3010 	return 0;
3011 }
3012 
bt_bap_unicast_group_add_streams(struct bt_bap_unicast_group * unicast_group,struct bt_bap_unicast_group_stream_pair_param params[],size_t num_param)3013 int bt_bap_unicast_group_add_streams(struct bt_bap_unicast_group *unicast_group,
3014 				       struct bt_bap_unicast_group_stream_pair_param params[],
3015 				       size_t num_param)
3016 {
3017 	struct bt_bap_stream *tmp_stream;
3018 	size_t total_stream_cnt;
3019 	struct bt_iso_cig *cig;
3020 	size_t num_added;
3021 	int err;
3022 
3023 	CHECKIF(unicast_group == NULL)
3024 	{
3025 		LOG_DBG("unicast_group is NULL");
3026 		return -EINVAL;
3027 	}
3028 
3029 	if (unicast_group->has_been_connected) {
3030 		LOG_DBG("Cannot modify a unicast_group where a CIS has been connected");
3031 		return -EINVAL;
3032 	}
3033 
3034 	CHECKIF(params == NULL)
3035 	{
3036 		LOG_DBG("params is NULL");
3037 		return -EINVAL;
3038 	}
3039 
3040 	CHECKIF(num_param == 0)
3041 	{
3042 		LOG_DBG("num_param is 0");
3043 		return -EINVAL;
3044 	}
3045 
3046 	total_stream_cnt = num_param;
3047 	SYS_SLIST_FOR_EACH_CONTAINER(&unicast_group->streams, tmp_stream, _node) {
3048 		total_stream_cnt++;
3049 	}
3050 
3051 	if (total_stream_cnt > UNICAST_GROUP_STREAM_CNT) {
3052 		LOG_DBG("Too many streams provided: %u/%u", total_stream_cnt,
3053 			UNICAST_GROUP_STREAM_CNT);
3054 		return -EINVAL;
3055 	}
3056 
3057 	for (size_t i = 0U; i < num_param; i++) {
3058 		if (!valid_group_stream_pair_param(unicast_group, &params[i])) {
3059 			return -EINVAL;
3060 		}
3061 	}
3062 
3063 	/* We can just check the CIG state to see if any streams have started as
3064 	 * that would start the ISO connection procedure
3065 	 */
3066 	cig = unicast_group->cig;
3067 	if (cig != NULL && cig->state != BT_ISO_CIG_STATE_CONFIGURED) {
3068 		LOG_DBG("At least one unicast group stream is started");
3069 		return -EBADMSG;
3070 	}
3071 
3072 	for (num_added = 0U; num_added < num_param; num_added++) {
3073 		struct bt_bap_unicast_group_stream_pair_param *stream_param;
3074 
3075 		stream_param = &params[num_added];
3076 
3077 		err = stream_pair_param_check(stream_param);
3078 		if (err < 0) {
3079 			return err;
3080 		}
3081 
3082 		err = unicast_group_add_stream_pair(unicast_group, stream_param);
3083 		if (err < 0) {
3084 			LOG_DBG("unicast_group_add_stream failed: %d", err);
3085 			goto fail;
3086 		}
3087 	}
3088 
3089 	err = bt_audio_cig_reconfigure(unicast_group);
3090 	if (err != 0) {
3091 		LOG_DBG("bt_audio_cig_reconfigure failed: %d", err);
3092 		goto fail;
3093 	}
3094 
3095 	return 0;
3096 
3097 fail:
3098 	/* Restore group by removing the newly added streams */
3099 	while (num_added--) {
3100 		unicast_group_del_stream_pair(unicast_group, &params[num_added]);
3101 	}
3102 
3103 	return err;
3104 }
3105 
bt_bap_unicast_group_delete(struct bt_bap_unicast_group * unicast_group)3106 int bt_bap_unicast_group_delete(struct bt_bap_unicast_group *unicast_group)
3107 {
3108 	struct bt_bap_stream *stream;
3109 
3110 	CHECKIF(unicast_group == NULL)
3111 	{
3112 		LOG_DBG("unicast_group is NULL");
3113 		return -EINVAL;
3114 	}
3115 
3116 	SYS_SLIST_FOR_EACH_CONTAINER(&unicast_group->streams, stream, _node) {
3117 		/* If a stream has an endpoint, it is not ready to be removed
3118 		 * from a group, as it is not in an idle state
3119 		 */
3120 		if (stream->ep != NULL) {
3121 			LOG_DBG("stream %p is not released", stream);
3122 			return -EINVAL;
3123 		}
3124 	}
3125 
3126 	if (unicast_group->cig != NULL) {
3127 		const int err = unicast_client_cig_terminate(unicast_group);
3128 
3129 		if (err != 0) {
3130 			LOG_DBG("unicast_client_cig_terminate failed with err %d", err);
3131 
3132 			return err;
3133 		}
3134 	}
3135 
3136 	unicast_group_free(unicast_group);
3137 
3138 	return 0;
3139 }
3140 
bt_bap_unicast_client_config(struct bt_bap_stream * stream,const struct bt_audio_codec_cfg * codec_cfg)3141 int bt_bap_unicast_client_config(struct bt_bap_stream *stream,
3142 				 const struct bt_audio_codec_cfg *codec_cfg)
3143 {
3144 	struct bt_bap_ep *ep = stream->ep;
3145 	struct bt_ascs_config_op *op;
3146 	struct net_buf_simple *buf;
3147 	int err;
3148 
3149 	LOG_DBG("stream %p", stream);
3150 
3151 	if (stream->conn == NULL) {
3152 		LOG_DBG("Stream %p does not have a connection", stream);
3153 
3154 		return -ENOTCONN;
3155 	}
3156 
3157 	buf = bt_bap_unicast_client_ep_create_pdu(stream->conn, BT_ASCS_CONFIG_OP);
3158 	if (buf == NULL) {
3159 		LOG_DBG("Could not create PDU");
3160 		return -EBUSY;
3161 	}
3162 
3163 	op = net_buf_simple_add(buf, sizeof(*op));
3164 	op->num_ases = 0x01;
3165 
3166 	err = unicast_client_ep_config(ep, buf, codec_cfg);
3167 	if (err != 0) {
3168 		return err;
3169 	}
3170 
3171 	err = bt_bap_unicast_client_ep_send(stream->conn, ep, buf);
3172 	if (err != 0) {
3173 		return err;
3174 	}
3175 
3176 	return 0;
3177 }
3178 
bt_bap_unicast_client_qos(struct bt_conn * conn,struct bt_bap_unicast_group * group)3179 int bt_bap_unicast_client_qos(struct bt_conn *conn, struct bt_bap_unicast_group *group)
3180 {
3181 	struct bt_bap_stream *stream;
3182 	struct bt_ascs_config_op *op;
3183 	struct net_buf_simple *buf;
3184 	struct bt_bap_ep *ep;
3185 	bool conn_stream_found;
3186 	int err;
3187 
3188 	if (conn == NULL) {
3189 		LOG_DBG("conn is NULL");
3190 
3191 		return -ENOTCONN;
3192 	}
3193 
3194 	/* Used to determine if a stream for the supplied connection pointer
3195 	 * was actually found
3196 	 */
3197 	conn_stream_found = false;
3198 
3199 	/* Validate streams before starting the QoS execution */
3200 	SYS_SLIST_FOR_EACH_CONTAINER(&group->streams, stream, _node) {
3201 		if (stream->conn != conn) {
3202 			/* Channel not part of this ACL, skip */
3203 			continue;
3204 		}
3205 		conn_stream_found = true;
3206 
3207 		ep = stream->ep;
3208 		if (ep == NULL) {
3209 			LOG_DBG("stream->ep is NULL");
3210 			return -EINVAL;
3211 		}
3212 
3213 		/* Can only be done if all the streams are in the codec
3214 		 * configured state or the QoS configured state
3215 		 */
3216 		switch (ep->status.state) {
3217 		case BT_BAP_EP_STATE_CODEC_CONFIGURED:
3218 		case BT_BAP_EP_STATE_QOS_CONFIGURED:
3219 			break;
3220 		default:
3221 			LOG_DBG("Invalid state: %s", bt_bap_ep_state_str(stream->ep->status.state));
3222 			return -EINVAL;
3223 		}
3224 
3225 		if (bt_bap_stream_verify_qos(stream, stream->qos) != BT_BAP_ASCS_REASON_NONE) {
3226 			return -EINVAL;
3227 		}
3228 
3229 		/* Verify ep->dir */
3230 		switch (ep->dir) {
3231 		case BT_AUDIO_DIR_SINK:
3232 		case BT_AUDIO_DIR_SOURCE:
3233 			break;
3234 		default:
3235 			__ASSERT(false, "invalid endpoint dir: %u", ep->dir);
3236 			return -EINVAL;
3237 		}
3238 
3239 		if (stream->bap_iso == NULL) {
3240 			/* This can only happen if the stream was somehow added
3241 			 * to a group without the bap_iso being bound to it
3242 			 */
3243 			LOG_ERR("Could not find bap_iso for stream %p", stream);
3244 			return -EINVAL;
3245 		}
3246 	}
3247 
3248 	if (!conn_stream_found) {
3249 		LOG_DBG("No streams in the group %p for conn %p", group, conn);
3250 		return -EINVAL;
3251 	}
3252 
3253 	/* Generate the control point write */
3254 	buf = bt_bap_unicast_client_ep_create_pdu(conn, BT_ASCS_QOS_OP);
3255 	if (buf == NULL) {
3256 		LOG_DBG("Could not create PDU");
3257 		return -EBUSY;
3258 	}
3259 
3260 	op = net_buf_simple_add(buf, sizeof(*op));
3261 
3262 	(void)memset(op, 0, sizeof(*op));
3263 	ep = NULL; /* Needed to find the control point handle */
3264 	SYS_SLIST_FOR_EACH_CONTAINER(&group->streams, stream, _node) {
3265 		if (stream->conn != conn) {
3266 			/* Channel not part of this ACL, skip */
3267 			continue;
3268 		}
3269 
3270 		op->num_ases++;
3271 
3272 		if (stream->ep->iso == NULL) {
3273 			/* Not yet bound with the bap_iso */
3274 			bt_bap_iso_bind_ep(stream->bap_iso, stream->ep);
3275 		}
3276 
3277 		err = bt_bap_unicast_client_ep_qos(stream->ep, buf, stream->qos);
3278 		if (err != 0) {
3279 			audio_stream_qos_cleanup(conn, group);
3280 
3281 			return err;
3282 		}
3283 
3284 		if (ep == NULL) {
3285 			ep = stream->ep;
3286 		}
3287 	}
3288 
3289 	err = bt_bap_unicast_client_ep_send(conn, ep, buf);
3290 	if (err != 0) {
3291 		LOG_DBG("Could not send config QoS: %d", err);
3292 		audio_stream_qos_cleanup(conn, group);
3293 
3294 		return err;
3295 	}
3296 
3297 	return 0;
3298 }
3299 
bt_bap_unicast_client_enable(struct bt_bap_stream * stream,const uint8_t meta[],size_t meta_len)3300 int bt_bap_unicast_client_enable(struct bt_bap_stream *stream, const uint8_t meta[],
3301 				 size_t meta_len)
3302 {
3303 	struct bt_bap_ep *ep = stream->ep;
3304 	struct net_buf_simple *buf;
3305 	struct bt_ascs_enable_op *req;
3306 	int err;
3307 
3308 	LOG_DBG("stream %p", stream);
3309 
3310 	if (stream->conn == NULL) {
3311 		LOG_DBG("Stream %p does not have a connection", stream);
3312 
3313 		return -ENOTCONN;
3314 	}
3315 
3316 	buf = bt_bap_unicast_client_ep_create_pdu(stream->conn, BT_ASCS_ENABLE_OP);
3317 	if (buf == NULL) {
3318 		LOG_DBG("Could not create PDU");
3319 		return -EBUSY;
3320 	}
3321 
3322 	req = net_buf_simple_add(buf, sizeof(*req));
3323 	req->num_ases = 0x01;
3324 
3325 	err = unicast_client_ep_enable(ep, buf, meta, meta_len);
3326 	if (err) {
3327 		return err;
3328 	}
3329 
3330 	return bt_bap_unicast_client_ep_send(stream->conn, ep, buf);
3331 }
3332 
bt_bap_unicast_client_metadata(struct bt_bap_stream * stream,const uint8_t meta[],size_t meta_len)3333 int bt_bap_unicast_client_metadata(struct bt_bap_stream *stream, const uint8_t meta[],
3334 				   size_t meta_len)
3335 {
3336 	struct bt_bap_ep *ep = stream->ep;
3337 	struct net_buf_simple *buf;
3338 	struct bt_ascs_enable_op *req;
3339 	int err;
3340 
3341 	LOG_DBG("stream %p", stream);
3342 
3343 	if (stream->conn == NULL) {
3344 		LOG_DBG("Stream %p does not have a connection", stream);
3345 
3346 		return -ENOTCONN;
3347 	}
3348 
3349 	buf = bt_bap_unicast_client_ep_create_pdu(stream->conn, BT_ASCS_METADATA_OP);
3350 	if (buf == NULL) {
3351 		LOG_DBG("Could not create PDU");
3352 		return -EBUSY;
3353 	}
3354 
3355 	req = net_buf_simple_add(buf, sizeof(*req));
3356 	req->num_ases = 0x01;
3357 
3358 	err = unicast_client_ep_metadata(ep, buf, meta, meta_len);
3359 	if (err) {
3360 		return err;
3361 	}
3362 
3363 	return bt_bap_unicast_client_ep_send(stream->conn, ep, buf);
3364 }
3365 
bt_bap_unicast_client_connect(struct bt_bap_stream * stream)3366 int bt_bap_unicast_client_connect(struct bt_bap_stream *stream)
3367 {
3368 	struct bt_iso_connect_param param;
3369 	struct bt_iso_chan *iso_chan;
3370 	enum bt_iso_state iso_state;
3371 
3372 	LOG_DBG("stream %p", stream);
3373 
3374 	if (stream == NULL) {
3375 		LOG_DBG("stream is NULL");
3376 
3377 		return -EINVAL;
3378 	}
3379 
3380 	iso_chan = bt_bap_stream_iso_chan_get(stream);
3381 	if (iso_chan == NULL) {
3382 		LOG_DBG("iso_chan is NULL");
3383 
3384 		return -EINVAL;
3385 	}
3386 
3387 	LOG_DBG("stream %p iso %p", stream, iso_chan);
3388 
3389 	param.acl = stream->conn;
3390 	param.iso_chan = iso_chan;
3391 
3392 	iso_state = iso_chan->state;
3393 	if (iso_state == BT_ISO_STATE_DISCONNECTED) {
3394 		const int err = bt_iso_chan_connect(&param, 1);
3395 
3396 		if (err == 0 || err == -EBUSY) { /* Expected / known return values */
3397 			return err;
3398 		}
3399 
3400 		/* unknown return value*/
3401 		LOG_DBG("Unexpected err %d from bt_iso_chan_connect", err);
3402 
3403 		return -ENOEXEC;
3404 	} else if (iso_state == BT_ISO_STATE_CONNECTING || iso_state == BT_ISO_STATE_CONNECTED) {
3405 		LOG_DBG("iso_chan %p already connecting or connected (%u)", iso_chan, iso_state);
3406 
3407 		return -EALREADY;
3408 	}
3409 
3410 	LOG_DBG("iso_chan %p in invalid state state (%u), cannot connect", iso_chan, iso_state);
3411 
3412 	return -EBADMSG;
3413 }
3414 
bt_bap_unicast_client_start(struct bt_bap_stream * stream)3415 int bt_bap_unicast_client_start(struct bt_bap_stream *stream)
3416 {
3417 	struct bt_bap_ep *ep = stream->ep;
3418 	int err;
3419 
3420 	LOG_DBG("stream %p", stream);
3421 
3422 	if (stream->conn == NULL) {
3423 		LOG_DBG("Stream %p does not have a connection", stream);
3424 
3425 		return -ENOTCONN;
3426 	}
3427 
3428 	/* As per the ASCS spec, only source streams can be started by the client */
3429 	if (ep->dir == BT_AUDIO_DIR_SINK) {
3430 		LOG_DBG("Stream %p is not a source stream", stream);
3431 
3432 		return -EINVAL;
3433 	}
3434 
3435 	ep->receiver_ready = true;
3436 
3437 	err = unicast_client_send_start(ep);
3438 	if (err != 0) {
3439 		LOG_DBG("Failed to send start: %d", err);
3440 
3441 		/* TBD: Should we release the stream then? */
3442 		ep->receiver_ready = false;
3443 
3444 		return err;
3445 	}
3446 
3447 	return 0;
3448 }
3449 
bt_bap_unicast_client_disable(struct bt_bap_stream * stream)3450 int bt_bap_unicast_client_disable(struct bt_bap_stream *stream)
3451 {
3452 	struct bt_bap_ep *ep = stream->ep;
3453 	struct net_buf_simple *buf;
3454 	struct bt_ascs_disable_op *req;
3455 	int err;
3456 
3457 	LOG_DBG("stream %p", stream);
3458 
3459 	if (stream->conn == NULL) {
3460 		LOG_DBG("Stream %p does not have a connection", stream);
3461 
3462 		return -ENOTCONN;
3463 	}
3464 
3465 	buf = bt_bap_unicast_client_ep_create_pdu(stream->conn, BT_ASCS_DISABLE_OP);
3466 	if (buf == NULL) {
3467 		LOG_DBG("Could not create PDU");
3468 		return -EBUSY;
3469 	}
3470 
3471 	req = net_buf_simple_add(buf, sizeof(*req));
3472 	req->num_ases = 0x01;
3473 
3474 	err = unicast_client_ep_disable(ep, buf);
3475 	if (err) {
3476 		return err;
3477 	}
3478 
3479 	return bt_bap_unicast_client_ep_send(stream->conn, ep, buf);
3480 }
3481 
bt_bap_unicast_client_stop(struct bt_bap_stream * stream)3482 int bt_bap_unicast_client_stop(struct bt_bap_stream *stream)
3483 {
3484 	struct bt_bap_ep *ep = stream->ep;
3485 	enum bt_iso_state iso_state;
3486 	struct net_buf_simple *buf;
3487 	struct bt_ascs_start_op *req;
3488 	int err;
3489 
3490 	LOG_DBG("stream %p", stream);
3491 
3492 	if (stream->conn == NULL) {
3493 		LOG_DBG("Stream %p does not have a connection", stream);
3494 
3495 		return -ENOTCONN;
3496 	}
3497 
3498 	/* ASCS_v1.0 3.2 ASE state machine transitions
3499 	 *
3500 	 * If the server detects link loss of a CIS for an ASE in the Streaming state or the
3501 	 * Disabling state, the server shall immediately transition that ASE to the QoS Configured
3502 	 * state.
3503 	 *
3504 	 * This effectively means that if an ASE no longer has a connected CIS, the server shall
3505 	 * bring it to the QoS Configured state. That means that we, as a unicast client, should not
3506 	 * attempt to stop it
3507 	 */
3508 	if (ep->iso == NULL) {
3509 		LOG_DBG("Stream endpoint does not have a CIS, server will stop the ASE");
3510 		return -EALREADY;
3511 	}
3512 
3513 	iso_state = ep->iso->chan.state;
3514 	if (iso_state != BT_ISO_STATE_CONNECTED && iso_state != BT_ISO_STATE_CONNECTING) {
3515 		LOG_DBG("Stream endpoint CIS is not connected, server will stop the ASE");
3516 		return -EALREADY;
3517 	}
3518 
3519 	buf = bt_bap_unicast_client_ep_create_pdu(stream->conn, BT_ASCS_STOP_OP);
3520 	if (buf == NULL) {
3521 		LOG_DBG("Could not create PDU");
3522 		return -EBUSY;
3523 	}
3524 
3525 	req = net_buf_simple_add(buf, sizeof(*req));
3526 	req->num_ases = 0x00;
3527 
3528 	/* When initiated by the client, valid only if Direction field
3529 	 * parameter value = 0x02 (Server is Audio Source)
3530 	 */
3531 	if (ep->dir == BT_AUDIO_DIR_SOURCE) {
3532 		err = unicast_client_ep_stop(ep, buf);
3533 		if (err) {
3534 			return err;
3535 		}
3536 		req->num_ases++;
3537 
3538 		err = bt_bap_unicast_client_ep_send(stream->conn, ep, buf);
3539 		if (err != 0) {
3540 			/* Return expected error directly */
3541 			if (err == -ENOTCONN || err == -ENOMEM) {
3542 				return err;
3543 			}
3544 
3545 			LOG_DBG("bt_bap_unicast_client_ep_send failed with unexpected error %d",
3546 				err);
3547 
3548 			return -ENOEXEC;
3549 		}
3550 	}
3551 
3552 	return 0;
3553 }
3554 
bt_bap_unicast_client_release(struct bt_bap_stream * stream)3555 int bt_bap_unicast_client_release(struct bt_bap_stream *stream)
3556 {
3557 	struct bt_bap_unicast_client_ep *client_ep;
3558 	struct bt_bap_ep *ep = stream->ep;
3559 	struct net_buf_simple *buf;
3560 	struct bt_ascs_disable_op *req;
3561 	int err, len;
3562 
3563 	LOG_DBG("stream %p", stream);
3564 
3565 	if (stream->conn == NULL) {
3566 		LOG_DBG("Stream %p does not have a connection", stream);
3567 
3568 		return -ENOTCONN;
3569 	}
3570 
3571 	buf = bt_bap_unicast_client_ep_create_pdu(stream->conn, BT_ASCS_RELEASE_OP);
3572 	if (buf == NULL) {
3573 		LOG_DBG("Could not create PDU");
3574 		return -EBUSY;
3575 	}
3576 
3577 	req = net_buf_simple_add(buf, sizeof(*req));
3578 	req->num_ases = 0x01;
3579 	len = buf->len;
3580 
3581 	/* Only attempt to release if not IDLE already */
3582 	if (stream->ep->status.state == BT_BAP_EP_STATE_IDLE) {
3583 		bt_bap_stream_reset(stream);
3584 	} else {
3585 		err = unicast_client_ep_release(ep, buf);
3586 		if (err) {
3587 			return err;
3588 		}
3589 	}
3590 
3591 	/* Check if anything needs to be send */
3592 	if (len == buf->len) {
3593 		return 0;
3594 	}
3595 
3596 	err = bt_bap_unicast_client_ep_send(stream->conn, ep, buf);
3597 	if (err != 0) {
3598 		return err;
3599 	}
3600 
3601 	client_ep = CONTAINER_OF(ep, struct bt_bap_unicast_client_ep, ep);
3602 	client_ep->release_requested = true;
3603 
3604 	return 0;
3605 }
3606 
unicast_client_cp_discover_func(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * discover)3607 static uint8_t unicast_client_cp_discover_func(struct bt_conn *conn,
3608 					       const struct bt_gatt_attr *attr,
3609 					       struct bt_gatt_discover_params *discover)
3610 {
3611 	struct bt_gatt_chrc *chrc;
3612 	uint16_t value_handle;
3613 
3614 	if (!attr) {
3615 		LOG_ERR("Unable to find ASE Control Point");
3616 
3617 		unicast_client_discover_complete(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND);
3618 		return BT_GATT_ITER_STOP;
3619 	}
3620 
3621 	chrc = attr->user_data;
3622 	value_handle = chrc->value_handle;
3623 	memset(discover, 0, sizeof(*discover));
3624 
3625 	LOG_DBG("conn %p attr %p handle 0x%04x", conn, attr, value_handle);
3626 
3627 	unicast_client_ep_set_cp(conn, value_handle);
3628 
3629 	return BT_GATT_ITER_STOP;
3630 }
3631 
unicast_client_ase_cp_discover(struct bt_conn * conn)3632 static int unicast_client_ase_cp_discover(struct bt_conn *conn)
3633 {
3634 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
3635 
3636 	LOG_DBG("conn %p", conn);
3637 
3638 	client->disc_params.uuid = cp_uuid;
3639 	client->disc_params.func = unicast_client_cp_discover_func;
3640 	client->disc_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
3641 	client->disc_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
3642 	client->disc_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
3643 
3644 	return bt_gatt_discover(conn, &client->disc_params);
3645 }
3646 
unicast_client_ase_read_func(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * read,const void * data,uint16_t length)3647 static uint8_t unicast_client_ase_read_func(struct bt_conn *conn, uint8_t err,
3648 					    struct bt_gatt_read_params *read, const void *data,
3649 					    uint16_t length)
3650 {
3651 	uint16_t handle = read->single.handle;
3652 	struct unicast_client *client;
3653 	struct net_buf_simple *buf;
3654 	struct bt_bap_ep *ep;
3655 	int cb_err;
3656 
3657 	LOG_DBG("conn %p err 0x%02x len %u", conn, err, length);
3658 
3659 	if (err) {
3660 		cb_err = err;
3661 		goto fail;
3662 	}
3663 
3664 	LOG_DBG("handle 0x%04x", handle);
3665 
3666 	client = &uni_cli_insts[bt_conn_index(conn)];
3667 	buf = &client->net_buf;
3668 
3669 	if (data != NULL) {
3670 		if (net_buf_simple_tailroom(buf) < length) {
3671 			LOG_DBG("Buffer full, invalid server response of size %u",
3672 				length + client->net_buf.len);
3673 
3674 			cb_err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
3675 
3676 			goto fail;
3677 		}
3678 
3679 		/* store data*/
3680 		net_buf_simple_add_mem(buf, data, length);
3681 
3682 		return BT_GATT_ITER_CONTINUE;
3683 	}
3684 
3685 	memset(read, 0, sizeof(*read));
3686 
3687 	if (buf->len < sizeof(struct bt_ascs_ase_status)) {
3688 		LOG_DBG("Read response too small (%u)", buf->len);
3689 
3690 		cb_err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
3691 
3692 		goto fail;
3693 	}
3694 
3695 	ep = unicast_client_ep_get(conn, client->dir, handle);
3696 	if (!ep) {
3697 		/* The BAP spec declares that the unicast client shall subscribe to all ASEs.
3698 		 * In case that we cannot support this due to memory restrictions, we should
3699 		 * consider the discovery procedure as failing.
3700 		 */
3701 		LOG_WRN("No space left to parse ASE");
3702 		cb_err = -ENOMEM;
3703 
3704 		goto fail;
3705 	}
3706 
3707 	unicast_client_ep_set_status(ep, buf);
3708 	cb_err = unicast_client_ep_subscribe(conn, ep);
3709 	if (cb_err != 0) {
3710 		LOG_DBG("Failed to subscribe to ep %p: %d", ep, cb_err);
3711 		goto fail;
3712 	}
3713 
3714 	reset_att_buf(client);
3715 
3716 	unicast_client_notify_endpoint(conn, ep);
3717 
3718 	cb_err = unicast_client_ase_discover(conn, handle);
3719 	if (cb_err != 0) {
3720 		LOG_DBG("Failed to read ASE: %d", cb_err);
3721 		goto fail;
3722 	}
3723 
3724 	return BT_GATT_ITER_STOP;
3725 
3726 fail:
3727 	unicast_client_discover_complete(conn, cb_err);
3728 	return BT_GATT_ITER_STOP;
3729 }
3730 
any_ases_found(const struct unicast_client * client)3731 static bool any_ases_found(const struct unicast_client *client)
3732 {
3733 	/* We always allocate ases from 0 to X, so to verify if any sink or source ASEs have been
3734 	 * found we can just check the first index
3735 	 */
3736 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
3737 	if (client->dir == BT_AUDIO_DIR_SINK && client->snks[0].handle == BAP_HANDLE_UNUSED) {
3738 		LOG_DBG("No sink ASEs found");
3739 		return false;
3740 	}
3741 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
3742 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
3743 	if (client->dir == BT_AUDIO_DIR_SOURCE && client->srcs[0].handle == BAP_HANDLE_UNUSED) {
3744 		LOG_DBG("No source ASEs found");
3745 		return false;
3746 	}
3747 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
3748 
3749 	return true;
3750 }
3751 
unicast_client_ase_discover_cb(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * discover)3752 static uint8_t unicast_client_ase_discover_cb(struct bt_conn *conn,
3753 					      const struct bt_gatt_attr *attr,
3754 					      struct bt_gatt_discover_params *discover)
3755 {
3756 	struct unicast_client *client;
3757 	struct bt_gatt_chrc *chrc;
3758 	uint16_t value_handle;
3759 	int err;
3760 
3761 	client = &uni_cli_insts[bt_conn_index(conn)];
3762 
3763 	if (attr == NULL) {
3764 		if (!any_ases_found(client)) {
3765 			unicast_client_discover_complete(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND);
3766 		} else {
3767 			err = unicast_client_ase_cp_discover(conn);
3768 			if (err != 0) {
3769 				LOG_ERR("Unable to discover ASE Control Point");
3770 
3771 				unicast_client_discover_complete(conn, err);
3772 			}
3773 		}
3774 
3775 		return BT_GATT_ITER_STOP;
3776 	}
3777 
3778 	chrc = attr->user_data;
3779 	value_handle = chrc->value_handle;
3780 	memset(discover, 0, sizeof(*discover));
3781 
3782 	LOG_DBG("conn %p attr %p handle 0x%04x dir %s", conn, attr, value_handle,
3783 		bt_audio_dir_str(client->dir));
3784 
3785 	client->read_params.func = unicast_client_ase_read_func;
3786 	client->read_params.handle_count = 1U;
3787 	client->read_params.single.handle = value_handle;
3788 	client->read_params.single.offset = 0U;
3789 
3790 	err = bt_gatt_read(conn, &client->read_params);
3791 	if (err != 0) {
3792 		LOG_DBG("Failed to read PAC records: %d", err);
3793 
3794 		unicast_client_discover_complete(conn, err);
3795 	}
3796 
3797 	return BT_GATT_ITER_STOP;
3798 }
3799 
unicast_client_ase_discover(struct bt_conn * conn,uint16_t start_handle)3800 static int unicast_client_ase_discover(struct bt_conn *conn, uint16_t start_handle)
3801 {
3802 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
3803 
3804 	LOG_DBG("conn %p ", conn);
3805 
3806 	if (client->dir == BT_AUDIO_DIR_SINK) {
3807 		client->disc_params.uuid = ase_snk_uuid;
3808 	} else if (client->dir == BT_AUDIO_DIR_SOURCE) {
3809 		client->disc_params.uuid = ase_src_uuid;
3810 	} else {
3811 		return -EINVAL;
3812 	}
3813 
3814 	client->disc_params.func = unicast_client_ase_discover_cb;
3815 	client->disc_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
3816 	client->disc_params.start_handle = start_handle;
3817 	client->disc_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
3818 
3819 	return bt_gatt_discover(conn, &client->disc_params);
3820 }
3821 
unicast_client_pacs_avail_ctx_read_func(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * read,const void * data,uint16_t length)3822 static uint8_t unicast_client_pacs_avail_ctx_read_func(struct bt_conn *conn, uint8_t err,
3823 						       struct bt_gatt_read_params *read,
3824 						       const void *data, uint16_t length)
3825 {
3826 	struct bt_pacs_context context;
3827 	struct net_buf_simple buf;
3828 	int cb_err;
3829 
3830 	memset(read, 0, sizeof(*read));
3831 
3832 	LOG_DBG("conn %p err 0x%02x len %u", conn, err, length);
3833 
3834 	if (err || data == NULL || length != sizeof(context)) {
3835 		LOG_DBG("Could not read available context: %d, %p, %u", err, data, length);
3836 
3837 		if (err == BT_ATT_ERR_SUCCESS) {
3838 			err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
3839 		}
3840 
3841 		unicast_client_discover_complete(conn, err);
3842 
3843 		return BT_GATT_ITER_STOP;
3844 	}
3845 
3846 	net_buf_simple_init_with_data(&buf, (void *)data, length);
3847 	context.snk = net_buf_simple_pull_le16(&buf);
3848 	context.src = net_buf_simple_pull_le16(&buf);
3849 
3850 	LOG_DBG("sink context %u, source context %u", context.snk, context.src);
3851 
3852 	unicast_client_notify_available_contexts(conn, context.snk, context.src);
3853 
3854 	/* Read ASE instances */
3855 	cb_err = unicast_client_ase_discover(conn, BT_ATT_FIRST_ATTRIBUTE_HANDLE);
3856 	if (cb_err != 0) {
3857 		LOG_ERR("Unable to read ASE: %d", cb_err);
3858 
3859 		unicast_client_discover_complete(conn, cb_err);
3860 	}
3861 
3862 	return BT_GATT_ITER_STOP;
3863 }
3864 
unicast_client_pacs_avail_ctx_notify_cb(struct bt_conn * conn,struct bt_gatt_subscribe_params * params,const void * data,uint16_t length)3865 static uint8_t unicast_client_pacs_avail_ctx_notify_cb(struct bt_conn *conn,
3866 						       struct bt_gatt_subscribe_params *params,
3867 						       const void *data, uint16_t length)
3868 {
3869 	struct bt_pacs_context context;
3870 	struct net_buf_simple buf;
3871 
3872 	LOG_DBG("conn %p len %u", conn, length);
3873 
3874 	if (!data) {
3875 		LOG_DBG("Unsubscribed");
3876 		params->value_handle = BAP_HANDLE_UNUSED;
3877 		return BT_GATT_ITER_STOP;
3878 	}
3879 
3880 	net_buf_simple_init_with_data(&buf, (void *)data, length);
3881 
3882 	if (buf.len != sizeof(context)) {
3883 		LOG_ERR("Avail_ctx notification incorrect size: %u", length);
3884 		return BT_GATT_ITER_STOP;
3885 	}
3886 
3887 	net_buf_simple_init_with_data(&buf, (void *)data, length);
3888 	context.snk = net_buf_simple_pull_le16(&buf);
3889 	context.src = net_buf_simple_pull_le16(&buf);
3890 
3891 	LOG_DBG("sink context %u, source context %u", context.snk, context.src);
3892 
3893 	unicast_client_notify_available_contexts(conn, context.snk, context.src);
3894 
3895 	return BT_GATT_ITER_CONTINUE;
3896 }
3897 
unicast_client_pacs_avail_ctx_read(struct bt_conn * conn,uint16_t handle)3898 static int unicast_client_pacs_avail_ctx_read(struct bt_conn *conn, uint16_t handle)
3899 {
3900 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
3901 
3902 	LOG_DBG("conn %p", conn);
3903 
3904 	client->read_params.func = unicast_client_pacs_avail_ctx_read_func;
3905 	client->read_params.handle_count = 1U;
3906 	client->read_params.single.handle = handle;
3907 	client->read_params.single.offset = 0U;
3908 
3909 	return bt_gatt_read(conn, &client->read_params);
3910 }
3911 
unicast_client_pacs_avail_ctx_discover_cb(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * discover)3912 static uint8_t unicast_client_pacs_avail_ctx_discover_cb(struct bt_conn *conn,
3913 							 const struct bt_gatt_attr *attr,
3914 							 struct bt_gatt_discover_params *discover)
3915 {
3916 	uint8_t index = bt_conn_index(conn);
3917 	const struct bt_gatt_chrc *chrc;
3918 	uint8_t chrc_properties;
3919 	uint16_t value_handle;
3920 	int err;
3921 
3922 	if (!attr) {
3923 		/* If available_ctx is not found, we terminate the discovery as
3924 		 * the characteristic is mandatory
3925 		 */
3926 
3927 		unicast_client_discover_complete(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND);
3928 
3929 		return BT_GATT_ITER_STOP;
3930 	}
3931 
3932 	chrc = attr->user_data;
3933 	chrc_properties = chrc->properties;
3934 	value_handle = chrc->value_handle;
3935 	memset(discover, 0, sizeof(*discover));
3936 
3937 	LOG_DBG("conn %p attr %p handle 0x%04x", conn, attr, value_handle);
3938 
3939 	if (chrc_properties & BT_GATT_CHRC_NOTIFY) {
3940 		struct bt_gatt_subscribe_params *sub_params;
3941 
3942 		sub_params = &uni_cli_insts[index].avail_ctx_subscribe;
3943 
3944 		if (sub_params->value_handle == 0) {
3945 			LOG_DBG("Subscribing to handle %u", value_handle);
3946 			sub_params->value_handle = value_handle;
3947 			sub_params->ccc_handle = BT_GATT_AUTO_DISCOVER_CCC_HANDLE;
3948 			sub_params->end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
3949 			sub_params->disc_params = &uni_cli_insts[index].avail_ctx_cc_disc;
3950 			sub_params->notify = unicast_client_pacs_avail_ctx_notify_cb;
3951 			sub_params->value = BT_GATT_CCC_NOTIFY;
3952 			atomic_set_bit(sub_params->flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
3953 
3954 			err = bt_gatt_subscribe(conn, sub_params);
3955 			if (err != 0 && err != -EALREADY) {
3956 				LOG_ERR("Failed to subscribe to avail_ctx: %d", err);
3957 			}
3958 		} /* else already subscribed */
3959 	} else {
3960 		LOG_DBG("Invalid chrc->properties: %u", chrc_properties);
3961 		/* If the characteristic is not subscribable we terminate the
3962 		 * discovery as BT_GATT_CHRC_NOTIFY is mandatory
3963 		 */
3964 		unicast_client_discover_complete(conn, BT_ATT_ERR_NOT_SUPPORTED);
3965 
3966 		return BT_GATT_ITER_STOP;
3967 	}
3968 
3969 	err = unicast_client_pacs_avail_ctx_read(conn, value_handle);
3970 	if (err != 0) {
3971 		LOG_DBG("Failed to read PACS avail_ctx: %d", err);
3972 
3973 		unicast_client_discover_complete(conn, err);
3974 	}
3975 
3976 	return BT_GATT_ITER_STOP;
3977 }
3978 
unicast_client_pacs_avail_ctx_discover(struct bt_conn * conn)3979 static int unicast_client_pacs_avail_ctx_discover(struct bt_conn *conn)
3980 {
3981 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
3982 
3983 	LOG_DBG("conn %p", conn);
3984 
3985 	client->disc_params.uuid = pacs_avail_ctx_uuid;
3986 	client->disc_params.func = unicast_client_pacs_avail_ctx_discover_cb;
3987 	client->disc_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
3988 	client->disc_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
3989 	client->disc_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
3990 
3991 	return bt_gatt_discover(conn, &client->disc_params);
3992 }
3993 
unicast_client_pacs_location_read_func(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * read,const void * data,uint16_t length)3994 static uint8_t unicast_client_pacs_location_read_func(struct bt_conn *conn, uint8_t err,
3995 						      struct bt_gatt_read_params *read,
3996 						      const void *data, uint16_t length)
3997 {
3998 	struct unicast_client *client;
3999 	struct net_buf_simple buf;
4000 	uint32_t location;
4001 	int cb_err;
4002 
4003 	memset(read, 0, sizeof(*read));
4004 
4005 	client = &uni_cli_insts[bt_conn_index(conn)];
4006 
4007 	LOG_DBG("conn %p err 0x%02x len %u", conn, err, length);
4008 
4009 	if (err || data == NULL || length != sizeof(location)) {
4010 		LOG_DBG("Unable to read PACS location for dir %s: %u, %p, %u",
4011 			bt_audio_dir_str(client->dir), err, data, length);
4012 
4013 		if (err == BT_ATT_ERR_SUCCESS) {
4014 			err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
4015 		}
4016 
4017 		unicast_client_discover_complete(conn, err);
4018 
4019 		return BT_GATT_ITER_STOP;
4020 	}
4021 
4022 	net_buf_simple_init_with_data(&buf, (void *)data, length);
4023 	location = net_buf_simple_pull_le32(&buf);
4024 
4025 	LOG_DBG("dir %s loc %X", bt_audio_dir_str(client->dir), location);
4026 
4027 	unicast_client_notify_location(conn, client->dir, (enum bt_audio_location)location);
4028 
4029 	/* Read available contexts */
4030 	cb_err = unicast_client_pacs_avail_ctx_discover(conn);
4031 	if (cb_err != 0) {
4032 		LOG_ERR("Unable to read available contexts: %d", cb_err);
4033 
4034 		unicast_client_discover_complete(conn, cb_err);
4035 	}
4036 
4037 	return BT_GATT_ITER_STOP;
4038 }
4039 
unicast_client_pacs_location_notify_cb(struct bt_conn * conn,struct bt_gatt_subscribe_params * params,const void * data,uint16_t length)4040 static uint8_t unicast_client_pacs_location_notify_cb(struct bt_conn *conn,
4041 						      struct bt_gatt_subscribe_params *params,
4042 						      const void *data, uint16_t length)
4043 {
4044 	struct net_buf_simple buf;
4045 	enum bt_audio_dir dir;
4046 	uint32_t location;
4047 
4048 	LOG_DBG("conn %p len %u", conn, length);
4049 
4050 	if (!data) {
4051 		LOG_DBG("Unsubscribed");
4052 		params->value_handle = BAP_HANDLE_UNUSED;
4053 		return BT_GATT_ITER_STOP;
4054 	}
4055 
4056 	net_buf_simple_init_with_data(&buf, (void *)data, length);
4057 
4058 	if (buf.len != sizeof(location)) {
4059 		LOG_ERR("Location notification incorrect size: %u", length);
4060 		return BT_GATT_ITER_STOP;
4061 	}
4062 
4063 	if (params == &uni_cli_insts[bt_conn_index(conn)].snk_loc_subscribe) {
4064 		dir = BT_AUDIO_DIR_SINK;
4065 	} else if (params == &uni_cli_insts[bt_conn_index(conn)].src_loc_subscribe) {
4066 		dir = BT_AUDIO_DIR_SOURCE;
4067 	} else {
4068 		LOG_ERR("Invalid notification");
4069 
4070 		return BT_GATT_ITER_CONTINUE;
4071 	}
4072 
4073 	net_buf_simple_init_with_data(&buf, (void *)data, length);
4074 	location = net_buf_simple_pull_le32(&buf);
4075 
4076 	LOG_DBG("dir %s loc %X", bt_audio_dir_str(dir), location);
4077 
4078 	unicast_client_notify_location(conn, dir, (enum bt_audio_location)location);
4079 
4080 	return BT_GATT_ITER_CONTINUE;
4081 }
4082 
unicast_client_pacs_location_read(struct bt_conn * conn,uint16_t handle)4083 static int unicast_client_pacs_location_read(struct bt_conn *conn, uint16_t handle)
4084 {
4085 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
4086 
4087 	LOG_DBG("conn %p", conn);
4088 
4089 	client->read_params.func = unicast_client_pacs_location_read_func;
4090 	client->read_params.handle_count = 1U;
4091 	client->read_params.single.handle = handle;
4092 	client->read_params.single.offset = 0U;
4093 
4094 	return bt_gatt_read(conn, &client->read_params);
4095 }
4096 
unicast_client_pacs_location_discover_cb(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * discover)4097 static uint8_t unicast_client_pacs_location_discover_cb(struct bt_conn *conn,
4098 							const struct bt_gatt_attr *attr,
4099 							struct bt_gatt_discover_params *discover)
4100 {
4101 	uint8_t index = bt_conn_index(conn);
4102 	const struct bt_gatt_chrc *chrc;
4103 	uint16_t value_handle;
4104 	int err;
4105 
4106 	if (!attr) {
4107 		/* If location is not found, we just continue reading the
4108 		 * available contexts, as location is optional.
4109 		 */
4110 		err = unicast_client_pacs_avail_ctx_discover(conn);
4111 		if (err != 0) {
4112 			LOG_ERR("Unable to read available contexts: %d", err);
4113 
4114 			unicast_client_discover_complete(conn, err);
4115 		}
4116 
4117 		return BT_GATT_ITER_STOP;
4118 	}
4119 
4120 	chrc = attr->user_data;
4121 	value_handle = chrc->value_handle;
4122 	memset(discover, 0, sizeof(*discover));
4123 
4124 	LOG_DBG("conn %p attr %p handle 0x%04x", conn, attr, value_handle);
4125 
4126 	if (chrc->properties & BT_GATT_CHRC_NOTIFY) {
4127 		const struct unicast_client *client = &uni_cli_insts[index];
4128 		struct bt_gatt_subscribe_params *sub_params;
4129 
4130 		if (client->dir == BT_AUDIO_DIR_SINK) {
4131 			sub_params = &uni_cli_insts[index].snk_loc_subscribe;
4132 		} else {
4133 			sub_params = &uni_cli_insts[index].src_loc_subscribe;
4134 		}
4135 
4136 		sub_params->value_handle = value_handle;
4137 		sub_params->ccc_handle = BT_GATT_AUTO_DISCOVER_CCC_HANDLE;
4138 		sub_params->end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
4139 		sub_params->disc_params = &uni_cli_insts[index].loc_cc_disc;
4140 		sub_params->notify = unicast_client_pacs_location_notify_cb;
4141 		sub_params->value = BT_GATT_CCC_NOTIFY;
4142 		atomic_set_bit(sub_params->flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
4143 
4144 		err = bt_gatt_subscribe(conn, sub_params);
4145 		if (err != 0 && err != -EALREADY) {
4146 			LOG_ERR("Failed to subscribe to location: %d", err);
4147 		}
4148 	}
4149 
4150 	err = unicast_client_pacs_location_read(conn, value_handle);
4151 	if (err != 0) {
4152 		LOG_DBG("Failed to read PACS location: %d", err);
4153 
4154 		unicast_client_discover_complete(conn, err);
4155 	}
4156 
4157 	return BT_GATT_ITER_STOP;
4158 }
4159 
unicast_client_pacs_location_discover(struct bt_conn * conn)4160 static int unicast_client_pacs_location_discover(struct bt_conn *conn)
4161 {
4162 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
4163 
4164 	LOG_DBG("conn %p dir %s", conn, bt_audio_dir_str(client->dir));
4165 
4166 	if (client->dir == BT_AUDIO_DIR_SINK) {
4167 		client->disc_params.uuid = pacs_snk_loc_uuid;
4168 	} else if (client->dir == BT_AUDIO_DIR_SOURCE) {
4169 		client->disc_params.uuid = pacs_src_loc_uuid;
4170 	} else {
4171 		return -EINVAL;
4172 	}
4173 
4174 	client->disc_params.func = unicast_client_pacs_location_discover_cb;
4175 	client->disc_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
4176 	client->disc_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
4177 	client->disc_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
4178 
4179 	return bt_gatt_discover(conn, &client->disc_params);
4180 }
4181 
unicast_client_pacs_context_read_func(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * read,const void * data,uint16_t length)4182 static uint8_t unicast_client_pacs_context_read_func(struct bt_conn *conn, uint8_t err,
4183 						     struct bt_gatt_read_params *read,
4184 						     const void *data, uint16_t length)
4185 {
4186 	struct net_buf_simple buf;
4187 	struct bt_pacs_context *context;
4188 	int cb_err;
4189 
4190 	memset(read, 0, sizeof(*read));
4191 
4192 	LOG_DBG("conn %p err 0x%02x len %u", conn, err, length);
4193 
4194 	if (err || length < sizeof(uint16_t) * 2) {
4195 		goto discover_loc;
4196 	}
4197 
4198 	net_buf_simple_init_with_data(&buf, (void *)data, length);
4199 	context = net_buf_simple_pull_mem(&buf, sizeof(*context));
4200 
4201 discover_loc:
4202 	/* Read ASE instances */
4203 	cb_err = unicast_client_pacs_location_discover(conn);
4204 	if (cb_err != 0) {
4205 		LOG_ERR("Unable to read PACS location: %d", cb_err);
4206 
4207 		unicast_client_discover_complete(conn, cb_err);
4208 	}
4209 
4210 	return BT_GATT_ITER_STOP;
4211 }
4212 
unicast_client_pacs_context_discover_cb(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * discover)4213 static uint8_t unicast_client_pacs_context_discover_cb(struct bt_conn *conn,
4214 						       const struct bt_gatt_attr *attr,
4215 						       struct bt_gatt_discover_params *discover)
4216 {
4217 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
4218 	struct bt_gatt_chrc *chrc;
4219 	uint16_t value_handle;
4220 	int err;
4221 
4222 	if (attr == NULL) {
4223 		LOG_ERR("Unable to find %s PAC context", bt_audio_dir_str(client->dir));
4224 
4225 		unicast_client_discover_complete(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND);
4226 
4227 		return BT_GATT_ITER_STOP;
4228 	}
4229 
4230 	chrc = attr->user_data;
4231 	value_handle = chrc->value_handle;
4232 	memset(discover, 0, sizeof(*discover));
4233 
4234 	LOG_DBG("conn %p attr %p handle 0x%04x dir %s", conn, attr, value_handle,
4235 		bt_audio_dir_str(client->dir));
4236 
4237 	/* TODO: Subscribe to PAC context */
4238 
4239 	client->read_params.func = unicast_client_pacs_context_read_func;
4240 	client->read_params.handle_count = 1U;
4241 	client->read_params.single.handle = value_handle;
4242 	client->read_params.single.offset = 0U;
4243 
4244 	err = bt_gatt_read(conn, &client->read_params);
4245 	if (err != 0) {
4246 		LOG_DBG("Failed to read PAC records: %d", err);
4247 
4248 		unicast_client_discover_complete(conn, err);
4249 	}
4250 
4251 	return BT_GATT_ITER_STOP;
4252 }
4253 
unicast_client_pacs_context_discover(struct bt_conn * conn)4254 static int unicast_client_pacs_context_discover(struct bt_conn *conn)
4255 {
4256 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
4257 
4258 	LOG_DBG("conn %p", conn);
4259 
4260 	client->disc_params.uuid = pacs_context_uuid;
4261 	client->disc_params.func = unicast_client_pacs_context_discover_cb;
4262 	client->disc_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
4263 	client->disc_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
4264 	client->disc_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
4265 
4266 	return bt_gatt_discover(conn, &client->disc_params);
4267 }
4268 
unicast_client_read_func(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * read,const void * data,uint16_t length)4269 static uint8_t unicast_client_read_func(struct bt_conn *conn, uint8_t err,
4270 					struct bt_gatt_read_params *read, const void *data,
4271 					uint16_t length)
4272 {
4273 	uint16_t handle = read->single.handle;
4274 	struct unicast_client *client;
4275 	struct bt_pacs_read_rsp *rsp;
4276 	struct net_buf_simple *buf;
4277 	int cb_err = err;
4278 	uint8_t i;
4279 
4280 	LOG_DBG("conn %p err 0x%02x len %u", conn, err, length);
4281 
4282 	if (cb_err != BT_ATT_ERR_SUCCESS) {
4283 		goto fail;
4284 	}
4285 
4286 	LOG_DBG("handle 0x%04x", handle);
4287 
4288 	client = &uni_cli_insts[bt_conn_index(conn)];
4289 	buf = &client->net_buf;
4290 
4291 	if (data != NULL) {
4292 		if (net_buf_simple_tailroom(buf) < length) {
4293 			LOG_DBG("Buffer full, invalid server response of size %u",
4294 				length + client->net_buf.len);
4295 
4296 			cb_err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
4297 
4298 			goto fail;
4299 		}
4300 
4301 		/* store data*/
4302 		net_buf_simple_add_mem(buf, data, length);
4303 
4304 		return BT_GATT_ITER_CONTINUE;
4305 	}
4306 
4307 	memset(read, 0, sizeof(*read));
4308 
4309 	if (buf->len < sizeof(*rsp)) {
4310 		LOG_DBG("Read response too small (%u)", buf->len);
4311 
4312 		cb_err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
4313 
4314 		goto fail;
4315 	}
4316 
4317 	rsp = net_buf_simple_pull_mem(buf, sizeof(*rsp));
4318 
4319 	/* If no PAC was found don't bother discovering ASE and ASE CP */
4320 	if (!rsp->num_pac) {
4321 		goto fail;
4322 	}
4323 
4324 	for (i = 0U; i < rsp->num_pac; i++) {
4325 		struct bt_audio_codec_cap codec_cap;
4326 		struct bt_pac_codec *pac_codec;
4327 		struct bt_pac_ltv_data *meta, *cc;
4328 		void *cc_ltv, *meta_ltv;
4329 
4330 		LOG_DBG("pac #%u/%u", i + 1, rsp->num_pac);
4331 
4332 		if (buf->len < sizeof(*pac_codec)) {
4333 			LOG_ERR("Malformed PAC: remaining len %u expected %zu",
4334 				buf->len, sizeof(*pac_codec));
4335 			break;
4336 		}
4337 
4338 		pac_codec = net_buf_simple_pull_mem(buf, sizeof(*pac_codec));
4339 
4340 		if (buf->len < sizeof(*cc)) {
4341 			LOG_ERR("Malformed PAC: remaining len %u expected %zu",
4342 				buf->len, sizeof(*cc));
4343 			break;
4344 		}
4345 
4346 		cc = net_buf_simple_pull_mem(buf, sizeof(*cc));
4347 		if (buf->len < cc->len) {
4348 			LOG_ERR("Malformed PAC: remaining len %u expected %zu",
4349 				buf->len, cc->len);
4350 			break;
4351 		}
4352 
4353 		cc_ltv = net_buf_simple_pull_mem(buf, cc->len);
4354 
4355 		if (buf->len < sizeof(*meta)) {
4356 			LOG_ERR("Malformed PAC: remaining len %u expected %zu",
4357 				buf->len, sizeof(*meta));
4358 			break;
4359 		}
4360 
4361 		meta = net_buf_simple_pull_mem(buf, sizeof(*meta));
4362 		if (buf->len < meta->len) {
4363 			LOG_ERR("Malformed PAC: remaining len %u expected %u",
4364 				buf->len, meta->len);
4365 			break;
4366 		}
4367 
4368 		meta_ltv = net_buf_simple_pull_mem(buf, meta->len);
4369 
4370 		if (unicast_client_set_codec_cap(pac_codec->id, sys_le16_to_cpu(pac_codec->cid),
4371 						 sys_le16_to_cpu(pac_codec->vid), cc_ltv, cc->len,
4372 						 meta_ltv, meta->len, &codec_cap)) {
4373 			LOG_ERR("Unable to parse Codec");
4374 			break;
4375 		}
4376 
4377 		LOG_DBG("codec 0x%02x capabilities len %u meta len %u ", codec_cap.id,
4378 			codec_cap.data_len, codec_cap.meta_len);
4379 
4380 		unicast_client_notify_pac_record(conn, &codec_cap);
4381 	}
4382 
4383 	reset_att_buf(client);
4384 
4385 	if (i != rsp->num_pac) {
4386 		LOG_DBG("Failed to process all PAC records (%u/%u)", i, rsp->num_pac);
4387 		cb_err = BT_ATT_ERR_INVALID_PDU;
4388 		goto fail;
4389 	}
4390 
4391 	/* Read PACS contexts */
4392 	cb_err = unicast_client_pacs_context_discover(conn);
4393 	if (cb_err != 0) {
4394 		LOG_ERR("Unable to read PACS context: %d", cb_err);
4395 		goto fail;
4396 	}
4397 
4398 	return BT_GATT_ITER_STOP;
4399 
4400 fail:
4401 	unicast_client_discover_complete(conn, cb_err);
4402 	return BT_GATT_ITER_STOP;
4403 }
4404 
unicast_client_pac_discover_cb(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * discover)4405 static uint8_t unicast_client_pac_discover_cb(struct bt_conn *conn,
4406 					      const struct bt_gatt_attr *attr,
4407 					      struct bt_gatt_discover_params *discover)
4408 {
4409 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
4410 	struct bt_gatt_chrc *chrc;
4411 	uint16_t value_handle;
4412 	int err;
4413 
4414 	if (attr == NULL) {
4415 		LOG_DBG("Unable to find %s PAC", bt_audio_dir_str(client->dir));
4416 
4417 		unicast_client_discover_complete(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND);
4418 
4419 		return BT_GATT_ITER_STOP;
4420 	}
4421 
4422 	chrc = attr->user_data;
4423 	value_handle = chrc->value_handle;
4424 	memset(discover, 0, sizeof(*discover));
4425 
4426 	LOG_DBG("conn %p attr %p handle 0x%04x dir %s", conn, attr, value_handle,
4427 		bt_audio_dir_str(client->dir));
4428 
4429 	/* TODO: Subscribe to PAC */
4430 
4431 	/* Reset to use for long read */
4432 	reset_att_buf(client);
4433 
4434 	client->read_params.func = unicast_client_read_func;
4435 	client->read_params.handle_count = 1U;
4436 	client->read_params.single.handle = value_handle;
4437 	client->read_params.single.offset = 0U;
4438 
4439 	err = bt_gatt_read(conn, &client->read_params);
4440 	if (err != 0) {
4441 		LOG_DBG("Failed to read PAC records: %d", err);
4442 
4443 		unicast_client_discover_complete(conn, err);
4444 	}
4445 
4446 	return BT_GATT_ITER_STOP;
4447 }
4448 
unicast_client_disconnected(struct bt_conn * conn,uint8_t reason)4449 static void unicast_client_disconnected(struct bt_conn *conn, uint8_t reason)
4450 {
4451 	LOG_DBG("conn %p reason 0x%02x", conn, reason);
4452 
4453 	unicast_client_ep_reset(conn, reason);
4454 }
4455 
4456 static struct bt_conn_cb conn_cbs = {
4457 	.disconnected = unicast_client_disconnected,
4458 };
4459 
bt_bap_unicast_client_discover(struct bt_conn * conn,enum bt_audio_dir dir)4460 int bt_bap_unicast_client_discover(struct bt_conn *conn, enum bt_audio_dir dir)
4461 {
4462 	struct unicast_client *client;
4463 	static bool conn_cb_registered;
4464 	uint8_t role;
4465 	int err;
4466 
4467 	if (!conn || conn->state != BT_CONN_CONNECTED) {
4468 		return -ENOTCONN;
4469 	}
4470 
4471 	role = conn->role;
4472 	if (role != BT_HCI_ROLE_CENTRAL) {
4473 		LOG_DBG("Invalid conn role: %u, shall be central", role);
4474 		return -EINVAL;
4475 	}
4476 
4477 	client = &uni_cli_insts[bt_conn_index(conn)];
4478 	if (atomic_test_and_set_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY)) {
4479 		LOG_DBG("Client connection is busy");
4480 		return -EBUSY;
4481 	}
4482 
4483 	if (dir == BT_AUDIO_DIR_SINK) {
4484 		client->disc_params.uuid = snk_uuid;
4485 	} else if (dir == BT_AUDIO_DIR_SOURCE) {
4486 		client->disc_params.uuid = src_uuid;
4487 	} else {
4488 		return -EINVAL;
4489 	}
4490 
4491 	client->disc_params.func = unicast_client_pac_discover_cb;
4492 	client->disc_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
4493 	client->disc_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
4494 	client->disc_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
4495 
4496 	if (!conn_cb_registered) {
4497 		bt_conn_cb_register(&conn_cbs);
4498 		conn_cb_registered = true;
4499 	}
4500 
4501 	err = bt_gatt_discover(conn, &client->disc_params);
4502 	if (err != 0) {
4503 		atomic_clear_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY);
4504 		return err;
4505 	}
4506 
4507 	client->dir = dir;
4508 
4509 	return 0;
4510 }
4511 
bt_bap_unicast_client_register_cb(struct bt_bap_unicast_client_cb * cb)4512 int bt_bap_unicast_client_register_cb(struct bt_bap_unicast_client_cb *cb)
4513 {
4514 	CHECKIF(cb == NULL) {
4515 		LOG_DBG("cb is NULL");
4516 		return -EINVAL;
4517 	}
4518 
4519 	if (sys_slist_find(&unicast_client_cbs, &cb->_node, NULL)) {
4520 		return -EEXIST;
4521 	}
4522 
4523 	sys_slist_append(&unicast_client_cbs, &cb->_node);
4524 
4525 	return 0;
4526 }
4527