1 /*
2  * Copyright (c) 2023-2025 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <errno.h>
7 #include <stdbool.h>
8 #include <stddef.h>
9 #include <stdint.h>
10 #include <string.h>
11 
12 #include <zephyr/autoconf.h>
13 #include <zephyr/bluetooth/att.h>
14 #include <zephyr/bluetooth/audio/cap.h>
15 #include <zephyr/bluetooth/audio/csip.h>
16 #include <zephyr/bluetooth/bluetooth.h>
17 #include <zephyr/bluetooth/conn.h>
18 #include <zephyr/bluetooth/gatt.h>
19 #include <zephyr/bluetooth/uuid.h>
20 #include <zephyr/logging/log.h>
21 #include <zephyr/sys/atomic.h>
22 #include <zephyr/sys/check.h>
23 #include <zephyr/sys/util.h>
24 #include <zephyr/sys/util_macro.h>
25 
26 #include "cap_internal.h"
27 #include "csip_internal.h"
28 
29 LOG_MODULE_REGISTER(bt_cap_common, CONFIG_BT_CAP_COMMON_LOG_LEVEL);
30 
31 #include "common/bt_str.h"
32 
33 static struct bt_cap_common_client bt_cap_common_clients[CONFIG_BT_MAX_CONN];
34 static const struct bt_uuid *cas_uuid = BT_UUID_CAS;
35 static struct bt_cap_common_proc active_proc;
36 
bt_cap_common_get_active_proc(void)37 struct bt_cap_common_proc *bt_cap_common_get_active_proc(void)
38 {
39 	return &active_proc;
40 }
41 
bt_cap_common_clear_active_proc(void)42 void bt_cap_common_clear_active_proc(void)
43 {
44 	(void)memset(&active_proc, 0, sizeof(active_proc));
45 }
46 
bt_cap_common_set_proc(enum bt_cap_common_proc_type proc_type,size_t proc_cnt)47 void bt_cap_common_set_proc(enum bt_cap_common_proc_type proc_type, size_t proc_cnt)
48 {
49 	LOG_DBG("Setting proc to %d for %zu streams", proc_type, proc_cnt);
50 
51 	active_proc.proc_cnt = proc_cnt;
52 	active_proc.proc_type = proc_type;
53 	active_proc.proc_done_cnt = 0U;
54 	active_proc.proc_initiated_cnt = 0U;
55 }
56 
57 #if defined(CONFIG_BT_CAP_INITIATOR_UNICAST)
bt_cap_common_set_subproc(enum bt_cap_common_subproc_type subproc_type)58 void bt_cap_common_set_subproc(enum bt_cap_common_subproc_type subproc_type)
59 {
60 	LOG_DBG("Setting subproc to %d", subproc_type);
61 
62 	active_proc.proc_done_cnt = 0U;
63 	active_proc.proc_initiated_cnt = 0U;
64 	active_proc.subproc_type = subproc_type;
65 }
66 
bt_cap_common_proc_is_type(enum bt_cap_common_proc_type proc_type)67 bool bt_cap_common_proc_is_type(enum bt_cap_common_proc_type proc_type)
68 {
69 	return active_proc.proc_type == proc_type;
70 }
71 
bt_cap_common_subproc_is_type(enum bt_cap_common_subproc_type subproc_type)72 bool bt_cap_common_subproc_is_type(enum bt_cap_common_subproc_type subproc_type)
73 {
74 	return active_proc.subproc_type == subproc_type;
75 }
76 #endif /* CONFIG_BT_CAP_INITIATOR_UNICAST */
77 
78 #if defined(CONFIG_BT_CAP_HANDOVER)
bt_cap_common_set_handover_active(void)79 void bt_cap_common_set_handover_active(void)
80 {
81 	atomic_set_bit(active_proc.proc_state_flags, BT_CAP_COMMON_PROC_STATE_HANDOVER);
82 }
83 
bt_cap_common_handover_is_active(void)84 bool bt_cap_common_handover_is_active(void)
85 {
86 	return atomic_test_bit(active_proc.proc_state_flags, BT_CAP_COMMON_PROC_STATE_HANDOVER);
87 }
88 #endif /* CONFIG_BT_CAP_HANDOVER */
89 
bt_cap_common_get_member_conn(enum bt_cap_set_type type,const union bt_cap_set_member * member)90 struct bt_conn *bt_cap_common_get_member_conn(enum bt_cap_set_type type,
91 					      const union bt_cap_set_member *member)
92 {
93 	if (member == NULL) {
94 		return NULL;
95 	}
96 
97 	if (type == BT_CAP_SET_TYPE_CSIP) {
98 		struct bt_cap_common_client *client;
99 
100 		/* We have verified that `client` won't be NULL in
101 		 * `valid_change_volume_param`.
102 		 */
103 
104 		client = bt_cap_common_get_client_by_csis(member->csip);
105 		if (client == NULL) {
106 			return NULL;
107 		}
108 
109 		return client->conn;
110 	}
111 
112 	return member->member;
113 }
114 
bt_cap_common_test_and_set_proc_active(void)115 bool bt_cap_common_test_and_set_proc_active(void)
116 {
117 	return atomic_test_and_set_bit(active_proc.proc_state_flags,
118 				       BT_CAP_COMMON_PROC_STATE_ACTIVE);
119 }
120 
bt_cap_common_proc_is_active(void)121 bool bt_cap_common_proc_is_active(void)
122 {
123 	return atomic_test_bit(active_proc.proc_state_flags, BT_CAP_COMMON_PROC_STATE_ACTIVE);
124 }
125 
bt_cap_common_proc_is_aborted(void)126 bool bt_cap_common_proc_is_aborted(void)
127 {
128 	return atomic_test_bit(active_proc.proc_state_flags, BT_CAP_COMMON_PROC_STATE_ABORTED);
129 }
130 
bt_cap_common_proc_all_handled(void)131 bool bt_cap_common_proc_all_handled(void)
132 {
133 	return active_proc.proc_done_cnt == active_proc.proc_initiated_cnt;
134 }
135 
bt_cap_common_proc_is_done(void)136 bool bt_cap_common_proc_is_done(void)
137 {
138 	return active_proc.proc_done_cnt == active_proc.proc_cnt;
139 }
140 
bt_cap_common_abort_proc(struct bt_conn * conn,int err)141 void bt_cap_common_abort_proc(struct bt_conn *conn, int err)
142 {
143 	if (bt_cap_common_proc_is_aborted()) {
144 		/* no-op */
145 		return;
146 	}
147 
148 #if defined(CONFIG_BT_CAP_INITIATOR_UNICAST)
149 	LOG_DBG("Aborting proc %d with subproc %d for %p: %d", active_proc.proc_type,
150 		active_proc.subproc_type, (void *)conn, err);
151 #else  /* !CONFIG_BT_CAP_INITIATOR_UNICAST */
152 	LOG_DBG("Aborting proc %d for %p: %d", active_proc.proc_type, (void *)conn, err);
153 #endif /* CONFIG_BT_CAP_INITIATOR_UNICAST */
154 
155 	active_proc.err = err;
156 	active_proc.failed_conn = conn;
157 	atomic_set_bit(active_proc.proc_state_flags, BT_CAP_COMMON_PROC_STATE_ABORTED);
158 }
159 
160 #if defined(CONFIG_BT_CAP_INITIATOR_UNICAST)
active_proc_is_initiator(void)161 static bool active_proc_is_initiator(void)
162 {
163 	switch (active_proc.proc_type) {
164 	case BT_CAP_COMMON_PROC_TYPE_START:
165 	case BT_CAP_COMMON_PROC_TYPE_UPDATE:
166 	case BT_CAP_COMMON_PROC_TYPE_STOP:
167 		return true;
168 	default:
169 		return false;
170 	}
171 }
172 #endif /* CONFIG_BT_CAP_INITIATOR_UNICAST */
173 
174 #if defined(CONFIG_BT_CAP_COMMANDER)
active_proc_is_commander(void)175 static bool active_proc_is_commander(void)
176 {
177 	switch (active_proc.proc_type) {
178 	case BT_CAP_COMMON_PROC_TYPE_VOLUME_CHANGE:
179 	case BT_CAP_COMMON_PROC_TYPE_VOLUME_OFFSET_CHANGE:
180 	case BT_CAP_COMMON_PROC_TYPE_VOLUME_MUTE_CHANGE:
181 	case BT_CAP_COMMON_PROC_TYPE_MICROPHONE_GAIN_CHANGE:
182 	case BT_CAP_COMMON_PROC_TYPE_MICROPHONE_MUTE_CHANGE:
183 	case BT_CAP_COMMON_PROC_TYPE_BROADCAST_RECEPTION_START:
184 	case BT_CAP_COMMON_PROC_TYPE_BROADCAST_RECEPTION_STOP:
185 	case BT_CAP_COMMON_PROC_TYPE_DISTRIBUTE_BROADCAST_CODE:
186 		return true;
187 	default:
188 		return false;
189 	}
190 }
191 #endif /* CONFIG_BT_CAP_INITIATOR_UNICAST */
192 
bt_cap_common_conn_in_active_proc(const struct bt_conn * conn)193 bool bt_cap_common_conn_in_active_proc(const struct bt_conn *conn)
194 {
195 	if (!bt_cap_common_proc_is_active()) {
196 		return false;
197 	}
198 
199 	for (size_t i = 0U; i < active_proc.proc_initiated_cnt; i++) {
200 #if defined(CONFIG_BT_CAP_INITIATOR_UNICAST)
201 		if (active_proc_is_initiator()) {
202 			if (active_proc.proc_param.initiator[i].stream->bap_stream.conn == conn) {
203 				return true;
204 			}
205 		}
206 #endif /* CONFIG_BT_CAP_INITIATOR_UNICAST */
207 #if defined(CONFIG_BT_CAP_COMMANDER)
208 		if (active_proc_is_commander()) {
209 			if (active_proc.proc_param.commander[i].conn == conn) {
210 				return true;
211 			}
212 		}
213 #endif /* CONFIG_BT_CAP_COMMANDER */
214 	}
215 
216 	return false;
217 }
218 
bt_cap_common_stream_in_active_proc(const struct bt_cap_stream * cap_stream)219 bool bt_cap_common_stream_in_active_proc(const struct bt_cap_stream *cap_stream)
220 {
221 	if (!bt_cap_common_proc_is_active()) {
222 		return false;
223 	}
224 
225 #if defined(CONFIG_BT_CAP_INITIATOR_UNICAST)
226 	if (active_proc_is_initiator()) {
227 		for (size_t i = 0U; i < active_proc.proc_cnt; i++) {
228 			if (active_proc.proc_param.initiator[i].stream == cap_stream) {
229 				return true;
230 			}
231 		}
232 	}
233 #endif /* CONFIG_BT_CAP_INITIATOR_UNICAST */
234 
235 	return false;
236 }
237 
bt_cap_common_disconnected(struct bt_conn * conn,uint8_t reason)238 void bt_cap_common_disconnected(struct bt_conn *conn, uint8_t reason)
239 {
240 	struct bt_cap_common_client *client = bt_cap_common_get_client_by_acl(conn);
241 
242 	if (client->conn != NULL) {
243 		bt_conn_unref(client->conn);
244 	}
245 	(void)memset(client, 0, sizeof(*client));
246 
247 	if (bt_cap_common_conn_in_active_proc(conn)) {
248 		bt_cap_common_abort_proc(conn, -ENOTCONN);
249 	}
250 }
251 
252 BT_CONN_CB_DEFINE(conn_callbacks) = {
253 	.disconnected = bt_cap_common_disconnected,
254 };
255 
bt_cap_common_get_client_by_acl(const struct bt_conn * acl)256 struct bt_cap_common_client *bt_cap_common_get_client_by_acl(const struct bt_conn *acl)
257 {
258 	if (acl == NULL) {
259 		return NULL;
260 	}
261 
262 	return &bt_cap_common_clients[bt_conn_index(acl)];
263 }
264 
265 struct bt_cap_common_client *
bt_cap_common_get_client_by_csis(const struct bt_csip_set_coordinator_csis_inst * csis_inst)266 bt_cap_common_get_client_by_csis(const struct bt_csip_set_coordinator_csis_inst *csis_inst)
267 {
268 	if (csis_inst == NULL) {
269 		return NULL;
270 	}
271 
272 	for (size_t i = 0U; i < ARRAY_SIZE(bt_cap_common_clients); i++) {
273 		struct bt_cap_common_client *client = &bt_cap_common_clients[i];
274 
275 		if (client->csis_inst == csis_inst) {
276 			return client;
277 		}
278 	}
279 
280 	return NULL;
281 }
282 
cap_common_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)283 static void cap_common_discover_complete(struct bt_conn *conn, int err,
284 					 const struct bt_csip_set_coordinator_set_member *member,
285 					 const struct bt_csip_set_coordinator_csis_inst *csis_inst)
286 {
287 	struct bt_cap_common_client *client;
288 
289 	client = bt_cap_common_get_client_by_acl(conn);
290 	if (client != NULL && client->discover_cb_func != NULL) {
291 		const bt_cap_common_discover_func_t cb_func = client->discover_cb_func;
292 
293 		client->discover_cb_func = NULL;
294 		cb_func(conn, err, member, csis_inst);
295 	}
296 }
297 
csis_client_discover_cb(struct bt_conn * conn,const struct bt_csip_set_coordinator_set_member * member,int err,size_t set_count)298 static void csis_client_discover_cb(struct bt_conn *conn,
299 				    const struct bt_csip_set_coordinator_set_member *member,
300 				    int err, size_t set_count)
301 {
302 	struct bt_cap_common_client *client;
303 
304 	if (err != 0) {
305 		LOG_DBG("CSIS client discover failed: %d", err);
306 
307 		cap_common_discover_complete(conn, err, NULL, NULL);
308 
309 		return;
310 	}
311 
312 	client = bt_cap_common_get_client_by_acl(conn);
313 	client->csis_inst =
314 		bt_csip_set_coordinator_csis_inst_by_handle(conn, client->csis_start_handle);
315 
316 	if (member == NULL || set_count == 0 || client->csis_inst == NULL) {
317 		LOG_ERR("Unable to find CSIS for CAS");
318 
319 		cap_common_discover_complete(conn, -ENODATA, NULL, NULL);
320 	} else {
321 		LOG_DBG("Found CAS with CSIS");
322 		cap_common_discover_complete(conn, 0, member, client->csis_inst);
323 	}
324 }
325 
bt_cap_common_discover_included_cb(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * params)326 static uint8_t bt_cap_common_discover_included_cb(struct bt_conn *conn,
327 						  const struct bt_gatt_attr *attr,
328 						  struct bt_gatt_discover_params *params)
329 {
330 	if (attr == NULL) {
331 		LOG_DBG("CAS CSIS include not found");
332 
333 		cap_common_discover_complete(conn, 0, NULL, NULL);
334 	} else {
335 		const struct bt_gatt_include *included_service = attr->user_data;
336 		struct bt_cap_common_client *client =
337 			CONTAINER_OF(params, struct bt_cap_common_client, param);
338 
339 		/* If the remote CAS includes CSIS, we first check if we
340 		 * have already discovered it, and if so we can just retrieve it
341 		 * and forward it to the application. If not, then we start
342 		 * CSIS discovery
343 		 */
344 		client->csis_start_handle = included_service->start_handle;
345 		client->csis_inst = bt_csip_set_coordinator_csis_inst_by_handle(
346 			conn, client->csis_start_handle);
347 		if (client->csis_inst == NULL) {
348 			static struct bt_csip_set_coordinator_cb csis_client_cb = {
349 				.discover = csis_client_discover_cb,
350 			};
351 			static bool csis_cbs_registered;
352 			int err;
353 
354 			LOG_DBG("CAS CSIS not known, discovering");
355 
356 			if (!csis_cbs_registered) {
357 				bt_csip_set_coordinator_register_cb(&csis_client_cb);
358 				csis_cbs_registered = true;
359 			}
360 
361 			err = bt_csip_set_coordinator_discover(conn);
362 			if (err != 0) {
363 				LOG_DBG("Discover failed (err %d)", err);
364 				cap_common_discover_complete(conn, err, NULL, NULL);
365 			}
366 		} else {
367 			const struct bt_csip_set_coordinator_set_member *member =
368 				bt_csip_set_coordinator_set_member_by_conn(conn);
369 
370 			LOG_DBG("Found CAS with CSIS");
371 
372 			cap_common_discover_complete(conn, 0, member, client->csis_inst);
373 		}
374 	}
375 
376 	return BT_GATT_ITER_STOP;
377 }
378 
bt_cap_common_discover_cas_cb(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * params)379 static uint8_t bt_cap_common_discover_cas_cb(struct bt_conn *conn, const struct bt_gatt_attr *attr,
380 					     struct bt_gatt_discover_params *params)
381 {
382 	if (attr == NULL) {
383 		cap_common_discover_complete(conn, -ENODATA, NULL, NULL);
384 	} else {
385 		const struct bt_gatt_service_val *prim_service = attr->user_data;
386 		struct bt_cap_common_client *client =
387 			CONTAINER_OF(params, struct bt_cap_common_client, param);
388 		int err;
389 
390 		client->conn = bt_conn_ref(conn);
391 
392 		if (attr->handle == prim_service->end_handle) {
393 			LOG_DBG("Found CAS without CSIS");
394 			cap_common_discover_complete(conn, 0, NULL, NULL);
395 
396 			return BT_GATT_ITER_STOP;
397 		}
398 
399 		LOG_DBG("Found CAS, discovering included CSIS");
400 
401 		params->uuid = NULL;
402 		params->start_handle = attr->handle + 1;
403 		params->end_handle = prim_service->end_handle;
404 		params->type = BT_GATT_DISCOVER_INCLUDE;
405 		params->func = bt_cap_common_discover_included_cb;
406 
407 		err = bt_gatt_discover(conn, params);
408 		if (err != 0) {
409 			LOG_DBG("Discover failed (err %d)", err);
410 
411 			cap_common_discover_complete(conn, err, NULL, NULL);
412 		}
413 	}
414 
415 	return BT_GATT_ITER_STOP;
416 }
417 
bt_cap_common_discover(struct bt_conn * conn,bt_cap_common_discover_func_t func)418 int bt_cap_common_discover(struct bt_conn *conn, bt_cap_common_discover_func_t func)
419 {
420 	struct bt_gatt_discover_params *param;
421 	struct bt_cap_common_client *client;
422 	int err;
423 
424 	client = bt_cap_common_get_client_by_acl(conn);
425 	if (client->discover_cb_func != NULL) {
426 		return -EBUSY;
427 	}
428 
429 	param = &client->param;
430 	param->func = bt_cap_common_discover_cas_cb;
431 	param->uuid = cas_uuid;
432 	param->type = BT_GATT_DISCOVER_PRIMARY;
433 	param->start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
434 	param->end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
435 
436 	client->discover_cb_func = func;
437 
438 	err = bt_gatt_discover(conn, param);
439 	if (err != 0) {
440 		client->discover_cb_func = NULL;
441 
442 		/* Report expected possible errors */
443 		if (err == -ENOTCONN || err == -ENOMEM) {
444 			return err;
445 		}
446 
447 		LOG_DBG("Unexpected err %d from bt_gatt_discover", err);
448 		return -ENOEXEC;
449 	}
450 
451 	return 0;
452 }
453