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