1 /* btp_vcp.c - Bluetooth VCP Tester */
2
3 /*
4 * Copyright (c) 2022 Codecoup
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #include <stdio.h>
10 #include <stdint.h>
11 #include <zephyr/sys/byteorder.h>
12 #include <zephyr/bluetooth/bluetooth.h>
13 #include <zephyr/bluetooth/testing.h>
14 #include <zephyr/bluetooth/audio/vcp.h>
15 #include <zephyr/bluetooth/audio/aics.h>
16 #include <zephyr/bluetooth/audio/vocs.h>
17 #include <zephyr/sys/util.h>
18 #include "btp/btp.h"
19
20 #include <../../subsys/bluetooth/audio/micp_internal.h>
21 #include <../../subsys/bluetooth/audio/aics_internal.h>
22 #include <../../subsys/bluetooth/audio/vcp_internal.h>
23 #include <../../subsys/bluetooth/audio/vocs_internal.h>
24 #include <zephyr/logging/log.h>
25
26 #define LOG_MODULE_NAME bttester_vcp
27 LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL);
28
29 #define BT_AICS_MAX_INPUT_DESCRIPTION_SIZE 16
30 #define BT_AICS_MAX_OUTPUT_DESCRIPTION_SIZE 16
31
32 static struct bt_vcp_vol_rend_register_param vcp_register_param;
33 static struct bt_vcp_vol_ctlr *vol_ctlr;
34 static struct bt_vcp_included included;
35 extern struct btp_aics_instance aics_server_instance;
36 extern struct btp_aics_instance aics_client_instance;
37 extern struct bt_aics_cb aics_client_cb;
38
39 struct service_handles {
40 struct {
41 uint16_t ctrl_pt;
42 uint16_t flags;
43 uint16_t state;
44 } vcp_handles;
45
46 struct {
47 uint16_t state;
48 uint16_t location;
49 uint16_t control;
50 uint16_t desc;
51 } vocs_handles;
52
53 struct {
54 uint16_t mute;
55 uint16_t state;
56 uint16_t gain;
57 uint16_t type;
58 uint16_t status;
59 uint16_t control;
60 uint16_t desc;
61 } aics_handles;
62 };
63
64 struct service_handles chrc_handles;
65
66 /* Volume Control Service */
vcs_supported_commands(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)67 static uint8_t vcs_supported_commands(const void *cmd, uint16_t cmd_len,
68 void *rsp, uint16_t *rsp_len)
69 {
70 struct btp_vcs_read_supported_commands_rp *rp = rsp;
71
72 /* octet 0 */
73 tester_set_bit(rp->data, BTP_VCS_READ_SUPPORTED_COMMANDS);
74 tester_set_bit(rp->data, BTP_VCS_SET_VOL);
75 tester_set_bit(rp->data, BTP_VCS_VOL_UP);
76 tester_set_bit(rp->data, BTP_VCS_VOL_DOWN);
77 tester_set_bit(rp->data, BTP_VCS_MUTE);
78 tester_set_bit(rp->data, BTP_VCS_UNMUTE);
79
80 *rsp_len = sizeof(*rp) + 1;
81
82 return BTP_STATUS_SUCCESS;
83 }
84
set_volume(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)85 static uint8_t set_volume(const void *cmd, uint16_t cmd_len,
86 void *rsp, uint16_t *rsp_len)
87 {
88 const struct btp_vcs_set_vol_cmd *cp = cmd;
89
90 LOG_DBG("Set volume 0x%02x", cp->volume);
91
92 if (bt_vcp_vol_rend_set_vol(cp->volume) != 0) {
93 return BTP_STATUS_FAILED;
94 }
95
96 return BTP_STATUS_SUCCESS;
97 }
98
vol_up(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)99 static uint8_t vol_up(const void *cmd, uint16_t cmd_len,
100 void *rsp, uint16_t *rsp_len)
101 {
102 LOG_DBG("Volume Up");
103
104 if (bt_vcp_vol_rend_vol_up() != 0) {
105 return BTP_STATUS_FAILED;
106 }
107
108 return BTP_STATUS_SUCCESS;
109 }
110
vol_down(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)111 static uint8_t vol_down(const void *cmd, uint16_t cmd_len,
112 void *rsp, uint16_t *rsp_len)
113 {
114 LOG_DBG("Volume Down");
115
116 if (bt_vcp_vol_rend_vol_down() != 0) {
117 return BTP_STATUS_FAILED;
118 }
119
120 return BTP_STATUS_SUCCESS;
121 }
122
mute(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)123 static uint8_t mute(const void *cmd, uint16_t cmd_len,
124 void *rsp, uint16_t *rsp_len)
125 {
126 LOG_DBG("Mute");
127
128 if (bt_vcp_vol_rend_mute() != 0) {
129 return BTP_STATUS_FAILED;
130 }
131
132 return BTP_STATUS_SUCCESS;
133 }
134
unmute(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)135 static uint8_t unmute(const void *cmd, uint16_t cmd_len,
136 void *rsp, uint16_t *rsp_len)
137 {
138 LOG_DBG("Unmute");
139
140 if (bt_vcp_vol_rend_unmute() != 0) {
141 return BTP_STATUS_FAILED;
142 }
143
144 return BTP_STATUS_SUCCESS;
145 }
146
vcs_state_cb(int err,uint8_t volume,uint8_t mute)147 static void vcs_state_cb(int err, uint8_t volume, uint8_t mute)
148 {
149 LOG_DBG("VCP state cb err (%d)", err);
150 }
151
vcs_flags_cb(int err,uint8_t flags)152 static void vcs_flags_cb(int err, uint8_t flags)
153 {
154 LOG_DBG("VCP flags cb err (%d)", err);
155 }
156
157 static struct bt_vcp_vol_rend_cb vcs_cb = {
158 .state = vcs_state_cb,
159 .flags = vcs_flags_cb,
160 };
161
162 static const struct btp_handler vcs_handlers[] = {
163 {
164 .opcode = BTP_VCS_READ_SUPPORTED_COMMANDS,
165 .index = BTP_INDEX_NONE,
166 .expect_len = 0,
167 .func = vcs_supported_commands,
168 },
169 {
170 .opcode = BTP_VCS_SET_VOL,
171 .expect_len = sizeof(struct btp_vcs_set_vol_cmd),
172 .func = set_volume,
173 },
174 {
175 .opcode = BTP_VCS_VOL_UP,
176 .expect_len = 0,
177 .func = vol_up,
178 },
179 {
180 .opcode = BTP_VCS_VOL_DOWN,
181 .expect_len = 0,
182 .func = vol_down,
183 },
184 {
185 .opcode = BTP_VCS_MUTE,
186 .expect_len = 0,
187 .func = mute,
188 },
189 {
190 .opcode = BTP_VCS_UNMUTE,
191 .expect_len = 0,
192 .func = unmute,
193 },
194 };
195
196 /* Volume Offset Control Service */
vocs_supported_commands(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)197 static uint8_t vocs_supported_commands(const void *cmd, uint16_t cmd_len,
198 void *rsp, uint16_t *rsp_len)
199 {
200 struct btp_vocs_read_supported_commands_rp *rp = rsp;
201
202 /* octet 0 */
203 tester_set_bit(rp->data, BTP_VOCS_READ_SUPPORTED_COMMANDS);
204 tester_set_bit(rp->data, BTP_VOCS_UPDATE_LOC);
205 tester_set_bit(rp->data, BTP_VOCS_UPDATE_DESC);
206 tester_set_bit(rp->data, BTP_VOCS_STATE_GET);
207 tester_set_bit(rp->data, BTP_VOCS_LOCATION_GET);
208 tester_set_bit(rp->data, BTP_VOCS_OFFSET_STATE_SET);
209
210 *rsp_len = sizeof(*rp) + 1;
211
212 return BTP_STATUS_SUCCESS;
213 }
214
vocs_state_cb(struct bt_vocs * inst,int err,int16_t offset)215 static void vocs_state_cb(struct bt_vocs *inst, int err, int16_t offset)
216 {
217 LOG_DBG("VOCS state callback err (%d)", err);
218 }
219
vocs_location_cb(struct bt_vocs * inst,int err,uint32_t location)220 static void vocs_location_cb(struct bt_vocs *inst, int err, uint32_t location)
221 {
222 LOG_DBG("VOCS location callback err (%d)", err);
223 }
224
vocs_description_cb(struct bt_vocs * inst,int err,char * description)225 static void vocs_description_cb(struct bt_vocs *inst, int err,
226 char *description)
227 {
228 LOG_DBG("VOCS desctripion callback (%d)", err);
229 }
230
231 static struct bt_vocs_cb vocs_cb = {
232 .state = vocs_state_cb,
233 .location = vocs_location_cb,
234 .description = vocs_description_cb
235 };
236
btp_send_vocs_state_ev(struct bt_conn * conn,uint8_t att_status,int16_t offset)237 static void btp_send_vocs_state_ev(struct bt_conn *conn, uint8_t att_status, int16_t offset)
238 {
239 struct btp_vocs_offset_state_ev ev;
240
241 bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
242
243 ev.att_status = att_status;
244 ev.offset = sys_cpu_to_le16(offset);
245
246 tester_event(BTP_SERVICE_ID_VOCS, BTP_VOCS_OFFSET_STATE_EV, &ev, sizeof(ev));
247 }
248
btp_send_vocs_location_ev(struct bt_conn * conn,uint8_t att_status,uint32_t location)249 static void btp_send_vocs_location_ev(struct bt_conn *conn, uint8_t att_status, uint32_t location)
250 {
251 struct btp_vocs_audio_location_ev ev;
252
253 bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
254
255 ev.att_status = att_status;
256 ev.location = sys_cpu_to_le32(location);
257
258 tester_event(BTP_SERVICE_ID_VOCS, BTP_VOCS_AUDIO_LOCATION_EV, &ev, sizeof(ev));
259 }
260
btp_send_vocs_procedure_ev(struct bt_conn * conn,uint8_t att_status,uint8_t opcode)261 static void btp_send_vocs_procedure_ev(struct bt_conn *conn, uint8_t att_status, uint8_t opcode)
262 {
263 struct btp_vocs_procedure_ev ev;
264
265 bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
266
267 ev.att_status = att_status;
268 ev.opcode = opcode;
269
270 tester_event(BTP_SERVICE_ID_VOCS, BTP_VOCS_PROCEDURE_EV, &ev, sizeof(ev));
271 }
272
vcp_vocs_state_cb(struct bt_vocs * inst,int err,int16_t offset)273 static void vcp_vocs_state_cb(struct bt_vocs *inst, int err, int16_t offset)
274 {
275 struct bt_conn *conn;
276
277 bt_vocs_client_conn_get(inst, &conn);
278 btp_send_vocs_state_ev(conn, err, offset);
279
280 LOG_DBG("VOCS Offset State callback");
281 }
282
vcp_vocs_location_cb(struct bt_vocs * inst,int err,uint32_t location)283 static void vcp_vocs_location_cb(struct bt_vocs *inst, int err, uint32_t location)
284 {
285 struct bt_conn *conn;
286
287 bt_vocs_client_conn_get(inst, &conn);
288 btp_send_vocs_location_ev(conn, err, location);
289
290 LOG_DBG("VOCS location callback err (%d)", err);
291 }
292
vcp_vocs_description_cb(struct bt_vocs * inst,int err,char * description)293 static void vcp_vocs_description_cb(struct bt_vocs *inst, int err,
294 char *description)
295 {
296 LOG_DBG("VOCS desctripion callback (%d)", err);
297 }
298
vcp_vocs_set_offset_cb(struct bt_vocs * inst,int err)299 static void vcp_vocs_set_offset_cb(struct bt_vocs *inst, int err)
300 {
301 struct bt_conn *conn;
302
303 bt_vocs_client_conn_get(inst, &conn);
304 btp_send_vocs_procedure_ev(conn, err, BTP_VOCS_OFFSET_STATE_SET);
305
306 LOG_DBG("VOCS Set Offset callback (%d)", err);
307 }
308
309 static struct bt_vocs_cb vocs_cl_cb = {
310 .state = vcp_vocs_state_cb,
311 .location = vcp_vocs_location_cb,
312 .description = vcp_vocs_description_cb,
313 #if defined(CONFIG_BT_VOCS_CLIENT)
314 .set_offset = vcp_vocs_set_offset_cb
315 #endif /* CONFIG_BT_VOCS_CLIENT */
316 };
317
vocs_audio_desc(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)318 static uint8_t vocs_audio_desc(const void *cmd, uint16_t cmd_len,
319 void *rsp, uint16_t *rsp_len)
320 {
321 const struct btp_vocs_audio_desc_cmd *cp = cmd;
322 char description[BT_AICS_MAX_OUTPUT_DESCRIPTION_SIZE];
323
324 if (cmd_len < sizeof(*cp) ||
325 cmd_len != sizeof(*cp) + cp->desc_len) {
326 return BTP_STATUS_FAILED;
327 }
328
329 if (cp->desc_len >= sizeof(description)) {
330 return BTP_STATUS_FAILED;
331 }
332
333 memcpy(description, cp->desc, cp->desc_len);
334 description[cp->desc_len] = '\0';
335
336 for (int i = 0; i < CONFIG_BT_VCP_VOL_REND_VOCS_INSTANCE_COUNT; i++) {
337 if (bt_vocs_description_set(included.vocs[i], description) != 0) {
338 return BTP_STATUS_FAILED;
339 }
340 }
341
342 return BTP_STATUS_SUCCESS;
343 }
344
vocs_audio_loc(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)345 static uint8_t vocs_audio_loc(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
346 {
347 const struct btp_vocs_audio_loc_cmd *cp = cmd;
348 uint32_t loc = sys_le32_to_cpu(cp->loc);
349
350 for (uint8_t i = 0; i < included.vocs_cnt; i++) {
351 if (bt_vocs_location_set(included.vocs[i], loc) != 0) {
352 return BTP_STATUS_FAILED;
353 }
354 }
355
356 return BTP_STATUS_SUCCESS;
357 }
358
vocs_state_get(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)359 static uint8_t vocs_state_get(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
360 {
361 int err;
362
363 LOG_DBG("Volume Offset Control Service offset state get");
364
365 err = bt_vocs_state_get(included.vocs[0]);
366 if (err) {
367 return BTP_STATUS_FAILED;
368 }
369
370 return BTP_STATUS_SUCCESS;
371 }
372
vocs_state_set(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)373 static uint8_t vocs_state_set(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
374 {
375 const struct btp_vocs_offset_set_cmd *cp = cmd;
376 int16_t offset = sys_le16_to_cpu(cp->offset);
377 int err;
378
379 LOG_DBG("VCP CTLR Set absolute volume %d", offset);
380
381 err = bt_vocs_state_set(included.vocs[0], cp->offset);
382 if (err) {
383 return BTP_STATUS_FAILED;
384 }
385
386 return BTP_STATUS_SUCCESS;
387 }
388
vocs_audio_location_get(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)389 static uint8_t vocs_audio_location_get(const void *cmd, uint16_t cmd_len, void *rsp,
390 uint16_t *rsp_len)
391 {
392 int err;
393
394 LOG_DBG("Volume Offset Control Service Audio Location get");
395
396 err = bt_vocs_location_get(included.vocs[0]);
397 if (err) {
398 return BTP_STATUS_FAILED;
399 }
400
401 return BTP_STATUS_SUCCESS;
402 }
403
404 static const struct btp_handler vocs_handlers[] = {
405 {
406 .opcode = BTP_VOCS_READ_SUPPORTED_COMMANDS,
407 .index = BTP_INDEX_NONE,
408 .expect_len = 0,
409 .func = vocs_supported_commands,
410 },
411 {
412 .opcode = BTP_VOCS_UPDATE_DESC,
413 .expect_len = BTP_HANDLER_LENGTH_VARIABLE,
414 .func = vocs_audio_desc,
415 },
416 {
417 .opcode = BTP_VOCS_UPDATE_LOC,
418 .expect_len = sizeof(struct btp_vocs_audio_loc_cmd),
419 .func = vocs_audio_loc,
420 },
421 {
422 .opcode = BTP_VOCS_STATE_GET,
423 .expect_len = sizeof(struct btp_vocs_state_get_cmd),
424 .func = vocs_state_get,
425 },
426 {
427 .opcode = BTP_VOCS_LOCATION_GET,
428 .expect_len = sizeof(struct btp_vocs_location_get_cmd),
429 .func = vocs_audio_location_get,
430 },
431 {
432 .opcode = BTP_VOCS_OFFSET_STATE_SET,
433 .expect_len = sizeof(struct btp_vocs_offset_set_cmd),
434 .func = vocs_state_set,
435 },
436 };
437
438 /* AICS Callbacks */
aics_state_cb(struct bt_aics * inst,int err,int8_t gain,uint8_t mute,uint8_t mode)439 static void aics_state_cb(struct bt_aics *inst, int err, int8_t gain,
440 uint8_t mute, uint8_t mode)
441 {
442 LOG_DBG("AICS state callback (%d)", err);
443 }
444
aics_gain_setting_cb(struct bt_aics * inst,int err,uint8_t units,int8_t minimum,int8_t maximum)445 static void aics_gain_setting_cb(struct bt_aics *inst, int err, uint8_t units,
446 int8_t minimum, int8_t maximum)
447 {
448 LOG_DBG("AICS gain setting callback (%d)", err);
449 }
450
aics_input_type_cb(struct bt_aics * inst,int err,uint8_t input_type)451 static void aics_input_type_cb(struct bt_aics *inst, int err,
452 uint8_t input_type)
453 {
454 LOG_DBG("AICS input type callback (%d)", err);
455 }
456
aics_status_cb(struct bt_aics * inst,int err,bool active)457 static void aics_status_cb(struct bt_aics *inst, int err, bool active)
458 {
459 LOG_DBG("AICS status callback (%d)", err);
460 }
461
aics_description_cb(struct bt_aics * inst,int err,char * description)462 static void aics_description_cb(struct bt_aics *inst, int err,
463 char *description)
464 {
465 LOG_DBG("AICS description callback (%d)", err);
466 }
467
468 struct bt_aics_cb aics_server_cb = {
469 .state = aics_state_cb,
470 .gain_setting = aics_gain_setting_cb,
471 .type = aics_input_type_cb,
472 .status = aics_status_cb,
473 .description = aics_description_cb,
474 };
475
476 /* General profile handling */
set_register_params(uint8_t gain_mode)477 static void set_register_params(uint8_t gain_mode)
478 {
479 char input_desc[CONFIG_BT_VCP_VOL_REND_AICS_INSTANCE_COUNT]
480 [BT_AICS_MAX_INPUT_DESCRIPTION_SIZE];
481 char output_desc[CONFIG_BT_VCP_VOL_REND_VOCS_INSTANCE_COUNT]
482 [BT_AICS_MAX_OUTPUT_DESCRIPTION_SIZE];
483
484 memset(&vcp_register_param, 0, sizeof(vcp_register_param));
485
486 for (size_t i = 0; i < ARRAY_SIZE(vcp_register_param.vocs_param); i++) {
487 vcp_register_param.vocs_param[i].location_writable = true;
488 vcp_register_param.vocs_param[i].desc_writable = true;
489 snprintf(output_desc[i], sizeof(output_desc[i]),
490 "Output %zu", i + 1);
491 vcp_register_param.vocs_param[i].output_desc = output_desc[i];
492 vcp_register_param.vocs_param[i].cb = &vocs_cb;
493 }
494
495 for (size_t i = 0; i < ARRAY_SIZE(vcp_register_param.aics_param); i++) {
496 vcp_register_param.aics_param[i].desc_writable = true;
497 snprintf(input_desc[i], sizeof(input_desc[i]),
498 "Input %zu", i + 1);
499 vcp_register_param.aics_param[i].description = input_desc[i];
500 vcp_register_param.aics_param[i].type = BT_AICS_INPUT_TYPE_DIGITAL;
501 vcp_register_param.aics_param[i].status = 1;
502 vcp_register_param.aics_param[i].gain_mode = gain_mode;
503 vcp_register_param.aics_param[i].units = 1;
504 vcp_register_param.aics_param[i].min_gain = 0;
505 vcp_register_param.aics_param[i].max_gain = 100;
506 vcp_register_param.aics_param[i].cb = &aics_server_cb;
507 }
508
509 vcp_register_param.step = 1;
510 vcp_register_param.mute = BT_VCP_STATE_UNMUTED;
511 vcp_register_param.volume = 100;
512 vcp_register_param.cb = &vcs_cb;
513 }
514
tester_init_vcs(void)515 uint8_t tester_init_vcs(void)
516 {
517 int err;
518
519 set_register_params(BT_AICS_MODE_MANUAL);
520
521 err = bt_vcp_vol_rend_register(&vcp_register_param);
522 if (err) {
523 return BTP_STATUS_FAILED;
524 }
525
526 err = bt_vcp_vol_rend_included_get(&included);
527 if (err) {
528 return BTP_STATUS_FAILED;
529 }
530
531 aics_server_instance.aics_cnt = included.aics_cnt;
532 aics_server_instance.aics = included.aics;
533
534 tester_register_command_handlers(BTP_SERVICE_ID_VCS, vcs_handlers,
535 ARRAY_SIZE(vcs_handlers));
536
537 return BTP_STATUS_SUCCESS;
538 }
539
tester_unregister_vcs(void)540 uint8_t tester_unregister_vcs(void)
541 {
542 return BTP_STATUS_SUCCESS;
543 }
544
tester_init_vocs(void)545 uint8_t tester_init_vocs(void)
546 {
547 tester_register_command_handlers(BTP_SERVICE_ID_VOCS, vocs_handlers,
548 ARRAY_SIZE(vocs_handlers));
549
550 return BTP_STATUS_SUCCESS;
551 }
552
tester_unregister_vocs(void)553 uint8_t tester_unregister_vocs(void)
554 {
555 return BTP_STATUS_SUCCESS;
556 }
557
558 /* Volume Control Profile */
btp_send_vcp_found_ev(struct bt_conn * conn,uint8_t att_status,const struct service_handles * chrc_handles)559 static void btp_send_vcp_found_ev(struct bt_conn *conn, uint8_t att_status,
560 const struct service_handles *chrc_handles)
561 {
562 struct btp_vcp_discovered_ev ev;
563
564 bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
565
566 ev.att_status = att_status;
567 ev.vcs_handles.control_handle = sys_cpu_to_le16(chrc_handles->vcp_handles.ctrl_pt);
568 ev.vcs_handles.flag_handle = sys_cpu_to_le16(chrc_handles->vcp_handles.flags);
569 ev.vcs_handles.state_handle = sys_cpu_to_le16(chrc_handles->vcp_handles.state);
570 ev.vocs_handles.state_handle = sys_cpu_to_le16(chrc_handles->vocs_handles.state);
571 ev.vocs_handles.location_handle = sys_cpu_to_le16(chrc_handles->vocs_handles.location);
572 ev.vocs_handles.control_handle = sys_cpu_to_le16(chrc_handles->vocs_handles.control);
573 ev.vocs_handles.desc_handle = sys_cpu_to_le16(chrc_handles->vocs_handles.desc);
574 ev.aics_handles.state_handle = sys_cpu_to_le16(chrc_handles->aics_handles.state);
575 ev.aics_handles.gain_handle = sys_cpu_to_le16(chrc_handles->aics_handles.gain);
576 ev.aics_handles.type_handle = sys_cpu_to_le16(chrc_handles->aics_handles.type);
577 ev.aics_handles.status_handle = sys_cpu_to_le16(chrc_handles->aics_handles.status);
578 ev.aics_handles.control_handle = sys_cpu_to_le16(chrc_handles->aics_handles.control);
579 ev.aics_handles.desc_handle = sys_cpu_to_le16(chrc_handles->aics_handles.desc);
580
581 tester_event(BTP_SERVICE_ID_VCP, BTP_VCP_DISCOVERED_EV, &ev, sizeof(ev));
582 }
583
btp_send_vcp_state_ev(struct bt_conn * conn,uint8_t att_status,uint8_t volume,uint8_t mute)584 static void btp_send_vcp_state_ev(struct bt_conn *conn, uint8_t att_status, uint8_t volume,
585 uint8_t mute)
586 {
587 struct btp_vcp_state_ev ev;
588
589 bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
590
591 ev.att_status = att_status;
592 ev.volume = volume;
593 ev.mute = mute;
594
595 tester_event(BTP_SERVICE_ID_VCP, BTP_VCP_STATE_EV, &ev, sizeof(ev));
596 }
597
btp_send_vcp_volume_flags_ev(struct bt_conn * conn,uint8_t att_status,uint8_t flags)598 static void btp_send_vcp_volume_flags_ev(struct bt_conn *conn, uint8_t att_status, uint8_t flags)
599 {
600 struct btp_vcp_volume_flags_ev ev;
601
602 bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
603
604 ev.att_status = att_status;
605 ev.flags = flags;
606
607 tester_event(BTP_SERVICE_ID_VCP, BTP_VCP_FLAGS_EV, &ev, sizeof(ev));
608 }
609
btp_send_vcp_procedure_ev(struct bt_conn * conn,uint8_t att_status,uint8_t opcode)610 static void btp_send_vcp_procedure_ev(struct bt_conn *conn, uint8_t att_status, uint8_t opcode)
611 {
612 struct btp_vcp_procedure_ev ev;
613
614 bt_addr_le_copy(&ev.address, bt_conn_get_dst(conn));
615
616 ev.att_status = att_status;
617 ev.opcode = opcode;
618
619 tester_event(BTP_SERVICE_ID_VCP, BTP_VCP_PROCEDURE_EV, &ev, sizeof(ev));
620 }
621
vcp_supported_commands(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)622 static uint8_t vcp_supported_commands(const void *cmd, uint16_t cmd_len,
623 void *rsp, uint16_t *rsp_len)
624 {
625 struct btp_vcp_read_supported_commands_rp *rp = rsp;
626
627 /* octet 0 */
628 tester_set_bit(rp->data, BTP_VCP_READ_SUPPORTED_COMMANDS);
629 tester_set_bit(rp->data, BTP_VCP_VOL_CTLR_DISCOVER);
630 tester_set_bit(rp->data, BTP_VCP_VOL_CTLR_STATE_READ);
631 tester_set_bit(rp->data, BTP_VCP_VOL_CTLR_FLAGS_READ);
632 tester_set_bit(rp->data, BTP_VCP_VOL_CTLR_VOL_DOWN);
633 tester_set_bit(rp->data, BTP_VCP_VOL_CTLR_VOL_UP);
634 tester_set_bit(rp->data, BTP_VCP_VOL_CTLR_UNMUTE_VOL_DOWN);
635
636 /* octet 1 */
637 tester_set_bit(rp->data, BTP_VCP_VOL_CTLR_UNMUTE_VOL_UP);
638 tester_set_bit(rp->data, BTP_VCP_VOL_CTLR_SET_VOL);
639 tester_set_bit(rp->data, BTP_VCP_VOL_CTLR_UNMUTE);
640 tester_set_bit(rp->data, BTP_VCP_VOL_CTLR_MUTE);
641
642 *rsp_len = sizeof(*rp) + 1;
643
644 return BTP_STATUS_SUCCESS;
645 }
646
vcp_vol_ctlr_discover_cb(struct bt_vcp_vol_ctlr * vol_ctlr,int err,uint8_t vocs_count,uint8_t aics_count)647 static void vcp_vol_ctlr_discover_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err, uint8_t vocs_count,
648 uint8_t aics_count)
649 {
650 struct bt_conn *conn;
651
652 if (err) {
653 LOG_DBG("Discovery failed (%d)", err);
654 return;
655 }
656
657 LOG_DBG("Discovery done with %u VOCS, %u AICS",
658 vocs_count, aics_count);
659
660 bt_vcp_vol_ctlr_conn_get(vol_ctlr, &conn);
661
662 if (bt_vcp_vol_ctlr_included_get(vol_ctlr, &included) != 0) {
663 LOG_DBG("Could not get included services");
664 memset(&chrc_handles.vocs_handles, 0, sizeof(chrc_handles.vocs_handles));
665 memset(&chrc_handles.aics_handles, 0, sizeof(chrc_handles.aics_handles));
666 } else {
667 aics_client_instance.aics_cnt = included.aics_cnt;
668 aics_client_instance.aics = included.aics;
669 bt_vocs_client_cb_register(vol_ctlr->vocs[0], &vocs_cl_cb);
670 bt_aics_client_cb_register(vol_ctlr->aics[0], &aics_client_cb);
671
672 struct bt_vocs_client *vocs_cli =
673 CONTAINER_OF(vol_ctlr->vocs[0], struct bt_vocs_client, vocs);
674 struct bt_aics_client *aics_cli = &vol_ctlr->aics[0]->cli;
675
676 chrc_handles.vocs_handles.state = vocs_cli->state_handle;
677 chrc_handles.vocs_handles.location = vocs_cli->location_handle;
678 chrc_handles.vocs_handles.control = vocs_cli->control_handle;
679 chrc_handles.vocs_handles.desc = vocs_cli->desc_handle;
680 chrc_handles.aics_handles.state = aics_cli->state_handle;
681 chrc_handles.aics_handles.gain = aics_cli->gain_handle;
682 chrc_handles.aics_handles.type = aics_cli->type_handle;
683 chrc_handles.aics_handles.status = aics_cli->status_handle;
684 chrc_handles.aics_handles.control = aics_cli->control_handle;
685 chrc_handles.aics_handles.desc = aics_cli->desc_handle;
686 }
687
688 chrc_handles.vcp_handles.ctrl_pt = vol_ctlr->control_handle;
689 chrc_handles.vcp_handles.flags = vol_ctlr->flag_handle;
690 chrc_handles.vcp_handles.state = vol_ctlr->state_handle;
691 btp_send_vcp_found_ev(conn, err, &chrc_handles);
692 }
693
vcp_vol_ctlr_state_cb(struct bt_vcp_vol_ctlr * vol_ctlr,int err,uint8_t volume,uint8_t mute)694 static void vcp_vol_ctlr_state_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err, uint8_t volume,
695 uint8_t mute)
696 {
697 struct bt_conn *conn;
698
699 bt_vcp_vol_ctlr_conn_get(vol_ctlr, &conn);
700 btp_send_vcp_state_ev(conn, err, volume, mute);
701
702 LOG_DBG("VCP Volume CTLR State callback");
703 }
704
vcp_vol_ctlr_flags_cb(struct bt_vcp_vol_ctlr * vol_ctlr,int err,uint8_t flags)705 static void vcp_vol_ctlr_flags_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err, uint8_t flags)
706 {
707 struct bt_conn *conn;
708
709 bt_vcp_vol_ctlr_conn_get(vol_ctlr, &conn);
710 btp_send_vcp_volume_flags_ev(conn, err, flags);
711
712 LOG_DBG("VCP CTLR Volume Flags callback");
713 }
714
vcp_vol_ctlr_vol_down_cb(struct bt_vcp_vol_ctlr * vol_ctlr,int err)715 static void vcp_vol_ctlr_vol_down_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err)
716 {
717 struct bt_conn *conn;
718
719 bt_vcp_vol_ctlr_conn_get(vol_ctlr, &conn);
720 btp_send_vcp_procedure_ev(conn, err, BTP_VCP_VOL_CTLR_VOL_DOWN);
721
722 LOG_DBG("VCP CTLR Volume down callback");
723 }
724
vcp_vol_ctlr_vol_up_cb(struct bt_vcp_vol_ctlr * vol_ctlr,int err)725 static void vcp_vol_ctlr_vol_up_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err)
726 {
727 struct bt_conn *conn;
728
729 bt_vcp_vol_ctlr_conn_get(vol_ctlr, &conn);
730 btp_send_vcp_procedure_ev(conn, err, BTP_VCP_VOL_CTLR_VOL_UP);
731
732 LOG_DBG("VCP CTLR Volume down callback");
733 }
734
vcp_vol_ctlr_unmute_vol_down_cb(struct bt_vcp_vol_ctlr * vol_ctlr,int err)735 static void vcp_vol_ctlr_unmute_vol_down_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err)
736 {
737 struct bt_conn *conn;
738
739 bt_vcp_vol_ctlr_conn_get(vol_ctlr, &conn);
740 btp_send_vcp_procedure_ev(conn, err, BTP_VCP_VOL_CTLR_UNMUTE_VOL_DOWN);
741
742 LOG_DBG("VCP CTLR Volume down and unmute callback");
743 }
744
vcp_vol_ctlr_unmute_vol_up_cb(struct bt_vcp_vol_ctlr * vol_ctlr,int err)745 static void vcp_vol_ctlr_unmute_vol_up_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err)
746 {
747 struct bt_conn *conn;
748
749 bt_vcp_vol_ctlr_conn_get(vol_ctlr, &conn);
750 btp_send_vcp_procedure_ev(conn, err, BTP_VCP_VOL_CTLR_UNMUTE_VOL_UP);
751
752 LOG_DBG("VCP CTLR Volume down and unmute callback");
753 }
754
vcp_vol_ctlr_set_vol_cb(struct bt_vcp_vol_ctlr * vol_ctlr,int err)755 static void vcp_vol_ctlr_set_vol_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err)
756 {
757 struct bt_conn *conn;
758
759 bt_vcp_vol_ctlr_conn_get(vol_ctlr, &conn);
760 btp_send_vcp_procedure_ev(conn, err, BTP_VCP_VOL_CTLR_SET_VOL);
761
762 LOG_DBG("VCP CTLR Set absolute volume callback");
763 }
764
vcp_vol_ctlr_unmute_cb(struct bt_vcp_vol_ctlr * vol_ctlr,int err)765 static void vcp_vol_ctlr_unmute_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err)
766 {
767 struct bt_conn *conn;
768
769 bt_vcp_vol_ctlr_conn_get(vol_ctlr, &conn);
770 btp_send_vcp_procedure_ev(conn, err, BTP_VCP_VOL_CTLR_UNMUTE);
771
772 LOG_DBG("VCP CTLR Volume down and unmute callback");
773 }
774
vcp_vol_ctlr_mute_cb(struct bt_vcp_vol_ctlr * vol_ctlr,int err)775 static void vcp_vol_ctlr_mute_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err)
776 {
777 struct bt_conn *conn;
778
779 bt_vcp_vol_ctlr_conn_get(vol_ctlr, &conn);
780 btp_send_vcp_procedure_ev(conn, err, BTP_VCP_VOL_CTLR_MUTE);
781
782 LOG_DBG("VCP CTLR Set absolute volume callback");
783 }
784
785 static struct bt_vcp_vol_ctlr_cb vcp_cbs = {
786 .discover = vcp_vol_ctlr_discover_cb,
787 .state = vcp_vol_ctlr_state_cb,
788 .flags = vcp_vol_ctlr_flags_cb,
789 .vol_down = vcp_vol_ctlr_vol_down_cb,
790 .vol_up = vcp_vol_ctlr_vol_up_cb,
791 .mute = vcp_vol_ctlr_mute_cb,
792 .unmute = vcp_vol_ctlr_unmute_cb,
793 .vol_down_unmute = vcp_vol_ctlr_unmute_vol_down_cb,
794 .vol_up_unmute = vcp_vol_ctlr_unmute_vol_up_cb,
795 .vol_set = vcp_vol_ctlr_set_vol_cb
796 };
797
vcp_discover(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)798 static uint8_t vcp_discover(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
799 {
800 const struct btp_vcp_discover_cmd *cp = cmd;
801 struct bt_conn *conn;
802 int err;
803
804 conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &cp->address);
805 if (!conn) {
806 LOG_ERR("Unknown connection");
807 return BTP_STATUS_FAILED;
808 }
809
810 err = bt_vcp_vol_ctlr_discover(conn, &vol_ctlr);
811 if (err) {
812 LOG_DBG("Fail: %d", err);
813 return BTP_STATUS_FAILED;
814 }
815
816 return BTP_STATUS_SUCCESS;
817 }
818
vcp_state_read(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)819 static uint8_t vcp_state_read(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
820 {
821 int err;
822
823 LOG_DBG("VCP State read");
824
825 err = bt_vcp_vol_ctlr_read_state(vol_ctlr);
826 if (err) {
827 return BTP_STATUS_FAILED;
828 }
829
830 return BTP_STATUS_SUCCESS;
831 }
832
vcp_volume_flags_read(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)833 static uint8_t vcp_volume_flags_read(const void *cmd, uint16_t cmd_len, void *rsp,
834 uint16_t *rsp_len)
835 {
836 int err;
837
838 LOG_DBG("VCP Volume Flags read");
839
840 err = bt_vcp_vol_ctlr_read_flags(vol_ctlr);
841 if (err) {
842 return BTP_STATUS_FAILED;
843 }
844
845 return BTP_STATUS_SUCCESS;
846 }
847
vcp_ctlr_vol_down(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)848 static uint8_t vcp_ctlr_vol_down(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
849 {
850 int err;
851
852 LOG_DBG("VCP CTLR Volume down");
853
854 err = bt_vcp_vol_ctlr_vol_down(vol_ctlr);
855 if (err) {
856 return BTP_STATUS_FAILED;
857 }
858
859 return BTP_STATUS_SUCCESS;
860 }
861
vcp_ctlr_vol_up(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)862 static uint8_t vcp_ctlr_vol_up(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
863 {
864 int err;
865
866 LOG_DBG("VCP CTLR Volume up");
867
868 err = bt_vcp_vol_ctlr_vol_up(vol_ctlr);
869 if (err) {
870 return BTP_STATUS_FAILED;
871 }
872
873 return BTP_STATUS_SUCCESS;
874 }
875
vcp_ctlr_unmute_vol_down(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)876 static uint8_t vcp_ctlr_unmute_vol_down(const void *cmd, uint16_t cmd_len, void *rsp,
877 uint16_t *rsp_len)
878 {
879 int err;
880
881 LOG_DBG("VCP CTLR Unmute, vol down");
882
883 err = bt_vcp_vol_ctlr_unmute_vol_down(vol_ctlr);
884 if (err) {
885 return BTP_STATUS_FAILED;
886 }
887
888 return BTP_STATUS_SUCCESS;
889 }
890
vcp_ctlr_unmute_vol_up(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)891 static uint8_t vcp_ctlr_unmute_vol_up(const void *cmd, uint16_t cmd_len, void *rsp,
892 uint16_t *rsp_len)
893 {
894 int err;
895
896 LOG_DBG("VCP CTLR Unmute, Volume up");
897
898 err = bt_vcp_vol_ctlr_unmute_vol_up(vol_ctlr);
899 if (err) {
900 return BTP_STATUS_FAILED;
901 }
902
903 return BTP_STATUS_SUCCESS;
904 }
905
vcp_ctlr_set_vol(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)906 static uint8_t vcp_ctlr_set_vol(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
907 {
908 const struct btp_vcp_ctlr_set_vol_cmd *cp = cmd;
909 int err;
910
911 LOG_DBG("VCP CTLR Set absolute volume %d", cp->volume);
912
913 err = bt_vcp_vol_ctlr_set_vol(vol_ctlr, cp->volume);
914 if (err) {
915 return BTP_STATUS_FAILED;
916 }
917
918 return BTP_STATUS_SUCCESS;
919 }
920
vcp_ctlr_unmute(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)921 static uint8_t vcp_ctlr_unmute(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
922 {
923 int err;
924
925 LOG_DBG("VCP CTLR Unmute");
926
927 err = bt_vcp_vol_ctlr_unmute(vol_ctlr);
928 if (err) {
929 return BTP_STATUS_FAILED;
930 }
931
932 return BTP_STATUS_SUCCESS;
933 }
934
vcp_ctlr_mute(const void * cmd,uint16_t cmd_len,void * rsp,uint16_t * rsp_len)935 static uint8_t vcp_ctlr_mute(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len)
936 {
937 int err;
938
939 LOG_DBG("VCP CTLR Mute");
940
941 err = bt_vcp_vol_ctlr_mute(vol_ctlr);
942 if (err) {
943 return BTP_STATUS_FAILED;
944 }
945
946 return BTP_STATUS_SUCCESS;
947 }
948
949 static const struct btp_handler vcp_handlers[] = {
950 {
951 .opcode = BTP_VCP_READ_SUPPORTED_COMMANDS,
952 .index = BTP_INDEX_NONE,
953 .expect_len = 0,
954 .func = vcp_supported_commands,
955 },
956 {
957 .opcode = BTP_VCP_VOL_CTLR_DISCOVER,
958 .expect_len = sizeof(struct btp_vcp_discover_cmd),
959 .func = vcp_discover,
960 },
961 {
962 .opcode = BTP_VCP_VOL_CTLR_STATE_READ,
963 .expect_len = sizeof(struct btp_vcp_state_read_cmd),
964 .func = vcp_state_read,
965 },
966 {
967 .opcode = BTP_VCP_VOL_CTLR_FLAGS_READ,
968 .expect_len = sizeof(struct btp_vcp_flags_read_cmd),
969 .func = vcp_volume_flags_read,
970 },
971 {
972 .opcode = BTP_VCP_VOL_CTLR_VOL_DOWN,
973 .expect_len = sizeof(struct btp_vcp_ctlr_vol_down_cmd),
974 .func = vcp_ctlr_vol_down,
975 },
976 {
977 .opcode = BTP_VCP_VOL_CTLR_VOL_UP,
978 .expect_len = sizeof(struct btp_vcp_ctlr_vol_up_cmd),
979 .func = vcp_ctlr_vol_up,
980 },
981 {
982 .opcode = BTP_VCP_VOL_CTLR_UNMUTE_VOL_DOWN,
983 .expect_len = sizeof(struct btp_vcp_ctlr_unmute_vol_down_cmd),
984 .func = vcp_ctlr_unmute_vol_down,
985 },
986 {
987 .opcode = BTP_VCP_VOL_CTLR_UNMUTE_VOL_UP,
988 .expect_len = sizeof(struct btp_vcp_ctlr_unmute_vol_up_cmd),
989 .func = vcp_ctlr_unmute_vol_up,
990 },
991 {
992 .opcode = BTP_VCP_VOL_CTLR_SET_VOL,
993 .expect_len = sizeof(struct btp_vcp_ctlr_set_vol_cmd),
994 .func = vcp_ctlr_set_vol,
995 },
996 {
997 .opcode = BTP_VCP_VOL_CTLR_UNMUTE,
998 .expect_len = sizeof(struct btp_vcp_ctlr_unmute_cmd),
999 .func = vcp_ctlr_unmute,
1000 },
1001 {
1002 .opcode = BTP_VCP_VOL_CTLR_MUTE,
1003 .expect_len = sizeof(struct btp_vcp_ctlr_mute_cmd),
1004 .func = vcp_ctlr_mute,
1005 },
1006 };
1007
tester_init_vcp(void)1008 uint8_t tester_init_vcp(void)
1009 {
1010 int err;
1011
1012 err = bt_vcp_vol_ctlr_cb_register(&vcp_cbs);
1013
1014 if (err) {
1015 LOG_DBG("Failed to register callbacks: %d", err);
1016 return BTP_STATUS_FAILED;
1017 }
1018
1019 tester_register_command_handlers(BTP_SERVICE_ID_VCP, vcp_handlers,
1020 ARRAY_SIZE(vcp_handlers));
1021
1022 return BTP_STATUS_SUCCESS;
1023 }
1024
tester_unregister_vcp(void)1025 uint8_t tester_unregister_vcp(void)
1026 {
1027 int err;
1028
1029 err = bt_vcp_vol_ctlr_cb_unregister(&vcp_cbs);
1030 if (err != 0) {
1031 LOG_DBG("Failed to unregister callbacks: %d", err);
1032 return BTP_STATUS_FAILED;
1033 }
1034
1035 return BTP_STATUS_SUCCESS;
1036 }
1037