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