1 /*
2  * Copyright (c) 2022-2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <errno.h>
8 #include <stdbool.h>
9 #include <stddef.h>
10 #include <stdint.h>
11 #include <string.h>
12 
13 #include <zephyr/autoconf.h>
14 #include <zephyr/bluetooth/audio/audio.h>
15 #include <zephyr/bluetooth/audio/bap.h>
16 #include <zephyr/bluetooth/audio/cap.h>
17 #include <zephyr/bluetooth/audio/csip.h>
18 #include <zephyr/bluetooth/audio/tbs.h>
19 #include <zephyr/bluetooth/bluetooth.h>
20 #include <zephyr/bluetooth/conn.h>
21 #include <zephyr/bluetooth/gatt.h>
22 #include <zephyr/bluetooth/iso.h>
23 #include <zephyr/logging/log.h>
24 #include <zephyr/net/buf.h>
25 #include <zephyr/sys/__assert.h>
26 #include <zephyr/sys/check.h>
27 #include <zephyr/sys/util.h>
28 #include <zephyr/sys/util_macro.h>
29 
30 #include "bap_endpoint.h"
31 #include "cap_internal.h"
32 #include "ccid_internal.h"
33 #include "csip_internal.h"
34 
35 LOG_MODULE_REGISTER(bt_cap_initiator, CONFIG_BT_CAP_INITIATOR_LOG_LEVEL);
36 
37 #include "common/bt_str.h"
38 
39 static const struct bt_cap_initiator_cb *cap_cb;
40 
bt_cap_initiator_register_cb(const struct bt_cap_initiator_cb * cb)41 int bt_cap_initiator_register_cb(const struct bt_cap_initiator_cb *cb)
42 {
43 	CHECKIF(cb == NULL) {
44 		LOG_DBG("cb is NULL");
45 		return -EINVAL;
46 	}
47 
48 	CHECKIF(cap_cb != NULL) {
49 		LOG_DBG("callbacks already registered");
50 		return -EALREADY;
51 	}
52 
53 	cap_cb = cb;
54 
55 	return 0;
56 }
57 
bt_cap_initiator_unregister_cb(const struct bt_cap_initiator_cb * cb)58 int bt_cap_initiator_unregister_cb(const struct bt_cap_initiator_cb *cb)
59 {
60 	CHECKIF(cb == NULL) {
61 		LOG_DBG("cb is NULL");
62 		return -EINVAL;
63 	}
64 
65 	CHECKIF(cap_cb != cb) {
66 		LOG_DBG("cb is not registered");
67 		return -EINVAL;
68 	}
69 
70 	cap_cb = NULL;
71 
72 	return 0;
73 }
74 
75 struct valid_metadata_param {
76 	bool stream_context_found;
77 	bool valid;
78 };
79 
data_func_cb(struct bt_data * data,void * user_data)80 static bool data_func_cb(struct bt_data *data, void *user_data)
81 {
82 	struct valid_metadata_param *metadata_param = (struct valid_metadata_param *)user_data;
83 
84 	LOG_DBG("type %u len %u data %s", data->type, data->data_len,
85 		bt_hex(data->data, data->data_len));
86 
87 	if (data->type == BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT) {
88 		if (data->data_len != 2) { /* Stream context size */
89 			return false;
90 		}
91 
92 		metadata_param->stream_context_found = true;
93 	} else if (IS_ENABLED(CONFIG_BT_CCID) && data->type == BT_AUDIO_METADATA_TYPE_CCID_LIST) {
94 		/* If the application supplies a CCID list, we verify that the CCIDs exist on our
95 		 * device
96 		 */
97 		for (uint8_t i = 0U; i < data->data_len; i++) {
98 			const uint8_t ccid = data->data[i];
99 
100 			if (bt_ccid_find_attr(ccid) == NULL) {
101 				LOG_DBG("Unknown characteristic for CCID 0x%02X", ccid);
102 				metadata_param->valid = false;
103 
104 				return false;
105 			}
106 		}
107 	}
108 
109 	return true;
110 }
111 
cap_initiator_valid_metadata(const uint8_t meta[],size_t meta_len)112 static bool cap_initiator_valid_metadata(const uint8_t meta[], size_t meta_len)
113 {
114 	struct valid_metadata_param metadata_param = {
115 		.stream_context_found = false,
116 		.valid = true,
117 	};
118 	int err;
119 
120 	LOG_DBG("meta %p len %zu", meta, meta_len);
121 
122 	err = bt_audio_data_parse(meta, meta_len, data_func_cb, &metadata_param);
123 	if (err != 0 && err != -ECANCELED) {
124 		return false;
125 	}
126 
127 	if (!metadata_param.stream_context_found) {
128 		LOG_DBG("No streaming context supplied");
129 	}
130 
131 	return metadata_param.stream_context_found && metadata_param.valid;
132 }
133 
134 #if defined(CONFIG_BT_BAP_BROADCAST_SOURCE)
135 static struct bt_cap_broadcast_source {
136 	struct bt_bap_broadcast_source *bap_broadcast;
137 } broadcast_sources[CONFIG_BT_BAP_BROADCAST_SRC_COUNT];
138 
cap_initiator_broadcast_audio_start_valid_param(const struct bt_cap_initiator_broadcast_create_param * param)139 static bool cap_initiator_broadcast_audio_start_valid_param(
140 	const struct bt_cap_initiator_broadcast_create_param *param)
141 {
142 
143 	for (size_t i = 0U; i < param->subgroup_count; i++) {
144 		const struct bt_cap_initiator_broadcast_subgroup_param *subgroup_param;
145 		const struct bt_audio_codec_cfg *codec_cfg;
146 		bool valid_metadata;
147 
148 		subgroup_param = &param->subgroup_params[i];
149 		codec_cfg = subgroup_param->codec_cfg;
150 
151 		/* Streaming Audio Context shall be present in CAP */
152 
153 		CHECKIF(codec_cfg == NULL) {
154 			LOG_DBG("subgroup[%zu]->codec_cfg is NULL", i);
155 			return false;
156 		}
157 
158 		valid_metadata =
159 			cap_initiator_valid_metadata(codec_cfg->meta, codec_cfg->meta_len);
160 
161 		CHECKIF(!valid_metadata) {
162 			LOG_DBG("Invalid metadata supplied for subgroup[%zu]", i);
163 			return false;
164 		}
165 	}
166 
167 	return true;
168 }
169 
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])170 static void cap_initiator_broadcast_to_bap_broadcast_param(
171 	const struct bt_cap_initiator_broadcast_create_param *cap_param,
172 	struct bt_bap_broadcast_source_param *bap_param,
173 	struct bt_bap_broadcast_source_subgroup_param
174 		bap_subgroup_params[CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT],
175 	struct bt_bap_broadcast_source_stream_param
176 		bap_stream_params[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT])
177 {
178 	size_t stream_cnt = 0U;
179 
180 	bap_param->params_count = cap_param->subgroup_count;
181 	bap_param->params = bap_subgroup_params;
182 	bap_param->qos = cap_param->qos;
183 	bap_param->packing = cap_param->packing;
184 	bap_param->encryption = cap_param->encryption;
185 	if (bap_param->encryption) {
186 		memcpy(bap_param->broadcast_code, cap_param->broadcast_code,
187 		       BT_AUDIO_BROADCAST_CODE_SIZE);
188 	} else {
189 		memset(bap_param->broadcast_code, 0, BT_AUDIO_BROADCAST_CODE_SIZE);
190 	}
191 
192 	for (size_t i = 0U; i < bap_param->params_count; i++) {
193 		const struct bt_cap_initiator_broadcast_subgroup_param *cap_subgroup_param =
194 			&cap_param->subgroup_params[i];
195 		struct bt_bap_broadcast_source_subgroup_param *bap_subgroup_param =
196 			&bap_param->params[i];
197 
198 		bap_subgroup_param->codec_cfg = cap_subgroup_param->codec_cfg;
199 		bap_subgroup_param->params_count = cap_subgroup_param->stream_count;
200 		bap_subgroup_param->params = &bap_stream_params[stream_cnt];
201 
202 		for (size_t j = 0U; j < bap_subgroup_param->params_count; j++, stream_cnt++) {
203 			const struct bt_cap_initiator_broadcast_stream_param *cap_stream_param =
204 				&cap_subgroup_param->stream_params[j];
205 			struct bt_bap_broadcast_source_stream_param *bap_stream_param =
206 				&bap_subgroup_param->params[j];
207 
208 			bap_stream_param->stream = &cap_stream_param->stream->bap_stream;
209 #if CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0
210 			bap_stream_param->data_len = cap_stream_param->data_len;
211 			/* We do not need to copy the data, as that is the same type of struct, so
212 			 * we can just point to the CAP parameter data
213 			 */
214 			bap_stream_param->data = cap_stream_param->data;
215 #endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0 */
216 		}
217 	}
218 }
219 
bt_cap_initiator_broadcast_audio_create(const struct bt_cap_initiator_broadcast_create_param * param,struct bt_cap_broadcast_source ** broadcast_source)220 int bt_cap_initiator_broadcast_audio_create(
221 	const struct bt_cap_initiator_broadcast_create_param *param,
222 	struct bt_cap_broadcast_source **broadcast_source)
223 {
224 	struct bt_bap_broadcast_source_subgroup_param
225 		bap_subgroup_params[CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT];
226 	struct bt_bap_broadcast_source_stream_param
227 		bap_stream_params[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT];
228 	struct bt_bap_broadcast_source_param bap_create_param = {0};
229 
230 	CHECKIF(param == NULL) {
231 		LOG_DBG("param is NULL");
232 		return -EINVAL;
233 	}
234 
235 	CHECKIF(broadcast_source == NULL) {
236 		LOG_DBG("source is NULL");
237 		return -EINVAL;
238 	}
239 
240 	if (!cap_initiator_broadcast_audio_start_valid_param(param)) {
241 		return -EINVAL;
242 	}
243 
244 	for (size_t i = 0; i < ARRAY_SIZE(broadcast_sources); i++) {
245 		if (broadcast_sources[i].bap_broadcast == NULL) {
246 			*broadcast_source = &broadcast_sources[i];
247 			break;
248 		}
249 	}
250 
251 	cap_initiator_broadcast_to_bap_broadcast_param(param, &bap_create_param,
252 						       bap_subgroup_params, bap_stream_params);
253 
254 	return bt_bap_broadcast_source_create(&bap_create_param,
255 					      &(*broadcast_source)->bap_broadcast);
256 }
257 
bt_cap_initiator_broadcast_audio_start(struct bt_cap_broadcast_source * broadcast_source,struct bt_le_ext_adv * adv)258 int bt_cap_initiator_broadcast_audio_start(struct bt_cap_broadcast_source *broadcast_source,
259 					   struct bt_le_ext_adv *adv)
260 {
261 	CHECKIF(adv == NULL) {
262 		LOG_DBG("adv is NULL");
263 		return -EINVAL;
264 	}
265 
266 	CHECKIF(broadcast_source == NULL) {
267 		LOG_DBG("broadcast_source is NULL");
268 		return -EINVAL;
269 	}
270 
271 	return bt_bap_broadcast_source_start(broadcast_source->bap_broadcast, adv);
272 }
273 
bt_cap_initiator_broadcast_audio_update(struct bt_cap_broadcast_source * broadcast_source,const uint8_t meta[],size_t meta_len)274 int bt_cap_initiator_broadcast_audio_update(struct bt_cap_broadcast_source *broadcast_source,
275 					    const uint8_t meta[], size_t meta_len)
276 {
277 	CHECKIF(broadcast_source == NULL) {
278 		LOG_DBG("broadcast_source is NULL");
279 		return -EINVAL;
280 	}
281 
282 	CHECKIF(meta == NULL) {
283 		LOG_DBG("meta is NULL");
284 		return -EINVAL;
285 	}
286 
287 	if (!cap_initiator_valid_metadata(meta, meta_len)) {
288 		LOG_DBG("Invalid metadata");
289 		return -EINVAL;
290 	}
291 
292 	return bt_bap_broadcast_source_update_metadata(broadcast_source->bap_broadcast, meta,
293 						       meta_len);
294 }
295 
bt_cap_initiator_broadcast_audio_stop(struct bt_cap_broadcast_source * broadcast_source)296 int bt_cap_initiator_broadcast_audio_stop(struct bt_cap_broadcast_source *broadcast_source)
297 {
298 	CHECKIF(broadcast_source == NULL) {
299 		LOG_DBG("broadcast_source is NULL");
300 		return -EINVAL;
301 	}
302 
303 	return bt_bap_broadcast_source_stop(broadcast_source->bap_broadcast);
304 }
305 
bt_cap_initiator_broadcast_audio_delete(struct bt_cap_broadcast_source * broadcast_source)306 int bt_cap_initiator_broadcast_audio_delete(struct bt_cap_broadcast_source *broadcast_source)
307 {
308 	int err;
309 
310 	CHECKIF(broadcast_source == NULL) {
311 		LOG_DBG("broadcast_source is NULL");
312 		return -EINVAL;
313 	}
314 
315 	err = bt_bap_broadcast_source_delete(broadcast_source->bap_broadcast);
316 	if (err == 0) {
317 		broadcast_source->bap_broadcast = NULL;
318 	}
319 
320 	return err;
321 }
322 
bt_cap_initiator_broadcast_get_id(const struct bt_cap_broadcast_source * broadcast_source,uint32_t * const broadcast_id)323 int bt_cap_initiator_broadcast_get_id(const struct bt_cap_broadcast_source *broadcast_source,
324 				      uint32_t *const broadcast_id)
325 {
326 	CHECKIF(broadcast_source == NULL) {
327 		LOG_DBG("broadcast_source is NULL");
328 		return -EINVAL;
329 	}
330 
331 	return bt_bap_broadcast_source_get_id(broadcast_source->bap_broadcast, broadcast_id);
332 }
333 
bt_cap_initiator_broadcast_get_base(struct bt_cap_broadcast_source * broadcast_source,struct net_buf_simple * base_buf)334 int bt_cap_initiator_broadcast_get_base(struct bt_cap_broadcast_source *broadcast_source,
335 					struct net_buf_simple *base_buf)
336 {
337 	CHECKIF(broadcast_source == NULL) {
338 		LOG_DBG("broadcast_source is NULL");
339 		return -EINVAL;
340 	}
341 
342 	return bt_bap_broadcast_source_get_base(broadcast_source->bap_broadcast, base_buf);
343 }
344 
345 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
346 
347 #if defined(CONFIG_BT_BAP_UNICAST_CLIENT)
348 
stream_get_state(const struct bt_bap_stream * bap_stream)349 static enum bt_bap_ep_state stream_get_state(const struct bt_bap_stream *bap_stream)
350 {
351 	struct bt_bap_ep_info ep_info;
352 	int err;
353 
354 	err = bt_bap_ep_get_info(bap_stream->ep, &ep_info);
355 	if (err != 0) {
356 		LOG_DBG("Failed to get endpoint info %p: %d", bap_stream, err);
357 
358 		return BT_BAP_EP_STATE_IDLE;
359 	}
360 
361 	return ep_info.state;
362 }
363 
stream_is_in_state(const struct bt_bap_stream * bap_stream,enum bt_bap_ep_state state)364 static bool stream_is_in_state(const struct bt_bap_stream *bap_stream, enum bt_bap_ep_state state)
365 {
366 	if (bap_stream->conn == NULL) {
367 		return state == BT_BAP_EP_STATE_IDLE;
368 	}
369 
370 	return stream_get_state(bap_stream) == state;
371 }
372 
stream_is_dir(const struct bt_bap_stream * bap_stream,enum bt_audio_dir dir)373 static bool stream_is_dir(const struct bt_bap_stream *bap_stream, enum bt_audio_dir dir)
374 {
375 	struct bt_bap_ep_info ep_info;
376 	int err;
377 
378 	if (bap_stream->conn == NULL) {
379 		return false;
380 	}
381 
382 	err = bt_bap_ep_get_info(bap_stream->ep, &ep_info);
383 	if (err != 0) {
384 		LOG_DBG("Failed to get endpoint info %p: %d", bap_stream, err);
385 
386 		return false;
387 	}
388 
389 	return ep_info.dir == dir;
390 }
391 
iso_is_in_state(const struct bt_cap_stream * cap_stream,enum bt_iso_state state)392 static bool iso_is_in_state(const struct bt_cap_stream *cap_stream, enum bt_iso_state state)
393 {
394 	const struct bt_bap_stream *bap_stream = &cap_stream->bap_stream;
395 	struct bt_bap_ep_info ep_info;
396 	int err;
397 
398 	err = bt_bap_ep_get_info(bap_stream->ep, &ep_info);
399 	if (err != 0) {
400 		LOG_DBG("Failed to get endpoint info %p: %d", bap_stream, err);
401 
402 		return false;
403 	}
404 
405 	if (ep_info.iso_chan == NULL) {
406 		return state == BT_ISO_STATE_DISCONNECTED;
407 	}
408 
409 	return state == ep_info.iso_chan->state;
410 }
411 
412 /**
413  * @brief Gets the next stream for the active procedure.
414  *
415  * Returns NULL if all streams are in the right state for the current step
416  */
417 static struct bt_cap_initiator_proc_param *
get_proc_param_by_cap_stream(struct bt_cap_common_proc * active_proc,const struct bt_cap_stream * cap_stream)418 get_proc_param_by_cap_stream(struct bt_cap_common_proc *active_proc,
419 			     const struct bt_cap_stream *cap_stream)
420 {
421 	for (size_t i = 0U; i < active_proc->proc_cnt; i++) {
422 		if (active_proc->proc_param.initiator[i].stream == cap_stream) {
423 			return &active_proc->proc_param.initiator[i];
424 		}
425 	}
426 
427 	return NULL;
428 }
429 
update_proc_done_cnt(struct bt_cap_common_proc * active_proc)430 static void update_proc_done_cnt(struct bt_cap_common_proc *active_proc)
431 {
432 	const enum bt_cap_common_subproc_type subproc_type = active_proc->subproc_type;
433 	const enum bt_cap_common_proc_type proc_type = active_proc->proc_type;
434 	size_t proc_done_cnt = 0U;
435 
436 	if (proc_type == BT_CAP_COMMON_PROC_TYPE_START) {
437 		/* To support state changes by the server, we cannot rely simply on the number of
438 		 * BAP procedures we have initiated. For the start and stop CAP procedures we use
439 		 * the states to determine how far we are.
440 		 */
441 		for (size_t i = 0U; i < active_proc->proc_cnt; i++) {
442 			const struct bt_cap_initiator_proc_param *proc_param;
443 			struct bt_cap_stream *cap_stream;
444 			struct bt_bap_stream *bap_stream;
445 			enum bt_bap_ep_state state;
446 
447 			proc_param = &active_proc->proc_param.initiator[i];
448 			cap_stream = proc_param->stream;
449 			bap_stream = &cap_stream->bap_stream;
450 
451 			state = stream_get_state(bap_stream);
452 
453 			switch (subproc_type) {
454 			case BT_CAP_COMMON_SUBPROC_TYPE_CODEC_CONFIG:
455 				if (state > BT_BAP_EP_STATE_IDLE) {
456 					proc_done_cnt++;
457 				}
458 				break;
459 			case BT_CAP_COMMON_SUBPROC_TYPE_QOS_CONFIG:
460 				if (state > BT_BAP_EP_STATE_CODEC_CONFIGURED) {
461 					proc_done_cnt++;
462 				} else if (state < BT_BAP_EP_STATE_CODEC_CONFIGURED) {
463 					/* Unexpected state - Abort */
464 					bt_cap_common_abort_proc(bap_stream->conn, -EBADMSG);
465 				}
466 				break;
467 			case BT_CAP_COMMON_SUBPROC_TYPE_ENABLE:
468 				if (state > BT_BAP_EP_STATE_QOS_CONFIGURED) {
469 					proc_done_cnt++;
470 				} else if (state < BT_BAP_EP_STATE_QOS_CONFIGURED) {
471 					/* Unexpected state - Abort */
472 					bt_cap_common_abort_proc(bap_stream->conn, -EBADMSG);
473 				}
474 				break;
475 			case BT_CAP_COMMON_SUBPROC_TYPE_CONNECT:
476 				if (state < BT_BAP_EP_STATE_ENABLING) {
477 					/* Unexpected state - Abort */
478 					bt_cap_common_abort_proc(bap_stream->conn, -EBADMSG);
479 				} else if (proc_param->start.connected) {
480 					proc_done_cnt++;
481 				}
482 				break;
483 			case BT_CAP_COMMON_SUBPROC_TYPE_START:
484 				if (state > BT_BAP_EP_STATE_ENABLING) {
485 					proc_done_cnt++;
486 				} else if (state < BT_BAP_EP_STATE_ENABLING ||
487 					   !iso_is_in_state(cap_stream, BT_ISO_STATE_CONNECTED)) {
488 					/* Unexpected state - Abort */
489 					bt_cap_common_abort_proc(bap_stream->conn, -EBADMSG);
490 				}
491 				break;
492 			default:
493 				__ASSERT(false, "Invalid subproc %d for %d", subproc_type,
494 					 proc_type);
495 			}
496 		}
497 	} else if (proc_type == BT_CAP_COMMON_PROC_TYPE_STOP) {
498 		/* To support state changes by the server, we cannot rely simply on the number of
499 		 * BAP procedures we have initiated. For the start and stop CAP procedures we use
500 		 * the states to determine how far we are.
501 		 */
502 		for (size_t i = 0U; i < active_proc->proc_cnt; i++) {
503 			const struct bt_cap_initiator_proc_param *proc_param;
504 			struct bt_cap_stream *cap_stream;
505 			struct bt_bap_stream *bap_stream;
506 			enum bt_bap_ep_state state;
507 
508 			proc_param = &active_proc->proc_param.initiator[i];
509 			cap_stream = proc_param->stream;
510 			bap_stream = &cap_stream->bap_stream;
511 
512 			state = stream_get_state(bap_stream);
513 
514 			switch (subproc_type) {
515 			case BT_CAP_COMMON_SUBPROC_TYPE_RELEASE:
516 				if (state == BT_BAP_EP_STATE_IDLE ||
517 				    state == BT_BAP_EP_STATE_CODEC_CONFIGURED) {
518 					proc_done_cnt++;
519 				}
520 				break;
521 			default:
522 				__ASSERT(false, "Invalid subproc %d for %d", subproc_type,
523 					 proc_type);
524 			}
525 		}
526 	} else if (proc_type == BT_CAP_COMMON_PROC_TYPE_UPDATE) {
527 		/* For metadata we cannot check the states for all streams, as it does not trigger a
528 		 * state change
529 		 */
530 		const struct bt_cap_initiator_proc_param *proc_param;
531 		struct bt_cap_stream *cap_stream;
532 		struct bt_bap_stream *bap_stream;
533 		enum bt_bap_ep_state state;
534 
535 		proc_param = &active_proc->proc_param.initiator[active_proc->proc_done_cnt];
536 		cap_stream = proc_param->stream;
537 		bap_stream = &cap_stream->bap_stream;
538 
539 		state = stream_get_state(bap_stream);
540 
541 		switch (subproc_type) {
542 		case BT_CAP_COMMON_SUBPROC_TYPE_META_UPDATE:
543 			if (state == BT_BAP_EP_STATE_ENABLING ||
544 			    state == BT_BAP_EP_STATE_STREAMING) {
545 				proc_done_cnt = active_proc->proc_done_cnt + 1U;
546 			} else {
547 				/* Unexpected state - Abort */
548 				bt_cap_common_abort_proc(bap_stream->conn, -EBADMSG);
549 			}
550 			break;
551 		default:
552 			__ASSERT(false, "Invalid subproc %d for %d", subproc_type, proc_type);
553 		}
554 	}
555 
556 	active_proc->proc_done_cnt = proc_done_cnt;
557 
558 	LOG_DBG("proc %d subproc %d: %zu/%zu", proc_type, subproc_type, active_proc->proc_done_cnt,
559 		active_proc->proc_cnt);
560 }
561 
562 /**
563  * @brief Gets the next stream for the active procedure.
564  *
565  * Returns NULL if all streams are in the right state for the current step
566  */
567 static struct bt_cap_initiator_proc_param *
get_next_proc_param(struct bt_cap_common_proc * active_proc)568 get_next_proc_param(struct bt_cap_common_proc *active_proc)
569 {
570 	const enum bt_cap_common_subproc_type subproc_type = active_proc->subproc_type;
571 
572 	for (size_t i = 0U; i < active_proc->proc_cnt; i++) {
573 		struct bt_cap_initiator_proc_param *proc_param;
574 		struct bt_cap_stream *cap_stream;
575 		struct bt_bap_stream *bap_stream;
576 
577 		proc_param = &active_proc->proc_param.initiator[i];
578 		cap_stream = proc_param->stream;
579 		bap_stream = &cap_stream->bap_stream;
580 
581 		switch (subproc_type) {
582 		case BT_CAP_COMMON_SUBPROC_TYPE_CODEC_CONFIG:
583 			if (stream_is_in_state(bap_stream, BT_BAP_EP_STATE_IDLE)) {
584 				return proc_param;
585 			}
586 			break;
587 		case BT_CAP_COMMON_SUBPROC_TYPE_QOS_CONFIG:
588 			if (stream_is_in_state(bap_stream, BT_BAP_EP_STATE_CODEC_CONFIGURED)) {
589 				return proc_param;
590 			}
591 			break;
592 		case BT_CAP_COMMON_SUBPROC_TYPE_ENABLE:
593 			if (stream_is_in_state(bap_stream, BT_BAP_EP_STATE_QOS_CONFIGURED)) {
594 				return proc_param;
595 			}
596 			break;
597 		case BT_CAP_COMMON_SUBPROC_TYPE_CONNECT:
598 			if (stream_is_in_state(bap_stream, BT_BAP_EP_STATE_ENABLING) &&
599 			    !proc_param->start.connected) {
600 				return proc_param;
601 			}
602 			break;
603 		case BT_CAP_COMMON_SUBPROC_TYPE_START:
604 			if (stream_is_in_state(bap_stream, BT_BAP_EP_STATE_ENABLING)) {
605 				/* TODO: Add check for connected */
606 				return proc_param;
607 			}
608 			break;
609 		case BT_CAP_COMMON_SUBPROC_TYPE_META_UPDATE:
610 			if (stream_is_in_state(bap_stream, BT_BAP_EP_STATE_ENABLING) ||
611 			    stream_is_in_state(bap_stream, BT_BAP_EP_STATE_STREAMING)) {
612 				return proc_param;
613 			}
614 			break;
615 		case BT_CAP_COMMON_SUBPROC_TYPE_RELEASE:
616 			if (!stream_is_in_state(bap_stream, BT_BAP_EP_STATE_IDLE)) {
617 				return proc_param;
618 			}
619 			break;
620 		default:
621 			break;
622 		}
623 	}
624 
625 	return NULL;
626 }
627 
628 static void
bt_cap_initiator_discover_complete(struct bt_conn * conn,int err,const struct bt_csip_set_coordinator_set_member * member,const struct bt_csip_set_coordinator_csis_inst * csis_inst)629 bt_cap_initiator_discover_complete(struct bt_conn *conn, int err,
630 				   const struct bt_csip_set_coordinator_set_member *member,
631 				   const struct bt_csip_set_coordinator_csis_inst *csis_inst)
632 {
633 	if (cap_cb && cap_cb->unicast_discovery_complete) {
634 		cap_cb->unicast_discovery_complete(conn, err, member, csis_inst);
635 	}
636 }
637 
bt_cap_initiator_unicast_discover(struct bt_conn * conn)638 int bt_cap_initiator_unicast_discover(struct bt_conn *conn)
639 {
640 	CHECKIF(conn == NULL) {
641 		LOG_DBG("NULL conn");
642 		return -EINVAL;
643 	}
644 
645 	return bt_cap_common_discover(conn, bt_cap_initiator_discover_complete);
646 }
647 
valid_unicast_audio_start_param(const struct bt_cap_unicast_audio_start_param * param)648 static bool valid_unicast_audio_start_param(const struct bt_cap_unicast_audio_start_param *param)
649 {
650 	struct bt_bap_unicast_group *unicast_group = NULL;
651 
652 	CHECKIF(param == NULL) {
653 		LOG_DBG("param is NULL");
654 		return false;
655 	}
656 
657 	CHECKIF(param->count == 0) {
658 		LOG_DBG("Invalid param->count: %u", param->count);
659 		return false;
660 	}
661 
662 	CHECKIF(param->stream_params == NULL) {
663 		LOG_DBG("param->stream_params is NULL");
664 		return false;
665 	}
666 
667 	CHECKIF(param->count > CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT) {
668 		LOG_DBG("param->count (%zu) is larger than "
669 			"CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT (%d)",
670 			param->count,
671 			CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT);
672 		return false;
673 	}
674 
675 	for (size_t i = 0U; i < param->count; i++) {
676 		const struct bt_cap_unicast_audio_start_stream_param *stream_param =
677 									&param->stream_params[i];
678 		const union bt_cap_set_member *member = &stream_param->member;
679 		const struct bt_cap_stream *cap_stream = stream_param->stream;
680 		const struct bt_audio_codec_cfg *codec_cfg = stream_param->codec_cfg;
681 		const struct bt_bap_stream *bap_stream;
682 		const struct bt_conn *member_conn =
683 			bt_cap_common_get_member_conn(param->type, member);
684 
685 		if (member == NULL) {
686 			LOG_DBG("param->members[%zu] is NULL", i);
687 			return false;
688 		}
689 
690 		if (member_conn == NULL) {
691 			LOG_DBG("Invalid param->members[%zu]", i);
692 			return false;
693 		}
694 
695 		CHECKIF(stream_param->codec_cfg == NULL) {
696 			LOG_DBG("param->stream_params[%zu].codec_cfg  is NULL", i);
697 			return false;
698 		}
699 
700 		CHECKIF(!cap_initiator_valid_metadata(codec_cfg->meta, codec_cfg->meta_len)) {
701 			LOG_DBG("param->stream_params[%zu].codec_cfg  is invalid", i);
702 			return false;
703 		}
704 
705 		CHECKIF(stream_param->ep == NULL) {
706 			LOG_DBG("param->stream_params[%zu].ep is NULL", i);
707 			return false;
708 		}
709 
710 		CHECKIF(member == NULL) {
711 			LOG_DBG("param->stream_params[%zu].member is NULL", i);
712 			return false;
713 		}
714 
715 		CHECKIF(cap_stream == NULL) {
716 			LOG_DBG("param->streams[%zu] is NULL", i);
717 			return false;
718 		}
719 
720 		bap_stream = &cap_stream->bap_stream;
721 
722 		CHECKIF(bap_stream->ep != NULL) {
723 			LOG_DBG("param->streams[%zu] is already started", i);
724 			return false;
725 		}
726 
727 		CHECKIF(bap_stream->group == NULL) {
728 			LOG_DBG("param->streams[%zu] is not in a unicast group", i);
729 			return false;
730 		}
731 
732 		/* Use the group of the first stream for comparison */
733 		if (unicast_group == NULL) {
734 			unicast_group = bap_stream->group;
735 		} else {
736 			CHECKIF(bap_stream->group != unicast_group) {
737 				LOG_DBG("param->streams[%zu] is not in this group %p", i,
738 					unicast_group);
739 				return false;
740 			}
741 		}
742 
743 		for (size_t j = 0U; j < i; j++) {
744 			if (param->stream_params[j].stream == cap_stream) {
745 				LOG_DBG("param->stream_params[%zu] (%p) is "
746 					"duplicated by "
747 					"param->stream_params[%zu] (%p)",
748 					j, param->stream_params[j].stream,
749 					i, cap_stream);
750 				return false;
751 			}
752 		}
753 	}
754 
755 	return true;
756 }
757 
cap_initiator_unicast_audio_proc_complete(void)758 static void cap_initiator_unicast_audio_proc_complete(void)
759 {
760 	struct bt_cap_common_proc *active_proc = bt_cap_common_get_active_proc();
761 	enum bt_cap_common_proc_type proc_type;
762 	struct bt_conn *failed_conn;
763 	int err;
764 
765 	failed_conn = active_proc->failed_conn;
766 	err = active_proc->err;
767 	proc_type = active_proc->proc_type;
768 	bt_cap_common_clear_active_proc();
769 
770 	if (cap_cb == NULL) {
771 		return;
772 	}
773 
774 	switch (proc_type) {
775 	case BT_CAP_COMMON_PROC_TYPE_START:
776 		if (cap_cb->unicast_start_complete != NULL) {
777 			cap_cb->unicast_start_complete(err, failed_conn);
778 		}
779 		break;
780 	case BT_CAP_COMMON_PROC_TYPE_UPDATE:
781 		if (cap_cb->unicast_update_complete != NULL) {
782 			cap_cb->unicast_update_complete(err, failed_conn);
783 		}
784 		break;
785 	case BT_CAP_COMMON_PROC_TYPE_STOP:
786 		if (cap_cb->unicast_stop_complete != NULL) {
787 			cap_cb->unicast_stop_complete(err, failed_conn);
788 		}
789 		break;
790 	case BT_CAP_COMMON_PROC_TYPE_NONE:
791 	default:
792 		__ASSERT(false, "Invalid proc_type: %u", proc_type);
793 	}
794 }
795 
cap_initiator_unicast_audio_configure(const struct bt_cap_unicast_audio_start_param * param)796 static int cap_initiator_unicast_audio_configure(
797 	const struct bt_cap_unicast_audio_start_param *param)
798 {
799 	struct bt_cap_common_proc *active_proc = bt_cap_common_get_active_proc();
800 	struct bt_cap_initiator_proc_param *proc_param;
801 	struct bt_audio_codec_cfg *codec_cfg;
802 	struct bt_bap_stream *bap_stream;
803 	struct bt_bap_ep *ep;
804 	struct bt_conn *conn;
805 	int err;
806 	/** TODO: If this is a CSIP set, then the order of the procedures may
807 	 * not match the order in the parameters, and the CSIP ordered access
808 	 * procedure should be used.
809 	 */
810 
811 	for (size_t i = 0U; i < param->count; i++) {
812 		struct bt_cap_unicast_audio_start_stream_param *stream_param =
813 									&param->stream_params[i];
814 		union bt_cap_set_member *member = &stream_param->member;
815 		struct bt_cap_stream *cap_stream = stream_param->stream;
816 
817 		conn = bt_cap_common_get_member_conn(param->type, member);
818 
819 		/* Ensure that ops are registered before any procedures are started */
820 		bt_cap_stream_ops_register_bap(cap_stream);
821 
822 		/* Store the necessary parameters as we cannot assume that the supplied parameters
823 		 * are kept valid
824 		 */
825 		active_proc->proc_param.initiator[i].stream = cap_stream;
826 		active_proc->proc_param.initiator[i].start.ep = stream_param->ep;
827 		active_proc->proc_param.initiator[i].start.conn = conn;
828 		active_proc->proc_param.initiator[i].start.codec_cfg = stream_param->codec_cfg;
829 	}
830 
831 	/* Store the information about the active procedure so that we can
832 	 * continue the procedure after each step
833 	 */
834 	bt_cap_common_start_proc(BT_CAP_COMMON_PROC_TYPE_START, param->count);
835 	bt_cap_common_set_subproc(BT_CAP_COMMON_SUBPROC_TYPE_CODEC_CONFIG);
836 
837 	proc_param = get_next_proc_param(active_proc);
838 	if (proc_param == NULL) {
839 		/* If proc_param is NULL then this step is a no-op and we can skip to the next step
840 		 */
841 		bt_cap_initiator_codec_configured(active_proc->proc_param.initiator[0].stream);
842 
843 		return 0;
844 	}
845 
846 	bap_stream = &proc_param->stream->bap_stream;
847 	codec_cfg = proc_param->start.codec_cfg;
848 	conn = proc_param->start.conn;
849 	ep = proc_param->start.ep;
850 	active_proc->proc_initiated_cnt++;
851 
852 	/* Since BAP operations may require a write long or a read long on the notification,
853 	 * we cannot assume that we can do multiple streams at once, thus do it one at a time.
854 	 * TODO: We should always be able to do one per ACL, so there is room for optimization.
855 	 */
856 	err = bt_bap_stream_config(conn, bap_stream, ep, codec_cfg);
857 	if (err != 0) {
858 		LOG_DBG("Failed to config stream %p: %d", proc_param->stream, err);
859 
860 		bt_cap_common_clear_active_proc();
861 	}
862 
863 	return err;
864 }
865 
bt_cap_initiator_unicast_audio_start(const struct bt_cap_unicast_audio_start_param * param)866 int bt_cap_initiator_unicast_audio_start(const struct bt_cap_unicast_audio_start_param *param)
867 {
868 	if (bt_cap_common_proc_is_active()) {
869 		LOG_DBG("A CAP procedure is already in progress");
870 
871 		return -EBUSY;
872 	}
873 
874 	if (!valid_unicast_audio_start_param(param)) {
875 		return -EINVAL;
876 	}
877 
878 	return cap_initiator_unicast_audio_configure(param);
879 }
880 
bt_cap_initiator_codec_configured(struct bt_cap_stream * cap_stream)881 void bt_cap_initiator_codec_configured(struct bt_cap_stream *cap_stream)
882 {
883 	struct bt_conn
884 		*conns[MIN(CONFIG_BT_MAX_CONN, CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT)];
885 	struct bt_cap_common_proc *active_proc = bt_cap_common_get_active_proc();
886 	struct bt_cap_initiator_proc_param *proc_param;
887 	struct bt_bap_unicast_group *unicast_group;
888 
889 	if (!bt_cap_common_stream_in_active_proc(cap_stream)) {
890 		/* State change happened outside of a procedure; ignore */
891 		return;
892 	}
893 
894 	LOG_DBG("cap_stream %p", cap_stream);
895 
896 	if (bt_cap_common_subproc_is_type(BT_CAP_COMMON_SUBPROC_TYPE_RELEASE)) {
897 		/* When releasing a stream, it may go into the codec configured state if
898 		 * the unicast server caches the configuration - We treat it as a release
899 		 */
900 		bt_cap_initiator_released(cap_stream);
901 		return;
902 	} else if (!bt_cap_common_subproc_is_type(BT_CAP_COMMON_SUBPROC_TYPE_CODEC_CONFIG)) {
903 		/* Unexpected callback - Abort */
904 		bt_cap_common_abort_proc(cap_stream->bap_stream.conn, -EBADMSG);
905 	} else {
906 		update_proc_done_cnt(active_proc);
907 
908 		LOG_DBG("Stream %p configured (%zu/%zu streams done)", cap_stream,
909 			active_proc->proc_done_cnt, active_proc->proc_cnt);
910 	}
911 
912 	if (bt_cap_common_proc_is_aborted()) {
913 		if (bt_cap_common_proc_all_handled()) {
914 			cap_initiator_unicast_audio_proc_complete();
915 		}
916 
917 		return;
918 	}
919 
920 	if (!bt_cap_common_proc_is_done()) {
921 		struct bt_cap_stream *next_cap_stream;
922 		struct bt_bap_stream *next_bap_stream;
923 		struct bt_audio_codec_cfg *codec_cfg;
924 		struct bt_conn *conn;
925 		struct bt_bap_ep *ep;
926 		int err;
927 
928 		proc_param = get_next_proc_param(active_proc);
929 		__ASSERT(proc_param != NULL, "proc is not done, but could not get next proc_param");
930 		next_cap_stream = proc_param->stream;
931 		conn = proc_param->start.conn;
932 		ep = proc_param->start.ep;
933 		codec_cfg = proc_param->start.codec_cfg;
934 		next_bap_stream = &next_cap_stream->bap_stream;
935 		active_proc->proc_initiated_cnt++;
936 
937 		/* Since BAP operations may require a write long or a read long on the notification,
938 		 * we cannot assume that we can do multiple streams at once, thus do it one at a
939 		 * time.
940 		 * TODO: We should always be able to do one per ACL, so there is room for
941 		 * optimization.
942 		 */
943 		err = bt_bap_stream_config(conn, next_bap_stream, ep, codec_cfg);
944 		if (err != 0) {
945 			LOG_DBG("Failed to config stream %p: %d", next_cap_stream, err);
946 
947 			bt_cap_common_abort_proc(conn, err);
948 			cap_initiator_unicast_audio_proc_complete();
949 		}
950 
951 		return;
952 	}
953 
954 	/* The QoS Configure procedure works on a set of connections and a
955 	 * unicast group, so we generate a list of unique connection pointers
956 	 * for the procedure
957 	 */
958 	(void)memset(conns, 0, sizeof(conns));
959 	for (size_t i = 0U; i < active_proc->proc_cnt; i++) {
960 		struct bt_conn *stream_conn =
961 			active_proc->proc_param.initiator[i].stream->bap_stream.conn;
962 		struct bt_conn **free_conn = NULL;
963 		bool already_added = false;
964 
965 		for (size_t j = 0U; j < ARRAY_SIZE(conns); j++) {
966 			if (stream_conn == conns[j]) {
967 				already_added = true;
968 				break;
969 			} else if (conns[j] == NULL && free_conn == NULL) {
970 				free_conn = &conns[j];
971 			}
972 		}
973 
974 		if (already_added) {
975 			continue;
976 		}
977 
978 		if (free_conn != NULL) {
979 			*free_conn = stream_conn;
980 		} else {
981 			__ASSERT_PRINT("No free conns");
982 		}
983 	}
984 
985 	/* All streams in the procedure share the same unicast group, so we just
986 	 * use the reference from the first stream
987 	 */
988 	bt_cap_common_set_subproc(BT_CAP_COMMON_SUBPROC_TYPE_QOS_CONFIG);
989 	proc_param = get_next_proc_param(active_proc);
990 	if (proc_param == NULL) {
991 		/* If proc_param is NULL then this step is a no-op and we can skip to the next step
992 		 */
993 		bt_cap_initiator_qos_configured(active_proc->proc_param.initiator[0].stream);
994 
995 		return;
996 	}
997 
998 	unicast_group = (struct bt_bap_unicast_group *)proc_param->stream->bap_stream.group;
999 
1000 	for (size_t i = 0U; i < ARRAY_SIZE(conns); i++) {
1001 		int err;
1002 
1003 		/* When conns[i] is NULL, we have QoS Configured all unique connections */
1004 		if (conns[i] == NULL) {
1005 			break;
1006 		}
1007 
1008 		active_proc->proc_initiated_cnt++;
1009 
1010 		err = bt_bap_stream_qos(conns[i], unicast_group);
1011 		if (err != 0) {
1012 			LOG_DBG("Failed to set stream QoS for conn %p and group %p: %d",
1013 				(void *)conns[i], unicast_group, err);
1014 
1015 			/* End or mark procedure as aborted.
1016 			 * If we have sent any requests over air, we will abort
1017 			 * once all sent requests has completed
1018 			 */
1019 			bt_cap_common_abort_proc(conns[i], err);
1020 			if (i == 0U) {
1021 				cap_initiator_unicast_audio_proc_complete();
1022 			}
1023 
1024 			return;
1025 		}
1026 	}
1027 }
1028 
bt_cap_initiator_qos_configured(struct bt_cap_stream * cap_stream)1029 void bt_cap_initiator_qos_configured(struct bt_cap_stream *cap_stream)
1030 {
1031 	struct bt_cap_common_proc *active_proc = bt_cap_common_get_active_proc();
1032 	struct bt_cap_initiator_proc_param *proc_param;
1033 	struct bt_cap_stream *next_cap_stream;
1034 	struct bt_bap_stream *bap_stream;
1035 	int err;
1036 
1037 	if (!bt_cap_common_stream_in_active_proc(cap_stream)) {
1038 		/* State change happened outside of a procedure; ignore */
1039 		return;
1040 	}
1041 
1042 	LOG_DBG("cap_stream %p", cap_stream);
1043 
1044 	if (!bt_cap_common_subproc_is_type(BT_CAP_COMMON_SUBPROC_TYPE_QOS_CONFIG)) {
1045 		/* Unexpected callback - Abort */
1046 		bt_cap_common_abort_proc(cap_stream->bap_stream.conn, -EBADMSG);
1047 	} else {
1048 		update_proc_done_cnt(active_proc);
1049 
1050 		LOG_DBG("Stream %p QoS configured (%zu/%zu streams done)", cap_stream,
1051 			active_proc->proc_done_cnt, active_proc->proc_cnt);
1052 	}
1053 
1054 	if (bt_cap_common_proc_is_aborted()) {
1055 		if (bt_cap_common_proc_all_handled()) {
1056 			cap_initiator_unicast_audio_proc_complete();
1057 		}
1058 
1059 		return;
1060 	}
1061 
1062 	if (!bt_cap_common_proc_is_done()) {
1063 		/* Not yet finished, wait for all */
1064 		return;
1065 	}
1066 
1067 	bt_cap_common_set_subproc(BT_CAP_COMMON_SUBPROC_TYPE_ENABLE);
1068 	proc_param = get_next_proc_param(active_proc);
1069 	if (proc_param == NULL) {
1070 		/* If proc_param is NULL then this step is a no-op and we can skip to the next step
1071 		 */
1072 		bt_cap_initiator_enabled(active_proc->proc_param.initiator[0].stream);
1073 
1074 		return;
1075 	}
1076 
1077 	next_cap_stream = proc_param->stream;
1078 	bap_stream = &next_cap_stream->bap_stream;
1079 	active_proc->proc_initiated_cnt++;
1080 
1081 	/* Since BAP operations may require a write long or a read long on the notification, we
1082 	 * cannot assume that we can do multiple streams at once, thus do it one at a time.
1083 	 * TODO: We should always be able to do one per ACL, so there is room for optimization.
1084 	 */
1085 	err = bt_bap_stream_enable(bap_stream, bap_stream->codec_cfg->meta,
1086 				   bap_stream->codec_cfg->meta_len);
1087 	if (err != 0) {
1088 		LOG_DBG("Failed to enable stream %p: %d", next_cap_stream, err);
1089 
1090 		bt_cap_common_abort_proc(bap_stream->conn, err);
1091 		cap_initiator_unicast_audio_proc_complete();
1092 	}
1093 }
1094 
bt_cap_initiator_enabled(struct bt_cap_stream * cap_stream)1095 void bt_cap_initiator_enabled(struct bt_cap_stream *cap_stream)
1096 {
1097 	struct bt_cap_common_proc *active_proc = bt_cap_common_get_active_proc();
1098 	struct bt_cap_initiator_proc_param *proc_param;
1099 	struct bt_bap_stream *bap_stream;
1100 	int err;
1101 
1102 	if (!bt_cap_common_stream_in_active_proc(cap_stream)) {
1103 		/* State change happened outside of a procedure; ignore */
1104 		return;
1105 	}
1106 
1107 	LOG_DBG("cap_stream %p", cap_stream);
1108 
1109 	if (!bt_cap_common_subproc_is_type(BT_CAP_COMMON_SUBPROC_TYPE_ENABLE)) {
1110 		/* Unexpected callback - Abort */
1111 		bt_cap_common_abort_proc(cap_stream->bap_stream.conn, -EBADMSG);
1112 	} else {
1113 		update_proc_done_cnt(active_proc);
1114 
1115 		LOG_DBG("Stream %p enabled (%zu/%zu streams done)", cap_stream,
1116 			active_proc->proc_done_cnt, active_proc->proc_cnt);
1117 	}
1118 
1119 	if (bt_cap_common_proc_is_aborted()) {
1120 		if (bt_cap_common_proc_all_handled()) {
1121 			cap_initiator_unicast_audio_proc_complete();
1122 		}
1123 
1124 		return;
1125 	}
1126 
1127 	if (!bt_cap_common_proc_is_done()) {
1128 		struct bt_cap_stream *next_cap_stream;
1129 		struct bt_bap_stream *next_bap_stream;
1130 
1131 		proc_param = get_next_proc_param(active_proc);
1132 		__ASSERT(proc_param != NULL, "proc is not done, but could not get next proc_param");
1133 		next_cap_stream = proc_param->stream;
1134 		next_bap_stream = &next_cap_stream->bap_stream;
1135 
1136 		active_proc->proc_initiated_cnt++;
1137 
1138 		/* Since BAP operations may require a write long or a read long on the notification,
1139 		 * we cannot assume that we can do multiple streams at once, thus do it one at a
1140 		 * time.
1141 		 * TODO: We should always be able to do one per ACL, so there is room for
1142 		 * optimization.
1143 		 */
1144 		err = bt_bap_stream_enable(next_bap_stream, next_bap_stream->codec_cfg->meta,
1145 					   next_bap_stream->codec_cfg->meta_len);
1146 		if (err != 0) {
1147 			LOG_DBG("Failed to enable stream %p: %d", next_cap_stream, err);
1148 
1149 			bt_cap_common_abort_proc(next_bap_stream->conn, err);
1150 			cap_initiator_unicast_audio_proc_complete();
1151 		}
1152 
1153 		return;
1154 	}
1155 
1156 	bt_cap_common_set_subproc(BT_CAP_COMMON_SUBPROC_TYPE_CONNECT);
1157 	proc_param = get_next_proc_param(active_proc);
1158 	if (proc_param == NULL) {
1159 		/* If proc_param is NULL then this step is a no-op and we can skip to the next step
1160 		 */
1161 		bt_cap_initiator_connected(active_proc->proc_param.initiator[0].stream);
1162 
1163 		return;
1164 	}
1165 
1166 	bap_stream = &proc_param->stream->bap_stream;
1167 
1168 	err = bt_bap_stream_connect(bap_stream);
1169 	if (err == -EALREADY) {
1170 		/* If the stream is already connected we can just call the callback directly
1171 		 * NOTE: It's important that we do not do any additional functionality after
1172 		 * calling this
1173 		 */
1174 		bt_cap_initiator_connected(proc_param->stream);
1175 	} else if (err != 0) {
1176 		LOG_DBG("Failed to connect stream %p: %d", proc_param->stream, err);
1177 
1178 		/* End and mark procedure as aborted.
1179 		 * If we have sent any requests over air, we will abort
1180 		 * once all sent requests has completed
1181 		 */
1182 		bt_cap_common_abort_proc(bap_stream->conn, err);
1183 		cap_initiator_unicast_audio_proc_complete();
1184 	}
1185 }
1186 
bt_cap_initiator_connected(struct bt_cap_stream * cap_stream)1187 void bt_cap_initiator_connected(struct bt_cap_stream *cap_stream)
1188 {
1189 	struct bt_cap_common_proc *active_proc = bt_cap_common_get_active_proc();
1190 	struct bt_cap_initiator_proc_param *proc_param;
1191 	struct bt_bap_stream *bap_stream;
1192 	int err;
1193 
1194 	if (!bt_cap_common_stream_in_active_proc(cap_stream)) {
1195 		/* State change happened outside of a procedure; ignore */
1196 		return;
1197 	}
1198 
1199 	LOG_DBG("cap_stream %p", cap_stream);
1200 
1201 	if (!bt_cap_common_subproc_is_type(BT_CAP_COMMON_SUBPROC_TYPE_CONNECT)) {
1202 		/* Unexpected callback - Abort */
1203 		bt_cap_common_abort_proc(cap_stream->bap_stream.conn, -EBADMSG);
1204 	} else {
1205 		proc_param = get_proc_param_by_cap_stream(active_proc, cap_stream);
1206 		__ASSERT_NO_MSG(proc_param != NULL);
1207 
1208 		/* Sets connected before update_proc_done_cnt as that is the only way to can track
1209 		 * the CIS state change
1210 		 */
1211 		proc_param->start.connected = true;
1212 		update_proc_done_cnt(active_proc);
1213 
1214 		LOG_DBG("Stream %p connected (%zu/%zu streams done)", cap_stream,
1215 			active_proc->proc_done_cnt, active_proc->proc_cnt);
1216 	}
1217 
1218 	if (bt_cap_common_proc_is_aborted()) {
1219 		if (bt_cap_common_proc_all_handled()) {
1220 			cap_initiator_unicast_audio_proc_complete();
1221 		}
1222 
1223 		return;
1224 	}
1225 
1226 	if (!bt_cap_common_proc_is_done()) {
1227 		struct bt_cap_stream *next_cap_stream;
1228 		struct bt_bap_stream *next_bap_stream;
1229 
1230 		proc_param = get_next_proc_param(active_proc);
1231 		__ASSERT(proc_param != NULL, "proc is not done, but could not get next proc_param");
1232 		next_cap_stream = proc_param->stream;
1233 		next_bap_stream = &next_cap_stream->bap_stream;
1234 
1235 		active_proc->proc_initiated_cnt++;
1236 
1237 		err = bt_bap_stream_connect(next_bap_stream);
1238 		if (err == 0 || err == -EALREADY) {
1239 			/* Pending connected - wait for connected callback */
1240 		} else if (err != 0) {
1241 			LOG_DBG("Failed to connect stream %p: %d", next_cap_stream, err);
1242 
1243 			bt_cap_common_abort_proc(next_bap_stream->conn, err);
1244 			cap_initiator_unicast_audio_proc_complete();
1245 		}
1246 
1247 		return;
1248 	}
1249 
1250 	/* All streams connected - Start sending the receiver start ready for all source
1251 	 * ASEs. For sink ASEs it is the responsibility of the unicast server to do the
1252 	 * receiver start ready operation. If there are no source ASEs then we just wait.
1253 	 */
1254 	bt_cap_common_set_subproc(BT_CAP_COMMON_SUBPROC_TYPE_START);
1255 	proc_param = get_next_proc_param(active_proc);
1256 	if (proc_param == NULL) {
1257 		/* If proc_param is NULL then this step is a no-op and we can skip to the next step
1258 		 */
1259 		bt_cap_initiator_started(active_proc->proc_param.initiator[0].stream);
1260 
1261 		return;
1262 	}
1263 
1264 	bap_stream = &proc_param->stream->bap_stream;
1265 	if (stream_is_dir(bap_stream, BT_AUDIO_DIR_SOURCE)) {
1266 		/* Since BAP operations may require a write long or a read long on the notification,
1267 		 * we cannot assume that we can do multiple streams at once, thus do it one at a
1268 		 * time.
1269 		 * TODO: We should always be able to do one per ACL, so there is room for
1270 		 * optimization.
1271 		 */
1272 		err = bt_bap_stream_start(bap_stream);
1273 		if (err != 0) {
1274 			LOG_DBG("Failed to start stream %p: %d", proc_param->stream, err);
1275 
1276 			bt_cap_common_abort_proc(bap_stream->conn, err);
1277 			cap_initiator_unicast_audio_proc_complete();
1278 
1279 			return;
1280 		}
1281 	}
1282 }
1283 
bt_cap_initiator_started(struct bt_cap_stream * cap_stream)1284 void bt_cap_initiator_started(struct bt_cap_stream *cap_stream)
1285 {
1286 	struct bt_cap_common_proc *active_proc = bt_cap_common_get_active_proc();
1287 
1288 	LOG_DBG("cap_stream %p", cap_stream);
1289 
1290 	if (!bt_cap_common_stream_in_active_proc(cap_stream)) {
1291 		/* State change happened outside of a procedure; ignore */
1292 		return;
1293 	}
1294 
1295 	/* Streams may go into the streaming state while we are connecting or starting them */
1296 	if (!bt_cap_common_subproc_is_type(BT_CAP_COMMON_SUBPROC_TYPE_START) &&
1297 	    !bt_cap_common_subproc_is_type(BT_CAP_COMMON_SUBPROC_TYPE_CONNECT)) {
1298 		/* Unexpected callback - Abort */
1299 		bt_cap_common_abort_proc(cap_stream->bap_stream.conn, -EBADMSG);
1300 	} else {
1301 		update_proc_done_cnt(active_proc);
1302 
1303 		LOG_DBG("Stream %p started (%zu/%zu streams done)", cap_stream,
1304 			active_proc->proc_done_cnt, active_proc->proc_cnt);
1305 	}
1306 
1307 	if (!bt_cap_common_proc_is_done()) {
1308 		struct bt_cap_initiator_proc_param *proc_param;
1309 		struct bt_cap_stream *next_cap_stream;
1310 		struct bt_bap_stream *next_bap_stream;
1311 
1312 		proc_param = get_next_proc_param(active_proc);
1313 		__ASSERT(proc_param != NULL, "proc is not done, but could not get next proc_param");
1314 		next_cap_stream = proc_param->stream;
1315 		next_bap_stream = &next_cap_stream->bap_stream;
1316 
1317 		if (stream_is_dir(next_bap_stream, BT_AUDIO_DIR_SOURCE)) {
1318 			int err;
1319 
1320 			/* Since BAP operations may require a write long or a read long on
1321 			 * the notification, we cannot assume that we can do multiple
1322 			 * streams at once, thus do it one at a time.
1323 			 * TODO: We should always be able to do one per ACL, so there is
1324 			 * room for optimization.
1325 			 */
1326 			err = bt_bap_stream_start(next_bap_stream);
1327 			if (err != 0) {
1328 				LOG_DBG("Failed to start stream %p: %d", next_cap_stream, err);
1329 
1330 				/* End and mark procedure as aborted.
1331 				 * If we have sent any requests over air, we will abort
1332 				 * once all sent requests has completed
1333 				 */
1334 				bt_cap_common_abort_proc(next_bap_stream->conn, err);
1335 				cap_initiator_unicast_audio_proc_complete();
1336 
1337 				return;
1338 			}
1339 		} /* else await notifications from server */
1340 
1341 		/* Return to await for response from server */
1342 		return;
1343 	}
1344 
1345 	cap_initiator_unicast_audio_proc_complete();
1346 }
1347 
can_update_metadata(const struct bt_bap_stream * bap_stream)1348 static bool can_update_metadata(const struct bt_bap_stream *bap_stream)
1349 {
1350 	return stream_is_in_state(bap_stream, BT_BAP_EP_STATE_ENABLING) ||
1351 	       stream_is_in_state(bap_stream, BT_BAP_EP_STATE_STREAMING);
1352 }
1353 
valid_unicast_audio_update_param(const struct bt_cap_unicast_audio_update_param * param)1354 static bool valid_unicast_audio_update_param(const struct bt_cap_unicast_audio_update_param *param)
1355 {
1356 	struct bt_bap_unicast_group *unicast_group = NULL;
1357 
1358 	CHECKIF(param == NULL) {
1359 		LOG_DBG("param is NULL");
1360 		return false;
1361 	}
1362 
1363 	CHECKIF(param->count == 0) {
1364 		LOG_DBG("Invalid param->count: %u", param->count);
1365 		return false;
1366 	}
1367 
1368 	CHECKIF(param->stream_params == NULL) {
1369 		LOG_DBG("param->stream_params is NULL");
1370 		return false;
1371 	}
1372 
1373 	CHECKIF(param->count > CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT) {
1374 		LOG_DBG("param->count (%zu) is larger than "
1375 			"CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT (%d)",
1376 			param->count, CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT);
1377 		return false;
1378 	}
1379 
1380 	for (size_t i = 0U; i < param->count; i++) {
1381 		const struct bt_cap_unicast_audio_update_stream_param *stream_param =
1382 			&param->stream_params[i];
1383 		const struct bt_cap_stream *cap_stream = stream_param->stream;
1384 		const struct bt_bap_stream *bap_stream;
1385 		struct bt_conn *conn;
1386 
1387 		CHECKIF(cap_stream == NULL) {
1388 			LOG_DBG("param->stream_params[%zu] is NULL", i);
1389 			return false;
1390 		}
1391 
1392 		bap_stream = &cap_stream->bap_stream;
1393 		conn = bap_stream->conn;
1394 		CHECKIF(conn == NULL) {
1395 			LOG_DBG("param->stream_params[%zu].stream->bap_stream.conn is NULL", i);
1396 
1397 			return -EINVAL;
1398 		}
1399 
1400 		CHECKIF(bap_stream->group == NULL) {
1401 			LOG_DBG("param->stream_params[%zu] is not in a unicast group", i);
1402 			return false;
1403 		}
1404 
1405 		/* Use the group of the first stream for comparison */
1406 		if (unicast_group == NULL) {
1407 			unicast_group = bap_stream->group;
1408 		} else {
1409 			CHECKIF(bap_stream->group != unicast_group) {
1410 				LOG_DBG("param->stream_params[%zu] is not in this group %p", i,
1411 					unicast_group);
1412 				return false;
1413 			}
1414 		}
1415 
1416 		if (!can_update_metadata(bap_stream)) {
1417 			LOG_DBG("param->stream_params[%zu].stream is not in right state to be "
1418 				"updated",
1419 				i);
1420 
1421 			return false;
1422 		}
1423 
1424 		if (!cap_initiator_valid_metadata(stream_param->meta, stream_param->meta_len)) {
1425 			LOG_DBG("param->stream_params[%zu] invalid metadata", i);
1426 
1427 			return false;
1428 		}
1429 
1430 		for (size_t j = 0U; j < i; j++) {
1431 			if (param->stream_params[j].stream == cap_stream) {
1432 				LOG_DBG("param->stream_params[%zu] (%p) is "
1433 					"duplicated by "
1434 					"param->stream_params[%zu] (%p)",
1435 					j, param->stream_params[j].stream, i, cap_stream);
1436 				return false;
1437 			}
1438 		}
1439 	}
1440 
1441 	return true;
1442 }
1443 
bt_cap_initiator_unicast_audio_update(const struct bt_cap_unicast_audio_update_param * param)1444 int bt_cap_initiator_unicast_audio_update(const struct bt_cap_unicast_audio_update_param *param)
1445 {
1446 	struct bt_cap_common_proc *active_proc = bt_cap_common_get_active_proc();
1447 	struct bt_cap_initiator_proc_param *proc_param;
1448 	struct bt_bap_stream *bap_stream;
1449 	const uint8_t *meta;
1450 	size_t meta_len;
1451 	int err;
1452 
1453 	if (bt_cap_common_proc_is_active()) {
1454 		LOG_DBG("A CAP procedure is already in progress");
1455 
1456 		return -EBUSY;
1457 	}
1458 
1459 	if (!valid_unicast_audio_update_param(param)) {
1460 		return -EINVAL;
1461 	}
1462 
1463 	for (size_t i = 0U; i < param->count; i++) {
1464 		const struct bt_cap_unicast_audio_update_stream_param *stream_param =
1465 			&param->stream_params[i];
1466 		struct bt_cap_stream *cap_stream = stream_param->stream;
1467 
1468 		active_proc->proc_param.initiator[i].stream = cap_stream;
1469 		active_proc->proc_param.initiator[i].meta_update.meta_len = stream_param->meta_len;
1470 		memcpy(&active_proc->proc_param.initiator[i].meta_update.meta, stream_param->meta,
1471 		       stream_param->meta_len);
1472 	}
1473 
1474 	bt_cap_common_start_proc(BT_CAP_COMMON_PROC_TYPE_UPDATE, param->count);
1475 	bt_cap_common_set_subproc(BT_CAP_COMMON_SUBPROC_TYPE_META_UPDATE);
1476 
1477 	proc_param = get_next_proc_param(active_proc);
1478 	__ASSERT(proc_param != NULL, "proc is not done, but could not get next proc_param");
1479 
1480 	bap_stream = &proc_param->stream->bap_stream;
1481 	meta_len = proc_param->meta_update.meta_len;
1482 	meta = proc_param->meta_update.meta;
1483 	active_proc->proc_initiated_cnt++;
1484 
1485 	err = bt_bap_stream_metadata(bap_stream, meta, meta_len);
1486 	if (err != 0) {
1487 		LOG_DBG("Failed to update metadata for stream %p: %d", proc_param->stream, err);
1488 
1489 		bt_cap_common_clear_active_proc();
1490 	}
1491 
1492 	return err;
1493 }
1494 
bt_cap_initiator_unicast_audio_cancel(void)1495 int bt_cap_initiator_unicast_audio_cancel(void)
1496 {
1497 	if (!bt_cap_common_proc_is_active() && !bt_cap_common_proc_is_aborted()) {
1498 		LOG_DBG("No CAP procedure is in progress");
1499 
1500 		return -EALREADY;
1501 	}
1502 
1503 	bt_cap_common_abort_proc(NULL, -ECANCELED);
1504 	cap_initiator_unicast_audio_proc_complete();
1505 
1506 	return 0;
1507 }
1508 
bt_cap_initiator_metadata_updated(struct bt_cap_stream * cap_stream)1509 void bt_cap_initiator_metadata_updated(struct bt_cap_stream *cap_stream)
1510 {
1511 	struct bt_cap_common_proc *active_proc = bt_cap_common_get_active_proc();
1512 
1513 	if (!bt_cap_common_stream_in_active_proc(cap_stream)) {
1514 		/* State change happened outside of a procedure; ignore */
1515 		return;
1516 	}
1517 
1518 	if (!bt_cap_common_subproc_is_type(BT_CAP_COMMON_SUBPROC_TYPE_META_UPDATE)) {
1519 		/* Unexpected callback - Abort */
1520 		bt_cap_common_abort_proc(cap_stream->bap_stream.conn, -EBADMSG);
1521 	} else {
1522 		update_proc_done_cnt(active_proc);
1523 
1524 		LOG_DBG("Stream %p QoS metadata updated (%zu/%zu streams done)", cap_stream,
1525 			active_proc->proc_done_cnt, active_proc->proc_cnt);
1526 	}
1527 
1528 	if (bt_cap_common_proc_is_aborted()) {
1529 		if (bt_cap_common_proc_all_handled()) {
1530 			cap_initiator_unicast_audio_proc_complete();
1531 		}
1532 
1533 		return;
1534 	}
1535 
1536 	if (!bt_cap_common_proc_is_done()) {
1537 		const size_t proc_done_cnt = active_proc->proc_done_cnt;
1538 		struct bt_cap_initiator_proc_param *proc_param;
1539 		struct bt_cap_stream *next_cap_stream;
1540 		struct bt_bap_stream *bap_stream;
1541 		const uint8_t *meta;
1542 		size_t meta_len;
1543 		int err;
1544 
1545 		proc_param = &active_proc->proc_param.initiator[proc_done_cnt];
1546 		meta_len = proc_param->meta_update.meta_len;
1547 		meta = proc_param->meta_update.meta;
1548 		next_cap_stream = proc_param->stream;
1549 		bap_stream = &next_cap_stream->bap_stream;
1550 		active_proc->proc_initiated_cnt++;
1551 
1552 		/* Since BAP operations may require a write long or a read long on the notification,
1553 		 * we cannot assume that we can do multiple streams at once, thus do it one at a
1554 		 * time.
1555 		 * TODO: We should always be able to do one per ACL, so there is room for
1556 		 * optimization.
1557 		 */
1558 
1559 		err = bt_bap_stream_metadata(bap_stream, meta, meta_len);
1560 		if (err != 0) {
1561 			LOG_DBG("Failed to update metadata for stream %p: %d", next_cap_stream,
1562 				err);
1563 
1564 			bt_cap_common_abort_proc(bap_stream->conn, err);
1565 			cap_initiator_unicast_audio_proc_complete();
1566 		}
1567 
1568 		return;
1569 	}
1570 
1571 	cap_initiator_unicast_audio_proc_complete();
1572 }
1573 
can_release(const struct bt_bap_stream * bap_stream)1574 static bool can_release(const struct bt_bap_stream *bap_stream)
1575 {
1576 	if (bap_stream->conn == NULL) {
1577 		return false;
1578 	}
1579 
1580 	return !stream_is_in_state(bap_stream, BT_BAP_EP_STATE_IDLE);
1581 }
1582 
valid_unicast_audio_stop_param(const struct bt_cap_unicast_audio_stop_param * param)1583 static bool valid_unicast_audio_stop_param(const struct bt_cap_unicast_audio_stop_param *param)
1584 {
1585 	struct bt_bap_unicast_group *unicast_group = NULL;
1586 
1587 	CHECKIF(param == NULL) {
1588 		LOG_DBG("param is NULL");
1589 		return false;
1590 	}
1591 
1592 	CHECKIF(param->count == 0) {
1593 		LOG_DBG("Invalid param->count: %u", param->count);
1594 		return false;
1595 	}
1596 
1597 	CHECKIF(param->streams == NULL) {
1598 		LOG_DBG("param->streams is NULL");
1599 		return false;
1600 	}
1601 
1602 	CHECKIF(param->count > CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT) {
1603 		LOG_DBG("param->count (%zu) is larger than "
1604 			"CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT (%d)",
1605 			param->count, CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT);
1606 		return false;
1607 	}
1608 
1609 	for (size_t i = 0U; i < param->count; i++) {
1610 		const struct bt_cap_stream *cap_stream = param->streams[i];
1611 		const struct bt_bap_stream *bap_stream;
1612 		struct bt_conn *conn;
1613 
1614 		CHECKIF(cap_stream == NULL) {
1615 			LOG_DBG("param->streams[%zu] is NULL", i);
1616 			return false;
1617 		}
1618 
1619 		bap_stream = &cap_stream->bap_stream;
1620 		conn = bap_stream->conn;
1621 		CHECKIF(conn == NULL) {
1622 			LOG_DBG("param->streams[%zu]->bap_stream.conn is NULL", i);
1623 
1624 			return -EINVAL;
1625 		}
1626 
1627 		CHECKIF(bap_stream->group == NULL) {
1628 			LOG_DBG("param->streams[%zu] is not in a unicast group", i);
1629 			return false;
1630 		}
1631 
1632 		/* Use the group of the first stream for comparison */
1633 		if (unicast_group == NULL) {
1634 			unicast_group = bap_stream->group;
1635 		} else {
1636 			CHECKIF(bap_stream->group != unicast_group) {
1637 				LOG_DBG("param->streams[%zu] is not in this group %p", i,
1638 					unicast_group);
1639 				return false;
1640 			}
1641 		}
1642 
1643 		if (!can_release(bap_stream)) {
1644 			LOG_DBG("Cannot stop param->streams[%zu]", i);
1645 
1646 			return false;
1647 		}
1648 
1649 		for (size_t j = 0U; j < i; j++) {
1650 			if (param->streams[j] == cap_stream) {
1651 				LOG_DBG("param->stream_params[%zu] (%p) is "
1652 					"duplicated by "
1653 					"param->stream_params[%zu] (%p)",
1654 					j, param->streams[j], i, cap_stream);
1655 				return false;
1656 			}
1657 		}
1658 	}
1659 
1660 	return true;
1661 }
1662 
bt_cap_initiator_unicast_audio_stop(const struct bt_cap_unicast_audio_stop_param * param)1663 int bt_cap_initiator_unicast_audio_stop(const struct bt_cap_unicast_audio_stop_param *param)
1664 {
1665 	struct bt_cap_common_proc *active_proc = bt_cap_common_get_active_proc();
1666 	struct bt_cap_initiator_proc_param *proc_param;
1667 	struct bt_bap_stream *bap_stream;
1668 	int err;
1669 
1670 	if (bt_cap_common_proc_is_active()) {
1671 		LOG_DBG("A CAP procedure is already in progress");
1672 
1673 		return -EBUSY;
1674 	}
1675 
1676 	if (!valid_unicast_audio_stop_param(param)) {
1677 		return -EINVAL;
1678 	}
1679 
1680 	for (size_t i = 0U; i < param->count; i++) {
1681 		struct bt_cap_stream *cap_stream = param->streams[i];
1682 
1683 		active_proc->proc_param.initiator[i].stream = cap_stream;
1684 	}
1685 
1686 	bt_cap_common_start_proc(BT_CAP_COMMON_PROC_TYPE_STOP, param->count);
1687 
1688 	bt_cap_common_set_subproc(BT_CAP_COMMON_SUBPROC_TYPE_RELEASE);
1689 
1690 	/** TODO: If this is a CSIP set, then the order of the procedures may
1691 	 * not match the order in the parameters, and the CSIP ordered access
1692 	 * procedure should be used.
1693 	 */
1694 	proc_param = get_next_proc_param(active_proc);
1695 	__ASSERT(proc_param != NULL, "proc is not done, but could not get next proc_param");
1696 
1697 	bap_stream = &proc_param->stream->bap_stream;
1698 	active_proc->proc_initiated_cnt++;
1699 
1700 	err = bt_bap_stream_release(bap_stream);
1701 	if (err != 0) {
1702 		LOG_DBG("Failed to stop bap_stream %p: %d", proc_param->stream, err);
1703 
1704 		bt_cap_common_clear_active_proc();
1705 	}
1706 
1707 	return err;
1708 }
1709 
bt_cap_initiator_released(struct bt_cap_stream * cap_stream)1710 void bt_cap_initiator_released(struct bt_cap_stream *cap_stream)
1711 {
1712 	struct bt_cap_common_proc *active_proc = bt_cap_common_get_active_proc();
1713 
1714 	if (!bt_cap_common_stream_in_active_proc(cap_stream)) {
1715 		/* State change happened outside of a procedure; ignore */
1716 		return;
1717 	}
1718 
1719 	if (!bt_cap_common_subproc_is_type(BT_CAP_COMMON_SUBPROC_TYPE_RELEASE)) {
1720 		/* Unexpected callback - Abort */
1721 		bt_cap_common_abort_proc(cap_stream->bap_stream.conn, -EBADMSG);
1722 	} else {
1723 		update_proc_done_cnt(active_proc);
1724 
1725 		LOG_DBG("Stream %p released (%zu/%zu streams done)", cap_stream,
1726 			active_proc->proc_done_cnt, active_proc->proc_cnt);
1727 	}
1728 
1729 	if (bt_cap_common_proc_is_aborted()) {
1730 		if (bt_cap_common_proc_all_handled()) {
1731 			cap_initiator_unicast_audio_proc_complete();
1732 		}
1733 
1734 		return;
1735 	}
1736 
1737 	if (!bt_cap_common_proc_is_done()) {
1738 		struct bt_cap_stream *next_cap_stream =
1739 			active_proc->proc_param.initiator[active_proc->proc_done_cnt].stream;
1740 		struct bt_bap_stream *bap_stream = &next_cap_stream->bap_stream;
1741 		int err;
1742 
1743 		active_proc->proc_initiated_cnt++;
1744 		/* Since BAP operations may require a write long or a read long on the
1745 		 * notification, we cannot assume that we can do multiple streams at once,
1746 		 * thus do it one at a time.
1747 		 * TODO: We should always be able to do one per ACL, so there is room for
1748 		 * optimization.
1749 		 */
1750 		err = bt_bap_stream_release(bap_stream);
1751 		if (err != 0) {
1752 			LOG_DBG("Failed to release stream %p: %d", next_cap_stream, err);
1753 
1754 			bt_cap_common_abort_proc(bap_stream->conn, err);
1755 			cap_initiator_unicast_audio_proc_complete();
1756 		}
1757 	} else {
1758 		cap_initiator_unicast_audio_proc_complete();
1759 	}
1760 }
1761 
1762 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
1763 
1764 #if defined(CONFIG_BT_BAP_BROADCAST_SOURCE) && defined(CONFIG_BT_BAP_UNICAST_CLIENT)
1765 
bt_cap_initiator_unicast_to_broadcast(const struct bt_cap_unicast_to_broadcast_param * param,struct bt_cap_broadcast_source ** source)1766 int bt_cap_initiator_unicast_to_broadcast(
1767 	const struct bt_cap_unicast_to_broadcast_param *param,
1768 	struct bt_cap_broadcast_source **source)
1769 {
1770 	return -ENOSYS;
1771 }
1772 
bt_cap_initiator_broadcast_to_unicast(const struct bt_cap_broadcast_to_unicast_param * param,struct bt_bap_unicast_group ** unicast_group)1773 int bt_cap_initiator_broadcast_to_unicast(const struct bt_cap_broadcast_to_unicast_param *param,
1774 					  struct bt_bap_unicast_group **unicast_group)
1775 {
1776 	return -ENOSYS;
1777 }
1778 
1779 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE && CONFIG_BT_BAP_UNICAST_CLIENT */
1780