1 /*
2  * Copyright (c) 2022 Codecoup
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <errno.h>
8 #include <stdbool.h>
9 #include <stddef.h>
10 #include <stdint.h>
11 #include <string.h>
12 #include <sys/types.h>
13 
14 #include <zephyr/autoconf.h>
15 #include <zephyr/bluetooth/audio/audio.h>
16 #include <zephyr/bluetooth/audio/pacs.h>
17 #include <zephyr/bluetooth/audio/has.h>
18 #include <zephyr/bluetooth/addr.h>
19 #include <zephyr/bluetooth/att.h>
20 #include <zephyr/bluetooth/bluetooth.h>
21 #include <zephyr/bluetooth/conn.h>
22 #include <zephyr/bluetooth/gatt.h>
23 #include <zephyr/bluetooth/uuid.h>
24 #include <zephyr/kernel.h>
25 #include <zephyr/logging/log.h>
26 #include <zephyr/net/buf.h>
27 #include <zephyr/settings/settings.h>
28 #include <zephyr/sys/__assert.h>
29 #include <zephyr/sys/atomic.h>
30 #include <zephyr/sys/check.h>
31 #include <zephyr/sys/slist.h>
32 #include <zephyr/sys/util.h>
33 #include <zephyr/sys/util_macro.h>
34 #include <zephyr/sys_clock.h>
35 #include <zephyr/toolchain.h>
36 
37 #include "../bluetooth/host/hci_core.h"
38 #include "../bluetooth/host/settings.h"
39 
40 #include "audio_internal.h"
41 #include "common/bt_str.h"
42 #include "has_internal.h"
43 
44 LOG_MODULE_REGISTER(bt_has, CONFIG_BT_HAS_LOG_LEVEL);
45 
46 /* The service allows operations with paired devices only.
47  * The number of clients is set to maximum number of simultaneous connections to paired devices.
48  */
49 #define MAX_INSTS MIN(CONFIG_BT_MAX_CONN, CONFIG_BT_MAX_PAIRED)
50 
51 #define BITS_CHANGED(_new_value, _old_value) ((_new_value) ^ (_old_value))
52 #define FEATURE_DEVICE_TYPE_UNCHANGED(_new_value) \
53 	!BITS_CHANGED(_new_value, (has.features & BT_HAS_FEAT_HEARING_AID_TYPE_MASK))
54 #define FEATURE_SYNC_SUPPORT_UNCHANGED(_new_value) \
55 	!BITS_CHANGED(_new_value, ((has.features & BT_HAS_FEAT_PRESET_SYNC_SUPP) != 0 ? 1 : 0))
56 #define FEATURE_IND_PRESETS_UNCHANGED(_new_value) \
57 	!BITS_CHANGED(_new_value, ((has.features & BT_HAS_FEAT_INDEPENDENT_PRESETS) != 0 ? 1 : 0))
58 #define BONDED_CLIENT_INIT_FLAGS \
59 	(BIT(FLAG_ACTIVE_INDEX_CHANGED) | BIT(FLAG_NOTIFY_PRESET_LIST) | BIT(FLAG_FEATURES_CHANGED))
60 
61 static struct bt_has has;
62 
63 #if defined(CONFIG_BT_HAS_ACTIVE_PRESET_INDEX)
active_preset_index_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)64 static void active_preset_index_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
65 {
66 	LOG_DBG("attr %p value 0x%04x", attr, value);
67 }
68 #endif /* CONFIG_BT_HAS_ACTIVE_PRESET_INDEX */
69 
70 #if defined(CONFIG_BT_HAS_PRESET_SUPPORT)
71 struct has_client;
72 
73 static int read_preset_response(struct has_client *client);
74 static int preset_list_changed(struct has_client *client);
75 static int preset_list_changed_generic_update_tail(struct has_client *client);
76 static int preset_list_changed_record_deleted_last(struct has_client *client);
77 static ssize_t write_control_point(struct bt_conn *conn, const struct bt_gatt_attr *attr,
78 				   const void *data, uint16_t len, uint16_t offset, uint8_t flags);
79 
preset_cp_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)80 static void preset_cp_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
81 {
82 	LOG_DBG("attr %p value 0x%04x", attr, value);
83 }
84 
read_active_preset_index(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)85 static ssize_t read_active_preset_index(struct bt_conn *conn, const struct bt_gatt_attr *attr,
86 					void *buf, uint16_t len, uint16_t offset)
87 {
88 	uint8_t active_index;
89 
90 	LOG_DBG("conn %p attr %p offset %d", (void *)conn, attr, offset);
91 
92 	if (offset > sizeof(active_index)) {
93 		return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
94 	}
95 
96 	active_index = bt_has_preset_active_get();
97 
98 	return bt_gatt_attr_read(conn, attr, buf, len, offset, &active_index, sizeof(active_index));
99 }
100 #endif /* CONFIG_BT_HAS_PRESET_SUPPORT */
101 
102 #if defined(CONFIG_BT_HAS_FEATURES_NOTIFIABLE)
features_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)103 static void features_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
104 {
105 	LOG_DBG("attr %p value 0x%04x", attr, value);
106 }
107 #endif /* CONFIG_BT_HAS_FEATURES_NOTIFIABLE */
108 
read_features(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)109 static ssize_t read_features(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf,
110 			     uint16_t len, uint16_t offset)
111 {
112 	LOG_DBG("conn %p attr %p offset %d", (void *)conn, attr, offset);
113 
114 	if (offset > sizeof(has.features)) {
115 		return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
116 	}
117 
118 	return bt_gatt_attr_read(conn, attr, buf, len, offset, &has.features,
119 				 sizeof(has.features));
120 }
121 
122 #if defined(CONFIG_BT_HAS_FEATURES_NOTIFIABLE)
123 #define BT_HAS_CHR_FEATURES \
124 	BT_AUDIO_CHRC(BT_UUID_HAS_HEARING_AID_FEATURES, \
125 		      BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \
126 		      BT_GATT_PERM_READ_ENCRYPT, \
127 		      read_features, NULL, NULL), \
128 	BT_AUDIO_CCC(features_cfg_changed),
129 #else
130 #define BT_HAS_CHR_FEATURES \
131 	BT_AUDIO_CHRC(BT_UUID_HAS_HEARING_AID_FEATURES, \
132 		      BT_GATT_CHRC_READ, \
133 		      BT_GATT_PERM_READ_ENCRYPT, \
134 		      read_features, NULL, NULL),
135 #endif /* CONFIG_BT_HAS_FEATURES_NOTIFIABLE */
136 
137 #if defined(CONFIG_BT_HAS_PRESET_SUPPORT)
138 #if defined(CONFIG_BT_HAS_PRESET_CONTROL_POINT_NOTIFIABLE)
139 #define BT_HAS_CHR_PRESET_CONTROL_POINT \
140 	BT_AUDIO_CHRC(BT_UUID_HAS_PRESET_CONTROL_POINT, \
141 		      BT_GATT_CHRC_WRITE | BT_GATT_CHRC_INDICATE | BT_GATT_CHRC_NOTIFY, \
142 		      BT_GATT_PERM_WRITE_ENCRYPT, \
143 		      NULL, write_control_point, NULL), \
144 	BT_AUDIO_CCC(preset_cp_cfg_changed),
145 #else
146 #define BT_HAS_CHR_PRESET_CONTROL_POINT \
147 	BT_AUDIO_CHRC(BT_UUID_HAS_PRESET_CONTROL_POINT, \
148 		      BT_GATT_CHRC_WRITE | BT_GATT_CHRC_INDICATE, \
149 		      BT_GATT_PERM_WRITE_ENCRYPT, \
150 		      NULL, write_control_point, NULL), \
151 	BT_AUDIO_CCC(preset_cp_cfg_changed),
152 #endif /* CONFIG_BT_HAS_PRESET_CONTROL_POINT_NOTIFIABLE */
153 #else
154 #define BT_HAS_CHR_PRESET_CONTROL_POINT
155 #endif /* CONFIG_BT_HAS_PRESET_SUPPORT */
156 
157 #if defined(CONFIG_BT_HAS_ACTIVE_PRESET_INDEX)
158 #define BT_HAS_CHR_ACTIVE_PRESET_INDEX \
159 	BT_AUDIO_CHRC(BT_UUID_HAS_ACTIVE_PRESET_INDEX, \
160 		      BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, \
161 		      BT_GATT_PERM_READ_ENCRYPT, \
162 		      read_active_preset_index, NULL, NULL), \
163 	BT_AUDIO_CCC(active_preset_index_cfg_changed)
164 #else
165 #define BT_HAS_CHR_ACTIVE_PRESET_INDEX
166 #endif /* CONFIG_BT_HAS_ACTIVE_PRESET_INDEX */
167 
168 /* Hearing Access Service GATT Attributes */
169 static struct bt_gatt_attr has_attrs[] = {
170 	BT_GATT_PRIMARY_SERVICE(BT_UUID_HAS),
171 	BT_HAS_CHR_FEATURES
172 	BT_HAS_CHR_PRESET_CONTROL_POINT
173 	BT_HAS_CHR_ACTIVE_PRESET_INDEX
174 };
175 
176 static struct bt_gatt_service has_svc;
177 static struct bt_gatt_attr *hearing_aid_features_attr;
178 static struct bt_gatt_attr *preset_control_point_attr;
179 static struct bt_gatt_attr *active_preset_index_attr;
180 
181 #if defined(CONFIG_BT_HAS_PRESET_SUPPORT) || defined(CONFIG_BT_HAS_FEATURES_NOTIFIABLE)
182 static void notify_work_handler(struct k_work *work);
183 
184 enum flag_internal {
185 	FLAG_ACTIVE_INDEX_CHANGED,
186 	FLAG_PENDING_READ_PRESET_RESPONSE,
187 	FLAG_NOTIFY_PRESET_LIST,
188 	FLAG_NOTIFY_PRESET_LIST_GENERIC_UPDATE_TAIL,
189 	FLAG_NOTIFY_PRESET_LIST_RECORD_DELETED_LAST,
190 	FLAG_FEATURES_CHANGED,
191 	FLAG_NUM,
192 };
193 
194 /* Stored client context */
195 static struct client_context {
196 	bt_addr_le_t addr;
197 
198 	/* Pending notification flags */
199 	ATOMIC_DEFINE(flags, FLAG_NUM);
200 
201 	/* Last notified preset index */
202 	uint8_t last_preset_index_known;
203 } contexts[CONFIG_BT_MAX_PAIRED];
204 
205 /* Connected client instance */
206 static struct has_client {
207 	struct bt_conn *conn;
208 #if defined(CONFIG_BT_HAS_PRESET_SUPPORT)
209 	union {
210 		struct bt_gatt_indicate_params ind;
211 #if defined(CONFIG_BT_HAS_PRESET_CONTROL_POINT_NOTIFIABLE)
212 		struct bt_gatt_notify_params ntf;
213 #endif /* CONFIG_BT_HAS_PRESET_CONTROL_POINT_NOTIFIABLE */
214 	} params;
215 
216 	uint8_t preset_changed_index_next;
217 	struct bt_has_cp_read_presets_req read_presets_req;
218 #endif /* CONFIG_BT_HAS_PRESET_SUPPORT */
219 	struct k_work_delayable notify_work;
220 	struct client_context *context;
221 } has_client_list[MAX_INSTS];
222 
223 
context_find(const bt_addr_le_t * addr)224 static struct client_context *context_find(const bt_addr_le_t *addr)
225 {
226 	__ASSERT_NO_MSG(addr != NULL);
227 
228 	for (size_t i = 0; i < ARRAY_SIZE(contexts); i++) {
229 		if (bt_addr_le_eq(&contexts[i].addr, addr)) {
230 			return &contexts[i];
231 		}
232 	}
233 
234 	return NULL;
235 }
236 
context_alloc(const bt_addr_le_t * addr)237 static struct client_context *context_alloc(const bt_addr_le_t *addr)
238 {
239 	struct client_context *context;
240 
241 	__ASSERT_NO_MSG(addr != NULL);
242 
243 	/* Free contexts has BT_ADDR_LE_ANY as the address */
244 	context = context_find(BT_ADDR_LE_ANY);
245 	if (context == NULL) {
246 		return NULL;
247 	}
248 
249 	memset(context, 0, sizeof(*context));
250 
251 	bt_addr_le_copy(&context->addr, addr);
252 
253 	return context;
254 }
255 
context_free(struct client_context * context)256 static void context_free(struct client_context *context)
257 {
258 	bt_addr_le_copy(&context->addr, BT_ADDR_LE_ANY);
259 }
260 
client_free(struct has_client * client)261 static void client_free(struct has_client *client)
262 {
263 	struct bt_conn_info info = { 0 };
264 	int err;
265 
266 #if defined(CONFIG_BT_HAS_PRESET_SUPPORT) || defined(CONFIG_BT_HAS_FEATURES_NOTIFIABLE)
267 	(void)k_work_cancel_delayable(&client->notify_work);
268 #endif /* CONFIG_BT_HAS_PRESET_SUPPORT || CONFIG_BT_HAS_FEATURES_NOTIFIABLE */
269 
270 	err = bt_conn_get_info(client->conn, &info);
271 	__ASSERT_NO_MSG(err == 0);
272 
273 	if (client->context != NULL && !bt_addr_le_is_bonded(info.id, info.le.dst)) {
274 		/* Free stored context of non-bonded client */
275 		context_free(client->context);
276 		client->context = NULL;
277 	}
278 
279 	bt_conn_unref(client->conn);
280 	client->conn = NULL;
281 }
282 
client_alloc(struct bt_conn * conn)283 static struct has_client *client_alloc(struct bt_conn *conn)
284 {
285 	struct bt_conn_info info = { 0 };
286 	struct has_client *client = NULL;
287 	int err;
288 
289 	for (size_t i = 0; i < ARRAY_SIZE(has_client_list); i++) {
290 		if (conn == has_client_list[i].conn) {
291 			return &has_client_list[i];
292 		}
293 
294 		/* first free slot */
295 		if (!client && has_client_list[i].conn == NULL) {
296 			client = &has_client_list[i];
297 		}
298 	}
299 
300 	__ASSERT(client, "failed to get client for conn %p", (void *)conn);
301 
302 	memset(client, 0, sizeof(*client));
303 
304 	client->conn = bt_conn_ref(conn);
305 
306 #if defined(CONFIG_BT_HAS_PRESET_SUPPORT) || defined(CONFIG_BT_HAS_FEATURES_NOTIFIABLE)
307 	k_work_init_delayable(&client->notify_work, notify_work_handler);
308 #endif /* CONFIG_BT_HAS_PRESET_SUPPORT || CONFIG_BT_HAS_FEATURES_NOTIFIABLE */
309 
310 	err = bt_conn_get_info(conn, &info);
311 	if (err != 0) {
312 		LOG_DBG("Could not get conn info: %d", err);
313 
314 		return NULL;
315 	}
316 
317 	client->context = context_find(info.le.dst);
318 	if (client->context == NULL) {
319 		client->context = context_alloc(info.le.dst);
320 		if (client->context == NULL) {
321 			LOG_ERR("Failed to allocate client_context for %s",
322 				bt_addr_le_str(info.le.dst));
323 
324 			client_free(client);
325 
326 			return NULL;
327 		}
328 
329 		LOG_DBG("New client_context for %s", bt_addr_le_str(info.le.dst));
330 	}
331 
332 	return client;
333 }
334 
client_find_by_conn(struct bt_conn * conn)335 static struct has_client *client_find_by_conn(struct bt_conn *conn)
336 {
337 	for (size_t i = 0; i < ARRAY_SIZE(has_client_list); i++) {
338 		if (conn == has_client_list[i].conn) {
339 			return &has_client_list[i];
340 		}
341 	}
342 
343 	return NULL;
344 }
345 
notify_work_reschedule(struct has_client * client,k_timeout_t delay)346 static void notify_work_reschedule(struct has_client *client, k_timeout_t delay)
347 {
348 	int err;
349 
350 	__ASSERT(client->conn, "Not connected");
351 
352 	if (k_work_delayable_remaining_get(&client->notify_work) > 0) {
353 		return;
354 	}
355 
356 	err = k_work_reschedule(&client->notify_work, delay);
357 	if (err < 0) {
358 		LOG_ERR("Failed to reschedule notification work err %d", err);
359 	}
360 }
361 
security_changed(struct bt_conn * conn,bt_security_t level,enum bt_security_err err)362 static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err)
363 {
364 	struct has_client *client;
365 	struct bt_conn_info info;
366 	int ret;
367 
368 	LOG_DBG("conn %p level %d err %d", (void *)conn, level, err);
369 
370 	if (err != BT_SECURITY_ERR_SUCCESS) {
371 		return;
372 	}
373 
374 	client = client_alloc(conn);
375 	if (unlikely(!client)) {
376 		LOG_ERR("Failed to allocate client");
377 		return;
378 	}
379 
380 	ret = bt_conn_get_info(client->conn, &info);
381 	if (ret < 0) {
382 		LOG_ERR("bt_conn_get_info err %d", ret);
383 		return;
384 	}
385 
386 	if (!bt_addr_le_is_bonded(info.id, info.le.dst)) {
387 		return;
388 	}
389 
390 	if (atomic_get(client->context->flags) != 0) {
391 		notify_work_reschedule(client, K_NO_WAIT);
392 	}
393 }
394 
disconnected(struct bt_conn * conn,uint8_t reason)395 static void disconnected(struct bt_conn *conn, uint8_t reason)
396 {
397 	struct has_client *client;
398 
399 	LOG_DBG("conn %p reason %d", (void *)conn, reason);
400 
401 	client = client_find_by_conn(conn);
402 	if (client) {
403 		client_free(client);
404 	}
405 }
406 
identity_resolved(struct bt_conn * conn,const bt_addr_le_t * rpa,const bt_addr_le_t * identity)407 static void identity_resolved(struct bt_conn *conn, const bt_addr_le_t *rpa,
408 			      const bt_addr_le_t *identity)
409 {
410 	struct has_client *client;
411 
412 	LOG_DBG("conn %p %s -> %s", (void *)conn, bt_addr_le_str(rpa), bt_addr_le_str(identity));
413 
414 	client = client_find_by_conn(conn);
415 	if (client == NULL) {
416 		return;
417 	}
418 
419 	bt_addr_le_copy(&client->context->addr, identity);
420 }
421 
422 BT_CONN_CB_DEFINE(conn_cb) = {
423 	.disconnected = disconnected,
424 	.security_changed = security_changed,
425 	.identity_resolved = identity_resolved,
426 };
427 
notify_work_handler(struct k_work * work)428 static void notify_work_handler(struct k_work *work)
429 {
430 	struct k_work_delayable *dwork = k_work_delayable_from_work(work);
431 	struct has_client *client = CONTAINER_OF(dwork, struct has_client, notify_work);
432 	int err;
433 
434 	if (IS_ENABLED(CONFIG_BT_HAS_FEATURES_NOTIFIABLE) &&
435 	    atomic_test_and_clear_bit(client->context->flags, FLAG_FEATURES_CHANGED) &&
436 	    bt_gatt_is_subscribed(client->conn, hearing_aid_features_attr, BT_GATT_CCC_NOTIFY)) {
437 		err = bt_gatt_notify(client->conn, hearing_aid_features_attr, &has.features,
438 				     sizeof(has.features));
439 		if (err == -ENOMEM) {
440 			atomic_set_bit(client->context->flags, FLAG_FEATURES_CHANGED);
441 			notify_work_reschedule(client, K_USEC(BT_AUDIO_NOTIFY_RETRY_DELAY_US));
442 		} else if (err < 0) {
443 			LOG_ERR("Notify features err %d", err);
444 		}
445 	}
446 
447 #if defined(CONFIG_BT_HAS_PRESET_SUPPORT)
448 	if (atomic_test_and_clear_bit(client->context->flags, FLAG_PENDING_READ_PRESET_RESPONSE)) {
449 		err = read_preset_response(client);
450 		if (err == -ENOMEM) {
451 			atomic_set_bit(client->context->flags, FLAG_PENDING_READ_PRESET_RESPONSE);
452 			notify_work_reschedule(client, K_USEC(BT_AUDIO_NOTIFY_RETRY_DELAY_US));
453 		} else if (err < 0) {
454 			LOG_ERR("Notify read preset response err %d", err);
455 		}
456 	} else if (atomic_test_and_clear_bit(client->context->flags, FLAG_NOTIFY_PRESET_LIST)) {
457 		err = preset_list_changed(client);
458 		if (err == -ENOMEM) {
459 			atomic_set_bit(client->context->flags, FLAG_NOTIFY_PRESET_LIST);
460 			notify_work_reschedule(client, K_USEC(BT_AUDIO_NOTIFY_RETRY_DELAY_US));
461 		} else if (err < 0) {
462 			LOG_ERR("Notify preset list changed err %d", err);
463 		}
464 	} else if (atomic_test_and_clear_bit(client->context->flags,
465 					     FLAG_NOTIFY_PRESET_LIST_GENERIC_UPDATE_TAIL)) {
466 		err = preset_list_changed_generic_update_tail(client);
467 		if (err == -ENOMEM) {
468 			atomic_set_bit(client->context->flags,
469 				       FLAG_NOTIFY_PRESET_LIST_GENERIC_UPDATE_TAIL);
470 			notify_work_reschedule(client, K_USEC(BT_AUDIO_NOTIFY_RETRY_DELAY_US));
471 		} else if (err < 0) {
472 			LOG_ERR("Notify preset list changed generic update tail err %d", err);
473 		}
474 	} else if (atomic_test_and_clear_bit(client->context->flags,
475 					     FLAG_NOTIFY_PRESET_LIST_RECORD_DELETED_LAST)) {
476 		err = preset_list_changed_record_deleted_last(client);
477 		if (err == -ENOMEM) {
478 			atomic_set_bit(client->context->flags,
479 				       FLAG_NOTIFY_PRESET_LIST_RECORD_DELETED_LAST);
480 			notify_work_reschedule(client, K_USEC(BT_AUDIO_NOTIFY_RETRY_DELAY_US));
481 		} else if (err < 0) {
482 			LOG_ERR("Notify preset list changed recoed deleted last err %d", err);
483 		}
484 	}
485 
486 #endif /* CONFIG_BT_HAS_PRESET_SUPPORT */
487 
488 	if (IS_ENABLED(CONFIG_BT_HAS_PRESET_SUPPORT) &&
489 	    atomic_test_and_clear_bit(client->context->flags, FLAG_ACTIVE_INDEX_CHANGED) &&
490 	    bt_gatt_is_subscribed(client->conn, active_preset_index_attr, BT_GATT_CCC_NOTIFY)) {
491 		uint8_t active_index;
492 
493 		active_index = bt_has_preset_active_get();
494 
495 		err = bt_gatt_notify(client->conn, active_preset_index_attr,
496 				     &active_index, sizeof(active_index));
497 		if (err == -ENOMEM) {
498 			atomic_set_bit(client->context->flags, FLAG_ACTIVE_INDEX_CHANGED);
499 			notify_work_reschedule(client, K_USEC(BT_AUDIO_NOTIFY_RETRY_DELAY_US));
500 		} else if (err < 0) {
501 			LOG_ERR("Notify active index err %d", err);
502 		}
503 	}
504 }
505 
notify(struct has_client * client,enum flag_internal flag)506 static void notify(struct has_client *client, enum flag_internal flag)
507 {
508 	if (client != NULL) {
509 		atomic_set_bit(client->context->flags, flag);
510 		notify_work_reschedule(client, K_NO_WAIT);
511 		return;
512 	}
513 
514 	/* Mark notification to be sent to all clients */
515 	for (size_t i = 0U; i < ARRAY_SIZE(contexts); i++) {
516 		atomic_set_bit(contexts[i].flags, flag);
517 	}
518 
519 	for (size_t i = 0U; i < ARRAY_SIZE(has_client_list); i++) {
520 		client = &has_client_list[i];
521 
522 		if (client->conn == NULL) {
523 			continue;
524 		}
525 
526 		notify_work_reschedule(client, K_NO_WAIT);
527 	}
528 }
529 
bond_deleted_cb(uint8_t id,const bt_addr_le_t * addr)530 static void bond_deleted_cb(uint8_t id, const bt_addr_le_t *addr)
531 {
532 	struct client_context *context;
533 
534 	context = context_find(addr);
535 	if (context != NULL) {
536 		context_free(context);
537 	}
538 
539 	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
540 		bt_settings_delete("has", 0, addr);
541 	}
542 }
543 
544 static struct bt_conn_auth_info_cb auth_info_cb = {
545 	.bond_deleted = bond_deleted_cb,
546 };
547 #endif /* CONFIG_BT_HAS_PRESET_SUPPORT || CONFIG_BT_HAS_FEATURES_NOTIFIABLE */
548 
549 #if defined(CONFIG_BT_HAS_PRESET_SUPPORT)
550 static struct has_preset *active_preset;
551 
552 /* HAS internal preset representation */
553 static struct has_preset {
554 	uint8_t index;
555 	enum bt_has_properties properties;
556 #if defined(CONFIG_BT_HAS_PRESET_NAME_DYNAMIC)
557 	char name[BT_HAS_PRESET_NAME_MAX + 1]; /* +1 byte for NULL-terminator */
558 #else
559 	const char *name;
560 #endif /* CONFIG_BT_HAS_PRESET_NAME_DYNAMIC */
561 	const struct bt_has_preset_ops *ops;
562 	sys_snode_t node;
563 } preset_pool[CONFIG_BT_HAS_PRESET_COUNT];
564 
565 static sys_slist_t preset_list = SYS_SLIST_STATIC_INIT(&preset_list);
566 static sys_slist_t preset_free_list = SYS_SLIST_STATIC_INIT(&preset_free_list);
567 
568 typedef uint8_t (*preset_func_t)(const struct has_preset *preset, void *user_data);
569 
preset_foreach(uint8_t start_index,uint8_t end_index,preset_func_t func,void * user_data)570 static void preset_foreach(uint8_t start_index, uint8_t end_index, preset_func_t func,
571 			   void *user_data)
572 {
573 	struct has_preset *preset, *tmp;
574 
575 	SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&preset_list, preset, tmp, node) {
576 		if (preset->index < start_index) {
577 			continue;
578 		}
579 
580 		if (preset->index > end_index) {
581 			return;
582 		}
583 
584 		if (func(preset, user_data) == BT_HAS_PRESET_ITER_STOP) {
585 			return;
586 		}
587 	}
588 }
589 
preset_found(const struct has_preset * preset,void * user_data)590 static uint8_t preset_found(const struct has_preset *preset, void *user_data)
591 {
592 	const struct has_preset **found = user_data;
593 
594 	*found = preset;
595 
596 	return BT_HAS_PRESET_ITER_STOP;
597 }
598 
preset_insert(struct has_preset * preset)599 static void preset_insert(struct has_preset *preset)
600 {
601 	struct has_preset *tmp, *prev = NULL;
602 
603 	SYS_SLIST_FOR_EACH_CONTAINER(&preset_list, tmp, node) {
604 		if (tmp->index > preset->index) {
605 			if (prev) {
606 				sys_slist_insert(&preset_list, &prev->node, &preset->node);
607 			} else {
608 				sys_slist_prepend(&preset_list, &preset->node);
609 			}
610 			return;
611 		}
612 
613 		prev = tmp;
614 	}
615 
616 	sys_slist_append(&preset_list, &preset->node);
617 }
618 
preset_alloc(uint8_t index,enum bt_has_properties properties,const char * name,const struct bt_has_preset_ops * ops)619 static struct has_preset *preset_alloc(uint8_t index, enum bt_has_properties properties,
620 				       const char *name, const struct bt_has_preset_ops *ops)
621 {
622 	struct has_preset *preset;
623 	sys_snode_t *node;
624 
625 	node = sys_slist_get(&preset_free_list);
626 	if (node == NULL) {
627 		return NULL;
628 	}
629 
630 	preset = CONTAINER_OF(node, struct has_preset, node);
631 	preset->index = index;
632 	preset->properties = properties;
633 #if defined(CONFIG_BT_HAS_PRESET_NAME_DYNAMIC)
634 	utf8_lcpy(preset->name, name, ARRAY_SIZE(preset->name));
635 #else
636 	preset->name = name;
637 #endif /* CONFIG_BT_HAS_PRESET_NAME_DYNAMIC */
638 	preset->ops = ops;
639 
640 	preset_insert(preset);
641 
642 	return preset;
643 }
644 
preset_free(struct has_preset * preset)645 static void preset_free(struct has_preset *preset)
646 {
647 	bool removed;
648 
649 	removed = sys_slist_find_and_remove(&preset_list, &preset->node);
650 	if (removed) {
651 		sys_slist_append(&preset_free_list, &preset->node);
652 	}
653 }
654 
preset_get_head(void)655 static struct has_preset *preset_get_head(void)
656 {
657 	struct has_preset *next;
658 
659 	return SYS_SLIST_PEEK_HEAD_CONTAINER(&preset_list, next, node);
660 }
661 
preset_get_tail(void)662 static struct has_preset *preset_get_tail(void)
663 {
664 	struct has_preset *prev;
665 
666 	return SYS_SLIST_PEEK_TAIL_CONTAINER(&preset_list, prev, node);
667 }
668 
preset_get_prev(const struct has_preset * preset)669 static struct has_preset *preset_get_prev(const struct has_preset *preset)
670 {
671 	struct has_preset *prev;
672 
673 	SYS_SLIST_FOR_EACH_CONTAINER(&preset_list, prev, node) {
674 		if (SYS_SLIST_PEEK_NEXT_CONTAINER(prev, node) == preset) {
675 			return prev;
676 		}
677 	}
678 
679 	prev = preset_get_tail();
680 	if (prev == preset) {
681 		return NULL;
682 	}
683 
684 	return prev;
685 }
686 
preset_lookup_index(uint8_t index)687 static struct has_preset *preset_lookup_index(uint8_t index)
688 {
689 	struct has_preset *preset;
690 
691 	SYS_SLIST_FOR_EACH_CONTAINER(&preset_list, preset, node) {
692 		if (preset->index == index) {
693 			return preset;
694 		}
695 	}
696 
697 	return NULL;
698 }
699 
preset_get_next(struct has_preset * preset)700 static struct has_preset *preset_get_next(struct has_preset *preset)
701 {
702 	struct has_preset *next;
703 
704 	next = SYS_SLIST_PEEK_NEXT_CONTAINER(preset, node);
705 	if (next == NULL) {
706 		next = preset_get_head();
707 		if (next == preset) {
708 			return NULL;
709 		}
710 	}
711 
712 	return next;
713 }
714 
preset_get_prev_index(const struct has_preset * preset)715 static uint8_t preset_get_prev_index(const struct has_preset *preset)
716 {
717 	const struct has_preset *prev;
718 
719 	prev = preset_get_prev(preset);
720 	if (prev == NULL || prev->index >= preset->index) {
721 		return BT_HAS_PRESET_INDEX_NONE;
722 	}
723 
724 	return prev->index;
725 }
726 
control_point_ntf_complete(struct bt_conn * conn,void * user_data)727 static void control_point_ntf_complete(struct bt_conn *conn, void *user_data)
728 {
729 	struct has_client *client = client_find_by_conn(conn);
730 
731 	LOG_DBG("conn %p", (void *)conn);
732 
733 	/* Resubmit if needed */
734 	if (client != NULL && atomic_get(client->context->flags) != 0) {
735 		notify_work_reschedule(client, K_NO_WAIT);
736 	}
737 }
738 
control_point_ind_complete(struct bt_conn * conn,struct bt_gatt_indicate_params * params,uint8_t err)739 static void control_point_ind_complete(struct bt_conn *conn,
740 				       struct bt_gatt_indicate_params *params,
741 				       uint8_t err)
742 {
743 	if (err) {
744 		/* TODO: Handle error somehow */
745 		LOG_ERR("conn %p err 0x%02x", (void *)conn, err);
746 	}
747 
748 	control_point_ntf_complete(conn, NULL);
749 }
750 
control_point_send(struct has_client * client,struct net_buf_simple * buf)751 static int control_point_send(struct has_client *client, struct net_buf_simple *buf)
752 {
753 	const uint16_t mtu_size = bt_gatt_get_mtu(client->conn);
754 	/* PDU structure is [Opcode (1)] [Handle (2)] [...] */
755 	const uint16_t pdu_size = 3 + buf->len;
756 
757 	if (mtu_size < pdu_size) {
758 		LOG_WRN("Sending truncated control point PDU %d < %d", mtu_size, pdu_size);
759 		buf->len -= (pdu_size - mtu_size);
760 	}
761 
762 #if defined(CONFIG_BT_HAS_PRESET_CONTROL_POINT_NOTIFIABLE)
763 	if (bt_eatt_count(client->conn) > 0 &&
764 	    bt_gatt_is_subscribed(client->conn, preset_control_point_attr, BT_GATT_CCC_NOTIFY)) {
765 		memset(&client->params.ntf, 0, sizeof(client->params.ntf));
766 		client->params.ntf.attr = preset_control_point_attr;
767 		client->params.ntf.func = control_point_ntf_complete;
768 		client->params.ntf.data = buf->data;
769 		client->params.ntf.len = buf->len;
770 
771 		return bt_gatt_notify_cb(client->conn, &client->params.ntf);
772 	}
773 #endif /* CONFIG_BT_HAS_PRESET_CONTROL_POINT_NOTIFIABLE */
774 
775 	if (bt_gatt_is_subscribed(client->conn, preset_control_point_attr, BT_GATT_CCC_INDICATE)) {
776 		memset(&client->params.ind, 0, sizeof(client->params.ind));
777 		client->params.ind.attr = preset_control_point_attr;
778 		client->params.ind.func = control_point_ind_complete;
779 		client->params.ind.destroy = NULL;
780 		client->params.ind.data = buf->data;
781 		client->params.ind.len = buf->len;
782 
783 		return bt_gatt_indicate(client->conn, &client->params.ind);
784 	}
785 
786 	return -ECANCELED;
787 }
788 
control_point_send_all(struct net_buf_simple * buf)789 static int control_point_send_all(struct net_buf_simple *buf)
790 {
791 	int result = 0;
792 
793 	for (size_t i = 0U; i < ARRAY_SIZE(contexts); i++) {
794 		struct client_context *context = &contexts[i];
795 		struct has_client *client = NULL;
796 		int err;
797 
798 		for (size_t j = 0U; j < ARRAY_SIZE(has_client_list); j++) {
799 			if (has_client_list[j].context == context) {
800 				client = &has_client_list[j];
801 				break;
802 			}
803 		}
804 
805 		if (client == NULL || client->conn == NULL) {
806 			/* Mark preset changed operation as pending */
807 			atomic_set_bit(context->flags, FLAG_NOTIFY_PRESET_LIST);
808 			continue;
809 		}
810 
811 		if (!bt_gatt_is_subscribed(client->conn, preset_control_point_attr,
812 					   BT_GATT_CCC_NOTIFY | BT_GATT_CCC_INDICATE)) {
813 			continue;
814 		}
815 
816 		err = control_point_send(client, buf);
817 		if (err) {
818 			result = err;
819 			/* continue anyway */
820 		}
821 	}
822 
823 	return result;
824 }
825 
bt_has_cp_read_preset_rsp(struct has_client * client,const struct has_preset * preset,bool is_last)826 static int bt_has_cp_read_preset_rsp(struct has_client *client, const struct has_preset *preset,
827 				     bool is_last)
828 {
829 	struct bt_has_cp_hdr *hdr;
830 	struct bt_has_cp_read_preset_rsp *rsp;
831 
832 	NET_BUF_SIMPLE_DEFINE(buf, sizeof(*hdr) + sizeof(*rsp) + BT_HAS_PRESET_NAME_MAX);
833 
834 	LOG_DBG("conn %p index 0x%02x prop 0x%02x %s is_last 0x%02x", (void *)client->conn,
835 		preset->index, preset->properties, preset->name, is_last);
836 
837 	hdr = net_buf_simple_add(&buf, sizeof(*hdr));
838 	hdr->opcode = BT_HAS_OP_READ_PRESET_RSP;
839 	rsp = net_buf_simple_add(&buf, sizeof(*rsp));
840 	rsp->is_last = is_last ? 0x01 : 0x00;
841 	rsp->index = preset->index;
842 	rsp->properties = preset->properties;
843 	net_buf_simple_add_mem(&buf, preset->name, strlen(preset->name));
844 
845 	return control_point_send(client, &buf);
846 }
847 
preset_changed_prepare(struct net_buf_simple * buf,uint8_t change_id,uint8_t is_last)848 static void preset_changed_prepare(struct net_buf_simple *buf, uint8_t change_id, uint8_t is_last)
849 {
850 	struct bt_has_cp_hdr *hdr;
851 	struct bt_has_cp_preset_changed *preset_changed;
852 
853 	hdr = net_buf_simple_add(buf, sizeof(*hdr));
854 	hdr->opcode = BT_HAS_OP_PRESET_CHANGED;
855 	preset_changed = net_buf_simple_add(buf, sizeof(*preset_changed));
856 	preset_changed->change_id = change_id;
857 	preset_changed->is_last = is_last;
858 }
859 
bt_has_cp_generic_update(struct has_client * client,uint8_t prev_index,uint8_t index,uint8_t properties,const char * name,uint8_t is_last)860 static int bt_has_cp_generic_update(struct has_client *client, uint8_t prev_index, uint8_t index,
861 				    uint8_t properties, const char *name, uint8_t is_last)
862 {
863 	struct bt_has_cp_generic_update *generic_update;
864 
865 	NET_BUF_SIMPLE_DEFINE(buf, sizeof(struct bt_has_cp_hdr) +
866 			      sizeof(struct bt_has_cp_preset_changed) +
867 			      sizeof(struct bt_has_cp_generic_update) + BT_HAS_PRESET_NAME_MAX);
868 
869 	LOG_DBG("client %p prev_index 0x%02x index 0x%02x prop 0x%02x %s is_last %d",
870 		client, prev_index, index, properties, name, is_last);
871 
872 	preset_changed_prepare(&buf, BT_HAS_CHANGE_ID_GENERIC_UPDATE, is_last);
873 
874 	generic_update = net_buf_simple_add(&buf, sizeof(*generic_update));
875 	generic_update->prev_index = prev_index;
876 	generic_update->index = index;
877 	generic_update->properties = properties;
878 	net_buf_simple_add_mem(&buf, name, strlen(name));
879 
880 	if (client) {
881 		return control_point_send(client, &buf);
882 	} else {
883 		return control_point_send_all(&buf);
884 	}
885 }
886 
887 #if defined(CONFIG_BT_SETTINGS)
888 struct client_context_store {
889 	/* Last notified preset index */
890 	uint8_t last_preset_index_known;
891 } __packed;
892 
settings_set_cb(const char * name,size_t len_rd,settings_read_cb read_cb,void * cb_arg)893 static int settings_set_cb(const char *name, size_t len_rd, settings_read_cb read_cb, void *cb_arg)
894 {
895 	struct client_context_store store;
896 	struct client_context *context;
897 	bt_addr_le_t addr;
898 	ssize_t len;
899 	int err;
900 
901 	if (!name) {
902 		LOG_ERR("Insufficient number of arguments");
903 		return -EINVAL;
904 	}
905 
906 	err = bt_settings_decode_key(name, &addr);
907 	if (err) {
908 		LOG_ERR("Unable to decode address %s", name);
909 		return -EINVAL;
910 	}
911 
912 	context = context_find(&addr);
913 	if (context == NULL) {
914 		/* Find and initialize a free entry */
915 		context = context_alloc(&addr);
916 		if (context == NULL) {
917 			LOG_ERR("Failed to allocate client_context for %s", bt_addr_le_str(&addr));
918 			return -ENOMEM;
919 		}
920 	}
921 
922 	if (len_rd) {
923 		len = read_cb(cb_arg, &store, sizeof(store));
924 		if (len < 0) {
925 			LOG_ERR("Failed to decode value (err %zd)", len);
926 			return len;
927 		}
928 
929 		context->last_preset_index_known = store.last_preset_index_known;
930 	} else {
931 		context->last_preset_index_known = 0x00;
932 	}
933 
934 	/* Notify all the characteristics values after reboot */
935 	atomic_set(context->flags, BONDED_CLIENT_INIT_FLAGS);
936 
937 	return 0;
938 }
939 
940 static BT_SETTINGS_DEFINE(has, "has", settings_set_cb, NULL);
941 
store_client_context(struct client_context * context)942 static void store_client_context(struct client_context *context)
943 {
944 	struct client_context_store store = {
945 		.last_preset_index_known = context->last_preset_index_known,
946 	};
947 	int err;
948 
949 	LOG_DBG("%s last_preset_index_known 0x%02x",
950 		bt_addr_le_str(&context->addr), store.last_preset_index_known);
951 
952 	err = bt_settings_store("has", 0, &context->addr, &store, sizeof(store));
953 	if (err != 0) {
954 		LOG_ERR("Failed to store err %d", err);
955 	}
956 }
957 #else
958 #define store_client_context(...)
959 #endif /* CONFIG_BT_SETTINGS */
960 
update_last_preset_index_known(struct has_client * client,uint8_t index)961 static void update_last_preset_index_known(struct has_client *client, uint8_t index)
962 {
963 	if (client != NULL && client->context != NULL &&
964 	    client->context->last_preset_index_known != index) {
965 		client->context->last_preset_index_known = index;
966 		store_client_context(client->context);
967 		return;
968 	}
969 
970 	for (size_t i = 0; i < ARRAY_SIZE(has_client_list); i++) {
971 		client = &has_client_list[i];
972 
973 		/* For each connected client */
974 		if (client->conn != NULL && client->context != NULL &&
975 		    client->context->last_preset_index_known != index) {
976 			client->context->last_preset_index_known = index;
977 			store_client_context(client->context);
978 		}
979 	}
980 }
981 
read_preset_response(struct has_client * client)982 static int read_preset_response(struct has_client *client)
983 {
984 	const struct has_preset *preset = NULL;
985 	bool is_last = true;
986 	int err;
987 
988 	__ASSERT_NO_MSG(client != NULL);
989 
990 	preset_foreach(client->read_presets_req.start_index, BT_HAS_PRESET_INDEX_LAST,
991 		       preset_found, &preset);
992 
993 	if (unlikely(preset == NULL)) {
994 		return bt_has_cp_read_preset_rsp(client, NULL, BT_HAS_IS_LAST);
995 	}
996 
997 	if (client->read_presets_req.num_presets > 1) {
998 		const struct has_preset *next = NULL;
999 
1000 		preset_foreach(preset->index + 1, BT_HAS_PRESET_INDEX_LAST, preset_found, &next);
1001 
1002 		is_last = next == NULL;
1003 	}
1004 
1005 	err = bt_has_cp_read_preset_rsp(client, preset, is_last);
1006 	if (err != 0) {
1007 		return err;
1008 	}
1009 
1010 	if (preset->index > client->context->last_preset_index_known) {
1011 		update_last_preset_index_known(client, preset->index);
1012 	}
1013 
1014 	if (!is_last) {
1015 		client->read_presets_req.start_index = preset->index + 1;
1016 		client->read_presets_req.num_presets--;
1017 
1018 		atomic_set_bit(client->context->flags, FLAG_PENDING_READ_PRESET_RESPONSE);
1019 		notify_work_reschedule(client, K_USEC(BT_AUDIO_NOTIFY_RETRY_DELAY_US));
1020 	}
1021 
1022 	return 0;
1023 }
1024 
bt_has_cp_preset_record_deleted(struct has_client * client,uint8_t index)1025 static int bt_has_cp_preset_record_deleted(struct has_client *client, uint8_t index)
1026 {
1027 	NET_BUF_SIMPLE_DEFINE(buf, sizeof(struct bt_has_cp_hdr) +
1028 			      sizeof(struct bt_has_cp_preset_changed) + sizeof(uint8_t));
1029 
1030 	LOG_DBG("client %p index 0x%02x", client, index);
1031 
1032 	preset_changed_prepare(&buf, BT_HAS_CHANGE_ID_PRESET_DELETED, BT_HAS_IS_LAST);
1033 	net_buf_simple_add_u8(&buf, index);
1034 
1035 	if (client != NULL) {
1036 		return control_point_send(client, &buf);
1037 	} else {
1038 		return control_point_send_all(&buf);
1039 	}
1040 }
1041 
1042 /* Generic Update the last (already deleted) preset */
preset_list_changed_generic_update_tail(struct has_client * client)1043 static int preset_list_changed_generic_update_tail(struct has_client *client)
1044 {
1045 	const struct has_preset *prev;
1046 	struct has_preset last = {
1047 		/* The index value of the last preset the client knew about. */
1048 		.index = client->context->last_preset_index_known,
1049 
1050 		/* As the properties of deleted preset is not available anymore, we set this value
1051 		 * to 0x00 meaning the preset is unavailable and non-writable which is actually true
1052 		 */
1053 		.properties = BT_HAS_PROP_NONE,
1054 
1055 		/* As the name of deleted preset are not available anymore, we set this value
1056 		 * to the value what is compliant with specification.
1057 		 * As per HAS_v1.0 the Name is 1-40 octet value.
1058 		 */
1059 		.name = "N/A",
1060 	};
1061 	int err;
1062 
1063 	prev = preset_get_tail();
1064 
1065 	err = bt_has_cp_generic_update(client, prev ? prev->index : BT_HAS_PRESET_INDEX_NONE,
1066 				       last.index, last.properties, last.name, false);
1067 	if (err != 0) {
1068 		return err;
1069 	}
1070 
1071 	return 0;
1072 }
1073 
preset_list_changed_record_deleted_last(struct has_client * client)1074 static int preset_list_changed_record_deleted_last(struct has_client *client)
1075 {
1076 	const struct has_preset *last;
1077 	int err;
1078 
1079 	err = bt_has_cp_preset_record_deleted(client, client->context->last_preset_index_known);
1080 	if (err != 0) {
1081 		return err;
1082 	}
1083 
1084 	last = preset_get_tail();
1085 
1086 	update_last_preset_index_known(client, last ? last->index : BT_HAS_PRESET_INDEX_NONE);
1087 
1088 	return 0;
1089 }
1090 
preset_list_changed(struct has_client * client)1091 static int preset_list_changed(struct has_client *client)
1092 {
1093 	const struct has_preset *preset = NULL;
1094 	const struct has_preset *next = NULL;
1095 	bool is_last = true;
1096 	int err;
1097 
1098 	if (sys_slist_is_empty(&preset_list)) {
1099 		/* The preset list is empty. We need to indicate deletion of all presets */
1100 		atomic_set_bit(client->context->flags,
1101 			       FLAG_NOTIFY_PRESET_LIST_GENERIC_UPDATE_TAIL);
1102 		atomic_set_bit(client->context->flags,
1103 			       FLAG_NOTIFY_PRESET_LIST_RECORD_DELETED_LAST);
1104 		notify_work_reschedule(client, K_USEC(BT_AUDIO_NOTIFY_RETRY_DELAY_US));
1105 
1106 		return 0;
1107 	}
1108 
1109 	preset_foreach(client->preset_changed_index_next, BT_HAS_PRESET_INDEX_LAST,
1110 		       preset_found, &preset);
1111 
1112 	if (preset == NULL) {
1113 		return 0;
1114 	}
1115 
1116 	preset_foreach(preset->index + 1, BT_HAS_PRESET_INDEX_LAST, preset_found, &next);
1117 
1118 	/* It is last Preset Changed notification if there are no presets left to notify and the
1119 	 * currently notified preset have the highest index known to the client.
1120 	 */
1121 	is_last = next == NULL && preset->index >= client->context->last_preset_index_known;
1122 
1123 	err = bt_has_cp_generic_update(client, preset_get_prev_index(preset), preset->index,
1124 				       preset->properties, preset->name, is_last);
1125 	if (err != 0) {
1126 		return err;
1127 	}
1128 
1129 	if (is_last) {
1130 		client->preset_changed_index_next = 0;
1131 
1132 		/* It's the last preset notified, so update the highest index known to the client */
1133 		update_last_preset_index_known(client, preset->index);
1134 
1135 		return 0;
1136 	}
1137 
1138 	if (next == NULL) {
1139 		/* If we end up here, the last preset known to the client has been removed.
1140 		 * As we do not hold the information about the deleted presets, we need to use
1141 		 * Generic Update procedure to:
1142 		 *   1. Notify the presets that have been removed in range
1143 		 *      (PrevIndex = current_preset_last, Index=previous_preset_last)
1144 		 *   2. Notify deletion of preset Index=previous_preset_last.
1145 		 */
1146 		atomic_set_bit(client->context->flags,
1147 			       FLAG_NOTIFY_PRESET_LIST_GENERIC_UPDATE_TAIL);
1148 		atomic_set_bit(client->context->flags,
1149 			       FLAG_NOTIFY_PRESET_LIST_RECORD_DELETED_LAST);
1150 	} else {
1151 		client->preset_changed_index_next = preset->index + 1;
1152 
1153 		atomic_set_bit(client->context->flags, FLAG_NOTIFY_PRESET_LIST);
1154 	}
1155 
1156 	notify_work_reschedule(client, K_USEC(BT_AUDIO_NOTIFY_RETRY_DELAY_US));
1157 
1158 	return 0;
1159 }
1160 
handle_read_preset_req(struct bt_conn * conn,struct net_buf_simple * buf)1161 static uint8_t handle_read_preset_req(struct bt_conn *conn, struct net_buf_simple *buf)
1162 {
1163 	const struct bt_has_cp_read_presets_req *req;
1164 	const struct has_preset *preset = NULL;
1165 	struct has_client *client;
1166 
1167 	if (buf->len < sizeof(*req)) {
1168 		return BT_HAS_ERR_INVALID_PARAM_LEN;
1169 	}
1170 
1171 	/* As per HAS_d1.0r00 Client Characteristic Configuration Descriptor Improperly Configured
1172 	 * shall be returned if client writes Read Presets Request but is not registered for
1173 	 * indications.
1174 	 */
1175 	if (!bt_gatt_is_subscribed(conn, preset_control_point_attr, BT_GATT_CCC_INDICATE)) {
1176 		return BT_ATT_ERR_CCC_IMPROPER_CONF;
1177 	}
1178 
1179 	client = client_find_by_conn(conn);
1180 	if (client == NULL) {
1181 		return BT_ATT_ERR_UNLIKELY;
1182 	}
1183 
1184 	req = net_buf_simple_pull_mem(buf, sizeof(*req));
1185 
1186 	LOG_DBG("start_index %d num_presets %d", req->start_index, req->num_presets);
1187 
1188 	/* Abort if there is no preset in requested index range */
1189 	preset_foreach(req->start_index, BT_HAS_PRESET_INDEX_LAST, preset_found, &preset);
1190 
1191 	if (preset == NULL) {
1192 		return BT_ATT_ERR_OUT_OF_RANGE;
1193 	}
1194 
1195 	/* Reject if already in progress */
1196 	if (atomic_test_bit(client->context->flags, FLAG_PENDING_READ_PRESET_RESPONSE)) {
1197 		return BT_HAS_ERR_OPERATION_NOT_POSSIBLE;
1198 	}
1199 
1200 	/* Store the request */
1201 	client->read_presets_req.start_index = req->start_index;
1202 	client->read_presets_req.num_presets = req->num_presets;
1203 
1204 	notify(client, FLAG_PENDING_READ_PRESET_RESPONSE);
1205 
1206 	return 0;
1207 }
1208 
set_preset_name(uint8_t index,const char * name,size_t len)1209 static int set_preset_name(uint8_t index, const char *name, size_t len)
1210 {
1211 	struct has_preset *preset = NULL;
1212 
1213 	LOG_DBG("index %d name_len %zu", index, len);
1214 
1215 	if (len < BT_HAS_PRESET_NAME_MIN || len > BT_HAS_PRESET_NAME_MAX) {
1216 		return -EINVAL;
1217 	}
1218 
1219 	/* Abort if there is no preset in requested index range */
1220 	preset_foreach(index, BT_HAS_PRESET_INDEX_LAST, preset_found, &preset);
1221 
1222 	if (preset == NULL) {
1223 		return -ENOENT;
1224 	}
1225 
1226 	if (!(preset->properties & BT_HAS_PROP_WRITABLE)) {
1227 		return -EPERM;
1228 	}
1229 
1230 	IF_ENABLED(CONFIG_BT_HAS_PRESET_NAME_DYNAMIC, (
1231 		__ASSERT(len < ARRAY_SIZE(preset->name), "No space for name");
1232 
1233 		(void)memcpy(preset->name, name, len);
1234 
1235 		/* NULL-terminate string */
1236 		preset->name[len] = '\0';
1237 
1238 		/* Properly truncate a NULL-terminated UTF-8 string */
1239 		utf8_trunc(preset->name);
1240 	));
1241 
1242 	if (preset->ops->name_changed) {
1243 		preset->ops->name_changed(index, preset->name);
1244 	}
1245 
1246 	return bt_has_cp_generic_update(NULL, preset_get_prev_index(preset), preset->index,
1247 					preset->properties, preset->name, BT_HAS_IS_LAST);
1248 }
1249 
handle_write_preset_name(struct bt_conn * conn,struct net_buf_simple * buf)1250 static uint8_t handle_write_preset_name(struct bt_conn *conn, struct net_buf_simple *buf)
1251 {
1252 	const struct bt_has_cp_write_preset_name *req;
1253 	struct has_client *client;
1254 	int err;
1255 
1256 	if (buf->len < sizeof(*req)) {
1257 		return BT_HAS_ERR_INVALID_PARAM_LEN;
1258 	}
1259 
1260 	/* As per HAS_v1.0 Client Characteristic Configuration Descriptor Improperly Configured
1261 	 * shall be returned if client writes Write Preset Name opcode but is not registered for
1262 	 * indications.
1263 	 */
1264 	if (!bt_gatt_is_subscribed(conn, preset_control_point_attr, BT_GATT_CCC_INDICATE)) {
1265 		return BT_ATT_ERR_CCC_IMPROPER_CONF;
1266 	}
1267 
1268 	client = client_find_by_conn(conn);
1269 	if (!client) {
1270 		return BT_ATT_ERR_UNLIKELY;
1271 	}
1272 
1273 	req = net_buf_simple_pull_mem(buf, sizeof(*req));
1274 
1275 	err = set_preset_name(req->index, req->name, buf->len);
1276 	if (err == -EINVAL) {
1277 		return BT_HAS_ERR_INVALID_PARAM_LEN;
1278 	} else if (err == -ENOENT) {
1279 		return BT_ATT_ERR_OUT_OF_RANGE;
1280 	} else if (err == -EPERM) {
1281 		return BT_HAS_ERR_WRITE_NAME_NOT_ALLOWED;
1282 	} else if (err) {
1283 		return BT_ATT_ERR_UNLIKELY;
1284 	}
1285 
1286 	return BT_ATT_ERR_SUCCESS;
1287 }
1288 
preset_set_active(struct has_preset * preset)1289 static void preset_set_active(struct has_preset *preset)
1290 {
1291 	if (active_preset != preset) {
1292 		active_preset = preset;
1293 
1294 		notify(NULL, FLAG_ACTIVE_INDEX_CHANGED);
1295 	}
1296 }
1297 
preset_select(struct has_preset * preset,bool sync)1298 static uint8_t preset_select(struct has_preset *preset, bool sync)
1299 {
1300 	const int err = preset->ops->select(preset->index, sync);
1301 
1302 	if (err == -EINPROGRESS) {
1303 		/* User has to confirm once the requested preset becomes active by
1304 		 * calling bt_has_preset_active_set.
1305 		 */
1306 		return 0;
1307 	}
1308 
1309 	if (err == -EBUSY) {
1310 		return BT_HAS_ERR_OPERATION_NOT_POSSIBLE;
1311 	}
1312 
1313 	if (err) {
1314 		return BT_ATT_ERR_UNLIKELY;
1315 	}
1316 
1317 	preset_set_active(preset);
1318 
1319 	return 0;
1320 }
1321 
is_preset_available(const struct has_preset * preset)1322 static bool is_preset_available(const struct has_preset *preset)
1323 {
1324 	return (preset->properties & BT_HAS_PROP_AVAILABLE) != 0;
1325 }
1326 
handle_set_active_preset(struct net_buf_simple * buf,bool sync)1327 static uint8_t handle_set_active_preset(struct net_buf_simple *buf, bool sync)
1328 {
1329 	const struct bt_has_cp_set_active_preset *pdu;
1330 	struct has_preset *preset;
1331 
1332 	if (buf->len < sizeof(*pdu)) {
1333 		return BT_HAS_ERR_INVALID_PARAM_LEN;
1334 	}
1335 
1336 	pdu = net_buf_simple_pull_mem(buf, sizeof(*pdu));
1337 
1338 	preset = preset_lookup_index(pdu->index);
1339 	if (preset == NULL) {
1340 		return BT_ATT_ERR_OUT_OF_RANGE;
1341 	}
1342 
1343 	if (!is_preset_available(preset)) {
1344 		return BT_HAS_ERR_OPERATION_NOT_POSSIBLE;
1345 	}
1346 
1347 	return preset_select(preset, sync);
1348 }
1349 
handle_set_next_preset(bool sync)1350 static uint8_t handle_set_next_preset(bool sync)
1351 {
1352 	struct has_preset *next, *tmp;
1353 
1354 	if (active_preset == NULL) {
1355 		next = preset_get_head();
1356 	} else {
1357 		next = preset_get_next(active_preset);
1358 	}
1359 
1360 	tmp = next;
1361 	do {
1362 		if (next == NULL) {
1363 			break;
1364 		}
1365 
1366 		if (is_preset_available(next)) {
1367 			return preset_select(next, sync);
1368 		}
1369 
1370 		next = preset_get_next(next);
1371 	} while (tmp != next);
1372 
1373 	return BT_HAS_ERR_OPERATION_NOT_POSSIBLE;
1374 }
1375 
handle_set_prev_preset(bool sync)1376 static uint8_t handle_set_prev_preset(bool sync)
1377 {
1378 	struct has_preset *prev, *tmp;
1379 
1380 	if (active_preset == NULL) {
1381 		prev = preset_get_tail();
1382 	} else {
1383 		prev = preset_get_prev(active_preset);
1384 	}
1385 
1386 	tmp = prev;
1387 	do {
1388 		if (prev == NULL) {
1389 			break;
1390 		}
1391 
1392 		if (is_preset_available(prev)) {
1393 			return preset_select(prev, sync);
1394 		}
1395 
1396 		prev = preset_get_prev(prev);
1397 	} while (tmp != prev);
1398 
1399 	return BT_HAS_ERR_OPERATION_NOT_POSSIBLE;
1400 }
1401 
handle_control_point_op(struct bt_conn * conn,struct net_buf_simple * buf)1402 static uint8_t handle_control_point_op(struct bt_conn *conn, struct net_buf_simple *buf)
1403 {
1404 	const struct bt_has_cp_hdr *hdr;
1405 
1406 	hdr = net_buf_simple_pull_mem(buf, sizeof(*hdr));
1407 
1408 	LOG_DBG("conn %p opcode %s (0x%02x)", (void *)conn, bt_has_op_str(hdr->opcode),
1409 		hdr->opcode);
1410 
1411 	switch (hdr->opcode) {
1412 	case BT_HAS_OP_READ_PRESET_REQ:
1413 		return handle_read_preset_req(conn, buf);
1414 	case BT_HAS_OP_WRITE_PRESET_NAME:
1415 		if (IS_ENABLED(CONFIG_BT_HAS_PRESET_NAME_DYNAMIC)) {
1416 			return handle_write_preset_name(conn, buf);
1417 		} else {
1418 			return BT_HAS_ERR_WRITE_NAME_NOT_ALLOWED;
1419 		}
1420 		break;
1421 	case BT_HAS_OP_SET_ACTIVE_PRESET:
1422 		return handle_set_active_preset(buf, false);
1423 	case BT_HAS_OP_SET_NEXT_PRESET:
1424 		return handle_set_next_preset(false);
1425 	case BT_HAS_OP_SET_PREV_PRESET:
1426 		return handle_set_prev_preset(false);
1427 	case BT_HAS_OP_SET_ACTIVE_PRESET_SYNC:
1428 		if ((has.features & BT_HAS_FEAT_PRESET_SYNC_SUPP) != 0) {
1429 			return handle_set_active_preset(buf, true);
1430 		} else {
1431 			return BT_HAS_ERR_PRESET_SYNC_NOT_SUPP;
1432 		}
1433 	case BT_HAS_OP_SET_NEXT_PRESET_SYNC:
1434 		if ((has.features & BT_HAS_FEAT_PRESET_SYNC_SUPP) != 0) {
1435 			return handle_set_next_preset(true);
1436 		} else {
1437 			return BT_HAS_ERR_PRESET_SYNC_NOT_SUPP;
1438 		}
1439 	case BT_HAS_OP_SET_PREV_PRESET_SYNC:
1440 		if ((has.features & BT_HAS_FEAT_PRESET_SYNC_SUPP) != 0) {
1441 			return handle_set_prev_preset(true);
1442 		} else {
1443 			return BT_HAS_ERR_PRESET_SYNC_NOT_SUPP;
1444 		}
1445 	};
1446 
1447 	return BT_HAS_ERR_INVALID_OPCODE;
1448 }
1449 
write_control_point(struct bt_conn * conn,const struct bt_gatt_attr * attr,const void * data,uint16_t len,uint16_t offset,uint8_t flags)1450 static ssize_t write_control_point(struct bt_conn *conn, const struct bt_gatt_attr *attr,
1451 				   const void *data, uint16_t len, uint16_t offset, uint8_t flags)
1452 {
1453 	struct net_buf_simple buf;
1454 	uint8_t err;
1455 
1456 	LOG_DBG("conn %p attr %p data %p len %d offset %d flags 0x%02x", (void *)conn, attr, data,
1457 		len, offset, flags);
1458 
1459 	if (offset > 0) {
1460 		return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
1461 	}
1462 
1463 	if (len == 0) {
1464 		return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
1465 	}
1466 
1467 	net_buf_simple_init_with_data(&buf, (void *)data, len);
1468 
1469 	err = handle_control_point_op(conn, &buf);
1470 	if (err) {
1471 		LOG_WRN("handle_control_point_op err 0x%02x", err);
1472 		return BT_GATT_ERR(err);
1473 	}
1474 
1475 	return len;
1476 }
1477 
bt_has_preset_register(const struct bt_has_preset_register_param * param)1478 int bt_has_preset_register(const struct bt_has_preset_register_param *param)
1479 {
1480 	struct has_preset *preset;
1481 	size_t name_len;
1482 
1483 	CHECKIF(param == NULL) {
1484 		LOG_ERR("param is NULL");
1485 		return -EINVAL;
1486 	}
1487 
1488 	CHECKIF(param->index == BT_HAS_PRESET_INDEX_NONE) {
1489 		LOG_ERR("param->index is invalid");
1490 		return -EINVAL;
1491 	}
1492 
1493 	CHECKIF(param->name == NULL) {
1494 		LOG_ERR("param->name is NULL");
1495 		return -EINVAL;
1496 	}
1497 
1498 	name_len = strlen(param->name);
1499 
1500 	CHECKIF(name_len < BT_HAS_PRESET_NAME_MIN) {
1501 		LOG_ERR("param->name is too short (%zu < %u)", name_len, BT_HAS_PRESET_NAME_MIN);
1502 		return -EINVAL;
1503 	}
1504 
1505 	CHECKIF(name_len > BT_HAS_PRESET_NAME_MAX) {
1506 		LOG_WRN("param->name is too long (%zu > %u)", name_len, BT_HAS_PRESET_NAME_MAX);
1507 	}
1508 
1509 	CHECKIF(param->ops == NULL) {
1510 		LOG_ERR("param->ops is NULL");
1511 		return -EINVAL;
1512 	}
1513 
1514 	CHECKIF(param->ops->select == NULL) {
1515 		LOG_ERR("param->ops->select is NULL");
1516 		return -EINVAL;
1517 	}
1518 
1519 	preset = preset_lookup_index(param->index);
1520 	if (preset != NULL) {
1521 		return -EALREADY;
1522 	}
1523 
1524 	CHECKIF(!IS_ENABLED(CONFIG_BT_HAS_PRESET_NAME_DYNAMIC) &&
1525 		(param->properties & BT_HAS_PROP_WRITABLE) > 0) {
1526 		LOG_ERR("Writable presets are not supported");
1527 		return -ENOTSUP;
1528 	}
1529 
1530 	preset = preset_alloc(param->index, param->properties, param->name, param->ops);
1531 	if (preset == NULL) {
1532 		return -ENOMEM;
1533 	}
1534 
1535 	if (preset == preset_get_tail()) {
1536 		update_last_preset_index_known(NULL, preset->index);
1537 	}
1538 
1539 	return bt_has_cp_generic_update(NULL, preset_get_prev_index(preset), preset->index,
1540 					preset->properties, preset->name, BT_HAS_IS_LAST);
1541 }
1542 
bt_has_preset_unregister(uint8_t index)1543 int bt_has_preset_unregister(uint8_t index)
1544 {
1545 	struct has_preset *preset;
1546 	int err;
1547 
1548 	CHECKIF(index == BT_HAS_PRESET_INDEX_NONE) {
1549 		LOG_ERR("index is invalid");
1550 		return -EINVAL;
1551 	}
1552 
1553 	preset = preset_lookup_index(index);
1554 	if (preset == NULL) {
1555 		return -ENOENT;
1556 	}
1557 
1558 	if (preset == active_preset) {
1559 		return -EADDRINUSE;
1560 	}
1561 
1562 	err = bt_has_cp_preset_record_deleted(NULL, preset->index);
1563 	if (err != 0) {
1564 		return err;
1565 	}
1566 
1567 	if (preset == preset_get_tail()) {
1568 		update_last_preset_index_known(NULL, preset_get_prev_index(preset));
1569 	}
1570 
1571 	preset_free(preset);
1572 
1573 	return 0;
1574 }
1575 
set_preset_availability(uint8_t index,bool available)1576 static int set_preset_availability(uint8_t index, bool available)
1577 {
1578 	NET_BUF_SIMPLE_DEFINE(buf, sizeof(struct bt_has_cp_hdr) +
1579 			      sizeof(struct bt_has_cp_preset_changed) + sizeof(uint8_t));
1580 	struct has_preset *preset;
1581 	uint8_t change_id;
1582 
1583 	CHECKIF(index == BT_HAS_PRESET_INDEX_NONE) {
1584 		LOG_ERR("index is invalid");
1585 		return -EINVAL;
1586 	}
1587 
1588 	preset = preset_lookup_index(index);
1589 	if (preset == NULL) {
1590 		return -ENOENT;
1591 	}
1592 
1593 	if (is_preset_available(preset) == available) {
1594 		/* availability not changed */
1595 		return 0;
1596 	}
1597 
1598 	preset->properties ^= BT_HAS_PROP_AVAILABLE;
1599 
1600 	if (is_preset_available(preset)) {
1601 		change_id = BT_HAS_CHANGE_ID_PRESET_AVAILABLE;
1602 	} else {
1603 		change_id = BT_HAS_CHANGE_ID_PRESET_UNAVAILABLE;
1604 	}
1605 
1606 	preset_changed_prepare(&buf, change_id, BT_HAS_IS_LAST);
1607 	net_buf_simple_add_u8(&buf, preset->index);
1608 
1609 	return control_point_send_all(&buf);
1610 }
1611 
bt_has_preset_available(uint8_t index)1612 int bt_has_preset_available(uint8_t index)
1613 {
1614 	return set_preset_availability(index, true);
1615 }
1616 
bt_has_preset_unavailable(uint8_t index)1617 int bt_has_preset_unavailable(uint8_t index)
1618 {
1619 	return set_preset_availability(index, false);
1620 }
1621 
1622 struct bt_has_preset_foreach_data {
1623 	bt_has_preset_func_t func;
1624 	void *user_data;
1625 };
1626 
bt_has_preset_foreach_func(const struct has_preset * preset,void * user_data)1627 static uint8_t bt_has_preset_foreach_func(const struct has_preset *preset, void *user_data)
1628 {
1629 	const struct bt_has_preset_foreach_data *data = user_data;
1630 
1631 	return data->func(preset->index, preset->properties, preset->name, data->user_data);
1632 }
1633 
bt_has_preset_foreach(uint8_t index,bt_has_preset_func_t func,void * user_data)1634 void bt_has_preset_foreach(uint8_t index, bt_has_preset_func_t func, void *user_data)
1635 {
1636 	uint8_t start_index, end_index;
1637 	struct bt_has_preset_foreach_data data = {
1638 		.func = func,
1639 		.user_data = user_data,
1640 	};
1641 
1642 	if (index == BT_HAS_PRESET_INDEX_NONE) {
1643 		start_index = BT_HAS_PRESET_INDEX_FIRST;
1644 		end_index = BT_HAS_PRESET_INDEX_LAST;
1645 	} else {
1646 		start_index = end_index = index;
1647 	}
1648 
1649 	preset_foreach(start_index, end_index, bt_has_preset_foreach_func, &data);
1650 }
1651 
bt_has_preset_active_set(uint8_t index)1652 int bt_has_preset_active_set(uint8_t index)
1653 {
1654 	struct has_preset *preset;
1655 
1656 	if (index == BT_HAS_PRESET_INDEX_NONE) {
1657 		preset_set_active(NULL);
1658 		return 0;
1659 	}
1660 
1661 	preset = preset_lookup_index(index);
1662 	if (preset == NULL) {
1663 		return -ENOENT;
1664 	}
1665 
1666 	if (!is_preset_available(preset)) {
1667 		return -EINVAL;
1668 	}
1669 
1670 	preset_set_active(preset);
1671 
1672 	return 0;
1673 }
1674 
bt_has_preset_active_get(void)1675 uint8_t bt_has_preset_active_get(void)
1676 {
1677 	if (active_preset == NULL) {
1678 		return BT_HAS_PRESET_INDEX_NONE;
1679 	}
1680 
1681 	return active_preset->index;
1682 }
1683 
bt_has_preset_name_change(uint8_t index,const char * name)1684 int bt_has_preset_name_change(uint8_t index, const char *name)
1685 {
1686 	CHECKIF(name == NULL) {
1687 		return -EINVAL;
1688 	}
1689 
1690 	if (IS_ENABLED(CONFIG_BT_HAS_PRESET_NAME_DYNAMIC)) {
1691 		return set_preset_name(index, name, strlen(name));
1692 	} else {
1693 		return -EOPNOTSUPP;
1694 	}
1695 }
1696 #endif /* CONFIG_BT_HAS_PRESET_SUPPORT */
1697 
has_features_register(const struct bt_has_features_param * features)1698 static int has_features_register(const struct bt_has_features_param *features)
1699 {
1700 	/* Initialize the supported features characteristic value */
1701 	has.features = features->type;
1702 
1703 	if (IS_ENABLED(CONFIG_BT_HAS_PRESET_SUPPORT)) {
1704 		has.features |= BT_HAS_FEAT_DYNAMIC_PRESETS;
1705 
1706 		if (features->preset_sync_support) {
1707 			if (features->type != BT_HAS_HEARING_AID_TYPE_BINAURAL) {
1708 				LOG_DBG("Preset sync support only available "
1709 					"for binaural hearing aid type");
1710 				return -EINVAL;
1711 			}
1712 
1713 			has.features |= BT_HAS_FEAT_PRESET_SYNC_SUPP;
1714 		}
1715 
1716 		if (features->independent_presets) {
1717 			if (features->type != BT_HAS_HEARING_AID_TYPE_BINAURAL) {
1718 				LOG_DBG("Independent presets only available "
1719 					"for binaural hearing aid type");
1720 				return -EINVAL;
1721 			}
1722 
1723 			has.features |= BT_HAS_FEAT_INDEPENDENT_PRESETS;
1724 		}
1725 	}
1726 
1727 	if (IS_ENABLED(CONFIG_BT_HAS_PRESET_NAME_DYNAMIC)) {
1728 		has.features |= BT_HAS_FEAT_WRITABLE_PRESETS_SUPP;
1729 	}
1730 
1731 	return 0;
1732 }
1733 
1734 #if defined(CONFIG_BT_HAS_FEATURES_NOTIFIABLE)
bt_has_features_set(const struct bt_has_features_param * features)1735 int bt_has_features_set(const struct bt_has_features_param *features)
1736 {
1737 	int err;
1738 
1739 	if (!has.registered) {
1740 		return -ENOTSUP;
1741 	}
1742 
1743 	/* Check whether any features will change, otherwise we don't want to notify clients */
1744 	if (FEATURE_DEVICE_TYPE_UNCHANGED(features->type) &&
1745 	    FEATURE_SYNC_SUPPORT_UNCHANGED(features->preset_sync_support) &&
1746 	    FEATURE_IND_PRESETS_UNCHANGED(features->independent_presets)) {
1747 		return 0;
1748 	}
1749 
1750 	err = has_features_register(features);
1751 	if (err != 0) {
1752 		LOG_DBG("Failed to register features");
1753 		return err;
1754 	}
1755 
1756 	notify(NULL, FLAG_FEATURES_CHANGED);
1757 
1758 	return 0;
1759 }
1760 #endif /* CONFIG_BT_HAS_FEATURES_NOTIFIABLE */
1761 
bt_has_register(const struct bt_has_features_param * features)1762 int bt_has_register(const struct bt_has_features_param *features)
1763 {
1764 	int err;
1765 
1766 	LOG_DBG("features %p", features);
1767 
1768 	CHECKIF(!features) {
1769 		LOG_DBG("NULL params pointer");
1770 		return -EINVAL;
1771 	}
1772 
1773 	if (has.registered) {
1774 		return -EALREADY;
1775 	}
1776 
1777 	err = has_features_register(features);
1778 	if (err != 0) {
1779 		LOG_DBG("HAS service failed to register features: %d", err);
1780 		return err;
1781 	}
1782 
1783 	has_svc = (struct bt_gatt_service)BT_GATT_SERVICE(has_attrs);
1784 	err = bt_gatt_service_register(&has_svc);
1785 	if (err != 0) {
1786 		LOG_DBG("HAS service register failed: %d", err);
1787 		return err;
1788 	}
1789 
1790 	if (IS_ENABLED(CONFIG_BT_HAS_FEATURES_NOTIFIABLE)) {
1791 		hearing_aid_features_attr = bt_gatt_find_by_uuid(has_svc.attrs, has_svc.attr_count,
1792 								 BT_UUID_HAS_HEARING_AID_FEATURES);
1793 		__ASSERT_NO_MSG(hearing_aid_features_attr != NULL);
1794 	}
1795 
1796 	if (IS_ENABLED(CONFIG_BT_HAS_PRESET_SUPPORT)) {
1797 		preset_control_point_attr = bt_gatt_find_by_uuid(has_svc.attrs, has_svc.attr_count,
1798 								 BT_UUID_HAS_PRESET_CONTROL_POINT);
1799 		__ASSERT_NO_MSG(preset_control_point_attr != NULL);
1800 
1801 		active_preset_index_attr = bt_gatt_find_by_uuid(has_svc.attrs, has_svc.attr_count,
1802 								BT_UUID_HAS_ACTIVE_PRESET_INDEX);
1803 		__ASSERT_NO_MSG(active_preset_index_attr != NULL);
1804 	}
1805 
1806 #if defined(CONFIG_BT_HAS_PRESET_SUPPORT)
1807 	for (size_t i = 0; i < ARRAY_SIZE(preset_pool); i++) {
1808 		struct has_preset *preset = &preset_pool[i];
1809 
1810 		sys_slist_append(&preset_free_list, &preset->node);
1811 	}
1812 #endif /* CONFIG_BT_HAS_PRESET_SUPPORT */
1813 
1814 #if defined(CONFIG_BT_HAS_PRESET_SUPPORT) || defined(CONFIG_BT_HAS_FEATURES_NOTIFIABLE)
1815 	bt_conn_auth_info_cb_register(&auth_info_cb);
1816 #endif /* CONFIG_BT_HAS_PRESET_SUPPORT || CONFIG_BT_HAS_FEATURES_NOTIFIABLE */
1817 
1818 	has.registered = true;
1819 
1820 	return 0;
1821 }
1822