1 /*
2  * Copyright (c) 2022-2023 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/aics.h>
15 #include <zephyr/bluetooth/audio/audio.h>
16 #include <zephyr/bluetooth/audio/bap.h>
17 #include <zephyr/bluetooth/audio/cap.h>
18 #include <zephyr/bluetooth/audio/csip.h>
19 #include <zephyr/bluetooth/audio/micp.h>
20 #include <zephyr/bluetooth/audio/vcp.h>
21 #include <zephyr/bluetooth/audio/vocs.h>
22 #include <zephyr/bluetooth/addr.h>
23 #include <zephyr/bluetooth/conn.h>
24 #include <zephyr/bluetooth/gap.h>
25 #include <zephyr/bluetooth/gatt.h>
26 #include <zephyr/logging/log.h>
27 #include <zephyr/sys/__assert.h>
28 #include <zephyr/sys/check.h>
29 #include <zephyr/sys/util.h>
30 
31 #include "audio_internal.h"
32 #include "bap_endpoint.h"
33 #include "bap_internal.h"
34 #include "cap_internal.h"
35 #include "csip_internal.h"
36 
37 LOG_MODULE_REGISTER(bt_cap_commander, CONFIG_BT_CAP_COMMANDER_LOG_LEVEL);
38 
39 #include "common/bt_str.h"
40 
41 static void cap_commander_proc_complete(void);
42 
43 static const struct bt_cap_commander_cb *cap_cb;
44 
bt_cap_commander_register_cb(const struct bt_cap_commander_cb * cb)45 int bt_cap_commander_register_cb(const struct bt_cap_commander_cb *cb)
46 {
47 	CHECKIF(cb == NULL) {
48 		LOG_DBG("cb is NULL");
49 
50 		return -EINVAL;
51 	}
52 
53 	CHECKIF(cap_cb != NULL) {
54 		LOG_DBG("callbacks already registered");
55 
56 		return -EALREADY;
57 	}
58 
59 	cap_cb = cb;
60 
61 	return 0;
62 }
63 
bt_cap_commander_unregister_cb(const struct bt_cap_commander_cb * cb)64 int bt_cap_commander_unregister_cb(const struct bt_cap_commander_cb *cb)
65 {
66 	CHECKIF(cb == NULL) {
67 		LOG_DBG("cb is NULL");
68 		return -EINVAL;
69 	}
70 
71 	CHECKIF(cap_cb != cb) {
72 		LOG_DBG("cb is not registered");
73 		return -EINVAL;
74 	}
75 
76 	cap_cb = NULL;
77 
78 	return 0;
79 }
80 
81 static void
cap_commander_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)82 cap_commander_discover_complete(struct bt_conn *conn, int err,
83 				const struct bt_csip_set_coordinator_set_member *member,
84 				const struct bt_csip_set_coordinator_csis_inst *csis_inst)
85 {
86 	if (cap_cb && cap_cb->discovery_complete) {
87 		cap_cb->discovery_complete(conn, err, member, csis_inst);
88 	}
89 }
90 
bt_cap_commander_discover(struct bt_conn * conn)91 int bt_cap_commander_discover(struct bt_conn *conn)
92 {
93 	CHECKIF(conn == NULL) {
94 		LOG_DBG("NULL conn");
95 		return -EINVAL;
96 	}
97 
98 	return bt_cap_common_discover(conn, cap_commander_discover_complete);
99 }
100 
101 #if defined(CONFIG_BT_BAP_BROADCAST_ASSISTANT)
102 static struct bt_bap_broadcast_assistant_cb broadcast_assistant_cb;
103 static bool broadcast_assistant_cb_registered;
104 
105 static void
copy_broadcast_reception_start_param(struct bt_bap_broadcast_assistant_add_src_param * add_src_param,struct cap_broadcast_reception_start * start_param)106 copy_broadcast_reception_start_param(struct bt_bap_broadcast_assistant_add_src_param *add_src_param,
107 				     struct cap_broadcast_reception_start *start_param)
108 {
109 	bt_addr_le_copy(&add_src_param->addr, &start_param->addr);
110 	add_src_param->adv_sid = start_param->adv_sid;
111 	add_src_param->broadcast_id = start_param->broadcast_id;
112 	add_src_param->pa_sync = true;
113 	add_src_param->pa_interval = start_param->pa_interval;
114 	add_src_param->num_subgroups = start_param->num_subgroups;
115 	add_src_param->subgroups = start_param->subgroups;
116 }
117 
cap_commander_broadcast_assistant_add_src_cb(struct bt_conn * conn,int err)118 static void cap_commander_broadcast_assistant_add_src_cb(struct bt_conn *conn, int err)
119 {
120 	struct bt_cap_common_proc *active_proc = bt_cap_common_get_active_proc();
121 	struct bt_bap_broadcast_assistant_add_src_param add_src_param = {0};
122 
123 	LOG_DBG("conn %p", (void *)conn);
124 
125 	if (!bt_cap_common_conn_in_active_proc(conn)) {
126 
127 		/* State change happened outside of a procedure; ignore */
128 		return;
129 	}
130 
131 	if (err != 0) {
132 		LOG_DBG("Failed to add source: %d", err);
133 		LOG_DBG("Aborting the proc %d %d", active_proc->proc_done_cnt,
134 			active_proc->proc_initiated_cnt);
135 
136 		bt_cap_common_abort_proc(conn, err);
137 	} else {
138 		active_proc->proc_done_cnt++;
139 
140 		LOG_DBG("Conn %p broadcast source added (%zu/%zu streams done)", (void *)conn,
141 			active_proc->proc_done_cnt, active_proc->proc_cnt);
142 	}
143 
144 	if (bt_cap_common_proc_is_aborted()) {
145 		if (bt_cap_common_proc_all_handled()) {
146 			cap_commander_proc_complete();
147 		}
148 
149 		return;
150 	}
151 
152 	if (!bt_cap_common_proc_is_done()) {
153 		struct bt_cap_commander_proc_param *proc_param;
154 
155 		proc_param = &active_proc->proc_param.commander[active_proc->proc_done_cnt];
156 		conn = proc_param->conn;
157 		copy_broadcast_reception_start_param(&add_src_param,
158 						     &proc_param->broadcast_reception_start);
159 
160 		active_proc->proc_initiated_cnt++;
161 		err = bt_bap_broadcast_assistant_add_src(conn, &add_src_param);
162 		if (err != 0) {
163 			LOG_DBG("Failed to perform broadcast reception start for conn %p: %d",
164 				(void *)conn, err);
165 			bt_cap_common_abort_proc(conn, err);
166 			cap_commander_proc_complete();
167 		}
168 	} else {
169 		cap_commander_proc_complete();
170 	}
171 }
172 
cap_commander_register_broadcast_assistant_cb(void)173 static int cap_commander_register_broadcast_assistant_cb(void)
174 {
175 	int err;
176 
177 	err = bt_bap_broadcast_assistant_register_cb(&broadcast_assistant_cb);
178 	if (err != 0) {
179 		LOG_DBG("Failed to register broadcast assistant callbacks: %d", err);
180 
181 		return -ENOEXEC;
182 	}
183 
184 	broadcast_assistant_cb_registered = true;
185 
186 	return 0;
187 }
188 
valid_broadcast_reception_start_param(const struct bt_cap_commander_broadcast_reception_start_param * param)189 static bool valid_broadcast_reception_start_param(
190 	const struct bt_cap_commander_broadcast_reception_start_param *param)
191 {
192 	uint32_t total_bis_sync = 0U;
193 
194 	CHECKIF(param == NULL) {
195 		LOG_DBG("param is NULL");
196 		return false;
197 	}
198 
199 	CHECKIF(param->count == 0) {
200 		LOG_DBG("Invalid param->count: %zu", param->count);
201 		return false;
202 	}
203 
204 	CHECKIF(param->count > CONFIG_BT_MAX_CONN) {
205 		LOG_DBG("param->count (%zu) is larger than CONFIG_BT_MAX_CONN (%d)", param->count,
206 			CONFIG_BT_MAX_CONN);
207 		return false;
208 	}
209 
210 	CHECKIF(param->param == NULL) {
211 		LOG_DBG("param->param is NULL");
212 		return false;
213 	}
214 
215 	for (size_t i = 0; i < param->count; i++) {
216 		const struct bt_cap_commander_broadcast_reception_start_member_param *start_param =
217 			&param->param[i];
218 		const union bt_cap_set_member *member = &param->param[i].member;
219 		const struct bt_conn *member_conn =
220 			bt_cap_common_get_member_conn(param->type, member);
221 
222 		if (member == NULL) {
223 			LOG_DBG("param->param[%zu].member is NULL", i);
224 			return false;
225 		}
226 
227 		if (member_conn == NULL) {
228 			LOG_DBG("Invalid param->param[%zu].member", i);
229 			return false;
230 		}
231 
232 		CHECKIF(start_param->addr.type > BT_ADDR_LE_RANDOM) {
233 			LOG_DBG("Invalid address type %u", start_param->addr.type);
234 			return false;
235 		}
236 
237 		CHECKIF(start_param->adv_sid > BT_GAP_SID_MAX) {
238 			LOG_DBG("param->param[%zu]->adv_sid is larger than %d", i, BT_GAP_SID_MAX);
239 			return false;
240 		}
241 
242 		CHECKIF(!IN_RANGE(start_param->pa_interval, BT_GAP_PER_ADV_MIN_INTERVAL,
243 				  BT_GAP_PER_ADV_MAX_INTERVAL)) {
244 			LOG_DBG("param->param[%zu]->pa_interval is out of range", i);
245 			return false;
246 		}
247 
248 		CHECKIF(start_param->broadcast_id > BT_AUDIO_BROADCAST_ID_MAX) {
249 			LOG_DBG("param->param[%zu]->broadcast_id is larger than %u", i,
250 				BT_AUDIO_BROADCAST_ID_MAX);
251 			return false;
252 		}
253 
254 		CHECKIF(start_param->num_subgroups == 0) {
255 			LOG_DBG("param->param[%zu]->num_subgroups is 0", i);
256 			return false;
257 		}
258 
259 		CHECKIF(start_param->num_subgroups > CONFIG_BT_BAP_BASS_MAX_SUBGROUPS) {
260 			LOG_DBG("Too many subgroups %u/%u", start_param->num_subgroups,
261 				CONFIG_BT_BAP_BASS_MAX_SUBGROUPS);
262 
263 			return false;
264 		}
265 
266 		CHECKIF(start_param->subgroups == NULL) {
267 			LOG_DBG("param->param[%zu]->subgroup is NULL", i);
268 			return false;
269 		}
270 
271 		total_bis_sync = 0U;
272 		for (size_t j = 0U; j < start_param->num_subgroups; j++) {
273 			const struct bt_bap_bass_subgroup *param_subgroups =
274 				&start_param->subgroups[j];
275 
276 			CHECKIF(!valid_bis_syncs(param_subgroups->bis_sync)) {
277 				LOG_DBG("param->param[%zu].subgroup[%zu].bis_sync is invalid %u", i,
278 					j, param_subgroups->bis_sync);
279 
280 				return false;
281 			}
282 
283 			CHECKIF((total_bis_sync & param_subgroups->bis_sync) != 0) {
284 				LOG_DBG("param->param[%zu].subgroup[%zu].bis_sync 0x%08X has "
285 					"duplicate bits (0x%08X) ",
286 					i, j, param_subgroups->bis_sync, total_bis_sync);
287 
288 				return false;
289 			}
290 
291 			total_bis_sync |= param_subgroups->bis_sync;
292 
293 			CHECKIF(param_subgroups->metadata_len >
294 				CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE) {
295 				LOG_DBG("param->param[%zu].subgroup[%zu].metadata_len too long "
296 					"%u/%u",
297 					i, j, param_subgroups->metadata_len,
298 					CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE);
299 
300 				return false;
301 			}
302 #if defined(CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE)
303 			CHECKIF(param_subgroups->metadata_len > 0 &&
304 				!bt_audio_valid_ltv(param_subgroups->metadata,
305 						    param_subgroups->metadata_len)) {
306 				LOG_DBG("param->param[%zu].subgroup[%zu].metadata not valid LTV", i,
307 					j);
308 			}
309 #endif
310 		}
311 
312 		for (size_t j = 0U; j < i; j++) {
313 			const union bt_cap_set_member *other = &param->param[j].member;
314 
315 			if (other == member) {
316 				LOG_DBG("param->members[%zu] (%p) is duplicated by "
317 					"param->members[%zu] (%p)",
318 					j, other, i, member);
319 				return false;
320 			}
321 		}
322 	}
323 
324 	return true;
325 }
326 
bt_cap_commander_broadcast_reception_start(const struct bt_cap_commander_broadcast_reception_start_param * param)327 int bt_cap_commander_broadcast_reception_start(
328 	const struct bt_cap_commander_broadcast_reception_start_param *param)
329 {
330 	struct bt_bap_broadcast_assistant_add_src_param add_src_param = {0};
331 	struct bt_cap_commander_proc_param *proc_param;
332 	struct bt_cap_common_proc *active_proc;
333 	struct bt_conn *conn;
334 	int err;
335 
336 	if (bt_cap_common_proc_is_active()) {
337 		LOG_DBG("A CAP procedure is already in progress");
338 
339 		return -EBUSY;
340 	}
341 
342 	if (!valid_broadcast_reception_start_param(param)) {
343 		return -EINVAL;
344 	}
345 
346 	bt_cap_common_start_proc(BT_CAP_COMMON_PROC_TYPE_BROADCAST_RECEPTION_START, param->count);
347 
348 	broadcast_assistant_cb.add_src = cap_commander_broadcast_assistant_add_src_cb;
349 	if (!broadcast_assistant_cb_registered &&
350 	    cap_commander_register_broadcast_assistant_cb() != 0) {
351 		LOG_DBG("Failed to register broadcast assistant callbacks");
352 
353 		return -ENOEXEC;
354 	}
355 
356 	active_proc = bt_cap_common_get_active_proc();
357 
358 	for (size_t i = 0U; i < param->count; i++) {
359 		const struct bt_cap_commander_broadcast_reception_start_member_param *member_param =
360 			&param->param[i];
361 		struct bt_cap_commander_proc_param *stored_param;
362 		struct bt_conn *member_conn =
363 			bt_cap_common_get_member_conn(param->type, &member_param->member);
364 
365 		if (member_conn == NULL) {
366 			LOG_DBG("Invalid param->members[%zu]", i);
367 
368 			return -EINVAL;
369 		}
370 
371 		/* Store the necessary parameters as we cannot assume that the supplied parameters
372 		 * are kept valid
373 		 * TODO: consider putting this into a function
374 		 */
375 		stored_param = &active_proc->proc_param.commander[i];
376 		stored_param->conn = member_conn;
377 		bt_addr_le_copy(&stored_param->broadcast_reception_start.addr, &member_param->addr);
378 		stored_param->broadcast_reception_start.adv_sid = member_param->adv_sid;
379 		stored_param->broadcast_reception_start.broadcast_id = member_param->broadcast_id;
380 		stored_param->broadcast_reception_start.pa_interval = member_param->pa_interval;
381 		stored_param->broadcast_reception_start.num_subgroups = member_param->num_subgroups;
382 		memcpy(stored_param->broadcast_reception_start.subgroups, member_param->subgroups,
383 		       sizeof(struct bt_bap_bass_subgroup) * member_param->num_subgroups);
384 	}
385 
386 	active_proc->proc_initiated_cnt++;
387 
388 	proc_param = &active_proc->proc_param.commander[0];
389 
390 	conn = proc_param->conn;
391 	copy_broadcast_reception_start_param(&add_src_param,
392 					     &proc_param->broadcast_reception_start);
393 
394 	/* TODO: what to do if we are adding a source that has already been added? */
395 	err = bt_bap_broadcast_assistant_add_src(conn, &add_src_param);
396 	if (err != 0) {
397 		LOG_DBG("Failed to start broadcast reception for conn %p: %d", (void *)conn, err);
398 
399 		return -ENOEXEC;
400 	}
401 
402 	return 0;
403 }
404 
405 static void
copy_broadcast_reception_stop_param(struct bt_bap_broadcast_assistant_mod_src_param * mod_src_param,struct cap_broadcast_reception_stop * stop_param)406 copy_broadcast_reception_stop_param(struct bt_bap_broadcast_assistant_mod_src_param *mod_src_param,
407 				    struct cap_broadcast_reception_stop *stop_param)
408 {
409 	mod_src_param->src_id = stop_param->src_id;
410 	mod_src_param->pa_sync = false;
411 	mod_src_param->pa_interval = BT_BAP_PA_INTERVAL_UNKNOWN;
412 	mod_src_param->num_subgroups = stop_param->num_subgroups;
413 
414 	mod_src_param->subgroups = stop_param->subgroups;
415 }
416 
cap_commander_broadcast_assistant_recv_state_cb(struct bt_conn * conn,int err,const struct bt_bap_scan_delegator_recv_state * state)417 static void cap_commander_broadcast_assistant_recv_state_cb(
418 	struct bt_conn *conn, int err, const struct bt_bap_scan_delegator_recv_state *state)
419 {
420 	struct bt_cap_common_proc *active_proc = bt_cap_common_get_active_proc();
421 
422 	if (state == NULL) {
423 		/* Empty receive state, indicating that the source has been removed
424 		 */
425 		return;
426 	}
427 
428 	if (bt_cap_common_conn_in_active_proc(conn) &&
429 	    active_proc->proc_type == BT_CAP_COMMON_PROC_TYPE_BROADCAST_RECEPTION_STOP) {
430 
431 		LOG_DBG("BASS recv state: conn %p, src_id %u", (void *)conn, state->src_id);
432 
433 		for (uint8_t i = 0; i < state->num_subgroups; i++) {
434 			const struct bt_bap_bass_subgroup *subgroup = &state->subgroups[i];
435 
436 			/* if bis_sync not equals 0 we can not remove the source (yet)
437 			 * and we need to wait for another notification
438 			 */
439 			if (subgroup->bis_sync != 0) {
440 				return;
441 			}
442 		}
443 
444 		LOG_DBG("Removing source for conn %p", (void *)conn);
445 		err = bt_bap_broadcast_assistant_rem_src(conn, state->src_id);
446 		if (err != 0) {
447 			LOG_DBG("Failed to rem_src for conn %p: %d", (void *)conn, err);
448 			bt_cap_common_abort_proc(conn, err);
449 			cap_commander_proc_complete();
450 		}
451 	}
452 }
453 
cap_commander_broadcast_assistant_rem_src_cb(struct bt_conn * conn,int err)454 static void cap_commander_broadcast_assistant_rem_src_cb(struct bt_conn *conn, int err)
455 {
456 	struct bt_cap_common_proc *active_proc = bt_cap_common_get_active_proc();
457 	struct bt_bap_broadcast_assistant_mod_src_param mod_src_param = {0};
458 
459 	if (!bt_cap_common_conn_in_active_proc(conn)) {
460 		/* State change happened outside of a procedure; ignore */
461 		return;
462 	}
463 
464 	if (err != 0) {
465 		LOG_DBG("Failed removing source: %d", err);
466 		LOG_DBG("Aborting the proc %d %d", active_proc->proc_done_cnt,
467 			active_proc->proc_initiated_cnt);
468 
469 		bt_cap_common_abort_proc(conn, err);
470 	} else {
471 		active_proc->proc_done_cnt++;
472 
473 		LOG_DBG("Conn %p broadcast source removed (%zu/%zu streams done)", (void *)conn,
474 			active_proc->proc_done_cnt, active_proc->proc_cnt);
475 	}
476 
477 	if (bt_cap_common_proc_is_aborted()) {
478 		if (bt_cap_common_proc_all_handled()) {
479 			cap_commander_proc_complete();
480 		}
481 
482 		return;
483 	}
484 
485 	if (!bt_cap_common_proc_is_done()) {
486 		struct bt_cap_commander_proc_param *proc_param;
487 
488 		proc_param = &active_proc->proc_param.commander[active_proc->proc_done_cnt];
489 		conn = proc_param->conn;
490 		copy_broadcast_reception_stop_param(&mod_src_param,
491 						    &proc_param->broadcast_reception_stop);
492 		active_proc->proc_initiated_cnt++;
493 		err = bt_bap_broadcast_assistant_mod_src(conn, &mod_src_param);
494 		if (err != 0) {
495 			LOG_DBG("Failed to mod_src for conn %p: %d", (void *)conn, err);
496 			bt_cap_common_abort_proc(conn, err);
497 			cap_commander_proc_complete();
498 		}
499 	} else {
500 		cap_commander_proc_complete();
501 	}
502 }
503 
cap_commander_broadcast_assistant_mod_src_cb(struct bt_conn * conn,int err)504 static void cap_commander_broadcast_assistant_mod_src_cb(struct bt_conn *conn, int err)
505 {
506 	struct bt_cap_common_proc *active_proc = bt_cap_common_get_active_proc();
507 
508 	if (!bt_cap_common_conn_in_active_proc(conn)) {
509 		/* State change happened outside of a procedure; ignore */
510 		return;
511 	}
512 
513 	if (err != 0) {
514 		LOG_DBG("Failed modifying source: %d", err);
515 		LOG_DBG("Aborting the proc %d %d", active_proc->proc_done_cnt,
516 			active_proc->proc_initiated_cnt);
517 
518 		bt_cap_common_abort_proc(conn, err);
519 	} else {
520 		LOG_DBG("Conn %p broadcast source modifified (%zu/%zu streams done)", (void *)conn,
521 			active_proc->proc_done_cnt, active_proc->proc_cnt);
522 	}
523 
524 	if (bt_cap_common_proc_is_aborted()) {
525 		if (bt_cap_common_proc_all_handled()) {
526 			cap_commander_proc_complete();
527 		}
528 	}
529 }
530 
valid_broadcast_reception_stop_param(const struct bt_cap_commander_broadcast_reception_stop_param * param)531 static bool valid_broadcast_reception_stop_param(
532 	const struct bt_cap_commander_broadcast_reception_stop_param *param)
533 {
534 	CHECKIF(param == NULL) {
535 		LOG_DBG("param is NULL");
536 		return false;
537 	}
538 
539 	CHECKIF(param->count == 0) {
540 		LOG_DBG("Invalid param->count: %zu", param->count);
541 		return false;
542 	}
543 
544 	CHECKIF(param->count > CONFIG_BT_MAX_CONN) {
545 		LOG_DBG("param->count (%zu) is larger than CONFIG_BT_MAX_CONN (%d)", param->count,
546 			CONFIG_BT_MAX_CONN);
547 		return false;
548 	}
549 
550 	CHECKIF(param->param == NULL) {
551 		LOG_DBG("param->param is NULL");
552 		return false;
553 	}
554 
555 	for (size_t i = 0; i < param->count; i++) {
556 		const struct bt_cap_commander_broadcast_reception_stop_member_param *stop_param =
557 			&param->param[i];
558 		const union bt_cap_set_member *member = &param->param[i].member;
559 		const struct bt_conn *member_conn =
560 			bt_cap_common_get_member_conn(param->type, member);
561 
562 		if (member == NULL) {
563 			LOG_DBG("param->param[%zu].member is NULL", i);
564 			return false;
565 		}
566 
567 		if (member_conn == NULL) {
568 			LOG_DBG("Invalid param->param[%zu].member", i);
569 			return false;
570 		}
571 
572 		CHECKIF(stop_param->num_subgroups == 0) {
573 			LOG_DBG("param->param[%zu]->num_subgroups is 0", i);
574 			return false;
575 		}
576 
577 		CHECKIF(stop_param->num_subgroups > CONFIG_BT_BAP_BASS_MAX_SUBGROUPS) {
578 			LOG_DBG("Too many subgroups %u/%u", stop_param->num_subgroups,
579 				CONFIG_BT_BAP_BASS_MAX_SUBGROUPS);
580 			return false;
581 		}
582 
583 		for (size_t j = 0U; j < i; j++) {
584 			const union bt_cap_set_member *other = &param->param[j].member;
585 			uint8_t other_src_id = param->param[j].src_id;
586 
587 			if (other == member && stop_param->src_id == other_src_id) {
588 				LOG_DBG("param->members[%zu], src_id %d (%p) is duplicated by "
589 					"param->members[%zu], src_id %d (%p)",
590 					j, other_src_id, other, i, stop_param->src_id, member);
591 				return false;
592 			}
593 		}
594 	}
595 
596 	return true;
597 }
598 
bt_cap_commander_broadcast_reception_stop(const struct bt_cap_commander_broadcast_reception_stop_param * param)599 int bt_cap_commander_broadcast_reception_stop(
600 	const struct bt_cap_commander_broadcast_reception_stop_param *param)
601 {
602 	struct bt_bap_broadcast_assistant_mod_src_param mod_src_param = {0};
603 	struct bt_cap_commander_proc_param *proc_param;
604 	struct bt_cap_common_proc *active_proc;
605 	struct bt_conn *conn;
606 	int err;
607 
608 	if (bt_cap_common_proc_is_active()) {
609 		LOG_DBG("A CAP procedure is already in progress");
610 
611 		return -EBUSY;
612 	}
613 
614 	if (!valid_broadcast_reception_stop_param(param)) {
615 		return -EINVAL;
616 	}
617 
618 	bt_cap_common_start_proc(BT_CAP_COMMON_PROC_TYPE_BROADCAST_RECEPTION_STOP, param->count);
619 
620 	broadcast_assistant_cb.mod_src = cap_commander_broadcast_assistant_mod_src_cb;
621 	broadcast_assistant_cb.rem_src = cap_commander_broadcast_assistant_rem_src_cb;
622 	broadcast_assistant_cb.recv_state = cap_commander_broadcast_assistant_recv_state_cb;
623 	if (!broadcast_assistant_cb_registered &&
624 	    cap_commander_register_broadcast_assistant_cb() != 0) {
625 		LOG_DBG("Failed to register broadcast assistant callbacks");
626 
627 		return -ENOEXEC;
628 	}
629 
630 	active_proc = bt_cap_common_get_active_proc();
631 
632 	for (size_t i = 0U; i < param->count; i++) {
633 		const struct bt_cap_commander_broadcast_reception_stop_member_param *member_param =
634 			&param->param[i];
635 		struct bt_cap_commander_proc_param *stored_param;
636 		struct bt_conn *member_conn =
637 			bt_cap_common_get_member_conn(param->type, &member_param->member);
638 
639 		if (member_conn == NULL) {
640 			LOG_DBG("Invalid param->member[%zu]", i);
641 
642 			return -EINVAL;
643 		}
644 		/* Store the necessary parameters as we cannot assume that the supplied
645 		 * parameters are kept valid
646 		 */
647 		stored_param = &active_proc->proc_param.commander[i];
648 		stored_param->conn = member_conn;
649 		stored_param->broadcast_reception_stop.src_id = member_param->src_id;
650 		stored_param->broadcast_reception_stop.num_subgroups = member_param->num_subgroups;
651 		for (size_t j = 0U; j < CONFIG_BT_BAP_BASS_MAX_SUBGROUPS; j++) {
652 			stored_param->broadcast_reception_stop.subgroups[j].bis_sync = 0;
653 			stored_param->broadcast_reception_stop.subgroups[j].metadata_len = 0;
654 		}
655 	}
656 
657 	proc_param = &active_proc->proc_param.commander[0];
658 
659 	conn = proc_param->conn;
660 	copy_broadcast_reception_stop_param(&mod_src_param, &proc_param->broadcast_reception_stop);
661 
662 	active_proc->proc_initiated_cnt++;
663 
664 	err = bt_bap_broadcast_assistant_mod_src(conn, &mod_src_param);
665 	if (err != 0) {
666 		LOG_DBG("Failed to stop broadcast reception for conn %p: %d", (void *)conn, err);
667 
668 		return -ENOEXEC;
669 	}
670 
671 	return 0;
672 }
673 
cap_commander_broadcast_assistant_set_broadcast_code_cb(struct bt_conn * conn,int err)674 static void cap_commander_broadcast_assistant_set_broadcast_code_cb(struct bt_conn *conn, int err)
675 {
676 	struct bt_cap_common_proc *active_proc = bt_cap_common_get_active_proc();
677 
678 	LOG_DBG("conn %p", (void *)conn);
679 
680 	if (!bt_cap_common_conn_in_active_proc(conn)) {
681 		/* State change happened outside of a procedure; ignore */
682 		return;
683 	}
684 
685 	if (err != 0) {
686 		LOG_DBG("Failed to distribute broadcast code: %d", err);
687 
688 		bt_cap_common_abort_proc(conn, err);
689 	} else {
690 		active_proc->proc_done_cnt++;
691 
692 		LOG_DBG("Conn %p broadcast code set (%zu/%zu done)", (void *)conn,
693 			active_proc->proc_done_cnt, active_proc->proc_cnt);
694 	}
695 
696 	if (bt_cap_common_proc_is_aborted()) {
697 		if (bt_cap_common_proc_all_handled()) {
698 			cap_commander_proc_complete();
699 		}
700 
701 		return;
702 	}
703 
704 	if (!bt_cap_common_proc_is_done()) {
705 		struct bt_cap_commander_proc_param *proc_param;
706 
707 		proc_param = &active_proc->proc_param.commander[active_proc->proc_done_cnt];
708 		conn = proc_param->conn;
709 
710 		active_proc->proc_initiated_cnt++;
711 		err = bt_bap_broadcast_assistant_set_broadcast_code(
712 			conn, proc_param->distribute_broadcast_code.src_id,
713 			proc_param->distribute_broadcast_code.broadcast_code);
714 		if (err != 0) {
715 			LOG_DBG("Failed to perform set broadcast code for conn %p: %d",
716 				(void *)conn, err);
717 			bt_cap_common_abort_proc(conn, err);
718 			cap_commander_proc_complete();
719 		}
720 	} else {
721 		cap_commander_proc_complete();
722 	}
723 }
724 
valid_distribute_broadcast_code_param(const struct bt_cap_commander_distribute_broadcast_code_param * param)725 static bool valid_distribute_broadcast_code_param(
726 	const struct bt_cap_commander_distribute_broadcast_code_param *param)
727 {
728 	CHECKIF(param == NULL) {
729 		LOG_DBG("param is NULL");
730 		return false;
731 	}
732 
733 	CHECKIF(param->count == 0) {
734 		LOG_DBG("Invalid param->count: %zu", param->count);
735 		return false;
736 	}
737 
738 	CHECKIF(param->count > CONFIG_BT_MAX_CONN) {
739 		LOG_DBG("param->count (%zu) is larger than CONFIG_BT_MAX_CONN (%d)", param->count,
740 			CONFIG_BT_MAX_CONN);
741 		return false;
742 	}
743 
744 	CHECKIF(param->param == NULL) {
745 		LOG_DBG("param->param is NULL");
746 		return false;
747 	}
748 
749 	for (size_t i = 0; i < param->count; i++) {
750 		const union bt_cap_set_member *member = &param->param[i].member;
751 		const struct bt_conn *member_conn =
752 			bt_cap_common_get_member_conn(param->type, member);
753 
754 		if (member == NULL) {
755 			LOG_DBG("param->param[%zu].member is NULL", i);
756 			return false;
757 		}
758 
759 		if (member_conn == NULL) {
760 			LOG_DBG("Invalid param->param[%zu].member", i);
761 			return false;
762 		}
763 
764 		for (size_t j = 0U; j < i; j++) {
765 			const union bt_cap_set_member *other = &param->param[j].member;
766 			const struct bt_conn *other_conn =
767 				bt_cap_common_get_member_conn(param->type, other);
768 
769 			if (other_conn == member_conn) {
770 				LOG_DBG("param->param[%zu].member.member (%p) is duplicated by "
771 					"param->member[%zu].member.member (%p)",
772 					j, (void *)other_conn, i, (void *)member_conn);
773 				return false;
774 			}
775 		}
776 	}
777 
778 	return true;
779 }
780 
bt_cap_commander_distribute_broadcast_code(const struct bt_cap_commander_distribute_broadcast_code_param * param)781 int bt_cap_commander_distribute_broadcast_code(
782 	const struct bt_cap_commander_distribute_broadcast_code_param *param)
783 {
784 	struct bt_cap_commander_proc_param *proc_param;
785 	struct bt_cap_common_proc *active_proc;
786 	struct bt_conn *conn;
787 	int err;
788 
789 	if (bt_cap_common_proc_is_active()) {
790 		LOG_DBG("A CAP procedure is already in progress");
791 
792 		return -EBUSY;
793 	}
794 
795 	if (!valid_distribute_broadcast_code_param(param)) {
796 		return -EINVAL;
797 	}
798 
799 	bt_cap_common_start_proc(BT_CAP_COMMON_PROC_TYPE_DISTRIBUTE_BROADCAST_CODE, param->count);
800 
801 	broadcast_assistant_cb.broadcast_code =
802 		cap_commander_broadcast_assistant_set_broadcast_code_cb;
803 	if (!broadcast_assistant_cb_registered &&
804 	    cap_commander_register_broadcast_assistant_cb() != 0) {
805 		LOG_DBG("Failed to register broadcast assistant callbacks");
806 
807 		return -ENOEXEC;
808 	}
809 
810 	active_proc = bt_cap_common_get_active_proc();
811 
812 	for (size_t i = 0U; i < param->count; i++) {
813 		const struct bt_cap_commander_distribute_broadcast_code_member_param *member_param =
814 			&param->param[i];
815 		struct bt_cap_commander_proc_param *stored_param;
816 		struct bt_conn *member_conn =
817 			bt_cap_common_get_member_conn(param->type, &member_param->member);
818 
819 		if (member_conn == NULL) {
820 			LOG_DBG("Invalid param->member[%zu]", i);
821 
822 			return -EINVAL;
823 		}
824 
825 		/* Store the necessary parameters as we cannot assume that the
826 		 * supplied parameters are kept valid
827 		 */
828 		stored_param = &active_proc->proc_param.commander[i];
829 		stored_param->conn = member_conn;
830 		stored_param->distribute_broadcast_code.src_id = member_param->src_id;
831 		memcpy(stored_param->distribute_broadcast_code.broadcast_code,
832 		       param->broadcast_code, BT_ISO_BROADCAST_CODE_SIZE);
833 	}
834 
835 	active_proc->proc_initiated_cnt++;
836 
837 	proc_param = &active_proc->proc_param.commander[0];
838 
839 	conn = proc_param->conn;
840 
841 	err = bt_bap_broadcast_assistant_set_broadcast_code(
842 		conn, proc_param->distribute_broadcast_code.src_id,
843 		proc_param->distribute_broadcast_code.broadcast_code);
844 
845 	if (err != 0) {
846 		LOG_DBG("Failed to start distribute broadcast code for conn %p: %d", (void *)conn,
847 			err);
848 
849 		return -ENOEXEC;
850 	}
851 
852 	return 0;
853 }
854 
855 #endif /* CONFIG_BT_BAP_BROADCAST_ASSISTANT */
856 
cap_commander_proc_complete(void)857 static void cap_commander_proc_complete(void)
858 {
859 	struct bt_cap_common_proc *active_proc = bt_cap_common_get_active_proc();
860 	enum bt_cap_common_proc_type proc_type;
861 	struct bt_conn *failed_conn;
862 	int err;
863 
864 	failed_conn = active_proc->failed_conn;
865 	err = active_proc->err;
866 	proc_type = active_proc->proc_type;
867 	bt_cap_common_clear_active_proc();
868 
869 	if (cap_cb == NULL) {
870 		return;
871 	}
872 
873 	switch (proc_type) {
874 #if defined(CONFIG_BT_VCP_VOL_CTLR)
875 	case BT_CAP_COMMON_PROC_TYPE_VOLUME_CHANGE:
876 		if (cap_cb->volume_changed != NULL) {
877 			cap_cb->volume_changed(failed_conn, err);
878 		}
879 		break;
880 	case BT_CAP_COMMON_PROC_TYPE_VOLUME_MUTE_CHANGE:
881 		if (cap_cb->volume_mute_changed != NULL) {
882 			cap_cb->volume_mute_changed(failed_conn, err);
883 		}
884 		break;
885 #if defined(CONFIG_BT_VCP_VOL_CTLR_VOCS)
886 	case BT_CAP_COMMON_PROC_TYPE_VOLUME_OFFSET_CHANGE:
887 		if (cap_cb->volume_offset_changed != NULL) {
888 			cap_cb->volume_offset_changed(failed_conn, err);
889 		}
890 		break;
891 #endif /* CONFIG_BT_VCP_VOL_CTLR_VOCS */
892 #endif /* CONFIG_BT_VCP_VOL_CTLR */
893 #if defined(CONFIG_BT_MICP_MIC_CTLR)
894 	case BT_CAP_COMMON_PROC_TYPE_MICROPHONE_MUTE_CHANGE:
895 		if (cap_cb->microphone_mute_changed != NULL) {
896 			cap_cb->microphone_mute_changed(failed_conn, err);
897 		}
898 		break;
899 #if defined(CONFIG_BT_MICP_MIC_CTLR_AICS)
900 	case BT_CAP_COMMON_PROC_TYPE_MICROPHONE_GAIN_CHANGE:
901 		if (cap_cb->microphone_gain_changed != NULL) {
902 			cap_cb->microphone_gain_changed(failed_conn, err);
903 		}
904 		break;
905 #endif /* CONFIG_BT_MICP_MIC_CTLR_AICS */
906 #endif /* CONFIG_BT_MICP_MIC_CTLR */
907 #if defined(CONFIG_BT_BAP_BROADCAST_ASSISTANT)
908 	case BT_CAP_COMMON_PROC_TYPE_BROADCAST_RECEPTION_START:
909 		if (cap_cb->broadcast_reception_start != NULL) {
910 			cap_cb->broadcast_reception_start(failed_conn, err);
911 		}
912 		break;
913 	case BT_CAP_COMMON_PROC_TYPE_BROADCAST_RECEPTION_STOP:
914 		if (cap_cb->broadcast_reception_stop != NULL) {
915 			cap_cb->broadcast_reception_stop(failed_conn, err);
916 		}
917 		break;
918 	case BT_CAP_COMMON_PROC_TYPE_DISTRIBUTE_BROADCAST_CODE:
919 		if (cap_cb->distribute_broadcast_code != NULL) {
920 			cap_cb->distribute_broadcast_code(failed_conn, err);
921 		}
922 		break;
923 #endif /* CONFIG_BT_BAP_BROADCAST_ASSISTANT */
924 	case BT_CAP_COMMON_PROC_TYPE_NONE:
925 	default:
926 		__ASSERT(false, "Invalid proc_type: %u", proc_type);
927 	}
928 }
929 
bt_cap_commander_cancel(void)930 int bt_cap_commander_cancel(void)
931 {
932 	if (!bt_cap_common_proc_is_active() && !bt_cap_common_proc_is_aborted()) {
933 		LOG_DBG("No CAP procedure is in progress");
934 
935 		return -EALREADY;
936 	}
937 
938 	bt_cap_common_abort_proc(NULL, -ECANCELED);
939 	cap_commander_proc_complete();
940 
941 	return 0;
942 }
943 
944 #if defined(CONFIG_BT_VCP_VOL_CTLR)
945 static struct bt_vcp_vol_ctlr_cb vol_ctlr_cb;
946 static bool vcp_cb_registered;
947 
cap_commander_register_vcp_cb(void)948 static int cap_commander_register_vcp_cb(void)
949 {
950 	int err;
951 
952 	err = bt_vcp_vol_ctlr_cb_register(&vol_ctlr_cb);
953 	if (err != 0) {
954 		LOG_DBG("Failed to register VCP callbacks: %d", err);
955 
956 		return -ENOEXEC;
957 	}
958 
959 	vcp_cb_registered = true;
960 
961 	return 0;
962 }
963 
valid_change_volume_param(const struct bt_cap_commander_change_volume_param * param)964 static bool valid_change_volume_param(const struct bt_cap_commander_change_volume_param *param)
965 {
966 	CHECKIF(param == NULL) {
967 		LOG_DBG("param is NULL");
968 		return false;
969 	}
970 
971 	CHECKIF(param->count == 0) {
972 		LOG_DBG("Invalid param->count: %u", param->count);
973 		return false;
974 	}
975 
976 	CHECKIF(param->members == NULL) {
977 		LOG_DBG("param->members is NULL");
978 		return false;
979 	}
980 
981 	CHECKIF(param->count > CONFIG_BT_MAX_CONN) {
982 		LOG_DBG("param->count (%zu) is larger than CONFIG_BT_MAX_CONN (%d)", param->count,
983 			CONFIG_BT_MAX_CONN);
984 		return false;
985 	}
986 
987 	for (size_t i = 0U; i < param->count; i++) {
988 		const union bt_cap_set_member *member = &param->members[i];
989 		const struct bt_conn *member_conn =
990 			bt_cap_common_get_member_conn(param->type, member);
991 
992 		if (member == NULL) {
993 			LOG_DBG("param->members[%zu] is NULL", i);
994 			return false;
995 		}
996 
997 		if (member_conn == NULL) {
998 			LOG_DBG("Invalid param->members[%zu]", i);
999 			return false;
1000 		}
1001 
1002 		if (bt_vcp_vol_ctlr_get_by_conn(member_conn) == NULL) {
1003 			LOG_DBG("Volume control not available for param->members[%zu]", i);
1004 			return false;
1005 		}
1006 
1007 		for (size_t j = 0U; j < i; j++) {
1008 			const union bt_cap_set_member *other = &param->members[j];
1009 
1010 			if (other == member) {
1011 				LOG_DBG("param->members[%zu] (%p) is duplicated by "
1012 					"param->members[%zu] (%p)",
1013 					j, other, i, member);
1014 				return false;
1015 			}
1016 		}
1017 	}
1018 
1019 	return true;
1020 }
1021 
cap_commander_vcp_vol_set_cb(struct bt_vcp_vol_ctlr * vol_ctlr,int err)1022 static void cap_commander_vcp_vol_set_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err)
1023 {
1024 	struct bt_cap_common_proc *active_proc = bt_cap_common_get_active_proc();
1025 	struct bt_conn *conn;
1026 	int vcp_err;
1027 
1028 	LOG_DBG("vol_ctlr %p", (void *)vol_ctlr);
1029 
1030 	vcp_err = bt_vcp_vol_ctlr_conn_get(vol_ctlr, &conn);
1031 	if (vcp_err != 0) {
1032 		LOG_ERR("Failed to get conn by vol_ctrl: %d", vcp_err);
1033 		return;
1034 	}
1035 
1036 	LOG_DBG("conn %p", (void *)conn);
1037 	if (!bt_cap_common_conn_in_active_proc(conn)) {
1038 		/* State change happened outside of a procedure; ignore */
1039 		return;
1040 	}
1041 
1042 	if (err != 0) {
1043 		LOG_DBG("Failed to set volume: %d", err);
1044 		bt_cap_common_abort_proc(conn, err);
1045 	} else {
1046 		active_proc->proc_done_cnt++;
1047 
1048 		LOG_DBG("Conn %p volume updated (%zu/%zu streams done)", (void *)conn,
1049 			active_proc->proc_done_cnt, active_proc->proc_cnt);
1050 	}
1051 
1052 	if (bt_cap_common_proc_is_aborted()) {
1053 		LOG_DBG("Proc is aborted");
1054 		if (bt_cap_common_proc_all_handled()) {
1055 			LOG_DBG("All handled");
1056 			cap_commander_proc_complete();
1057 		}
1058 
1059 		return;
1060 	}
1061 
1062 	if (!bt_cap_common_proc_is_done()) {
1063 		const struct bt_cap_commander_proc_param *proc_param;
1064 
1065 		proc_param = &active_proc->proc_param.commander[active_proc->proc_done_cnt];
1066 		conn = proc_param->conn;
1067 		active_proc->proc_initiated_cnt++;
1068 		err = bt_vcp_vol_ctlr_set_vol(bt_vcp_vol_ctlr_get_by_conn(conn),
1069 					      proc_param->change_volume.volume);
1070 		if (err != 0) {
1071 			LOG_DBG("Failed to set volume for conn %p: %d", (void *)conn, err);
1072 			bt_cap_common_abort_proc(conn, err);
1073 			cap_commander_proc_complete();
1074 		}
1075 	} else {
1076 		cap_commander_proc_complete();
1077 	}
1078 }
1079 
bt_cap_commander_change_volume(const struct bt_cap_commander_change_volume_param * param)1080 int bt_cap_commander_change_volume(const struct bt_cap_commander_change_volume_param *param)
1081 {
1082 	const struct bt_cap_commander_proc_param *proc_param;
1083 	struct bt_cap_common_proc *active_proc;
1084 	struct bt_conn *conn;
1085 	int err;
1086 
1087 	if (bt_cap_common_proc_is_active()) {
1088 		LOG_DBG("A CAP procedure is already in progress");
1089 
1090 		return -EBUSY;
1091 	}
1092 
1093 	if (!valid_change_volume_param(param)) {
1094 		return -EINVAL;
1095 	}
1096 
1097 	bt_cap_common_start_proc(BT_CAP_COMMON_PROC_TYPE_VOLUME_CHANGE, param->count);
1098 
1099 	vol_ctlr_cb.vol_set = cap_commander_vcp_vol_set_cb;
1100 	if (!vcp_cb_registered && cap_commander_register_vcp_cb() != 0) {
1101 		LOG_DBG("Failed to register VCP callbacks");
1102 
1103 		return -ENOEXEC;
1104 	}
1105 
1106 	active_proc = bt_cap_common_get_active_proc();
1107 
1108 	for (size_t i = 0U; i < param->count; i++) {
1109 		struct bt_conn *member_conn =
1110 			bt_cap_common_get_member_conn(param->type, &param->members[i]);
1111 
1112 		if (member_conn == NULL) {
1113 			LOG_DBG("Invalid param->members[%zu]", i);
1114 			return -EINVAL;
1115 		}
1116 
1117 		/* Store the necessary parameters as we cannot assume that the supplied parameters
1118 		 * are kept valid
1119 		 */
1120 		active_proc->proc_param.commander[i].conn = member_conn;
1121 		active_proc->proc_param.commander[i].change_volume.volume = param->volume;
1122 	}
1123 
1124 	proc_param = &active_proc->proc_param.commander[0];
1125 	conn = proc_param->conn;
1126 	active_proc->proc_initiated_cnt++;
1127 	err = bt_vcp_vol_ctlr_set_vol(bt_vcp_vol_ctlr_get_by_conn(conn),
1128 				      proc_param->change_volume.volume);
1129 	if (err != 0) {
1130 		LOG_DBG("Failed to set volume for conn %p: %d", (void *)conn, err);
1131 		return -ENOEXEC;
1132 	}
1133 
1134 	return 0;
1135 }
1136 
valid_change_volume_mute_state_param(const struct bt_cap_commander_change_volume_mute_state_param * param)1137 static bool valid_change_volume_mute_state_param(
1138 	const struct bt_cap_commander_change_volume_mute_state_param *param)
1139 {
1140 	CHECKIF(param == NULL) {
1141 		LOG_DBG("param is NULL");
1142 		return false;
1143 	}
1144 
1145 	CHECKIF(param->count == 0) {
1146 		LOG_DBG("Invalid param->count: %u", param->count);
1147 		return false;
1148 	}
1149 
1150 	CHECKIF(param->members == NULL) {
1151 		LOG_DBG("param->members is NULL");
1152 		return false;
1153 	}
1154 
1155 	CHECKIF(param->count > CONFIG_BT_MAX_CONN) {
1156 		LOG_DBG("param->count (%zu) is larger than CONFIG_BT_MAX_CONN (%d)", param->count,
1157 			CONFIG_BT_MAX_CONN);
1158 		return false;
1159 	}
1160 
1161 	for (size_t i = 0U; i < param->count; i++) {
1162 		const union bt_cap_set_member *member = &param->members[i];
1163 		const struct bt_conn *member_conn =
1164 			bt_cap_common_get_member_conn(param->type, member);
1165 
1166 		if (member == NULL) {
1167 			LOG_DBG("param->members[%zu] is NULL", i);
1168 			return false;
1169 		}
1170 
1171 		if (member_conn == NULL) {
1172 			LOG_DBG("Invalid param->members[%zu]", i);
1173 			return false;
1174 		}
1175 
1176 		CHECKIF(bt_vcp_vol_ctlr_get_by_conn(member_conn) == NULL) {
1177 			LOG_DBG("Volume control not available for param->members[%zu]", i);
1178 			return false;
1179 		}
1180 
1181 		for (size_t j = 0U; j < i; j++) {
1182 			const union bt_cap_set_member *other = &param->members[j];
1183 
1184 			CHECKIF(other == member) {
1185 				LOG_DBG("param->members[%zu] (%p) is duplicated by "
1186 					"param->members[%zu] (%p)",
1187 					j, other, i, member);
1188 				return false;
1189 			}
1190 		}
1191 	}
1192 
1193 	return true;
1194 }
1195 
cap_commander_vcp_vol_mute_cb(struct bt_vcp_vol_ctlr * vol_ctlr,int err)1196 static void cap_commander_vcp_vol_mute_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err)
1197 {
1198 	struct bt_cap_common_proc *active_proc = bt_cap_common_get_active_proc();
1199 	struct bt_conn *conn;
1200 	int vcp_err;
1201 
1202 	LOG_DBG("vol_ctlr %p", (void *)vol_ctlr);
1203 
1204 	vcp_err = bt_vcp_vol_ctlr_conn_get(vol_ctlr, &conn);
1205 	if (vcp_err != 0) {
1206 		LOG_ERR("Failed to get conn by vol_ctrl: %d", vcp_err);
1207 		return;
1208 	}
1209 
1210 	LOG_DBG("conn %p", (void *)conn);
1211 	if (!bt_cap_common_conn_in_active_proc(conn)) {
1212 		/* State change happened outside of a procedure; ignore */
1213 		return;
1214 	}
1215 
1216 	if (err != 0) {
1217 		LOG_DBG("Failed to set volume: %d", err);
1218 		bt_cap_common_abort_proc(conn, err);
1219 	} else {
1220 		active_proc->proc_done_cnt++;
1221 
1222 		LOG_DBG("Conn %p volume updated (%zu/%zu streams done)", (void *)conn,
1223 			active_proc->proc_done_cnt, active_proc->proc_cnt);
1224 	}
1225 
1226 	if (bt_cap_common_proc_is_aborted()) {
1227 		LOG_DBG("Proc is aborted");
1228 		if (bt_cap_common_proc_all_handled()) {
1229 			LOG_DBG("All handled");
1230 			cap_commander_proc_complete();
1231 		}
1232 
1233 		return;
1234 	}
1235 
1236 	if (!bt_cap_common_proc_is_done()) {
1237 		const struct bt_cap_commander_proc_param *proc_param;
1238 
1239 		proc_param = &active_proc->proc_param.commander[active_proc->proc_done_cnt];
1240 		conn = proc_param->conn;
1241 		active_proc->proc_initiated_cnt++;
1242 		if (proc_param->change_vol_mute.mute) {
1243 			err = bt_vcp_vol_ctlr_mute(bt_vcp_vol_ctlr_get_by_conn(conn));
1244 		} else {
1245 			err = bt_vcp_vol_ctlr_unmute(bt_vcp_vol_ctlr_get_by_conn(conn));
1246 		}
1247 
1248 		if (err != 0) {
1249 			LOG_DBG("Failed to set volume for conn %p: %d", (void *)conn, err);
1250 			bt_cap_common_abort_proc(conn, err);
1251 			cap_commander_proc_complete();
1252 		}
1253 	} else {
1254 		cap_commander_proc_complete();
1255 	}
1256 }
1257 
bt_cap_commander_change_volume_mute_state(const struct bt_cap_commander_change_volume_mute_state_param * param)1258 int bt_cap_commander_change_volume_mute_state(
1259 	const struct bt_cap_commander_change_volume_mute_state_param *param)
1260 {
1261 	const struct bt_cap_commander_proc_param *proc_param;
1262 	struct bt_cap_common_proc *active_proc;
1263 	struct bt_conn *conn;
1264 	int err;
1265 
1266 	if (bt_cap_common_proc_is_active()) {
1267 		LOG_DBG("A CAP procedure is already in progress");
1268 
1269 		return -EBUSY;
1270 	}
1271 
1272 	if (!valid_change_volume_mute_state_param(param)) {
1273 		return -EINVAL;
1274 	}
1275 
1276 	bt_cap_common_start_proc(BT_CAP_COMMON_PROC_TYPE_VOLUME_MUTE_CHANGE, param->count);
1277 
1278 	vol_ctlr_cb.mute = cap_commander_vcp_vol_mute_cb;
1279 	vol_ctlr_cb.unmute = cap_commander_vcp_vol_mute_cb;
1280 	if (!vcp_cb_registered && cap_commander_register_vcp_cb() != 0) {
1281 		LOG_DBG("Failed to register VCP callbacks");
1282 
1283 		return -ENOEXEC;
1284 	}
1285 
1286 	active_proc = bt_cap_common_get_active_proc();
1287 
1288 	for (size_t i = 0U; i < param->count; i++) {
1289 		struct bt_conn *member_conn =
1290 			bt_cap_common_get_member_conn(param->type, &param->members[i]);
1291 
1292 		CHECKIF(member_conn == NULL) {
1293 			LOG_DBG("Invalid param->members[%zu]", i);
1294 			return -EINVAL;
1295 		}
1296 
1297 		/* Store the necessary parameters as we cannot assume that the supplied parameters
1298 		 * are kept valid
1299 		 */
1300 		active_proc->proc_param.commander[i].conn = member_conn;
1301 		active_proc->proc_param.commander[i].change_vol_mute.mute = param->mute;
1302 	}
1303 
1304 	proc_param = &active_proc->proc_param.commander[0];
1305 	conn = proc_param->conn;
1306 	active_proc->proc_initiated_cnt++;
1307 
1308 	if (proc_param->change_vol_mute.mute) {
1309 		err = bt_vcp_vol_ctlr_mute(bt_vcp_vol_ctlr_get_by_conn(conn));
1310 	} else {
1311 		err = bt_vcp_vol_ctlr_unmute(bt_vcp_vol_ctlr_get_by_conn(conn));
1312 	}
1313 
1314 	if (err != 0) {
1315 		LOG_DBG("Failed to set volume mute state for conn %p: %d", (void *)conn, err);
1316 		return -ENOEXEC;
1317 	}
1318 
1319 	return 0;
1320 }
1321 
1322 #if defined(CONFIG_BT_VCP_VOL_CTLR_VOCS)
1323 static bool
valid_change_offset_param(const struct bt_cap_commander_change_volume_offset_param * param)1324 valid_change_offset_param(const struct bt_cap_commander_change_volume_offset_param *param)
1325 {
1326 	CHECKIF(param == NULL) {
1327 		LOG_DBG("param is NULL");
1328 		return false;
1329 	}
1330 
1331 	CHECKIF(param->count == 0) {
1332 		LOG_DBG("Invalid param->count: %u", param->count);
1333 		return false;
1334 	}
1335 
1336 	CHECKIF(param->param == NULL) {
1337 		LOG_DBG("param->param is NULL");
1338 		return false;
1339 	}
1340 
1341 	CHECKIF(param->count > CONFIG_BT_MAX_CONN) {
1342 		LOG_DBG("param->count (%zu) is larger than CONFIG_BT_MAX_CONN (%d)", param->count,
1343 			CONFIG_BT_MAX_CONN);
1344 		return false;
1345 	}
1346 
1347 	for (size_t i = 0U; i < param->count; i++) {
1348 		const struct bt_cap_commander_change_volume_offset_member_param *member_param =
1349 			&param->param[i];
1350 		const union bt_cap_set_member *member = &member_param->member;
1351 		const struct bt_conn *member_conn =
1352 			bt_cap_common_get_member_conn(param->type, member);
1353 		struct bt_vcp_vol_ctlr *vol_ctlr;
1354 		struct bt_vcp_included included;
1355 		int err;
1356 
1357 		if (member == NULL) {
1358 			LOG_DBG("param->param[%zu].member is NULL", i);
1359 			return false;
1360 		}
1361 
1362 		if (member_conn == NULL) {
1363 			LOG_DBG("Invalid param->param[%zu].member", i);
1364 			return false;
1365 		}
1366 
1367 		vol_ctlr = bt_vcp_vol_ctlr_get_by_conn(member_conn);
1368 		if (vol_ctlr == NULL) {
1369 			LOG_DBG("Volume control not available for param->param[%zu].member", i);
1370 			return false;
1371 		}
1372 
1373 		err = bt_vcp_vol_ctlr_included_get(vol_ctlr, &included);
1374 		if (err != 0 || included.vocs_cnt == 0) {
1375 			LOG_DBG("Volume offset control not available for param->param[%zu].member",
1376 				i);
1377 			return -ENOEXEC;
1378 		}
1379 
1380 		if (!IN_RANGE(member_param->offset, BT_VOCS_MIN_OFFSET, BT_VOCS_MAX_OFFSET)) {
1381 			LOG_DBG("Invalid offset %d for param->param[%zu].offset",
1382 				member_param->offset, i);
1383 			return false;
1384 		}
1385 
1386 		for (size_t j = 0U; j < i; j++) {
1387 			const union bt_cap_set_member *other = &param->param[j].member;
1388 
1389 			if (other == member) {
1390 				LOG_DBG("param->param[%zu].member (%p) is duplicated by "
1391 					"param->param[%zu].member (%p)",
1392 					j, other, i, member);
1393 				return false;
1394 			}
1395 		}
1396 	}
1397 
1398 	return true;
1399 }
1400 
cap_commander_vcp_set_offset_cb(struct bt_vocs * inst,int err)1401 static void cap_commander_vcp_set_offset_cb(struct bt_vocs *inst, int err)
1402 {
1403 	struct bt_cap_common_proc *active_proc = bt_cap_common_get_active_proc();
1404 	struct bt_conn *conn;
1405 	int vocs_err;
1406 
1407 	LOG_DBG("bt_vocs %p", (void *)inst);
1408 
1409 	vocs_err = bt_vocs_client_conn_get(inst, &conn);
1410 	if (vocs_err != 0) {
1411 		LOG_ERR("Failed to get conn by inst: %d", vocs_err);
1412 		return;
1413 	}
1414 
1415 	LOG_DBG("conn %p", (void *)conn);
1416 	if (!bt_cap_common_conn_in_active_proc(conn)) {
1417 		/* State change happened outside of a procedure; ignore */
1418 		return;
1419 	}
1420 
1421 	if (err != 0) {
1422 		LOG_DBG("Failed to set offset: %d", err);
1423 		bt_cap_common_abort_proc(conn, err);
1424 	} else {
1425 		active_proc->proc_done_cnt++;
1426 
1427 		LOG_DBG("Conn %p offset updated (%zu/%zu streams done)", (void *)conn,
1428 			active_proc->proc_done_cnt, active_proc->proc_cnt);
1429 	}
1430 
1431 	if (bt_cap_common_proc_is_aborted()) {
1432 		LOG_DBG("Proc is aborted");
1433 		if (bt_cap_common_proc_all_handled()) {
1434 			LOG_DBG("All handled");
1435 			cap_commander_proc_complete();
1436 		}
1437 
1438 		return;
1439 	}
1440 
1441 	if (!bt_cap_common_proc_is_done()) {
1442 		const struct bt_cap_commander_proc_param *proc_param;
1443 
1444 		proc_param = &active_proc->proc_param.commander[active_proc->proc_done_cnt];
1445 		conn = proc_param->conn;
1446 		active_proc->proc_initiated_cnt++;
1447 
1448 		err = bt_vocs_state_set(proc_param->change_offset.vocs,
1449 					proc_param->change_offset.offset);
1450 		if (err != 0) {
1451 			LOG_DBG("Failed to set offset for conn %p: %d", (void *)conn, err);
1452 			bt_cap_common_abort_proc(conn, err);
1453 			cap_commander_proc_complete();
1454 		}
1455 	} else {
1456 		cap_commander_proc_complete();
1457 	}
1458 }
1459 
bt_cap_commander_change_volume_offset(const struct bt_cap_commander_change_volume_offset_param * param)1460 int bt_cap_commander_change_volume_offset(
1461 	const struct bt_cap_commander_change_volume_offset_param *param)
1462 {
1463 	const struct bt_cap_commander_proc_param *proc_param;
1464 	struct bt_cap_common_proc *active_proc;
1465 	struct bt_vcp_vol_ctlr *vol_ctlr;
1466 	struct bt_conn *conn;
1467 	int err;
1468 
1469 	if (bt_cap_common_proc_is_active()) {
1470 		LOG_DBG("A CAP procedure is already in progress");
1471 
1472 		return -EBUSY;
1473 	}
1474 
1475 	if (!valid_change_offset_param(param)) {
1476 		return -EINVAL;
1477 	}
1478 
1479 	bt_cap_common_start_proc(BT_CAP_COMMON_PROC_TYPE_VOLUME_OFFSET_CHANGE, param->count);
1480 
1481 	vol_ctlr_cb.vocs_cb.set_offset = cap_commander_vcp_set_offset_cb;
1482 	if (!vcp_cb_registered && cap_commander_register_vcp_cb() != 0) {
1483 		LOG_DBG("Failed to register VCP callbacks");
1484 
1485 		return -ENOEXEC;
1486 	}
1487 
1488 	active_proc = bt_cap_common_get_active_proc();
1489 
1490 	for (size_t i = 0U; i < param->count; i++) {
1491 		const struct bt_cap_commander_change_volume_offset_member_param *member_param =
1492 			&param->param[i];
1493 		struct bt_conn *member_conn =
1494 			bt_cap_common_get_member_conn(param->type, &member_param->member);
1495 		struct bt_vcp_included included;
1496 
1497 		if (member_conn == NULL) {
1498 			LOG_DBG("Invalid param->members[%zu]", i);
1499 			return -EINVAL;
1500 		}
1501 
1502 		vol_ctlr = bt_vcp_vol_ctlr_get_by_conn(member_conn);
1503 		if (vol_ctlr == NULL) {
1504 			LOG_DBG("Invalid param->members[%zu] vol_ctlr", i);
1505 			return -EINVAL;
1506 		}
1507 
1508 		err = bt_vcp_vol_ctlr_included_get(vol_ctlr, &included);
1509 		if (err != 0 || included.vocs_cnt == 0) {
1510 			LOG_DBG("Invalid param->members[%zu] vocs", i);
1511 			return -EINVAL;
1512 		}
1513 
1514 		/* Store the necessary parameters as we cannot assume that the supplied parameters
1515 		 * are kept valid
1516 		 */
1517 		active_proc->proc_param.commander[i].conn = member_conn;
1518 		active_proc->proc_param.commander[i].change_offset.offset = member_param->offset;
1519 		/* TODO: For now we just use the first VOCS instance
1520 		 * - How should we handle multiple?
1521 		 */
1522 		active_proc->proc_param.commander[i].change_offset.vocs = included.vocs[0];
1523 	}
1524 
1525 	proc_param = &active_proc->proc_param.commander[0];
1526 	conn = proc_param->conn;
1527 	active_proc->proc_initiated_cnt++;
1528 
1529 	err = bt_vocs_state_set(proc_param->change_offset.vocs, proc_param->change_offset.offset);
1530 	if (err != 0) {
1531 		LOG_DBG("Failed to set volume for conn %p: %d", (void *)conn, err);
1532 		return -ENOEXEC;
1533 	}
1534 
1535 	return 0;
1536 }
1537 #endif /* CONFIG_BT_VCP_VOL_CTLR_VOCS */
1538 #endif /* CONFIG_BT_VCP_VOL_CTLR */
1539 
1540 #if defined(CONFIG_BT_MICP_MIC_CTLR)
1541 static struct bt_micp_mic_ctlr_cb mic_ctlr_cb;
1542 static bool micp_callbacks_registered;
1543 
cap_commander_register_micp_callbacks(void)1544 static int cap_commander_register_micp_callbacks(void)
1545 {
1546 	int err;
1547 
1548 	err = bt_micp_mic_ctlr_cb_register(&mic_ctlr_cb);
1549 	if (err != 0) {
1550 		LOG_DBG("Failed to register MICP callbacks: %d", err);
1551 
1552 		return -ENOEXEC;
1553 	}
1554 
1555 	micp_callbacks_registered = true;
1556 
1557 	return 0;
1558 }
1559 
valid_change_microphone_mute_state_param(const struct bt_cap_commander_change_microphone_mute_state_param * param)1560 static bool valid_change_microphone_mute_state_param(
1561 	const struct bt_cap_commander_change_microphone_mute_state_param *param)
1562 {
1563 	CHECKIF(param == NULL) {
1564 		LOG_DBG("param is NULL");
1565 		return false;
1566 	}
1567 
1568 	CHECKIF(param->count == 0) {
1569 		LOG_DBG("Invalid param->count: %u", param->count);
1570 		return false;
1571 	}
1572 
1573 	CHECKIF(param->members == NULL) {
1574 		LOG_DBG("param->members is NULL");
1575 		return false;
1576 	}
1577 
1578 	CHECKIF(param->count > CONFIG_BT_MAX_CONN) {
1579 		LOG_DBG("param->count (%zu) is larger than CONFIG_BT_MAX_CONN (%d)", param->count,
1580 			CONFIG_BT_MAX_CONN);
1581 		return false;
1582 	}
1583 
1584 	for (size_t i = 0U; i < param->count; i++) {
1585 		const union bt_cap_set_member *member = &param->members[i];
1586 		const struct bt_conn *member_conn =
1587 			bt_cap_common_get_member_conn(param->type, member);
1588 
1589 		if (member == NULL) {
1590 			LOG_DBG("param->members[%zu] is NULL", i);
1591 			return false;
1592 		}
1593 
1594 		if (member_conn == NULL) {
1595 			LOG_DBG("Invalid param->members[%zu]", i);
1596 			return false;
1597 		}
1598 
1599 		CHECKIF(bt_micp_mic_ctlr_get_by_conn(member_conn) == NULL) {
1600 			LOG_DBG("Microphone control not available for param->members[%zu]", i);
1601 			return false;
1602 		}
1603 
1604 		for (size_t j = 0U; j < i; j++) {
1605 			const union bt_cap_set_member *other = &param->members[j];
1606 
1607 			CHECKIF(other == member) {
1608 				LOG_DBG("param->members[%zu] (%p) is duplicated by "
1609 					"param->members[%zu] (%p)",
1610 					j, other, i, member);
1611 				return false;
1612 			}
1613 		}
1614 	}
1615 
1616 	return true;
1617 }
1618 
cap_commander_micp_mic_mute_cb(struct bt_micp_mic_ctlr * mic_ctlr,int err)1619 static void cap_commander_micp_mic_mute_cb(struct bt_micp_mic_ctlr *mic_ctlr, int err)
1620 {
1621 	struct bt_cap_common_proc *active_proc = bt_cap_common_get_active_proc();
1622 	struct bt_conn *conn;
1623 	int micp_err;
1624 
1625 	LOG_DBG("mic_ctlr %p", (void *)mic_ctlr);
1626 
1627 	micp_err = bt_micp_mic_ctlr_conn_get(mic_ctlr, &conn);
1628 	if (micp_err != 0) {
1629 		LOG_ERR("Failed to get conn by mic_ctlr: %d", micp_err);
1630 		return;
1631 	}
1632 
1633 	LOG_DBG("conn %p", (void *)conn);
1634 	if (!bt_cap_common_conn_in_active_proc(conn)) {
1635 		/* State change happened outside of a procedure; ignore */
1636 		return;
1637 	}
1638 
1639 	if (err != 0) {
1640 		LOG_DBG("Failed to change microphone mute: %d", err);
1641 		bt_cap_common_abort_proc(conn, err);
1642 	} else {
1643 		active_proc->proc_done_cnt++;
1644 
1645 		LOG_DBG("Conn %p mute updated (%zu/%zu streams done)", (void *)conn,
1646 			active_proc->proc_done_cnt, active_proc->proc_cnt);
1647 	}
1648 
1649 	if (bt_cap_common_proc_is_aborted()) {
1650 		LOG_DBG("Proc is aborted");
1651 		if (bt_cap_common_proc_all_handled()) {
1652 			LOG_DBG("All handled");
1653 			cap_commander_proc_complete();
1654 		}
1655 
1656 		return;
1657 	}
1658 
1659 	if (!bt_cap_common_proc_is_done()) {
1660 		const struct bt_cap_commander_proc_param *proc_param;
1661 
1662 		proc_param = &active_proc->proc_param.commander[active_proc->proc_done_cnt];
1663 		conn = proc_param->conn;
1664 		active_proc->proc_initiated_cnt++;
1665 		if (proc_param->change_mic_mute.mute) {
1666 			err = bt_micp_mic_ctlr_mute(bt_micp_mic_ctlr_get_by_conn(conn));
1667 		} else {
1668 			err = bt_micp_mic_ctlr_unmute(bt_micp_mic_ctlr_get_by_conn(conn));
1669 		}
1670 
1671 		if (err != 0) {
1672 			LOG_DBG("Failed to change mute for conn %p: %d", (void *)conn, err);
1673 			bt_cap_common_abort_proc(conn, err);
1674 			cap_commander_proc_complete();
1675 		}
1676 	} else {
1677 		cap_commander_proc_complete();
1678 	}
1679 }
1680 
bt_cap_commander_change_microphone_mute_state(const struct bt_cap_commander_change_microphone_mute_state_param * param)1681 int bt_cap_commander_change_microphone_mute_state(
1682 	const struct bt_cap_commander_change_microphone_mute_state_param *param)
1683 {
1684 	const struct bt_cap_commander_proc_param *proc_param;
1685 	struct bt_cap_common_proc *active_proc;
1686 	struct bt_conn *conn;
1687 	int err;
1688 
1689 	if (bt_cap_common_proc_is_active()) {
1690 		LOG_DBG("A CAP procedure is already in progress");
1691 
1692 		return -EBUSY;
1693 	}
1694 
1695 	if (!valid_change_microphone_mute_state_param(param)) {
1696 		return -EINVAL;
1697 	}
1698 
1699 	bt_cap_common_start_proc(BT_CAP_COMMON_PROC_TYPE_MICROPHONE_MUTE_CHANGE, param->count);
1700 
1701 	mic_ctlr_cb.mute_written = cap_commander_micp_mic_mute_cb;
1702 	mic_ctlr_cb.unmute_written = cap_commander_micp_mic_mute_cb;
1703 	if (!micp_callbacks_registered && cap_commander_register_micp_callbacks() != 0) {
1704 		LOG_DBG("Failed to register MICP callbacks");
1705 
1706 		return -ENOEXEC;
1707 	}
1708 
1709 	active_proc = bt_cap_common_get_active_proc();
1710 
1711 	for (size_t i = 0U; i < param->count; i++) {
1712 		struct bt_conn *member_conn =
1713 			bt_cap_common_get_member_conn(param->type, &param->members[i]);
1714 
1715 		CHECKIF(member_conn == NULL) {
1716 			LOG_DBG("Invalid param->members[%zu]", i);
1717 			return -EINVAL;
1718 		}
1719 
1720 		/* Store the necessary parameters as we cannot assume that the supplied parameters
1721 		 * are kept valid
1722 		 */
1723 		active_proc->proc_param.commander[i].conn = member_conn;
1724 		active_proc->proc_param.commander[i].change_mic_mute.mute = param->mute;
1725 	}
1726 
1727 	proc_param = &active_proc->proc_param.commander[0];
1728 	conn = proc_param->conn;
1729 	active_proc->proc_initiated_cnt++;
1730 
1731 	if (proc_param->change_mic_mute.mute) {
1732 		err = bt_micp_mic_ctlr_mute(bt_micp_mic_ctlr_get_by_conn(conn));
1733 	} else {
1734 		err = bt_micp_mic_ctlr_unmute(bt_micp_mic_ctlr_get_by_conn(conn));
1735 	}
1736 
1737 	if (err != 0) {
1738 		LOG_DBG("Failed to set microphone mute state for conn %p: %d", (void *)conn, err);
1739 		return -ENOEXEC;
1740 	}
1741 
1742 	return 0;
1743 }
1744 
1745 #if defined(CONFIG_BT_MICP_MIC_CTLR_AICS)
valid_change_microphone_gain_param(const struct bt_cap_commander_change_microphone_gain_setting_param * param)1746 static bool valid_change_microphone_gain_param(
1747 	const struct bt_cap_commander_change_microphone_gain_setting_param *param)
1748 {
1749 	CHECKIF(param == NULL) {
1750 		LOG_DBG("param is NULL");
1751 		return false;
1752 	}
1753 
1754 	CHECKIF(param->count == 0) {
1755 		LOG_DBG("Invalid param->count: %u", param->count);
1756 		return false;
1757 	}
1758 
1759 	CHECKIF(param->param == NULL) {
1760 		LOG_DBG("param->param is NULL");
1761 		return false;
1762 	}
1763 
1764 	CHECKIF(param->count > CONFIG_BT_MAX_CONN) {
1765 		LOG_DBG("param->count (%zu) is larger than CONFIG_BT_MAX_CONN (%d)", param->count,
1766 			CONFIG_BT_MAX_CONN);
1767 		return false;
1768 	}
1769 
1770 	for (size_t i = 0U; i < param->count; i++) {
1771 		const union bt_cap_set_member *member = &param->param[i].member;
1772 		const struct bt_conn *member_conn =
1773 			bt_cap_common_get_member_conn(param->type, member);
1774 		struct bt_micp_mic_ctlr *mic_ctlr;
1775 		struct bt_micp_included included;
1776 		int err;
1777 
1778 		if (member == NULL) {
1779 			LOG_DBG("param->param[%zu].member is NULL", i);
1780 			return false;
1781 		}
1782 
1783 		if (member_conn == NULL) {
1784 			LOG_DBG("Invalid param->param[%zu].member", i);
1785 			return false;
1786 		}
1787 
1788 		mic_ctlr = bt_micp_mic_ctlr_get_by_conn(member_conn);
1789 		if (mic_ctlr == NULL) {
1790 			LOG_DBG("Microphone control not available for param->param[%zu].member", i);
1791 			return false;
1792 		}
1793 
1794 		err = bt_micp_mic_ctlr_included_get(mic_ctlr, &included);
1795 		if (err != 0 || included.aics_cnt == 0) {
1796 			LOG_DBG("Microphone audio input control not available for "
1797 				"param->param[%zu].member",
1798 				i);
1799 			return -ENOEXEC;
1800 		}
1801 
1802 		for (size_t j = 0U; j < i; j++) {
1803 			const union bt_cap_set_member *other = &param->param[j].member;
1804 
1805 			if (other == member) {
1806 				LOG_DBG("param->param[%zu].member (%p) is duplicated by "
1807 					"param->param[%zu].member (%p)",
1808 					j, other, i, member);
1809 				return false;
1810 			}
1811 		}
1812 	}
1813 
1814 	return true;
1815 }
1816 
cap_commander_micp_gain_set_cb(struct bt_aics * inst,int err)1817 static void cap_commander_micp_gain_set_cb(struct bt_aics *inst, int err)
1818 {
1819 	struct bt_cap_common_proc *active_proc = bt_cap_common_get_active_proc();
1820 	struct bt_conn *conn;
1821 	int micp_err;
1822 
1823 	LOG_DBG("bt_aics %p", (void *)inst);
1824 
1825 	micp_err = bt_aics_client_conn_get(inst, &conn);
1826 	if (micp_err != 0) {
1827 		LOG_ERR("Failed to get conn by aics: %d", micp_err);
1828 		return;
1829 	}
1830 
1831 	LOG_DBG("conn %p", (void *)conn);
1832 	if (!bt_cap_common_conn_in_active_proc(conn)) {
1833 		/* State change happened outside of a procedure; ignore */
1834 		return;
1835 	}
1836 
1837 	if (err != 0) {
1838 		LOG_DBG("Failed to set gain: %d", err);
1839 		bt_cap_common_abort_proc(conn, err);
1840 	} else {
1841 		active_proc->proc_done_cnt++;
1842 
1843 		LOG_DBG("Conn %p gain updated (%zu/%zu streams done)", (void *)conn,
1844 			active_proc->proc_done_cnt, active_proc->proc_cnt);
1845 	}
1846 
1847 	if (bt_cap_common_proc_is_aborted()) {
1848 		LOG_DBG("Proc is aborted");
1849 		if (bt_cap_common_proc_all_handled()) {
1850 			LOG_DBG("All handled");
1851 			cap_commander_proc_complete();
1852 		}
1853 
1854 		return;
1855 	}
1856 
1857 	if (!bt_cap_common_proc_is_done()) {
1858 		const struct bt_cap_commander_proc_param *proc_param;
1859 
1860 		proc_param = &active_proc->proc_param.commander[active_proc->proc_done_cnt];
1861 		conn = proc_param->conn;
1862 		active_proc->proc_initiated_cnt++;
1863 		err = bt_aics_gain_set(proc_param->change_gain.aics, proc_param->change_gain.gain);
1864 		if (err != 0) {
1865 			LOG_DBG("Failed to set gain for conn %p: %d", (void *)conn, err);
1866 			bt_cap_common_abort_proc(conn, err);
1867 			cap_commander_proc_complete();
1868 		}
1869 	} else {
1870 		cap_commander_proc_complete();
1871 	}
1872 }
1873 
bt_cap_commander_change_microphone_gain_setting(const struct bt_cap_commander_change_microphone_gain_setting_param * param)1874 int bt_cap_commander_change_microphone_gain_setting(
1875 	const struct bt_cap_commander_change_microphone_gain_setting_param *param)
1876 {
1877 	const struct bt_cap_commander_proc_param *proc_param;
1878 	struct bt_cap_common_proc *active_proc;
1879 	struct bt_conn *conn;
1880 	int err;
1881 
1882 	if (bt_cap_common_proc_is_active()) {
1883 		LOG_DBG("A CAP procedure is already in progress");
1884 
1885 		return -EBUSY;
1886 	}
1887 
1888 	if (!valid_change_microphone_gain_param(param)) {
1889 		return -EINVAL;
1890 	}
1891 
1892 	bt_cap_common_start_proc(BT_CAP_COMMON_PROC_TYPE_MICROPHONE_GAIN_CHANGE, param->count);
1893 
1894 	mic_ctlr_cb.aics_cb.set_gain = cap_commander_micp_gain_set_cb;
1895 	if (!micp_callbacks_registered && cap_commander_register_micp_callbacks() != 0) {
1896 		LOG_DBG("Failed to register MICP callbacks");
1897 
1898 		return -ENOEXEC;
1899 	}
1900 
1901 	active_proc = bt_cap_common_get_active_proc();
1902 
1903 	for (size_t i = 0U; i < param->count; i++) {
1904 		const union bt_cap_set_member *member = &param->param[i].member;
1905 		struct bt_conn *member_conn = bt_cap_common_get_member_conn(param->type, member);
1906 		struct bt_micp_mic_ctlr *mic_ctlr;
1907 		struct bt_micp_included included;
1908 
1909 		if (member_conn == NULL) {
1910 			LOG_DBG("Invalid param->param[%zu].member", i);
1911 			return -EINVAL;
1912 		}
1913 
1914 		mic_ctlr = bt_micp_mic_ctlr_get_by_conn(member_conn);
1915 		if (mic_ctlr == NULL) {
1916 			LOG_DBG("Invalid param->param[%zu].member mic_ctlr", i);
1917 			return -EINVAL;
1918 		}
1919 
1920 		err = bt_micp_mic_ctlr_included_get(mic_ctlr, &included);
1921 		if (err != 0 || included.aics_cnt == 0) {
1922 			LOG_DBG("Invalid param->param[%zu].member aics", i);
1923 			return -EINVAL;
1924 		}
1925 
1926 		/* Store the necessary parameters as we cannot assume that the supplied parameters
1927 		 * are kept valid
1928 		 */
1929 		active_proc->proc_param.commander[i].conn = member_conn;
1930 		active_proc->proc_param.commander[i].change_gain.gain = param->param[i].gain;
1931 		/* TODO: For now we just use the first AICS instance
1932 		 * - How should we handle multiple?
1933 		 */
1934 		active_proc->proc_param.commander[i].change_gain.aics = included.aics[0];
1935 	}
1936 
1937 	proc_param = &active_proc->proc_param.commander[0];
1938 	conn = proc_param->conn;
1939 	active_proc->proc_initiated_cnt++;
1940 
1941 	err = bt_aics_gain_set(proc_param->change_gain.aics, proc_param->change_gain.gain);
1942 	if (err != 0) {
1943 		LOG_DBG("Failed to set gain for conn %p: %d", (void *)conn, err);
1944 		return -ENOEXEC;
1945 	}
1946 
1947 	return 0;
1948 }
1949 #endif /* CONFIG_BT_MICP_MIC_CTLR_AICS */
1950 #endif /* CONFIG_BT_MICP_MIC_CTLR */
1951