1 /* btp_micp.c - Bluetooth MICP 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 #include <stdio.h>
12
13 #include <zephyr/types.h>
14 #include <zephyr/kernel.h>
15
16 #include <zephyr/bluetooth/bluetooth.h>
17 #include <zephyr/bluetooth/audio/audio.h>
18 #include <zephyr/bluetooth/audio/micp.h>
19 #include <zephyr/bluetooth/audio/aics.h>
20
21 #include <zephyr/logging/log.h>
22 #include <zephyr/sys/byteorder.h>
23
24 #include <../../subsys/bluetooth/audio/micp_internal.h>
25 #include <../../subsys/bluetooth/audio/aics_internal.h>
26
27 #include "bap_endpoint.h"
28 #include "btp/btp.h"
29
30 #define LOG_MODULE_NAME bttester_micp
31 LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL);
32
33 static struct bt_micp_mic_ctlr *mic_ctlr;
34 static struct bt_micp_mic_dev_register_param mic_dev_register_param;
35 static uint8_t mute_state;
36
37 #if defined(CONFIG_BT_MICP_MIC_CTLR_AICS)
38 static struct bt_micp_included micp_included;
39 struct chrc_handles {
40 uint16_t mute_handle;
41 uint16_t state_handle;
42 uint16_t gain_handle;
43 uint16_t type_handle;
44 uint16_t status_handle;
45 uint16_t control_handle;
46 uint16_t desc_handle;
47 };
48 struct chrc_handles micp_handles;
49 extern struct btp_aics_instance aics_client_instance;
50 extern struct bt_aics_cb aics_client_cb;
51 #endif /* CONFIG_BT_MICP_MIC_CTLR_AICS */
52
53 /* Microphone Control Profile */
btp_send_micp_found_ev(struct bt_conn * conn,uint8_t att_status,const struct chrc_handles * micp_handles)54 static void btp_send_micp_found_ev(struct bt_conn *conn, uint8_t att_status,
55 const struct chrc_handles *micp_handles)
56 {
57 struct btp_micp_discovered_ev ev;
58
59 bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
60
61 ev.att_status = att_status;
62 ev.mute_handle = sys_cpu_to_le16(micp_handles->mute_handle);
63 ev.state_handle = sys_cpu_to_le16(micp_handles->state_handle);
64 ev.gain_handle = sys_cpu_to_le16(micp_handles->gain_handle);
65 ev.type_handle = sys_cpu_to_le16(micp_handles->type_handle);
66 ev.status_handle = sys_cpu_to_le16(micp_handles->status_handle);
67 ev.control_handle = sys_cpu_to_le16(micp_handles->control_handle);
68 ev.desc_handle = sys_cpu_to_le16(micp_handles->desc_handle);
69
70 tester_event(BTP_SERVICE_ID_MICP, BTP_MICP_DISCOVERED_EV, &ev, sizeof(ev));
71 }
72
btp_send_micp_mute_state_ev(struct bt_conn * conn,uint8_t att_status,uint8_t mute)73 static void btp_send_micp_mute_state_ev(struct bt_conn *conn, uint8_t att_status, uint8_t mute)
74 {
75 struct btp_micp_mute_state_ev ev;
76
77 bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
78
79 ev.att_status = att_status;
80 ev.mute = mute;
81
82 tester_event(BTP_SERVICE_ID_MICP, BTP_MICP_MUTE_STATE_EV, &ev, sizeof(ev));
83 }
84
micp_mic_ctlr_mute_cb(struct bt_micp_mic_ctlr * mic_ctlr,int err,uint8_t mute)85 static void micp_mic_ctlr_mute_cb(struct bt_micp_mic_ctlr *mic_ctlr, int err, uint8_t mute)
86 {
87 struct bt_conn *conn;
88
89 mute_state = mute;
90
91 bt_micp_mic_ctlr_conn_get(mic_ctlr, &conn);
92 btp_send_micp_mute_state_ev(conn, err, mute_state);
93
94 LOG_DBG("MICP Mute cb (%d)", err);
95 }
96
micp_mic_ctlr_mute_written_cb(struct bt_micp_mic_ctlr * mic_ctlr,int err)97 static void micp_mic_ctlr_mute_written_cb(struct bt_micp_mic_ctlr *mic_ctlr, int err)
98 {
99 struct bt_conn *conn;
100
101 bt_micp_mic_ctlr_conn_get(mic_ctlr, &conn);
102 btp_send_micp_mute_state_ev(conn, err, mute_state);
103
104 LOG_DBG("MICP Mute Written cb (%d))", err);
105 }
106
micp_mic_ctlr_unmute_written_cb(struct bt_micp_mic_ctlr * mic_ctlr,int err)107 static void micp_mic_ctlr_unmute_written_cb(struct bt_micp_mic_ctlr *mic_ctlr, int err)
108 {
109 struct bt_conn *conn;
110
111 bt_micp_mic_ctlr_conn_get(mic_ctlr, &conn);
112 btp_send_micp_mute_state_ev(conn, err, mute_state);
113
114 LOG_DBG("MICP Mute Unwritten cb (%d))", err);
115 }
116
micp_mic_ctlr_discover_cb(struct bt_micp_mic_ctlr * mic_ctlr,int err,uint8_t aics_count)117 static void micp_mic_ctlr_discover_cb(struct bt_micp_mic_ctlr *mic_ctlr, int err,
118 uint8_t aics_count)
119 {
120 struct bt_conn *conn;
121
122 if (err) {
123 LOG_DBG("Discovery failed (%d)", err);
124 return;
125 }
126
127 LOG_DBG("Discovery done with %u AICS",
128 aics_count);
129
130 bt_micp_mic_ctlr_conn_get(mic_ctlr, &conn);
131
132 #if defined(CONFIG_BT_MICP_MIC_CTLR_AICS)
133 if (bt_micp_mic_ctlr_included_get(mic_ctlr, &micp_included) != 0) {
134 LOG_DBG("Could not get included services");
135 memset(&micp_handles, 0, sizeof(micp_handles));
136 } else {
137 aics_client_instance.aics_cnt = micp_included.aics_cnt;
138 aics_client_instance.aics = micp_included.aics;
139 bt_aics_client_cb_register(aics_client_instance.aics[0], &aics_client_cb);
140
141 micp_handles.state_handle = micp_included.aics[0]->cli.state_handle;
142 micp_handles.gain_handle = micp_included.aics[0]->cli.gain_handle;
143 micp_handles.type_handle = micp_included.aics[0]->cli.type_handle;
144 micp_handles.status_handle = micp_included.aics[0]->cli.status_handle;
145 micp_handles.control_handle = micp_included.aics[0]->cli.control_handle;
146 micp_handles.desc_handle = micp_included.aics[0]->cli.desc_handle;
147 }
148 #endif /* CONFIG_BT_MICP_MIC_CTLR_AICS */
149
150 micp_handles.mute_handle = mic_ctlr->mute_handle;
151 btp_send_micp_found_ev(conn, err, &micp_handles);
152 }
153
154 static struct bt_micp_mic_ctlr_cb micp_cbs = {
155 .discover = micp_mic_ctlr_discover_cb,
156 .mute = micp_mic_ctlr_mute_cb,
157 .mute_written = micp_mic_ctlr_mute_written_cb,
158 .unmute_written = micp_mic_ctlr_unmute_written_cb,
159 };
160
micp_supported_commands(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)161 static uint8_t micp_supported_commands(const void *cmd, uint16_t cmd_len, void *rsp,
162 uint16_t *rsp_len)
163 {
164 struct btp_micp_read_supported_commands_rp *rp = rsp;
165
166 /* octet 0 */
167 tester_set_bit(rp->data, BTP_MICP_READ_SUPPORTED_COMMANDS);
168 tester_set_bit(rp->data, BTP_MICP_CTLR_DISCOVER);
169 tester_set_bit(rp->data, BTP_MICP_CTLR_MUTE_READ);
170 tester_set_bit(rp->data, BTP_MICP_CTLR_MUTE);
171
172 *rsp_len = sizeof(*rp) + 1;
173
174 return BTP_STATUS_SUCCESS;
175 }
176
micp_discover(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)177 static uint8_t micp_discover(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
178 {
179 const struct btp_micp_discover_cmd *cp = cmd;
180 struct bt_conn *conn;
181 int err;
182
183 conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address);
184 if (!conn) {
185 LOG_ERR("Unknown connection");
186 return BTP_STATUS_FAILED;
187 }
188
189 err = bt_micp_mic_ctlr_discover(conn, &mic_ctlr);
190 if (err) {
191 LOG_DBG("Fail: %d", err);
192 return BTP_STATUS_FAILED;
193 }
194
195 return BTP_STATUS_SUCCESS;
196 }
197
micp_mute_read(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)198 static uint8_t micp_mute_read(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
199 {
200 int err;
201
202 LOG_DBG("Read mute");
203
204 err = bt_micp_mic_ctlr_mute_get(mic_ctlr);
205 if (err) {
206 return BTP_STATUS_FAILED;
207 }
208
209 return BTP_STATUS_SUCCESS;
210 }
211
micp_mute(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)212 static uint8_t micp_mute(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
213 {
214 int err;
215
216 LOG_DBG("MICP Mute");
217
218 err = bt_micp_mic_ctlr_mute(mic_ctlr);
219 if (err) {
220 return BTP_STATUS_FAILED;
221 }
222
223 return BTP_STATUS_SUCCESS;
224 }
225
226 static const struct btp_handler micp_handlers[] = {
227 {
228 .opcode = BTP_MICP_READ_SUPPORTED_COMMANDS,
229 .index = BTP_INDEX_NONE,
230 .expect_len = 0,
231 .func = micp_supported_commands,
232 },
233 {
234 .opcode = BTP_MICP_CTLR_DISCOVER,
235 .expect_len = sizeof(struct btp_micp_discover_cmd),
236 .func = micp_discover,
237 },
238 {
239 .opcode = BTP_MICP_CTLR_MUTE_READ,
240 .expect_len = sizeof(struct btp_micp_mute_read_cmd),
241 .func = micp_mute_read,
242 },
243 {
244 .opcode = BTP_MICP_CTLR_MUTE,
245 .expect_len = sizeof(struct btp_micp_mute_cmd),
246 .func = micp_mute,
247 },
248 };
249
tester_init_micp(void)250 uint8_t tester_init_micp(void)
251 {
252 int err;
253
254 err = bt_micp_mic_ctlr_cb_register(&micp_cbs);
255
256 if (err) {
257 LOG_DBG("Failed to register callbacks: %d", err);
258 return BTP_STATUS_FAILED;
259 }
260
261 tester_register_command_handlers(BTP_SERVICE_ID_MICP, micp_handlers,
262 ARRAY_SIZE(micp_handlers));
263
264 return BTP_STATUS_SUCCESS;
265 }
266
tester_unregister_micp(void)267 uint8_t tester_unregister_micp(void)
268 {
269 (void)bt_micp_mic_ctlr_cb_register(NULL);
270 return BTP_STATUS_SUCCESS;
271 }
272
273 /* Microphone Control Service */
mics_supported_commands(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)274 static uint8_t mics_supported_commands(const void *cmd, uint16_t cmd_len, void *rsp,
275 uint16_t *rsp_len)
276 {
277 struct btp_mics_read_supported_commands_rp *rp = rsp;
278
279 /* octet 0 */
280 tester_set_bit(rp->data, BTP_MICS_READ_SUPPORTED_COMMANDS);
281 tester_set_bit(rp->data, BTP_MICS_DEV_MUTE_DISABLE);
282 tester_set_bit(rp->data, BTP_MICS_DEV_MUTE_READ);
283 tester_set_bit(rp->data, BTP_MICS_DEV_MUTE);
284 tester_set_bit(rp->data, BTP_MICS_DEV_UNMUTE);
285
286 *rsp_len = sizeof(*rp) + 1;
287
288 return BTP_STATUS_SUCCESS;
289 }
290
mics_mute_disable(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)291 static uint8_t mics_mute_disable(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
292 {
293 int err;
294
295 LOG_DBG("MICP Mute disable");
296
297 err = bt_micp_mic_dev_mute_disable();
298 if (err) {
299 return BTP_STATUS_FAILED;
300 }
301
302 return BTP_STATUS_SUCCESS;
303 }
304
mics_mute_read(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)305 static uint8_t mics_mute_read(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
306 {
307 int err;
308
309 LOG_DBG("MICS Mute state read");
310
311 err = bt_micp_mic_dev_mute_get();
312 if (err) {
313 return BTP_STATUS_FAILED;
314 }
315
316 return BTP_STATUS_SUCCESS;
317 }
318
mics_mute(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)319 static uint8_t mics_mute(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
320 {
321 int err;
322
323 LOG_DBG("MICS Mute");
324
325 err = bt_micp_mic_dev_mute();
326 if (err) {
327 return BTP_STATUS_FAILED;
328 }
329
330 return BTP_STATUS_SUCCESS;
331 }
332
mics_unmute(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)333 static uint8_t mics_unmute(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
334 {
335 int err;
336
337 LOG_DBG("MICS Mute");
338
339 err = bt_micp_mic_dev_unmute();
340 if (err) {
341 return BTP_STATUS_FAILED;
342 }
343
344 return BTP_STATUS_SUCCESS;
345 }
346
btp_send_mics_mute_state_ev(uint8_t mute)347 static void btp_send_mics_mute_state_ev(uint8_t mute)
348 {
349 struct btp_mics_mute_state_ev ev;
350
351 ev.mute = mute;
352
353 tester_event(BTP_SERVICE_ID_MICS, BTP_MICS_MUTE_STATE_EV, &ev, sizeof(ev));
354 }
355
mic_dev_mute_cb(uint8_t mute)356 static void mic_dev_mute_cb(uint8_t mute)
357 {
358 LOG_DBG("Microphone Device Mute cb");
359
360 btp_send_mics_mute_state_ev(mute);
361 }
362
363 static struct bt_micp_mic_dev_cb mic_dev_cb = {
364 .mute = mic_dev_mute_cb,
365 };
366
367 #if defined(CONFIG_BT_MICP_MIC_DEV_AICS)
aics_state_cb(struct bt_aics * inst,int err,int8_t gain,uint8_t mute,uint8_t mode)368 static void aics_state_cb(struct bt_aics *inst, int err, int8_t gain,
369 uint8_t mute, uint8_t mode)
370 {
371 LOG_DBG("AICS state callback (%d)", err);
372 }
373
aics_gain_setting_cb(struct bt_aics * inst,int err,uint8_t units,int8_t minimum,int8_t maximum)374 static void aics_gain_setting_cb(struct bt_aics *inst, int err, uint8_t units,
375 int8_t minimum, int8_t maximum)
376 {
377 LOG_DBG("AICS gain setting callback (%d)", err);
378 }
379
aics_input_type_cb(struct bt_aics * inst,int err,uint8_t input_type)380 static void aics_input_type_cb(struct bt_aics *inst, int err,
381 uint8_t input_type)
382 {
383 LOG_DBG("AICS input type callback (%d)", err);
384 }
385
aics_status_cb(struct bt_aics * inst,int err,bool active)386 static void aics_status_cb(struct bt_aics *inst, int err, bool active)
387 {
388 LOG_DBG("AICS status callback (%d)", err);
389 }
390
aics_description_cb(struct bt_aics * inst,int err,char * description)391 static void aics_description_cb(struct bt_aics *inst, int err,
392 char *description)
393 {
394 LOG_DBG("AICS description callback (%d)", err);
395 }
396
397 struct bt_aics_cb aics_mic_dev_cb = {
398 .state = aics_state_cb,
399 .gain_setting = aics_gain_setting_cb,
400 .type = aics_input_type_cb,
401 .status = aics_status_cb,
402 .description = aics_description_cb,
403 };
404 #endif /* CONFIG_BT_MICP_MIC_DEV_AICS */
405
406 static const struct btp_handler mics_handlers[] = {
407 {
408 .opcode = BTP_MICS_READ_SUPPORTED_COMMANDS,
409 .index = BTP_INDEX_NONE,
410 .expect_len = 0,
411 .func = mics_supported_commands,
412 },
413 {
414 .opcode = BTP_MICS_DEV_MUTE_DISABLE,
415 .expect_len = 0,
416 .func = mics_mute_disable,
417 },
418 {
419 .opcode = BTP_MICS_DEV_MUTE_READ,
420 .expect_len = 0,
421 .func = mics_mute_read,
422 },
423 {
424 .opcode = BTP_MICS_DEV_MUTE,
425 .expect_len = 0,
426 .func = mics_mute,
427 },
428 {
429 .opcode = BTP_MICS_DEV_UNMUTE,
430 .expect_len = 0,
431 .func = mics_unmute,
432 },
433 };
434
tester_init_mics(void)435 uint8_t tester_init_mics(void)
436 {
437 int err;
438
439 memset(&mic_dev_register_param, 0, sizeof(mic_dev_register_param));
440
441 #if defined(CONFIG_BT_MICP_MIC_DEV_AICS)
442 char input_desc[CONFIG_BT_MICP_MIC_DEV_AICS_INSTANCE_COUNT][16];
443
444 for (size_t i = 0; i < ARRAY_SIZE(mic_dev_register_param.aics_param); i++) {
445 mic_dev_register_param.aics_param[i].desc_writable = true;
446 snprintf(input_desc[i], sizeof(input_desc[i]),
447 "Input %zu", i + 1);
448 mic_dev_register_param.aics_param[i].description = input_desc[i];
449 mic_dev_register_param.aics_param[i].type = BT_AICS_INPUT_TYPE_DIGITAL;
450 mic_dev_register_param.aics_param[i].status = 1;
451 mic_dev_register_param.aics_param[i].gain_mode = BT_AICS_MODE_MANUAL;
452 mic_dev_register_param.aics_param[i].units = 1;
453 mic_dev_register_param.aics_param[i].min_gain = 0;
454 mic_dev_register_param.aics_param[i].max_gain = 100;
455 mic_dev_register_param.aics_param[i].cb = &aics_mic_dev_cb;
456 }
457 #endif /* CONFIG_BT_MICP_MIC_DEV_AICS */
458
459 mic_dev_register_param.cb = &mic_dev_cb;
460
461 err = bt_micp_mic_dev_register(&mic_dev_register_param);
462 if (err) {
463 return BTP_STATUS_FAILED;
464 }
465
466 #if defined(CONFIG_BT_MICP_MIC_DEV_AICS)
467 err = bt_micp_mic_dev_included_get(&micp_included);
468 if (err) {
469 return BTP_STATUS_FAILED;
470 }
471 #endif /* CONFIG_BT_MICP_MIC_DEV_AICS */
472
473 tester_register_command_handlers(BTP_SERVICE_ID_MICS, mics_handlers,
474 ARRAY_SIZE(mics_handlers));
475
476 return BTP_STATUS_SUCCESS;
477 }
478
tester_unregister_mics(void)479 uint8_t tester_unregister_mics(void)
480 {
481 return BTP_STATUS_SUCCESS;
482 }
483