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