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 	uint16_t max_ntf_size;
1751 	struct bt_bap_ep *ep;
1752 
1753 	client_ep = CONTAINER_OF(params, struct bt_bap_unicast_client_ep, subscribe);
1754 	ep = &client_ep->ep;
1755 
1756 	LOG_DBG("conn %p ep %p len %u", conn, ep, length);
1757 
1758 	/* Cancel any pending long reads for the endpoint */
1759 	(void)k_work_cancel_delayable(&client_ep->ase_read_work);
1760 
1761 	if (!data) {
1762 		LOG_DBG("Unsubscribed");
1763 		params->value_handle = BAP_HANDLE_UNUSED;
1764 		return BT_GATT_ITER_STOP;
1765 	}
1766 
1767 	max_ntf_size = bt_audio_get_max_ntf_size(conn);
1768 
1769 	if (length == max_ntf_size) {
1770 		struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
1771 
1772 		if (!atomic_test_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY)) {
1773 			struct net_buf_simple *long_read_buf = &client->net_buf;
1774 
1775 			/* store data*/
1776 			net_buf_simple_add_mem(long_read_buf, data, length);
1777 		}
1778 
1779 		long_ase_read(client_ep);
1780 
1781 		return BT_GATT_ITER_CONTINUE;
1782 	}
1783 
1784 	net_buf_simple_init_with_data(&buf, (void *)data, length);
1785 
1786 	if (buf.len < sizeof(struct bt_ascs_ase_status)) {
1787 		LOG_ERR("Notification too small");
1788 		return BT_GATT_ITER_STOP;
1789 	}
1790 
1791 	/* Set reason in case this exits the streaming state, unless already set */
1792 	if (ep->reason == BT_HCI_ERR_SUCCESS) {
1793 		ep->reason = BT_HCI_ERR_REMOTE_USER_TERM_CONN;
1794 	}
1795 
1796 	unicast_client_ep_set_status(ep, &buf);
1797 
1798 	return BT_GATT_ITER_CONTINUE;
1799 }
1800 
unicast_client_ep_subscribe(struct bt_conn * conn,struct bt_bap_ep * ep)1801 static int unicast_client_ep_subscribe(struct bt_conn *conn, struct bt_bap_ep *ep)
1802 {
1803 	struct bt_bap_unicast_client_ep *client_ep;
1804 	int err;
1805 
1806 	client_ep = CONTAINER_OF(ep, struct bt_bap_unicast_client_ep, ep);
1807 
1808 	LOG_DBG("ep %p handle 0x%02x", ep, client_ep->handle);
1809 
1810 	if (client_ep->subscribe.value_handle) {
1811 		return 0;
1812 	}
1813 
1814 	client_ep->subscribe.value_handle = client_ep->handle;
1815 	client_ep->subscribe.ccc_handle = BT_GATT_AUTO_DISCOVER_CCC_HANDLE;
1816 	client_ep->subscribe.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
1817 	client_ep->subscribe.disc_params = &client_ep->discover;
1818 	client_ep->subscribe.notify = unicast_client_ep_notify;
1819 	client_ep->subscribe.value = BT_GATT_CCC_NOTIFY;
1820 	atomic_set_bit(client_ep->subscribe.flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
1821 
1822 	err = bt_gatt_subscribe(conn, &client_ep->subscribe);
1823 	if (err != 0 && err != -EALREADY) {
1824 		return err;
1825 	}
1826 
1827 	return 0;
1828 }
1829 
unicast_client_cp_sub_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_subscribe_params * sub_params)1830 static void unicast_client_cp_sub_cb(struct bt_conn *conn, uint8_t err,
1831 				     struct bt_gatt_subscribe_params *sub_params)
1832 {
1833 
1834 	LOG_DBG("conn %p err %u", conn, err);
1835 
1836 	unicast_client_discover_complete(conn, err);
1837 }
1838 
unicast_client_ep_set_cp(struct bt_conn * conn,uint16_t handle)1839 static void unicast_client_ep_set_cp(struct bt_conn *conn, uint16_t handle)
1840 {
1841 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
1842 
1843 	LOG_DBG("conn %p 0x%04x", conn, handle);
1844 
1845 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
1846 	for (size_t i = 0U; i < ARRAY_SIZE(client->snks); i++) {
1847 		struct bt_bap_unicast_client_ep *client_ep = &client->snks[i];
1848 
1849 		if (client_ep->handle) {
1850 			client_ep->cp_handle = handle;
1851 		}
1852 	}
1853 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
1854 
1855 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
1856 	for (size_t i = 0U; i < ARRAY_SIZE(client->srcs); i++) {
1857 		struct bt_bap_unicast_client_ep *client_ep = &client->srcs[i];
1858 
1859 		if (client_ep->handle) {
1860 			client_ep->cp_handle = handle;
1861 		}
1862 	}
1863 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
1864 
1865 	if (!client->cp_subscribe.value_handle) {
1866 		int err;
1867 
1868 		client->cp_subscribe.value_handle = handle;
1869 		client->cp_subscribe.ccc_handle = BT_GATT_AUTO_DISCOVER_CCC_HANDLE;
1870 		client->cp_subscribe.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
1871 		client->cp_subscribe.disc_params = &client->disc_params;
1872 		client->cp_subscribe.notify = unicast_client_cp_notify;
1873 		client->cp_subscribe.value = BT_GATT_CCC_NOTIFY;
1874 		client->cp_subscribe.subscribe = unicast_client_cp_sub_cb;
1875 		atomic_set_bit(client->cp_subscribe.flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
1876 
1877 		err = bt_gatt_subscribe(conn, &client->cp_subscribe);
1878 		if (err != 0 && err != -EALREADY) {
1879 			LOG_DBG("Failed to subscribe: %d", err);
1880 
1881 			unicast_client_discover_complete(conn, err);
1882 
1883 			return;
1884 		}
1885 	} else { /* already subscribed */
1886 		unicast_client_discover_complete(conn, 0);
1887 	}
1888 }
1889 
bt_bap_unicast_client_ep_create_pdu(struct bt_conn * conn,uint8_t op)1890 struct net_buf_simple *bt_bap_unicast_client_ep_create_pdu(struct bt_conn *conn, uint8_t op)
1891 {
1892 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
1893 	struct bt_ascs_ase_cp *hdr;
1894 
1895 	if (atomic_test_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY)) {
1896 		return NULL;
1897 	}
1898 
1899 	hdr = net_buf_simple_add(&client->net_buf, sizeof(*hdr));
1900 	hdr->op = op;
1901 
1902 	return &client->net_buf;
1903 }
1904 
unicast_client_ep_config(struct bt_bap_ep * ep,struct net_buf_simple * buf,const struct bt_audio_codec_cfg * codec_cfg)1905 static int unicast_client_ep_config(struct bt_bap_ep *ep, struct net_buf_simple *buf,
1906 				    const struct bt_audio_codec_cfg *codec_cfg)
1907 {
1908 	struct bt_ascs_config *req;
1909 
1910 	LOG_DBG("ep %p buf %p codec %p", ep, buf, codec_cfg);
1911 
1912 	if (!ep) {
1913 		return -EINVAL;
1914 	}
1915 
1916 	switch (ep->status.state) {
1917 	/* Valid only if ASE_State field = 0x00 (Idle) */
1918 	case BT_BAP_EP_STATE_IDLE:
1919 		/* or 0x01 (Codec Configured) */
1920 	case BT_BAP_EP_STATE_CODEC_CONFIGURED:
1921 		/* or 0x02 (QoS Configured) */
1922 	case BT_BAP_EP_STATE_QOS_CONFIGURED:
1923 		break;
1924 	default:
1925 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
1926 		return -EINVAL;
1927 	}
1928 
1929 	LOG_DBG("id 0x%02x dir %s codec 0x%02x", ep->status.id, bt_audio_dir_str(ep->dir),
1930 		codec_cfg->id);
1931 
1932 	req = net_buf_simple_add(buf, sizeof(*req));
1933 	req->ase = ep->status.id;
1934 	req->latency = 0x02; /* TODO: Select target latency based on additional input? */
1935 	req->phy = 0x02;     /* TODO: Select target PHY based on additional input? */
1936 	req->codec.id = codec_cfg->id;
1937 	req->codec.cid = codec_cfg->cid;
1938 	req->codec.vid = codec_cfg->vid;
1939 
1940 	req->cc_len = codec_cfg->data_len;
1941 	net_buf_simple_add_mem(buf, codec_cfg->data, codec_cfg->data_len);
1942 
1943 	return 0;
1944 }
1945 
bt_bap_unicast_client_ep_qos(struct bt_bap_ep * ep,struct net_buf_simple * buf,struct bt_bap_qos_cfg * qos)1946 int bt_bap_unicast_client_ep_qos(struct bt_bap_ep *ep, struct net_buf_simple *buf,
1947 				 struct bt_bap_qos_cfg *qos)
1948 {
1949 	struct bt_ascs_qos *req;
1950 	struct bt_conn_iso *conn_iso;
1951 
1952 	LOG_DBG("ep %p buf %p qos %p", ep, buf, qos);
1953 
1954 	if (!ep) {
1955 		return -EINVAL;
1956 	}
1957 
1958 	switch (ep->status.state) {
1959 	/* Valid only if ASE_State field = 0x01 (Codec Configured) */
1960 	case BT_BAP_EP_STATE_CODEC_CONFIGURED:
1961 		/* or 0x02 (QoS Configured) */
1962 	case BT_BAP_EP_STATE_QOS_CONFIGURED:
1963 		break;
1964 	default:
1965 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
1966 		return -EINVAL;
1967 	}
1968 
1969 	conn_iso = &ep->iso->chan.iso->iso;
1970 
1971 	LOG_DBG("id 0x%02x cig 0x%02x cis 0x%02x interval %u framing 0x%02x "
1972 		"phy 0x%02x sdu %u rtn %u latency %u pd %u",
1973 		ep->status.id, conn_iso->cig_id, conn_iso->cis_id, qos->interval, qos->framing,
1974 		qos->phy, qos->sdu, qos->rtn, qos->latency, qos->pd);
1975 
1976 	req = net_buf_simple_add(buf, sizeof(*req));
1977 	req->ase = ep->status.id;
1978 	/* TODO: don't hardcode CIG and CIS, they should come from ISO */
1979 	req->cig = conn_iso->cig_id;
1980 	req->cis = conn_iso->cis_id;
1981 	sys_put_le24(qos->interval, req->interval);
1982 	req->framing = qos->framing;
1983 	req->phy = qos->phy;
1984 	req->sdu = qos->sdu;
1985 	req->rtn = qos->rtn;
1986 	req->latency = sys_cpu_to_le16(qos->latency);
1987 	sys_put_le24(qos->pd, req->pd);
1988 
1989 	return 0;
1990 }
1991 
unicast_client_ep_enable(struct bt_bap_ep * ep,struct net_buf_simple * buf,const uint8_t meta[],size_t meta_len)1992 static int unicast_client_ep_enable(struct bt_bap_ep *ep, struct net_buf_simple *buf,
1993 				    const uint8_t meta[], size_t meta_len)
1994 {
1995 	struct bt_ascs_metadata *req;
1996 
1997 	LOG_DBG("ep %p buf %p meta_len %zu", ep, buf, meta_len);
1998 
1999 	if (!ep) {
2000 		return -EINVAL;
2001 	}
2002 
2003 	if (ep->status.state != BT_BAP_EP_STATE_QOS_CONFIGURED) {
2004 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
2005 		return -EINVAL;
2006 	}
2007 
2008 	LOG_DBG("id 0x%02x", ep->status.id);
2009 
2010 	req = net_buf_simple_add(buf, sizeof(*req));
2011 	req->ase = ep->status.id;
2012 
2013 	req->len = meta_len;
2014 	net_buf_simple_add_mem(buf, meta, meta_len);
2015 
2016 	return 0;
2017 }
2018 
unicast_client_ep_metadata(struct bt_bap_ep * ep,struct net_buf_simple * buf,const uint8_t meta[],size_t meta_len)2019 static int unicast_client_ep_metadata(struct bt_bap_ep *ep, struct net_buf_simple *buf,
2020 				      const uint8_t meta[], size_t meta_len)
2021 {
2022 	struct bt_ascs_metadata *req;
2023 
2024 	LOG_DBG("ep %p buf %p meta_len %zu", ep, buf, meta_len);
2025 
2026 	if (!ep) {
2027 		return -EINVAL;
2028 	}
2029 
2030 	switch (ep->status.state) {
2031 	/* Valid for an ASE only if ASE_State field = 0x03 (Enabling) */
2032 	case BT_BAP_EP_STATE_ENABLING:
2033 	/* or 0x04 (Streaming) */
2034 	case BT_BAP_EP_STATE_STREAMING:
2035 		break;
2036 	default:
2037 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
2038 		return -EINVAL;
2039 	}
2040 
2041 	LOG_DBG("id 0x%02x", ep->status.id);
2042 
2043 	req = net_buf_simple_add(buf, sizeof(*req));
2044 	req->ase = ep->status.id;
2045 
2046 	req->len = meta_len;
2047 	net_buf_simple_add_mem(buf, meta, meta_len);
2048 
2049 	return 0;
2050 }
2051 
unicast_client_ep_start(struct bt_bap_ep * ep,struct net_buf_simple * buf)2052 static int unicast_client_ep_start(struct bt_bap_ep *ep, struct net_buf_simple *buf)
2053 {
2054 	LOG_DBG("ep %p buf %p", ep, buf);
2055 
2056 	if (!ep) {
2057 		return -EINVAL;
2058 	}
2059 
2060 	if (ep->status.state != BT_BAP_EP_STATE_ENABLING &&
2061 	    ep->status.state != BT_BAP_EP_STATE_DISABLING) {
2062 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
2063 		return -EINVAL;
2064 	}
2065 
2066 	LOG_DBG("id 0x%02x", ep->status.id);
2067 
2068 	net_buf_simple_add_u8(buf, ep->status.id);
2069 
2070 	return 0;
2071 }
2072 
unicast_client_ep_disable(struct bt_bap_ep * ep,struct net_buf_simple * buf)2073 static int unicast_client_ep_disable(struct bt_bap_ep *ep, struct net_buf_simple *buf)
2074 {
2075 	LOG_DBG("ep %p buf %p", ep, buf);
2076 
2077 	if (!ep) {
2078 		return -EINVAL;
2079 	}
2080 
2081 	switch (ep->status.state) {
2082 	/* Valid only if ASE_State field = 0x03 (Enabling) */
2083 	case BT_BAP_EP_STATE_ENABLING:
2084 		/* or 0x04 (Streaming) */
2085 	case BT_BAP_EP_STATE_STREAMING:
2086 		break;
2087 	default:
2088 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
2089 		return -EINVAL;
2090 	}
2091 
2092 	LOG_DBG("id 0x%02x", ep->status.id);
2093 
2094 	net_buf_simple_add_u8(buf, ep->status.id);
2095 
2096 	return 0;
2097 }
2098 
unicast_client_ep_stop(struct bt_bap_ep * ep,struct net_buf_simple * buf)2099 static int unicast_client_ep_stop(struct bt_bap_ep *ep, struct net_buf_simple *buf)
2100 {
2101 	LOG_DBG("ep %p buf %p", ep, buf);
2102 
2103 	if (!ep) {
2104 		return -EINVAL;
2105 	}
2106 
2107 	/* Valid only if ASE_State field value = 0x05 (Disabling). */
2108 	if (ep->status.state != BT_BAP_EP_STATE_DISABLING) {
2109 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
2110 		return -EINVAL;
2111 	}
2112 
2113 	LOG_DBG("id 0x%02x", ep->status.id);
2114 
2115 	net_buf_simple_add_u8(buf, ep->status.id);
2116 
2117 	return 0;
2118 }
2119 
unicast_client_ep_release(struct bt_bap_ep * ep,struct net_buf_simple * buf)2120 static int unicast_client_ep_release(struct bt_bap_ep *ep, struct net_buf_simple *buf)
2121 {
2122 	LOG_DBG("ep %p buf %p", ep, buf);
2123 
2124 	if (!ep) {
2125 		return -EINVAL;
2126 	}
2127 
2128 	switch (ep->status.state) {
2129 	/* Valid only if ASE_State field = 0x01 (Codec Configured) */
2130 	case BT_BAP_EP_STATE_CODEC_CONFIGURED:
2131 		/* or 0x02 (QoS Configured) */
2132 	case BT_BAP_EP_STATE_QOS_CONFIGURED:
2133 		/* or 0x03 (Enabling) */
2134 	case BT_BAP_EP_STATE_ENABLING:
2135 		/* or 0x04 (Streaming) */
2136 	case BT_BAP_EP_STATE_STREAMING:
2137 		/* or 0x05 (Disabling) */
2138 	case BT_BAP_EP_STATE_DISABLING:
2139 		break;
2140 	default:
2141 		LOG_ERR("Invalid state: %s", bt_bap_ep_state_str(ep->status.state));
2142 		return -EINVAL;
2143 	}
2144 
2145 	LOG_DBG("id 0x%02x", ep->status.id);
2146 
2147 	net_buf_simple_add_u8(buf, ep->status.id);
2148 
2149 	return 0;
2150 }
2151 
gatt_write_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_write_params * params)2152 static void gatt_write_cb(struct bt_conn *conn, uint8_t err, struct bt_gatt_write_params *params)
2153 {
2154 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
2155 
2156 	LOG_DBG("conn %p err %u", conn, err);
2157 
2158 	memset(params, 0, sizeof(*params));
2159 	reset_att_buf(client);
2160 	atomic_clear_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY);
2161 
2162 	/* TBD: Should we do anything in case of error here? */
2163 }
2164 
bt_bap_unicast_client_ep_send(struct bt_conn * conn,struct bt_bap_ep * ep,struct net_buf_simple * buf)2165 int bt_bap_unicast_client_ep_send(struct bt_conn *conn, struct bt_bap_ep *ep,
2166 				  struct net_buf_simple *buf)
2167 {
2168 	const uint16_t max_write_size = bt_audio_get_max_ntf_size(conn);
2169 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
2170 	struct bt_bap_unicast_client_ep *client_ep =
2171 		CONTAINER_OF(ep, struct bt_bap_unicast_client_ep, ep);
2172 	int err;
2173 
2174 	LOG_DBG("conn %p ep %p buf %p len %u", conn, ep, buf, buf->len);
2175 
2176 	if (buf->len > max_write_size) {
2177 		if (atomic_test_and_set_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY)) {
2178 			LOG_DBG("Client connection is busy");
2179 			return -EBUSY;
2180 		}
2181 
2182 		client->write_params.func = gatt_write_cb;
2183 		client->write_params.handle = client_ep->cp_handle;
2184 		client->write_params.offset = 0U;
2185 		client->write_params.data = buf->data;
2186 		client->write_params.length = buf->len;
2187 #if defined(CONFIG_BT_EATT)
2188 		client->write_params.chan_opt = BT_ATT_CHAN_OPT_NONE;
2189 #endif /* CONFIG_BT_EATT */
2190 
2191 		err = bt_gatt_write(conn, &client->write_params);
2192 		if (err != 0) {
2193 			LOG_DBG("bt_gatt_write failed: %d", err);
2194 			atomic_clear_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY);
2195 		}
2196 	} else {
2197 		err = bt_gatt_write_without_response(conn, client_ep->cp_handle, buf->data,
2198 						     buf->len, false);
2199 		if (err != 0) {
2200 			LOG_DBG("bt_gatt_write_without_response failed: %d", err);
2201 		}
2202 
2203 		/* No callback for writing without response, so reset the buffer here */
2204 		reset_att_buf(client);
2205 	}
2206 
2207 	if (err == 0) {
2208 		client_ep->cp_ntf_pending = true;
2209 	}
2210 
2211 	return err;
2212 }
2213 
unicast_client_reset(struct bt_bap_ep * ep,uint8_t reason)2214 static void unicast_client_reset(struct bt_bap_ep *ep, uint8_t reason)
2215 {
2216 	struct bt_bap_unicast_client_ep *client_ep =
2217 		CONTAINER_OF(ep, struct bt_bap_unicast_client_ep, ep);
2218 
2219 	LOG_DBG("ep %p", ep);
2220 	ep->reason = reason;
2221 
2222 	/* Pretend we received an idle state notification from the server to trigger all cleanup */
2223 	unicast_client_ep_set_local_idle_state(ep);
2224 
2225 	if (ep->iso != NULL && ep->iso->chan.state == BT_ISO_STATE_DISCONNECTING) {
2226 		/* Wait for ISO disconnected event */
2227 		return;
2228 	}
2229 
2230 	(void)k_work_cancel_delayable(&client_ep->ase_read_work);
2231 	(void)memset(ep, 0, sizeof(*ep));
2232 
2233 	client_ep->cp_handle = BAP_HANDLE_UNUSED;
2234 	client_ep->handle = BAP_HANDLE_UNUSED;
2235 	(void)memset(&client_ep->discover, 0, sizeof(client_ep->discover));
2236 	client_ep->release_requested = false;
2237 	client_ep->cp_ntf_pending = false;
2238 	/* Need to keep the subscribe params intact for the callback */
2239 }
2240 
unicast_client_ep_reset(struct bt_conn * conn,uint8_t reason)2241 static void unicast_client_ep_reset(struct bt_conn *conn, uint8_t reason)
2242 {
2243 	struct unicast_client *client;
2244 	uint8_t index;
2245 
2246 	LOG_DBG("conn %p", conn);
2247 
2248 	index = bt_conn_index(conn);
2249 
2250 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
2251 	for (size_t i = 0U; i < ARRAY_SIZE(uni_cli_insts[index].snks); i++) {
2252 		struct bt_bap_ep *ep = &uni_cli_insts[index].snks[i].ep;
2253 
2254 		unicast_client_reset(ep, reason);
2255 	}
2256 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
2257 
2258 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
2259 	for (size_t i = 0U; i < ARRAY_SIZE(uni_cli_insts[index].srcs); i++) {
2260 		struct bt_bap_ep *ep = &uni_cli_insts[index].srcs[i].ep;
2261 
2262 		unicast_client_reset(ep, reason);
2263 	}
2264 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
2265 
2266 	client = &uni_cli_insts[index];
2267 	atomic_clear_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY);
2268 	client->dir = 0U;
2269 	reset_att_buf(client);
2270 }
2271 
bt_bap_qos_cfg_to_cig_param(struct bt_iso_cig_param * cig_param,const struct bt_bap_unicast_group * group)2272 static void bt_bap_qos_cfg_to_cig_param(struct bt_iso_cig_param *cig_param,
2273 					    const struct bt_bap_unicast_group *group)
2274 {
2275 	cig_param->framing = group->cig_param.framing;
2276 	cig_param->c_to_p_interval = group->cig_param.c_to_p_interval;
2277 	cig_param->p_to_c_interval = group->cig_param.p_to_c_interval;
2278 	cig_param->c_to_p_latency = group->cig_param.c_to_p_latency;
2279 	cig_param->p_to_c_latency = group->cig_param.p_to_c_latency;
2280 	cig_param->packing = group->cig_param.packing;
2281 	cig_param->sca = BT_GAP_SCA_UNKNOWN;
2282 
2283 	IF_ENABLED(CONFIG_BT_ISO_TEST_PARAMS, ({
2284 		cig_param->c_to_p_ft = group->cig_param.c_to_p_ft;
2285 		cig_param->p_to_c_ft = group->cig_param.p_to_c_ft;
2286 		cig_param->iso_interval = group->cig_param.iso_interval;
2287 	}));
2288 
2289 	/* In the case that we only setup a single direction, we still need
2290 	 * (as per section 7.8.97 LE Set CIG Parameters command) to set the interval and latency on
2291 	 * both sides. The value shall be ignored, but the value may not always be ignored correctly
2292 	 * by all controllers, so we always set it here.
2293 	 * If it is at this point unset, then we set the opposing direction to the same value.
2294 	 */
2295 	if (cig_param->c_to_p_interval == 0U) {
2296 		cig_param->c_to_p_interval = cig_param->p_to_c_interval;
2297 	} else if (cig_param->p_to_c_interval == 0U) {
2298 		cig_param->p_to_c_interval = cig_param->c_to_p_interval;
2299 	}
2300 
2301 	if (cig_param->c_to_p_latency == 0U) {
2302 		cig_param->c_to_p_latency = cig_param->p_to_c_latency;
2303 	} else if (cig_param->p_to_c_latency == 0U) {
2304 		cig_param->p_to_c_latency = cig_param->c_to_p_latency;
2305 	}
2306 }
2307 
unicast_group_get_cis_count(const struct bt_bap_unicast_group * unicast_group)2308 static uint8_t unicast_group_get_cis_count(const struct bt_bap_unicast_group *unicast_group)
2309 {
2310 	uint8_t cis_count = 0U;
2311 
2312 	for (size_t i = 0U; i < ARRAY_SIZE(unicast_group->cis); i++) {
2313 		if (unicast_group->cis[i] == NULL) {
2314 			/* A NULL CIS acts as a NULL terminator */
2315 			break;
2316 		}
2317 
2318 		cis_count++;
2319 	}
2320 
2321 	return cis_count;
2322 }
2323 
bt_audio_cig_create(struct bt_bap_unicast_group * group)2324 static int bt_audio_cig_create(struct bt_bap_unicast_group *group)
2325 {
2326 	struct bt_iso_cig_param param = {0};
2327 	int err;
2328 
2329 	LOG_DBG("group %p", group);
2330 
2331 	param.num_cis = unicast_group_get_cis_count(group);
2332 	param.cis_channels = group->cis;
2333 	bt_bap_qos_cfg_to_cig_param(&param, group);
2334 
2335 	err = bt_iso_cig_create(&param, &group->cig);
2336 	if (err != 0) {
2337 		LOG_ERR("bt_iso_cig_create failed: %d", err);
2338 		return err;
2339 	}
2340 
2341 	return 0;
2342 }
2343 
bt_audio_cig_reconfigure(struct bt_bap_unicast_group * group)2344 static int bt_audio_cig_reconfigure(struct bt_bap_unicast_group *group)
2345 {
2346 	struct bt_iso_cig_param param;
2347 	uint8_t cis_count;
2348 	int err;
2349 
2350 	LOG_DBG("group %p ", group);
2351 
2352 	cis_count = 0U;
2353 	for (size_t i = 0U; i < ARRAY_SIZE(group->cis); i++) {
2354 		if (group->cis[i] == NULL) {
2355 			/* A NULL CIS acts as a NULL terminator */
2356 			break;
2357 		}
2358 
2359 		cis_count++;
2360 	}
2361 
2362 	param.num_cis = cis_count;
2363 	param.cis_channels = group->cis;
2364 	bt_bap_qos_cfg_to_cig_param(&param, group);
2365 
2366 	err = bt_iso_cig_reconfigure(group->cig, &param);
2367 	if (err != 0) {
2368 		LOG_ERR("bt_iso_cig_create failed: %d", err);
2369 		return err;
2370 	}
2371 
2372 	return 0;
2373 }
2374 
audio_stream_qos_cleanup(const struct bt_conn * conn,struct bt_bap_unicast_group * group)2375 static void audio_stream_qos_cleanup(const struct bt_conn *conn,
2376 				     struct bt_bap_unicast_group *group)
2377 {
2378 	struct bt_bap_stream *stream;
2379 
2380 	SYS_SLIST_FOR_EACH_CONTAINER(&group->streams, stream, _node) {
2381 		if (stream->conn != conn) {
2382 			/* Channel not part of this ACL, skip */
2383 			continue;
2384 		}
2385 
2386 		if (stream->ep == NULL) {
2387 			/* Stream did not have a endpoint configured yet */
2388 			continue;
2389 		}
2390 
2391 		bt_bap_iso_unbind_ep(stream->ep->iso, stream->ep);
2392 	}
2393 }
2394 
unicast_client_cig_terminate(struct bt_bap_unicast_group * group)2395 static int unicast_client_cig_terminate(struct bt_bap_unicast_group *group)
2396 {
2397 	LOG_DBG("group %p", group);
2398 
2399 	return bt_iso_cig_terminate(group->cig);
2400 }
2401 
unicast_group_add_iso(struct bt_bap_unicast_group * group,struct bt_bap_iso * iso)2402 static int unicast_group_add_iso(struct bt_bap_unicast_group *group, struct bt_bap_iso *iso)
2403 {
2404 	struct bt_iso_chan **chan_slot = NULL;
2405 
2406 	__ASSERT_NO_MSG(group != NULL);
2407 	__ASSERT_NO_MSG(iso != NULL);
2408 
2409 	/* Append iso channel to the group->cis array */
2410 	for (size_t i = 0U; i < ARRAY_SIZE(group->cis); i++) {
2411 		/* Return if already there */
2412 		if (group->cis[i] == &iso->chan) {
2413 			return 0;
2414 		}
2415 
2416 		if (chan_slot == NULL && group->cis[i] == NULL) {
2417 			chan_slot = &group->cis[i];
2418 		}
2419 	}
2420 
2421 	if (chan_slot == NULL) {
2422 		return -ENOMEM;
2423 	}
2424 
2425 	*chan_slot = &iso->chan;
2426 
2427 	return 0;
2428 }
2429 
unicast_group_del_iso(struct bt_bap_unicast_group * group,struct bt_bap_iso * iso)2430 static void unicast_group_del_iso(struct bt_bap_unicast_group *group, struct bt_bap_iso *iso)
2431 {
2432 	struct bt_bap_stream *stream;
2433 
2434 	__ASSERT_NO_MSG(group != NULL);
2435 	__ASSERT_NO_MSG(iso != NULL);
2436 
2437 	SYS_SLIST_FOR_EACH_CONTAINER(&group->streams, stream, _node) {
2438 		if (stream->ep->iso == iso) {
2439 			/* still in use by some other stream */
2440 			return;
2441 		}
2442 	}
2443 
2444 	for (size_t i = 0U; i < ARRAY_SIZE(group->cis); i++) {
2445 		if (group->cis[i] == &iso->chan) {
2446 			group->cis[i] = NULL;
2447 			return;
2448 		}
2449 	}
2450 }
2451 
unicast_client_qos_cfg_to_iso_qos(struct bt_bap_iso * iso,const struct bt_bap_qos_cfg * qos,enum bt_audio_dir dir)2452 static void unicast_client_qos_cfg_to_iso_qos(struct bt_bap_iso *iso,
2453 					      const struct bt_bap_qos_cfg *qos,
2454 					      enum bt_audio_dir dir)
2455 {
2456 	struct bt_iso_chan_io_qos *io_qos;
2457 	struct bt_iso_chan_io_qos *other_io_qos;
2458 
2459 	if (dir == BT_AUDIO_DIR_SINK) {
2460 		/* If the endpoint is a sink, then we need to
2461 		 * configure our TX parameters
2462 		 */
2463 		io_qos = iso->chan.qos->tx;
2464 		if (bt_bap_iso_get_ep(true, iso, BT_AUDIO_DIR_SOURCE) == NULL) {
2465 			other_io_qos = iso->chan.qos->rx;
2466 		} else {
2467 			other_io_qos = NULL;
2468 		}
2469 	} else {
2470 		/* If the endpoint is a source, then we need to
2471 		 * configure our RX parameters
2472 		 */
2473 		io_qos = iso->chan.qos->rx;
2474 		if (bt_bap_iso_get_ep(true, iso, BT_AUDIO_DIR_SINK) == NULL) {
2475 			other_io_qos = iso->chan.qos->tx;
2476 		} else {
2477 			other_io_qos = NULL;
2478 		}
2479 	}
2480 
2481 	bt_bap_qos_cfg_to_iso_qos(io_qos, qos);
2482 #if defined(CONFIG_BT_ISO_TEST_PARAMS)
2483 	iso->chan.qos->num_subevents = qos->num_subevents;
2484 #endif /* CONFIG_BT_ISO_TEST_PARAMS */
2485 
2486 	if (other_io_qos != NULL) {
2487 		/* If the opposing ASE of the CIS is not yet configured, we
2488 		 * still need to set the PHY value when creating the CIG.
2489 		 */
2490 		other_io_qos->phy = io_qos->phy;
2491 	}
2492 }
2493 
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)2494 static void unicast_group_set_iso_stream_param(struct bt_bap_unicast_group *group,
2495 					       struct bt_bap_iso *iso,
2496 					       struct bt_bap_qos_cfg *qos,
2497 					       enum bt_audio_dir dir)
2498 {
2499 	/* Store the stream Codec QoS in the bap_iso */
2500 	unicast_client_qos_cfg_to_iso_qos(iso, qos, dir);
2501 
2502 	/* Store the group Codec QoS in the group - This assume thats the parameters have been
2503 	 * verified first
2504 	 */
2505 	group->cig_param.framing = qos->framing;
2506 	if (dir == BT_AUDIO_DIR_SOURCE) {
2507 		group->cig_param.p_to_c_interval = qos->interval;
2508 		group->cig_param.p_to_c_latency = qos->latency;
2509 	} else {
2510 		group->cig_param.c_to_p_interval = qos->interval;
2511 		group->cig_param.c_to_p_latency = qos->latency;
2512 	}
2513 }
2514 
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)2515 static void unicast_group_add_stream(struct bt_bap_unicast_group *group,
2516 				     struct bt_bap_unicast_group_stream_param *param,
2517 				     struct bt_bap_iso *iso, enum bt_audio_dir dir)
2518 {
2519 	struct bt_bap_stream *stream = param->stream;
2520 	struct bt_bap_qos_cfg *qos = param->qos;
2521 
2522 	LOG_DBG("group %p stream %p qos %p iso %p dir %u", group, stream, qos, iso, dir);
2523 
2524 	__ASSERT_NO_MSG(stream->ep == NULL || (stream->ep != NULL && stream->ep->iso == NULL));
2525 
2526 	stream->qos = qos;
2527 	stream->group = group;
2528 
2529 	/* iso initialized already */
2530 	bt_bap_iso_bind_stream(iso, stream, dir);
2531 	if (stream->ep != NULL) {
2532 		bt_bap_iso_bind_ep(iso, stream->ep);
2533 	}
2534 
2535 	unicast_group_set_iso_stream_param(group, iso, qos, dir);
2536 
2537 	sys_slist_append(&group->streams, &stream->_node);
2538 }
2539 
unicast_group_add_stream_pair(struct bt_bap_unicast_group * group,struct bt_bap_unicast_group_stream_pair_param * param)2540 static int unicast_group_add_stream_pair(struct bt_bap_unicast_group *group,
2541 					 struct bt_bap_unicast_group_stream_pair_param *param)
2542 {
2543 	struct bt_bap_iso *iso;
2544 	int err;
2545 
2546 	__ASSERT_NO_MSG(group != NULL);
2547 	__ASSERT_NO_MSG(param != NULL);
2548 	__ASSERT_NO_MSG(param->rx_param != NULL || param->tx_param != NULL);
2549 
2550 	iso = bt_bap_unicast_client_new_audio_iso();
2551 	if (iso == NULL) {
2552 		return -ENOMEM;
2553 	}
2554 
2555 	err = unicast_group_add_iso(group, iso);
2556 	if (err < 0) {
2557 		bt_bap_iso_unref(iso);
2558 		return err;
2559 	}
2560 
2561 	if (param->rx_param != NULL) {
2562 		unicast_group_add_stream(group, param->rx_param, iso, BT_AUDIO_DIR_SOURCE);
2563 	}
2564 
2565 	if (param->tx_param != NULL) {
2566 		unicast_group_add_stream(group, param->tx_param, iso, BT_AUDIO_DIR_SINK);
2567 	}
2568 
2569 	bt_bap_iso_unref(iso);
2570 
2571 	return 0;
2572 }
2573 
unicast_group_del_stream(struct bt_bap_unicast_group * group,struct bt_bap_stream * stream,enum bt_audio_dir dir)2574 static void unicast_group_del_stream(struct bt_bap_unicast_group *group,
2575 				     struct bt_bap_stream *stream, enum bt_audio_dir dir)
2576 {
2577 	__ASSERT_NO_MSG(group != NULL);
2578 	__ASSERT_NO_MSG(stream != NULL);
2579 
2580 	if (sys_slist_find_and_remove(&group->streams, &stream->_node)) {
2581 		struct bt_bap_ep *ep = stream->ep;
2582 
2583 		if (stream->bap_iso != NULL) {
2584 			bt_bap_iso_unbind_stream(stream->bap_iso, stream, dir);
2585 		}
2586 
2587 		if (ep != NULL && ep->iso != NULL) {
2588 			unicast_group_del_iso(group, ep->iso);
2589 
2590 			bt_bap_iso_unbind_ep(ep->iso, ep);
2591 		}
2592 
2593 		stream->group = NULL;
2594 	}
2595 }
2596 
unicast_group_del_stream_pair(struct bt_bap_unicast_group * group,struct bt_bap_unicast_group_stream_pair_param * param)2597 static void unicast_group_del_stream_pair(struct bt_bap_unicast_group *group,
2598 					  struct bt_bap_unicast_group_stream_pair_param *param)
2599 {
2600 	__ASSERT_NO_MSG(group != NULL);
2601 	__ASSERT_NO_MSG(param != NULL);
2602 	__ASSERT_NO_MSG(param->rx_param != NULL || param->tx_param != NULL);
2603 
2604 	if (param->rx_param != NULL) {
2605 		__ASSERT_NO_MSG(param->rx_param->stream);
2606 		unicast_group_del_stream(group, param->rx_param->stream, BT_AUDIO_DIR_SOURCE);
2607 	}
2608 
2609 	if (param->tx_param != NULL) {
2610 		__ASSERT_NO_MSG(param->tx_param->stream);
2611 		unicast_group_del_stream(group, param->tx_param->stream, BT_AUDIO_DIR_SINK);
2612 	}
2613 }
2614 
unicast_group_alloc(void)2615 static struct bt_bap_unicast_group *unicast_group_alloc(void)
2616 {
2617 	struct bt_bap_unicast_group *group = NULL;
2618 
2619 	for (size_t i = 0U; i < ARRAY_SIZE(unicast_groups); i++) {
2620 		if (!unicast_groups[i].allocated) {
2621 			group = &unicast_groups[i];
2622 
2623 			(void)memset(group, 0, sizeof(*group));
2624 
2625 			group->allocated = true;
2626 			group->index = i;
2627 
2628 			break;
2629 		}
2630 	}
2631 
2632 	return group;
2633 }
2634 
unicast_group_free(struct bt_bap_unicast_group * group)2635 static void unicast_group_free(struct bt_bap_unicast_group *group)
2636 {
2637 	struct bt_bap_stream *stream, *next;
2638 
2639 	__ASSERT_NO_MSG(group != NULL);
2640 
2641 	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&group->streams, stream, next, _node) {
2642 		struct bt_bap_iso *bap_iso = stream->bap_iso;
2643 		struct bt_bap_ep *ep = stream->ep;
2644 
2645 		stream->group = NULL;
2646 		if (bap_iso != NULL) {
2647 			if (bap_iso->rx.stream == stream) {
2648 				bt_bap_iso_unbind_stream(stream->bap_iso, stream,
2649 							 BT_AUDIO_DIR_SOURCE);
2650 			} else if (bap_iso->tx.stream == stream) {
2651 				bt_bap_iso_unbind_stream(stream->bap_iso, stream,
2652 							 BT_AUDIO_DIR_SINK);
2653 			} else {
2654 				__ASSERT_PRINT("stream %p has invalid bap_iso %p", stream, bap_iso);
2655 			}
2656 		}
2657 
2658 		if (ep != NULL && ep->iso != NULL) {
2659 			bt_bap_iso_unbind_ep(ep->iso, ep);
2660 		}
2661 
2662 		sys_slist_remove(&group->streams, NULL, &stream->_node);
2663 	}
2664 
2665 	group->allocated = false;
2666 }
2667 
stream_param_check(const struct bt_bap_unicast_group_stream_param * param)2668 static int stream_param_check(const struct bt_bap_unicast_group_stream_param *param)
2669 {
2670 	CHECKIF(param->stream == NULL)
2671 	{
2672 		LOG_DBG("param->stream is NULL");
2673 		return -EINVAL;
2674 	}
2675 
2676 	CHECKIF(param->qos == NULL)
2677 	{
2678 		LOG_DBG("param->qos is NULL");
2679 		return -EINVAL;
2680 	}
2681 
2682 	if (param->stream != NULL && param->stream->group != NULL) {
2683 		LOG_DBG("stream %p already part of group %p", param->stream, param->stream->group);
2684 		return -EALREADY;
2685 	}
2686 
2687 	CHECKIF(bt_audio_verify_qos(param->qos) != BT_BAP_ASCS_REASON_NONE)
2688 	{
2689 		LOG_DBG("Invalid QoS");
2690 		return -EINVAL;
2691 	}
2692 
2693 	return 0;
2694 }
2695 
stream_pair_param_check(const struct bt_bap_unicast_group_stream_pair_param * param)2696 static int stream_pair_param_check(const struct bt_bap_unicast_group_stream_pair_param *param)
2697 {
2698 	int err;
2699 
2700 	CHECKIF(param->rx_param == NULL && param->tx_param == NULL)
2701 	{
2702 		LOG_DBG("Invalid stream parameters");
2703 		return -EINVAL;
2704 	}
2705 
2706 	if (param->rx_param != NULL) {
2707 		err = stream_param_check(param->rx_param);
2708 		if (err < 0) {
2709 			return err;
2710 		}
2711 	}
2712 
2713 	if (param->tx_param != NULL) {
2714 		err = stream_param_check(param->tx_param);
2715 		if (err < 0) {
2716 			return err;
2717 		}
2718 	}
2719 
2720 	return 0;
2721 }
2722 
2723 /** 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)2724 static bool valid_unicast_group_stream_param(const struct bt_bap_unicast_group *unicast_group,
2725 					     const struct bt_bap_unicast_group_stream_param *param,
2726 					     struct bt_bap_unicast_group_cig_param *cig_param,
2727 					     enum bt_audio_dir dir)
2728 {
2729 	const struct bt_bap_qos_cfg *qos;
2730 
2731 	CHECKIF(param->stream == NULL) {
2732 		LOG_DBG("param->stream is NULL");
2733 		return -EINVAL;
2734 	}
2735 
2736 	CHECKIF(param->qos == NULL) {
2737 		LOG_DBG("param->qos is NULL");
2738 		return -EINVAL;
2739 	}
2740 
2741 	if (param->stream != NULL && param->stream->group != NULL) {
2742 		if (unicast_group != NULL && param->stream->group != unicast_group) {
2743 			LOG_DBG("stream %p not part of group %p (%p)", param->stream, unicast_group,
2744 				param->stream->group);
2745 		} else {
2746 			LOG_DBG("stream %p already part of group %p", param->stream,
2747 				param->stream->group);
2748 		}
2749 		return -EALREADY;
2750 	}
2751 
2752 	CHECKIF(bt_audio_verify_qos(param->qos) != BT_BAP_ASCS_REASON_NONE) {
2753 		LOG_DBG("Invalid QoS");
2754 		return -EINVAL;
2755 	}
2756 
2757 	qos = param->qos;
2758 
2759 	/* If unset we set the interval else we verify that all streams use the same interval and
2760 	 * latency in the same direction, as that is required when creating a CIG
2761 	 */
2762 	if (dir == BT_AUDIO_DIR_SINK) {
2763 		if (cig_param->c_to_p_interval == 0) {
2764 			cig_param->c_to_p_interval = qos->interval;
2765 		} else if (cig_param->c_to_p_interval != qos->interval) {
2766 			return false;
2767 		}
2768 
2769 		if (cig_param->c_to_p_latency == 0) {
2770 			cig_param->c_to_p_latency = qos->latency;
2771 		} else if (cig_param->c_to_p_latency != qos->latency) {
2772 			return false;
2773 		}
2774 	} else {
2775 		if (cig_param->p_to_c_interval == 0) {
2776 			cig_param->p_to_c_interval = qos->interval;
2777 		} else if (cig_param->p_to_c_interval != qos->interval) {
2778 			return false;
2779 		}
2780 
2781 		if (cig_param->p_to_c_latency == 0) {
2782 			cig_param->p_to_c_latency = qos->latency;
2783 		} else if (cig_param->p_to_c_latency != qos->latency) {
2784 			return false;
2785 		}
2786 	}
2787 
2788 	if (cig_param->framing == 0) {
2789 		if (qos->framing == BT_BAP_QOS_CFG_FRAMING_UNFRAMED) {
2790 			cig_param->framing = BT_ISO_FRAMING_UNFRAMED;
2791 		} else if (qos->framing == BT_BAP_QOS_CFG_FRAMING_FRAMED) {
2792 			cig_param->framing = BT_ISO_FRAMING_FRAMED;
2793 		}
2794 	} else if ((qos->framing == BT_BAP_QOS_CFG_FRAMING_UNFRAMED &&
2795 		    cig_param->framing != BT_ISO_FRAMING_UNFRAMED) ||
2796 		   (qos->framing == BT_BAP_QOS_CFG_FRAMING_FRAMED &&
2797 		    cig_param->framing != BT_ISO_FRAMING_FRAMED)) {
2798 		return false;
2799 	}
2800 
2801 	return true;
2802 }
2803 
2804 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)2805 valid_group_stream_pair_param(const struct bt_bap_unicast_group *unicast_group,
2806 			      const struct bt_bap_unicast_group_stream_pair_param *pair_param)
2807 {
2808 	struct bt_bap_unicast_group_cig_param cig_param = {0};
2809 
2810 	CHECKIF(pair_param == NULL) {
2811 		LOG_DBG("pair_param is NULL");
2812 		return false;
2813 	}
2814 
2815 	if (pair_param->rx_param != NULL) {
2816 		if (!valid_unicast_group_stream_param(unicast_group, pair_param->rx_param,
2817 						      &cig_param, BT_AUDIO_DIR_SOURCE)) {
2818 			return false;
2819 		}
2820 	}
2821 
2822 	if (pair_param->tx_param != NULL) {
2823 		if (!valid_unicast_group_stream_param(unicast_group, pair_param->tx_param,
2824 						      &cig_param, BT_AUDIO_DIR_SINK)) {
2825 			return false;
2826 		}
2827 	}
2828 
2829 	return true;
2830 }
2831 
valid_unicast_group_param(struct bt_bap_unicast_group * unicast_group,const struct bt_bap_unicast_group_param * param)2832 static bool valid_unicast_group_param(struct bt_bap_unicast_group *unicast_group,
2833 				      const struct bt_bap_unicast_group_param *param)
2834 {
2835 	CHECKIF(param == NULL) {
2836 		LOG_DBG("streams is NULL");
2837 		return false;
2838 	}
2839 
2840 	CHECKIF(param->params_count > UNICAST_GROUP_STREAM_CNT) {
2841 		LOG_DBG("Too many streams provided: %u/%u", param->params_count,
2842 			UNICAST_GROUP_STREAM_CNT);
2843 		return false;
2844 	}
2845 
2846 	if (unicast_group != NULL) {
2847 		const size_t group_cis_cnt = unicast_group_get_cis_count(unicast_group);
2848 
2849 		if (param->params_count != group_cis_cnt) {
2850 			LOG_DBG("Mismatch between group CIS count (%zu) and params_count (%zu)",
2851 				group_cis_cnt, param->params_count);
2852 
2853 			return false;
2854 		}
2855 	}
2856 
2857 	for (size_t i = 0U; i < param->params_count; i++) {
2858 		if (!valid_group_stream_pair_param(unicast_group, &param->params[i])) {
2859 			return false;
2860 		}
2861 	}
2862 
2863 	return true;
2864 }
2865 
bt_bap_unicast_group_create(struct bt_bap_unicast_group_param * param,struct bt_bap_unicast_group ** out_unicast_group)2866 int bt_bap_unicast_group_create(struct bt_bap_unicast_group_param *param,
2867 				  struct bt_bap_unicast_group **out_unicast_group)
2868 {
2869 	struct bt_bap_unicast_group *unicast_group;
2870 	int err;
2871 
2872 	CHECKIF(out_unicast_group == NULL)
2873 	{
2874 		LOG_DBG("out_unicast_group is NULL");
2875 		return -EINVAL;
2876 	}
2877 	/* Set out_unicast_group to NULL until the source has actually been created */
2878 	*out_unicast_group = NULL;
2879 
2880 	unicast_group = unicast_group_alloc();
2881 	if (unicast_group == NULL) {
2882 		LOG_DBG("Could not allocate any more unicast groups");
2883 		return -ENOMEM;
2884 	}
2885 
2886 	if (!valid_unicast_group_param(NULL, param)) {
2887 		unicast_group_free(unicast_group);
2888 
2889 		return -EINVAL;
2890 	}
2891 
2892 	for (size_t i = 0U; i < param->params_count; i++) {
2893 		struct bt_bap_unicast_group_stream_pair_param *stream_param;
2894 
2895 		stream_param = &param->params[i];
2896 
2897 		unicast_group->cig_param.packing = param->packing;
2898 		IF_ENABLED(CONFIG_BT_ISO_TEST_PARAMS, ({
2899 			unicast_group->cig_param.c_to_p_ft = param->c_to_p_ft;
2900 			unicast_group->cig_param.p_to_c_ft = param->p_to_c_ft;
2901 			unicast_group->cig_param.iso_interval = param->iso_interval;
2902 		}));
2903 
2904 		err = unicast_group_add_stream_pair(unicast_group, stream_param);
2905 		if (err < 0) {
2906 			LOG_DBG("unicast_group_add_stream failed: %d", err);
2907 			unicast_group_free(unicast_group);
2908 
2909 			return err;
2910 		}
2911 	}
2912 
2913 	err = bt_audio_cig_create(unicast_group);
2914 	if (err != 0) {
2915 		LOG_DBG("bt_audio_cig_create failed: %d", err);
2916 		unicast_group_free(unicast_group);
2917 
2918 		return err;
2919 	}
2920 
2921 	*out_unicast_group = unicast_group;
2922 
2923 	return 0;
2924 }
2925 
bt_bap_unicast_group_reconfig(struct bt_bap_unicast_group * unicast_group,const struct bt_bap_unicast_group_param * param)2926 int bt_bap_unicast_group_reconfig(struct bt_bap_unicast_group *unicast_group,
2927 				  const struct bt_bap_unicast_group_param *param)
2928 {
2929 	struct bt_iso_chan_io_qos rx_io_qos_backup[UNICAST_GROUP_STREAM_CNT];
2930 	struct bt_iso_chan_io_qos tx_io_qos_backup[UNICAST_GROUP_STREAM_CNT];
2931 	struct bt_bap_unicast_group_cig_param cig_param_backup;
2932 	struct bt_bap_stream *tmp_stream;
2933 	size_t idx;
2934 	int err;
2935 
2936 	IF_ENABLED(CONFIG_BT_ISO_TEST_PARAMS,
2937 		   (uint8_t num_subevents_backup[UNICAST_GROUP_STREAM_CNT]));
2938 
2939 	CHECKIF(unicast_group == NULL) {
2940 		LOG_DBG("unicast_group is NULL");
2941 		return -EINVAL;
2942 	}
2943 
2944 	if (unicast_group->has_been_connected) {
2945 		LOG_DBG("Cannot modify a unicast_group where a CIS has been connected");
2946 		return -EINVAL;
2947 	}
2948 
2949 	if (!valid_unicast_group_param(unicast_group, param)) {
2950 		return -EINVAL;
2951 	}
2952 
2953 	/* Make backups of the values in case that the reconfigure request is rejected by e.g. the
2954 	 * controller
2955 	 */
2956 	idx = 0U;
2957 	SYS_SLIST_FOR_EACH_CONTAINER(&unicast_group->streams, tmp_stream, _node) {
2958 		memcpy(&rx_io_qos_backup[idx], tmp_stream->bap_iso->chan.qos->rx,
2959 		       sizeof(rx_io_qos_backup[idx]));
2960 		memcpy(&tx_io_qos_backup[idx], tmp_stream->bap_iso->chan.qos->tx,
2961 		       sizeof(tx_io_qos_backup[idx]));
2962 		IF_ENABLED(
2963 			CONFIG_BT_ISO_TEST_PARAMS,
2964 			(num_subevents_backup[idx] = tmp_stream->bap_iso->chan.qos->num_subevents));
2965 		idx++;
2966 	}
2967 	memcpy(&cig_param_backup, &unicast_group->cig_param, sizeof(cig_param_backup));
2968 
2969 	/* Update the stream and group parameters */
2970 	for (size_t i = 0U; i < param->params_count; i++) {
2971 		struct bt_bap_unicast_group_stream_pair_param *stream_param = &param->params[i];
2972 		struct bt_bap_unicast_group_stream_param *rx_param = stream_param->rx_param;
2973 		struct bt_bap_unicast_group_stream_param *tx_param = stream_param->tx_param;
2974 
2975 		if (rx_param != NULL) {
2976 			unicast_group_set_iso_stream_param(unicast_group, rx_param->stream->bap_iso,
2977 							   rx_param->qos, BT_AUDIO_DIR_SOURCE);
2978 		}
2979 
2980 		if (tx_param != NULL) {
2981 			unicast_group_set_iso_stream_param(unicast_group, tx_param->stream->bap_iso,
2982 							   tx_param->qos, BT_AUDIO_DIR_SOURCE);
2983 		}
2984 	}
2985 
2986 	/* Reconfigure the CIG based on the above new values */
2987 	err = bt_audio_cig_reconfigure(unicast_group);
2988 	if (err != 0) {
2989 		LOG_DBG("bt_audio_cig_reconfigure failed: %d", err);
2990 
2991 		/* Revert any changes above */
2992 		memcpy(&unicast_group->cig_param, &cig_param_backup, sizeof(cig_param_backup));
2993 		idx = 0U;
2994 		SYS_SLIST_FOR_EACH_CONTAINER(&unicast_group->streams, tmp_stream, _node) {
2995 			memcpy(tmp_stream->bap_iso->chan.qos->rx, &rx_io_qos_backup[idx],
2996 			       sizeof(rx_io_qos_backup[idx]));
2997 			memcpy(tmp_stream->bap_iso->chan.qos->tx, &tx_io_qos_backup[idx],
2998 			       sizeof(tx_io_qos_backup[idx]));
2999 			IF_ENABLED(CONFIG_BT_ISO_TEST_PARAMS,
3000 				   (tmp_stream->bap_iso->chan.qos->num_subevents =
3001 					    num_subevents_backup[idx]));
3002 			idx++;
3003 		}
3004 
3005 		return err;
3006 	}
3007 
3008 	return 0;
3009 }
3010 
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)3011 int bt_bap_unicast_group_add_streams(struct bt_bap_unicast_group *unicast_group,
3012 				       struct bt_bap_unicast_group_stream_pair_param params[],
3013 				       size_t num_param)
3014 {
3015 	struct bt_bap_stream *tmp_stream;
3016 	size_t total_stream_cnt;
3017 	struct bt_iso_cig *cig;
3018 	size_t num_added;
3019 	int err;
3020 
3021 	CHECKIF(unicast_group == NULL)
3022 	{
3023 		LOG_DBG("unicast_group is NULL");
3024 		return -EINVAL;
3025 	}
3026 
3027 	if (unicast_group->has_been_connected) {
3028 		LOG_DBG("Cannot modify a unicast_group where a CIS has been connected");
3029 		return -EINVAL;
3030 	}
3031 
3032 	CHECKIF(params == NULL)
3033 	{
3034 		LOG_DBG("params is NULL");
3035 		return -EINVAL;
3036 	}
3037 
3038 	CHECKIF(num_param == 0)
3039 	{
3040 		LOG_DBG("num_param is 0");
3041 		return -EINVAL;
3042 	}
3043 
3044 	total_stream_cnt = num_param;
3045 	SYS_SLIST_FOR_EACH_CONTAINER(&unicast_group->streams, tmp_stream, _node) {
3046 		total_stream_cnt++;
3047 	}
3048 
3049 	if (total_stream_cnt > UNICAST_GROUP_STREAM_CNT) {
3050 		LOG_DBG("Too many streams provided: %u/%u", total_stream_cnt,
3051 			UNICAST_GROUP_STREAM_CNT);
3052 		return -EINVAL;
3053 	}
3054 
3055 	for (size_t i = 0U; i < num_param; i++) {
3056 		if (!valid_group_stream_pair_param(unicast_group, &params[i])) {
3057 			return -EINVAL;
3058 		}
3059 	}
3060 
3061 	/* We can just check the CIG state to see if any streams have started as
3062 	 * that would start the ISO connection procedure
3063 	 */
3064 	cig = unicast_group->cig;
3065 	if (cig != NULL && cig->state != BT_ISO_CIG_STATE_CONFIGURED) {
3066 		LOG_DBG("At least one unicast group stream is started");
3067 		return -EBADMSG;
3068 	}
3069 
3070 	for (num_added = 0U; num_added < num_param; num_added++) {
3071 		struct bt_bap_unicast_group_stream_pair_param *stream_param;
3072 
3073 		stream_param = &params[num_added];
3074 
3075 		err = stream_pair_param_check(stream_param);
3076 		if (err < 0) {
3077 			return err;
3078 		}
3079 
3080 		err = unicast_group_add_stream_pair(unicast_group, stream_param);
3081 		if (err < 0) {
3082 			LOG_DBG("unicast_group_add_stream failed: %d", err);
3083 			goto fail;
3084 		}
3085 	}
3086 
3087 	err = bt_audio_cig_reconfigure(unicast_group);
3088 	if (err != 0) {
3089 		LOG_DBG("bt_audio_cig_reconfigure failed: %d", err);
3090 		goto fail;
3091 	}
3092 
3093 	return 0;
3094 
3095 fail:
3096 	/* Restore group by removing the newly added streams */
3097 	while (num_added--) {
3098 		unicast_group_del_stream_pair(unicast_group, &params[num_added]);
3099 	}
3100 
3101 	return err;
3102 }
3103 
bt_bap_unicast_group_delete(struct bt_bap_unicast_group * unicast_group)3104 int bt_bap_unicast_group_delete(struct bt_bap_unicast_group *unicast_group)
3105 {
3106 	struct bt_bap_stream *stream;
3107 
3108 	CHECKIF(unicast_group == NULL)
3109 	{
3110 		LOG_DBG("unicast_group is NULL");
3111 		return -EINVAL;
3112 	}
3113 
3114 	SYS_SLIST_FOR_EACH_CONTAINER(&unicast_group->streams, stream, _node) {
3115 		/* If a stream has an endpoint, it is not ready to be removed
3116 		 * from a group, as it is not in an idle state
3117 		 */
3118 		if (stream->ep != NULL) {
3119 			LOG_DBG("stream %p is not released", stream);
3120 			return -EINVAL;
3121 		}
3122 	}
3123 
3124 	if (unicast_group->cig != NULL) {
3125 		const int err = unicast_client_cig_terminate(unicast_group);
3126 
3127 		if (err != 0) {
3128 			LOG_DBG("unicast_client_cig_terminate failed with err %d", err);
3129 
3130 			return err;
3131 		}
3132 	}
3133 
3134 	unicast_group_free(unicast_group);
3135 
3136 	return 0;
3137 }
3138 
bt_bap_unicast_client_config(struct bt_bap_stream * stream,const struct bt_audio_codec_cfg * codec_cfg)3139 int bt_bap_unicast_client_config(struct bt_bap_stream *stream,
3140 				 const struct bt_audio_codec_cfg *codec_cfg)
3141 {
3142 	struct bt_bap_ep *ep = stream->ep;
3143 	struct bt_ascs_config_op *op;
3144 	struct net_buf_simple *buf;
3145 	int err;
3146 
3147 	LOG_DBG("stream %p", stream);
3148 
3149 	if (stream->conn == NULL) {
3150 		LOG_DBG("Stream %p does not have a connection", stream);
3151 
3152 		return -ENOTCONN;
3153 	}
3154 
3155 	buf = bt_bap_unicast_client_ep_create_pdu(stream->conn, BT_ASCS_CONFIG_OP);
3156 	if (buf == NULL) {
3157 		LOG_DBG("Could not create PDU");
3158 		return -EBUSY;
3159 	}
3160 
3161 	op = net_buf_simple_add(buf, sizeof(*op));
3162 	op->num_ases = 0x01;
3163 
3164 	err = unicast_client_ep_config(ep, buf, codec_cfg);
3165 	if (err != 0) {
3166 		return err;
3167 	}
3168 
3169 	err = bt_bap_unicast_client_ep_send(stream->conn, ep, buf);
3170 	if (err != 0) {
3171 		return err;
3172 	}
3173 
3174 	return 0;
3175 }
3176 
bt_bap_unicast_client_qos(struct bt_conn * conn,struct bt_bap_unicast_group * group)3177 int bt_bap_unicast_client_qos(struct bt_conn *conn, struct bt_bap_unicast_group *group)
3178 {
3179 	struct bt_bap_stream *stream;
3180 	struct bt_ascs_config_op *op;
3181 	struct net_buf_simple *buf;
3182 	struct bt_bap_ep *ep;
3183 	bool conn_stream_found;
3184 	int err;
3185 
3186 	if (conn == NULL) {
3187 		LOG_DBG("conn is NULL");
3188 
3189 		return -ENOTCONN;
3190 	}
3191 
3192 	/* Used to determine if a stream for the supplied connection pointer
3193 	 * was actually found
3194 	 */
3195 	conn_stream_found = false;
3196 
3197 	/* Validate streams before starting the QoS execution */
3198 	SYS_SLIST_FOR_EACH_CONTAINER(&group->streams, stream, _node) {
3199 		if (stream->conn != conn) {
3200 			/* Channel not part of this ACL, skip */
3201 			continue;
3202 		}
3203 		conn_stream_found = true;
3204 
3205 		ep = stream->ep;
3206 		if (ep == NULL) {
3207 			LOG_DBG("stream->ep is NULL");
3208 			return -EINVAL;
3209 		}
3210 
3211 		/* Can only be done if all the streams are in the codec
3212 		 * configured state or the QoS configured state
3213 		 */
3214 		switch (ep->status.state) {
3215 		case BT_BAP_EP_STATE_CODEC_CONFIGURED:
3216 		case BT_BAP_EP_STATE_QOS_CONFIGURED:
3217 			break;
3218 		default:
3219 			LOG_DBG("Invalid state: %s", bt_bap_ep_state_str(stream->ep->status.state));
3220 			return -EINVAL;
3221 		}
3222 
3223 		if (bt_bap_stream_verify_qos(stream, stream->qos) != BT_BAP_ASCS_REASON_NONE) {
3224 			return -EINVAL;
3225 		}
3226 
3227 		/* Verify ep->dir */
3228 		switch (ep->dir) {
3229 		case BT_AUDIO_DIR_SINK:
3230 		case BT_AUDIO_DIR_SOURCE:
3231 			break;
3232 		default:
3233 			__ASSERT(false, "invalid endpoint dir: %u", ep->dir);
3234 			return -EINVAL;
3235 		}
3236 
3237 		if (stream->bap_iso == NULL) {
3238 			/* This can only happen if the stream was somehow added
3239 			 * to a group without the bap_iso being bound to it
3240 			 */
3241 			LOG_ERR("Could not find bap_iso for stream %p", stream);
3242 			return -EINVAL;
3243 		}
3244 	}
3245 
3246 	if (!conn_stream_found) {
3247 		LOG_DBG("No streams in the group %p for conn %p", group, conn);
3248 		return -EINVAL;
3249 	}
3250 
3251 	/* Generate the control point write */
3252 	buf = bt_bap_unicast_client_ep_create_pdu(conn, BT_ASCS_QOS_OP);
3253 	if (buf == NULL) {
3254 		LOG_DBG("Could not create PDU");
3255 		return -EBUSY;
3256 	}
3257 
3258 	op = net_buf_simple_add(buf, sizeof(*op));
3259 
3260 	(void)memset(op, 0, sizeof(*op));
3261 	ep = NULL; /* Needed to find the control point handle */
3262 	SYS_SLIST_FOR_EACH_CONTAINER(&group->streams, stream, _node) {
3263 		if (stream->conn != conn) {
3264 			/* Channel not part of this ACL, skip */
3265 			continue;
3266 		}
3267 
3268 		op->num_ases++;
3269 
3270 		if (stream->ep->iso == NULL) {
3271 			/* Not yet bound with the bap_iso */
3272 			bt_bap_iso_bind_ep(stream->bap_iso, stream->ep);
3273 		}
3274 
3275 		err = bt_bap_unicast_client_ep_qos(stream->ep, buf, stream->qos);
3276 		if (err != 0) {
3277 			audio_stream_qos_cleanup(conn, group);
3278 
3279 			return err;
3280 		}
3281 
3282 		if (ep == NULL) {
3283 			ep = stream->ep;
3284 		}
3285 	}
3286 
3287 	err = bt_bap_unicast_client_ep_send(conn, ep, buf);
3288 	if (err != 0) {
3289 		LOG_DBG("Could not send config QoS: %d", err);
3290 		audio_stream_qos_cleanup(conn, group);
3291 
3292 		return err;
3293 	}
3294 
3295 	return 0;
3296 }
3297 
bt_bap_unicast_client_enable(struct bt_bap_stream * stream,const uint8_t meta[],size_t meta_len)3298 int bt_bap_unicast_client_enable(struct bt_bap_stream *stream, const uint8_t meta[],
3299 				 size_t meta_len)
3300 {
3301 	struct bt_bap_ep *ep = stream->ep;
3302 	struct net_buf_simple *buf;
3303 	struct bt_ascs_enable_op *req;
3304 	int err;
3305 
3306 	LOG_DBG("stream %p", stream);
3307 
3308 	if (stream->conn == NULL) {
3309 		LOG_DBG("Stream %p does not have a connection", stream);
3310 
3311 		return -ENOTCONN;
3312 	}
3313 
3314 	buf = bt_bap_unicast_client_ep_create_pdu(stream->conn, BT_ASCS_ENABLE_OP);
3315 	if (buf == NULL) {
3316 		LOG_DBG("Could not create PDU");
3317 		return -EBUSY;
3318 	}
3319 
3320 	req = net_buf_simple_add(buf, sizeof(*req));
3321 	req->num_ases = 0x01;
3322 
3323 	err = unicast_client_ep_enable(ep, buf, meta, meta_len);
3324 	if (err) {
3325 		return err;
3326 	}
3327 
3328 	return bt_bap_unicast_client_ep_send(stream->conn, ep, buf);
3329 }
3330 
bt_bap_unicast_client_metadata(struct bt_bap_stream * stream,const uint8_t meta[],size_t meta_len)3331 int bt_bap_unicast_client_metadata(struct bt_bap_stream *stream, const uint8_t meta[],
3332 				   size_t meta_len)
3333 {
3334 	struct bt_bap_ep *ep = stream->ep;
3335 	struct net_buf_simple *buf;
3336 	struct bt_ascs_enable_op *req;
3337 	int err;
3338 
3339 	LOG_DBG("stream %p", stream);
3340 
3341 	if (stream->conn == NULL) {
3342 		LOG_DBG("Stream %p does not have a connection", stream);
3343 
3344 		return -ENOTCONN;
3345 	}
3346 
3347 	buf = bt_bap_unicast_client_ep_create_pdu(stream->conn, BT_ASCS_METADATA_OP);
3348 	if (buf == NULL) {
3349 		LOG_DBG("Could not create PDU");
3350 		return -EBUSY;
3351 	}
3352 
3353 	req = net_buf_simple_add(buf, sizeof(*req));
3354 	req->num_ases = 0x01;
3355 
3356 	err = unicast_client_ep_metadata(ep, buf, meta, meta_len);
3357 	if (err) {
3358 		return err;
3359 	}
3360 
3361 	return bt_bap_unicast_client_ep_send(stream->conn, ep, buf);
3362 }
3363 
bt_bap_unicast_client_connect(struct bt_bap_stream * stream)3364 int bt_bap_unicast_client_connect(struct bt_bap_stream *stream)
3365 {
3366 	struct bt_iso_connect_param param;
3367 	struct bt_iso_chan *iso_chan;
3368 	enum bt_iso_state iso_state;
3369 
3370 	LOG_DBG("stream %p", stream);
3371 
3372 	if (stream == NULL) {
3373 		LOG_DBG("stream is NULL");
3374 
3375 		return -EINVAL;
3376 	}
3377 
3378 	iso_chan = bt_bap_stream_iso_chan_get(stream);
3379 	if (iso_chan == NULL) {
3380 		LOG_DBG("iso_chan is NULL");
3381 
3382 		return -EINVAL;
3383 	}
3384 
3385 	LOG_DBG("stream %p iso %p", stream, iso_chan);
3386 
3387 	param.acl = stream->conn;
3388 	param.iso_chan = iso_chan;
3389 
3390 	iso_state = iso_chan->state;
3391 	if (iso_state == BT_ISO_STATE_DISCONNECTED) {
3392 		const int err = bt_iso_chan_connect(&param, 1);
3393 
3394 		if (err == 0 || err == -EBUSY) { /* Expected / known return values */
3395 			return err;
3396 		}
3397 
3398 		/* unknown return value*/
3399 		LOG_DBG("Unexpected err %d from bt_iso_chan_connect", err);
3400 
3401 		return -ENOEXEC;
3402 	} else if (iso_state == BT_ISO_STATE_CONNECTING || iso_state == BT_ISO_STATE_CONNECTED) {
3403 		LOG_DBG("iso_chan %p already connecting or connected (%u)", iso_chan, iso_state);
3404 
3405 		return -EALREADY;
3406 	}
3407 
3408 	LOG_DBG("iso_chan %p in invalid state state (%u), cannot connect", iso_chan, iso_state);
3409 
3410 	return -EBADMSG;
3411 }
3412 
bt_bap_unicast_client_start(struct bt_bap_stream * stream)3413 int bt_bap_unicast_client_start(struct bt_bap_stream *stream)
3414 {
3415 	struct bt_bap_ep *ep = stream->ep;
3416 	int err;
3417 
3418 	LOG_DBG("stream %p", stream);
3419 
3420 	if (stream->conn == NULL) {
3421 		LOG_DBG("Stream %p does not have a connection", stream);
3422 
3423 		return -ENOTCONN;
3424 	}
3425 
3426 	/* As per the ASCS spec, only source streams can be started by the client */
3427 	if (ep->dir == BT_AUDIO_DIR_SINK) {
3428 		LOG_DBG("Stream %p is not a source stream", stream);
3429 
3430 		return -EINVAL;
3431 	}
3432 
3433 	ep->receiver_ready = true;
3434 
3435 	err = unicast_client_send_start(ep);
3436 	if (err != 0) {
3437 		LOG_DBG("Failed to send start: %d", err);
3438 
3439 		/* TBD: Should we release the stream then? */
3440 		ep->receiver_ready = false;
3441 
3442 		return err;
3443 	}
3444 
3445 	return 0;
3446 }
3447 
bt_bap_unicast_client_disable(struct bt_bap_stream * stream)3448 int bt_bap_unicast_client_disable(struct bt_bap_stream *stream)
3449 {
3450 	struct bt_bap_ep *ep = stream->ep;
3451 	struct net_buf_simple *buf;
3452 	struct bt_ascs_disable_op *req;
3453 	int err;
3454 
3455 	LOG_DBG("stream %p", stream);
3456 
3457 	if (stream->conn == NULL) {
3458 		LOG_DBG("Stream %p does not have a connection", stream);
3459 
3460 		return -ENOTCONN;
3461 	}
3462 
3463 	buf = bt_bap_unicast_client_ep_create_pdu(stream->conn, BT_ASCS_DISABLE_OP);
3464 	if (buf == NULL) {
3465 		LOG_DBG("Could not create PDU");
3466 		return -EBUSY;
3467 	}
3468 
3469 	req = net_buf_simple_add(buf, sizeof(*req));
3470 	req->num_ases = 0x01;
3471 
3472 	err = unicast_client_ep_disable(ep, buf);
3473 	if (err) {
3474 		return err;
3475 	}
3476 
3477 	return bt_bap_unicast_client_ep_send(stream->conn, ep, buf);
3478 }
3479 
bt_bap_unicast_client_stop(struct bt_bap_stream * stream)3480 int bt_bap_unicast_client_stop(struct bt_bap_stream *stream)
3481 {
3482 	struct bt_bap_ep *ep = stream->ep;
3483 	enum bt_iso_state iso_state;
3484 	struct net_buf_simple *buf;
3485 	struct bt_ascs_start_op *req;
3486 	int err;
3487 
3488 	LOG_DBG("stream %p", stream);
3489 
3490 	if (stream->conn == NULL) {
3491 		LOG_DBG("Stream %p does not have a connection", stream);
3492 
3493 		return -ENOTCONN;
3494 	}
3495 
3496 	/* ASCS_v1.0 3.2 ASE state machine transitions
3497 	 *
3498 	 * If the server detects link loss of a CIS for an ASE in the Streaming state or the
3499 	 * Disabling state, the server shall immediately transition that ASE to the QoS Configured
3500 	 * state.
3501 	 *
3502 	 * This effectively means that if an ASE no longer has a connected CIS, the server shall
3503 	 * bring it to the QoS Configured state. That means that we, as a unicast client, should not
3504 	 * attempt to stop it
3505 	 */
3506 	if (ep->iso == NULL) {
3507 		LOG_DBG("Stream endpoint does not have a CIS, server will stop the ASE");
3508 		return -EALREADY;
3509 	}
3510 
3511 	iso_state = ep->iso->chan.state;
3512 	if (iso_state != BT_ISO_STATE_CONNECTED && iso_state != BT_ISO_STATE_CONNECTING) {
3513 		LOG_DBG("Stream endpoint CIS is not connected, server will stop the ASE");
3514 		return -EALREADY;
3515 	}
3516 
3517 	buf = bt_bap_unicast_client_ep_create_pdu(stream->conn, BT_ASCS_STOP_OP);
3518 	if (buf == NULL) {
3519 		LOG_DBG("Could not create PDU");
3520 		return -EBUSY;
3521 	}
3522 
3523 	req = net_buf_simple_add(buf, sizeof(*req));
3524 	req->num_ases = 0x00;
3525 
3526 	/* When initiated by the client, valid only if Direction field
3527 	 * parameter value = 0x02 (Server is Audio Source)
3528 	 */
3529 	if (ep->dir == BT_AUDIO_DIR_SOURCE) {
3530 		err = unicast_client_ep_stop(ep, buf);
3531 		if (err) {
3532 			return err;
3533 		}
3534 		req->num_ases++;
3535 
3536 		err = bt_bap_unicast_client_ep_send(stream->conn, ep, buf);
3537 		if (err != 0) {
3538 			/* Return expected error directly */
3539 			if (err == -ENOTCONN || err == -ENOMEM) {
3540 				return err;
3541 			}
3542 
3543 			LOG_DBG("bt_bap_unicast_client_ep_send failed with unexpected error %d",
3544 				err);
3545 
3546 			return -ENOEXEC;
3547 		}
3548 	}
3549 
3550 	return 0;
3551 }
3552 
bt_bap_unicast_client_release(struct bt_bap_stream * stream)3553 int bt_bap_unicast_client_release(struct bt_bap_stream *stream)
3554 {
3555 	struct bt_bap_unicast_client_ep *client_ep;
3556 	struct bt_bap_ep *ep = stream->ep;
3557 	struct net_buf_simple *buf;
3558 	struct bt_ascs_disable_op *req;
3559 	int err, len;
3560 
3561 	LOG_DBG("stream %p", stream);
3562 
3563 	if (stream->conn == NULL) {
3564 		LOG_DBG("Stream %p does not have a connection", stream);
3565 
3566 		return -ENOTCONN;
3567 	}
3568 
3569 	buf = bt_bap_unicast_client_ep_create_pdu(stream->conn, BT_ASCS_RELEASE_OP);
3570 	if (buf == NULL) {
3571 		LOG_DBG("Could not create PDU");
3572 		return -EBUSY;
3573 	}
3574 
3575 	req = net_buf_simple_add(buf, sizeof(*req));
3576 	req->num_ases = 0x01;
3577 	len = buf->len;
3578 
3579 	/* Only attempt to release if not IDLE already */
3580 	if (stream->ep->status.state == BT_BAP_EP_STATE_IDLE) {
3581 		bt_bap_stream_reset(stream);
3582 	} else {
3583 		err = unicast_client_ep_release(ep, buf);
3584 		if (err) {
3585 			return err;
3586 		}
3587 	}
3588 
3589 	/* Check if anything needs to be send */
3590 	if (len == buf->len) {
3591 		return 0;
3592 	}
3593 
3594 	err = bt_bap_unicast_client_ep_send(stream->conn, ep, buf);
3595 	if (err != 0) {
3596 		return err;
3597 	}
3598 
3599 	client_ep = CONTAINER_OF(ep, struct bt_bap_unicast_client_ep, ep);
3600 	client_ep->release_requested = true;
3601 
3602 	return 0;
3603 }
3604 
unicast_client_cp_discover_func(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * discover)3605 static uint8_t unicast_client_cp_discover_func(struct bt_conn *conn,
3606 					       const struct bt_gatt_attr *attr,
3607 					       struct bt_gatt_discover_params *discover)
3608 {
3609 	struct bt_gatt_chrc *chrc;
3610 	uint16_t value_handle;
3611 
3612 	if (!attr) {
3613 		LOG_ERR("Unable to find ASE Control Point");
3614 
3615 		unicast_client_discover_complete(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND);
3616 		return BT_GATT_ITER_STOP;
3617 	}
3618 
3619 	chrc = attr->user_data;
3620 	value_handle = chrc->value_handle;
3621 	memset(discover, 0, sizeof(*discover));
3622 
3623 	LOG_DBG("conn %p attr %p handle 0x%04x", conn, attr, value_handle);
3624 
3625 	unicast_client_ep_set_cp(conn, value_handle);
3626 
3627 	return BT_GATT_ITER_STOP;
3628 }
3629 
unicast_client_ase_cp_discover(struct bt_conn * conn)3630 static int unicast_client_ase_cp_discover(struct bt_conn *conn)
3631 {
3632 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
3633 
3634 	LOG_DBG("conn %p", conn);
3635 
3636 	client->disc_params.uuid = cp_uuid;
3637 	client->disc_params.func = unicast_client_cp_discover_func;
3638 	client->disc_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
3639 	client->disc_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
3640 	client->disc_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
3641 
3642 	return bt_gatt_discover(conn, &client->disc_params);
3643 }
3644 
unicast_client_ase_read_func(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * read,const void * data,uint16_t length)3645 static uint8_t unicast_client_ase_read_func(struct bt_conn *conn, uint8_t err,
3646 					    struct bt_gatt_read_params *read, const void *data,
3647 					    uint16_t length)
3648 {
3649 	uint16_t handle = read->single.handle;
3650 	struct unicast_client *client;
3651 	struct net_buf_simple *buf;
3652 	struct bt_bap_ep *ep;
3653 	int cb_err;
3654 
3655 	LOG_DBG("conn %p err 0x%02x len %u", conn, err, length);
3656 
3657 	if (err) {
3658 		cb_err = err;
3659 		goto fail;
3660 	}
3661 
3662 	LOG_DBG("handle 0x%04x", handle);
3663 
3664 	client = &uni_cli_insts[bt_conn_index(conn)];
3665 	buf = &client->net_buf;
3666 
3667 	if (data != NULL) {
3668 		if (net_buf_simple_tailroom(buf) < length) {
3669 			LOG_DBG("Buffer full, invalid server response of size %u",
3670 				length + client->net_buf.len);
3671 
3672 			cb_err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
3673 
3674 			goto fail;
3675 		}
3676 
3677 		/* store data*/
3678 		net_buf_simple_add_mem(buf, data, length);
3679 
3680 		return BT_GATT_ITER_CONTINUE;
3681 	}
3682 
3683 	memset(read, 0, sizeof(*read));
3684 
3685 	if (buf->len < sizeof(struct bt_ascs_ase_status)) {
3686 		LOG_DBG("Read response too small (%u)", buf->len);
3687 
3688 		cb_err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
3689 
3690 		goto fail;
3691 	}
3692 
3693 	ep = unicast_client_ep_get(conn, client->dir, handle);
3694 	if (!ep) {
3695 		/* The BAP spec declares that the unicast client shall subscribe to all ASEs.
3696 		 * In case that we cannot support this due to memory restrictions, we should
3697 		 * consider the discovery procedure as failing.
3698 		 */
3699 		LOG_WRN("No space left to parse ASE");
3700 		cb_err = -ENOMEM;
3701 
3702 		goto fail;
3703 	}
3704 
3705 	unicast_client_ep_set_status(ep, buf);
3706 	cb_err = unicast_client_ep_subscribe(conn, ep);
3707 	if (cb_err != 0) {
3708 		LOG_DBG("Failed to subscribe to ep %p: %d", ep, cb_err);
3709 		goto fail;
3710 	}
3711 
3712 	reset_att_buf(client);
3713 
3714 	unicast_client_notify_endpoint(conn, ep);
3715 
3716 	cb_err = unicast_client_ase_discover(conn, handle);
3717 	if (cb_err != 0) {
3718 		LOG_DBG("Failed to read ASE: %d", cb_err);
3719 		goto fail;
3720 	}
3721 
3722 	return BT_GATT_ITER_STOP;
3723 
3724 fail:
3725 	unicast_client_discover_complete(conn, cb_err);
3726 	return BT_GATT_ITER_STOP;
3727 }
3728 
any_ases_found(const struct unicast_client * client)3729 static bool any_ases_found(const struct unicast_client *client)
3730 {
3731 	/* We always allocate ases from 0 to X, so to verify if any sink or source ASEs have been
3732 	 * found we can just check the first index
3733 	 */
3734 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
3735 	if (client->dir == BT_AUDIO_DIR_SINK && client->snks[0].handle == BAP_HANDLE_UNUSED) {
3736 		LOG_DBG("No sink ASEs found");
3737 		return false;
3738 	}
3739 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
3740 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
3741 	if (client->dir == BT_AUDIO_DIR_SOURCE && client->srcs[0].handle == BAP_HANDLE_UNUSED) {
3742 		LOG_DBG("No source ASEs found");
3743 		return false;
3744 	}
3745 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0 */
3746 
3747 	return true;
3748 }
3749 
unicast_client_ase_discover_cb(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * discover)3750 static uint8_t unicast_client_ase_discover_cb(struct bt_conn *conn,
3751 					      const struct bt_gatt_attr *attr,
3752 					      struct bt_gatt_discover_params *discover)
3753 {
3754 	struct unicast_client *client;
3755 	struct bt_gatt_chrc *chrc;
3756 	uint16_t value_handle;
3757 	int err;
3758 
3759 	client = &uni_cli_insts[bt_conn_index(conn)];
3760 
3761 	if (attr == NULL) {
3762 		if (!any_ases_found(client)) {
3763 			unicast_client_discover_complete(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND);
3764 		} else {
3765 			err = unicast_client_ase_cp_discover(conn);
3766 			if (err != 0) {
3767 				LOG_ERR("Unable to discover ASE Control Point");
3768 
3769 				unicast_client_discover_complete(conn, err);
3770 			}
3771 		}
3772 
3773 		return BT_GATT_ITER_STOP;
3774 	}
3775 
3776 	chrc = attr->user_data;
3777 	value_handle = chrc->value_handle;
3778 	memset(discover, 0, sizeof(*discover));
3779 
3780 	LOG_DBG("conn %p attr %p handle 0x%04x dir %s", conn, attr, value_handle,
3781 		bt_audio_dir_str(client->dir));
3782 
3783 	client->read_params.func = unicast_client_ase_read_func;
3784 	client->read_params.handle_count = 1U;
3785 	client->read_params.single.handle = value_handle;
3786 	client->read_params.single.offset = 0U;
3787 
3788 	err = bt_gatt_read(conn, &client->read_params);
3789 	if (err != 0) {
3790 		LOG_DBG("Failed to read PAC records: %d", err);
3791 
3792 		unicast_client_discover_complete(conn, err);
3793 	}
3794 
3795 	return BT_GATT_ITER_STOP;
3796 }
3797 
unicast_client_ase_discover(struct bt_conn * conn,uint16_t start_handle)3798 static int unicast_client_ase_discover(struct bt_conn *conn, uint16_t start_handle)
3799 {
3800 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
3801 
3802 	LOG_DBG("conn %p ", conn);
3803 
3804 	if (client->dir == BT_AUDIO_DIR_SINK) {
3805 		client->disc_params.uuid = ase_snk_uuid;
3806 	} else if (client->dir == BT_AUDIO_DIR_SOURCE) {
3807 		client->disc_params.uuid = ase_src_uuid;
3808 	} else {
3809 		return -EINVAL;
3810 	}
3811 
3812 	client->disc_params.func = unicast_client_ase_discover_cb;
3813 	client->disc_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
3814 	client->disc_params.start_handle = start_handle;
3815 	client->disc_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
3816 
3817 	return bt_gatt_discover(conn, &client->disc_params);
3818 }
3819 
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)3820 static uint8_t unicast_client_pacs_avail_ctx_read_func(struct bt_conn *conn, uint8_t err,
3821 						       struct bt_gatt_read_params *read,
3822 						       const void *data, uint16_t length)
3823 {
3824 	struct bt_pacs_context context;
3825 	struct net_buf_simple buf;
3826 	int cb_err;
3827 
3828 	memset(read, 0, sizeof(*read));
3829 
3830 	LOG_DBG("conn %p err 0x%02x len %u", conn, err, length);
3831 
3832 	if (err || data == NULL || length != sizeof(context)) {
3833 		LOG_DBG("Could not read available context: %d, %p, %u", err, data, length);
3834 
3835 		if (err == BT_ATT_ERR_SUCCESS) {
3836 			err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
3837 		}
3838 
3839 		unicast_client_discover_complete(conn, err);
3840 
3841 		return BT_GATT_ITER_STOP;
3842 	}
3843 
3844 	net_buf_simple_init_with_data(&buf, (void *)data, length);
3845 	context.snk = net_buf_simple_pull_le16(&buf);
3846 	context.src = net_buf_simple_pull_le16(&buf);
3847 
3848 	LOG_DBG("sink context %u, source context %u", context.snk, context.src);
3849 
3850 	unicast_client_notify_available_contexts(conn, context.snk, context.src);
3851 
3852 	/* Read ASE instances */
3853 	cb_err = unicast_client_ase_discover(conn, BT_ATT_FIRST_ATTRIBUTE_HANDLE);
3854 	if (cb_err != 0) {
3855 		LOG_ERR("Unable to read ASE: %d", cb_err);
3856 
3857 		unicast_client_discover_complete(conn, cb_err);
3858 	}
3859 
3860 	return BT_GATT_ITER_STOP;
3861 }
3862 
unicast_client_pacs_avail_ctx_notify_cb(struct bt_conn * conn,struct bt_gatt_subscribe_params * params,const void * data,uint16_t length)3863 static uint8_t unicast_client_pacs_avail_ctx_notify_cb(struct bt_conn *conn,
3864 						       struct bt_gatt_subscribe_params *params,
3865 						       const void *data, uint16_t length)
3866 {
3867 	struct bt_pacs_context context;
3868 	struct net_buf_simple buf;
3869 
3870 	LOG_DBG("conn %p len %u", conn, length);
3871 
3872 	if (!data) {
3873 		LOG_DBG("Unsubscribed");
3874 		params->value_handle = BAP_HANDLE_UNUSED;
3875 		return BT_GATT_ITER_STOP;
3876 	}
3877 
3878 	net_buf_simple_init_with_data(&buf, (void *)data, length);
3879 
3880 	if (buf.len != sizeof(context)) {
3881 		LOG_ERR("Avail_ctx notification incorrect size: %u", length);
3882 		return BT_GATT_ITER_STOP;
3883 	}
3884 
3885 	net_buf_simple_init_with_data(&buf, (void *)data, length);
3886 	context.snk = net_buf_simple_pull_le16(&buf);
3887 	context.src = net_buf_simple_pull_le16(&buf);
3888 
3889 	LOG_DBG("sink context %u, source context %u", context.snk, context.src);
3890 
3891 	unicast_client_notify_available_contexts(conn, context.snk, context.src);
3892 
3893 	return BT_GATT_ITER_CONTINUE;
3894 }
3895 
unicast_client_pacs_avail_ctx_read(struct bt_conn * conn,uint16_t handle)3896 static int unicast_client_pacs_avail_ctx_read(struct bt_conn *conn, uint16_t handle)
3897 {
3898 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
3899 
3900 	LOG_DBG("conn %p", conn);
3901 
3902 	client->read_params.func = unicast_client_pacs_avail_ctx_read_func;
3903 	client->read_params.handle_count = 1U;
3904 	client->read_params.single.handle = handle;
3905 	client->read_params.single.offset = 0U;
3906 
3907 	return bt_gatt_read(conn, &client->read_params);
3908 }
3909 
unicast_client_pacs_avail_ctx_discover_cb(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * discover)3910 static uint8_t unicast_client_pacs_avail_ctx_discover_cb(struct bt_conn *conn,
3911 							 const struct bt_gatt_attr *attr,
3912 							 struct bt_gatt_discover_params *discover)
3913 {
3914 	uint8_t index = bt_conn_index(conn);
3915 	const struct bt_gatt_chrc *chrc;
3916 	uint8_t chrc_properties;
3917 	uint16_t value_handle;
3918 	int err;
3919 
3920 	if (!attr) {
3921 		/* If available_ctx is not found, we terminate the discovery as
3922 		 * the characteristic is mandatory
3923 		 */
3924 
3925 		unicast_client_discover_complete(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND);
3926 
3927 		return BT_GATT_ITER_STOP;
3928 	}
3929 
3930 	chrc = attr->user_data;
3931 	chrc_properties = chrc->properties;
3932 	value_handle = chrc->value_handle;
3933 	memset(discover, 0, sizeof(*discover));
3934 
3935 	LOG_DBG("conn %p attr %p handle 0x%04x", conn, attr, value_handle);
3936 
3937 	if (chrc_properties & BT_GATT_CHRC_NOTIFY) {
3938 		struct bt_gatt_subscribe_params *sub_params;
3939 
3940 		sub_params = &uni_cli_insts[index].avail_ctx_subscribe;
3941 
3942 		if (sub_params->value_handle == 0) {
3943 			LOG_DBG("Subscribing to handle %u", value_handle);
3944 			sub_params->value_handle = value_handle;
3945 			sub_params->ccc_handle = BT_GATT_AUTO_DISCOVER_CCC_HANDLE;
3946 			sub_params->end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
3947 			sub_params->disc_params = &uni_cli_insts[index].avail_ctx_cc_disc;
3948 			sub_params->notify = unicast_client_pacs_avail_ctx_notify_cb;
3949 			sub_params->value = BT_GATT_CCC_NOTIFY;
3950 			atomic_set_bit(sub_params->flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
3951 
3952 			err = bt_gatt_subscribe(conn, sub_params);
3953 			if (err != 0 && err != -EALREADY) {
3954 				LOG_ERR("Failed to subscribe to avail_ctx: %d", err);
3955 			}
3956 		} /* else already subscribed */
3957 	} else {
3958 		LOG_DBG("Invalid chrc->properties: %u", chrc_properties);
3959 		/* If the characteristic is not subscribable we terminate the
3960 		 * discovery as BT_GATT_CHRC_NOTIFY is mandatory
3961 		 */
3962 		unicast_client_discover_complete(conn, BT_ATT_ERR_NOT_SUPPORTED);
3963 
3964 		return BT_GATT_ITER_STOP;
3965 	}
3966 
3967 	err = unicast_client_pacs_avail_ctx_read(conn, value_handle);
3968 	if (err != 0) {
3969 		LOG_DBG("Failed to read PACS avail_ctx: %d", err);
3970 
3971 		unicast_client_discover_complete(conn, err);
3972 	}
3973 
3974 	return BT_GATT_ITER_STOP;
3975 }
3976 
unicast_client_pacs_avail_ctx_discover(struct bt_conn * conn)3977 static int unicast_client_pacs_avail_ctx_discover(struct bt_conn *conn)
3978 {
3979 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
3980 
3981 	LOG_DBG("conn %p", conn);
3982 
3983 	client->disc_params.uuid = pacs_avail_ctx_uuid;
3984 	client->disc_params.func = unicast_client_pacs_avail_ctx_discover_cb;
3985 	client->disc_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
3986 	client->disc_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
3987 	client->disc_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
3988 
3989 	return bt_gatt_discover(conn, &client->disc_params);
3990 }
3991 
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)3992 static uint8_t unicast_client_pacs_location_read_func(struct bt_conn *conn, uint8_t err,
3993 						      struct bt_gatt_read_params *read,
3994 						      const void *data, uint16_t length)
3995 {
3996 	struct unicast_client *client;
3997 	struct net_buf_simple buf;
3998 	uint32_t location;
3999 	int cb_err;
4000 
4001 	memset(read, 0, sizeof(*read));
4002 
4003 	client = &uni_cli_insts[bt_conn_index(conn)];
4004 
4005 	LOG_DBG("conn %p err 0x%02x len %u", conn, err, length);
4006 
4007 	if (err || data == NULL || length != sizeof(location)) {
4008 		LOG_DBG("Unable to read PACS location for dir %s: %u, %p, %u",
4009 			bt_audio_dir_str(client->dir), err, data, length);
4010 
4011 		if (err == BT_ATT_ERR_SUCCESS) {
4012 			err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
4013 		}
4014 
4015 		unicast_client_discover_complete(conn, err);
4016 
4017 		return BT_GATT_ITER_STOP;
4018 	}
4019 
4020 	net_buf_simple_init_with_data(&buf, (void *)data, length);
4021 	location = net_buf_simple_pull_le32(&buf);
4022 
4023 	LOG_DBG("dir %s loc %X", bt_audio_dir_str(client->dir), location);
4024 
4025 	unicast_client_notify_location(conn, client->dir, (enum bt_audio_location)location);
4026 
4027 	/* Read available contexts */
4028 	cb_err = unicast_client_pacs_avail_ctx_discover(conn);
4029 	if (cb_err != 0) {
4030 		LOG_ERR("Unable to read available contexts: %d", cb_err);
4031 
4032 		unicast_client_discover_complete(conn, cb_err);
4033 	}
4034 
4035 	return BT_GATT_ITER_STOP;
4036 }
4037 
unicast_client_pacs_location_notify_cb(struct bt_conn * conn,struct bt_gatt_subscribe_params * params,const void * data,uint16_t length)4038 static uint8_t unicast_client_pacs_location_notify_cb(struct bt_conn *conn,
4039 						      struct bt_gatt_subscribe_params *params,
4040 						      const void *data, uint16_t length)
4041 {
4042 	struct net_buf_simple buf;
4043 	enum bt_audio_dir dir;
4044 	uint32_t location;
4045 
4046 	LOG_DBG("conn %p len %u", conn, length);
4047 
4048 	if (!data) {
4049 		LOG_DBG("Unsubscribed");
4050 		params->value_handle = BAP_HANDLE_UNUSED;
4051 		return BT_GATT_ITER_STOP;
4052 	}
4053 
4054 	net_buf_simple_init_with_data(&buf, (void *)data, length);
4055 
4056 	if (buf.len != sizeof(location)) {
4057 		LOG_ERR("Location notification incorrect size: %u", length);
4058 		return BT_GATT_ITER_STOP;
4059 	}
4060 
4061 	if (params == &uni_cli_insts[bt_conn_index(conn)].snk_loc_subscribe) {
4062 		dir = BT_AUDIO_DIR_SINK;
4063 	} else if (params == &uni_cli_insts[bt_conn_index(conn)].src_loc_subscribe) {
4064 		dir = BT_AUDIO_DIR_SOURCE;
4065 	} else {
4066 		LOG_ERR("Invalid notification");
4067 
4068 		return BT_GATT_ITER_CONTINUE;
4069 	}
4070 
4071 	net_buf_simple_init_with_data(&buf, (void *)data, length);
4072 	location = net_buf_simple_pull_le32(&buf);
4073 
4074 	LOG_DBG("dir %s loc %X", bt_audio_dir_str(dir), location);
4075 
4076 	unicast_client_notify_location(conn, dir, (enum bt_audio_location)location);
4077 
4078 	return BT_GATT_ITER_CONTINUE;
4079 }
4080 
unicast_client_pacs_location_read(struct bt_conn * conn,uint16_t handle)4081 static int unicast_client_pacs_location_read(struct bt_conn *conn, uint16_t handle)
4082 {
4083 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
4084 
4085 	LOG_DBG("conn %p", conn);
4086 
4087 	client->read_params.func = unicast_client_pacs_location_read_func;
4088 	client->read_params.handle_count = 1U;
4089 	client->read_params.single.handle = handle;
4090 	client->read_params.single.offset = 0U;
4091 
4092 	return bt_gatt_read(conn, &client->read_params);
4093 }
4094 
unicast_client_pacs_location_discover_cb(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * discover)4095 static uint8_t unicast_client_pacs_location_discover_cb(struct bt_conn *conn,
4096 							const struct bt_gatt_attr *attr,
4097 							struct bt_gatt_discover_params *discover)
4098 {
4099 	uint8_t index = bt_conn_index(conn);
4100 	const struct bt_gatt_chrc *chrc;
4101 	uint16_t value_handle;
4102 	int err;
4103 
4104 	if (!attr) {
4105 		/* If location is not found, we just continue reading the
4106 		 * available contexts, as location is optional.
4107 		 */
4108 		err = unicast_client_pacs_avail_ctx_discover(conn);
4109 		if (err != 0) {
4110 			LOG_ERR("Unable to read available contexts: %d", err);
4111 
4112 			unicast_client_discover_complete(conn, err);
4113 		}
4114 
4115 		return BT_GATT_ITER_STOP;
4116 	}
4117 
4118 	chrc = attr->user_data;
4119 	value_handle = chrc->value_handle;
4120 	memset(discover, 0, sizeof(*discover));
4121 
4122 	LOG_DBG("conn %p attr %p handle 0x%04x", conn, attr, value_handle);
4123 
4124 	if (chrc->properties & BT_GATT_CHRC_NOTIFY) {
4125 		const struct unicast_client *client = &uni_cli_insts[index];
4126 		struct bt_gatt_subscribe_params *sub_params;
4127 
4128 		if (client->dir == BT_AUDIO_DIR_SINK) {
4129 			sub_params = &uni_cli_insts[index].snk_loc_subscribe;
4130 		} else {
4131 			sub_params = &uni_cli_insts[index].src_loc_subscribe;
4132 		}
4133 
4134 		sub_params->value_handle = value_handle;
4135 		sub_params->ccc_handle = BT_GATT_AUTO_DISCOVER_CCC_HANDLE;
4136 		sub_params->end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
4137 		sub_params->disc_params = &uni_cli_insts[index].loc_cc_disc;
4138 		sub_params->notify = unicast_client_pacs_location_notify_cb;
4139 		sub_params->value = BT_GATT_CCC_NOTIFY;
4140 		atomic_set_bit(sub_params->flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
4141 
4142 		err = bt_gatt_subscribe(conn, sub_params);
4143 		if (err != 0 && err != -EALREADY) {
4144 			LOG_ERR("Failed to subscribe to location: %d", err);
4145 		}
4146 	}
4147 
4148 	err = unicast_client_pacs_location_read(conn, value_handle);
4149 	if (err != 0) {
4150 		LOG_DBG("Failed to read PACS location: %d", err);
4151 
4152 		unicast_client_discover_complete(conn, err);
4153 	}
4154 
4155 	return BT_GATT_ITER_STOP;
4156 }
4157 
unicast_client_pacs_location_discover(struct bt_conn * conn)4158 static int unicast_client_pacs_location_discover(struct bt_conn *conn)
4159 {
4160 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
4161 
4162 	LOG_DBG("conn %p dir %s", conn, bt_audio_dir_str(client->dir));
4163 
4164 	if (client->dir == BT_AUDIO_DIR_SINK) {
4165 		client->disc_params.uuid = pacs_snk_loc_uuid;
4166 	} else if (client->dir == BT_AUDIO_DIR_SOURCE) {
4167 		client->disc_params.uuid = pacs_src_loc_uuid;
4168 	} else {
4169 		return -EINVAL;
4170 	}
4171 
4172 	client->disc_params.func = unicast_client_pacs_location_discover_cb;
4173 	client->disc_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
4174 	client->disc_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
4175 	client->disc_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
4176 
4177 	return bt_gatt_discover(conn, &client->disc_params);
4178 }
4179 
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)4180 static uint8_t unicast_client_pacs_context_read_func(struct bt_conn *conn, uint8_t err,
4181 						     struct bt_gatt_read_params *read,
4182 						     const void *data, uint16_t length)
4183 {
4184 	struct net_buf_simple buf;
4185 	struct bt_pacs_context *context;
4186 	int cb_err;
4187 
4188 	memset(read, 0, sizeof(*read));
4189 
4190 	LOG_DBG("conn %p err 0x%02x len %u", conn, err, length);
4191 
4192 	if (err || length < sizeof(uint16_t) * 2) {
4193 		goto discover_loc;
4194 	}
4195 
4196 	net_buf_simple_init_with_data(&buf, (void *)data, length);
4197 	context = net_buf_simple_pull_mem(&buf, sizeof(*context));
4198 
4199 discover_loc:
4200 	/* Read ASE instances */
4201 	cb_err = unicast_client_pacs_location_discover(conn);
4202 	if (cb_err != 0) {
4203 		LOG_ERR("Unable to read PACS location: %d", cb_err);
4204 
4205 		unicast_client_discover_complete(conn, cb_err);
4206 	}
4207 
4208 	return BT_GATT_ITER_STOP;
4209 }
4210 
unicast_client_pacs_context_discover_cb(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * discover)4211 static uint8_t unicast_client_pacs_context_discover_cb(struct bt_conn *conn,
4212 						       const struct bt_gatt_attr *attr,
4213 						       struct bt_gatt_discover_params *discover)
4214 {
4215 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
4216 	struct bt_gatt_chrc *chrc;
4217 	uint16_t value_handle;
4218 	int err;
4219 
4220 	if (attr == NULL) {
4221 		LOG_ERR("Unable to find %s PAC context", bt_audio_dir_str(client->dir));
4222 
4223 		unicast_client_discover_complete(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND);
4224 
4225 		return BT_GATT_ITER_STOP;
4226 	}
4227 
4228 	chrc = attr->user_data;
4229 	value_handle = chrc->value_handle;
4230 	memset(discover, 0, sizeof(*discover));
4231 
4232 	LOG_DBG("conn %p attr %p handle 0x%04x dir %s", conn, attr, value_handle,
4233 		bt_audio_dir_str(client->dir));
4234 
4235 	/* TODO: Subscribe to PAC context */
4236 
4237 	client->read_params.func = unicast_client_pacs_context_read_func;
4238 	client->read_params.handle_count = 1U;
4239 	client->read_params.single.handle = value_handle;
4240 	client->read_params.single.offset = 0U;
4241 
4242 	err = bt_gatt_read(conn, &client->read_params);
4243 	if (err != 0) {
4244 		LOG_DBG("Failed to read PAC records: %d", err);
4245 
4246 		unicast_client_discover_complete(conn, err);
4247 	}
4248 
4249 	return BT_GATT_ITER_STOP;
4250 }
4251 
unicast_client_pacs_context_discover(struct bt_conn * conn)4252 static int unicast_client_pacs_context_discover(struct bt_conn *conn)
4253 {
4254 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
4255 
4256 	LOG_DBG("conn %p", conn);
4257 
4258 	client->disc_params.uuid = pacs_context_uuid;
4259 	client->disc_params.func = unicast_client_pacs_context_discover_cb;
4260 	client->disc_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
4261 	client->disc_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
4262 	client->disc_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
4263 
4264 	return bt_gatt_discover(conn, &client->disc_params);
4265 }
4266 
unicast_client_read_func(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * read,const void * data,uint16_t length)4267 static uint8_t unicast_client_read_func(struct bt_conn *conn, uint8_t err,
4268 					struct bt_gatt_read_params *read, const void *data,
4269 					uint16_t length)
4270 {
4271 	uint16_t handle = read->single.handle;
4272 	struct unicast_client *client;
4273 	struct bt_pacs_read_rsp *rsp;
4274 	struct net_buf_simple *buf;
4275 	int cb_err = err;
4276 	uint8_t i;
4277 
4278 	LOG_DBG("conn %p err 0x%02x len %u", conn, err, length);
4279 
4280 	if (cb_err != BT_ATT_ERR_SUCCESS) {
4281 		goto fail;
4282 	}
4283 
4284 	LOG_DBG("handle 0x%04x", handle);
4285 
4286 	client = &uni_cli_insts[bt_conn_index(conn)];
4287 	buf = &client->net_buf;
4288 
4289 	if (data != NULL) {
4290 		if (net_buf_simple_tailroom(buf) < length) {
4291 			LOG_DBG("Buffer full, invalid server response of size %u",
4292 				length + client->net_buf.len);
4293 
4294 			cb_err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
4295 
4296 			goto fail;
4297 		}
4298 
4299 		/* store data*/
4300 		net_buf_simple_add_mem(buf, data, length);
4301 
4302 		return BT_GATT_ITER_CONTINUE;
4303 	}
4304 
4305 	memset(read, 0, sizeof(*read));
4306 
4307 	if (buf->len < sizeof(*rsp)) {
4308 		LOG_DBG("Read response too small (%u)", buf->len);
4309 
4310 		cb_err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
4311 
4312 		goto fail;
4313 	}
4314 
4315 	rsp = net_buf_simple_pull_mem(buf, sizeof(*rsp));
4316 
4317 	/* If no PAC was found don't bother discovering ASE and ASE CP */
4318 	if (!rsp->num_pac) {
4319 		goto fail;
4320 	}
4321 
4322 	for (i = 0U; i < rsp->num_pac; i++) {
4323 		struct bt_audio_codec_cap codec_cap;
4324 		struct bt_pac_codec *pac_codec;
4325 		struct bt_pac_ltv_data *meta, *cc;
4326 		void *cc_ltv, *meta_ltv;
4327 
4328 		LOG_DBG("pac #%u/%u", i + 1, rsp->num_pac);
4329 
4330 		if (buf->len < sizeof(*pac_codec)) {
4331 			LOG_ERR("Malformed PAC: remaining len %u expected %zu",
4332 				buf->len, sizeof(*pac_codec));
4333 			break;
4334 		}
4335 
4336 		pac_codec = net_buf_simple_pull_mem(buf, sizeof(*pac_codec));
4337 
4338 		if (buf->len < sizeof(*cc)) {
4339 			LOG_ERR("Malformed PAC: remaining len %u expected %zu",
4340 				buf->len, sizeof(*cc));
4341 			break;
4342 		}
4343 
4344 		cc = net_buf_simple_pull_mem(buf, sizeof(*cc));
4345 		if (buf->len < cc->len) {
4346 			LOG_ERR("Malformed PAC: remaining len %u expected %zu",
4347 				buf->len, cc->len);
4348 			break;
4349 		}
4350 
4351 		cc_ltv = net_buf_simple_pull_mem(buf, cc->len);
4352 
4353 		if (buf->len < sizeof(*meta)) {
4354 			LOG_ERR("Malformed PAC: remaining len %u expected %zu",
4355 				buf->len, sizeof(*meta));
4356 			break;
4357 		}
4358 
4359 		meta = net_buf_simple_pull_mem(buf, sizeof(*meta));
4360 		if (buf->len < meta->len) {
4361 			LOG_ERR("Malformed PAC: remaining len %u expected %u",
4362 				buf->len, meta->len);
4363 			break;
4364 		}
4365 
4366 		meta_ltv = net_buf_simple_pull_mem(buf, meta->len);
4367 
4368 		if (unicast_client_set_codec_cap(pac_codec->id, sys_le16_to_cpu(pac_codec->cid),
4369 						 sys_le16_to_cpu(pac_codec->vid), cc_ltv, cc->len,
4370 						 meta_ltv, meta->len, &codec_cap)) {
4371 			LOG_ERR("Unable to parse Codec");
4372 			break;
4373 		}
4374 
4375 		LOG_DBG("codec 0x%02x capabilities len %u meta len %u ", codec_cap.id,
4376 			codec_cap.data_len, codec_cap.meta_len);
4377 
4378 		unicast_client_notify_pac_record(conn, &codec_cap);
4379 	}
4380 
4381 	reset_att_buf(client);
4382 
4383 	if (i != rsp->num_pac) {
4384 		LOG_DBG("Failed to process all PAC records (%u/%u)", i, rsp->num_pac);
4385 		cb_err = BT_ATT_ERR_INVALID_PDU;
4386 		goto fail;
4387 	}
4388 
4389 	/* Read PACS contexts */
4390 	cb_err = unicast_client_pacs_context_discover(conn);
4391 	if (cb_err != 0) {
4392 		LOG_ERR("Unable to read PACS context: %d", cb_err);
4393 		goto fail;
4394 	}
4395 
4396 	return BT_GATT_ITER_STOP;
4397 
4398 fail:
4399 	unicast_client_discover_complete(conn, cb_err);
4400 	return BT_GATT_ITER_STOP;
4401 }
4402 
unicast_client_pac_discover_cb(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * discover)4403 static uint8_t unicast_client_pac_discover_cb(struct bt_conn *conn,
4404 					      const struct bt_gatt_attr *attr,
4405 					      struct bt_gatt_discover_params *discover)
4406 {
4407 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
4408 	struct bt_gatt_chrc *chrc;
4409 	uint16_t value_handle;
4410 	int err;
4411 
4412 	if (attr == NULL) {
4413 		LOG_DBG("Unable to find %s PAC", bt_audio_dir_str(client->dir));
4414 
4415 		unicast_client_discover_complete(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND);
4416 
4417 		return BT_GATT_ITER_STOP;
4418 	}
4419 
4420 	chrc = attr->user_data;
4421 	value_handle = chrc->value_handle;
4422 	memset(discover, 0, sizeof(*discover));
4423 
4424 	LOG_DBG("conn %p attr %p handle 0x%04x dir %s", conn, attr, value_handle,
4425 		bt_audio_dir_str(client->dir));
4426 
4427 	/* TODO: Subscribe to PAC */
4428 
4429 	/* Reset to use for long read */
4430 	reset_att_buf(client);
4431 
4432 	client->read_params.func = unicast_client_read_func;
4433 	client->read_params.handle_count = 1U;
4434 	client->read_params.single.handle = value_handle;
4435 	client->read_params.single.offset = 0U;
4436 
4437 	err = bt_gatt_read(conn, &client->read_params);
4438 	if (err != 0) {
4439 		LOG_DBG("Failed to read PAC records: %d", err);
4440 
4441 		unicast_client_discover_complete(conn, err);
4442 	}
4443 
4444 	return BT_GATT_ITER_STOP;
4445 }
4446 
unicast_client_disconnected(struct bt_conn * conn,uint8_t reason)4447 static void unicast_client_disconnected(struct bt_conn *conn, uint8_t reason)
4448 {
4449 	LOG_DBG("conn %p reason 0x%02x", conn, reason);
4450 
4451 	unicast_client_ep_reset(conn, reason);
4452 }
4453 
4454 static struct bt_conn_cb conn_cbs = {
4455 	.disconnected = unicast_client_disconnected,
4456 };
4457 
bt_bap_unicast_client_discover(struct bt_conn * conn,enum bt_audio_dir dir)4458 int bt_bap_unicast_client_discover(struct bt_conn *conn, enum bt_audio_dir dir)
4459 {
4460 	struct unicast_client *client;
4461 	static bool conn_cb_registered;
4462 	uint8_t role;
4463 	int err;
4464 
4465 	if (!conn || conn->state != BT_CONN_CONNECTED) {
4466 		return -ENOTCONN;
4467 	}
4468 
4469 	role = conn->role;
4470 	if (role != BT_HCI_ROLE_CENTRAL) {
4471 		LOG_DBG("Invalid conn role: %u, shall be central", role);
4472 		return -EINVAL;
4473 	}
4474 
4475 	client = &uni_cli_insts[bt_conn_index(conn)];
4476 	if (atomic_test_and_set_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY)) {
4477 		LOG_DBG("Client connection is busy");
4478 		return -EBUSY;
4479 	}
4480 
4481 	if (dir == BT_AUDIO_DIR_SINK) {
4482 		client->disc_params.uuid = snk_uuid;
4483 	} else if (dir == BT_AUDIO_DIR_SOURCE) {
4484 		client->disc_params.uuid = src_uuid;
4485 	} else {
4486 		return -EINVAL;
4487 	}
4488 
4489 	client->disc_params.func = unicast_client_pac_discover_cb;
4490 	client->disc_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
4491 	client->disc_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
4492 	client->disc_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
4493 
4494 	if (!conn_cb_registered) {
4495 		bt_conn_cb_register(&conn_cbs);
4496 		conn_cb_registered = true;
4497 	}
4498 
4499 	err = bt_gatt_discover(conn, &client->disc_params);
4500 	if (err != 0) {
4501 		atomic_clear_bit(client->flags, UNICAST_CLIENT_FLAG_BUSY);
4502 		return err;
4503 	}
4504 
4505 	client->dir = dir;
4506 
4507 	return 0;
4508 }
4509 
bt_bap_unicast_client_register_cb(struct bt_bap_unicast_client_cb * cb)4510 int bt_bap_unicast_client_register_cb(struct bt_bap_unicast_client_cb *cb)
4511 {
4512 	CHECKIF(cb == NULL) {
4513 		LOG_DBG("cb is NULL");
4514 		return -EINVAL;
4515 	}
4516 
4517 	if (sys_slist_find(&unicast_client_cbs, &cb->_node, NULL)) {
4518 		return -EEXIST;
4519 	}
4520 
4521 	sys_slist_append(&unicast_client_cbs, &cb->_node);
4522 
4523 	return 0;
4524 }
4525