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