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