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