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