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