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