1 /* btp_aics.c - Bluetooth AICS Tester */
2 
3 /*
4  * Copyright (c) 2023 Codecoup
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include <stddef.h>
10 #include <errno.h>
11 
12 #include <zephyr/types.h>
13 #include <zephyr/kernel.h>
14 
15 #include <zephyr/bluetooth/bluetooth.h>
16 #include <zephyr/bluetooth/audio/audio.h>
17 #include <zephyr/bluetooth/audio/micp.h>
18 #include <zephyr/bluetooth/audio/aics.h>
19 #include <zephyr/logging/log.h>
20 #include <zephyr/sys/byteorder.h>
21 
22 #include "bap_endpoint.h"
23 #include "btp/btp.h"
24 
25 #define LOG_MODULE_NAME bttester_aics
26 LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL);
27 
28 #define BT_AICS_MAX_INPUT_DESCRIPTION_SIZE 16
29 #define BT_AICS_MAX_OUTPUT_DESCRIPTION_SIZE 16
30 
31 struct btp_aics_instance aics_client_instance;
32 struct btp_aics_instance aics_server_instance;
33 
34 static struct net_buf_simple *rx_ev_buf = NET_BUF_SIMPLE(BT_AICS_MAX_INPUT_DESCRIPTION_SIZE +
35 							 sizeof(struct btp_aics_description_ev));
36 
aics_supported_commands(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)37 static uint8_t aics_supported_commands(const void *cmd, uint16_t cmd_len, void *rsp,
38 				       uint16_t *rsp_len)
39 {
40 	struct btp_aics_read_supported_commands_rp *rp = rsp;
41 
42 	/* octet 0 */
43 	tester_set_bit(rp->data, BTP_AICS_READ_SUPPORTED_COMMANDS);
44 	tester_set_bit(rp->data, BTP_AICS_SET_GAIN);
45 	tester_set_bit(rp->data, BTP_AICS_MUTE);
46 	tester_set_bit(rp->data, BTP_AICS_UNMUTE);
47 	tester_set_bit(rp->data, BTP_AICS_MAN_GAIN_SET);
48 	tester_set_bit(rp->data, BTP_AICS_AUTO_GAIN_SET);
49 	tester_set_bit(rp->data, BTP_AICS_SET_MAN_GAIN_ONLY);
50 
51 	/* octet 1 */
52 	tester_set_bit(rp->data, BTP_AICS_SET_AUTO_GAIN_ONLY);
53 	tester_set_bit(rp->data, BTP_AICS_AUDIO_DESCRIPTION_SET);
54 	tester_set_bit(rp->data, BTP_AICS_MUTE_DISABLE);
55 	tester_set_bit(rp->data, BTP_AICS_GAIN_SETTING_PROP_GET);
56 	tester_set_bit(rp->data, BTP_AICS_TYPE_GET);
57 	tester_set_bit(rp->data, BTP_AICS_STATUS_GET);
58 	tester_set_bit(rp->data, BTP_AICS_STATE_GET);
59 
60 	/* octet 2 */
61 	tester_set_bit(rp->data, BTP_AICS_DESCRIPTION_GET);
62 
63 	*rsp_len = sizeof(*rp) + 2;
64 
65 	return BTP_STATUS_SUCCESS;
66 }
67 
btp_send_aics_state_ev(struct bt_conn * conn,uint8_t att_status,int8_t gain,uint8_t mute,uint8_t mode)68 void btp_send_aics_state_ev(struct bt_conn *conn, uint8_t att_status, int8_t gain, uint8_t mute,
69 			    uint8_t mode)
70 {
71 	struct btp_aics_state_ev ev;
72 
73 	bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
74 
75 	ev.att_status = att_status;
76 	ev.gain = gain;
77 	ev.mute = mute;
78 	ev.mode = mode;
79 
80 	tester_event(BTP_SERVICE_ID_AICS, BTP_AICS_STATE_EV, &ev, sizeof(ev));
81 }
82 
btp_send_gain_setting_properties_ev(struct bt_conn * conn,uint8_t att_status,uint8_t units,int8_t minimum,int8_t maximum)83 void btp_send_gain_setting_properties_ev(struct bt_conn *conn,  uint8_t att_status, uint8_t units,
84 					 int8_t minimum, int8_t maximum)
85 {
86 	struct btp_gain_setting_properties_ev ev;
87 
88 	bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
89 
90 	ev.att_status = att_status;
91 	ev.units = units;
92 	ev.minimum = minimum;
93 	ev.maximum = maximum;
94 
95 	tester_event(BTP_SERVICE_ID_AICS, BTP_GAIN_SETTING_PROPERTIES_EV, &ev, sizeof(ev));
96 }
97 
btp_send_aics_input_type_event(struct bt_conn * conn,uint8_t att_status,uint8_t input_type)98 void btp_send_aics_input_type_event(struct bt_conn *conn, uint8_t att_status, uint8_t input_type)
99 {
100 	struct btp_aics_input_type_ev ev;
101 
102 	bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
103 
104 	ev.att_status = att_status;
105 	ev.input_type = input_type;
106 
107 	tester_event(BTP_SERVICE_ID_AICS, BTP_AICS_INPUT_TYPE_EV, &ev, sizeof(ev));
108 }
109 
btp_send_aics_status_ev(struct bt_conn * conn,uint8_t att_status,bool active)110 void btp_send_aics_status_ev(struct bt_conn *conn, uint8_t att_status, bool active)
111 {
112 	struct btp_aics_status_ev ev;
113 
114 	bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
115 
116 	ev.att_status = att_status;
117 	ev.active = active;
118 
119 	tester_event(BTP_SERVICE_ID_AICS, BTP_AICS_STATUS_EV, &ev, sizeof(ev));
120 }
121 
btp_send_aics_description_ev(struct bt_conn * conn,uint8_t att_status,uint8_t data_len,char * description)122 void btp_send_aics_description_ev(struct bt_conn *conn, uint8_t att_status, uint8_t data_len,
123 				  char *description)
124 {
125 	struct btp_aics_description_ev *ev;
126 
127 	net_buf_simple_init(rx_ev_buf, 0);
128 
129 	ev = net_buf_simple_add(rx_ev_buf, sizeof(*ev));
130 
131 	bt_addr_le_copy(&ev->address, bt_conn_get_dst(conn));
132 
133 	ev->att_status = att_status;
134 	ev->data_len = data_len;
135 	memcpy(ev->data, description, data_len);
136 
137 	tester_event(BTP_SERVICE_ID_AICS, BTP_AICS_DESCRIPTION_EV, ev, sizeof(*ev) + data_len);
138 }
139 
btp_send_aics_procedure_ev(struct bt_conn * conn,uint8_t att_status,uint8_t opcode)140 void btp_send_aics_procedure_ev(struct bt_conn *conn, uint8_t att_status, uint8_t opcode)
141 {
142 	struct btp_aics_procedure_ev ev;
143 
144 	bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
145 
146 	ev.att_status = att_status;
147 	ev.opcode = opcode;
148 
149 	tester_event(BTP_SERVICE_ID_AICS, BTP_AICS_PROCEDURE_EV, &ev, sizeof(ev));
150 }
151 
aics_set_gain(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)152 static uint8_t aics_set_gain(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
153 {
154 	const struct btp_aics_set_gain_cmd *cp = cmd;
155 
156 	LOG_DBG("AICS set gain %d", cp->gain);
157 
158 	if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) {
159 		if (bt_aics_gain_set(aics_client_instance.aics[0], cp->gain) != 0) {
160 			return BTP_STATUS_FAILED;
161 		}
162 	} else {
163 		for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) {
164 			if (bt_aics_gain_set(aics_server_instance.aics[i], cp->gain) != 0) {
165 				return BTP_STATUS_FAILED;
166 			}
167 		}
168 	}
169 
170 	return BTP_STATUS_SUCCESS;
171 }
172 
aics_unmute(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)173 static uint8_t aics_unmute(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
174 {
175 	const struct btp_aics_unmute_cmd *cp = cmd;
176 
177 	LOG_DBG("AICS Unmute");
178 
179 	if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) {
180 		if (bt_aics_unmute(aics_client_instance.aics[0]) != 0) {
181 			return BTP_STATUS_FAILED;
182 		}
183 	} else {
184 		for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) {
185 			if (bt_aics_unmute(aics_server_instance.aics[i]) != 0) {
186 				return BTP_STATUS_FAILED;
187 			}
188 		}
189 	}
190 
191 	return BTP_STATUS_SUCCESS;
192 }
193 
aics_mute(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)194 static uint8_t aics_mute(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
195 {
196 	const struct btp_aics_mute_cmd *cp = cmd;
197 
198 	LOG_DBG("AICS Mute");
199 
200 	if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) {
201 		if (bt_aics_mute(aics_client_instance.aics[0]) != 0) {
202 			return BTP_STATUS_FAILED;
203 		}
204 	} else {
205 		for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) {
206 			if (bt_aics_mute(aics_server_instance.aics[i]) != 0) {
207 				return BTP_STATUS_FAILED;
208 			}
209 		}
210 	}
211 
212 	return BTP_STATUS_SUCCESS;
213 }
214 
aics_state_get(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)215 static uint8_t aics_state_get(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
216 {
217 	const struct btp_aics_state_cmd *cp = cmd;
218 
219 	LOG_DBG("AICS State");
220 
221 	if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) {
222 		if (bt_aics_state_get(aics_client_instance.aics[0]) != 0) {
223 			return BTP_STATUS_FAILED;
224 		}
225 	} else {
226 		for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) {
227 			if (bt_aics_state_get(aics_server_instance.aics[i]) != 0) {
228 				return BTP_STATUS_FAILED;
229 			}
230 		}
231 	}
232 
233 	return BTP_STATUS_SUCCESS;
234 }
235 
aics_type_get(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)236 static uint8_t aics_type_get(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
237 {
238 	const struct btp_aics_type_cmd *cp = cmd;
239 
240 	LOG_DBG("AICS Type");
241 
242 	if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) {
243 		if (bt_aics_type_get(aics_client_instance.aics[0]) != 0) {
244 			return BTP_STATUS_FAILED;
245 		}
246 	} else {
247 		for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) {
248 			if (bt_aics_type_get(aics_server_instance.aics[i]) != 0) {
249 				return BTP_STATUS_FAILED;
250 			}
251 		}
252 	}
253 
254 	return BTP_STATUS_SUCCESS;
255 }
256 
aics_status_get(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)257 static uint8_t aics_status_get(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
258 {
259 	const struct btp_aics_status_cmd *cp = cmd;
260 
261 	LOG_DBG("AICS Status");
262 
263 	if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) {
264 		if (bt_aics_status_get(aics_client_instance.aics[0]) != 0) {
265 			return BTP_STATUS_FAILED;
266 		}
267 	} else {
268 		for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) {
269 			if (bt_aics_status_get(aics_server_instance.aics[i]) != 0) {
270 				return BTP_STATUS_FAILED;
271 			}
272 		}
273 	}
274 
275 	return BTP_STATUS_SUCCESS;
276 }
277 
aics_gain_setting_prop_get(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)278 static uint8_t aics_gain_setting_prop_get(const void *cmd, uint16_t cmd_len, void *rsp,
279 					  uint16_t *rsp_len)
280 {
281 	const struct btp_aics_gain_setting_prop_cmd *cp = cmd;
282 
283 	LOG_DBG("AICS Gain settings properties");
284 
285 	if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) {
286 		if (bt_aics_gain_setting_get(aics_client_instance.aics[0]) != 0) {
287 			return BTP_STATUS_FAILED;
288 		}
289 	} else {
290 		for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) {
291 			if (bt_aics_gain_setting_get(aics_server_instance.aics[i]) != 0) {
292 				return BTP_STATUS_FAILED;
293 			}
294 		}
295 	}
296 
297 	return BTP_STATUS_SUCCESS;
298 }
299 
aics_man_gain_set(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)300 static uint8_t aics_man_gain_set(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
301 {
302 	const struct btp_aics_manual_gain_cmd *cp = cmd;
303 
304 	LOG_DBG("AICS set manual gain mode");
305 
306 	if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) {
307 		if (bt_aics_manual_gain_set(aics_client_instance.aics[0]) != 0) {
308 			return BTP_STATUS_FAILED;
309 		}
310 	} else {
311 		for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) {
312 			if (bt_aics_manual_gain_set(aics_server_instance.aics[i]) != 0) {
313 				return BTP_STATUS_FAILED;
314 			}
315 		}
316 	}
317 
318 	return BTP_STATUS_SUCCESS;
319 }
320 
aics_auto_gain_set(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)321 static uint8_t aics_auto_gain_set(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
322 {
323 	const struct btp_aics_auto_gain_cmd *cp = cmd;
324 
325 	LOG_DBG("AICS set automatic gain mode");
326 
327 	if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) {
328 		if (bt_aics_automatic_gain_set(aics_client_instance.aics[0]) != 0) {
329 			return BTP_STATUS_FAILED;
330 		}
331 	} else {
332 		for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) {
333 			if (bt_aics_automatic_gain_set(aics_server_instance.aics[i]) != 0) {
334 				return BTP_STATUS_FAILED;
335 			}
336 		}
337 	}
338 
339 	return BTP_STATUS_SUCCESS;
340 }
341 
aics_set_man_gain_only(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)342 static uint8_t aics_set_man_gain_only(const void *cmd, uint16_t cmd_len, void *rsp,
343 				      uint16_t *rsp_len)
344 {
345 	LOG_DBG("AICS manual gain only set");
346 
347 	for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) {
348 		if (bt_aics_gain_set_manual_only(aics_server_instance.aics[i]) != 0) {
349 			return BTP_STATUS_FAILED;
350 		}
351 	}
352 
353 	return BTP_STATUS_SUCCESS;
354 }
355 
aics_set_auto_gain_only(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)356 static uint8_t aics_set_auto_gain_only(const void *cmd, uint16_t cmd_len, void *rsp,
357 				       uint16_t *rsp_len)
358 {
359 	LOG_DBG("AICS auto gain only set");
360 
361 	for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) {
362 		if (bt_aics_gain_set_auto_only(aics_server_instance.aics[i]) != 0) {
363 			return BTP_STATUS_FAILED;
364 		}
365 	}
366 
367 	return BTP_STATUS_SUCCESS;
368 }
369 
aics_mute_disable(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)370 static uint8_t aics_mute_disable(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
371 {
372 	LOG_DBG("AICS disable mute");
373 
374 	for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) {
375 		if (bt_aics_disable_mute(aics_server_instance.aics[i]) != 0) {
376 			return BTP_STATUS_FAILED;
377 		}
378 	}
379 
380 	return BTP_STATUS_SUCCESS;
381 }
382 
aics_desc_set(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)383 static uint8_t aics_desc_set(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
384 {
385 	const struct btp_aics_audio_desc_cmd *cp = cmd;
386 	char description[BT_AICS_MAX_INPUT_DESCRIPTION_SIZE];
387 
388 	LOG_DBG("AICS set description");
389 
390 	if (cmd_len < sizeof(*cp) || cmd_len != sizeof(*cp) + cp->desc_len) {
391 		return BTP_STATUS_FAILED;
392 	}
393 
394 	if (cp->desc_len >= sizeof(description)) {
395 		return BTP_STATUS_FAILED;
396 	}
397 
398 	if (cp->desc_len > (BT_AICS_MAX_INPUT_DESCRIPTION_SIZE - 1)) {
399 		return BTP_STATUS_FAILED;
400 	}
401 
402 	memcpy(description, cp->desc, cp->desc_len);
403 	description[cp->desc_len] = '\0';
404 
405 	for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) {
406 		if (bt_aics_description_set(aics_server_instance.aics[i], description) != 0) {
407 			return BTP_STATUS_FAILED;
408 		}
409 	}
410 
411 	return BTP_STATUS_SUCCESS;
412 }
413 
aics_desc_get(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)414 static uint8_t aics_desc_get(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
415 {
416 	const struct btp_aics_desc_cmd *cp = cmd;
417 
418 	LOG_DBG("AICS Description");
419 
420 	if (!bt_addr_le_eq(&cp->address, BT_ADDR_LE_ANY)) {
421 		if (bt_aics_description_get(aics_client_instance.aics[0]) != 0) {
422 			return BTP_STATUS_FAILED;
423 		}
424 	} else {
425 		for (uint8_t i = 0; i < aics_server_instance.aics_cnt; i++) {
426 			if (bt_aics_description_get(aics_server_instance.aics[i]) != 0) {
427 				return BTP_STATUS_FAILED;
428 			}
429 		}
430 	}
431 
432 	return BTP_STATUS_SUCCESS;
433 }
434 
435 static const struct btp_handler aics_handlers[] = {
436 	{
437 		.opcode = BTP_AICS_READ_SUPPORTED_COMMANDS,
438 		.index = BTP_INDEX_NONE,
439 		.expect_len = 0,
440 		.func = aics_supported_commands,
441 	},
442 	{
443 		.opcode = BTP_AICS_SET_GAIN,
444 		.expect_len = sizeof(struct btp_aics_set_gain_cmd),
445 		.func = aics_set_gain,
446 	},
447 	{
448 		.opcode = BTP_AICS_MUTE,
449 		.expect_len = sizeof(struct btp_aics_mute_cmd),
450 		.func = aics_mute,
451 	},
452 	{
453 		.opcode = BTP_AICS_UNMUTE,
454 		.expect_len = sizeof(struct btp_aics_unmute_cmd),
455 		.func = aics_unmute,
456 	},
457 	{
458 		.opcode = BTP_AICS_GAIN_SETTING_PROP_GET,
459 		.expect_len = sizeof(struct btp_aics_gain_setting_prop_cmd),
460 		.func = aics_gain_setting_prop_get,
461 	},
462 	{
463 		.opcode = BTP_AICS_MUTE_DISABLE,
464 		.expect_len = 0,
465 		.func = aics_mute_disable,
466 	},
467 	{
468 		.opcode = BTP_AICS_MAN_GAIN_SET,
469 		.expect_len = sizeof(struct btp_aics_manual_gain_cmd),
470 		.func = aics_man_gain_set,
471 	},
472 	{
473 		.opcode = BTP_AICS_AUTO_GAIN_SET,
474 		.expect_len = sizeof(struct btp_aics_auto_gain_cmd),
475 		.func = aics_auto_gain_set,
476 	},
477 	{
478 		.opcode = BTP_AICS_SET_AUTO_GAIN_ONLY,
479 		.expect_len = 0,
480 		.func = aics_set_auto_gain_only,
481 	},
482 	{
483 		.opcode = BTP_AICS_SET_MAN_GAIN_ONLY,
484 		.expect_len = 0,
485 		.func = aics_set_man_gain_only,
486 	},
487 	{
488 		.opcode = BTP_AICS_AUDIO_DESCRIPTION_SET,
489 		.expect_len = BTP_HANDLER_LENGTH_VARIABLE,
490 		.func = aics_desc_set,
491 	},
492 	{
493 		.opcode = BTP_AICS_DESCRIPTION_GET,
494 		.expect_len = sizeof(struct btp_aics_desc_cmd),
495 		.func = aics_desc_get,
496 	},
497 	{
498 		.opcode = BTP_AICS_TYPE_GET,
499 		.expect_len = sizeof(struct btp_aics_type_cmd),
500 		.func = aics_type_get,
501 	},
502 	{
503 		.opcode = BTP_AICS_STATUS_GET,
504 		.expect_len = sizeof(struct btp_aics_status_cmd),
505 		.func = aics_status_get,
506 	},
507 	{
508 		.opcode = BTP_AICS_STATE_GET,
509 		.expect_len = sizeof(struct btp_aics_state_cmd),
510 		.func = aics_state_get,
511 	},
512 };
513 
aics_state_cb(struct bt_aics * inst,int err,int8_t gain,uint8_t mute,uint8_t mode)514 static void aics_state_cb(struct bt_aics *inst, int err, int8_t gain, uint8_t mute, uint8_t mode)
515 {
516 	struct bt_conn *conn;
517 
518 	bt_aics_client_conn_get(inst, &conn);
519 
520 	if (err) {
521 		if (err < 0) {
522 			err = BT_ATT_ERR_UNLIKELY;
523 		}
524 		btp_send_aics_state_ev(conn, err, 0, 0, 0);
525 	} else {
526 		btp_send_aics_state_ev(conn, 0, gain, mute, mode);
527 	}
528 
529 	LOG_DBG("AICS state callback (%d)", err);
530 }
531 
aics_gain_setting_cb(struct bt_aics * inst,int err,uint8_t units,int8_t minimum,int8_t maximum)532 static void aics_gain_setting_cb(struct bt_aics *inst, int err, uint8_t units, int8_t minimum,
533 				 int8_t maximum)
534 {
535 	struct bt_conn *conn;
536 
537 	bt_aics_client_conn_get(inst, &conn);
538 	btp_send_gain_setting_properties_ev(conn, err, units, minimum, maximum);
539 
540 	LOG_DBG("AICS gain setting callback (%d)", err);
541 }
542 
aics_input_type_cb(struct bt_aics * inst,int err,uint8_t input_type)543 static void aics_input_type_cb(struct bt_aics *inst, int err, uint8_t input_type)
544 {
545 	struct bt_conn *conn;
546 
547 	bt_aics_client_conn_get(inst, &conn);
548 	btp_send_aics_input_type_event(conn, err, input_type);
549 
550 	LOG_DBG("AICS input type callback (%d)", err);
551 }
552 
aics_status_cb(struct bt_aics * inst,int err,bool active)553 static void aics_status_cb(struct bt_aics *inst, int err, bool active)
554 {
555 	struct bt_conn *conn;
556 
557 	bt_aics_client_conn_get(inst, &conn);
558 	btp_send_aics_status_ev(conn, err, active);
559 
560 	LOG_DBG("AICS status callback (%d)", err);
561 }
562 
aics_description_cb(struct bt_aics * inst,int err,char * description)563 static void aics_description_cb(struct bt_aics *inst, int err, char *description)
564 {
565 	struct bt_conn *conn;
566 	uint8_t data_len = strlen(description);
567 
568 	bt_aics_client_conn_get(inst, &conn);
569 	btp_send_aics_description_ev(conn, err, data_len, description);
570 
571 	LOG_DBG("AICS description callback (%d)", err);
572 }
573 
aics_set_gain_cb(struct bt_aics * inst,int err)574 static void aics_set_gain_cb(struct bt_aics *inst, int err)
575 {
576 	struct bt_conn *conn;
577 
578 	bt_aics_client_conn_get(inst, &conn);
579 
580 	btp_send_aics_procedure_ev(conn, err, BTP_AICS_SET_GAIN);
581 
582 	LOG_DBG("AICS set gain cb (%d)", err);
583 }
584 
aics_mute_cb(struct bt_aics * inst,int err)585 static void aics_mute_cb(struct bt_aics *inst, int err)
586 {
587 	struct bt_conn *conn;
588 
589 	bt_aics_client_conn_get(inst, &conn);
590 
591 	btp_send_aics_procedure_ev(conn, err, BTP_AICS_MUTE);
592 
593 	LOG_DBG("AICS mute cb (%d)", err);
594 }
595 
aics_unmute_cb(struct bt_aics * inst,int err)596 static void aics_unmute_cb(struct bt_aics *inst, int err)
597 {
598 	struct bt_conn *conn;
599 
600 	bt_aics_client_conn_get(inst, &conn);
601 
602 	btp_send_aics_procedure_ev(conn, err, BTP_AICS_UNMUTE);
603 
604 	LOG_DBG("AICS unmute cb (%d)", err);
605 }
606 
aics_set_man_gain_cb(struct bt_aics * inst,int err)607 static void aics_set_man_gain_cb(struct bt_aics *inst, int err)
608 {
609 	struct bt_conn *conn;
610 
611 	bt_aics_client_conn_get(inst, &conn);
612 
613 	btp_send_aics_procedure_ev(conn, err, BTP_AICS_MAN_GAIN_SET);
614 
615 	LOG_DBG("AICS set manual gain cb (%d)", err);
616 }
617 
aics_set_auto_gain_cb(struct bt_aics * inst,int err)618 static void aics_set_auto_gain_cb(struct bt_aics *inst, int err)
619 {
620 	struct bt_conn *conn;
621 
622 	bt_aics_client_conn_get(inst, &conn);
623 
624 	btp_send_aics_procedure_ev(conn, err, BTP_AICS_AUTO_GAIN_SET);
625 
626 	LOG_DBG("AICS set automatic gain cb (%d)", err);
627 }
628 
629 struct bt_aics_cb aics_client_cb = {
630 	.state = aics_state_cb,
631 	.gain_setting = aics_gain_setting_cb,
632 	.type = aics_input_type_cb,
633 	.status = aics_status_cb,
634 	.description = aics_description_cb,
635 #if defined(CONFIG_BT_AICS_CLIENT)
636 	.set_gain = aics_set_gain_cb,
637 	.unmute = aics_unmute_cb,
638 	.mute = aics_mute_cb,
639 	.set_manual_mode = aics_set_man_gain_cb,
640 	.set_auto_mode = aics_set_auto_gain_cb
641 #endif /* CONFIG_BT_AICS_CLIENT */
642 };
643 
tester_init_aics(void)644 uint8_t tester_init_aics(void)
645 {
646 	tester_register_command_handlers(BTP_SERVICE_ID_AICS, aics_handlers,
647 					 ARRAY_SIZE(aics_handlers));
648 
649 	return BTP_STATUS_SUCCESS;
650 }
651 
tester_unregister_aics(void)652 uint8_t tester_unregister_aics(void)
653 {
654 	return BTP_STATUS_SUCCESS;
655 }
656