1 /*
2  * Copyright (c) 2020 Bose Corporation
3  * Copyright (c) 2020 Nordic Semiconductor ASA
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <errno.h>
9 #include <stdbool.h>
10 #include <stddef.h>
11 #include <stdint.h>
12 #include <string.h>
13 #include <sys/types.h>
14 
15 #include <zephyr/autoconf.h>
16 #include <zephyr/bluetooth/att.h>
17 #include <zephyr/bluetooth/bluetooth.h>
18 #include <zephyr/bluetooth/conn.h>
19 #include <zephyr/bluetooth/gatt.h>
20 #include <zephyr/bluetooth/audio/aics.h>
21 #include <zephyr/bluetooth/uuid.h>
22 #include <zephyr/device.h>
23 #include <zephyr/init.h>
24 #include <zephyr/kernel.h>
25 #include <zephyr/sys/atomic.h>
26 #include <zephyr/sys/byteorder.h>
27 #include <zephyr/sys/check.h>
28 #include <zephyr/sys/util.h>
29 #include <zephyr/sys/util_macro.h>
30 #include <zephyr/sys_clock.h>
31 
32 #include "aics_internal.h"
33 #include "audio_internal.h"
34 
35 #define LOG_LEVEL CONFIG_BT_AICS_LOG_LEVEL
36 #include <zephyr/logging/log.h>
37 LOG_MODULE_REGISTER(bt_aics);
38 
39 #define VALID_AICS_OPCODE(opcode)                                              \
40 	((opcode) >= BT_AICS_OPCODE_SET_GAIN && (opcode) <= BT_AICS_OPCODE_SET_AUTO)
41 
42 #define AICS_CP_LEN                 0x02
43 #define AICS_CP_SET_GAIN_LEN        0x03
44 
45 
46 static ssize_t write_description(struct bt_conn *conn,
47 				 const struct bt_gatt_attr *attr,
48 				 const void *buf, uint16_t len, uint16_t offset,
49 				 uint8_t flags);
50 
51 static ssize_t write_aics_control(struct bt_conn *conn,
52 				  const struct bt_gatt_attr *attr,
53 				  const void *buf, uint16_t len,
54 				  uint16_t offset, uint8_t flags);
55 
56 #if defined(CONFIG_BT_AICS)
57 static void aics_state_cfg_changed(const struct bt_gatt_attr *attr,
58 				   uint16_t value);
59 static ssize_t read_aics_state(struct bt_conn *conn,
60 			       const struct bt_gatt_attr *attr,
61 			       void *buf, uint16_t len, uint16_t offset);
62 static ssize_t read_aics_gain_settings(struct bt_conn *conn,
63 				       const struct bt_gatt_attr *attr,
64 				       void *buf, uint16_t len,
65 				       uint16_t offset);
66 static ssize_t read_type(struct bt_conn *conn, const struct bt_gatt_attr *attr,
67 			 void *buf, uint16_t len, uint16_t offset);
68 static void aics_input_status_cfg_changed(const struct bt_gatt_attr *attr,
69 					  uint16_t value);
70 static ssize_t read_input_status(struct bt_conn *conn,
71 				 const struct bt_gatt_attr *attr,
72 				 void *buf, uint16_t len, uint16_t offset);
73 static void aics_description_cfg_changed(const struct bt_gatt_attr *attr,
74 					 uint16_t value);
75 static ssize_t read_description(struct bt_conn *conn,
76 				const struct bt_gatt_attr *attr, void *buf,
77 				uint16_t len, uint16_t offset);
78 
79 #define BT_AICS_SERVICE_DEFINITION(_aics) {                                    \
80 	BT_GATT_SECONDARY_SERVICE(BT_UUID_AICS),                               \
81 	BT_AUDIO_CHRC(BT_UUID_AICS_STATE,                                      \
82 		      BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,                 \
83 		      BT_GATT_PERM_READ_ENCRYPT,                               \
84 		      read_aics_state, NULL, &_aics),                          \
85 	BT_AUDIO_CCC(aics_state_cfg_changed),                                  \
86 	BT_AUDIO_CHRC(BT_UUID_AICS_GAIN_SETTINGS,                              \
87 		      BT_GATT_CHRC_READ,                                       \
88 		      BT_GATT_PERM_READ_ENCRYPT,                               \
89 		      read_aics_gain_settings, NULL, &_aics),                  \
90 	BT_AUDIO_CHRC(BT_UUID_AICS_INPUT_TYPE,                                 \
91 		      BT_GATT_CHRC_READ,                                       \
92 		      BT_GATT_PERM_READ_ENCRYPT,                               \
93 		      read_type, NULL, &_aics),                                \
94 	BT_AUDIO_CHRC(BT_UUID_AICS_INPUT_STATUS,                               \
95 		      BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,                 \
96 		      BT_GATT_PERM_READ_ENCRYPT,                               \
97 		      read_input_status, NULL, &_aics),                        \
98 	BT_AUDIO_CCC(aics_input_status_cfg_changed),                           \
99 	BT_AUDIO_CHRC(BT_UUID_AICS_CONTROL,                                    \
100 		      BT_GATT_CHRC_WRITE,                                      \
101 		      BT_GATT_PERM_WRITE_ENCRYPT,                              \
102 		      NULL, write_aics_control, &_aics),                       \
103 	BT_AUDIO_CHRC(BT_UUID_AICS_DESCRIPTION,                                \
104 		      BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,                 \
105 		      BT_GATT_PERM_READ_ENCRYPT,                               \
106 		      read_description, write_description, &_aics),            \
107 	BT_AUDIO_CCC(aics_description_cfg_changed)                             \
108 	}
109 
110 
111 static struct bt_aics aics_insts[CONFIG_BT_AICS_MAX_INSTANCE_COUNT];
112 static uint32_t instance_cnt;
113 BT_GATT_SERVICE_INSTANCE_DEFINE(aics_service_list, aics_insts,
114 				CONFIG_BT_AICS_MAX_INSTANCE_COUNT,
115 				BT_AICS_SERVICE_DEFINITION);
116 
aics_state_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)117 static void aics_state_cfg_changed(const struct bt_gatt_attr *attr,
118 				   uint16_t value)
119 {
120 	LOG_DBG("value 0x%04x", value);
121 }
122 
read_aics_state(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)123 static ssize_t read_aics_state(struct bt_conn *conn,
124 			       const struct bt_gatt_attr *attr, void *buf,
125 			       uint16_t len, uint16_t offset)
126 {
127 	struct bt_aics *inst = BT_AUDIO_CHRC_USER_DATA(attr);
128 
129 	LOG_DBG("gain %d, mute %u, gain_mode %u, counter %u", inst->srv.state.gain,
130 		inst->srv.state.mute, inst->srv.state.gain_mode, inst->srv.state.change_counter);
131 
132 	return bt_gatt_attr_read(conn, attr, buf, len, offset, &inst->srv.state,
133 				 sizeof(inst->srv.state));
134 }
135 
read_aics_gain_settings(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)136 static ssize_t read_aics_gain_settings(struct bt_conn *conn,
137 				       const struct bt_gatt_attr *attr,
138 				       void *buf, uint16_t len, uint16_t offset)
139 {
140 	struct bt_aics *inst = BT_AUDIO_CHRC_USER_DATA(attr);
141 
142 	LOG_DBG("units %u, min %d, max %d", inst->srv.gain_settings.units,
143 		inst->srv.gain_settings.minimum, inst->srv.gain_settings.maximum);
144 
145 	return bt_gatt_attr_read(conn, attr, buf, len, offset,
146 				 &inst->srv.gain_settings,
147 				 sizeof(inst->srv.gain_settings));
148 }
149 
read_type(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)150 static ssize_t read_type(struct bt_conn *conn, const struct bt_gatt_attr *attr,
151 			 void *buf, uint16_t len, uint16_t offset)
152 {
153 	struct bt_aics *inst = BT_AUDIO_CHRC_USER_DATA(attr);
154 
155 	LOG_DBG("%u", inst->srv.type);
156 
157 	return bt_gatt_attr_read(conn, attr, buf, len, offset, &inst->srv.type,
158 				 sizeof(inst->srv.type));
159 }
160 
aics_input_status_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)161 static void aics_input_status_cfg_changed(const struct bt_gatt_attr *attr,
162 					  uint16_t value)
163 {
164 	LOG_DBG("value 0x%04x", value);
165 }
166 
read_input_status(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)167 static ssize_t read_input_status(struct bt_conn *conn,
168 				 const struct bt_gatt_attr *attr, void *buf,
169 				 uint16_t len, uint16_t offset)
170 {
171 	struct bt_aics *inst = BT_AUDIO_CHRC_USER_DATA(attr);
172 
173 	LOG_DBG("%u", inst->srv.status);
174 
175 	return bt_gatt_attr_read(conn, attr, buf, len, offset, &inst->srv.status,
176 				 sizeof(inst->srv.status));
177 }
178 
aics_notify_str(enum bt_aics_notify notify)179 static const char *aics_notify_str(enum bt_aics_notify notify)
180 {
181 	switch (notify) {
182 	case AICS_NOTIFY_STATE:
183 		return "state";
184 	case AICS_NOTIFY_DESCRIPTION:
185 		return "description";
186 	case AICS_NOTIFY_STATUS:
187 		return "status";
188 	default:
189 		return "unknown";
190 	}
191 }
192 
notify_work_reschedule(struct bt_aics * inst,enum bt_aics_notify notify,k_timeout_t delay)193 static void notify_work_reschedule(struct bt_aics *inst, enum bt_aics_notify notify,
194 				   k_timeout_t delay)
195 {
196 	int err;
197 
198 	atomic_set_bit(inst->srv.notify, notify);
199 
200 	err = k_work_reschedule(&inst->srv.notify_work, K_NO_WAIT);
201 	if (err < 0) {
202 		LOG_ERR("Failed to reschedule %s notification err %d",
203 			aics_notify_str(notify), err);
204 	}
205 }
206 
notify(struct bt_aics * inst,enum bt_aics_notify notify,const struct bt_uuid * uuid,const void * data,uint16_t len)207 static void notify(struct bt_aics *inst, enum bt_aics_notify notify, const struct bt_uuid *uuid,
208 		   const void *data, uint16_t len)
209 {
210 	int err;
211 
212 	err = bt_gatt_notify_uuid(NULL, uuid, inst->srv.service_p->attrs, data, len);
213 	if (err == -ENOMEM) {
214 		notify_work_reschedule(inst, notify, K_USEC(BT_AUDIO_NOTIFY_RETRY_DELAY_US));
215 	} else if (err < 0 && err != -ENOTCONN) {
216 		LOG_ERR("Notify %s err %d", aics_notify_str(notify), err);
217 	}
218 }
219 
notify_work_handler(struct k_work * work)220 static void notify_work_handler(struct k_work *work)
221 {
222 	struct k_work_delayable *d_work = k_work_delayable_from_work(work);
223 	struct bt_aics *inst = CONTAINER_OF(d_work, struct bt_aics, srv.notify_work);
224 
225 	if (atomic_test_and_clear_bit(inst->srv.notify, AICS_NOTIFY_STATE)) {
226 		notify(inst, AICS_NOTIFY_STATE, BT_UUID_AICS_STATE, &inst->srv.state,
227 		       sizeof(inst->srv.state));
228 	}
229 
230 	if (atomic_test_and_clear_bit(inst->srv.notify, AICS_NOTIFY_DESCRIPTION)) {
231 		notify(inst, AICS_NOTIFY_DESCRIPTION, BT_UUID_AICS_DESCRIPTION,
232 		       &inst->srv.description, strlen(inst->srv.description));
233 	}
234 
235 	if (atomic_test_and_clear_bit(inst->srv.notify, AICS_NOTIFY_STATUS)) {
236 		notify(inst, AICS_NOTIFY_STATUS, BT_UUID_AICS_INPUT_STATUS, &inst->srv.status,
237 		       sizeof(inst->srv.status));
238 	}
239 }
240 
value_changed(struct bt_aics * inst,enum bt_aics_notify notify)241 static void value_changed(struct bt_aics *inst, enum bt_aics_notify notify)
242 {
243 	notify_work_reschedule(inst, notify, K_NO_WAIT);
244 }
245 #else
246 #define value_changed(...)
247 #endif /* CONFIG_BT_AICS */
248 
write_aics_control(struct bt_conn * conn,const struct bt_gatt_attr * attr,const void * buf,uint16_t len,uint16_t offset,uint8_t flags)249 static ssize_t write_aics_control(struct bt_conn *conn,
250 				  const struct bt_gatt_attr *attr,
251 				  const void *buf, uint16_t len,
252 				  uint16_t offset, uint8_t flags)
253 {
254 	struct bt_aics *inst = BT_AUDIO_CHRC_USER_DATA(attr);
255 	const struct bt_aics_gain_control *cp = buf;
256 	bool notify = false;
257 
258 	if (offset) {
259 		return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
260 	}
261 
262 	if (!len || !buf) {
263 		return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
264 	}
265 
266 	/* Check opcode before length */
267 	if (!VALID_AICS_OPCODE(cp->cp.opcode)) {
268 		LOG_DBG("Invalid opcode %u", cp->cp.opcode);
269 		return BT_GATT_ERR(BT_AICS_ERR_OP_NOT_SUPPORTED);
270 	}
271 
272 	if ((len < AICS_CP_LEN) ||
273 	    (len == AICS_CP_SET_GAIN_LEN && cp->cp.opcode != BT_AICS_OPCODE_SET_GAIN) ||
274 	    (len > AICS_CP_SET_GAIN_LEN)) {
275 		return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
276 	}
277 
278 	LOG_DBG("Opcode %u, counter %u", cp->cp.opcode, cp->cp.counter);
279 	if (cp->cp.counter != inst->srv.state.change_counter) {
280 		return BT_GATT_ERR(BT_AICS_ERR_INVALID_COUNTER);
281 	}
282 
283 	switch (cp->cp.opcode) {
284 	case BT_AICS_OPCODE_SET_GAIN:
285 		LOG_DBG("Set gain %d", cp->gain_setting);
286 		if (cp->gain_setting < inst->srv.gain_settings.minimum ||
287 		    cp->gain_setting > inst->srv.gain_settings.maximum) {
288 			return BT_GATT_ERR(BT_AICS_ERR_OUT_OF_RANGE);
289 		}
290 		if (BT_AICS_INPUT_MODE_SETTABLE(inst->srv.state.gain_mode) &&
291 		    inst->srv.state.gain != cp->gain_setting) {
292 			inst->srv.state.gain = cp->gain_setting;
293 			notify = true;
294 		}
295 		break;
296 	case BT_AICS_OPCODE_UNMUTE:
297 		LOG_DBG("Unmute");
298 		if (inst->srv.state.mute == BT_AICS_STATE_MUTE_DISABLED) {
299 			return BT_GATT_ERR(BT_AICS_ERR_MUTE_DISABLED);
300 		}
301 		if (inst->srv.state.mute != BT_AICS_STATE_UNMUTED) {
302 			inst->srv.state.mute = BT_AICS_STATE_UNMUTED;
303 			notify = true;
304 		}
305 		break;
306 	case BT_AICS_OPCODE_MUTE:
307 		LOG_DBG("Mute");
308 		if (inst->srv.state.mute == BT_AICS_STATE_MUTE_DISABLED) {
309 			return BT_GATT_ERR(BT_AICS_ERR_MUTE_DISABLED);
310 		}
311 		if (inst->srv.state.mute != BT_AICS_STATE_MUTED) {
312 			inst->srv.state.mute = BT_AICS_STATE_MUTED;
313 			notify = true;
314 		}
315 		break;
316 	case BT_AICS_OPCODE_SET_MANUAL:
317 		LOG_DBG("Set manual mode");
318 		if (BT_AICS_INPUT_MODE_IMMUTABLE(inst->srv.state.gain_mode)) {
319 			return BT_GATT_ERR(BT_AICS_ERR_GAIN_MODE_NOT_ALLOWED);
320 		}
321 		if (inst->srv.state.gain_mode != BT_AICS_MODE_MANUAL) {
322 			inst->srv.state.gain_mode = BT_AICS_MODE_MANUAL;
323 			notify = true;
324 		}
325 		break;
326 	case BT_AICS_OPCODE_SET_AUTO:
327 		LOG_DBG("Set automatic mode");
328 		if (BT_AICS_INPUT_MODE_IMMUTABLE(inst->srv.state.gain_mode)) {
329 			return BT_GATT_ERR(BT_AICS_ERR_GAIN_MODE_NOT_ALLOWED);
330 		}
331 		if (inst->srv.state.gain_mode != BT_AICS_MODE_AUTO) {
332 			inst->srv.state.gain_mode = BT_AICS_MODE_AUTO;
333 			notify = true;
334 		}
335 		break;
336 	default:
337 		return BT_GATT_ERR(BT_AICS_ERR_OP_NOT_SUPPORTED);
338 	}
339 
340 	if (notify) {
341 		inst->srv.state.change_counter++;
342 
343 		LOG_DBG("New state: gain %d, mute %u, gain_mode %u, counter %u",
344 			inst->srv.state.gain, inst->srv.state.mute, inst->srv.state.gain_mode,
345 			inst->srv.state.change_counter);
346 
347 		value_changed(inst, AICS_NOTIFY_STATE);
348 
349 		if (inst->srv.cb && inst->srv.cb->state) {
350 			inst->srv.cb->state(inst, 0, inst->srv.state.gain,
351 					inst->srv.state.mute,
352 					inst->srv.state.gain_mode);
353 		} else {
354 			LOG_DBG("Callback not registered for instance %p", inst);
355 		}
356 	}
357 
358 	return len;
359 }
360 
361 #if defined(CONFIG_BT_AICS)
aics_description_cfg_changed(const struct bt_gatt_attr * attr,uint16_t value)362 static void aics_description_cfg_changed(const struct bt_gatt_attr *attr,
363 					 uint16_t value)
364 {
365 	LOG_DBG("value 0x%04x", value);
366 }
367 #endif /* CONFIG_BT_AICS */
368 
write_description(struct bt_conn * conn,const struct bt_gatt_attr * attr,const void * buf,uint16_t len,uint16_t offset,uint8_t flags)369 static ssize_t write_description(struct bt_conn *conn,
370 				 const struct bt_gatt_attr *attr,
371 				 const void *buf, uint16_t len, uint16_t offset,
372 				 uint8_t flags)
373 {
374 	struct bt_aics *inst = BT_AUDIO_CHRC_USER_DATA(attr);
375 
376 	if (len >= sizeof(inst->srv.description)) {
377 		LOG_DBG("Output desc was clipped from length %u to %zu", len,
378 			sizeof(inst->srv.description) - 1);
379 		/* We just clip the string value if it's too long */
380 		len = (uint16_t)sizeof(inst->srv.description) - 1;
381 	}
382 
383 	if (memcmp(buf, inst->srv.description, len)) {
384 		memcpy(inst->srv.description, buf, len);
385 		inst->srv.description[len] = '\0';
386 
387 		value_changed(inst, AICS_NOTIFY_DESCRIPTION);
388 
389 		if (inst->srv.cb && inst->srv.cb->description) {
390 			inst->srv.cb->description(inst, 0,
391 						  inst->srv.description);
392 		} else {
393 			LOG_DBG("Callback not registered for instance %p", inst);
394 		}
395 	}
396 
397 	LOG_DBG("%s", inst->srv.description);
398 
399 	return len;
400 }
401 
aics_write(struct bt_aics * inst,ssize_t (* write)(struct bt_conn * conn,const struct bt_gatt_attr * attr,const void * buf,uint16_t len,uint16_t offset,uint8_t flags),const void * buf,uint16_t len)402 static int aics_write(struct bt_aics *inst,
403 		      ssize_t (*write)(struct bt_conn *conn,
404 				       const struct bt_gatt_attr *attr,
405 				       const void *buf, uint16_t len,
406 				       uint16_t offset, uint8_t flags),
407 		      const void *buf, uint16_t len)
408 {
409 	struct bt_audio_attr_user_data user_data = {
410 		.user_data = inst,
411 	};
412 	struct bt_gatt_attr attr = {
413 		.user_data = &user_data,
414 	};
415 	int err;
416 
417 	err = write(NULL, &attr, buf, len, 0, 0);
418 	if (err < 0) {
419 		return err;
420 	}
421 
422 	return 0;
423 }
424 
425 #if defined(CONFIG_BT_AICS)
read_description(struct bt_conn * conn,const struct bt_gatt_attr * attr,void * buf,uint16_t len,uint16_t offset)426 static ssize_t read_description(struct bt_conn *conn,
427 				const struct bt_gatt_attr *attr, void *buf,
428 				uint16_t len, uint16_t offset)
429 {
430 	struct bt_aics *inst = BT_AUDIO_CHRC_USER_DATA(attr);
431 
432 	LOG_DBG("%s", inst->srv.description);
433 
434 	return bt_gatt_attr_read(conn, attr, buf, len, offset,
435 				 &inst->srv.description, strlen(inst->srv.description));
436 }
437 
438 /************************ PUBLIC API ************************/
bt_aics_svc_decl_get(struct bt_aics * aics)439 void *bt_aics_svc_decl_get(struct bt_aics *aics)
440 {
441 	CHECKIF(!aics) {
442 		LOG_DBG("NULL instance");
443 		return NULL;
444 	}
445 
446 	return aics->srv.service_p->attrs;
447 }
448 
prepare_aics_instances(void)449 static void prepare_aics_instances(void)
450 {
451 	for (int i = 0; i < ARRAY_SIZE(aics_insts); i++) {
452 		aics_insts[i].srv.service_p = &aics_service_list[i];
453 	}
454 }
455 
bt_aics_register(struct bt_aics * aics,struct bt_aics_register_param * param)456 int bt_aics_register(struct bt_aics *aics, struct bt_aics_register_param *param)
457 {
458 	int err;
459 	static bool instance_prepared;
460 
461 	CHECKIF(!aics) {
462 		LOG_DBG("NULL aics pointer");
463 		return -ENOTCONN;
464 	}
465 
466 	CHECKIF(!param) {
467 		LOG_DBG("NULL param");
468 		return -EINVAL;
469 	}
470 
471 	if (!instance_prepared) {
472 		prepare_aics_instances();
473 		instance_prepared = true;
474 	}
475 
476 	CHECKIF(aics->srv.initialized) {
477 		return -EALREADY;
478 	}
479 
480 	CHECKIF(param->mute > BT_AICS_STATE_MUTE_DISABLED) {
481 		LOG_DBG("Invalid AICS mute value: %u", param->mute);
482 		return -EINVAL;
483 	}
484 
485 	CHECKIF(param->gain_mode > BT_AICS_MODE_AUTO) {
486 		LOG_DBG("Invalid AICS mode value: %u", param->gain_mode);
487 		return -EINVAL;
488 	}
489 
490 	CHECKIF(param->type > BT_AICS_INPUT_TYPE_STREAMING) {
491 		LOG_DBG("Invalid AICS input type value: %u", param->type);
492 		return -EINVAL;
493 	}
494 
495 	CHECKIF(param->units == 0) {
496 		LOG_DBG("AICS units value shall not be 0");
497 		return -EINVAL;
498 	}
499 
500 	CHECKIF(!(param->min_gain <= param->max_gain)) {
501 		LOG_DBG("AICS min gain (%d) shall be lower than or equal to max gain (%d)",
502 			param->min_gain, param->max_gain);
503 		return -EINVAL;
504 	}
505 
506 	CHECKIF(param->gain < param->min_gain || param->gain > param->max_gain) {
507 		LOG_DBG("AICS gain (%d) shall be not lower than min gain (%d) "
508 		       "or higher than max gain (%d)",
509 		       param->gain, param->min_gain, param->max_gain);
510 		return -EINVAL;
511 	}
512 
513 	aics->srv.state.gain = param->gain;
514 	aics->srv.state.mute = param->mute;
515 	aics->srv.state.gain_mode = param->gain_mode;
516 	aics->srv.gain_settings.units = param->units;
517 	aics->srv.gain_settings.minimum = param->min_gain;
518 	aics->srv.gain_settings.maximum = param->max_gain;
519 	aics->srv.type = param->type;
520 	aics->srv.status = param->status ? BT_AICS_STATUS_ACTIVE : BT_AICS_STATUS_INACTIVE;
521 	aics->srv.cb = param->cb;
522 
523 	atomic_clear(aics->srv.notify);
524 	k_work_init_delayable(&aics->srv.notify_work, notify_work_handler);
525 
526 	if (param->description) {
527 		(void)utf8_lcpy(aics->srv.description, param->description,
528 				sizeof(aics->srv.description));
529 		if (IS_ENABLED(CONFIG_BT_AICS_LOG_LEVEL_DBG) &&
530 		    strcmp(aics->srv.description, param->description)) {
531 			LOG_DBG("Input desc clipped to %s", aics->srv.description);
532 		}
533 	}
534 
535 	/* Iterate over the attributes in AICS (starting from i = 1 to skip the
536 	 * service declaration) to find the BT_UUID_AICS_DESCRIPTION and update
537 	 * the characteristic value (at [i]), update that with the write
538 	 * permission and callback, and also update the characteristic
539 	 * declaration (always found at [i - 1]) with the
540 	 * BT_GATT_CHRC_WRITE_WITHOUT_RESP property.
541 	 */
542 	if (param->desc_writable) {
543 		for (int i = 1; i < aics->srv.service_p->attr_count; i++) {
544 			struct bt_gatt_attr *attr;
545 
546 			attr = &aics->srv.service_p->attrs[i];
547 
548 			if (!bt_uuid_cmp(attr->uuid, BT_UUID_AICS_DESCRIPTION)) {
549 				/* Update attr and chrc to be writable */
550 				struct bt_gatt_chrc *chrc;
551 
552 				chrc = aics->srv.service_p->attrs[i - 1].user_data;
553 				attr->perm |= BT_GATT_PERM_WRITE_ENCRYPT;
554 				chrc->properties |= BT_GATT_CHRC_WRITE_WITHOUT_RESP;
555 
556 				break;
557 			}
558 		}
559 	}
560 
561 	err = bt_gatt_service_register(aics->srv.service_p);
562 	if (err) {
563 		LOG_DBG("Could not register AICS service");
564 		return err;
565 	}
566 
567 	aics->srv.initialized = true;
568 
569 	return 0;
570 }
571 
bt_aics_free_instance_get(void)572 struct bt_aics *bt_aics_free_instance_get(void)
573 {
574 	if (instance_cnt >= CONFIG_BT_AICS_MAX_INSTANCE_COUNT) {
575 		return NULL;
576 	}
577 
578 	return (struct bt_aics *)&aics_insts[instance_cnt++];
579 }
580 
581 /****************************** PUBLIC API ******************************/
bt_aics_deactivate(struct bt_aics * inst)582 int bt_aics_deactivate(struct bt_aics *inst)
583 {
584 	CHECKIF(!inst) {
585 		LOG_DBG("NULL instance");
586 		return -EINVAL;
587 	}
588 
589 	if (IS_ENABLED(CONFIG_BT_AICS_CLIENT) && inst->client_instance) {
590 		return -ENOTSUP;
591 	}
592 
593 	if (inst->srv.status == BT_AICS_STATUS_ACTIVE) {
594 		inst->srv.status = BT_AICS_STATUS_INACTIVE;
595 		LOG_DBG("Instance %p: Status was set to inactive", inst);
596 
597 		value_changed(inst, AICS_NOTIFY_STATUS);
598 
599 		if (inst->srv.cb && inst->srv.cb->status) {
600 			inst->srv.cb->status(inst, 0, inst->srv.status);
601 		} else {
602 			LOG_DBG("Callback not registered for instance %p", inst);
603 		}
604 	}
605 
606 	return 0;
607 }
608 
bt_aics_activate(struct bt_aics * inst)609 int bt_aics_activate(struct bt_aics *inst)
610 {
611 	CHECKIF(!inst) {
612 		LOG_DBG("NULL instance");
613 		return -EINVAL;
614 	}
615 
616 	if (IS_ENABLED(CONFIG_BT_AICS_CLIENT) && inst->client_instance) {
617 		return -ENOTSUP;
618 	}
619 
620 	if (inst->srv.status == BT_AICS_STATUS_INACTIVE) {
621 		inst->srv.status = BT_AICS_STATUS_ACTIVE;
622 		LOG_DBG("Instance %p: Status was set to active", inst);
623 
624 		value_changed(inst, AICS_NOTIFY_STATUS);
625 
626 		if (inst->srv.cb && inst->srv.cb->status) {
627 			inst->srv.cb->status(inst, 0, inst->srv.status);
628 		} else {
629 			LOG_DBG("Callback not registered for instance %p", inst);
630 		}
631 	}
632 
633 	return 0;
634 }
635 
636 #endif /* CONFIG_BT_AICS */
bt_aics_gain_set_manual_only(struct bt_aics * inst)637 int bt_aics_gain_set_manual_only(struct bt_aics *inst)
638 {
639 	CHECKIF(!inst) {
640 		LOG_DBG("NULL instance");
641 		return -EINVAL;
642 	}
643 
644 	inst->srv.state.gain_mode = BT_AICS_MODE_MANUAL_ONLY;
645 
646 	value_changed(inst, AICS_NOTIFY_STATE);
647 
648 	return 0;
649 }
650 
bt_aics_gain_set_auto_only(struct bt_aics * inst)651 int bt_aics_gain_set_auto_only(struct bt_aics *inst)
652 {
653 	CHECKIF(!inst) {
654 		LOG_DBG("NULL instance");
655 		return -EINVAL;
656 	}
657 
658 	inst->srv.state.gain_mode = BT_AICS_MODE_AUTO_ONLY;
659 
660 	value_changed(inst, AICS_NOTIFY_STATE);
661 
662 	return 0;
663 }
664 
bt_aics_state_get(struct bt_aics * inst)665 int bt_aics_state_get(struct bt_aics *inst)
666 {
667 	CHECKIF(!inst) {
668 		LOG_DBG("NULL instance");
669 		return -EINVAL;
670 	}
671 
672 	if (IS_ENABLED(CONFIG_BT_AICS_CLIENT) && inst->client_instance) {
673 		return bt_aics_client_state_get(inst);
674 	} else if (IS_ENABLED(CONFIG_BT_AICS) && !inst->client_instance) {
675 		if (inst->srv.cb && inst->srv.cb->state) {
676 			inst->srv.cb->state(inst, 0, inst->srv.state.gain,
677 					    inst->srv.state.mute,
678 					    inst->srv.state.gain_mode);
679 		} else {
680 			LOG_DBG("Callback not registered for instance %p", inst);
681 		}
682 		return 0;
683 	}
684 
685 	return -ENOTSUP;
686 }
687 
bt_aics_gain_setting_get(struct bt_aics * inst)688 int bt_aics_gain_setting_get(struct bt_aics *inst)
689 {
690 	CHECKIF(!inst) {
691 		LOG_DBG("NULL instance");
692 		return -EINVAL;
693 	}
694 
695 	if (IS_ENABLED(CONFIG_BT_AICS_CLIENT) && inst->client_instance) {
696 		return bt_aics_client_gain_setting_get(inst);
697 	} else if (IS_ENABLED(CONFIG_BT_AICS) && !inst->client_instance) {
698 		if (inst->srv.cb && inst->srv.cb->gain_setting) {
699 			inst->srv.cb->gain_setting(inst, 0,
700 						   inst->srv.gain_settings.units,
701 						   inst->srv.gain_settings.minimum,
702 						   inst->srv.gain_settings.maximum);
703 		} else {
704 			LOG_DBG("Callback not registered for instance %p", inst);
705 		}
706 		return 0;
707 	}
708 
709 	return -ENOTSUP;
710 }
711 
bt_aics_type_get(struct bt_aics * inst)712 int bt_aics_type_get(struct bt_aics *inst)
713 {
714 	CHECKIF(!inst) {
715 		LOG_DBG("NULL instance");
716 		return -EINVAL;
717 	}
718 
719 	if (IS_ENABLED(CONFIG_BT_AICS_CLIENT) && inst->client_instance) {
720 		return bt_aics_client_type_get(inst);
721 	} else if (IS_ENABLED(CONFIG_BT_AICS) && !inst->client_instance) {
722 		if (inst->srv.cb && inst->srv.cb->type) {
723 			inst->srv.cb->type(inst, 0, inst->srv.type);
724 		} else {
725 			LOG_DBG("Callback not registered for instance %p", inst);
726 		}
727 		return 0;
728 	}
729 
730 	return -ENOTSUP;
731 }
732 
bt_aics_status_get(struct bt_aics * inst)733 int bt_aics_status_get(struct bt_aics *inst)
734 {
735 	CHECKIF(!inst) {
736 		LOG_DBG("NULL instance");
737 		return -EINVAL;
738 	}
739 
740 	if (IS_ENABLED(CONFIG_BT_AICS_CLIENT) && inst->client_instance) {
741 		return bt_aics_client_status_get(inst);
742 	} else if (IS_ENABLED(CONFIG_BT_AICS) && !inst->client_instance) {
743 		if (inst->srv.cb && inst->srv.cb->status) {
744 			inst->srv.cb->status(inst, 0, inst->srv.status);
745 		} else {
746 			LOG_DBG("Callback not registered for instance %p", inst);
747 		}
748 		return 0;
749 	}
750 
751 	return -ENOTSUP;
752 }
753 
bt_aics_disable_mute(struct bt_aics * inst)754 int bt_aics_disable_mute(struct bt_aics *inst)
755 {
756 	CHECKIF(!inst) {
757 		LOG_DBG("NULL instance");
758 		return -EINVAL;
759 	}
760 
761 	inst->srv.state.mute = BT_AICS_STATE_MUTE_DISABLED;
762 
763 	value_changed(inst, AICS_NOTIFY_STATE);
764 
765 	return 0;
766 }
767 
bt_aics_unmute(struct bt_aics * inst)768 int bt_aics_unmute(struct bt_aics *inst)
769 {
770 	CHECKIF(!inst) {
771 		LOG_DBG("NULL instance");
772 		return -EINVAL;
773 	}
774 
775 	if (IS_ENABLED(CONFIG_BT_AICS_CLIENT) && inst->client_instance) {
776 		return bt_aics_client_unmute(inst);
777 	} else if (IS_ENABLED(CONFIG_BT_AICS) && !inst->client_instance) {
778 		struct bt_aics_control cp;
779 
780 		cp.opcode = BT_AICS_OPCODE_UNMUTE;
781 		cp.counter = inst->srv.state.change_counter;
782 
783 		return aics_write(inst, write_aics_control, &cp, sizeof(cp));
784 	}
785 
786 	return -ENOTSUP;
787 }
788 
bt_aics_mute(struct bt_aics * inst)789 int bt_aics_mute(struct bt_aics *inst)
790 {
791 	CHECKIF(!inst) {
792 		LOG_DBG("NULL instance");
793 		return -EINVAL;
794 	}
795 
796 	if (IS_ENABLED(CONFIG_BT_AICS_CLIENT) && inst->client_instance) {
797 		return bt_aics_client_mute(inst);
798 	} else if (IS_ENABLED(CONFIG_BT_AICS) && !inst->client_instance) {
799 		struct bt_aics_control cp;
800 
801 		cp.opcode = BT_AICS_OPCODE_MUTE;
802 		cp.counter = inst->srv.state.change_counter;
803 
804 		return aics_write(inst, write_aics_control, &cp, sizeof(cp));
805 	}
806 
807 	return -ENOTSUP;
808 }
809 
bt_aics_manual_gain_set(struct bt_aics * inst)810 int bt_aics_manual_gain_set(struct bt_aics *inst)
811 {
812 	CHECKIF(!inst) {
813 		LOG_DBG("NULL instance");
814 		return -EINVAL;
815 	}
816 
817 	if (IS_ENABLED(CONFIG_BT_AICS_CLIENT) && inst->client_instance) {
818 		return bt_aics_client_manual_gain_set(inst);
819 	} else if (IS_ENABLED(CONFIG_BT_AICS) && !inst->client_instance) {
820 		struct bt_aics_control cp;
821 
822 		cp.opcode = BT_AICS_OPCODE_SET_MANUAL;
823 		cp.counter = inst->srv.state.change_counter;
824 
825 		return aics_write(inst, write_aics_control, &cp, sizeof(cp));
826 	}
827 
828 	return -ENOTSUP;
829 }
830 
bt_aics_automatic_gain_set(struct bt_aics * inst)831 int bt_aics_automatic_gain_set(struct bt_aics *inst)
832 {
833 	CHECKIF(!inst) {
834 		LOG_DBG("NULL instance");
835 		return -EINVAL;
836 	}
837 
838 	if (IS_ENABLED(CONFIG_BT_AICS_CLIENT) && inst->client_instance) {
839 		return bt_aics_client_automatic_gain_set(inst);
840 	} else if (IS_ENABLED(CONFIG_BT_AICS) && !inst->client_instance) {
841 		struct bt_aics_control cp;
842 
843 		cp.opcode = BT_AICS_OPCODE_SET_AUTO;
844 		cp.counter = inst->srv.state.change_counter;
845 
846 		return aics_write(inst, write_aics_control, &cp, sizeof(cp));
847 	}
848 
849 	return -ENOTSUP;
850 }
851 
bt_aics_gain_set(struct bt_aics * inst,int8_t gain)852 int bt_aics_gain_set(struct bt_aics *inst, int8_t gain)
853 {
854 	CHECKIF(!inst) {
855 		LOG_DBG("NULL instance");
856 		return -EINVAL;
857 	}
858 
859 	if (IS_ENABLED(CONFIG_BT_AICS_CLIENT) && inst->client_instance) {
860 		return bt_aics_client_gain_set(inst, gain);
861 	} else if (IS_ENABLED(CONFIG_BT_AICS) && !inst->client_instance) {
862 		struct bt_aics_gain_control cp;
863 
864 		cp.cp.opcode = BT_AICS_OPCODE_SET_GAIN;
865 		cp.cp.counter = inst->srv.state.change_counter;
866 		cp.gain_setting = gain;
867 
868 		return aics_write(inst, write_aics_control, &cp, sizeof(cp));
869 	}
870 
871 	return -ENOTSUP;
872 }
873 
bt_aics_description_get(struct bt_aics * inst)874 int bt_aics_description_get(struct bt_aics *inst)
875 {
876 	CHECKIF(!inst) {
877 		LOG_DBG("NULL instance");
878 		return -EINVAL;
879 	}
880 
881 	if (IS_ENABLED(CONFIG_BT_AICS_CLIENT) && inst->client_instance) {
882 		return bt_aics_client_description_get(inst);
883 	} else if (IS_ENABLED(CONFIG_BT_AICS) && !inst->client_instance) {
884 		if (inst->srv.cb && inst->srv.cb->description) {
885 			inst->srv.cb->description(inst, 0,
886 						  inst->srv.description);
887 		} else {
888 			LOG_DBG("Callback not registered for instance %p", inst);
889 		}
890 		return 0;
891 	}
892 
893 	return -ENOTSUP;
894 }
895 
bt_aics_description_set(struct bt_aics * inst,const char * description)896 int bt_aics_description_set(struct bt_aics *inst, const char *description)
897 {
898 	CHECKIF(!inst) {
899 		LOG_DBG("NULL instance");
900 		return -EINVAL;
901 	}
902 
903 	CHECKIF(!description) {
904 		LOG_DBG("NULL description");
905 		return -EINVAL;
906 	}
907 
908 	if (IS_ENABLED(CONFIG_BT_AICS_CLIENT) && inst->client_instance) {
909 		return bt_aics_client_description_set(inst, description);
910 	} else if (IS_ENABLED(CONFIG_BT_AICS) && !inst->client_instance) {
911 		return aics_write(inst, write_description, description, strlen(description));
912 	}
913 
914 	return -ENOTSUP;
915 }
916