1 /*  Bluetooth CSIP - Coordinated Set Identification Profile */
2 
3 /*
4  * Copyright (c) 2019 Bose Corporation
5  * Copyright (c) 2020-2025 Nordic Semiconductor ASA
6  *
7  * SPDX-License-Identifier: Apache-2.0
8  */
9 #include <sys/types.h>
10 #include <errno.h>
11 #include <stdbool.h>
12 #include <stddef.h>
13 #include <stdint.h>
14 #include <stdlib.h>
15 #include <string.h>
16 
17 #include <zephyr/autoconf.h>
18 #include <zephyr/bluetooth/addr.h>
19 #include <zephyr/bluetooth/att.h>
20 #include <zephyr/bluetooth/audio/csip.h>
21 #include <zephyr/bluetooth/bluetooth.h>
22 #include <zephyr/bluetooth/conn.h>
23 #include <zephyr/bluetooth/crypto.h>
24 #include <zephyr/bluetooth/gatt.h>
25 #include <zephyr/bluetooth/buf.h>
26 #include <zephyr/bluetooth/uuid.h>
27 #include <zephyr/device.h>
28 #include <zephyr/init.h>
29 #include <zephyr/kernel.h>
30 #include <zephyr/logging/log.h>
31 #include <zephyr/sys/__assert.h>
32 #include <zephyr/sys/atomic.h>
33 #include <zephyr/sys/util.h>
34 #include <zephyr/sys/util_macro.h>
35 #include <zephyr/sys_clock.h>
36 #include <zephyr/types.h>
37 #include <zephyr/sys/byteorder.h>
38 #include <zephyr/sys/check.h>
39 
40 #include "../host/conn_internal.h"
41 #include "../host/keys.h"
42 #include "../host/settings.h"
43 
44 #include "common/bt_str.h"
45 #include "audio_internal.h"
46 #include "csip_internal.h"
47 #include "csip_crypto.h"
48 
49 #define CSIP_SET_LOCK_TIMER_VALUE       K_SECONDS(60)
50 
51 #define CSIS_CHAR_ATTR_COUNT	  3 /* declaration + value + cccd */
52 #define CSIS_RANK_CHAR_ATTR_COUNT 2 /* declaration + value */
53 
54 LOG_MODULE_REGISTER(bt_csip_set_member, CONFIG_BT_CSIP_SET_MEMBER_LOG_LEVEL);
55 
56 enum csip_flag {
57 	FLAG_ACTIVE,
58 	FLAG_NOTIFY_LOCK,
59 	FLAG_NOTIFY_SIRK,
60 	FLAG_NOTIFY_SIZE,
61 	FLAG_NUM,
62 };
63 
64 struct csip_client {
65 	bt_addr_le_t addr;
66 
67 	/* Pending notification flags */
68 	ATOMIC_DEFINE(flags, FLAG_NUM);
69 };
70 
71 struct bt_csip_set_member_svc_inst {
72 	struct bt_csip_sirk sirk;
73 	uint8_t set_size;
74 	uint8_t set_lock;
75 	uint8_t rank;
76 	bool lockable;
77 	struct bt_csip_set_member_cb *cb;
78 	struct k_work_delayable set_lock_timer;
79 	bt_addr_le_t lock_client_addr;
80 	struct bt_gatt_service *service_p;
81 	struct csip_client clients[CONFIG_BT_MAX_PAIRED];
82 	/* Must be last: exclude from memset during unregister */
83 	struct k_mutex mutex;
84 };
85 
86 static struct bt_csip_set_member_svc_inst svc_insts[CONFIG_BT_CSIP_SET_MEMBER_MAX_INSTANCE_COUNT];
87 
88 static void deferred_nfy_work_handler(struct k_work *work);
89 static void add_bonded_addr_to_client_list(const struct bt_bond_info *info, void *data);
90 
91 #if defined(CONFIG_BT_SETTINGS)
csip_settings_commit(void)92 static int csip_settings_commit(void)
93 {
94 	bt_foreach_bond(BT_ID_DEFAULT, add_bonded_addr_to_client_list, NULL);
95 
96 	LOG_DBG("Restored CSIP client list from bonded devices");
97 
98 	return 0;
99 }
100 
101 /* Register CSIP settings handler with commit priority, BT_SETTINGS_CPRIO_2,
102  * to ensure csip_settings_commit() runs after BT keys settings are loaded.
103  * Priority is reduced to ensure existing bonds are loaded first.
104  */
105 SETTINGS_STATIC_HANDLER_DEFINE_WITH_CPRIO(bt_csip_set_member, "bt/csip", NULL, NULL,
106 					csip_settings_commit, NULL, BT_SETTINGS_CPRIO_2);
107 #endif /* CONFIG_BT_SETTINGS */
108 
109 static K_WORK_DELAYABLE_DEFINE(deferred_nfy_work, deferred_nfy_work_handler);
110 
is_last_client_to_write(const struct bt_csip_set_member_svc_inst * svc_inst,const struct bt_conn * conn)111 static bool is_last_client_to_write(const struct bt_csip_set_member_svc_inst *svc_inst,
112 				    const struct bt_conn *conn)
113 {
114 	if (conn != NULL) {
115 		return bt_addr_le_eq(bt_conn_get_dst(conn),
116 				     &svc_inst->lock_client_addr);
117 	} else {
118 		return bt_addr_le_eq(BT_ADDR_LE_NONE, &svc_inst->lock_client_addr);
119 	}
120 }
121 
notify_work_reschedule(k_timeout_t delay)122 static void notify_work_reschedule(k_timeout_t delay)
123 {
124 	int err;
125 
126 	/* If it is already scheduled, don't reschedule */
127 	if (k_work_delayable_remaining_get(&deferred_nfy_work) > 0) {
128 		return;
129 	}
130 
131 	err = k_work_reschedule(&deferred_nfy_work, delay);
132 	if (err < 0) {
133 		LOG_ERR("Failed to reschedule notification work err %d", err);
134 	}
135 }
136 
notify_clients(struct bt_csip_set_member_svc_inst * svc_inst,struct bt_conn * excluded_client,enum csip_flag flag)137 static void notify_clients(struct bt_csip_set_member_svc_inst *svc_inst,
138 			   struct bt_conn *excluded_client, enum csip_flag flag)
139 {
140 	bool submit_work = false;
141 
142 	/* Mark all bonded devices (except the excluded one) as pending notifications */
143 	for (size_t i = 0U; i < ARRAY_SIZE(svc_inst->clients); i++) {
144 		struct csip_client *client;
145 
146 		client = &svc_inst->clients[i];
147 
148 		if (atomic_test_bit(client->flags, FLAG_ACTIVE)) {
149 			if (excluded_client != NULL &&
150 			    bt_addr_le_eq(bt_conn_get_dst(excluded_client), &client->addr)) {
151 				continue;
152 			}
153 
154 			atomic_set_bit(client->flags, flag);
155 			submit_work = true;
156 		}
157 	}
158 
159 	/* Reschedule work for notifying */
160 	if (submit_work) {
161 		notify_work_reschedule(K_NO_WAIT);
162 	}
163 }
164 
sirk_encrypt(struct bt_conn * conn,const struct bt_csip_sirk * sirk,struct bt_csip_sirk * enc_sirk)165 static int sirk_encrypt(struct bt_conn *conn, const struct bt_csip_sirk *sirk,
166 			struct bt_csip_sirk *enc_sirk)
167 {
168 	int err;
169 	const uint8_t *k;
170 
171 	if (IS_ENABLED(CONFIG_BT_CSIP_SET_MEMBER_TEST_SAMPLE_DATA)) {
172 		/* test_k is from the sample data from A.2 in the CSIS spec */
173 		static const uint8_t test_k[] = {
174 			/* Sample data is in big-endian, we need it in little-endian. */
175 			REVERSE_ARGS(0x67, 0x6e, 0x1b, 0x9b,
176 				     0xd4, 0x48, 0x69, 0x6f,
177 				     0x06, 0x1e, 0xc6, 0x22,
178 				     0x3c, 0xe5, 0xce, 0xd9) };
179 		LOG_DBG("Encrypting test SIRK");
180 		k = test_k;
181 	} else {
182 		if (conn == NULL) {
183 			return -EINVAL;
184 		}
185 
186 		k = conn->le.keys->ltk.val;
187 	}
188 
189 	err = bt_csip_sef(k, sirk->value, enc_sirk->value);
190 
191 	if (err != 0) {
192 		return err;
193 	}
194 
195 	enc_sirk->type = BT_CSIP_SIRK_TYPE_ENCRYPTED;
196 
197 	return 0;
198 }
199 
generate_prand(uint8_t dest[BT_CSIP_CRYPTO_PRAND_SIZE])200 static int generate_prand(uint8_t dest[BT_CSIP_CRYPTO_PRAND_SIZE])
201 {
202 	bool valid = false;
203 
204 	do {
205 		int res;
206 		uint32_t prand;
207 
208 		*dest = 0;
209 		res = bt_rand(dest, BT_CSIP_CRYPTO_PRAND_SIZE);
210 		if (res != 0) {
211 			return res;
212 		}
213 
214 		/* Validate Prand: Must contain both a 1 and a 0 */
215 		prand = sys_get_le24(dest);
216 		if (prand != 0 && prand != 0x3FFFFF) {
217 			valid = true;
218 		}
219 	} while (!valid);
220 
221 	dest[BT_CSIP_CRYPTO_PRAND_SIZE - 1] &= 0x3F;
222 	dest[BT_CSIP_CRYPTO_PRAND_SIZE - 1] |= BIT(6);
223 
224 	return 0;
225 }
226 
bt_csip_set_member_generate_rsi(const struct bt_csip_set_member_svc_inst * svc_inst,uint8_t rsi[BT_CSIP_RSI_SIZE])227 int bt_csip_set_member_generate_rsi(const struct bt_csip_set_member_svc_inst *svc_inst,
228 				    uint8_t rsi[BT_CSIP_RSI_SIZE])
229 {
230 	int res = 0;
231 	uint8_t prand[BT_CSIP_CRYPTO_PRAND_SIZE];
232 	uint8_t hash[BT_CSIP_CRYPTO_HASH_SIZE];
233 
234 	if (IS_ENABLED(CONFIG_BT_CSIP_SET_MEMBER_TEST_SAMPLE_DATA)) {
235 		/* prand is from the sample data from A.2 in the CSIS spec */
236 		sys_put_le24(0x69f563, prand);
237 	} else {
238 		res = generate_prand(prand);
239 
240 		if (res != 0) {
241 			LOG_WRN("Could not generate new prand");
242 			return res;
243 		}
244 	}
245 
246 	res = bt_csip_sih(svc_inst->sirk.value, prand, hash);
247 	if (res != 0) {
248 		LOG_WRN("Could not generate new RSI");
249 		return res;
250 	}
251 
252 	(void)memcpy(rsi, hash, BT_CSIP_CRYPTO_HASH_SIZE);
253 	(void)memcpy(rsi + BT_CSIP_CRYPTO_HASH_SIZE, prand, BT_CSIP_CRYPTO_PRAND_SIZE);
254 
255 	return res;
256 }
257 
read_sirk(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)258 static ssize_t read_sirk(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf,
259 			 uint16_t len, uint16_t offset)
260 {
261 	struct bt_csip_sirk enc_sirk;
262 	struct bt_csip_sirk *sirk;
263 	struct bt_csip_set_member_svc_inst *svc_inst = BT_AUDIO_CHRC_USER_DATA(attr);
264 
265 	if (svc_inst->cb != NULL && svc_inst->cb->sirk_read_req != NULL) {
266 		ssize_t gatt_err = BT_GATT_ERR(BT_ATT_ERR_SUCCESS);
267 		uint8_t cb_rsp;
268 
269 		/* Ask higher layer for what SIRK to return, if any */
270 		cb_rsp = svc_inst->cb->sirk_read_req(conn, &svc_insts[0]);
271 
272 		if (cb_rsp == BT_CSIP_READ_SIRK_REQ_RSP_ACCEPT) {
273 			sirk = &svc_inst->sirk;
274 		} else if (IS_ENABLED(CONFIG_BT_CSIP_SET_MEMBER_ENC_SIRK_SUPPORT) &&
275 			   cb_rsp == BT_CSIP_READ_SIRK_REQ_RSP_ACCEPT_ENC) {
276 			int err;
277 
278 			err = sirk_encrypt(conn, &svc_inst->sirk, &enc_sirk);
279 			if (err != 0) {
280 				LOG_ERR("Could not encrypt SIRK: %d",
281 					err);
282 				gatt_err = BT_GATT_ERR(BT_ATT_ERR_UNLIKELY);
283 			} else {
284 				sirk = &enc_sirk;
285 				LOG_HEXDUMP_DBG(enc_sirk.value, sizeof(enc_sirk.value),
286 						"Encrypted SIRK");
287 			}
288 		} else if (cb_rsp == BT_CSIP_READ_SIRK_REQ_RSP_REJECT) {
289 			gatt_err = BT_GATT_ERR(BT_ATT_ERR_AUTHORIZATION);
290 		} else if (cb_rsp == BT_CSIP_READ_SIRK_REQ_RSP_OOB_ONLY) {
291 			gatt_err = BT_GATT_ERR(BT_CSIP_ERROR_SIRK_OOB_ONLY);
292 		} else {
293 			LOG_ERR("Invalid callback response: %u", cb_rsp);
294 			gatt_err = BT_GATT_ERR(BT_ATT_ERR_UNLIKELY);
295 		}
296 
297 		if (gatt_err != BT_GATT_ERR(BT_ATT_ERR_SUCCESS)) {
298 			return gatt_err;
299 		}
300 	} else {
301 		sirk = &svc_inst->sirk;
302 	}
303 
304 	LOG_DBG("SIRK %sencrypted", sirk->type == BT_CSIP_SIRK_TYPE_PLAIN ? "not " : "");
305 	LOG_HEXDUMP_DBG(svc_inst->sirk.value, sizeof(svc_inst->sirk.value), "SIRK");
306 	return bt_gatt_attr_read(conn, attr, buf, len, offset,
307 				 sirk, sizeof(*sirk));
308 }
309 
310 #if defined(CONFIG_BT_CSIP_SET_MEMBER_SIRK_NOTIFIABLE)
sirk_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)311 static void sirk_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
312 {
313 	LOG_DBG("value 0x%04x", value);
314 }
315 #endif /* CONFIG_BT_CSIP_SET_MEMBER_SIRK_NOTIFIABLE */
316 
read_set_size(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)317 static ssize_t read_set_size(struct bt_conn *conn,
318 			     const struct bt_gatt_attr *attr,
319 			     void *buf, uint16_t len, uint16_t offset)
320 {
321 	struct bt_csip_set_member_svc_inst *svc_inst = BT_AUDIO_CHRC_USER_DATA(attr);
322 
323 	LOG_DBG("%u", svc_inst->set_size);
324 
325 	return bt_gatt_attr_read(conn, attr, buf, len, offset,
326 				 &svc_inst->set_size,
327 				 sizeof(svc_inst->set_size));
328 }
329 
330 #if defined(CONFIG_BT_CSIP_SET_MEMBER_SIZE_NOTIFIABLE)
set_size_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)331 static void set_size_cfg_changed(const struct bt_gatt_attr *attr,
332 				 uint16_t value)
333 {
334 	LOG_DBG("value 0x%04x", value);
335 }
336 #endif /* CONFIG_BT_CSIP_SET_MEMBER_SIZE_NOTIFIABLE */
337 
read_set_lock(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)338 static ssize_t read_set_lock(struct bt_conn *conn,
339 			     const struct bt_gatt_attr *attr,
340 			     void *buf, uint16_t len, uint16_t offset)
341 {
342 	struct bt_csip_set_member_svc_inst *svc_inst = BT_AUDIO_CHRC_USER_DATA(attr);
343 
344 	LOG_DBG("%u", svc_inst->set_lock);
345 
346 	return bt_gatt_attr_read(conn, attr, buf, len, offset,
347 				 &svc_inst->set_lock,
348 				 sizeof(svc_inst->set_lock));
349 }
350 
351 /**
352  * @brief Set the lock value of a CSIP instance.
353  *
354  * @param conn      The connection locking the instance.
355  *                  Will be NULL if the server locally sets the lock.
356  * @param svc_inst  The CSIP instance to change the lock value of
357  * @param val       The lock value (BT_CSIP_LOCK_VALUE or BT_CSIP_RELEASE_VALUE)
358  *
359  * @return BT_CSIP_ERROR_* on failure or 0 if success
360  */
set_lock(struct bt_conn * conn,struct bt_csip_set_member_svc_inst * svc_inst,uint8_t val)361 static uint8_t set_lock(struct bt_conn *conn,
362 			struct bt_csip_set_member_svc_inst *svc_inst,
363 			uint8_t val)
364 {
365 	bool notify;
366 
367 	if (val != BT_CSIP_RELEASE_VALUE && val != BT_CSIP_LOCK_VALUE) {
368 		return BT_CSIP_ERROR_LOCK_INVAL_VALUE;
369 	}
370 
371 	if (svc_inst->set_lock == BT_CSIP_LOCK_VALUE) {
372 		if (val == BT_CSIP_LOCK_VALUE) {
373 			if (is_last_client_to_write(svc_inst, conn)) {
374 				return BT_CSIP_ERROR_LOCK_ALREADY_GRANTED;
375 			} else {
376 				return BT_CSIP_ERROR_LOCK_DENIED;
377 			}
378 		} else if (!is_last_client_to_write(svc_inst, conn)) {
379 			return BT_CSIP_ERROR_LOCK_RELEASE_DENIED;
380 		}
381 	}
382 
383 	notify = svc_inst->set_lock != val;
384 
385 	svc_inst->set_lock = val;
386 	if (svc_inst->set_lock == BT_CSIP_LOCK_VALUE) {
387 		if (conn != NULL) {
388 			bt_addr_le_copy(&svc_inst->lock_client_addr,
389 					bt_conn_get_dst(conn));
390 		}
391 		(void)k_work_reschedule(&svc_inst->set_lock_timer,
392 					CSIP_SET_LOCK_TIMER_VALUE);
393 	} else {
394 		bt_addr_le_copy(&svc_inst->lock_client_addr, BT_ADDR_LE_NONE);
395 		(void)k_work_cancel_delayable(&svc_inst->set_lock_timer);
396 	}
397 
398 	LOG_DBG("%u", svc_inst->set_lock);
399 
400 	if (notify) {
401 		/*
402 		 * The Spec states that all clients, except for the
403 		 * client writing the value, shall be notified
404 		 * (if subscribed)
405 		 */
406 		notify_clients(svc_inst, conn, FLAG_NOTIFY_LOCK);
407 
408 		if (svc_inst->cb != NULL && svc_inst->cb->lock_changed != NULL) {
409 			bool locked = svc_inst->set_lock == BT_CSIP_LOCK_VALUE;
410 
411 			svc_inst->cb->lock_changed(conn, svc_inst, locked);
412 		}
413 	}
414 
415 	return 0;
416 }
417 
write_set_lock(struct bt_conn * conn,const struct bt_gatt_attr * attr,const void * buf,uint16_t len,uint16_t offset,uint8_t flags)418 static ssize_t write_set_lock(struct bt_conn *conn,
419 			      const struct bt_gatt_attr *attr,
420 			      const void *buf, uint16_t len,
421 			      uint16_t offset, uint8_t flags)
422 {
423 	ssize_t res;
424 	uint8_t val;
425 	struct bt_csip_set_member_svc_inst *svc_inst = BT_AUDIO_CHRC_USER_DATA(attr);
426 
427 	if (offset != 0) {
428 		return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
429 	} else if (len != sizeof(val)) {
430 		return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
431 	}
432 
433 	(void)memcpy(&val, buf, len);
434 
435 	res = set_lock(conn, svc_inst, val);
436 	if (res != BT_ATT_ERR_SUCCESS) {
437 		return BT_GATT_ERR(res);
438 	}
439 
440 	return len;
441 }
442 
set_lock_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)443 static void set_lock_cfg_changed(const struct bt_gatt_attr *attr,
444 				 uint16_t value)
445 {
446 	LOG_DBG("value 0x%04x", value);
447 }
448 
read_rank(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)449 static ssize_t read_rank(struct bt_conn *conn, const struct bt_gatt_attr *attr,
450 			 void *buf, uint16_t len, uint16_t offset)
451 {
452 	struct bt_csip_set_member_svc_inst *svc_inst = BT_AUDIO_CHRC_USER_DATA(attr);
453 
454 	LOG_DBG("%u", svc_inst->rank);
455 
456 	return bt_gatt_attr_read(conn, attr, buf, len, offset,
457 				 &svc_inst->rank,
458 				 sizeof(svc_inst->rank));
459 
460 }
461 
set_lock_timer_handler(struct k_work * work)462 static void set_lock_timer_handler(struct k_work *work)
463 {
464 	struct k_work_delayable *delayable;
465 	struct bt_csip_set_member_svc_inst *svc_inst;
466 
467 	delayable = k_work_delayable_from_work(work);
468 	svc_inst = CONTAINER_OF(delayable, struct bt_csip_set_member_svc_inst,
469 				set_lock_timer);
470 
471 	LOG_DBG("Lock timeout, releasing");
472 	svc_inst->set_lock = BT_CSIP_RELEASE_VALUE;
473 	notify_clients(svc_inst, NULL, FLAG_NOTIFY_LOCK);
474 
475 	if (svc_inst->cb != NULL && svc_inst->cb->lock_changed != NULL) {
476 		bool locked = svc_inst->set_lock == BT_CSIP_LOCK_VALUE;
477 
478 		svc_inst->cb->lock_changed(NULL, svc_inst, locked);
479 	}
480 }
481 
csip_security_changed(struct bt_conn * conn,bt_security_t level,enum bt_security_err err)482 static void csip_security_changed(struct bt_conn *conn, bt_security_t level,
483 				  enum bt_security_err err)
484 {
485 	const bt_addr_le_t *peer_addr;
486 
487 	if (err != 0 || conn->encrypt == 0) {
488 		return;
489 	}
490 
491 	peer_addr = bt_conn_get_dst(conn);
492 
493 	if (!bt_le_bond_exists(conn->id, &conn->le.dst)) {
494 		return;
495 	}
496 
497 	for (size_t i = 0U; i < ARRAY_SIZE(svc_insts); i++) {
498 		struct bt_csip_set_member_svc_inst *svc_inst = &svc_insts[i];
499 		struct csip_client *client;
500 		bool found = false;
501 
502 		/* Check if client is already in the active list */
503 		for (size_t j = 0U; j < ARRAY_SIZE(svc_inst->clients); j++) {
504 			client = &svc_inst->clients[j];
505 
506 			if (atomic_test_bit(client->flags, FLAG_ACTIVE) &&
507 			    bt_addr_le_eq(peer_addr, &client->addr)) {
508 				found = true;
509 				break;
510 			}
511 		}
512 
513 		/* If not found, add the bonded address to the client list */
514 		if (!found) {
515 			const struct bt_bond_info bond_info = {
516 				.addr = *peer_addr
517 			};
518 
519 			add_bonded_addr_to_client_list(&bond_info, NULL);
520 			return;
521 		}
522 
523 		/* Check if client is set with FLAG_NOTIFY_LOCK */
524 		if (atomic_test_bit(client->flags, FLAG_NOTIFY_LOCK)) {
525 			notify_work_reschedule(K_NO_WAIT);
526 			break;
527 		}
528 	}
529 }
530 
handle_csip_disconnect(struct bt_csip_set_member_svc_inst * svc_inst,struct bt_conn * conn)531 static void handle_csip_disconnect(struct bt_csip_set_member_svc_inst *svc_inst,
532 				   struct bt_conn *conn)
533 {
534 	LOG_DBG("Non-bonded device");
535 	if (is_last_client_to_write(svc_inst, conn)) {
536 		bt_addr_le_copy(&svc_inst->lock_client_addr, BT_ADDR_LE_NONE);
537 		svc_inst->set_lock = BT_CSIP_RELEASE_VALUE;
538 		notify_clients(svc_inst, NULL, FLAG_NOTIFY_LOCK);
539 
540 		if (svc_inst->cb != NULL && svc_inst->cb->lock_changed != NULL) {
541 			bool locked = svc_inst->set_lock == BT_CSIP_LOCK_VALUE;
542 
543 			svc_inst->cb->lock_changed(conn, svc_inst, locked);
544 		}
545 	}
546 
547 	/* Check if the disconnected device once was bonded and stored
548 	 * here as a bonded device
549 	 */
550 	for (size_t i = 0U; i < ARRAY_SIZE(svc_inst->clients); i++) {
551 		struct csip_client *client;
552 
553 		client = &svc_inst->clients[i];
554 
555 		if (bt_addr_le_eq(bt_conn_get_dst(conn), &client->addr)) {
556 			(void)memset(client, 0, sizeof(*client));
557 			break;
558 		}
559 	}
560 }
561 
csip_disconnected(struct bt_conn * conn,uint8_t reason)562 static void csip_disconnected(struct bt_conn *conn, uint8_t reason)
563 {
564 	LOG_DBG("Disconnected: %s (reason %u)", bt_addr_le_str(bt_conn_get_dst(conn)), reason);
565 
566 	if (!bt_le_bond_exists(conn->id, &conn->le.dst)) {
567 		for (size_t i = 0U; i < ARRAY_SIZE(svc_insts); i++) {
568 			handle_csip_disconnect(&svc_insts[i], conn);
569 		}
570 	}
571 }
572 
handle_csip_auth_complete(struct bt_csip_set_member_svc_inst * svc_inst,struct bt_conn * conn)573 static void handle_csip_auth_complete(struct bt_csip_set_member_svc_inst *svc_inst,
574 				      struct bt_conn *conn)
575 {
576 	/* Check if already in list, and do nothing if it is */
577 	for (size_t i = 0U; i < ARRAY_SIZE(svc_inst->clients); i++) {
578 		struct csip_client *client;
579 
580 		client = &svc_inst->clients[i];
581 
582 		if (atomic_test_bit(client->flags, FLAG_ACTIVE) &&
583 		    bt_addr_le_eq(bt_conn_get_dst(conn), &client->addr)) {
584 			return;
585 		}
586 	}
587 
588 	/* Else add the device */
589 	for (size_t i = 0U; i < ARRAY_SIZE(svc_inst->clients); i++) {
590 		struct csip_client *client;
591 
592 		client = &svc_inst->clients[i];
593 
594 		if (!atomic_test_bit(client->flags, FLAG_ACTIVE)) {
595 			atomic_set_bit(client->flags, FLAG_ACTIVE);
596 			memcpy(&client->addr, bt_conn_get_dst(conn), sizeof(bt_addr_le_t));
597 
598 			/* Send out all pending notifications */
599 			notify_work_reschedule(K_NO_WAIT);
600 			return;
601 		}
602 	}
603 
604 	LOG_WRN("Could not add device to pending notification list");
605 }
606 
auth_pairing_complete(struct bt_conn * conn,bool bonded)607 static void auth_pairing_complete(struct bt_conn *conn, bool bonded)
608 {
609 	/**
610 	 * If a pairing is complete for a bonded device, then we
611 	 * 1) Store the connection pointer to later validate SIRK encryption
612 	 * 2) Check if the device is already in the `clients`, and if it is
613 	 * not, then we
614 	 * 3) Check if there's room for another device in the `clients`
615 	 *    array. If there are no more room for a new device, then
616 	 * 4) Either we ignore this new device (bad luck), or we overwrite
617 	 *    the oldest entry, following the behavior of the key storage.
618 	 */
619 
620 	LOG_DBG("%s paired (%sbonded)", bt_addr_le_str(bt_conn_get_dst(conn)),
621 		bonded ? "" : "not ");
622 
623 	if (!bonded) {
624 		return;
625 	}
626 
627 	for (size_t i = 0U; i < ARRAY_SIZE(svc_insts); i++) {
628 		handle_csip_auth_complete(&svc_insts[i], conn);
629 	}
630 }
631 
csip_bond_deleted(uint8_t id,const bt_addr_le_t * peer)632 static void csip_bond_deleted(uint8_t id, const bt_addr_le_t *peer)
633 {
634 	for (size_t i = 0U; i < ARRAY_SIZE(svc_insts); i++) {
635 		struct bt_csip_set_member_svc_inst *svc_inst = &svc_insts[i];
636 
637 		for (size_t j = 0U; j < ARRAY_SIZE(svc_inst->clients); j++) {
638 
639 			/* Check if match, and if active, if so, reset */
640 			if (atomic_test_bit(svc_inst->clients[i].flags, FLAG_ACTIVE) &&
641 			    bt_addr_le_eq(peer, &svc_inst->clients[i].addr)) {
642 				atomic_clear(svc_inst->clients[i].flags);
643 				(void)memset(&svc_inst->clients[i].addr, 0, sizeof(bt_addr_le_t));
644 				break;
645 			}
646 		}
647 	}
648 }
649 
650 BT_CONN_CB_DEFINE(conn_callbacks) = {
651 	.disconnected = csip_disconnected,
652 	.security_changed = csip_security_changed,
653 };
654 
655 static struct bt_conn_auth_info_cb auth_callbacks = {
656 	.pairing_complete = auth_pairing_complete,
657 	.bond_deleted = csip_bond_deleted
658 };
659 
660 #if defined(CONFIG_BT_CSIP_SET_MEMBER_SIRK_NOTIFIABLE)
661 #define BT_CSIS_CHR_SIRK(_csip)                                                                    \
662 	BT_AUDIO_CHRC(BT_UUID_CSIS_SIRK, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,                  \
663 		      BT_GATT_PERM_READ_ENCRYPT, read_sirk, NULL, &_csip),                         \
664 		BT_AUDIO_CCC(sirk_cfg_changed)
665 #else
666 #define BT_CSIS_CHR_SIRK(_csip)                                                                    \
667 	BT_AUDIO_CHRC(BT_UUID_CSIS_SIRK, BT_GATT_CHRC_READ, BT_GATT_PERM_READ_ENCRYPT, read_sirk,  \
668 		      NULL, &_csip)
669 #endif /* CONFIG_BT_CSIP_SET_MEMBER_SIRK_NOTIFIABLE */
670 
671 #if defined(CONFIG_BT_CSIP_SET_MEMBER_SIZE_NOTIFIABLE)
672 #define BT_CSIS_CHR_SIZE(_csip)                                                                    \
673 	BT_AUDIO_CHRC(BT_UUID_CSIS_SET_SIZE, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,              \
674 		      BT_GATT_PERM_READ_ENCRYPT, read_set_size, NULL, &_csip),                     \
675 		BT_AUDIO_CCC(set_size_cfg_changed)
676 #else
677 #define BT_CSIS_CHR_SIZE(_csip)                                                                    \
678 	BT_AUDIO_CHRC(BT_UUID_CSIS_SET_SIZE, BT_GATT_CHRC_READ, BT_GATT_PERM_READ_ENCRYPT,         \
679 		      read_set_size, NULL, &_csip)
680 #endif /* CONFIG_BT_CSIP_SET_MEMBER_SIZE_NOTIFIABLE */
681 
682 #define BT_CSIP_SERVICE_DEFINITION(_csip) {\
683 	BT_GATT_PRIMARY_SERVICE(BT_UUID_CSIS), \
684 	BT_CSIS_CHR_SIRK(_csip), \
685 	BT_CSIS_CHR_SIZE(_csip), \
686 	BT_AUDIO_CHRC(BT_UUID_CSIS_SET_LOCK, \
687 		      BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY | BT_GATT_CHRC_WRITE, \
688 		      BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT, \
689 		      read_set_lock, write_set_lock, &_csip), \
690 	BT_AUDIO_CCC(set_lock_cfg_changed), \
691 	BT_AUDIO_CHRC(BT_UUID_CSIS_RANK, \
692 		      BT_GATT_CHRC_READ, \
693 		      BT_GATT_PERM_READ_ENCRYPT, \
694 		      read_rank, NULL, &_csip) \
695 	}
696 
697 BT_GATT_SERVICE_INSTANCE_DEFINE(csip_set_member_service_list, svc_insts,
698 				CONFIG_BT_CSIP_SET_MEMBER_MAX_INSTANCE_COUNT,
699 				BT_CSIP_SERVICE_DEFINITION);
700 
701 /****************************** Public API ******************************/
bt_csip_set_member_svc_decl_get(const struct bt_csip_set_member_svc_inst * svc_inst)702 void *bt_csip_set_member_svc_decl_get(const struct bt_csip_set_member_svc_inst *svc_inst)
703 {
704 	if (svc_inst == NULL || svc_inst->service_p == NULL) {
705 		return NULL;
706 	}
707 
708 	return svc_inst->service_p->attrs;
709 }
710 
valid_register_param(const struct bt_csip_set_member_register_param * param)711 static bool valid_register_param(const struct bt_csip_set_member_register_param *param)
712 {
713 	if (param->lockable && param->rank == 0) {
714 		LOG_DBG("Rank cannot be 0 if service is lockable");
715 		return false;
716 	}
717 
718 	if (param->rank > 0 && param->set_size > 0 && param->rank > param->set_size) {
719 		LOG_DBG("Invalid rank: %u (shall be less than or equal to set_size: %u)",
720 			param->rank, param->set_size);
721 		return false;
722 	}
723 
724 #if CONFIG_BT_CSIP_SET_MEMBER_MAX_INSTANCE_COUNT > 1
725 	if (param->parent == NULL) {
726 		LOG_DBG("Parent service not provided");
727 		return false;
728 	}
729 #endif /* CONFIG_BT_CSIP_SET_MEMBER_MAX_INSTANCE_COUNT > 1 */
730 
731 	return true;
732 }
733 
remove_csis_char(const struct bt_uuid * uuid,struct bt_gatt_service * svc)734 static void remove_csis_char(const struct bt_uuid *uuid, struct bt_gatt_service *svc)
735 {
736 	size_t attrs_to_rem;
737 
738 	/* Rank does not have any CCCD */
739 	if (bt_uuid_cmp(uuid, BT_UUID_CSIS_RANK) == 0) {
740 		attrs_to_rem = CSIS_RANK_CHAR_ATTR_COUNT;
741 	} else {
742 		attrs_to_rem = CSIS_CHAR_ATTR_COUNT;
743 	}
744 
745 	/* Start at index 4 as the first 4 attributes are mandatory */
746 	for (size_t i = 4U; i < svc->attr_count; i++) {
747 		if (bt_uuid_cmp(svc->attrs[i].uuid, uuid) == 0) {
748 			/* Remove the characteristic declaration, the characteristic value and
749 			 * potentially the CCCD. The value declaration will be a i - 1, the
750 			 * characteristic value at i and the CCCD is potentially at i + 1
751 			 */
752 
753 			/* We use attrs_to_rem to determine whether there is a CCCD after the
754 			 * characteristic value or not, which then determines if this is the last
755 			 * characteristic or not
756 			 */
757 			if (i == (svc->attr_count - (attrs_to_rem - 1))) {
758 				/* This is the last characteristic in the service: just decrement
759 				 * the attr_count by number of attributes to remove
760 				 * (CSIS_CHAR_ATTR_COUNT)
761 				 */
762 			} else {
763 				/* Move all following attributes attrs_to_rem locations "up" */
764 				for (size_t j = i - 1U; j < svc->attr_count - attrs_to_rem; j++) {
765 					svc->attrs[j] = svc->attrs[j + attrs_to_rem];
766 				}
767 			}
768 
769 			svc->attr_count -= attrs_to_rem;
770 
771 			return;
772 		}
773 	}
774 
775 	__ASSERT(false, "Failed to remove CSIS char %s", bt_uuid_str(uuid));
776 }
777 
notify(struct bt_csip_set_member_svc_inst * svc_inst,struct bt_conn * conn,const struct bt_uuid * uuid,const void * data,uint16_t len)778 static void notify(struct bt_csip_set_member_svc_inst *svc_inst, struct bt_conn *conn,
779 		   const struct bt_uuid *uuid, const void *data, uint16_t len)
780 {
781 	int err;
782 	const struct bt_gatt_attr *attr;
783 
784 	attr = bt_gatt_find_by_uuid(
785 		svc_inst->service_p->attrs,
786 		svc_inst->service_p->attr_count,
787 		uuid);
788 
789 	if (attr == NULL) {
790 		LOG_WRN("Attribute for UUID %p not found", uuid);
791 		return;
792 	}
793 
794 	if (!bt_gatt_is_subscribed(conn, attr, BT_GATT_CCC_NOTIFY)) {
795 		LOG_DBG("Connection %p not subscribed to UUID %p", conn, uuid);
796 		return;
797 	}
798 
799 	err = bt_gatt_notify(conn, attr, data, len);
800 	if (err) {
801 		if (err == -ENOTCONN) {
802 			LOG_DBG("Notification error: ENOTCONN (%d)", err);
803 		} else {
804 			LOG_ERR("Notification error: %d", err);
805 		}
806 	}
807 }
808 
notify_cb(struct bt_conn * conn,void * data)809 static void notify_cb(struct bt_conn *conn, void *data)
810 {
811 	struct bt_conn_info info;
812 	int err = 0;
813 
814 	err = bt_conn_get_info(conn, &info);
815 	if (err != 0) {
816 		return;
817 	}
818 
819 	if (info.state != BT_CONN_STATE_CONNECTED) {
820 		/* Not connected */
821 		LOG_DBG("Not connected: %u", info.state);
822 		return;
823 	}
824 
825 	for (size_t i = 0U; i < ARRAY_SIZE(svc_insts); i++) {
826 		struct bt_csip_set_member_svc_inst *svc_inst = &svc_insts[i];
827 		struct csip_client *client;
828 		bool client_found = false;
829 
830 		err = k_mutex_lock(&svc_inst->mutex, K_NO_WAIT);
831 		if (err != 0) {
832 			LOG_DBG("Mutex lock failed (%d) for svc_inst[%zu], rescheduling", err, i);
833 			notify_work_reschedule(K_USEC(BT_AUDIO_NOTIFY_RETRY_DELAY_US));
834 			continue;
835 		}
836 
837 		if (svc_inst->service_p == NULL || svc_inst->service_p->attrs == NULL) {
838 			goto unlock_and_return;
839 		}
840 
841 		/* find the client object for the connection */
842 		for (size_t j = 0U; j < ARRAY_SIZE(svc_inst->clients); j++) {
843 
844 			client = &svc_inst->clients[j];
845 
846 			if (atomic_test_bit(client->flags, FLAG_ACTIVE) &&
847 			    bt_addr_le_eq(bt_conn_get_dst(conn), &client->addr)) {
848 				client_found = true;
849 				break;
850 			}
851 		}
852 
853 		if (client_found == false) {
854 			goto unlock_and_return;
855 		}
856 
857 		if (atomic_test_and_clear_bit(client->flags, FLAG_NOTIFY_LOCK)) {
858 			notify(svc_inst, conn, BT_UUID_CSIS_SET_LOCK, &svc_inst->set_lock,
859 			       sizeof(svc_inst->set_lock));
860 		}
861 
862 		if (IS_ENABLED(CONFIG_BT_CSIP_SET_MEMBER_SIRK_NOTIFIABLE) &&
863 		    atomic_test_and_clear_bit(client->flags, FLAG_NOTIFY_SIRK)) {
864 			notify(svc_inst, conn, BT_UUID_CSIS_SIRK, &svc_inst->sirk,
865 			       sizeof(svc_inst->sirk));
866 		}
867 
868 		if (IS_ENABLED(CONFIG_BT_CSIP_SET_MEMBER_SIZE_NOTIFIABLE) &&
869 		    atomic_test_and_clear_bit(client->flags, FLAG_NOTIFY_SIZE)) {
870 			notify(svc_inst, conn, BT_UUID_CSIS_SET_SIZE, &svc_inst->set_size,
871 			       sizeof(svc_inst->set_size));
872 		}
873 
874 unlock_and_return:
875 		err = k_mutex_unlock(&svc_inst->mutex);
876 		__ASSERT(err == 0, "Failed to unlock mutex: %d", err);
877 	}
878 }
879 
deferred_nfy_work_handler(struct k_work * work)880 static void deferred_nfy_work_handler(struct k_work *work)
881 {
882 	bt_conn_foreach(BT_CONN_TYPE_LE, notify_cb, NULL);
883 }
884 
add_bonded_addr_to_client_list(const struct bt_bond_info * info,void * data)885 static void add_bonded_addr_to_client_list(const struct bt_bond_info *info, void *data)
886 {
887 
888 	for (size_t i = 0U; i < ARRAY_SIZE(svc_insts); i++) {
889 		struct bt_csip_set_member_svc_inst *svc_inst = &svc_insts[i];
890 
891 		for (size_t j = 0U; j < ARRAY_SIZE(svc_inst->clients); j++) {
892 			/* Check if device is registered, it not, add it */
893 			if (!atomic_test_bit(svc_inst->clients[j].flags, FLAG_ACTIVE)) {
894 				char addr_str[BT_ADDR_LE_STR_LEN];
895 
896 				atomic_set_bit(svc_inst->clients[j].flags, FLAG_ACTIVE);
897 				memcpy(&svc_inst->clients[j].addr, &info->addr,
898 				       sizeof(bt_addr_le_t));
899 				bt_addr_le_to_str(&svc_inst->clients[j].addr, addr_str,
900 						  sizeof(addr_str));
901 				LOG_DBG("Added %s to bonded list\n", addr_str);
902 				return;
903 			}
904 		}
905 	}
906 }
907 
bt_csip_set_member_register(const struct bt_csip_set_member_register_param * param,struct bt_csip_set_member_svc_inst ** svc_inst)908 int bt_csip_set_member_register(const struct bt_csip_set_member_register_param *param,
909 				struct bt_csip_set_member_svc_inst **svc_inst)
910 {
911 	static bool first_register;
912 	struct bt_csip_set_member_svc_inst *inst;
913 	int err;
914 
915 	CHECKIF(param == NULL) {
916 		LOG_DBG("NULL param");
917 		return -EINVAL;
918 	}
919 
920 	CHECKIF(!valid_register_param(param)) {
921 		LOG_DBG("Invalid parameters");
922 		return -EINVAL;
923 	}
924 
925 	if (!first_register) {
926 		for (size_t i = 0U; i < ARRAY_SIZE(svc_insts); i++) {
927 			k_mutex_init(&svc_insts[i].mutex);
928 		}
929 		bt_conn_auth_info_cb_register(&auth_callbacks);
930 		first_register = true;
931 	}
932 
933 	inst = NULL;
934 	ARRAY_FOR_EACH(svc_insts, i) {
935 		if (svc_insts[i].service_p == NULL) {
936 			inst = &svc_insts[i];
937 
938 			err = k_mutex_lock(&inst->mutex, K_NO_WAIT);
939 			if (err != 0) {
940 				/* Try the next */
941 				continue;
942 			}
943 
944 			inst->service_p = &csip_set_member_service_list[i];
945 			break;
946 		}
947 	}
948 
949 	if (inst == NULL) {
950 		LOG_DBG("Too many set member registrations");
951 		return -ENOMEM;
952 	}
953 
954 	/* The removal of the optional characteristics should be done in reverse order of the order
955 	 * in BT_CSIP_SERVICE_DEFINITION, as that improves the performance of remove_csis_char,
956 	 * since it's easier to remove the last characteristic
957 	 */
958 	if (param->rank == 0U) {
959 		remove_csis_char(BT_UUID_CSIS_RANK, inst->service_p);
960 	}
961 
962 	if (param->set_size == 0U) {
963 		remove_csis_char(BT_UUID_CSIS_SET_SIZE, inst->service_p);
964 	}
965 
966 	if (!param->lockable) {
967 		remove_csis_char(BT_UUID_CSIS_SET_LOCK, inst->service_p);
968 	}
969 
970 	err = bt_gatt_service_register(inst->service_p);
971 	if (err != 0) {
972 		int mutex_err;
973 
974 		LOG_DBG("CSIS service register failed: %d", err);
975 		mutex_err = k_mutex_unlock(&inst->mutex);
976 		__ASSERT(mutex_err == 0, "Failed to unlock mutex: %d", mutex_err);
977 		return err;
978 	}
979 
980 	k_work_init_delayable(&inst->set_lock_timer,
981 			      set_lock_timer_handler);
982 	inst->rank = param->rank;
983 	inst->set_size = param->set_size;
984 	inst->set_lock = BT_CSIP_RELEASE_VALUE;
985 	inst->sirk.type = BT_CSIP_SIRK_TYPE_PLAIN;
986 	inst->cb = param->cb;
987 	inst->lockable = param->lockable;
988 	bt_addr_le_copy(&inst->lock_client_addr, BT_ADDR_LE_NONE);
989 
990 	if (IS_ENABLED(CONFIG_BT_CSIP_SET_MEMBER_TEST_SAMPLE_DATA)) {
991 		uint8_t test_sirk[] = {
992 			0xcd, 0xcc, 0x72, 0xdd, 0x86, 0x8c, 0xcd, 0xce,
993 			0x22, 0xfd, 0xa1, 0x21, 0x09, 0x7d, 0x7d, 0x45,
994 		};
995 
996 		(void)memcpy(inst->sirk.value, test_sirk, sizeof(test_sirk));
997 		LOG_DBG("CSIP SIRK was overwritten by sample data SIRK");
998 	} else {
999 		(void)memcpy(inst->sirk.value, param->sirk, sizeof(inst->sirk.value));
1000 	}
1001 
1002 	*svc_inst = inst;
1003 
1004 	err = k_mutex_unlock(&inst->mutex);
1005 	__ASSERT(err == 0, "Failed to unlock mutex: %d", err);
1006 
1007 	return 0;
1008 }
1009 
bt_csip_set_member_unregister(struct bt_csip_set_member_svc_inst * svc_inst)1010 int bt_csip_set_member_unregister(struct bt_csip_set_member_svc_inst *svc_inst)
1011 {
1012 	int err;
1013 
1014 	CHECKIF(svc_inst == NULL) {
1015 		LOG_DBG("NULL svc_inst");
1016 		return -EINVAL;
1017 	}
1018 
1019 	err = k_mutex_lock(&svc_inst->mutex, K_NO_WAIT);
1020 	if (err != 0) {
1021 		LOG_DBG("Failed to lock mutex");
1022 		return -EBUSY;
1023 	}
1024 
1025 	err = bt_gatt_service_unregister(svc_inst->service_p);
1026 	if (err != 0) {
1027 		int mutex_err;
1028 
1029 		LOG_DBG("CSIS service unregister failed: %d", err);
1030 		mutex_err = k_mutex_unlock(&svc_inst->mutex);
1031 		__ASSERT(mutex_err == 0, "Failed to unlock mutex: %d", mutex_err);
1032 
1033 		return err;
1034 	}
1035 
1036 	/* Restore original declaration */
1037 
1038 	/* attrs_0 is an array of the original attributes, and while the actual number of attributes
1039 	 * may change, the size of the array stays the same, so we can use that to restore the
1040 	 * original attribute count
1041 	 */
1042 	(void)memcpy(svc_inst->service_p->attrs,
1043 		     (struct bt_gatt_attr[])BT_CSIP_SERVICE_DEFINITION(svc_inst), sizeof(attrs_0));
1044 	svc_inst->service_p->attr_count = ARRAY_SIZE(attrs_0);
1045 
1046 	(void)k_work_cancel_delayable(&svc_inst->set_lock_timer);
1047 
1048 	memset(svc_inst, 0, offsetof(struct bt_csip_set_member_svc_inst, mutex));
1049 
1050 	err = k_mutex_unlock(&svc_inst->mutex);
1051 	__ASSERT(err == 0, "Failed to unlock mutex: %d", err);
1052 
1053 	return 0;
1054 }
1055 
bt_csip_set_member_sirk(struct bt_csip_set_member_svc_inst * svc_inst,const uint8_t sirk[BT_CSIP_SIRK_SIZE])1056 int bt_csip_set_member_sirk(struct bt_csip_set_member_svc_inst *svc_inst,
1057 			    const uint8_t sirk[BT_CSIP_SIRK_SIZE])
1058 {
1059 	CHECKIF(svc_inst == NULL) {
1060 		LOG_DBG("NULL svc_inst");
1061 		return -EINVAL;
1062 	}
1063 
1064 	CHECKIF(sirk == NULL) {
1065 		LOG_DBG("NULL SIRK");
1066 		return -EINVAL;
1067 	}
1068 
1069 	if (memcmp(sirk, svc_inst->sirk.value, BT_CSIP_SIRK_SIZE) != 0) {
1070 		memcpy(svc_inst->sirk.value, sirk, BT_CSIP_SIRK_SIZE);
1071 
1072 		if (IS_ENABLED(CONFIG_BT_CSIP_SET_MEMBER_SIRK_NOTIFIABLE)) {
1073 			notify_clients(svc_inst, NULL, FLAG_NOTIFY_SIRK);
1074 		}
1075 	}
1076 
1077 	return 0;
1078 }
1079 
bt_csip_set_member_set_size_and_rank(struct bt_csip_set_member_svc_inst * svc_inst,uint8_t size,uint8_t rank)1080 int bt_csip_set_member_set_size_and_rank(struct bt_csip_set_member_svc_inst *svc_inst, uint8_t size,
1081 					 uint8_t rank)
1082 {
1083 	if (svc_inst == NULL) {
1084 		LOG_DBG("svc_inst is NULL");
1085 		return -EINVAL;
1086 	}
1087 
1088 	if (size < 1U) {
1089 		LOG_DBG("Invalid set size %u", size);
1090 		return -EINVAL;
1091 	}
1092 
1093 	if (!svc_inst->lockable && rank != 0U) {
1094 		LOG_DBG("Invalid rank %u for non-lockable service", rank);
1095 		return -EINVAL;
1096 	}
1097 
1098 	if (svc_inst->lockable && !IN_RANGE(rank, 1U, size)) {
1099 		LOG_DBG("Invalid rank: %u for size %u", rank, size);
1100 		return -EINVAL;
1101 	}
1102 
1103 	if (svc_inst->set_size == size && svc_inst->rank == rank) {
1104 		LOG_DBG("Set size %u and rank %u is already set", size, rank);
1105 		return -EALREADY;
1106 	}
1107 
1108 	svc_inst->set_size = size;
1109 	svc_inst->rank = svc_inst->lockable ? rank : 0U;
1110 
1111 	if (IS_ENABLED(CONFIG_BT_CSIP_SET_MEMBER_SIZE_NOTIFIABLE)) {
1112 		notify_clients(svc_inst, NULL, FLAG_NOTIFY_SIZE);
1113 	}
1114 
1115 	return 0;
1116 }
1117 
bt_csip_set_member_get_info(const struct bt_csip_set_member_svc_inst * svc_inst,struct bt_csip_set_member_set_info * info)1118 int bt_csip_set_member_get_info(const struct bt_csip_set_member_svc_inst *svc_inst,
1119 				struct bt_csip_set_member_set_info *info)
1120 {
1121 	if (svc_inst == NULL) {
1122 		LOG_DBG("svc_inst is NULL");
1123 		return -EINVAL;
1124 	}
1125 
1126 	if (info == NULL) {
1127 		LOG_DBG("info is NULL");
1128 		return -EINVAL;
1129 	}
1130 
1131 	info->lockable = svc_inst->lockable;
1132 	info->locked = svc_inst->set_lock == BT_CSIP_LOCK_VALUE;
1133 	info->rank = svc_inst->rank;
1134 	info->set_size = svc_inst->set_size;
1135 	memcpy(info->sirk, svc_inst->sirk.value, BT_CSIP_SIRK_SIZE);
1136 	bt_addr_le_copy(&info->lock_client_addr, &svc_inst->lock_client_addr);
1137 
1138 	return 0;
1139 }
1140 
bt_csip_set_member_lock(struct bt_csip_set_member_svc_inst * svc_inst,bool lock,bool force)1141 int bt_csip_set_member_lock(struct bt_csip_set_member_svc_inst *svc_inst,
1142 			    bool lock, bool force)
1143 {
1144 	uint8_t lock_val;
1145 	int err = 0;
1146 
1147 	if (lock) {
1148 		lock_val = BT_CSIP_LOCK_VALUE;
1149 	} else {
1150 		lock_val = BT_CSIP_RELEASE_VALUE;
1151 	}
1152 
1153 	if (!lock && force) {
1154 		svc_inst->set_lock = BT_CSIP_RELEASE_VALUE;
1155 		notify_clients(svc_inst, NULL, FLAG_NOTIFY_LOCK);
1156 
1157 		if (svc_inst->cb != NULL && svc_inst->cb->lock_changed != NULL) {
1158 			svc_inst->cb->lock_changed(NULL, &svc_insts[0], false);
1159 		}
1160 	} else {
1161 		err = set_lock(NULL, svc_inst, lock_val);
1162 	}
1163 
1164 	if (err < 0) {
1165 		return BT_GATT_ERR(err);
1166 	} else {
1167 		return 0;
1168 	}
1169 }
1170