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