1 /* Bluetooth Coordinated Set Identification Client
2  *
3  * Copyright (c) 2020 Bose Corporation
4  * Copyright (c) 2021-2024 Nordic Semiconductor ASA
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  *
8  * csip_set_coordinator should be used in the following way
9  *  1) Find and connect to a set device
10  *  2) Do discovery
11  *  3) read values (always SIRK, size, lock and rank if possible)
12  *  4) Discover other set members if applicable
13  *  5) Connect and bond with each set member
14  *  6) Do discovery of each member
15  *  7) Read rank for each set member
16  *  8) Lock all members based on rank if possible
17  *  9) Do whatever is needed during lock
18  * 10) Unlock all members
19  */
20 
21 #include <errno.h>
22 #include <stdbool.h>
23 #include <stddef.h>
24 #include <stdint.h>
25 #include <stdlib.h>
26 #include <string.h>
27 
28 #include <zephyr/autoconf.h>
29 #include <zephyr/bluetooth/att.h>
30 #include <zephyr/bluetooth/audio/csip.h>
31 #include <zephyr/bluetooth/bluetooth.h>
32 #include <zephyr/bluetooth/conn.h>
33 #include <zephyr/bluetooth/gap.h>
34 #include <zephyr/bluetooth/gatt.h>
35 #include <zephyr/bluetooth/buf.h>
36 #include <zephyr/bluetooth/uuid.h>
37 #include <zephyr/device.h>
38 #include <zephyr/init.h>
39 #include <zephyr/kernel.h>
40 #include <zephyr/logging/log.h>
41 #include <zephyr/sys/__assert.h>
42 #include <zephyr/sys/atomic.h>
43 #include <zephyr/sys/slist.h>
44 #include <zephyr/sys/util.h>
45 #include <zephyr/sys/util_macro.h>
46 #include <zephyr/types.h>
47 #include <zephyr/sys/check.h>
48 #include <zephyr/sys/byteorder.h>
49 
50 #include "csip_crypto.h"
51 #include "csip_internal.h"
52 #include "common/bt_str.h"
53 #include "host/conn_internal.h"
54 #include "host/keys.h"
55 #include "host/hci_core.h"
56 
57 LOG_MODULE_REGISTER(bt_csip_set_coordinator, CONFIG_BT_CSIP_SET_COORDINATOR_LOG_LEVEL);
58 
59 static struct active_members {
60 	struct bt_csip_set_coordinator_set_member *members[CONFIG_BT_MAX_CONN];
61 	struct bt_csip_set_coordinator_set_info info;
62 	uint8_t members_count;
63 	uint8_t members_handled;
64 	uint8_t members_restored;
65 	bool in_progress;
66 
67 	bt_csip_set_coordinator_ordered_access_t oap_cb;
68 } active;
69 
70 enum set_coordinator_flag {
71 	SET_COORDINATOR_FLAG_BUSY,
72 
73 	SET_COORDINATOR_FLAG_NUM_FLAGS, /* keep as last */
74 };
75 
76 struct bt_csip_set_coordinator_inst {
77 	uint8_t inst_count;
78 	uint8_t gatt_write_buf[1];
79 
80 	struct bt_csip_set_coordinator_svc_inst
81 		svc_insts[CONFIG_BT_CSIP_SET_COORDINATOR_MAX_CSIS_INSTANCES];
82 	struct bt_csip_set_coordinator_set_member set_member;
83 	struct bt_conn *conn;
84 	struct bt_csip_set_coordinator_svc_inst *cur_inst;
85 	struct bt_gatt_discover_params discover_params;
86 	struct bt_gatt_read_params read_params;
87 	struct bt_gatt_write_params write_params;
88 
89 	ATOMIC_DEFINE(flags, SET_COORDINATOR_FLAG_NUM_FLAGS);
90 };
91 
92 static struct bt_uuid_16 uuid = BT_UUID_INIT_16(0);
93 
94 static sys_slist_t csip_set_coordinator_cbs = SYS_SLIST_STATIC_INIT(&csip_set_coordinator_cbs);
95 static struct bt_csip_set_coordinator_inst client_insts[CONFIG_BT_MAX_CONN];
96 
97 static int read_sirk(struct bt_csip_set_coordinator_svc_inst *svc_inst);
98 static int csip_set_coordinator_read_set_size(struct bt_conn *conn,
99 					      uint8_t inst_idx,
100 					      bt_gatt_read_func_t cb);
101 static int csip_set_coordinator_read_set_lock(struct bt_csip_set_coordinator_svc_inst *svc_inst);
102 
103 static uint8_t csip_set_coordinator_discover_insts_read_sirk_cb(struct bt_conn *conn, uint8_t err,
104 								struct bt_gatt_read_params *params,
105 								const void *data, uint16_t length);
106 static void discover_insts_resume(struct bt_conn *conn, uint16_t sirk_handle,
107 				 uint16_t size_handle, uint16_t rank_handle);
108 
active_members_reset(void)109 static void active_members_reset(void)
110 {
111 	for (size_t i = 0U; i < active.members_count; i++) {
112 		const struct bt_csip_set_coordinator_set_member *member = active.members[i];
113 		struct bt_csip_set_coordinator_inst *client =
114 			CONTAINER_OF(member, struct bt_csip_set_coordinator_inst, set_member);
115 
116 		atomic_clear_bit(client->flags, SET_COORDINATOR_FLAG_BUSY);
117 	}
118 
119 	(void)memset(&active, 0, sizeof(active));
120 }
121 
lookup_instance_by_handle(struct bt_conn * conn,uint16_t handle)122 static struct bt_csip_set_coordinator_svc_inst *lookup_instance_by_handle(struct bt_conn *conn,
123 						 uint16_t handle)
124 {
125 	uint8_t conn_index;
126 	struct bt_csip_set_coordinator_inst *client;
127 
128 	__ASSERT(conn, "NULL conn");
129 	__ASSERT(handle > 0, "Handle cannot be 0");
130 
131 	conn_index = bt_conn_index(conn);
132 	client = &client_insts[conn_index];
133 
134 	for (int i = 0; i < ARRAY_SIZE(client->svc_insts); i++) {
135 		if (client->svc_insts[i].start_handle <= handle &&
136 		    client->svc_insts[i].end_handle >= handle) {
137 			return &client->svc_insts[i];
138 		}
139 	}
140 
141 	return NULL;
142 }
143 
bt_csip_set_coordinator_lookup_instance_by_index(const struct bt_conn * conn,uint8_t idx)144 struct bt_csip_set_coordinator_svc_inst *bt_csip_set_coordinator_lookup_instance_by_index
145 	(const struct bt_conn *conn, uint8_t idx)
146 {
147 	uint8_t conn_index;
148 	struct bt_csip_set_coordinator_inst *client;
149 
150 	__ASSERT(conn, "NULL conn");
151 	__ASSERT(idx < CONFIG_BT_CSIP_SET_COORDINATOR_MAX_CSIS_INSTANCES,
152 		 "Index shall be less than maximum number of instances %u (was %u)",
153 		 CONFIG_BT_CSIP_SET_COORDINATOR_MAX_CSIS_INSTANCES, idx);
154 
155 	conn_index = bt_conn_index(conn);
156 	client = &client_insts[conn_index];
157 	return &client->svc_insts[idx];
158 }
159 
lookup_instance_by_set_info(const struct bt_csip_set_coordinator_set_member * member,const struct bt_csip_set_coordinator_set_info * set_info)160 static struct bt_csip_set_coordinator_svc_inst *lookup_instance_by_set_info(
161 	const struct bt_csip_set_coordinator_set_member *member,
162 	const struct bt_csip_set_coordinator_set_info *set_info)
163 {
164 	struct bt_csip_set_coordinator_inst *inst =
165 		CONTAINER_OF(member, struct bt_csip_set_coordinator_inst, set_member);
166 
167 	for (int i = 0; i < ARRAY_SIZE(member->insts); i++) {
168 		const struct bt_csip_set_coordinator_set_info *member_set_info;
169 
170 		member_set_info = &member->insts[i].info;
171 		if (member_set_info->set_size == set_info->set_size &&
172 		    memcmp(member_set_info->sirk, set_info->sirk, sizeof(set_info->sirk)) == 0) {
173 			return bt_csip_set_coordinator_lookup_instance_by_index(inst->conn, i);
174 		}
175 	}
176 
177 	return NULL;
178 }
179 
get_next_active_instance(void)180 static struct bt_csip_set_coordinator_svc_inst *get_next_active_instance(void)
181 {
182 	struct bt_csip_set_coordinator_set_member *member;
183 	struct bt_csip_set_coordinator_svc_inst *svc_inst;
184 
185 	member = active.members[active.members_handled];
186 
187 	svc_inst = lookup_instance_by_set_info(member, &active.info);
188 	if (svc_inst == NULL) {
189 		LOG_DBG("Failed to lookup instance by set_info");
190 	}
191 
192 	return svc_inst;
193 }
194 
member_rank_compare_asc(const void * m1,const void * m2)195 static int member_rank_compare_asc(const void *m1, const void *m2)
196 {
197 	const struct bt_csip_set_coordinator_set_member *member_1 =
198 		*(const struct bt_csip_set_coordinator_set_member **)m1;
199 	const struct bt_csip_set_coordinator_set_member *member_2 =
200 		*(const struct bt_csip_set_coordinator_set_member **)m2;
201 	struct bt_csip_set_coordinator_svc_inst *svc_inst_1;
202 	struct bt_csip_set_coordinator_svc_inst *svc_inst_2;
203 
204 	svc_inst_1 = lookup_instance_by_set_info(member_1, &active.info);
205 	svc_inst_2 = lookup_instance_by_set_info(member_2, &active.info);
206 
207 	if (svc_inst_1 == NULL) {
208 		LOG_ERR("svc_inst_1 was NULL for member %p", member_1);
209 		return 0;
210 	}
211 
212 	if (svc_inst_2 == NULL) {
213 		LOG_ERR("svc_inst_2 was NULL for member %p", member_2);
214 		return 0;
215 	}
216 
217 	return svc_inst_1->set_info->rank - svc_inst_2->set_info->rank;
218 }
219 
member_rank_compare_desc(const void * m1,const void * m2)220 static int member_rank_compare_desc(const void *m1, const void *m2)
221 {
222 	/* If we call the "compare ascending" function with the members
223 	 * reversed, it will work as a descending comparison
224 	 */
225 	return member_rank_compare_asc(m2, m1);
226 }
227 
active_members_store_ordered(const struct bt_csip_set_coordinator_set_member * members[],size_t count,const struct bt_csip_set_coordinator_set_info * info,bool ascending)228 static void active_members_store_ordered(const struct bt_csip_set_coordinator_set_member *members[],
229 					 size_t count,
230 					 const struct bt_csip_set_coordinator_set_info *info,
231 					 bool ascending)
232 {
233 	(void)memcpy(active.members, members, count * sizeof(members[0U]));
234 	active.members_count = count;
235 	memcpy(&active.info, info, sizeof(active.info));
236 
237 	if (count > 1U && CONFIG_BT_MAX_CONN > 1) {
238 		qsort(active.members, count, sizeof(members[0U]),
239 		ascending ? member_rank_compare_asc : member_rank_compare_desc);
240 
241 #if defined(CONFIG_ASSERT)
242 		for (size_t i = 1U; i < count; i++) {
243 			const struct bt_csip_set_coordinator_svc_inst *svc_inst_1 =
244 				lookup_instance_by_set_info(active.members[i - 1U], info);
245 			const struct bt_csip_set_coordinator_svc_inst *svc_inst_2 =
246 				lookup_instance_by_set_info(active.members[i], info);
247 			const uint8_t rank_1 = svc_inst_1->set_info->rank;
248 			const uint8_t rank_2 = svc_inst_2->set_info->rank;
249 
250 			if (ascending) {
251 				__ASSERT(rank_1 <= rank_2,
252 					 "Members not sorted by ascending rank %u - %u", rank_1,
253 					 rank_2);
254 			} else {
255 				__ASSERT(rank_1 >= rank_2,
256 					 "Members not sorted by descending rank %u - %u", rank_1,
257 					 rank_2);
258 			}
259 		}
260 #endif /* CONFIG_ASSERT */
261 	}
262 }
263 
sirk_decrypt(struct bt_conn * conn,const uint8_t * enc_sirk,uint8_t * out_sirk)264 static int sirk_decrypt(struct bt_conn *conn,
265 			const uint8_t *enc_sirk,
266 			uint8_t *out_sirk)
267 {
268 	int err;
269 	uint8_t *k;
270 
271 	if (IS_ENABLED(CONFIG_BT_CSIP_SET_COORDINATOR_TEST_SAMPLE_DATA)) {
272 		/* test_k is from the sample data from A.2 in the CSIS spec */
273 		static uint8_t test_k[] = {0x67, 0x6e, 0x1b, 0x9b,
274 					   0xd4, 0x48, 0x69, 0x6f,
275 					   0x06, 0x1e, 0xc6, 0x22,
276 					   0x3c, 0xe5, 0xce, 0xd9};
277 		static bool swapped;
278 
279 		LOG_DBG("Decrypting with sample data K");
280 
281 		if (!swapped && IS_ENABLED(CONFIG_LITTLE_ENDIAN)) {
282 			/* Swap test_k to little endian */
283 			sys_mem_swap(test_k, 16);
284 			swapped = true;
285 		}
286 		k = test_k;
287 	} else {
288 		k = conn->le.keys->ltk.val;
289 	}
290 
291 	err = bt_csip_sdf(k, enc_sirk, out_sirk);
292 
293 	return err;
294 }
295 
lock_changed(struct bt_csip_set_coordinator_csis_inst * inst,bool locked)296 static void lock_changed(struct bt_csip_set_coordinator_csis_inst *inst, bool locked)
297 {
298 	struct bt_csip_set_coordinator_cb *listener;
299 
300 	active_members_reset();
301 
302 	SYS_SLIST_FOR_EACH_CONTAINER(&csip_set_coordinator_cbs, listener, _node) {
303 		if (listener->lock_changed) {
304 			listener->lock_changed(inst, locked);
305 		}
306 	}
307 }
308 
sirk_changed(struct bt_csip_set_coordinator_csis_inst * inst)309 static void sirk_changed(struct bt_csip_set_coordinator_csis_inst *inst)
310 {
311 	struct bt_csip_set_coordinator_cb *listener;
312 
313 	SYS_SLIST_FOR_EACH_CONTAINER(&csip_set_coordinator_cbs, listener, _node) {
314 		if (listener->sirk_changed) {
315 			listener->sirk_changed(inst);
316 		}
317 	}
318 }
319 
release_set_complete(int err)320 static void release_set_complete(int err)
321 {
322 	struct bt_csip_set_coordinator_cb *listener;
323 
324 	active_members_reset();
325 
326 	SYS_SLIST_FOR_EACH_CONTAINER(&csip_set_coordinator_cbs, listener, _node) {
327 		if (listener->release_set) {
328 			listener->release_set(err);
329 		}
330 	}
331 }
332 
lock_set_complete(int err)333 static void lock_set_complete(int err)
334 {
335 	struct bt_csip_set_coordinator_cb *listener;
336 
337 	active_members_reset();
338 
339 	SYS_SLIST_FOR_EACH_CONTAINER(&csip_set_coordinator_cbs, listener, _node) {
340 		if (listener->lock_set) {
341 			listener->lock_set(err);
342 		}
343 	}
344 }
345 
ordered_access_complete(const struct bt_csip_set_coordinator_set_info * set_info,int err,bool locked,struct bt_csip_set_coordinator_set_member * member)346 static void ordered_access_complete(const struct bt_csip_set_coordinator_set_info *set_info,
347 				    int err, bool locked,
348 				    struct bt_csip_set_coordinator_set_member *member)
349 {
350 
351 	struct bt_csip_set_coordinator_cb *listener;
352 
353 	active_members_reset();
354 
355 	SYS_SLIST_FOR_EACH_CONTAINER(&csip_set_coordinator_cbs, listener, _node) {
356 		if (listener->ordered_access) {
357 			listener->ordered_access(set_info, err, locked, member);
358 		}
359 	}
360 }
361 
discover_complete(struct bt_csip_set_coordinator_inst * client,int err)362 static void discover_complete(struct bt_csip_set_coordinator_inst *client,
363 			      int err)
364 {
365 	struct bt_csip_set_coordinator_cb *listener;
366 
367 	client->cur_inst = NULL;
368 	atomic_clear_bit(client->flags, SET_COORDINATOR_FLAG_BUSY);
369 
370 	SYS_SLIST_FOR_EACH_CONTAINER(&csip_set_coordinator_cbs, listener, _node) {
371 		if (listener->discover) {
372 			if (err == 0) {
373 				listener->discover(client->conn,
374 						   &client->set_member,
375 						   err, client->inst_count);
376 			} else {
377 				listener->discover(client->conn, NULL, err, 0U);
378 			}
379 		}
380 	}
381 }
382 
sirk_notify_func(struct bt_conn * conn,struct bt_gatt_subscribe_params * params,const void * data,uint16_t length)383 static uint8_t sirk_notify_func(struct bt_conn *conn,
384 				struct bt_gatt_subscribe_params *params,
385 				const void *data, uint16_t length)
386 {
387 	uint16_t handle = params->value_handle;
388 	struct bt_csip_set_coordinator_svc_inst *svc_inst;
389 
390 	if (data == NULL) {
391 		LOG_DBG("[UNSUBSCRIBED] %u", params->value_handle);
392 		params->value_handle = 0U;
393 
394 		return BT_GATT_ITER_STOP;
395 	}
396 
397 	if (conn == NULL) {
398 		return BT_GATT_ITER_CONTINUE;
399 	}
400 
401 	svc_inst = lookup_instance_by_handle(conn, handle);
402 
403 	if (svc_inst != NULL) {
404 		LOG_DBG("Instance %u", svc_inst->idx);
405 		if (length == sizeof(struct bt_csip_sirk)) {
406 			struct bt_csip_sirk *sirk = (struct bt_csip_sirk *)data;
407 			struct bt_csip_set_coordinator_inst *client;
408 			struct bt_csip_set_coordinator_csis_inst *inst;
409 			uint8_t *dst_sirk;
410 
411 			client = &client_insts[bt_conn_index(conn)];
412 			inst = &client->set_member.insts[svc_inst->idx];
413 			dst_sirk = inst->info.sirk;
414 
415 			LOG_DBG("SIRK %sencrypted",
416 				sirk->type == BT_CSIP_SIRK_TYPE_PLAIN ? "not " : "");
417 
418 			/* Assuming not connected to other set devices */
419 			if (sirk->type == BT_CSIP_SIRK_TYPE_ENCRYPTED) {
420 				if (IS_ENABLED(CONFIG_BT_CSIP_SET_COORDINATOR_ENC_SIRK_SUPPORT)) {
421 					int err;
422 
423 					LOG_HEXDUMP_DBG(sirk->value, sizeof(*sirk),
424 							"Encrypted SIRK");
425 					err = sirk_decrypt(conn, sirk->value,
426 							   dst_sirk);
427 					if (err != 0) {
428 						LOG_ERR("Could not decrypt "
429 							"SIRK %d",
430 							err);
431 					}
432 				} else {
433 					LOG_DBG("Encrypted SIRK not supported");
434 					return BT_GATT_ITER_CONTINUE;
435 				}
436 			} else {
437 				(void)memcpy(dst_sirk, sirk->value, sizeof(sirk->value));
438 			}
439 
440 			LOG_HEXDUMP_DBG(dst_sirk, BT_CSIP_SIRK_SIZE, "SIRK");
441 
442 			sirk_changed(inst);
443 		} else {
444 			LOG_DBG("Invalid length %u", length);
445 		}
446 	} else {
447 		LOG_DBG("Notification/Indication on unknown service inst");
448 	}
449 
450 	return BT_GATT_ITER_CONTINUE;
451 }
452 
size_notify_func(struct bt_conn * conn,struct bt_gatt_subscribe_params * params,const void * data,uint16_t length)453 static uint8_t size_notify_func(struct bt_conn *conn,
454 				struct bt_gatt_subscribe_params *params,
455 				const void *data, uint16_t length)
456 {
457 	uint8_t set_size;
458 	uint16_t handle = params->value_handle;
459 	struct bt_csip_set_coordinator_svc_inst *svc_inst;
460 
461 	if (data == NULL) {
462 		LOG_DBG("[UNSUBSCRIBED] %u", params->value_handle);
463 		params->value_handle = 0U;
464 
465 		return BT_GATT_ITER_STOP;
466 	}
467 
468 	if (conn == NULL) {
469 		return BT_GATT_ITER_CONTINUE;
470 	}
471 
472 	svc_inst = lookup_instance_by_handle(conn, handle);
473 
474 	if (svc_inst != NULL) {
475 		if (length == sizeof(set_size)) {
476 			struct bt_csip_set_coordinator_inst *client;
477 			struct bt_csip_set_coordinator_set_info *set_info;
478 
479 			client = &client_insts[bt_conn_index(conn)];
480 			set_info = &client->set_member.insts[svc_inst->idx].info;
481 
482 			(void)memcpy(&set_size, data, length);
483 			LOG_DBG("Set size updated from %u to %u", set_info->set_size, set_size);
484 
485 			set_info->set_size = set_size;
486 			/* TODO: Notify app */
487 		} else {
488 			LOG_DBG("Invalid length %u", length);
489 		}
490 
491 	} else {
492 		LOG_DBG("Notification/Indication on unknown service inst");
493 	}
494 	LOG_HEXDUMP_DBG(data, length, "Value");
495 
496 	return BT_GATT_ITER_CONTINUE;
497 }
498 
lock_notify_func(struct bt_conn * conn,struct bt_gatt_subscribe_params * params,const void * data,uint16_t length)499 static uint8_t lock_notify_func(struct bt_conn *conn,
500 				struct bt_gatt_subscribe_params *params,
501 				const void *data, uint16_t length)
502 {
503 	uint8_t value;
504 	uint16_t handle = params->value_handle;
505 	struct bt_csip_set_coordinator_svc_inst *svc_inst;
506 
507 	if (data == NULL) {
508 		LOG_DBG("[UNSUBSCRIBED] %u", params->value_handle);
509 		params->value_handle = 0U;
510 
511 		return BT_GATT_ITER_STOP;
512 	}
513 
514 	if (conn == NULL) {
515 		return BT_GATT_ITER_CONTINUE;
516 	}
517 
518 	svc_inst = lookup_instance_by_handle(conn, handle);
519 
520 	if (svc_inst != NULL) {
521 		if (length == sizeof(svc_inst->set_lock)) {
522 			struct bt_csip_set_coordinator_inst *client;
523 			struct bt_csip_set_coordinator_csis_inst *inst;
524 			bool locked;
525 
526 			(void)memcpy(&value, data, length);
527 			if (value != BT_CSIP_RELEASE_VALUE &&
528 			    value != BT_CSIP_LOCK_VALUE) {
529 				LOG_DBG("Invalid value %u", value);
530 				return BT_GATT_ITER_STOP;
531 			}
532 
533 			(void)memcpy(&svc_inst->set_lock, data, length);
534 
535 			locked = svc_inst->set_lock == BT_CSIP_LOCK_VALUE;
536 			LOG_DBG("Instance %u lock was %s", svc_inst->idx,
537 				locked ? "locked" : "released");
538 
539 			client = &client_insts[bt_conn_index(conn)];
540 			inst = &client->set_member.insts[svc_inst->idx];
541 
542 			lock_changed(inst, locked);
543 		} else {
544 			LOG_DBG("Invalid length %u", length);
545 		}
546 	} else {
547 		LOG_DBG("Notification/Indication on unknown service inst");
548 	}
549 	LOG_HEXDUMP_DBG(data, length, "Value");
550 
551 	return BT_GATT_ITER_CONTINUE;
552 }
553 
csip_set_coordinator_write_set_lock(struct bt_csip_set_coordinator_svc_inst * inst,bool lock,bt_gatt_write_func_t cb)554 static int csip_set_coordinator_write_set_lock(struct bt_csip_set_coordinator_svc_inst *inst,
555 					       bool lock,
556 					       bt_gatt_write_func_t cb)
557 {
558 	struct bt_csip_set_coordinator_inst *client = &client_insts[bt_conn_index(inst->conn)];
559 
560 	if (inst->set_lock_handle == 0) {
561 		LOG_DBG("Handle not set");
562 		client->cur_inst = NULL;
563 		return -EINVAL;
564 	}
565 
566 	/* Write to call control point */
567 	client->gatt_write_buf[0] = lock ? BT_CSIP_LOCK_VALUE : BT_CSIP_RELEASE_VALUE;
568 	client->write_params.data = client->gatt_write_buf;
569 	client->write_params.length = sizeof(lock);
570 	client->write_params.func = cb;
571 	client->write_params.handle = inst->set_lock_handle;
572 
573 	return bt_gatt_write(inst->conn, &client->write_params);
574 }
575 
read_sirk(struct bt_csip_set_coordinator_svc_inst * svc_inst)576 static int read_sirk(struct bt_csip_set_coordinator_svc_inst *svc_inst)
577 {
578 	struct bt_csip_set_coordinator_inst *client = &client_insts[bt_conn_index(svc_inst->conn)];
579 
580 	if (client->cur_inst != NULL) {
581 		if (client->cur_inst != svc_inst) {
582 			return -EBUSY;
583 		}
584 	} else {
585 		client->cur_inst = svc_inst;
586 	}
587 
588 	if (svc_inst->sirk_handle == 0) {
589 		LOG_DBG("Handle not set");
590 		return -EINVAL;
591 	}
592 
593 	client->read_params.func = csip_set_coordinator_discover_insts_read_sirk_cb;
594 	client->read_params.handle_count = 1;
595 	client->read_params.single.handle = svc_inst->sirk_handle;
596 	client->read_params.single.offset = 0U;
597 
598 	return bt_gatt_read(svc_inst->conn, &client->read_params);
599 }
600 
csip_set_coordinator_read_set_size(struct bt_conn * conn,uint8_t inst_idx,bt_gatt_read_func_t cb)601 static int csip_set_coordinator_read_set_size(struct bt_conn *conn,
602 					      uint8_t inst_idx,
603 					      bt_gatt_read_func_t cb)
604 {
605 	struct bt_csip_set_coordinator_inst *client = &client_insts[bt_conn_index(conn)];
606 
607 	if (inst_idx >= CONFIG_BT_CSIP_SET_COORDINATOR_MAX_CSIS_INSTANCES) {
608 		return -EINVAL;
609 	} else if (client->cur_inst != NULL) {
610 		if (client->cur_inst !=
611 		    bt_csip_set_coordinator_lookup_instance_by_index(conn, inst_idx)) {
612 			return -EBUSY;
613 		}
614 	} else {
615 		client->cur_inst = bt_csip_set_coordinator_lookup_instance_by_index(conn, inst_idx);
616 		if (client->cur_inst == NULL) {
617 			LOG_DBG("Inst not found");
618 			return -EINVAL;
619 		}
620 	}
621 
622 	if (client->cur_inst->set_size_handle == 0) {
623 		LOG_DBG("Handle not set");
624 		client->cur_inst = NULL;
625 		return -EINVAL;
626 	}
627 
628 	client->read_params.func = cb;
629 	client->read_params.handle_count = 1;
630 	client->read_params.single.handle = client->cur_inst->set_size_handle;
631 	client->read_params.single.offset = 0U;
632 
633 	return bt_gatt_read(conn, &client->read_params);
634 }
635 
csip_set_coordinator_read_rank(struct bt_conn * conn,uint8_t inst_idx,bt_gatt_read_func_t cb)636 static int csip_set_coordinator_read_rank(struct bt_conn *conn,
637 					  uint8_t inst_idx,
638 					  bt_gatt_read_func_t cb)
639 {
640 	struct bt_csip_set_coordinator_inst *client = &client_insts[bt_conn_index(conn)];
641 
642 	if (inst_idx >= CONFIG_BT_CSIP_SET_COORDINATOR_MAX_CSIS_INSTANCES) {
643 		return -EINVAL;
644 	} else if (client->cur_inst != NULL) {
645 		if (client->cur_inst !=
646 		    bt_csip_set_coordinator_lookup_instance_by_index(conn, inst_idx)) {
647 			return -EBUSY;
648 		}
649 	} else {
650 		client->cur_inst = bt_csip_set_coordinator_lookup_instance_by_index(conn, inst_idx);
651 		if (client->cur_inst == NULL) {
652 			LOG_DBG("Inst not found");
653 			return -EINVAL;
654 		}
655 	}
656 
657 	if (client->cur_inst->rank_handle == 0) {
658 		LOG_DBG("Handle not set");
659 		client->cur_inst = NULL;
660 		return -EINVAL;
661 	}
662 
663 	client->read_params.func = cb;
664 	client->read_params.handle_count = 1;
665 	client->read_params.single.handle = client->cur_inst->rank_handle;
666 	client->read_params.single.offset = 0U;
667 
668 	return bt_gatt_read(conn, &client->read_params);
669 }
670 
csip_set_coordinator_discover_sets(struct bt_csip_set_coordinator_inst * client)671 static int csip_set_coordinator_discover_sets(struct bt_csip_set_coordinator_inst *client)
672 {
673 	struct bt_csip_set_coordinator_set_member *member = &client->set_member;
674 
675 	/* Start reading values and call CB when done */
676 	return read_sirk((struct bt_csip_set_coordinator_svc_inst *)member->insts[0].svc_inst);
677 }
678 
discover_func(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * params)679 static uint8_t discover_func(struct bt_conn *conn,
680 			     const struct bt_gatt_attr *attr,
681 			     struct bt_gatt_discover_params *params)
682 {
683 	struct bt_gatt_chrc *chrc;
684 	struct bt_csip_set_coordinator_inst *client = &client_insts[bt_conn_index(conn)];
685 	struct bt_gatt_subscribe_params *sub_params = NULL;
686 	void *notify_handler = NULL;
687 
688 	if (attr == NULL) {
689 		LOG_DBG("Setup complete for %u / %u", client->cur_inst->idx + 1,
690 			client->inst_count);
691 		(void)memset(params, 0, sizeof(*params));
692 
693 		if (CONFIG_BT_CSIP_SET_COORDINATOR_MAX_CSIS_INSTANCES > 1 &&
694 		    (client->cur_inst->idx + 1) < client->inst_count) {
695 			int err;
696 
697 			client->cur_inst = &client->svc_insts[client->cur_inst->idx + 1];
698 			client->discover_params.uuid = NULL;
699 			client->discover_params.start_handle = client->cur_inst->start_handle;
700 			client->discover_params.end_handle = client->cur_inst->end_handle;
701 			client->discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
702 			client->discover_params.func = discover_func;
703 
704 			err = bt_gatt_discover(conn, &client->discover_params);
705 			if (err != 0) {
706 				LOG_DBG("Discover failed (err %d)", err);
707 				discover_complete(client, err);
708 			}
709 
710 		} else {
711 			int err;
712 
713 			client->cur_inst = NULL;
714 			err = csip_set_coordinator_discover_sets(client);
715 			if (err != 0) {
716 				LOG_DBG("Discover sets failed (err %d)", err);
717 				discover_complete(client, err);
718 			}
719 		}
720 		return BT_GATT_ITER_STOP;
721 	}
722 
723 	LOG_DBG("[ATTRIBUTE] handle 0x%04X", attr->handle);
724 
725 	if (params->type == BT_GATT_DISCOVER_CHARACTERISTIC &&
726 	    client->inst_count != 0) {
727 		chrc = (struct bt_gatt_chrc *)attr->user_data;
728 		if (bt_uuid_cmp(chrc->uuid, BT_UUID_CSIS_SIRK) == 0) {
729 			LOG_DBG("SIRK");
730 			client->cur_inst->sirk_handle = chrc->value_handle;
731 			sub_params = &client->cur_inst->sirk_sub_params;
732 			sub_params->disc_params = &client->cur_inst->sirk_sub_disc_params;
733 			notify_handler = sirk_notify_func;
734 		} else if (bt_uuid_cmp(chrc->uuid, BT_UUID_CSIS_SET_SIZE) == 0) {
735 			LOG_DBG("Set size");
736 			client->cur_inst->set_size_handle = chrc->value_handle;
737 			sub_params = &client->cur_inst->size_sub_params;
738 			sub_params->disc_params = &client->cur_inst->size_sub_disc_params;
739 			notify_handler = size_notify_func;
740 		} else if (bt_uuid_cmp(chrc->uuid, BT_UUID_CSIS_SET_LOCK) == 0) {
741 			struct bt_csip_set_coordinator_set_info *set_info;
742 
743 			LOG_DBG("Set lock");
744 			client->cur_inst->set_lock_handle = chrc->value_handle;
745 			sub_params = &client->cur_inst->lock_sub_params;
746 			sub_params->disc_params = &client->cur_inst->lock_sub_disc_params;
747 			notify_handler = lock_notify_func;
748 
749 			set_info = &client->set_member.insts[client->cur_inst->idx].info;
750 			set_info->lockable = true;
751 		} else if (bt_uuid_cmp(chrc->uuid, BT_UUID_CSIS_RANK) == 0) {
752 			LOG_DBG("Set rank");
753 			client->cur_inst->rank_handle = chrc->value_handle;
754 		}
755 
756 		if (sub_params != NULL && notify_handler != NULL) {
757 			sub_params->value = 0;
758 			if ((chrc->properties & BT_GATT_CHRC_NOTIFY) != 0) {
759 				sub_params->value = BT_GATT_CCC_NOTIFY;
760 			} else if ((chrc->properties & BT_GATT_CHRC_INDICATE) != 0) {
761 				sub_params->value = BT_GATT_CCC_INDICATE;
762 			}
763 
764 			if (sub_params->value != 0) {
765 				int err;
766 
767 				sub_params->ccc_handle = BT_GATT_AUTO_DISCOVER_CCC_HANDLE;
768 				sub_params->end_handle = client->cur_inst->end_handle;
769 				sub_params->value_handle = chrc->value_handle;
770 				sub_params->notify = notify_handler;
771 				atomic_set_bit(sub_params->flags, BT_GATT_SUBSCRIBE_FLAG_VOLATILE);
772 
773 				err = bt_gatt_subscribe(conn, sub_params);
774 				if (err != 0 && err != -EALREADY) {
775 					LOG_DBG("Failed to subscribe (err %d)", err);
776 					discover_complete(client, err);
777 
778 					return BT_GATT_ITER_STOP;
779 				}
780 			}
781 		}
782 	}
783 
784 	return BT_GATT_ITER_CONTINUE;
785 }
786 
primary_discover_func(struct bt_conn * conn,const struct bt_gatt_attr * attr,struct bt_gatt_discover_params * params)787 static uint8_t primary_discover_func(struct bt_conn *conn,
788 				     const struct bt_gatt_attr *attr,
789 				     struct bt_gatt_discover_params *params)
790 {
791 	struct bt_gatt_service_val *prim_service;
792 	struct bt_csip_set_coordinator_inst *client = &client_insts[bt_conn_index(conn)];
793 
794 	if (attr == NULL ||
795 	    client->inst_count == CONFIG_BT_CSIP_SET_COORDINATOR_MAX_CSIS_INSTANCES) {
796 		LOG_DBG("Discover complete, found %u instances", client->inst_count);
797 		(void)memset(params, 0, sizeof(*params));
798 
799 		if (client->inst_count != 0) {
800 			int err;
801 
802 			client->cur_inst = &client->svc_insts[0];
803 			client->discover_params.uuid = NULL;
804 			client->discover_params.start_handle = client->cur_inst->start_handle;
805 			client->discover_params.end_handle = client->cur_inst->end_handle;
806 			client->discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
807 			client->discover_params.func = discover_func;
808 
809 			err = bt_gatt_discover(conn, &client->discover_params);
810 			if (err != 0) {
811 				LOG_DBG("Discover failed (err %d)", err);
812 				discover_complete(client, err);
813 			}
814 		} else {
815 			discover_complete(client, 0);
816 		}
817 
818 		return BT_GATT_ITER_STOP;
819 	}
820 
821 	LOG_DBG("[ATTRIBUTE] handle 0x%04X", attr->handle);
822 
823 	if (params->type == BT_GATT_DISCOVER_PRIMARY) {
824 		prim_service = (struct bt_gatt_service_val *)attr->user_data;
825 		client->discover_params.start_handle = attr->handle + 1;
826 
827 		client->cur_inst = &client->svc_insts[client->inst_count];
828 		client->cur_inst->idx = client->inst_count;
829 		client->cur_inst->start_handle = attr->handle;
830 		client->cur_inst->end_handle = prim_service->end_handle;
831 		client->cur_inst->conn = bt_conn_ref(conn);
832 		client->cur_inst->set_info = &client->set_member.insts[client->cur_inst->idx].info;
833 		client->inst_count++;
834 	}
835 
836 	return BT_GATT_ITER_CONTINUE;
837 }
838 
bt_csip_set_coordinator_is_set_member(const uint8_t sirk[BT_CSIP_SIRK_SIZE],struct bt_data * data)839 bool bt_csip_set_coordinator_is_set_member(const uint8_t sirk[BT_CSIP_SIRK_SIZE],
840 					   struct bt_data *data)
841 {
842 	if (data->type == BT_DATA_CSIS_RSI &&
843 	    data->data_len == BT_CSIP_RSI_SIZE) {
844 		uint8_t err;
845 		uint8_t hash[BT_CSIP_CRYPTO_HASH_SIZE];
846 		uint8_t prand[BT_CSIP_CRYPTO_PRAND_SIZE];
847 		uint8_t calculated_hash[BT_CSIP_CRYPTO_HASH_SIZE];
848 
849 		memcpy(hash, data->data, BT_CSIP_CRYPTO_HASH_SIZE);
850 		memcpy(prand, data->data + BT_CSIP_CRYPTO_HASH_SIZE, BT_CSIP_CRYPTO_PRAND_SIZE);
851 
852 		LOG_DBG("hash: %s", bt_hex(hash, BT_CSIP_CRYPTO_HASH_SIZE));
853 		LOG_DBG("prand %s", bt_hex(prand, BT_CSIP_CRYPTO_PRAND_SIZE));
854 		err = bt_csip_sih(sirk, prand, calculated_hash);
855 		if (err != 0) {
856 			return false;
857 		}
858 
859 		LOG_DBG("calculated_hash: %s", bt_hex(calculated_hash, BT_CSIP_CRYPTO_HASH_SIZE));
860 		LOG_DBG("hash: %s", bt_hex(hash, BT_CSIP_CRYPTO_HASH_SIZE));
861 
862 		return memcmp(calculated_hash, hash, BT_CSIP_CRYPTO_HASH_SIZE) == 0;
863 	}
864 
865 	return false;
866 }
867 
csip_set_coordinator_discover_insts_read_rank_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * params,const void * data,uint16_t length)868 static uint8_t csip_set_coordinator_discover_insts_read_rank_cb(struct bt_conn *conn,
869 								uint8_t err,
870 								struct bt_gatt_read_params *params,
871 								const void *data,
872 								uint16_t length)
873 {
874 	struct bt_csip_set_coordinator_inst *client = &client_insts[bt_conn_index(conn)];
875 
876 	__ASSERT(client->cur_inst != NULL, "client->cur_inst must not be NULL");
877 
878 	if (err != 0) {
879 		LOG_DBG("err: 0x%02X", err);
880 
881 		discover_complete(client, err);
882 	} else if (data != NULL) {
883 		struct bt_csip_set_coordinator_set_info *set_info;
884 
885 		LOG_HEXDUMP_DBG(data, length, "Data read");
886 
887 		set_info = &client->set_member.insts[client->cur_inst->idx].info;
888 
889 		if (length == sizeof(set_info->rank)) {
890 			(void)memcpy(&set_info->rank, data, length);
891 			LOG_DBG("%u", set_info->rank);
892 		} else {
893 			LOG_DBG("Invalid length, continuing to next member");
894 		}
895 
896 		discover_insts_resume(conn, 0, 0, 0);
897 	}
898 
899 	return BT_GATT_ITER_STOP;
900 }
901 
csip_set_coordinator_discover_insts_read_set_size_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * params,const void * data,uint16_t length)902 static uint8_t csip_set_coordinator_discover_insts_read_set_size_cb(
903 	struct bt_conn *conn, uint8_t err, struct bt_gatt_read_params *params,
904 	const void *data, uint16_t length)
905 {
906 	struct bt_csip_set_coordinator_inst *client = &client_insts[bt_conn_index(conn)];
907 
908 	__ASSERT(client->cur_inst != NULL, "client->cur_inst must not be NULL");
909 
910 	if (err != 0) {
911 		LOG_DBG("err: 0x%02X", err);
912 
913 		discover_complete(client, err);
914 	} else if (data != NULL) {
915 		struct bt_csip_set_coordinator_set_info *set_info;
916 
917 		LOG_HEXDUMP_DBG(data, length, "Data read");
918 
919 		set_info = &client->set_member.insts[client->cur_inst->idx].info;
920 
921 		if (length == sizeof(set_info->set_size)) {
922 			(void)memcpy(&set_info->set_size, data, length);
923 			LOG_DBG("%u", set_info->set_size);
924 		} else {
925 			LOG_DBG("Invalid length");
926 		}
927 
928 		discover_insts_resume(conn, 0, 0, client->cur_inst->rank_handle);
929 	}
930 
931 	return BT_GATT_ITER_STOP;
932 }
933 
parse_sirk(struct bt_csip_set_coordinator_inst * client,const void * data,uint16_t length)934 static int parse_sirk(struct bt_csip_set_coordinator_inst *client,
935 		      const void *data, uint16_t length)
936 {
937 	uint8_t *sirk;
938 
939 	sirk = client->set_member.insts[client->cur_inst->idx].info.sirk;
940 
941 	if (length == sizeof(struct bt_csip_sirk)) {
942 		struct bt_csip_sirk *recvd_sirk = (struct bt_csip_sirk *)data;
943 
944 		LOG_DBG("SIRK %sencrypted",
945 			recvd_sirk->type == BT_CSIP_SIRK_TYPE_PLAIN ? "not " : "");
946 		/* Assuming not connected to other set devices */
947 		if (recvd_sirk->type == BT_CSIP_SIRK_TYPE_ENCRYPTED) {
948 			if (IS_ENABLED(CONFIG_BT_CSIP_SET_COORDINATOR_ENC_SIRK_SUPPORT)) {
949 				int err;
950 
951 				LOG_HEXDUMP_DBG(recvd_sirk->value, sizeof(recvd_sirk->value),
952 						"Encrypted SIRK");
953 				err = sirk_decrypt(client->conn, recvd_sirk->value, sirk);
954 				if (err != 0) {
955 					LOG_ERR("Could not decrypt "
956 						"SIRK %d",
957 						err);
958 					return err;
959 				}
960 			} else {
961 				LOG_WRN("Encrypted SIRK not supported");
962 				sirk = NULL;
963 				return BT_ATT_ERR_INSUFFICIENT_ENCRYPTION;
964 			}
965 		} else {
966 			(void)memcpy(sirk, recvd_sirk->value, sizeof(recvd_sirk->value));
967 		}
968 
969 		if (sirk != NULL) {
970 			LOG_HEXDUMP_DBG(sirk, BT_CSIP_SIRK_SIZE, "SIRK");
971 		}
972 	} else {
973 		LOG_DBG("Invalid length");
974 		return BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
975 	}
976 
977 	return 0;
978 }
979 
csip_set_coordinator_discover_insts_read_sirk_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * params,const void * data,uint16_t length)980 static uint8_t csip_set_coordinator_discover_insts_read_sirk_cb(struct bt_conn *conn, uint8_t err,
981 								struct bt_gatt_read_params *params,
982 								const void *data, uint16_t length)
983 {
984 	struct bt_csip_set_coordinator_inst *client = &client_insts[bt_conn_index(conn)];
985 	int cb_err = err;
986 	__ASSERT(client->cur_inst != NULL, "client->cur_inst must not be NULL");
987 
988 	if (err != 0) {
989 		LOG_DBG("err: 0x%02X", err);
990 
991 		discover_complete(client, err);
992 	} else if (data != NULL) {
993 		LOG_HEXDUMP_DBG(data, length, "Data read");
994 
995 		cb_err = parse_sirk(client, data, length);
996 
997 		if (cb_err != 0) {
998 			LOG_DBG("Could not parse SIRK: %d", cb_err);
999 		} else {
1000 			discover_insts_resume(conn, 0, client->cur_inst->set_size_handle,
1001 					      client->cur_inst->rank_handle);
1002 		}
1003 	}
1004 
1005 	return BT_GATT_ITER_STOP;
1006 }
1007 
1008 /**
1009  * @brief Reads the (next) characteristics for the set discovery procedure
1010  *
1011  * It skips all handles that are 0.
1012  *
1013  * @param conn        Connection to a CSIP set member device.
1014  * @param sirk_handle 0, or the handle for the SIRK characteristic.
1015  * @param size_handle 0, or the handle for the size characteristic.
1016  * @param rank_handle 0, or the handle for the rank characteristic.
1017  */
discover_insts_resume(struct bt_conn * conn,uint16_t sirk_handle,uint16_t size_handle,uint16_t rank_handle)1018 static void discover_insts_resume(struct bt_conn *conn, uint16_t sirk_handle,
1019 				 uint16_t size_handle, uint16_t rank_handle)
1020 {
1021 	int cb_err = 0;
1022 	struct bt_csip_set_coordinator_inst *client = &client_insts[bt_conn_index(conn)];
1023 
1024 	if (size_handle != 0) {
1025 		cb_err = csip_set_coordinator_read_set_size(
1026 			conn, client->cur_inst->idx,
1027 			csip_set_coordinator_discover_insts_read_set_size_cb);
1028 		if (cb_err != 0) {
1029 			LOG_DBG("Could not read set size: %d", cb_err);
1030 		}
1031 	} else if (rank_handle != 0) {
1032 		cb_err = csip_set_coordinator_read_rank(
1033 			conn, client->cur_inst->idx,
1034 			csip_set_coordinator_discover_insts_read_rank_cb);
1035 		if (cb_err != 0) {
1036 			LOG_DBG("Could not read set rank: %d", cb_err);
1037 		}
1038 	} else {
1039 		uint8_t next_idx = client->cur_inst->idx + 1;
1040 
1041 		client->cur_inst = NULL;
1042 		if (next_idx < client->inst_count) {
1043 			client->cur_inst =
1044 				bt_csip_set_coordinator_lookup_instance_by_index(conn, next_idx);
1045 
1046 			/* Read next */
1047 			cb_err = read_sirk(client->cur_inst);
1048 		} else {
1049 			discover_complete(client, 0);
1050 
1051 			return;
1052 		}
1053 	}
1054 
1055 	if (cb_err != 0) {
1056 		discover_complete(client, cb_err);
1057 	}
1058 }
1059 
csip_set_coordinator_write_restore_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_write_params * params)1060 static void csip_set_coordinator_write_restore_cb(struct bt_conn *conn,
1061 						  uint8_t err,
1062 						  struct bt_gatt_write_params *params)
1063 {
1064 	struct bt_csip_set_coordinator_inst *client = &client_insts[bt_conn_index(conn)];
1065 
1066 	if (err != 0) {
1067 		LOG_WRN("Could not restore (%d)", err);
1068 		release_set_complete(err);
1069 
1070 		return;
1071 	}
1072 
1073 	active.members_restored++;
1074 	LOG_DBG("Restored %u/%u members", active.members_restored, active.members_handled);
1075 
1076 	if (active.members_restored < active.members_handled &&
1077 	    CONFIG_BT_MAX_CONN > 1) {
1078 		struct bt_csip_set_coordinator_set_member *member;
1079 		int csip_err;
1080 
1081 		member = active.members[active.members_handled - active.members_restored - 1];
1082 		client->cur_inst = lookup_instance_by_set_info(member, &active.info);
1083 		if (client->cur_inst == NULL) {
1084 			release_set_complete(-ENOENT);
1085 
1086 			return;
1087 		}
1088 
1089 		csip_err = csip_set_coordinator_write_set_lock(
1090 			client->cur_inst, false, csip_set_coordinator_write_restore_cb);
1091 		if (csip_err != 0) {
1092 			LOG_DBG("Failed to release next member[%u]: %d", active.members_handled,
1093 				csip_err);
1094 
1095 			release_set_complete(csip_err);
1096 		}
1097 	} else {
1098 		release_set_complete(0);
1099 	}
1100 }
1101 
csip_set_coordinator_write_lock_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_write_params * params)1102 static void csip_set_coordinator_write_lock_cb(struct bt_conn *conn,
1103 					       uint8_t err,
1104 					       struct bt_gatt_write_params *params)
1105 {
1106 	struct bt_csip_set_coordinator_inst *client = &client_insts[bt_conn_index(conn)];
1107 
1108 	if (err != 0) {
1109 		LOG_DBG("Could not lock (0x%X)", err);
1110 		if (active.members_handled > 0 && CONFIG_BT_MAX_CONN > 1) {
1111 			struct bt_csip_set_coordinator_set_member *member;
1112 			int csip_err;
1113 
1114 			active.members_restored = 0;
1115 
1116 			member = active.members[active.members_handled - 1];
1117 			client->cur_inst = lookup_instance_by_set_info(member, &active.info);
1118 			if (client->cur_inst == NULL) {
1119 				LOG_DBG("Failed to lookup instance by set_info");
1120 
1121 				lock_set_complete(-ENOENT);
1122 				return;
1123 			}
1124 
1125 			csip_err = csip_set_coordinator_write_set_lock(
1126 				client->cur_inst, false, csip_set_coordinator_write_restore_cb);
1127 			if (csip_err != 0) {
1128 				LOG_WRN("Could not release lock of previous locked member: %d",
1129 					csip_err);
1130 				active_members_reset();
1131 				return;
1132 			}
1133 		} else {
1134 			lock_set_complete(err);
1135 		}
1136 
1137 		return;
1138 	}
1139 
1140 	active.members_handled++;
1141 	LOG_DBG("Locked %u/%u members", active.members_handled, active.members_count);
1142 
1143 	if (active.members_handled < active.members_count) {
1144 		struct bt_csip_set_coordinator_svc_inst *prev_inst = client->cur_inst;
1145 		int csip_err;
1146 
1147 		client->cur_inst = get_next_active_instance();
1148 		if (client->cur_inst == NULL) {
1149 			lock_set_complete(-ENOENT);
1150 
1151 			return;
1152 		}
1153 
1154 		csip_err = csip_set_coordinator_write_set_lock(client->cur_inst, true,
1155 							       csip_set_coordinator_write_lock_cb);
1156 		if (csip_err != 0) {
1157 			LOG_DBG("Failed to lock next member[%u]: %d", active.members_handled,
1158 				csip_err);
1159 
1160 			active.members_restored = 0;
1161 
1162 			csip_err = csip_set_coordinator_write_set_lock(
1163 					prev_inst, false,
1164 					csip_set_coordinator_write_restore_cb);
1165 			if (csip_err != 0) {
1166 				LOG_WRN("Could not release lock of previous locked member: %d",
1167 					csip_err);
1168 				active_members_reset();
1169 				return;
1170 			}
1171 		}
1172 	} else {
1173 		lock_set_complete(0);
1174 	}
1175 }
1176 
csip_set_coordinator_write_release_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_write_params * params)1177 static void csip_set_coordinator_write_release_cb(struct bt_conn *conn, uint8_t err,
1178 						  struct bt_gatt_write_params *params)
1179 {
1180 	struct bt_csip_set_coordinator_inst *client = &client_insts[bt_conn_index(conn)];
1181 
1182 	if (err != 0) {
1183 		LOG_DBG("Could not release lock (%d)", err);
1184 		release_set_complete(err);
1185 
1186 		return;
1187 	}
1188 
1189 	active.members_handled++;
1190 	LOG_DBG("Released %u/%u members", active.members_handled, active.members_count);
1191 
1192 	if (active.members_handled < active.members_count) {
1193 		int csip_err;
1194 
1195 		client->cur_inst = get_next_active_instance();
1196 		if (client->cur_inst == NULL) {
1197 			release_set_complete(-ENOENT);
1198 
1199 			return;
1200 		}
1201 
1202 		csip_err = csip_set_coordinator_write_set_lock(
1203 			client->cur_inst, false, csip_set_coordinator_write_release_cb);
1204 		if (csip_err != 0) {
1205 			LOG_DBG("Failed to release next member[%u]: %d", active.members_handled,
1206 				csip_err);
1207 
1208 			release_set_complete(csip_err);
1209 		}
1210 	} else {
1211 		release_set_complete(0);
1212 	}
1213 }
1214 
csip_set_coordinator_lock_state_read_cb(int err,bool locked)1215 static void csip_set_coordinator_lock_state_read_cb(int err, bool locked)
1216 {
1217 	const struct bt_csip_set_coordinator_set_info *info = &active.info;
1218 	struct bt_csip_set_coordinator_set_member *cur_member = NULL;
1219 
1220 	if (err || locked) {
1221 		cur_member = active.members[active.members_handled];
1222 	} else if (active.oap_cb == NULL || !active.oap_cb(info, active.members,
1223 		   active.members_count)) {
1224 		err = -ECANCELED;
1225 	}
1226 
1227 	ordered_access_complete(info, err, locked, cur_member);
1228 }
1229 
csip_set_coordinator_read_lock_cb(struct bt_conn * conn,uint8_t err,struct bt_gatt_read_params * params,const void * data,uint16_t length)1230 static uint8_t csip_set_coordinator_read_lock_cb(struct bt_conn *conn,
1231 						 uint8_t err,
1232 						 struct bt_gatt_read_params *params,
1233 						 const void *data,
1234 						 uint16_t length)
1235 {
1236 	struct bt_csip_set_coordinator_inst *client = &client_insts[bt_conn_index(conn)];
1237 	uint8_t value = 0;
1238 
1239 	if (err != 0) {
1240 		LOG_DBG("Could not read lock value (0x%X)", err);
1241 
1242 		csip_set_coordinator_lock_state_read_cb(err, false);
1243 
1244 		return BT_GATT_ITER_STOP;
1245 	}
1246 
1247 	active.members_handled++;
1248 	LOG_DBG("Read lock state on %u/%u members", active.members_handled, active.members_count);
1249 
1250 	if (data == NULL || length != sizeof(client->cur_inst->set_lock)) {
1251 		LOG_DBG("Invalid data %p or length %u", data, length);
1252 
1253 		csip_set_coordinator_lock_state_read_cb(err, false);
1254 
1255 		return BT_GATT_ITER_STOP;
1256 	}
1257 
1258 	value = ((uint8_t *)data)[0];
1259 	if (value != BT_CSIP_RELEASE_VALUE && value != BT_CSIP_LOCK_VALUE) {
1260 		LOG_DBG("Invalid value %u read", value);
1261 		err = BT_ATT_ERR_UNLIKELY;
1262 
1263 		csip_set_coordinator_lock_state_read_cb(err, false);
1264 
1265 		return BT_GATT_ITER_STOP;
1266 	}
1267 
1268 	client->cur_inst->set_lock = value;
1269 
1270 	if (value != BT_CSIP_RELEASE_VALUE) {
1271 		LOG_DBG("Set member not unlocked");
1272 
1273 		csip_set_coordinator_lock_state_read_cb(0, true);
1274 
1275 		return BT_GATT_ITER_STOP;
1276 	}
1277 
1278 	if (active.members_handled < active.members_count) {
1279 		int csip_err;
1280 
1281 		client->cur_inst = get_next_active_instance();
1282 		if (client->cur_inst == NULL) {
1283 			csip_set_coordinator_lock_state_read_cb(-ENOENT, false);
1284 
1285 			return BT_GATT_ITER_STOP;
1286 		}
1287 
1288 		csip_err = csip_set_coordinator_read_set_lock(client->cur_inst);
1289 		if (csip_err != 0) {
1290 			LOG_DBG("Failed to read next member[%u]: %d", active.members_handled,
1291 				csip_err);
1292 
1293 			csip_set_coordinator_lock_state_read_cb(err, false);
1294 		}
1295 	} else {
1296 		csip_set_coordinator_lock_state_read_cb(0, false);
1297 	}
1298 
1299 	return BT_GATT_ITER_STOP;
1300 }
1301 
csip_set_coordinator_read_set_lock(struct bt_csip_set_coordinator_svc_inst * inst)1302 static int csip_set_coordinator_read_set_lock(struct bt_csip_set_coordinator_svc_inst *inst)
1303 {
1304 	struct bt_csip_set_coordinator_inst *client = &client_insts[bt_conn_index(inst->conn)];
1305 	int err;
1306 
1307 	if (inst->set_lock_handle == 0) {
1308 		LOG_DBG("Handle not set");
1309 		client->cur_inst = NULL;
1310 		return -EINVAL;
1311 	}
1312 
1313 	client->read_params.func = csip_set_coordinator_read_lock_cb;
1314 	client->read_params.handle_count = 1;
1315 	client->read_params.single.handle = inst->set_lock_handle;
1316 	client->read_params.single.offset = 0;
1317 
1318 	client->cur_inst = inst;
1319 
1320 	err = bt_gatt_read(inst->conn, &client->read_params);
1321 	if (err != 0) {
1322 		client->cur_inst = NULL;
1323 	}
1324 
1325 	return err;
1326 }
1327 
csip_set_coordinator_reset(struct bt_csip_set_coordinator_inst * inst)1328 static void csip_set_coordinator_reset(struct bt_csip_set_coordinator_inst *inst)
1329 {
1330 	inst->inst_count = 0U;
1331 	memset(&inst->set_member, 0, sizeof(inst->set_member));
1332 
1333 	for (size_t i = 0; i < ARRAY_SIZE(inst->svc_insts); i++) {
1334 		struct bt_csip_set_coordinator_svc_inst *svc_inst = &inst->svc_insts[i];
1335 
1336 		svc_inst->idx = 0;
1337 		svc_inst->set_lock = 0;
1338 		svc_inst->start_handle = 0;
1339 		svc_inst->end_handle = 0;
1340 		svc_inst->sirk_handle = 0;
1341 		svc_inst->set_size_handle = 0;
1342 		svc_inst->set_lock_handle = 0;
1343 		svc_inst->rank_handle = 0;
1344 
1345 		if (svc_inst->conn != NULL) {
1346 			struct bt_conn *conn = svc_inst->conn;
1347 
1348 			bt_conn_unref(conn);
1349 			svc_inst->conn = NULL;
1350 		}
1351 
1352 		if (svc_inst->set_info != NULL) {
1353 			memset(svc_inst->set_info, 0, sizeof(*svc_inst->set_info));
1354 			svc_inst->set_info = NULL;
1355 		}
1356 	}
1357 
1358 	if (inst->conn) {
1359 		bt_conn_unref(inst->conn);
1360 		inst->conn = NULL;
1361 	}
1362 }
1363 
disconnected(struct bt_conn * conn,uint8_t reason)1364 static void disconnected(struct bt_conn *conn, uint8_t reason)
1365 {
1366 	struct bt_csip_set_coordinator_inst *inst = &client_insts[bt_conn_index(conn)];
1367 
1368 	if (inst->conn == conn) {
1369 		csip_set_coordinator_reset(inst);
1370 	}
1371 }
1372 
1373 BT_CONN_CB_DEFINE(conn_callbacks) = {
1374 	.disconnected = disconnected,
1375 };
1376 
bt_csip_set_coordinator_csis_inst_by_handle(struct bt_conn * conn,uint16_t start_handle)1377 struct bt_csip_set_coordinator_csis_inst *bt_csip_set_coordinator_csis_inst_by_handle(
1378 	struct bt_conn *conn, uint16_t start_handle)
1379 {
1380 	const struct bt_csip_set_coordinator_svc_inst *svc_inst;
1381 
1382 	CHECKIF(conn == NULL) {
1383 		LOG_DBG("conn is NULL");
1384 
1385 		return NULL;
1386 	}
1387 
1388 	CHECKIF(start_handle == 0) {
1389 		LOG_DBG("start_handle is 0");
1390 
1391 		return NULL;
1392 	}
1393 
1394 	svc_inst = lookup_instance_by_handle(conn, start_handle);
1395 
1396 	if (svc_inst != NULL) {
1397 		struct bt_csip_set_coordinator_inst *client;
1398 
1399 		client = &client_insts[bt_conn_index(conn)];
1400 
1401 		return &client->set_member.insts[svc_inst->idx];
1402 	}
1403 
1404 	return NULL;
1405 }
1406 
1407 struct bt_csip_set_coordinator_set_member *
bt_csip_set_coordinator_set_member_by_conn(const struct bt_conn * conn)1408 bt_csip_set_coordinator_set_member_by_conn(const struct bt_conn *conn)
1409 {
1410 	struct bt_csip_set_coordinator_inst *client;
1411 
1412 	CHECKIF(conn == NULL) {
1413 		LOG_DBG("conn is NULL");
1414 
1415 		return NULL;
1416 	}
1417 
1418 	client = &client_insts[bt_conn_index(conn)];
1419 	if (client->conn == conn) {
1420 		return &client->set_member;
1421 	}
1422 
1423 	return NULL;
1424 }
1425 
1426 /*************************** PUBLIC FUNCTIONS ***************************/
bt_csip_set_coordinator_register_cb(struct bt_csip_set_coordinator_cb * cb)1427 int bt_csip_set_coordinator_register_cb(struct bt_csip_set_coordinator_cb *cb)
1428 {
1429 	CHECKIF(cb == NULL) {
1430 		LOG_DBG("cb is NULL");
1431 
1432 		return -EINVAL;
1433 	}
1434 
1435 	sys_slist_append(&csip_set_coordinator_cbs, &cb->_node);
1436 
1437 	return 0;
1438 }
1439 
bt_csip_set_coordinator_discover(struct bt_conn * conn)1440 int bt_csip_set_coordinator_discover(struct bt_conn *conn)
1441 {
1442 	int err;
1443 	struct bt_csip_set_coordinator_inst *client;
1444 
1445 	CHECKIF(conn == NULL) {
1446 		LOG_DBG("NULL conn");
1447 		return -EINVAL;
1448 	}
1449 
1450 	client = &client_insts[bt_conn_index(conn)];
1451 	if (atomic_test_and_set_bit(client->flags, SET_COORDINATOR_FLAG_BUSY)) {
1452 		return -EBUSY;
1453 	}
1454 
1455 	csip_set_coordinator_reset(client);
1456 
1457 	/* Discover CSIS on peer, setup handles and notify */
1458 	(void)memset(&client->discover_params, 0, sizeof(client->discover_params));
1459 	(void)memcpy(&uuid, BT_UUID_CSIS, sizeof(uuid));
1460 	client->discover_params.func = primary_discover_func;
1461 	client->discover_params.uuid = &uuid.uuid;
1462 	client->discover_params.type = BT_GATT_DISCOVER_PRIMARY;
1463 	client->discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
1464 	client->discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
1465 
1466 	err = bt_gatt_discover(conn, &client->discover_params);
1467 	if (err == 0) {
1468 		for (size_t i = 0; i < ARRAY_SIZE(client->set_member.insts); i++) {
1469 			client->set_member.insts[i].svc_inst = (void *)&client->svc_insts[i];
1470 		}
1471 		client->conn = bt_conn_ref(conn);
1472 	} else {
1473 		atomic_clear_bit(client->flags, SET_COORDINATOR_FLAG_BUSY);
1474 	}
1475 
1476 	return err;
1477 }
1478 
verify_members(const struct bt_csip_set_coordinator_set_member ** members,uint8_t count,const struct bt_csip_set_coordinator_set_info * set_info)1479 static int verify_members(const struct bt_csip_set_coordinator_set_member **members,
1480 			  uint8_t count,
1481 			  const struct bt_csip_set_coordinator_set_info *set_info)
1482 {
1483 	bool zero_rank;
1484 	uint8_t ranks[CONFIG_BT_MAX_CONN];
1485 
1486 	if (count > CONFIG_BT_MAX_CONN) {
1487 		LOG_DBG("count (%u) larger than maximum support servers (%d)", count,
1488 			CONFIG_BT_MAX_CONN);
1489 		return -EINVAL;
1490 	}
1491 
1492 	zero_rank = false;
1493 	for (int i = 0; i < count; i++) {
1494 		const struct bt_csip_set_coordinator_set_member *member = members[i];
1495 		struct bt_csip_set_coordinator_inst *client_inst =
1496 			CONTAINER_OF(member, struct bt_csip_set_coordinator_inst, set_member);
1497 		struct bt_csip_set_coordinator_svc_inst *svc_inst;
1498 		struct bt_conn *conn;
1499 
1500 		CHECKIF(member == NULL) {
1501 			LOG_DBG("Invalid member[%d] was NULL", i);
1502 			return -EINVAL;
1503 		}
1504 
1505 		conn = client_inst->conn;
1506 
1507 		CHECKIF(conn == NULL) {
1508 			LOG_DBG("Member[%d] conn was NULL", i);
1509 			return -EINVAL;
1510 		}
1511 
1512 		if (conn->state != BT_CONN_CONNECTED) {
1513 			LOG_DBG("Member[%d] was not connected", i);
1514 			return -ENOTCONN;
1515 		}
1516 
1517 		svc_inst = lookup_instance_by_set_info(member, set_info);
1518 		if (svc_inst == NULL) {
1519 			LOG_DBG("Member[%d] could not find matching instance for the set_info", i);
1520 			return -EINVAL;
1521 		}
1522 
1523 		ranks[i] = svc_inst->set_info->rank;
1524 		if (ranks[i] == 0U && !zero_rank) {
1525 			zero_rank = true;
1526 		} else if (ranks[i] != 0 && zero_rank) {
1527 			/* all members in a set shall either use rank, or not use rank */
1528 			LOG_DBG("Found mix of 0 and non-0 ranks");
1529 			return -EINVAL;
1530 		}
1531 	}
1532 
1533 	if (CONFIG_BT_MAX_CONN > 1 && !zero_rank && count > 1U) {
1534 		/* Search for duplicate ranks */
1535 		for (uint8_t i = 0U; i < count - 1; i++) {
1536 			for (uint8_t j = i + 1; j < count; j++) {
1537 				if (ranks[j] == ranks[i]) {
1538 					/* duplicate rank */
1539 					LOG_DBG("Duplicate rank (%u) for members[%zu] "
1540 						"and members[%zu]",
1541 						ranks[i], i, j);
1542 					return -EINVAL;
1543 				}
1544 			}
1545 		}
1546 	}
1547 
1548 	return 0;
1549 }
1550 
check_and_set_members_busy(const struct bt_csip_set_coordinator_set_member * members[],size_t count)1551 static bool check_and_set_members_busy(const struct bt_csip_set_coordinator_set_member *members[],
1552 				       size_t count)
1553 {
1554 	size_t num_free;
1555 
1556 	for (num_free = 0U; num_free < count; num_free++) {
1557 		const struct bt_csip_set_coordinator_set_member *member = members[num_free];
1558 		struct bt_csip_set_coordinator_inst *client =
1559 			CONTAINER_OF(member, struct bt_csip_set_coordinator_inst, set_member);
1560 
1561 		if (atomic_test_and_set_bit(client->flags, SET_COORDINATOR_FLAG_BUSY)) {
1562 			LOG_DBG("Member[%zu] (%p) is busy", num_free, member);
1563 			break;
1564 		}
1565 	}
1566 
1567 	/* If any is busy, revert any busy states we've set */
1568 	if (num_free != count) {
1569 		for (size_t i = 0U; i < num_free; i++) {
1570 			const struct bt_csip_set_coordinator_set_member *member = members[i];
1571 			struct bt_csip_set_coordinator_inst *client = CONTAINER_OF(
1572 				member, struct bt_csip_set_coordinator_inst, set_member);
1573 
1574 			atomic_clear_bit(client->flags, SET_COORDINATOR_FLAG_BUSY);
1575 		}
1576 	}
1577 
1578 	return num_free == count;
1579 }
1580 
1581 static int
csip_set_coordinator_get_lock_state(const struct bt_csip_set_coordinator_set_member ** members,uint8_t count,const struct bt_csip_set_coordinator_set_info * set_info)1582 csip_set_coordinator_get_lock_state(const struct bt_csip_set_coordinator_set_member **members,
1583 				    uint8_t count,
1584 				    const struct bt_csip_set_coordinator_set_info *set_info)
1585 {
1586 	int err;
1587 
1588 	if (active.in_progress) {
1589 		LOG_DBG("Procedure in progress");
1590 		return -EBUSY;
1591 	}
1592 
1593 	err = verify_members(members, count, set_info);
1594 	if (err != 0) {
1595 		LOG_DBG("Could not verify members: %d", err);
1596 		return err;
1597 	}
1598 
1599 	if (!check_and_set_members_busy(members, count)) {
1600 		LOG_DBG("One or more members are busy");
1601 		return -EBUSY;
1602 	}
1603 
1604 	active_members_store_ordered(members, count, set_info, true);
1605 
1606 	for (uint8_t i = 0U; i < count; i++) {
1607 		struct bt_csip_set_coordinator_svc_inst *svc_inst;
1608 
1609 		svc_inst = lookup_instance_by_set_info(active.members[i], &active.info);
1610 		if (svc_inst == NULL) {
1611 			LOG_DBG("Failed to lookup instance by set_info");
1612 
1613 			active_members_reset();
1614 			return -ENOENT;
1615 		}
1616 
1617 		if (svc_inst->set_info->lockable) {
1618 			err = csip_set_coordinator_read_set_lock(svc_inst);
1619 			if (err == 0) {
1620 				active.in_progress = true;
1621 			}
1622 
1623 			break;
1624 		}
1625 
1626 		active.members_handled++;
1627 	}
1628 
1629 	if (!active.in_progress && err == 0) {
1630 		/* We are not reading any lock states (because they are not on the remote devices),
1631 		 * so we can just initiate the ordered access procedure (oap) callback directly
1632 		 * here.
1633 		 */
1634 		if (active.oap_cb == NULL ||
1635 		    !active.oap_cb(&active.info, active.members, active.members_count)) {
1636 			err = -ECANCELED;
1637 		}
1638 
1639 		ordered_access_complete(&active.info, err, false, NULL);
1640 	}
1641 
1642 	return err;
1643 }
1644 
bt_csip_set_coordinator_ordered_access(const struct bt_csip_set_coordinator_set_member * members[],uint8_t count,const struct bt_csip_set_coordinator_set_info * set_info,bt_csip_set_coordinator_ordered_access_t cb)1645 int bt_csip_set_coordinator_ordered_access(
1646 	const struct bt_csip_set_coordinator_set_member *members[],
1647 	uint8_t count,
1648 	const struct bt_csip_set_coordinator_set_info *set_info,
1649 	bt_csip_set_coordinator_ordered_access_t cb)
1650 {
1651 	int err;
1652 
1653 	/* wait for the get_lock_state to finish and then call the callback */
1654 	active.oap_cb = cb;
1655 
1656 	err = csip_set_coordinator_get_lock_state(members, count, set_info);
1657 	if (err != 0) {
1658 		active.oap_cb = NULL;
1659 
1660 		return err;
1661 	}
1662 
1663 	return 0;
1664 }
1665 
1666 /* As per CSIP, locking and releasing sets can only be done by bonded devices, so it does not makes
1667  * sense to have these functions available if we do not support bonding
1668  */
1669 #if defined(CONFIG_BT_BONDABLE)
all_members_bonded(const struct bt_csip_set_coordinator_set_member * members[],size_t count)1670 static bool all_members_bonded(const struct bt_csip_set_coordinator_set_member *members[],
1671 			       size_t count)
1672 {
1673 	for (size_t i = 0U; i < count; i++) {
1674 		const struct bt_csip_set_coordinator_set_member *member = members[i];
1675 		const struct bt_csip_set_coordinator_inst *client =
1676 			CONTAINER_OF(member, struct bt_csip_set_coordinator_inst, set_member);
1677 		struct bt_conn_info info;
1678 		int err;
1679 
1680 		err = bt_conn_get_info(client->conn, &info);
1681 		if (err != 0 || !bt_addr_le_is_bonded(info.id, info.le.dst)) {
1682 			LOG_DBG("Member[%zu] is not bonded", i);
1683 
1684 			return false;
1685 		}
1686 	}
1687 
1688 	return true;
1689 }
1690 
bt_csip_set_coordinator_lock(const struct bt_csip_set_coordinator_set_member ** members,uint8_t count,const struct bt_csip_set_coordinator_set_info * set_info)1691 int bt_csip_set_coordinator_lock(
1692 	const struct bt_csip_set_coordinator_set_member **members,
1693 	uint8_t count,
1694 	const struct bt_csip_set_coordinator_set_info *set_info)
1695 {
1696 	struct bt_csip_set_coordinator_svc_inst *svc_inst;
1697 	int err;
1698 
1699 	CHECKIF(active.in_progress) {
1700 		LOG_DBG("Procedure in progress");
1701 		return -EBUSY;
1702 	}
1703 
1704 	err = verify_members(members, count, set_info);
1705 	if (err != 0) {
1706 		LOG_DBG("Could not verify members: %d", err);
1707 		return err;
1708 	}
1709 
1710 	if (!all_members_bonded(members, count)) {
1711 		return -EINVAL;
1712 	}
1713 
1714 	if (!check_and_set_members_busy(members, count)) {
1715 		LOG_DBG("One or more members are busy");
1716 		return -EBUSY;
1717 	}
1718 
1719 	active_members_store_ordered(members, count, set_info, true);
1720 
1721 	svc_inst = lookup_instance_by_set_info(active.members[0], &active.info);
1722 	if (svc_inst == NULL) {
1723 		LOG_DBG("Failed to lookup instance by set_info");
1724 
1725 		active_members_reset();
1726 		return -ENOENT;
1727 	}
1728 
1729 	err = csip_set_coordinator_write_set_lock(svc_inst, true,
1730 						  csip_set_coordinator_write_lock_cb);
1731 	if (err == 0) {
1732 		active.in_progress = true;
1733 	}
1734 
1735 	return err;
1736 }
1737 
bt_csip_set_coordinator_release(const struct bt_csip_set_coordinator_set_member ** members,uint8_t count,const struct bt_csip_set_coordinator_set_info * set_info)1738 int bt_csip_set_coordinator_release(const struct bt_csip_set_coordinator_set_member **members,
1739 				    uint8_t count,
1740 				    const struct bt_csip_set_coordinator_set_info *set_info)
1741 {
1742 	struct bt_csip_set_coordinator_svc_inst *svc_inst;
1743 	int err;
1744 
1745 	CHECKIF(active.in_progress) {
1746 		LOG_DBG("Procedure in progress");
1747 		return -EBUSY;
1748 	}
1749 
1750 	err = verify_members(members, count, set_info);
1751 	if (err != 0) {
1752 		LOG_DBG("Could not verify members: %d", err);
1753 		return err;
1754 	}
1755 
1756 	if (!all_members_bonded(members, count)) {
1757 		return -EINVAL;
1758 	}
1759 
1760 	if (!check_and_set_members_busy(members, count)) {
1761 		LOG_DBG("One or more members are busy");
1762 		return -EBUSY;
1763 	}
1764 
1765 	active_members_store_ordered(members, count, set_info, false);
1766 
1767 	svc_inst = lookup_instance_by_set_info(active.members[0], &active.info);
1768 	if (svc_inst == NULL) {
1769 		LOG_DBG("Failed to lookup instance by set_info");
1770 
1771 		active_members_reset();
1772 		return -ENOENT;
1773 	}
1774 
1775 	err = csip_set_coordinator_write_set_lock(svc_inst, false,
1776 						  csip_set_coordinator_write_release_cb);
1777 	if (err == 0) {
1778 		active.in_progress = true;
1779 	}
1780 
1781 	return err;
1782 }
1783 #endif /* CONFIG_BT_BONDABLE */
1784