1 /*
2  * Copyright (c) 2022-2023 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/sys/check.h>
8 #include <zephyr/bluetooth/gatt.h>
9 #include <zephyr/bluetooth/audio/audio.h>
10 #include <zephyr/bluetooth/audio/cap.h>
11 #include <zephyr/bluetooth/audio/tbs.h>
12 #include "cap_internal.h"
13 #include "csip_internal.h"
14 #include "bap_endpoint.h"
15 
16 #include <zephyr/logging/log.h>
17 
18 LOG_MODULE_REGISTER(bt_cap_initiator, CONFIG_BT_CAP_INITIATOR_LOG_LEVEL);
19 
20 #include "common/bt_str.h"
21 
22 static const struct bt_cap_initiator_cb *cap_cb;
23 
bt_cap_initiator_register_cb(const struct bt_cap_initiator_cb * cb)24 int bt_cap_initiator_register_cb(const struct bt_cap_initiator_cb *cb)
25 {
26 	CHECKIF(cb == NULL) {
27 		LOG_DBG("cb is NULL");
28 		return -EINVAL;
29 	}
30 
31 	CHECKIF(cap_cb != NULL) {
32 		LOG_DBG("callbacks already registered");
33 		return -EALREADY;
34 	}
35 
36 	cap_cb = cb;
37 
38 	return 0;
39 }
40 
data_func_cb(struct bt_data * data,void * user_data)41 static bool data_func_cb(struct bt_data *data, void *user_data)
42 {
43 	bool *stream_context_found = (bool *)user_data;
44 
45 	LOG_DBG("type %u len %u data %s", data->type, data->data_len,
46 		bt_hex(data->data, data->data_len));
47 
48 	if (data->type == BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT) {
49 		if (data->data_len != 2) { /* Stream context size */
50 			return false;
51 		}
52 
53 		*stream_context_found = true;
54 		return false;
55 	}
56 
57 	return true;
58 }
59 
cap_initiator_valid_metadata(const uint8_t meta[],size_t meta_len)60 static bool cap_initiator_valid_metadata(const uint8_t meta[], size_t meta_len)
61 {
62 	bool stream_context_found = false;
63 	int err;
64 
65 	LOG_DBG("meta %p len %zu", meta, meta_len);
66 
67 	err = bt_audio_data_parse(meta, meta_len, data_func_cb, &stream_context_found);
68 	if (err != 0 && err != -ECANCELED) {
69 		return false;
70 	}
71 
72 	if (!stream_context_found) {
73 		LOG_DBG("No streaming context supplied");
74 	}
75 
76 	return stream_context_found;
77 }
78 
79 #if defined(CONFIG_BT_BAP_BROADCAST_SOURCE)
80 static struct bt_cap_broadcast_source {
81 	struct bt_bap_broadcast_source *bap_broadcast;
82 } broadcast_sources[CONFIG_BT_BAP_BROADCAST_SRC_COUNT];
83 
cap_initiator_broadcast_audio_start_valid_param(const struct bt_cap_initiator_broadcast_create_param * param)84 static bool cap_initiator_broadcast_audio_start_valid_param(
85 	const struct bt_cap_initiator_broadcast_create_param *param)
86 {
87 
88 	for (size_t i = 0U; i < param->subgroup_count; i++) {
89 		const struct bt_cap_initiator_broadcast_subgroup_param *subgroup_param;
90 		const struct bt_audio_codec_cfg *codec_cfg;
91 		bool valid_metadata;
92 
93 		subgroup_param = &param->subgroup_params[i];
94 		codec_cfg = subgroup_param->codec_cfg;
95 
96 		/* Streaming Audio Context shall be present in CAP */
97 
98 		CHECKIF(codec_cfg == NULL) {
99 			LOG_DBG("subgroup[%zu]->codec_cfg is NULL", i);
100 			return false;
101 		}
102 
103 		valid_metadata =
104 			cap_initiator_valid_metadata(codec_cfg->meta, codec_cfg->meta_len);
105 
106 		CHECKIF(!valid_metadata) {
107 			LOG_DBG("Invalid metadata supplied for subgroup[%zu]", i);
108 			return false;
109 		}
110 	}
111 
112 	return true;
113 }
114 
cap_initiator_broadcast_to_bap_broadcast_param(const struct bt_cap_initiator_broadcast_create_param * cap_param,struct bt_bap_broadcast_source_param * bap_param,struct bt_bap_broadcast_source_subgroup_param bap_subgroup_params[CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT],struct bt_bap_broadcast_source_stream_param bap_stream_params[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT])115 static void cap_initiator_broadcast_to_bap_broadcast_param(
116 	const struct bt_cap_initiator_broadcast_create_param *cap_param,
117 	struct bt_bap_broadcast_source_param *bap_param,
118 	struct bt_bap_broadcast_source_subgroup_param
119 		bap_subgroup_params[CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT],
120 	struct bt_bap_broadcast_source_stream_param
121 		bap_stream_params[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT])
122 {
123 	size_t stream_cnt = 0U;
124 
125 	bap_param->params_count = cap_param->subgroup_count;
126 	bap_param->params = bap_subgroup_params;
127 	bap_param->qos = cap_param->qos;
128 	bap_param->packing = cap_param->packing;
129 	bap_param->encryption = cap_param->encryption;
130 	if (bap_param->encryption) {
131 		memcpy(bap_param->broadcast_code, cap_param->broadcast_code,
132 		       BT_AUDIO_BROADCAST_CODE_SIZE);
133 	} else {
134 		memset(bap_param->broadcast_code, 0, BT_AUDIO_BROADCAST_CODE_SIZE);
135 	}
136 
137 	for (size_t i = 0U; i < bap_param->params_count; i++) {
138 		const struct bt_cap_initiator_broadcast_subgroup_param *cap_subgroup_param =
139 			&cap_param->subgroup_params[i];
140 		struct bt_bap_broadcast_source_subgroup_param *bap_subgroup_param =
141 			&bap_param->params[i];
142 
143 		bap_subgroup_param->codec_cfg = cap_subgroup_param->codec_cfg;
144 		bap_subgroup_param->params_count = cap_subgroup_param->stream_count;
145 		bap_subgroup_param->params = &bap_stream_params[stream_cnt];
146 
147 		for (size_t j = 0U; j < bap_subgroup_param->params_count; j++, stream_cnt++) {
148 			const struct bt_cap_initiator_broadcast_stream_param *cap_stream_param =
149 				&cap_subgroup_param->stream_params[j];
150 			struct bt_bap_broadcast_source_stream_param *bap_stream_param =
151 				&bap_subgroup_param->params[j];
152 
153 			bap_stream_param->stream = &cap_stream_param->stream->bap_stream;
154 #if CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0
155 			bap_stream_param->data_len = cap_stream_param->data_len;
156 			/* We do not need to copy the data, as that is the same type of struct, so
157 			 * we can just point to the CAP parameter data
158 			 */
159 			bap_stream_param->data = cap_stream_param->data;
160 #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0 */
161 		}
162 	}
163 }
164 
bt_cap_initiator_broadcast_audio_create(const struct bt_cap_initiator_broadcast_create_param * param,struct bt_cap_broadcast_source ** broadcast_source)165 int bt_cap_initiator_broadcast_audio_create(
166 	const struct bt_cap_initiator_broadcast_create_param *param,
167 	struct bt_cap_broadcast_source **broadcast_source)
168 {
169 	struct bt_bap_broadcast_source_subgroup_param
170 		bap_subgroup_params[CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT];
171 	struct bt_bap_broadcast_source_stream_param
172 		bap_stream_params[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT];
173 	struct bt_bap_broadcast_source_param bap_create_param;
174 
175 	CHECKIF(param == NULL) {
176 		LOG_DBG("param is NULL");
177 		return -EINVAL;
178 	}
179 
180 	CHECKIF(broadcast_source == NULL) {
181 		LOG_DBG("source is NULL");
182 		return -EINVAL;
183 	}
184 
185 	if (!cap_initiator_broadcast_audio_start_valid_param(param)) {
186 		return -EINVAL;
187 	}
188 
189 	for (size_t i = 0; i < ARRAY_SIZE(broadcast_sources); i++) {
190 		if (broadcast_sources[i].bap_broadcast == NULL) {
191 			*broadcast_source = &broadcast_sources[i];
192 			break;
193 		}
194 	}
195 
196 	cap_initiator_broadcast_to_bap_broadcast_param(param, &bap_create_param,
197 						       bap_subgroup_params, bap_stream_params);
198 
199 	return bt_bap_broadcast_source_create(&bap_create_param,
200 					      &(*broadcast_source)->bap_broadcast);
201 }
202 
bt_cap_initiator_broadcast_audio_start(struct bt_cap_broadcast_source * broadcast_source,struct bt_le_ext_adv * adv)203 int bt_cap_initiator_broadcast_audio_start(struct bt_cap_broadcast_source *broadcast_source,
204 					   struct bt_le_ext_adv *adv)
205 {
206 	CHECKIF(adv == NULL) {
207 		LOG_DBG("adv is NULL");
208 		return -EINVAL;
209 	}
210 
211 	CHECKIF(broadcast_source == NULL) {
212 		LOG_DBG("broadcast_source is NULL");
213 		return -EINVAL;
214 	}
215 
216 	return bt_bap_broadcast_source_start(broadcast_source->bap_broadcast, adv);
217 }
218 
bt_cap_initiator_broadcast_audio_update(struct bt_cap_broadcast_source * broadcast_source,const uint8_t meta[],size_t meta_len)219 int bt_cap_initiator_broadcast_audio_update(struct bt_cap_broadcast_source *broadcast_source,
220 					    const uint8_t meta[], size_t meta_len)
221 {
222 	CHECKIF(broadcast_source == NULL) {
223 		LOG_DBG("broadcast_source is NULL");
224 		return -EINVAL;
225 	}
226 
227 	CHECKIF(meta == NULL) {
228 		LOG_DBG("meta is NULL");
229 		return -EINVAL;
230 	}
231 
232 	if (!cap_initiator_valid_metadata(meta, meta_len)) {
233 		LOG_DBG("Invalid metadata");
234 		return -EINVAL;
235 	}
236 
237 	return bt_bap_broadcast_source_update_metadata(broadcast_source->bap_broadcast, meta,
238 						       meta_len);
239 }
240 
bt_cap_initiator_broadcast_audio_stop(struct bt_cap_broadcast_source * broadcast_source)241 int bt_cap_initiator_broadcast_audio_stop(struct bt_cap_broadcast_source *broadcast_source)
242 {
243 	CHECKIF(broadcast_source == NULL) {
244 		LOG_DBG("broadcast_source is NULL");
245 		return -EINVAL;
246 	}
247 
248 	return bt_bap_broadcast_source_stop(broadcast_source->bap_broadcast);
249 }
250 
bt_cap_initiator_broadcast_audio_delete(struct bt_cap_broadcast_source * broadcast_source)251 int bt_cap_initiator_broadcast_audio_delete(struct bt_cap_broadcast_source *broadcast_source)
252 {
253 	int err;
254 
255 	CHECKIF(broadcast_source == NULL) {
256 		LOG_DBG("broadcast_source is NULL");
257 		return -EINVAL;
258 	}
259 
260 	err = bt_bap_broadcast_source_delete(broadcast_source->bap_broadcast);
261 	if (err == 0) {
262 		broadcast_source->bap_broadcast = NULL;
263 	}
264 
265 	return err;
266 }
267 
bt_cap_initiator_broadcast_get_id(const struct bt_cap_broadcast_source * broadcast_source,uint32_t * const broadcast_id)268 int bt_cap_initiator_broadcast_get_id(const struct bt_cap_broadcast_source *broadcast_source,
269 				      uint32_t *const broadcast_id)
270 {
271 	CHECKIF(broadcast_source == NULL) {
272 		LOG_DBG("broadcast_source is NULL");
273 		return -EINVAL;
274 	}
275 
276 	return bt_bap_broadcast_source_get_id(broadcast_source->bap_broadcast, broadcast_id);
277 }
278 
bt_cap_initiator_broadcast_get_base(struct bt_cap_broadcast_source * broadcast_source,struct net_buf_simple * base_buf)279 int bt_cap_initiator_broadcast_get_base(struct bt_cap_broadcast_source *broadcast_source,
280 					struct net_buf_simple *base_buf)
281 {
282 	CHECKIF(broadcast_source == NULL) {
283 		LOG_DBG("broadcast_source is NULL");
284 		return -EINVAL;
285 	}
286 
287 	return bt_bap_broadcast_source_get_base(broadcast_source->bap_broadcast, base_buf);
288 }
289 
290 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
291 
292 #if defined(CONFIG_BT_BAP_UNICAST_CLIENT)
293 enum {
294 	CAP_UNICAST_PROC_STATE_ACTIVE,
295 	CAP_UNICAST_PROC_STATE_ABORTED,
296 
297 	CAP_UNICAST_PROC_STATE_FLAG_NUM,
298 } cap_unicast_proc_state;
299 
300 enum cap_unicast_proc_type {
301 	CAP_UNICAST_PROC_TYPE_NONE,
302 	CAP_UNICAST_PROC_TYPE_START,
303 	CAP_UNICAST_PROC_TYPE_UPDATE,
304 	CAP_UNICAST_PROC_TYPE_STOP,
305 };
306 
307 enum cap_unicast_subproc_type {
308 	CAP_UNICAST_SUBPROC_TYPE_NONE,
309 	CAP_UNICAST_SUBPROC_TYPE_CODEC_CONFIG,
310 	CAP_UNICAST_SUBPROC_TYPE_QOS_CONFIG,
311 	CAP_UNICAST_SUBPROC_TYPE_ENABLE,
312 	CAP_UNICAST_SUBPROC_TYPE_START,
313 	CAP_UNICAST_SUBPROC_TYPE_META_UPDATE,
314 	CAP_UNICAST_SUBPROC_TYPE_RELEASE,
315 };
316 
317 struct cap_unicast_proc_param {
318 	struct bt_cap_stream *stream;
319 	union {
320 		struct {
321 			struct bt_conn *conn;
322 			struct bt_bap_ep *ep;
323 			struct bt_audio_codec_cfg codec_cfg;
324 		} start;
325 		struct {
326 			/** Codec Specific Capabilities Metadata count */
327 			size_t meta_len;
328 			/** Codec Specific Capabilities Metadata */
329 			uint8_t meta[CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE];
330 		} meta_update;
331 	};
332 };
333 
334 struct cap_unicast_proc {
335 	ATOMIC_DEFINE(proc_state_flags, CAP_UNICAST_PROC_STATE_FLAG_NUM);
336 	/* Total number of streams in the procedure*/
337 	size_t stream_cnt;
338 	/* Number of streams where a subprocedure have been started */
339 	size_t stream_initiated_cnt;
340 	/* Number of streams done with the procedure */
341 	size_t stream_done_cnt;
342 	enum cap_unicast_proc_type proc_type;
343 	enum cap_unicast_subproc_type subproc_type;
344 	int err;
345 	struct bt_conn *failed_conn;
346 	struct cap_unicast_proc_param proc_param[CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT];
347 	struct bt_bap_unicast_group *unicast_group;
348 };
349 
350 struct cap_unicast_client {
351 	struct bt_conn *conn;
352 	struct bt_gatt_discover_params param;
353 	uint16_t csis_start_handle;
354 	const struct bt_csip_set_coordinator_csis_inst *csis_inst;
355 	bool cas_found;
356 };
357 
358 static struct cap_unicast_client bt_cap_unicast_clients[CONFIG_BT_MAX_CONN];
359 static const struct bt_uuid *cas_uuid = BT_UUID_CAS;
360 static struct cap_unicast_proc active_proc;
361 
cap_set_subproc(enum cap_unicast_subproc_type subproc_type)362 static void cap_set_subproc(enum cap_unicast_subproc_type subproc_type)
363 {
364 	active_proc.stream_done_cnt = 0U;
365 	active_proc.stream_initiated_cnt = 0U;
366 	active_proc.subproc_type = subproc_type;
367 }
368 
cap_proc_is_active(void)369 static bool cap_proc_is_active(void)
370 {
371 	return atomic_test_bit(active_proc.proc_state_flags, CAP_UNICAST_PROC_STATE_ACTIVE);
372 }
373 
cap_proc_is_aborted(void)374 static bool cap_proc_is_aborted(void)
375 {
376 	return atomic_test_bit(active_proc.proc_state_flags, CAP_UNICAST_PROC_STATE_ABORTED);
377 }
378 
cap_proc_all_streams_handled(void)379 static bool cap_proc_all_streams_handled(void)
380 {
381 	return active_proc.stream_done_cnt == active_proc.stream_initiated_cnt;
382 }
383 
cap_proc_is_done(void)384 static bool cap_proc_is_done(void)
385 {
386 	return active_proc.stream_done_cnt == active_proc.stream_cnt;
387 }
388 
cap_abort_proc(struct bt_conn * conn,int err)389 static void cap_abort_proc(struct bt_conn *conn, int err)
390 {
391 	if (cap_proc_is_aborted()) {
392 		/* no-op */
393 		return;
394 	}
395 
396 	active_proc.err = err;
397 	active_proc.failed_conn = conn;
398 	atomic_set_bit(active_proc.proc_state_flags, CAP_UNICAST_PROC_STATE_ABORTED);
399 }
400 
cap_conn_in_active_proc(const struct bt_conn * conn)401 static bool cap_conn_in_active_proc(const struct bt_conn *conn)
402 {
403 	if (!cap_proc_is_active()) {
404 		return false;
405 	}
406 
407 	for (size_t i = 0U; i < active_proc.stream_initiated_cnt; i++) {
408 		if (active_proc.proc_param[i].stream->bap_stream.conn == conn) {
409 			return true;
410 		}
411 	}
412 
413 	return false;
414 }
415 
cap_initiator_disconnected(struct bt_conn * conn,uint8_t reason)416 static void cap_initiator_disconnected(struct bt_conn *conn, uint8_t reason)
417 {
418 	struct cap_unicast_client *client;
419 
420 	client = &bt_cap_unicast_clients[bt_conn_index(conn)];
421 
422 	if (client->conn != NULL) {
423 		bt_conn_unref(client->conn);
424 	}
425 	(void)memset(client, 0, sizeof(*client));
426 
427 	if (cap_conn_in_active_proc(conn)) {
428 		cap_abort_proc(conn, -ENOTCONN);
429 	}
430 }
431 
432 BT_CONN_CB_DEFINE(conn_callbacks) = {
433 	.disconnected = cap_initiator_disconnected,
434 };
435 
lookup_unicast_client_by_csis(const struct bt_csip_set_coordinator_csis_inst * csis_inst)436 static struct cap_unicast_client *lookup_unicast_client_by_csis(
437 	const struct bt_csip_set_coordinator_csis_inst *csis_inst)
438 {
439 	if (csis_inst == NULL) {
440 		return NULL;
441 	}
442 
443 	for (size_t i = 0U; i < ARRAY_SIZE(bt_cap_unicast_clients); i++) {
444 		struct cap_unicast_client *client = &bt_cap_unicast_clients[i];
445 
446 		if (client->csis_inst == csis_inst) {
447 			return client;
448 		}
449 	}
450 
451 	return NULL;
452 }
453 
csis_client_discover_cb(struct bt_conn * conn,const struct bt_csip_set_coordinator_set_member * member,int err,size_t set_count)454 static void csis_client_discover_cb(struct bt_conn *conn,
455 				    const struct bt_csip_set_coordinator_set_member *member,
456 				    int err, size_t set_count)
457 {
458 	struct cap_unicast_client *client;
459 
460 	if (err != 0) {
461 		LOG_DBG("CSIS client discover failed: %d", err);
462 
463 		if (cap_cb && cap_cb->unicast_discovery_complete) {
464 			cap_cb->unicast_discovery_complete(conn, err, NULL);
465 		}
466 
467 		return;
468 	}
469 
470 	client = &bt_cap_unicast_clients[bt_conn_index(conn)];
471 	client->csis_inst = bt_csip_set_coordinator_csis_inst_by_handle(
472 					conn, client->csis_start_handle);
473 
474 	if (member == NULL || set_count == 0 || client->csis_inst == NULL) {
475 		LOG_ERR("Unable to find CSIS for CAS");
476 
477 		if (cap_cb && cap_cb->unicast_discovery_complete) {
478 			cap_cb->unicast_discovery_complete(conn, -ENODATA,
479 							   NULL);
480 		}
481 	} else {
482 		LOG_DBG("Found CAS with CSIS");
483 		if (cap_cb && cap_cb->unicast_discovery_complete) {
484 			cap_cb->unicast_discovery_complete(conn, 0,
485 							   client->csis_inst);
486 		}
487 	}
488 }
489 
cap_unicast_discover_included_cb(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * params)490 static uint8_t cap_unicast_discover_included_cb(struct bt_conn *conn,
491 						const struct bt_gatt_attr *attr,
492 						struct bt_gatt_discover_params *params)
493 {
494 	params->func = NULL;
495 
496 	if (attr == NULL) {
497 		LOG_DBG("CAS CSIS include not found");
498 
499 		if (cap_cb && cap_cb->unicast_discovery_complete) {
500 			cap_cb->unicast_discovery_complete(conn, 0, NULL);
501 		}
502 	} else {
503 		const struct bt_gatt_include *included_service = attr->user_data;
504 		struct cap_unicast_client *client = CONTAINER_OF(params,
505 								 struct cap_unicast_client,
506 								 param);
507 
508 		/* If the remote CAS includes CSIS, we first check if we
509 		 * have already discovered it, and if so we can just retrieve it
510 		 * and forward it to the application. If not, then we start
511 		 * CSIS discovery
512 		 */
513 		client->csis_start_handle = included_service->start_handle;
514 		client->csis_inst = bt_csip_set_coordinator_csis_inst_by_handle(
515 					conn, client->csis_start_handle);
516 
517 		if (client->csis_inst == NULL) {
518 			static struct bt_csip_set_coordinator_cb csis_client_cb = {
519 				.discover = csis_client_discover_cb
520 			};
521 			static bool csis_cbs_registered;
522 			int err;
523 
524 			LOG_DBG("CAS CSIS not known, discovering");
525 
526 			if (!csis_cbs_registered) {
527 				bt_csip_set_coordinator_register_cb(&csis_client_cb);
528 				csis_cbs_registered = true;
529 			}
530 
531 			err = bt_csip_set_coordinator_discover(conn);
532 			if (err != 0) {
533 				LOG_DBG("Discover failed (err %d)", err);
534 				if (cap_cb && cap_cb->unicast_discovery_complete) {
535 					cap_cb->unicast_discovery_complete(conn,
536 									   err,
537 									   NULL);
538 				}
539 			}
540 		} else if (cap_cb && cap_cb->unicast_discovery_complete) {
541 			LOG_DBG("Found CAS with CSIS");
542 			cap_cb->unicast_discovery_complete(conn, 0,
543 							   client->csis_inst);
544 		}
545 	}
546 
547 	return BT_GATT_ITER_STOP;
548 }
549 
cap_unicast_discover_cas_cb(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * params)550 static uint8_t cap_unicast_discover_cas_cb(struct bt_conn *conn,
551 				       const struct bt_gatt_attr *attr,
552 				       struct bt_gatt_discover_params *params)
553 {
554 	params->func = NULL;
555 
556 	if (attr == NULL) {
557 		if (cap_cb && cap_cb->unicast_discovery_complete) {
558 			cap_cb->unicast_discovery_complete(conn, -ENODATA,
559 							   NULL);
560 		}
561 	} else {
562 		const struct bt_gatt_service_val *prim_service = attr->user_data;
563 		struct cap_unicast_client *client = CONTAINER_OF(params,
564 								 struct cap_unicast_client,
565 								 param);
566 		int err;
567 
568 		client->cas_found = true;
569 		client->conn = bt_conn_ref(conn);
570 
571 		if (attr->handle == prim_service->end_handle) {
572 			LOG_DBG("Found CAS without CSIS");
573 			cap_cb->unicast_discovery_complete(conn, 0, NULL);
574 
575 			return BT_GATT_ITER_STOP;
576 		}
577 
578 		LOG_DBG("Found CAS, discovering included CSIS");
579 
580 		params->uuid = NULL;
581 		params->start_handle = attr->handle + 1;
582 		params->end_handle = prim_service->end_handle;
583 		params->type = BT_GATT_DISCOVER_INCLUDE;
584 		params->func = cap_unicast_discover_included_cb;
585 
586 		err = bt_gatt_discover(conn, params);
587 		if (err != 0) {
588 			LOG_DBG("Discover failed (err %d)", err);
589 
590 			params->func = NULL;
591 			if (cap_cb && cap_cb->unicast_discovery_complete) {
592 				cap_cb->unicast_discovery_complete(conn, err,
593 								   NULL);
594 			}
595 		}
596 	}
597 
598 	return BT_GATT_ITER_STOP;
599 }
600 
bt_cap_initiator_unicast_discover(struct bt_conn * conn)601 int bt_cap_initiator_unicast_discover(struct bt_conn *conn)
602 {
603 	struct bt_gatt_discover_params *param;
604 	int err;
605 
606 	CHECKIF(conn == NULL) {
607 		LOG_DBG("NULL conn");
608 		return -EINVAL;
609 	}
610 
611 	param = &bt_cap_unicast_clients[bt_conn_index(conn)].param;
612 
613 	/* use param->func to tell if a client is "busy" */
614 	if (param->func != NULL) {
615 		return -EBUSY;
616 	}
617 
618 	param->func = cap_unicast_discover_cas_cb;
619 	param->uuid = cas_uuid;
620 	param->type = BT_GATT_DISCOVER_PRIMARY;
621 	param->start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
622 	param->end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
623 
624 	err = bt_gatt_discover(conn, param);
625 	if (err != 0) {
626 		param->func = NULL;
627 	}
628 
629 	return err;
630 }
631 
cap_stream_in_active_proc(const struct bt_cap_stream * cap_stream)632 static bool cap_stream_in_active_proc(const struct bt_cap_stream *cap_stream)
633 {
634 	if (!cap_proc_is_active()) {
635 		return false;
636 	}
637 
638 	for (size_t i = 0U; i < active_proc.stream_cnt; i++) {
639 		if (active_proc.proc_param[i].stream == cap_stream) {
640 			return true;
641 		}
642 	}
643 
644 	return false;
645 }
646 
valid_unicast_audio_start_param(const struct bt_cap_unicast_audio_start_param * param,struct bt_bap_unicast_group * unicast_group)647 static bool valid_unicast_audio_start_param(const struct bt_cap_unicast_audio_start_param *param,
648 					    struct bt_bap_unicast_group *unicast_group)
649 {
650 	CHECKIF(param == NULL) {
651 		LOG_DBG("param is NULL");
652 		return false;
653 	}
654 
655 	CHECKIF(param->count == 0) {
656 		LOG_DBG("Invalid param->count: %u", param->count);
657 		return false;
658 	}
659 
660 	CHECKIF(param->stream_params == NULL) {
661 		LOG_DBG("param->stream_params is NULL");
662 		return false;
663 	}
664 
665 	CHECKIF(param->count > CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT) {
666 		LOG_DBG("param->count (%zu) is larger than "
667 			"CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT (%d)",
668 			param->count,
669 			CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT);
670 		return false;
671 	}
672 
673 	for (size_t i = 0U; i < param->count; i++) {
674 		const struct bt_cap_unicast_audio_start_stream_param *stream_param =
675 									&param->stream_params[i];
676 		const union bt_cap_set_member *member = &stream_param->member;
677 		const struct bt_cap_stream *cap_stream = stream_param->stream;
678 		const struct bt_audio_codec_cfg *codec_cfg = stream_param->codec_cfg;
679 		const struct bt_bap_stream *bap_stream;
680 
681 		CHECKIF(stream_param->codec_cfg == NULL) {
682 			LOG_DBG("param->stream_params[%zu].codec_cfg  is NULL", i);
683 			return false;
684 		}
685 
686 		CHECKIF(!cap_initiator_valid_metadata(codec_cfg->meta, codec_cfg->meta_len)) {
687 			LOG_DBG("param->stream_params[%zu].codec_cfg  is invalid", i);
688 			return false;
689 		}
690 
691 		CHECKIF(stream_param->ep == NULL) {
692 			LOG_DBG("param->stream_params[%zu].ep is NULL", i);
693 			return false;
694 		}
695 
696 		CHECKIF(member == NULL) {
697 			LOG_DBG("param->stream_params[%zu].member is NULL", i);
698 			return false;
699 		}
700 
701 		if (param->type == BT_CAP_SET_TYPE_AD_HOC) {
702 			struct cap_unicast_client *client;
703 
704 			CHECKIF(member->member == NULL) {
705 				LOG_DBG("param->members[%zu] is NULL", i);
706 				return false;
707 			}
708 
709 			client = &bt_cap_unicast_clients[bt_conn_index(member->member)];
710 
711 			if (!client->cas_found) {
712 				LOG_DBG("CAS was not found for param->members[%zu]", i);
713 				return false;
714 			}
715 		}
716 
717 		if (param->type == BT_CAP_SET_TYPE_CSIP) {
718 			struct cap_unicast_client *client;
719 
720 			CHECKIF(member->csip == NULL) {
721 				LOG_DBG("param->csip.set[%zu] is NULL", i);
722 				return false;
723 			}
724 
725 			client = lookup_unicast_client_by_csis(member->csip);
726 			if (client == NULL) {
727 				LOG_DBG("CSIS was not found for param->members[%zu]", i);
728 				return false;
729 			}
730 		}
731 
732 		CHECKIF(cap_stream == NULL) {
733 			LOG_DBG("param->streams[%zu] is NULL", i);
734 			return false;
735 		}
736 
737 		bap_stream = &cap_stream->bap_stream;
738 
739 		CHECKIF(bap_stream->ep != NULL) {
740 			LOG_DBG("param->streams[%zu] is already started", i);
741 			return false;
742 		}
743 
744 		CHECKIF(bap_stream->group == NULL) {
745 			LOG_DBG("param->streams[%zu] is not in a unicast group", i);
746 			return false;
747 		}
748 
749 		CHECKIF(bap_stream->group != unicast_group) {
750 			LOG_DBG("param->streams[%zu] is not in this group %p", i, unicast_group);
751 			return false;
752 		}
753 
754 		for (size_t j = 0U; j < i; j++) {
755 			if (param->stream_params[j].stream == cap_stream) {
756 				LOG_DBG("param->stream_params[%zu] (%p) is "
757 					"duplicated by "
758 					"param->stream_params[%zu] (%p)",
759 					j, param->stream_params[j].stream,
760 					i, cap_stream);
761 				return false;
762 			}
763 		}
764 	}
765 
766 	return true;
767 }
768 
cap_initiator_unicast_audio_proc_complete(void)769 static void cap_initiator_unicast_audio_proc_complete(void)
770 {
771 	struct bt_bap_unicast_group *unicast_group;
772 	enum cap_unicast_proc_type proc_type;
773 	struct bt_conn *failed_conn;
774 	int err;
775 
776 	unicast_group = active_proc.unicast_group;
777 	failed_conn = active_proc.failed_conn;
778 	err = active_proc.err;
779 	proc_type = active_proc.proc_type;
780 	(void)memset(&active_proc, 0, sizeof(active_proc));
781 
782 	if (cap_cb == NULL) {
783 		return;
784 	}
785 
786 	switch (proc_type) {
787 	case CAP_UNICAST_PROC_TYPE_START:
788 		if (cap_cb->unicast_start_complete != NULL) {
789 			cap_cb->unicast_start_complete(unicast_group, err, failed_conn);
790 		}
791 		break;
792 	case CAP_UNICAST_PROC_TYPE_UPDATE:
793 		if (cap_cb->unicast_update_complete != NULL) {
794 			cap_cb->unicast_update_complete(err, failed_conn);
795 		}
796 		break;
797 	case CAP_UNICAST_PROC_TYPE_STOP:
798 		if (cap_cb->unicast_stop_complete != NULL) {
799 			cap_cb->unicast_stop_complete(unicast_group, err, failed_conn);
800 		}
801 		break;
802 	case CAP_UNICAST_PROC_TYPE_NONE:
803 	default:
804 		__ASSERT(false, "Invalid proc_type: %u", proc_type);
805 	}
806 }
807 
cap_initiator_unicast_audio_configure(const struct bt_cap_unicast_audio_start_param * param)808 static int cap_initiator_unicast_audio_configure(
809 	const struct bt_cap_unicast_audio_start_param *param)
810 {
811 	struct cap_unicast_proc_param *proc_param;
812 	struct bt_audio_codec_cfg *codec_cfg;
813 	struct bt_bap_stream *bap_stream;
814 	struct bt_bap_ep *ep;
815 	struct bt_conn *conn;
816 	int err;
817 	/** TODO: If this is a CSIP set, then the order of the procedures may
818 	 * not match the order in the parameters, and the CSIP ordered access
819 	 * procedure should be used.
820 	 */
821 
822 	for (size_t i = 0U; i < param->count; i++) {
823 		struct bt_cap_unicast_audio_start_stream_param *stream_param =
824 									&param->stream_params[i];
825 		union bt_cap_set_member *member = &stream_param->member;
826 		struct bt_cap_stream *cap_stream = stream_param->stream;
827 
828 		if (param->type == BT_CAP_SET_TYPE_AD_HOC) {
829 			conn = member->member;
830 		} else {
831 			struct cap_unicast_client *client;
832 
833 			/* We have verified that `client` wont be NULL in
834 			 * `valid_unicast_audio_start_param`.
835 			 */
836 			client = lookup_unicast_client_by_csis(member->csip);
837 			__ASSERT(client != NULL, "client is NULL");
838 			conn = client->conn;
839 		}
840 
841 		/* Ensure that ops are registered before any procedures are started */
842 		bt_cap_stream_ops_register_bap(cap_stream);
843 
844 		/* Store the necessary parameters as we cannot assume that the supplied parameters
845 		 * are kept valid
846 		 */
847 		active_proc.proc_param[i].stream = cap_stream;
848 		active_proc.proc_param[i].start.ep = stream_param->ep;
849 		active_proc.proc_param[i].start.conn = conn;
850 		memcpy(&active_proc.proc_param[i].start.codec_cfg, stream_param->codec_cfg,
851 		       sizeof(*stream_param->codec_cfg));
852 	}
853 
854 	/* Store the information about the active procedure so that we can
855 	 * continue the procedure after each step
856 	 */
857 	atomic_set_bit(active_proc.proc_state_flags, CAP_UNICAST_PROC_STATE_ACTIVE);
858 	active_proc.stream_cnt = param->count;
859 
860 	cap_set_subproc(CAP_UNICAST_SUBPROC_TYPE_CODEC_CONFIG);
861 
862 	proc_param = &active_proc.proc_param[0];
863 	bap_stream = &proc_param->stream->bap_stream;
864 	codec_cfg = &proc_param->start.codec_cfg;
865 	conn = proc_param->start.conn;
866 	ep = proc_param->start.ep;
867 
868 	/* Since BAP operations may require a write long or a read long on the notification,
869 	 * we cannot assume that we can do multiple streams at once, thus do it one at a time.
870 	 * TODO: We should always be able to do one per ACL, so there is room for optimization.
871 	 */
872 	err = bt_bap_stream_config(conn, bap_stream, ep, codec_cfg);
873 	if (err != 0) {
874 		LOG_DBG("Failed to config stream %p: %d", proc_param->stream, err);
875 
876 		(void)memset(&active_proc, 0, sizeof(active_proc));
877 	} else {
878 		active_proc.stream_initiated_cnt++;
879 	}
880 
881 	return err;
882 }
883 
bt_cap_initiator_unicast_audio_start(const struct bt_cap_unicast_audio_start_param * param,struct bt_bap_unicast_group * unicast_group)884 int bt_cap_initiator_unicast_audio_start(const struct bt_cap_unicast_audio_start_param *param,
885 					 struct bt_bap_unicast_group *unicast_group)
886 {
887 	if (cap_proc_is_active()) {
888 		LOG_DBG("A CAP procedure is already in progress");
889 
890 		return -EBUSY;
891 	}
892 
893 	CHECKIF(unicast_group == NULL) {
894 		LOG_DBG("unicast_group is NULL");
895 		return -EINVAL;
896 	}
897 
898 	if (!valid_unicast_audio_start_param(param, unicast_group)) {
899 		return -EINVAL;
900 	}
901 
902 	active_proc.unicast_group = unicast_group;
903 	active_proc.proc_type = CAP_UNICAST_PROC_TYPE_START;
904 
905 	return cap_initiator_unicast_audio_configure(param);
906 }
907 
bt_cap_initiator_codec_configured(struct bt_cap_stream * cap_stream)908 void bt_cap_initiator_codec_configured(struct bt_cap_stream *cap_stream)
909 {
910 	struct bt_conn
911 		*conns[MIN(CONFIG_BT_MAX_CONN, CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT)];
912 	struct cap_unicast_proc_param *proc_param;
913 	struct bt_bap_unicast_group *unicast_group;
914 
915 	if (!cap_stream_in_active_proc(cap_stream)) {
916 		/* State change happened outside of a procedure; ignore */
917 		return;
918 	}
919 
920 	if (active_proc.subproc_type == CAP_UNICAST_SUBPROC_TYPE_RELEASE) {
921 		/* When releasing a stream, it may go into the codec configured state if
922 		 * the unicast server caches the configuration - We treat it as a release
923 		 */
924 		bt_cap_initiator_released(cap_stream);
925 		return;
926 	} else if (active_proc.subproc_type != CAP_UNICAST_SUBPROC_TYPE_CODEC_CONFIG) {
927 		/* Unexpected callback - Abort */
928 		cap_abort_proc(cap_stream->bap_stream.conn, -EBADMSG);
929 	} else {
930 		active_proc.stream_done_cnt++;
931 
932 		LOG_DBG("Stream %p configured (%zu/%zu streams done)", cap_stream,
933 			active_proc.stream_done_cnt, active_proc.stream_cnt);
934 	}
935 
936 	if (cap_proc_is_aborted()) {
937 		if (cap_proc_all_streams_handled()) {
938 			cap_initiator_unicast_audio_proc_complete();
939 		}
940 
941 		return;
942 	}
943 
944 	if (!cap_proc_is_done()) {
945 		struct bt_cap_stream *next_cap_stream =
946 			active_proc.proc_param[active_proc.stream_done_cnt].stream;
947 		struct bt_conn *conn =
948 			active_proc.proc_param[active_proc.stream_done_cnt].start.conn;
949 		struct bt_bap_ep *ep = active_proc.proc_param[active_proc.stream_done_cnt].start.ep;
950 		struct bt_audio_codec_cfg *codec_cfg =
951 			&active_proc.proc_param[active_proc.stream_done_cnt].start.codec_cfg;
952 		struct bt_bap_stream *bap_stream = &next_cap_stream->bap_stream;
953 		int err;
954 
955 		/* Since BAP operations may require a write long or a read long on the notification,
956 		 * we cannot assume that we can do multiple streams at once, thus do it one at a
957 		 * time.
958 		 * TODO: We should always be able to do one per ACL, so there is room for
959 		 * optimization.
960 		 */
961 		err = bt_bap_stream_config(conn, bap_stream, ep, codec_cfg);
962 		if (err != 0) {
963 			LOG_DBG("Failed to config stream %p: %d", next_cap_stream, err);
964 
965 			cap_abort_proc(conn, err);
966 			cap_initiator_unicast_audio_proc_complete();
967 		} else {
968 			active_proc.stream_initiated_cnt++;
969 		}
970 
971 		return;
972 	}
973 
974 	/* The QoS Configure procedure works on a set of connections and a
975 	 * unicast group, so we generate a list of unique connection pointers
976 	 * for the procedure
977 	 */
978 	(void)memset(conns, 0, sizeof(conns));
979 	for (size_t i = 0U; i < active_proc.stream_cnt; i++) {
980 		struct bt_conn *stream_conn = active_proc.proc_param[i].stream->bap_stream.conn;
981 		struct bt_conn **free_conn = NULL;
982 		bool already_added = false;
983 
984 		for (size_t j = 0U; j < ARRAY_SIZE(conns); j++) {
985 			if (stream_conn == conns[j]) {
986 				already_added = true;
987 				break;
988 			} else if (conns[j] == NULL && free_conn == NULL) {
989 				free_conn = &conns[j];
990 			}
991 		}
992 
993 		if (already_added) {
994 			continue;
995 		}
996 
997 		if (free_conn != NULL) {
998 			*free_conn = stream_conn;
999 		} else {
1000 			__ASSERT_PRINT("No free conns");
1001 		}
1002 	}
1003 
1004 	/* All streams in the procedure share the same unicast group, so we just
1005 	 * use the reference from the first stream
1006 	 */
1007 	proc_param = &active_proc.proc_param[0];
1008 	unicast_group = (struct bt_bap_unicast_group *)proc_param->stream->bap_stream.group;
1009 	cap_set_subproc(CAP_UNICAST_SUBPROC_TYPE_QOS_CONFIG);
1010 
1011 	for (size_t i = 0U; i < ARRAY_SIZE(conns); i++) {
1012 		int err;
1013 
1014 		/* When conns[i] is NULL, we have QoS Configured all unique connections */
1015 		if (conns[i] == NULL) {
1016 			break;
1017 		}
1018 
1019 		err = bt_bap_stream_qos(conns[i], unicast_group);
1020 		if (err != 0) {
1021 			LOG_DBG("Failed to set stream QoS for conn %p and group %p: %d",
1022 				(void *)conns[i], unicast_group, err);
1023 
1024 			/* End or mark procedure as aborted.
1025 			 * If we have sent any requests over air, we will abort
1026 			 * once all sent requests has completed
1027 			 */
1028 			cap_abort_proc(conns[i], err);
1029 			if (i == 0U) {
1030 				cap_initiator_unicast_audio_proc_complete();
1031 			}
1032 
1033 			return;
1034 		}
1035 
1036 		active_proc.stream_initiated_cnt++;
1037 	}
1038 }
1039 
bt_cap_initiator_qos_configured(struct bt_cap_stream * cap_stream)1040 void bt_cap_initiator_qos_configured(struct bt_cap_stream *cap_stream)
1041 {
1042 	struct cap_unicast_proc_param *proc_param;
1043 	struct bt_cap_stream *next_cap_stream;
1044 	struct bt_bap_stream *bap_stream;
1045 	int err;
1046 
1047 	if (!cap_stream_in_active_proc(cap_stream)) {
1048 		/* State change happened outside of a procedure; ignore */
1049 		return;
1050 	}
1051 
1052 	if (active_proc.subproc_type != CAP_UNICAST_SUBPROC_TYPE_QOS_CONFIG) {
1053 		/* Unexpected callback - Abort */
1054 		cap_abort_proc(cap_stream->bap_stream.conn, -EBADMSG);
1055 	} else {
1056 		active_proc.stream_done_cnt++;
1057 
1058 		LOG_DBG("Stream %p QoS configured (%zu/%zu streams done)", cap_stream,
1059 			active_proc.stream_done_cnt, active_proc.stream_cnt);
1060 	}
1061 
1062 	if (cap_proc_is_aborted()) {
1063 		if (cap_proc_all_streams_handled()) {
1064 			cap_initiator_unicast_audio_proc_complete();
1065 		}
1066 
1067 		return;
1068 	}
1069 
1070 	if (!cap_proc_is_done()) {
1071 		/* Not yet finished, wait for all */
1072 		return;
1073 	}
1074 
1075 	cap_set_subproc(CAP_UNICAST_SUBPROC_TYPE_ENABLE);
1076 	proc_param = &active_proc.proc_param[0];
1077 	next_cap_stream = proc_param->stream;
1078 	bap_stream = &next_cap_stream->bap_stream;
1079 
1080 	/* Since BAP operations may require a write long or a read long on the notification, we
1081 	 * cannot assume that we can do multiple streams at once, thus do it one at a time.
1082 	 * TODO: We should always be able to do one per ACL, so there is room for optimization.
1083 	 */
1084 	err = bt_bap_stream_enable(bap_stream, bap_stream->codec_cfg->meta,
1085 				   bap_stream->codec_cfg->meta_len);
1086 	if (err != 0) {
1087 		LOG_DBG("Failed to enable stream %p: %d", next_cap_stream, err);
1088 
1089 		cap_abort_proc(bap_stream->conn, err);
1090 		cap_initiator_unicast_audio_proc_complete();
1091 	} else {
1092 		active_proc.stream_initiated_cnt++;
1093 	}
1094 }
1095 
bt_cap_initiator_enabled(struct bt_cap_stream * cap_stream)1096 void bt_cap_initiator_enabled(struct bt_cap_stream *cap_stream)
1097 {
1098 	struct cap_unicast_proc_param *proc_param;
1099 	struct bt_bap_stream *bap_stream;
1100 	int err;
1101 
1102 	if (!cap_stream_in_active_proc(cap_stream)) {
1103 		/* State change happened outside of a procedure; ignore */
1104 		return;
1105 	}
1106 
1107 	if (active_proc.subproc_type != CAP_UNICAST_SUBPROC_TYPE_ENABLE) {
1108 		/* Unexpected callback - Abort */
1109 		cap_abort_proc(cap_stream->bap_stream.conn, -EBADMSG);
1110 	} else {
1111 		active_proc.stream_done_cnt++;
1112 
1113 		LOG_DBG("Stream %p enabled (%zu/%zu streams done)", cap_stream,
1114 			active_proc.stream_done_cnt, active_proc.stream_cnt);
1115 	}
1116 
1117 	if (cap_proc_is_aborted()) {
1118 		if (cap_proc_all_streams_handled()) {
1119 			cap_initiator_unicast_audio_proc_complete();
1120 		}
1121 
1122 		return;
1123 	}
1124 
1125 	if (!cap_proc_is_done()) {
1126 		struct bt_cap_stream *next_cap_stream =
1127 			active_proc.proc_param[active_proc.stream_done_cnt].stream;
1128 		struct bt_bap_stream *next_bap_stream = &next_cap_stream->bap_stream;
1129 
1130 		/* Since BAP operations may require a write long or a read long on the notification,
1131 		 * we cannot assume that we can do multiple streams at once, thus do it one at a
1132 		 * time.
1133 		 * TODO: We should always be able to do one per ACL, so there is room for
1134 		 * optimization.
1135 		 */
1136 		err = bt_bap_stream_enable(next_bap_stream, next_bap_stream->codec_cfg->meta,
1137 					   next_bap_stream->codec_cfg->meta_len);
1138 		if (err != 0) {
1139 			LOG_DBG("Failed to enable stream %p: %d", next_cap_stream, err);
1140 
1141 			cap_abort_proc(next_bap_stream->conn, err);
1142 			cap_initiator_unicast_audio_proc_complete();
1143 		} else {
1144 			active_proc.stream_initiated_cnt++;
1145 		}
1146 
1147 		return;
1148 	}
1149 
1150 	cap_set_subproc(CAP_UNICAST_SUBPROC_TYPE_START);
1151 	proc_param = &active_proc.proc_param[0];
1152 	bap_stream = &proc_param->stream->bap_stream;
1153 
1154 	/* Since BAP operations may require a write long or a read long on the notification, we
1155 	 * cannot assume that we can do multiple streams at once, thus do it one at a time.
1156 	 * TODO: We should always be able to do one per ACL, so there is room for optimization.
1157 	 */
1158 	err = bt_bap_stream_start(bap_stream);
1159 	if (err != 0) {
1160 		LOG_DBG("Failed to start stream %p: %d", proc_param->stream, err);
1161 
1162 		/* End and mark procedure as aborted.
1163 		 * If we have sent any requests over air, we will abort
1164 		 * once all sent requests has completed
1165 		 */
1166 		cap_abort_proc(bap_stream->conn, err);
1167 		cap_initiator_unicast_audio_proc_complete();
1168 
1169 		return;
1170 	}
1171 }
1172 
bt_cap_initiator_started(struct bt_cap_stream * cap_stream)1173 void bt_cap_initiator_started(struct bt_cap_stream *cap_stream)
1174 {
1175 	if (!cap_stream_in_active_proc(cap_stream)) {
1176 		/* State change happened outside of a procedure; ignore */
1177 		return;
1178 	}
1179 
1180 	if (active_proc.subproc_type != CAP_UNICAST_SUBPROC_TYPE_START) {
1181 		/* Unexpected callback - Abort */
1182 		cap_abort_proc(cap_stream->bap_stream.conn, -EBADMSG);
1183 	} else {
1184 		active_proc.stream_done_cnt++;
1185 
1186 		LOG_DBG("Stream %p started (%zu/%zu streams done)",
1187 			cap_stream, active_proc.stream_done_cnt,
1188 			active_proc.stream_cnt);
1189 	}
1190 
1191 	/* Since bt_bap_stream_start connects the ISO, we can, at this point,
1192 	 * only do this one by one due to a restriction in the ISO layer
1193 	 * (maximum 1 outstanding ISO connection request at any one time).
1194 	 */
1195 	if (!cap_proc_is_done()) {
1196 		struct bt_cap_stream *next_cap_stream =
1197 			active_proc.proc_param[active_proc.stream_done_cnt].stream;
1198 		struct bt_bap_stream *bap_stream = &next_cap_stream->bap_stream;
1199 		int err;
1200 
1201 		/* Not yet finished, start next */
1202 		err = bt_bap_stream_start(bap_stream);
1203 		if (err != 0) {
1204 			LOG_DBG("Failed to start stream %p: %d", next_cap_stream, err);
1205 
1206 			/* End and mark procedure as aborted.
1207 			 * If we have sent any requests over air, we will abort
1208 			 * once all sent requests has completed
1209 			 */
1210 			cap_abort_proc(bap_stream->conn, err);
1211 			cap_initiator_unicast_audio_proc_complete();
1212 		}
1213 	} else {
1214 		cap_initiator_unicast_audio_proc_complete();
1215 	}
1216 }
1217 
can_update_metadata(const struct bt_bap_stream * bap_stream)1218 static bool can_update_metadata(const struct bt_bap_stream *bap_stream)
1219 {
1220 	struct bt_bap_ep_info ep_info;
1221 	int err;
1222 
1223 	if (bap_stream->conn == NULL) {
1224 		return false;
1225 	}
1226 
1227 	err = bt_bap_ep_get_info(bap_stream->ep, &ep_info);
1228 	if (err != 0) {
1229 		LOG_DBG("Failed to get endpoint info %p: %d", bap_stream, err);
1230 
1231 		return false;
1232 	}
1233 
1234 	return ep_info.state == BT_BAP_EP_STATE_ENABLING ||
1235 	       ep_info.state == BT_BAP_EP_STATE_STREAMING;
1236 }
1237 
bt_cap_initiator_unicast_audio_update(const struct bt_cap_unicast_audio_update_param params[],size_t count)1238 int bt_cap_initiator_unicast_audio_update(const struct bt_cap_unicast_audio_update_param params[],
1239 					  size_t count)
1240 {
1241 	struct cap_unicast_proc_param *proc_param;
1242 	struct bt_bap_stream *bap_stream;
1243 	const uint8_t *meta;
1244 	size_t meta_len;
1245 	int err;
1246 
1247 	CHECKIF(params == NULL) {
1248 		LOG_DBG("params is NULL");
1249 
1250 		return -EINVAL;
1251 	}
1252 
1253 	CHECKIF(count == 0) {
1254 		LOG_DBG("count is 0");
1255 
1256 		return -EINVAL;
1257 	}
1258 
1259 	if (cap_proc_is_active()) {
1260 		LOG_DBG("A CAP procedure is already in progress");
1261 
1262 		return -EBUSY;
1263 	}
1264 
1265 	for (size_t i = 0U; i < count; i++) {
1266 		struct bt_cap_stream *cap_stream = params[i].stream;
1267 
1268 		CHECKIF(cap_stream == NULL) {
1269 			LOG_DBG("params[%zu].stream is NULL", i);
1270 
1271 			return -EINVAL;
1272 		}
1273 
1274 		CHECKIF(cap_stream->bap_stream.conn == NULL) {
1275 			LOG_DBG("params[%zu].stream->bap_stream.conn is NULL", i);
1276 
1277 			return -EINVAL;
1278 		}
1279 
1280 		CHECKIF(!cap_initiator_valid_metadata(params[i].meta,
1281 						      params[i].meta_len)) {
1282 			LOG_DBG("params[%zu].meta is invalid", i);
1283 
1284 			return -EINVAL;
1285 		}
1286 
1287 		for (size_t j = 0U; j < i; j++) {
1288 			if (params[j].stream == cap_stream) {
1289 				LOG_DBG("param.streams[%zu] is duplicated by param.streams[%zu]",
1290 					j, i);
1291 				return -EINVAL;
1292 			}
1293 		}
1294 
1295 		if (!can_update_metadata(&cap_stream->bap_stream)) {
1296 			LOG_DBG("params[%zu].stream is not in right state to be updated", i);
1297 
1298 			return -EINVAL;
1299 		}
1300 
1301 		active_proc.proc_param[i].stream = cap_stream;
1302 		active_proc.proc_param[i].meta_update.meta_len = params[i].meta_len;
1303 		memcpy(&active_proc.proc_param[i].meta_update.meta, params[i].meta,
1304 		       params[i].meta_len);
1305 	}
1306 
1307 	atomic_set_bit(active_proc.proc_state_flags, CAP_UNICAST_PROC_STATE_ACTIVE);
1308 	active_proc.stream_cnt = count;
1309 
1310 	active_proc.proc_type = CAP_UNICAST_PROC_TYPE_UPDATE;
1311 	cap_set_subproc(CAP_UNICAST_SUBPROC_TYPE_META_UPDATE);
1312 
1313 	proc_param = &active_proc.proc_param[0];
1314 	bap_stream = &proc_param->stream->bap_stream;
1315 	meta_len = proc_param->meta_update.meta_len;
1316 	meta = proc_param->meta_update.meta;
1317 
1318 	err = bt_bap_stream_metadata(bap_stream, meta, meta_len);
1319 	if (err != 0) {
1320 		LOG_DBG("Failed to update metadata for stream %p: %d", proc_param->stream, err);
1321 
1322 		(void)memset(&active_proc, 0, sizeof(active_proc));
1323 	} else {
1324 		active_proc.stream_initiated_cnt++;
1325 	}
1326 
1327 	return err;
1328 }
1329 
bt_cap_initiator_unicast_audio_cancel(void)1330 int bt_cap_initiator_unicast_audio_cancel(void)
1331 {
1332 	if (!cap_proc_is_active() && !cap_proc_is_aborted()) {
1333 		LOG_DBG("No CAP procedure is in progress");
1334 
1335 		return -EALREADY;
1336 	}
1337 
1338 	cap_abort_proc(NULL, -ECANCELED);
1339 	cap_initiator_unicast_audio_proc_complete();
1340 
1341 	return 0;
1342 }
1343 
bt_cap_initiator_metadata_updated(struct bt_cap_stream * cap_stream)1344 void bt_cap_initiator_metadata_updated(struct bt_cap_stream *cap_stream)
1345 {
1346 	if (!cap_stream_in_active_proc(cap_stream)) {
1347 		/* State change happened outside of a procedure; ignore */
1348 		return;
1349 	}
1350 
1351 	if (active_proc.subproc_type != CAP_UNICAST_SUBPROC_TYPE_META_UPDATE) {
1352 		/* Unexpected callback - Abort */
1353 		cap_abort_proc(cap_stream->bap_stream.conn, -EBADMSG);
1354 	} else {
1355 		active_proc.stream_done_cnt++;
1356 
1357 		LOG_DBG("Stream %p QoS metadata updated (%zu/%zu streams done)",
1358 			cap_stream, active_proc.stream_done_cnt,
1359 			active_proc.stream_cnt);
1360 	}
1361 
1362 	if (cap_proc_is_aborted()) {
1363 		if (cap_proc_all_streams_handled()) {
1364 			cap_initiator_unicast_audio_proc_complete();
1365 		}
1366 
1367 		return;
1368 	}
1369 
1370 	if (!cap_proc_is_done()) {
1371 		const size_t meta_len =
1372 			active_proc.proc_param[active_proc.stream_done_cnt].meta_update.meta_len;
1373 		const uint8_t *meta =
1374 			active_proc.proc_param[active_proc.stream_done_cnt].meta_update.meta;
1375 		struct bt_cap_stream *next_cap_stream =
1376 			active_proc.proc_param[active_proc.stream_done_cnt].stream;
1377 		struct bt_bap_stream *bap_stream = &next_cap_stream->bap_stream;
1378 		int err;
1379 
1380 		/* Since BAP operations may require a write long or a read long on the notification,
1381 		 * we cannot assume that we can do multiple streams at once, thus do it one at a
1382 		 * time.
1383 		 * TODO: We should always be able to do one per ACL, so there is room for
1384 		 * optimization.
1385 		 */
1386 
1387 		err = bt_bap_stream_metadata(bap_stream, meta, meta_len);
1388 		if (err != 0) {
1389 			LOG_DBG("Failed to update metadata for stream %p: %d", next_cap_stream,
1390 				err);
1391 
1392 			cap_abort_proc(bap_stream->conn, err);
1393 			cap_initiator_unicast_audio_proc_complete();
1394 		} else {
1395 			active_proc.stream_initiated_cnt++;
1396 		}
1397 
1398 		return;
1399 	}
1400 
1401 	cap_initiator_unicast_audio_proc_complete();
1402 }
1403 
can_release(const struct bt_bap_stream * bap_stream)1404 static bool can_release(const struct bt_bap_stream *bap_stream)
1405 {
1406 	struct bt_bap_ep_info ep_info;
1407 	int err;
1408 
1409 	if (bap_stream->conn == NULL) {
1410 		return false;
1411 	}
1412 
1413 	err = bt_bap_ep_get_info(bap_stream->ep, &ep_info);
1414 	if (err != 0) {
1415 		LOG_DBG("Failed to get endpoint info %p: %d", bap_stream, err);
1416 
1417 		return false;
1418 	}
1419 
1420 	return ep_info.state != BT_BAP_EP_STATE_IDLE;
1421 }
1422 
bt_cap_initiator_unicast_audio_stop(struct bt_bap_unicast_group * unicast_group)1423 int bt_cap_initiator_unicast_audio_stop(struct bt_bap_unicast_group *unicast_group)
1424 {
1425 	struct cap_unicast_proc_param *proc_param;
1426 	struct bt_bap_stream *bap_stream;
1427 	size_t stream_cnt;
1428 	int err;
1429 
1430 	if (cap_proc_is_active()) {
1431 		LOG_DBG("A CAP procedure is already in progress");
1432 
1433 		return -EBUSY;
1434 	}
1435 
1436 	CHECKIF(unicast_group == NULL) {
1437 		LOG_DBG("unicast_group is NULL");
1438 		return -EINVAL;
1439 	}
1440 
1441 	stream_cnt = 0U;
1442 	SYS_SLIST_FOR_EACH_CONTAINER(&unicast_group->streams, bap_stream, _node) {
1443 		if (can_release(bap_stream)) {
1444 			struct bt_cap_stream *cap_stream =
1445 				CONTAINER_OF(bap_stream, struct bt_cap_stream, bap_stream);
1446 			active_proc.proc_param[stream_cnt].stream = cap_stream;
1447 			stream_cnt++;
1448 		}
1449 	}
1450 
1451 	if (stream_cnt == 0U) {
1452 		LOG_DBG("All streams are already stopped");
1453 
1454 		return -EALREADY;
1455 	}
1456 
1457 	atomic_set_bit(active_proc.proc_state_flags,
1458 		       CAP_UNICAST_PROC_STATE_ACTIVE);
1459 	active_proc.stream_cnt = stream_cnt;
1460 	active_proc.unicast_group = unicast_group;
1461 	active_proc.proc_type = CAP_UNICAST_PROC_TYPE_STOP;
1462 
1463 	cap_set_subproc(CAP_UNICAST_SUBPROC_TYPE_RELEASE);
1464 
1465 	/** TODO: If this is a CSIP set, then the order of the procedures may
1466 	 * not match the order in the parameters, and the CSIP ordered access
1467 	 * procedure should be used.
1468 	 */
1469 	proc_param = &active_proc.proc_param[0];
1470 	bap_stream = &proc_param->stream->bap_stream;
1471 
1472 	err = bt_bap_stream_release(bap_stream);
1473 	if (err != 0) {
1474 		LOG_DBG("Failed to stop bap_stream %p: %d", proc_param->stream, err);
1475 
1476 		(void)memset(&active_proc, 0, sizeof(active_proc));
1477 	} else {
1478 		active_proc.stream_initiated_cnt++;
1479 	}
1480 
1481 	return err;
1482 }
1483 
bt_cap_initiator_released(struct bt_cap_stream * cap_stream)1484 void bt_cap_initiator_released(struct bt_cap_stream *cap_stream)
1485 {
1486 	if (!cap_stream_in_active_proc(cap_stream)) {
1487 		/* State change happened outside of a procedure; ignore */
1488 		return;
1489 	}
1490 
1491 	if (active_proc.subproc_type != CAP_UNICAST_SUBPROC_TYPE_RELEASE) {
1492 		/* Unexpected callback - Abort */
1493 		cap_abort_proc(cap_stream->bap_stream.conn, -EBADMSG);
1494 	} else {
1495 		active_proc.stream_done_cnt++;
1496 
1497 		LOG_DBG("Stream %p released (%zu/%zu streams done)",
1498 			cap_stream, active_proc.stream_done_cnt,
1499 			active_proc.stream_cnt);
1500 	}
1501 
1502 	if (cap_proc_is_aborted()) {
1503 		if (cap_proc_all_streams_handled()) {
1504 			cap_initiator_unicast_audio_proc_complete();
1505 		}
1506 
1507 		return;
1508 	}
1509 
1510 	if (!cap_proc_is_done()) {
1511 		struct bt_cap_stream *next_cap_stream =
1512 			active_proc.proc_param[active_proc.stream_done_cnt].stream;
1513 		struct bt_bap_stream *bap_stream = &next_cap_stream->bap_stream;
1514 		int err;
1515 
1516 		/* Since BAP operations may require a write long or a read long on the notification,
1517 		 * we cannot assume that we can do multiple streams at once, thus do it one at a
1518 		 * time.
1519 		 * TODO: We should always be able to do one per ACL, so there is room for
1520 		 * optimization.
1521 		 */
1522 		err = bt_bap_stream_release(bap_stream);
1523 		if (err != 0) {
1524 			LOG_DBG("Failed to release stream %p: %d", next_cap_stream, err);
1525 
1526 			cap_abort_proc(bap_stream->conn, err);
1527 			cap_initiator_unicast_audio_proc_complete();
1528 		} else {
1529 			active_proc.stream_initiated_cnt++;
1530 		}
1531 	} else {
1532 		cap_initiator_unicast_audio_proc_complete();
1533 	}
1534 }
1535 
1536 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
1537 
1538 #if defined(CONFIG_BT_BAP_BROADCAST_SOURCE) && defined(CONFIG_BT_BAP_UNICAST_CLIENT)
1539 
bt_cap_initiator_unicast_to_broadcast(const struct bt_cap_unicast_to_broadcast_param * param,struct bt_cap_broadcast_source ** source)1540 int bt_cap_initiator_unicast_to_broadcast(
1541 	const struct bt_cap_unicast_to_broadcast_param *param,
1542 	struct bt_cap_broadcast_source **source)
1543 {
1544 	return -ENOSYS;
1545 }
1546 
bt_cap_initiator_broadcast_to_unicast(const struct bt_cap_broadcast_to_unicast_param * param,struct bt_bap_unicast_group ** unicast_group)1547 int bt_cap_initiator_broadcast_to_unicast(const struct bt_cap_broadcast_to_unicast_param *param,
1548 					  struct bt_bap_unicast_group **unicast_group)
1549 {
1550 	return -ENOSYS;
1551 }
1552 
1553 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE && CONFIG_BT_BAP_UNICAST_CLIENT */
1554