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