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