1 /*
2 * Copyright (c) 2021-2022 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <stdbool.h>
7 #include <stdint.h>
8 #include <string.h>
9
10 #include <zephyr/autoconf.h>
11 #include <zephyr/bluetooth/audio/aics.h>
12 #include <zephyr/bluetooth/audio/audio.h>
13 #include <zephyr/bluetooth/audio/vcp.h>
14 #include <zephyr/bluetooth/audio/vocs.h>
15 #include <zephyr/bluetooth/bluetooth.h>
16 #include <zephyr/sys/printk.h>
17
18 #include "bstests.h"
19 #include "common.h"
20
21 #ifdef CONFIG_BT_VCP_VOL_CTLR
22 #define VOCS_DESC_SIZE 64
23 #define AICS_DESC_SIZE 64
24
25 extern enum bst_result_t bst_result;
26
27 static struct bt_vcp_vol_ctlr *vol_ctlr;
28 static struct bt_vcp_included vcp_included;
29 static volatile bool g_discovery_complete;
30 static volatile bool g_write_complete;
31
32 static volatile uint8_t g_volume;
33 static volatile uint8_t g_mute;
34 static volatile uint8_t g_flags;
35 static volatile int16_t g_vocs_offset;
36 static volatile uint32_t g_vocs_location;
37 static char g_vocs_desc[VOCS_DESC_SIZE];
38 static volatile int8_t g_aics_gain;
39 static volatile uint8_t g_aics_input_mute;
40 static volatile uint8_t g_aics_mode;
41 static volatile uint8_t g_aics_input_type;
42 static volatile uint8_t g_aics_units;
43 static volatile uint8_t g_aics_gain_max;
44 static volatile uint8_t g_aics_gain_min;
45 static volatile bool g_aics_active = 1;
46 static char g_aics_desc[AICS_DESC_SIZE];
47 static volatile bool g_cb;
48
vcs_state_cb(struct bt_vcp_vol_ctlr * vol_ctlr,int err,uint8_t volume,uint8_t mute)49 static void vcs_state_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err,
50 uint8_t volume, uint8_t mute)
51 {
52 if (err != 0) {
53 FAIL("VCP state cb err (%d)", err);
54 return;
55 }
56
57 g_volume = volume;
58 g_mute = mute;
59
60 g_cb = true;
61 }
62
vcs_flags_cb(struct bt_vcp_vol_ctlr * vol_ctlr,int err,uint8_t flags)63 static void vcs_flags_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err,
64 uint8_t flags)
65 {
66 if (err != 0) {
67 FAIL("VCP flags cb err (%d)", err);
68 return;
69 }
70
71 g_flags = flags;
72
73 g_cb = true;
74 }
75
vocs_state_cb(struct bt_vocs * inst,int err,int16_t offset)76 static void vocs_state_cb(struct bt_vocs *inst, int err, int16_t offset)
77 {
78 if (err != 0) {
79 FAIL("VOCS state cb err (%d)", err);
80 return;
81 }
82
83 g_vocs_offset = offset;
84
85 g_cb = true;
86 }
87
vocs_location_cb(struct bt_vocs * inst,int err,uint32_t location)88 static void vocs_location_cb(struct bt_vocs *inst, int err, uint32_t location)
89 {
90 if (err != 0) {
91 FAIL("VOCS location cb err (%d)", err);
92 return;
93 }
94
95 g_vocs_location = location;
96
97 g_cb = true;
98 }
99
vocs_description_cb(struct bt_vocs * inst,int err,char * description)100 static void vocs_description_cb(struct bt_vocs *inst, int err,
101 char *description)
102 {
103 if (err != 0) {
104 FAIL("VOCS description cb err (%d)", err);
105 return;
106 }
107
108 if (strlen(description) > sizeof(g_vocs_desc) - 1) {
109 printk("Warning: VOCS description (%zu) is larger than buffer (%zu)\n",
110 strlen(description), sizeof(g_vocs_desc) - 1);
111 }
112
113 strncpy(g_vocs_desc, description, sizeof(g_vocs_desc) - 1);
114 g_vocs_desc[sizeof(g_vocs_desc) - 1] = '\0';
115
116 g_cb = true;
117 }
118
vocs_write_cb(struct bt_vocs * inst,int err)119 static void vocs_write_cb(struct bt_vocs *inst, int err)
120 {
121 if (err != 0) {
122 FAIL("VOCS write failed (%d)\n", err);
123 return;
124 }
125
126 g_write_complete = true;
127 }
128
aics_state_cb(struct bt_aics * inst,int err,int8_t gain,uint8_t mute,uint8_t mode)129 static void aics_state_cb(struct bt_aics *inst, int err, int8_t gain,
130 uint8_t mute, uint8_t mode)
131 {
132 if (err != 0) {
133 FAIL("AICS state cb err (%d)", err);
134 return;
135 }
136
137 g_aics_gain = gain;
138 g_aics_input_mute = mute;
139 g_aics_mode = mode;
140
141 g_cb = true;
142 }
143
aics_gain_setting_cb(struct bt_aics * inst,int err,uint8_t units,int8_t minimum,int8_t maximum)144 static void aics_gain_setting_cb(struct bt_aics *inst, int err, uint8_t units,
145 int8_t minimum, int8_t maximum)
146 {
147 if (err != 0) {
148 FAIL("AICS gain setting cb err (%d)", err);
149 return;
150 }
151
152 g_aics_units = units;
153 g_aics_gain_min = minimum;
154 g_aics_gain_max = maximum;
155
156 g_cb = true;
157 }
158
aics_input_type_cb(struct bt_aics * inst,int err,uint8_t input_type)159 static void aics_input_type_cb(struct bt_aics *inst, int err,
160 uint8_t input_type)
161 {
162 if (err != 0) {
163 FAIL("AICS input type cb err (%d)", err);
164 return;
165 }
166
167 g_aics_input_type = input_type;
168
169 g_cb = true;
170 }
171
aics_status_cb(struct bt_aics * inst,int err,bool active)172 static void aics_status_cb(struct bt_aics *inst, int err, bool active)
173 {
174 if (err != 0) {
175 FAIL("AICS status cb err (%d)", err);
176 return;
177 }
178
179 g_aics_active = active;
180
181 g_cb = true;
182 }
183
aics_description_cb(struct bt_aics * inst,int err,char * description)184 static void aics_description_cb(struct bt_aics *inst, int err,
185 char *description)
186 {
187 if (err != 0) {
188 FAIL("AICS description cb err (%d)", err);
189 return;
190 }
191
192 if (strlen(description) > sizeof(g_aics_desc) - 1) {
193 printk("Warning: AICS description (%zu) is larger than buffer (%zu)\n",
194 strlen(description), sizeof(g_aics_desc) - 1);
195 }
196
197 strncpy(g_aics_desc, description, sizeof(g_aics_desc) - 1);
198 g_aics_desc[sizeof(g_aics_desc) - 1] = '\0';
199
200 g_cb = true;
201 }
202
aics_write_cb(struct bt_aics * inst,int err)203 static void aics_write_cb(struct bt_aics *inst, int err)
204 {
205 if (err != 0) {
206 FAIL("AICS write failed (%d)\n", err);
207 return;
208 }
209
210 g_write_complete = true;
211 }
212
vcs_discover_cb(struct bt_vcp_vol_ctlr * vol_ctlr,int err,uint8_t vocs_count,uint8_t aics_count)213 static void vcs_discover_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err,
214 uint8_t vocs_count, uint8_t aics_count)
215 {
216 if (err != 0) {
217 FAIL("VCP could not be discovered (%d)\n", err);
218 return;
219 }
220
221 g_discovery_complete = true;
222 }
223
vcs_write_cb(struct bt_vcp_vol_ctlr * vol_ctlr,int err)224 static void vcs_write_cb(struct bt_vcp_vol_ctlr *vol_ctlr, int err)
225 {
226 if (err != 0) {
227 FAIL("VCP write failed (%d)\n", err);
228 return;
229 }
230
231 g_write_complete = true;
232 }
233
test_aics_deactivate(void)234 static void test_aics_deactivate(void)
235 {
236 int err;
237
238 /* Invalid behavior */
239 err = bt_aics_deactivate(NULL);
240 if (err == 0) {
241 FAIL("bt_aics_deactivate with NULL inst pointer did not fail");
242 return;
243 }
244
245 /* Valid behavior */
246 printk("Attempting to deactivate AICS\n");
247 err = bt_aics_deactivate(vcp_included.aics[0]);
248 if (err == 0) {
249 FAIL("bt_aics_deactivate as client instance did not fail");
250 return;
251 }
252 }
253
test_aics_activate(void)254 static void test_aics_activate(void)
255 {
256 int err;
257
258 /* Invalid behavior */
259 err = bt_aics_activate(NULL);
260 if (err == 0) {
261 FAIL("bt_aics_activate with NULL inst pointer did not fail");
262 return;
263 }
264
265 /* Valid behavior */
266 printk("Attempting to activate AICS\n");
267 err = bt_aics_activate(vcp_included.aics[0]);
268 if (err == 0) {
269 FAIL("bt_aics_activate as client instance did not fail");
270 return;
271 }
272 }
273
test_aics_state_get(void)274 static void test_aics_state_get(void)
275 {
276 int err;
277
278 /* Invalid behavior */
279 err = bt_aics_state_get(NULL);
280 if (err == 0) {
281 FAIL("bt_aics_state_get with NULL inst pointer did not fail");
282 return;
283 }
284
285 /* Valid behavior */
286 printk("Getting AICS state\n");
287 g_cb = false;
288
289 err = bt_aics_state_get(vcp_included.aics[0]);
290 if (err != 0) {
291 FAIL("Could not get AICS state (err %d)\n", err);
292 return;
293 }
294
295 WAIT_FOR_COND(g_cb);
296 printk("AICS state get\n");
297 }
298
aics_gain_setting_get(void)299 static void aics_gain_setting_get(void)
300 {
301 int err;
302
303 /* Invalid behavior */
304 err = bt_aics_gain_setting_get(NULL);
305 if (err == 0) {
306 FAIL("bt_aics_gain_setting_get with NULL inst pointer did not fail");
307 return;
308 }
309
310 /* Valid behavior */
311 printk("Getting AICS gain setting\n");
312 g_cb = false;
313
314 err = bt_aics_gain_setting_get(vcp_included.aics[0]);
315 if (err != 0) {
316 FAIL("Could not get AICS gain setting (err %d)\n", err);
317 return;
318 }
319
320 WAIT_FOR_COND(g_cb);
321 printk("AICS gain setting get\n");
322 }
323
aics_type_get(void)324 static void aics_type_get(void)
325 {
326 const uint8_t expected_input_type = BT_AICS_INPUT_TYPE_DIGITAL;
327 int err;
328
329 /* Invalid behavior */
330 err = bt_aics_type_get(NULL);
331 if (err == 0) {
332 FAIL("bt_aics_type_get with NULL inst pointer did not fail");
333 return;
334 }
335
336 /* Valid behavior */
337 printk("Getting AICS input type\n");
338
339 err = bt_aics_type_get(vcp_included.aics[0]);
340 if (err != 0) {
341 FAIL("Could not get AICS input type (err %d)\n", err);
342 return;
343 }
344
345 /* Expect and wait for input_type from init */
346 WAIT_FOR_COND(expected_input_type == g_aics_input_type);
347 printk("AICS input type get\n");
348 }
349
aics_status_get(void)350 static void aics_status_get(void)
351 {
352 int err;
353
354 /* Invalid behavior */
355 err = bt_aics_status_get(NULL);
356 if (err == 0) {
357 FAIL("bt_aics_status_get with NULL inst pointer did not fail");
358 return;
359 }
360
361 /* Valid behavior */
362 printk("Getting AICS status\n");
363 g_cb = false;
364
365 err = bt_aics_status_get(vcp_included.aics[0]);
366 if (err != 0) {
367 FAIL("Could not get AICS status (err %d)\n", err);
368 return;
369 }
370
371 WAIT_FOR_COND(g_cb);
372 printk("AICS status get\n");
373 }
374
aics_get_description(void)375 static void aics_get_description(void)
376 {
377 int err;
378
379 /* Invalid behavior */
380 err = bt_aics_description_get(NULL);
381 if (err == 0) {
382 FAIL("bt_aics_description_get with NULL inst pointer did not fail");
383 return;
384 }
385
386 /* Valid behavior */
387 printk("Getting AICS description\n");
388 g_cb = false;
389
390 err = bt_aics_description_get(vcp_included.aics[0]);
391 if (err != 0) {
392 FAIL("Could not get AICS description (err %d)\n", err);
393 return;
394 }
395
396 WAIT_FOR_COND(g_cb);
397 printk("AICS description get\n");
398 }
399
test_aics_mute(void)400 static void test_aics_mute(void)
401 {
402 const uint8_t expected_input_mute = BT_AICS_STATE_MUTED;
403 int err;
404
405 /* Invalid behavior */
406 err = bt_aics_mute(NULL);
407 if (err == 0) {
408 FAIL("bt_aics_mute with NULL inst pointer did not fail");
409 return;
410 }
411
412 /* Valid behavior */
413 printk("Setting AICS mute\n");
414 g_write_complete = false;
415
416 err = bt_aics_mute(vcp_included.aics[0]);
417 if (err != 0) {
418 FAIL("Could not set AICS mute (err %d)\n", err);
419 return;
420 }
421
422 WAIT_FOR_COND(g_write_complete && expected_input_mute == g_aics_input_mute);
423 printk("AICS mute set\n");
424 }
425
test_aics_unmute(void)426 static void test_aics_unmute(void)
427 {
428 const uint8_t expected_input_mute = BT_AICS_STATE_UNMUTED;
429 int err;
430
431 /* Invalid behavior */
432 err = bt_aics_unmute(NULL);
433 if (err == 0) {
434 FAIL("bt_aics_unmute with NULL inst pointer did not fail");
435 return;
436 }
437
438 /* Valid behavior */
439 printk("Setting AICS unmute\n");
440 g_write_complete = false;
441
442 err = bt_aics_unmute(vcp_included.aics[0]);
443 if (err != 0) {
444 FAIL("Could not set AICS unmute (err %d)\n", err);
445 return;
446 }
447
448 WAIT_FOR_COND(g_write_complete && expected_input_mute == g_aics_input_mute);
449 printk("AICS unmute set\n");
450 }
451
test_aics_automatic_gain_set(void)452 static void test_aics_automatic_gain_set(void)
453 {
454 const uint8_t expected_mode = BT_AICS_MODE_AUTO;
455 int err;
456
457 /* Invalid behavior */
458 err = bt_aics_automatic_gain_set(NULL);
459 if (err == 0) {
460 FAIL("bt_aics_automatic_gain_set with NULL inst pointer did not fail");
461 return;
462 }
463
464 /* Valid behavior */
465 printk("Setting AICS auto mode\n");
466 g_write_complete = false;
467
468 err = bt_aics_automatic_gain_set(vcp_included.aics[0]);
469 if (err != 0) {
470 FAIL("Could not set AICS auto mode (err %d)\n", err);
471 return;
472 }
473
474 WAIT_FOR_COND(g_write_complete && expected_mode == g_aics_mode);
475 printk("AICS auto mode set\n");
476 }
477
test_aics_manual_gain_set(void)478 static void test_aics_manual_gain_set(void)
479 {
480 const uint8_t expected_mode = BT_AICS_MODE_MANUAL;
481 int err;
482
483 /* Invalid behavior */
484 err = bt_aics_manual_gain_set(NULL);
485 if (err == 0) {
486 FAIL("bt_aics_manual_gain_set with NULL inst pointer did not fail");
487 return;
488 }
489
490 /* Valid behavior */
491 printk("Setting AICS manual mode\n");
492 g_write_complete = false;
493
494 err = bt_aics_manual_gain_set(vcp_included.aics[0]);
495 if (err != 0) {
496 FAIL("Could not set AICS manual mode (err %d)\n", err);
497 return;
498 }
499
500 WAIT_FOR_COND(g_write_complete && expected_mode == g_aics_mode);
501 printk("AICS manual mode set\n");
502 }
503
test_aics_gain_set(void)504 static void test_aics_gain_set(void)
505 {
506 const int8_t expected_gain = g_aics_gain_max - 1;
507 int err;
508
509 /* Invalid behavior */
510 err = bt_aics_gain_set(NULL, expected_gain);
511 if (err == 0) {
512 FAIL("bt_aics_gain_set with NULL inst pointer did not fail");
513 return;
514 }
515
516 /* Valid behavior */
517 printk("Setting AICS gain\n");
518 g_write_complete = false;
519
520 err = bt_aics_gain_set(vcp_included.aics[0], expected_gain);
521 if (err != 0) {
522 FAIL("Could not set AICS gain (err %d)\n", err);
523 return;
524 }
525
526 WAIT_FOR_COND(g_write_complete && expected_gain == g_aics_gain);
527 printk("AICS gain set\n");
528 }
529
test_aics_description_set(void)530 static void test_aics_description_set(void)
531 {
532 const char *expected_aics_desc = "New Input Description";
533 int err;
534
535 /* Invalid behavior */
536 err = bt_aics_description_set(NULL, expected_aics_desc);
537 if (err == 0) {
538 FAIL("bt_aics_description_set with NULL inst pointer did not fail");
539 return;
540 }
541
542 err = bt_aics_description_set(vcp_included.aics[0], NULL);
543 if (err == 0) {
544 FAIL("bt_aics_description_set with NULL description pointer did not fail");
545 return;
546 }
547
548 /* Valid behavior */
549 printk("Setting AICS Description\n");
550 g_cb = false;
551
552 err = bt_aics_description_set(vcp_included.aics[0], expected_aics_desc);
553 if (err != 0) {
554 FAIL("Could not set AICS Description (err %d)\n", err);
555 return;
556 }
557
558 WAIT_FOR_COND(g_cb &&
559 strncmp(expected_aics_desc, g_aics_desc, strlen(expected_aics_desc)) == 0);
560 printk("AICS Description set\n");
561 }
562
test_aics(void)563 static void test_aics(void)
564 {
565 test_aics_deactivate();
566 test_aics_activate();
567 test_aics_state_get();
568 aics_gain_setting_get();
569 aics_type_get();
570 aics_status_get();
571 aics_get_description();
572 test_aics_mute();
573 test_aics_unmute();
574 test_aics_automatic_gain_set();
575 test_aics_manual_gain_set();
576 test_aics_gain_set();
577 test_aics_description_set();
578 }
579
test_vocs_state_get(void)580 static void test_vocs_state_get(void)
581 {
582 int err;
583
584 /* Invalid behavior */
585 err = bt_vocs_state_get(NULL);
586 if (err == 0) {
587 FAIL("bt_vocs_state_get with NULL inst pointer did not fail");
588 return;
589 }
590
591 /* Valid behavior */
592 printk("Getting VOCS state\n");
593 g_cb = false;
594
595 err = bt_vocs_state_get(vcp_included.vocs[0]);
596 if (err != 0) {
597 FAIL("Could not get VOCS state (err %d)\n", err);
598 return;
599 }
600
601 WAIT_FOR_COND(g_cb);
602 printk("VOCS state get\n");
603 }
604
test_vocs_location_get(void)605 static void test_vocs_location_get(void)
606 {
607 int err;
608
609 /* Invalid behavior */
610 err = bt_vocs_location_get(NULL);
611 if (err == 0) {
612 FAIL("bt_vocs_location_get with NULL inst pointer did not fail");
613 return;
614 }
615
616 /* Valid behavior */
617 printk("Getting VOCS location\n");
618 g_cb = false;
619
620 err = bt_vocs_location_get(vcp_included.vocs[0]);
621 if (err != 0) {
622 FAIL("Could not get VOCS location (err %d)\n", err);
623 return;
624 }
625
626 WAIT_FOR_COND(g_cb);
627 printk("VOCS location get\n");
628 }
629
test_vocs_description_get(void)630 static void test_vocs_description_get(void)
631 {
632 int err;
633
634 /* Invalid behavior */
635 err = bt_vocs_description_get(NULL);
636 if (err == 0) {
637 FAIL("bt_vocs_description_get with NULL inst pointer did not fail");
638 return;
639 }
640
641 /* Valid behavior */
642 printk("Getting VOCS description\n");
643 g_cb = false;
644
645 err = bt_vocs_description_get(vcp_included.vocs[0]);
646 if (err != 0) {
647 FAIL("Could not get VOCS description (err %d)\n", err);
648 return;
649 }
650
651 WAIT_FOR_COND(g_cb);
652 printk("VOCS description get\n");
653 }
654
test_vocs_location_set(void)655 static void test_vocs_location_set(void)
656 {
657 const uint32_t expected_location = g_vocs_location + 1;
658 uint32_t invalid_location;
659 int err;
660
661 /* Invalid behavior */
662 err = bt_vocs_location_set(NULL, expected_location);
663 if (err == 0) {
664 FAIL("bt_vocs_location_set with NULL inst pointer did not fail");
665 return;
666 }
667
668 invalid_location = BT_AUDIO_LOCATION_ANY + 1;
669
670 err = bt_vocs_location_set(vcp_included.vocs[0], invalid_location);
671 if (err == 0) {
672 FAIL("bt_vocs_location_set with location 0x%08X did not fail", invalid_location);
673 return;
674 }
675
676 /* Valid behavior */
677 printk("Setting VOCS location\n");
678
679 err = bt_vocs_location_set(vcp_included.vocs[0], expected_location);
680 if (err != 0) {
681 FAIL("Could not set VOCS location (err %d)\n", err);
682 return;
683 }
684
685 WAIT_FOR_COND(expected_location == g_vocs_location);
686 printk("VOCS location set\n");
687 }
688
test_vocs_state_set(void)689 static void test_vocs_state_set(void)
690 {
691 const int16_t expected_offset = g_vocs_offset + 1;
692 int16_t invalid_offset;
693 int err;
694
695 /* Invalid behavior */
696 err = bt_vocs_state_set(NULL, expected_offset);
697 if (err == 0) {
698 FAIL("bt_vocs_state_set with NULL inst pointer did not fail");
699 return;
700 }
701
702 invalid_offset = BT_VOCS_MIN_OFFSET - 1;
703
704 err = bt_vocs_state_set(vcp_included.vocs[0], invalid_offset);
705 if (err == 0) {
706 FAIL("bt_vocs_state_set with NULL offset %d did not fail", invalid_offset);
707 return;
708 }
709
710 invalid_offset = BT_VOCS_MAX_OFFSET + 1;
711
712 err = bt_vocs_state_set(vcp_included.vocs[0], invalid_offset);
713 if (err == 0) {
714 FAIL("bt_vocs_state_set with NULL offset %d did not fail", invalid_offset);
715 return;
716 }
717
718 /* Valid behavior */
719 printk("Setting VOCS state\n");
720 g_write_complete = false;
721
722 err = bt_vocs_state_set(vcp_included.vocs[0], expected_offset);
723 if (err != 0) {
724 FAIL("Could not set VOCS state (err %d)\n", err);
725 return;
726 }
727
728 WAIT_FOR_COND(g_write_complete && expected_offset == g_vocs_offset);
729 printk("VOCS state set\n");
730 }
731
test_vocs_description_set(void)732 static void test_vocs_description_set(void)
733 {
734 const char *expected_vocs_desc = "New Output Description";
735 int err;
736
737 /* Invalid behavior */
738 err = bt_vocs_description_set(NULL, expected_vocs_desc);
739 if (err == 0) {
740 FAIL("bt_vocs_description_set with NULL inst pointer did not fail");
741 return;
742 }
743
744 err = bt_vocs_description_set(vcp_included.vocs[0], NULL);
745 if (err == 0) {
746 FAIL("bt_vocs_description_set with NULL description pointer did not fail");
747 return;
748 }
749
750 /* Valid behavior */
751 printk("Setting VOCS description\n");
752 g_cb = false;
753
754 err = bt_vocs_description_set(vcp_included.vocs[0], expected_vocs_desc);
755 if (err != 0) {
756 FAIL("Could not set VOCS description (err %d)\n", err);
757 return;
758 }
759
760 WAIT_FOR_COND(g_cb &&
761 strncmp(expected_vocs_desc, g_vocs_desc, strlen(expected_vocs_desc)) == 0);
762 printk("VOCS description set\n");
763 }
764
test_vocs(void)765 static void test_vocs(void)
766 {
767 test_vocs_state_get();
768 test_vocs_location_get();
769 test_vocs_description_get();
770 test_vocs_location_set();
771 test_vocs_state_set();
772 test_vocs_description_set();
773 }
774
test_cb_register(void)775 static void test_cb_register(void)
776 {
777 static struct bt_vcp_vol_ctlr_cb vcp_cbs = {
778 .discover = vcs_discover_cb,
779 .vol_down = vcs_write_cb,
780 .vol_up = vcs_write_cb,
781 .mute = vcs_write_cb,
782 .unmute = vcs_write_cb,
783 .vol_down_unmute = vcs_write_cb,
784 .vol_up_unmute = vcs_write_cb,
785 .vol_set = vcs_write_cb,
786 .state = vcs_state_cb,
787 .flags = vcs_flags_cb,
788 .vocs_cb = {
789 .state = vocs_state_cb,
790 .location = vocs_location_cb,
791 .description = vocs_description_cb,
792 .set_offset = vocs_write_cb,
793 },
794 .aics_cb = {
795 .state = aics_state_cb,
796 .gain_setting = aics_gain_setting_cb,
797 .type = aics_input_type_cb,
798 .status = aics_status_cb,
799 .description = aics_description_cb,
800 .set_gain = aics_write_cb,
801 .unmute = aics_write_cb,
802 .mute = aics_write_cb,
803 .set_manual_mode = aics_write_cb,
804 .set_auto_mode = aics_write_cb,
805 }
806 };
807 int err;
808
809 err = bt_vcp_vol_ctlr_cb_register(&vcp_cbs);
810 if (err != 0) {
811 FAIL("CB register failed (err %d)\n", err);
812 return;
813 }
814 }
815
test_discover(void)816 static void test_discover(void)
817 {
818 int err;
819
820 g_discovery_complete = false;
821
822 /* Invalid behavior */
823 err = bt_vcp_vol_ctlr_discover(NULL, &vol_ctlr);
824 if (err == 0) {
825 FAIL("bt_vcp_vol_ctlr_discover with NULL conn pointer did not fail");
826 return;
827 }
828
829 err = bt_vcp_vol_ctlr_discover(default_conn, NULL);
830 if (err == 0) {
831 FAIL("bt_vcp_vol_ctlr_discover with NULL inst pointer did not fail");
832 return;
833 }
834
835 /* Valid behavior */
836 err = bt_vcp_vol_ctlr_discover(default_conn, &vol_ctlr);
837 if (err != 0) {
838 FAIL("Failed to discover VCP %d", err);
839 return;
840 }
841
842 WAIT_FOR_COND(g_discovery_complete);
843 }
844
test_included_get(void)845 static void test_included_get(void)
846 {
847 int err;
848
849 /* Invalid behavior */
850 err = bt_vcp_vol_ctlr_included_get(NULL, &vcp_included);
851 if (err == 0) {
852 FAIL("bt_vcp_vol_ctlr_included_get with NULL inst pointer did not fail");
853 return;
854 }
855
856 err = bt_vcp_vol_ctlr_included_get(vol_ctlr, NULL);
857 if (err == 0) {
858 FAIL("bt_vcp_vol_ctlr_included_get with NULL include pointer did not fail");
859 return;
860 }
861
862 /* Valid behavior */
863 err = bt_vcp_vol_ctlr_included_get(vol_ctlr, &vcp_included);
864 if (err != 0) {
865 FAIL("Failed to get VCP included services (err %d)\n", err);
866 return;
867 }
868 }
869
test_conn_get(void)870 static void test_conn_get(void)
871 {
872 struct bt_conn *cached_conn;
873 int err;
874
875 /* Invalid behavior */
876 err = bt_vcp_vol_ctlr_conn_get(NULL, &cached_conn);
877 if (err == 0) {
878 FAIL("bt_vcp_vol_ctlr_conn_get with NULL inst pointer did not fail");
879 return;
880 }
881
882 err = bt_vcp_vol_ctlr_conn_get(vol_ctlr, NULL);
883 if (err == 0) {
884 FAIL("bt_vcp_vol_ctlr_conn_get with NULL cached_conn pointer did not fail");
885 return;
886 }
887
888 /* Valid behavior */
889 printk("Getting VCP volume controller conn\n");
890
891 err = bt_vcp_vol_ctlr_conn_get(vol_ctlr, &cached_conn);
892 if (err != 0) {
893 FAIL("Could not get VCP volume controller conn (err %d)\n", err);
894 return;
895 }
896
897 if (cached_conn != default_conn) {
898 FAIL("Cached conn was not the conn used to discover");
899 return;
900 }
901
902 printk("Got VCP volume controller conn\n");
903 }
904
test_read_state(void)905 static void test_read_state(void)
906 {
907 int err;
908
909 /* Invalid behavior */
910 err = bt_vcp_vol_ctlr_read_state(NULL);
911 if (err == 0) {
912 FAIL("bt_vcp_vol_ctlr_read_state with NULL inst pointer did not fail");
913 return;
914 }
915
916 /* Valid behavior */
917 printk("Getting VCP volume state\n");
918 g_cb = false;
919
920 err = bt_vcp_vol_ctlr_read_state(vol_ctlr);
921 if (err != 0) {
922 FAIL("Could not get VCP volume (err %d)\n", err);
923 return;
924 }
925
926 WAIT_FOR_COND(g_cb);
927 printk("VCP volume get\n");
928 }
929
test_read_flags(void)930 static void test_read_flags(void)
931 {
932 int err;
933
934 /* Invalid behavior */
935 err = bt_vcp_vol_ctlr_read_flags(NULL);
936 if (err == 0) {
937 FAIL("bt_vcp_vol_ctlr_read_flags with NULL inst pointer did not fail");
938 return;
939 }
940
941 /* Valid behavior */
942 printk("Getting VCP flags\n");
943 g_cb = false;
944
945 err = bt_vcp_vol_ctlr_read_flags(vol_ctlr);
946 if (err != 0) {
947 FAIL("Could not get VCP flags (err %d)\n", err);
948 return;
949 }
950
951 WAIT_FOR_COND(g_cb);
952 printk("VCP flags get\n");
953 }
954
test_set_vol(void)955 static void test_set_vol(void)
956 {
957 const uint8_t expected_volume = g_volume + 5; /* Overflow is OK */
958 int err;
959
960 g_write_complete = g_cb = false;
961
962 /* Invalid behavior - No invalid volume values to attempt to set */
963 err = bt_vcp_vol_ctlr_set_vol(NULL, expected_volume);
964 if (err == 0) {
965 FAIL("bt_vcp_vol_ctlr_set_vol with NULL inst pointer did not fail");
966 return;
967 }
968
969 /* Valid behavior */
970 err = bt_vcp_vol_ctlr_set_vol(vol_ctlr, expected_volume);
971 if (err != 0) {
972 FAIL("Could not set VCP volume (err %d)\n", err);
973 return;
974 }
975
976 WAIT_FOR_COND(g_volume == expected_volume && g_cb && g_write_complete);
977 printk("VCP volume set\n");
978 }
979
test_vol_down(void)980 static void test_vol_down(void)
981 {
982 const uint8_t previous_volume = g_volume;
983 int err;
984
985 /* Invalid behavior */
986 err = bt_vcp_vol_ctlr_vol_down(NULL);
987 if (err == 0) {
988 FAIL("bt_vcp_vol_ctlr_vol_down with NULL inst pointer did not fail");
989 return;
990 }
991
992 /* Valid behavior */
993 printk("Downing VCP volume\n");
994 g_write_complete = g_cb = false;
995
996 err = bt_vcp_vol_ctlr_vol_down(vol_ctlr);
997 if (err != 0) {
998 FAIL("Could not get down VCP volume (err %d)\n", err);
999 return;
1000 }
1001
1002 WAIT_FOR_COND(previous_volume == 0 ||
1003 (g_volume < previous_volume && g_cb && g_write_complete));
1004 printk("VCP volume downed\n");
1005 }
1006
test_vol_up(void)1007 static void test_vol_up(void)
1008 {
1009 const uint8_t previous_volume = g_volume;
1010 int err;
1011
1012 /* Invalid behavior */
1013 err = bt_vcp_vol_ctlr_vol_up(NULL);
1014 if (err == 0) {
1015 FAIL("bt_vcp_vol_ctlr_vol_up with NULL inst pointer did not fail");
1016 return;
1017 }
1018
1019 /* Valid behavior */
1020 printk("Upping VCP volume\n");
1021 g_write_complete = g_cb = false;
1022
1023 err = bt_vcp_vol_ctlr_vol_up(vol_ctlr);
1024 if (err != 0) {
1025 FAIL("Could not up VCP volume (err %d)\n", err);
1026 return;
1027 }
1028
1029 WAIT_FOR_COND(previous_volume == UINT8_MAX ||
1030 (g_volume > previous_volume && g_cb && g_write_complete));
1031 printk("VCP volume upped\n");
1032 }
1033
test_mute(void)1034 static void test_mute(void)
1035 {
1036 const uint8_t expected_mute = BT_VCP_STATE_MUTED;
1037 int err;
1038
1039 /* Invalid behavior */
1040 err = bt_vcp_vol_ctlr_mute(NULL);
1041 if (err == 0) {
1042 FAIL("bt_vcp_vol_ctlr_mute with NULL inst pointer did not fail");
1043 return;
1044 }
1045
1046 /* Valid behavior */
1047 printk("Muting VCP\n");
1048 g_write_complete = g_cb = false;
1049
1050 err = bt_vcp_vol_ctlr_mute(vol_ctlr);
1051 if (err != 0) {
1052 FAIL("Could not mute VCP (err %d)\n", err);
1053 return;
1054 }
1055
1056 WAIT_FOR_COND(g_mute == expected_mute && g_cb && g_write_complete);
1057 printk("VCP muted\n");
1058 }
1059
test_unmute_vol_down(void)1060 static void test_unmute_vol_down(void)
1061 {
1062 const uint8_t expected_mute = BT_VCP_STATE_UNMUTED;
1063 const uint8_t previous_volume = g_volume;
1064 int err;
1065
1066 /* Invalid behavior */
1067 err = bt_vcp_vol_ctlr_unmute_vol_down(NULL);
1068 if (err == 0) {
1069 FAIL("bt_vcp_vol_ctlr_unmute_vol_down with NULL inst pointer did not fail");
1070 return;
1071 }
1072
1073 /* Valid behavior */
1074 printk("Downing and unmuting VCP\n");
1075 g_write_complete = g_cb = false;
1076
1077 err = bt_vcp_vol_ctlr_unmute_vol_down(vol_ctlr);
1078 if (err != 0) {
1079 FAIL("Could not down and unmute VCP (err %d)\n", err);
1080 return;
1081 }
1082
1083 WAIT_FOR_COND((previous_volume == 0 || g_volume < previous_volume) &&
1084 expected_mute == g_mute &&
1085 g_cb &&
1086 g_write_complete);
1087 printk("VCP volume downed and unmuted\n");
1088 }
1089
test_unmute_vol_up(void)1090 static void test_unmute_vol_up(void)
1091 {
1092 const uint8_t expected_mute = BT_VCP_STATE_UNMUTED;
1093 const uint8_t previous_volume = g_volume;
1094 int err;
1095
1096 /* Invalid behavior */
1097 err = bt_vcp_vol_ctlr_unmute_vol_up(NULL);
1098 if (err == 0) {
1099 FAIL("bt_vcp_vol_ctlr_unmute_vol_up with NULL inst pointer did not fail");
1100 return;
1101 }
1102
1103 /* Valid behavior */
1104 printk("Upping and unmuting VCP\n");
1105 g_write_complete = g_cb = false;
1106
1107 err = bt_vcp_vol_ctlr_unmute_vol_up(vol_ctlr);
1108 if (err != 0) {
1109 FAIL("Could not up and unmute VCP (err %d)\n", err);
1110 return;
1111 }
1112
1113 WAIT_FOR_COND((previous_volume == UINT8_MAX || g_volume > previous_volume) &&
1114 g_mute == expected_mute &&
1115 g_cb &&
1116 g_write_complete);
1117 printk("VCP volume upped and unmuted\n");
1118 }
1119
test_unmute(void)1120 static void test_unmute(void)
1121 {
1122 const uint8_t expected_mute = BT_VCP_STATE_UNMUTED;
1123 int err;
1124
1125 /* Invalid behavior */
1126 err = bt_vcp_vol_ctlr_unmute(NULL);
1127 if (err == 0) {
1128 FAIL("bt_vcp_vol_ctlr_unmute with NULL inst pointer did not fail");
1129 return;
1130 }
1131
1132 /* Valid behavior */
1133 printk("Unmuting VCP\n");
1134 g_write_complete = g_cb = false;
1135
1136 err = bt_vcp_vol_ctlr_unmute(vol_ctlr);
1137 if (err != 0) {
1138 FAIL("Could not unmute VCP (err %d)\n", err);
1139 return;
1140 }
1141
1142 WAIT_FOR_COND(g_mute == expected_mute && g_cb && g_write_complete);
1143 printk("VCP volume unmuted\n");
1144 }
1145
test_main(void)1146 static void test_main(void)
1147 {
1148 int err;
1149
1150 err = bt_enable(NULL);
1151 if (err != 0) {
1152 FAIL("Bluetooth discover failed (err %d)\n", err);
1153 return;
1154 }
1155
1156 bt_le_scan_cb_register(&common_scan_cb);
1157 test_cb_register();
1158
1159 err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL);
1160 if (err != 0) {
1161 FAIL("Scanning failed to start (err %d)\n", err);
1162 return;
1163 }
1164
1165 printk("Scanning successfully started\n");
1166
1167 WAIT_FOR_FLAG(flag_connected);
1168
1169 test_discover();
1170 test_discover(); /* test that we can discover twice */
1171 test_included_get();
1172 test_conn_get();
1173 test_read_state();
1174 test_read_flags();
1175 test_set_vol();
1176 test_vol_down();
1177 test_vol_up();
1178 test_mute();
1179 test_unmute_vol_down();
1180 test_mute();
1181 test_unmute_vol_up();
1182 test_mute();
1183 test_unmute();
1184
1185 if (CONFIG_BT_VCP_VOL_CTLR_VOCS > 0) {
1186 test_vocs();
1187 }
1188
1189 if (CONFIG_BT_VCP_VOL_CTLR_MAX_AICS_INST > 0) {
1190 test_aics();
1191 }
1192
1193 PASS("VCP volume controller Passed\n");
1194 }
1195
1196 static const struct bst_test_instance test_vcs[] = {
1197 {
1198 .test_id = "vcp_vol_ctlr",
1199 .test_pre_init_f = test_init,
1200 .test_tick_f = test_tick,
1201 .test_main_f = test_main
1202 },
1203 BSTEST_END_MARKER
1204 };
1205
test_vcp_vol_ctlr_install(struct bst_test_list * tests)1206 struct bst_test_list *test_vcp_vol_ctlr_install(struct bst_test_list *tests)
1207 {
1208 return bst_add_tests(tests, test_vcs);
1209 }
1210
1211 #else
1212
test_vcp_vol_ctlr_install(struct bst_test_list * tests)1213 struct bst_test_list *test_vcp_vol_ctlr_install(struct bst_test_list *tests)
1214 {
1215 return tests;
1216 }
1217
1218 #endif /* CONFIG_BT_VCP_VOL_CTLR */
1219