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