Skip to content

Commit a7fe853

Browse files
Thalleyaescolar
authored andcommitted
tests: bsim: Bluetooth: Add broadcast sink cfg data validation
Add additional validation of the config data in the broadcast sink test, both ensuring that the BASE is properly parsed, that the BASE contains mandatory information and that the stream get the right values copied. Signed-off-by: Emil Gydesen <[email protected]>
1 parent 8a6c1d9 commit a7fe853

File tree

1 file changed

+243
-3
lines changed

1 file changed

+243
-3
lines changed

tests/bsim/bluetooth/audio/src/bap_broadcast_sink_test.c

Lines changed: 243 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,24 @@ static uint32_t requested_bis_sync;
3737
static struct bt_le_ext_adv *ext_adv;
3838
static const struct bt_bap_scan_delegator_recv_state *req_recv_state;
3939

40+
#define SUPPORTED_CHAN_COUNTS BT_AUDIO_CODEC_CAP_CHAN_COUNT_SUPPORT(1, 2)
41+
#define SUPPORTED_MIN_OCTETS_PER_FRAME 30
42+
#define SUPPORTED_MAX_OCTETS_PER_FRAME 155
43+
#define SUPPORTED_MAX_FRAMES_PER_SDU 1
44+
45+
/* We support 1 or 2 channels, so the maximum SDU size we support will be 2 times the maximum frame
46+
* size per frame we support
47+
*/
48+
#define SUPPORTED_MAX_SDU_SIZE (2 * SUPPORTED_MAX_FRAMES_PER_SDU * SUPPORTED_MAX_OCTETS_PER_FRAME)
49+
50+
BUILD_ASSERT(CONFIG_BT_ISO_RX_MTU >= SUPPORTED_MAX_SDU_SIZE);
51+
52+
#define SUPPORTED_CONTEXTS (BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA)
53+
4054
static const struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP_LC3(
41-
BT_AUDIO_CODEC_CAP_FREQ_ANY, BT_AUDIO_CODEC_CAP_DURATION_ANY,
42-
BT_AUDIO_CODEC_CAP_CHAN_COUNT_SUPPORT(1, 2), 30, 240, 2,
43-
(BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA));
55+
BT_AUDIO_CODEC_CAP_FREQ_ANY, BT_AUDIO_CODEC_CAP_DURATION_ANY, SUPPORTED_CHAN_COUNTS,
56+
SUPPORTED_MIN_OCTETS_PER_FRAME, SUPPORTED_MAX_OCTETS_PER_FRAME,
57+
SUPPORTED_MAX_FRAMES_PER_SDU, SUPPORTED_CONTEXTS);
4458

4559
static K_SEM_DEFINE(sem_started, 0U, ARRAY_SIZE(streams));
4660
static K_SEM_DEFINE(sem_stopped, 0U, ARRAY_SIZE(streams));
@@ -52,6 +66,122 @@ static K_SEM_DEFINE(sem_stopped, 0U, ARRAY_SIZE(streams));
5266
static const uint32_t bis_index_mask = BIT_MASK(ARRAY_SIZE(streams) + 1U);
5367
static uint32_t bis_index_bitfield;
5468

69+
static uint8_t count_bits(enum bt_audio_location chan_allocation)
70+
{
71+
uint8_t cnt = 0U;
72+
73+
while (chan_allocation != 0) {
74+
cnt += chan_allocation & 1U;
75+
chan_allocation >>= 1;
76+
}
77+
78+
return cnt;
79+
}
80+
81+
static bool valid_base_subgroup(const struct bt_bap_base_subgroup *subgroup)
82+
{
83+
struct bt_audio_codec_cfg codec_cfg = {0};
84+
enum bt_audio_location chan_allocation;
85+
uint8_t frames_blocks_per_sdu;
86+
size_t min_sdu_size_required;
87+
uint16_t octets_per_frame;
88+
uint8_t chan_cnt;
89+
int ret;
90+
91+
ret = bt_bap_base_subgroup_codec_to_codec_cfg(subgroup, &codec_cfg);
92+
if (ret < 0) {
93+
printk("Could not get subgroup codec_cfg: %d\n", ret);
94+
95+
return false;
96+
}
97+
98+
ret = bt_audio_codec_cfg_get_freq(&codec_cfg);
99+
if (ret >= 0) {
100+
const int freq = bt_audio_codec_cfg_freq_to_freq_hz(ret);
101+
102+
if (freq < 0) {
103+
printk("Invalid subgroup frequency value: %d (%d)\n", ret, freq);
104+
105+
return false;
106+
}
107+
} else {
108+
printk("Could not get subgroup frequency: %d\n", ret);
109+
110+
return false;
111+
}
112+
113+
ret = bt_audio_codec_cfg_get_frame_dur(&codec_cfg);
114+
if (ret >= 0) {
115+
const int frame_duration_us = bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret);
116+
117+
if (frame_duration_us < 0) {
118+
printk("Invalid subgroup frame duration value: %d (%d)\n", ret,
119+
frame_duration_us);
120+
121+
return false;
122+
}
123+
} else {
124+
printk("Could not get subgroup frame duration: %d\n", ret);
125+
126+
return false;
127+
}
128+
129+
ret = bt_audio_codec_cfg_get_chan_allocation(&codec_cfg, &chan_allocation);
130+
if (ret == 0) {
131+
chan_cnt = count_bits(chan_allocation);
132+
} else {
133+
printk("Could not get subgroup channel allocation: %d\n", ret);
134+
/* Channel allocation is an optional field, and omitting it implicitly means mono */
135+
chan_cnt = 1U;
136+
}
137+
138+
if (chan_cnt == 0 || (BIT(chan_cnt - 1) & SUPPORTED_CHAN_COUNTS) == 0) {
139+
printk("Unsupported channel count: %u\n", chan_cnt);
140+
141+
return false;
142+
}
143+
144+
ret = bt_audio_codec_cfg_get_octets_per_frame(&codec_cfg);
145+
if (ret > 0) {
146+
octets_per_frame = (uint16_t)ret;
147+
} else {
148+
printk("Could not get subgroup octets per frame: %d\n", ret);
149+
150+
return false;
151+
}
152+
153+
if (!IN_RANGE(octets_per_frame, SUPPORTED_MIN_OCTETS_PER_FRAME,
154+
SUPPORTED_MAX_OCTETS_PER_FRAME)) {
155+
printk("Unsupported octets per frame: %u\n", octets_per_frame);
156+
157+
return false;
158+
}
159+
160+
ret = bt_audio_codec_cfg_get_frame_blocks_per_sdu(&codec_cfg, false);
161+
if (ret > 0) {
162+
frames_blocks_per_sdu = (uint8_t)ret;
163+
} else {
164+
printk("Could not get subgroup octets per frame: %d\n", ret);
165+
/* Frame blocks per SDU is optional and is implicitly 1 */
166+
frames_blocks_per_sdu = 1U;
167+
}
168+
169+
/* An SDU can consist of X frame blocks, each with Y frames (one per channel) of size Z in
170+
* them. The minimum SDU size required for this is X * Y * Z.
171+
*/
172+
min_sdu_size_required = chan_cnt * octets_per_frame * frames_blocks_per_sdu;
173+
if (min_sdu_size_required > SUPPORTED_MAX_SDU_SIZE) {
174+
printk("With %zu channels and %u octets per frame and %u frames per block, SDUs "
175+
"shall be at minimum %zu, we only support %d\n",
176+
chan_cnt, octets_per_frame, frames_blocks_per_sdu, min_sdu_size_required,
177+
SUPPORTED_MAX_SDU_SIZE);
178+
179+
return false;
180+
}
181+
182+
return true;
183+
}
184+
55185
static bool base_subgroup_cb(const struct bt_bap_base_subgroup *subgroup, void *user_data)
56186
{
57187
static uint8_t metadata[CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE];
@@ -74,6 +204,11 @@ static bool base_subgroup_cb(const struct bt_bap_base_subgroup *subgroup, void *
74204
metadata_size = (size_t)ret;
75205
(void)memcpy(metadata, meta, metadata_size);
76206

207+
if (!valid_base_subgroup(subgroup)) {
208+
printk("Invalid or unsupported subgroup\n");
209+
return false;
210+
}
211+
77212
return true;
78213
}
79214

@@ -258,10 +393,115 @@ static struct bt_bap_scan_delegator_cb scan_delegator_cbs = {
258393
.bis_sync_req = bis_sync_req_cb,
259394
};
260395

396+
static void validate_stream_codec_cfg(const struct bt_bap_stream *stream)
397+
{
398+
struct bt_audio_codec_cfg *codec_cfg = stream->codec_cfg;
399+
enum bt_audio_location chan_allocation;
400+
uint8_t frames_blocks_per_sdu;
401+
size_t min_sdu_size_required;
402+
uint16_t octets_per_frame;
403+
uint8_t chan_cnt;
404+
int ret;
405+
406+
ret = bt_audio_codec_cfg_get_freq(codec_cfg);
407+
if (ret >= 0) {
408+
const int freq = bt_audio_codec_cfg_freq_to_freq_hz(ret);
409+
410+
if (freq < 0) {
411+
FAIL("Invalid frequency value: %d (%d)\n", ret, freq);
412+
413+
return;
414+
}
415+
} else {
416+
FAIL("Could not get frequency: %d\n", ret);
417+
418+
return;
419+
}
420+
421+
ret = bt_audio_codec_cfg_get_frame_dur(codec_cfg);
422+
if (ret >= 0) {
423+
const int frame_duration_us = bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret);
424+
425+
if (frame_duration_us < 0) {
426+
FAIL("Invalid frame duration value: %d (%d)\n", ret, frame_duration_us);
427+
428+
return;
429+
}
430+
} else {
431+
FAIL("Could not get frame duration: %d\n", ret);
432+
433+
return;
434+
}
435+
436+
/* The broadcast source sets the channel allocation in the BIS to
437+
* BT_AUDIO_LOCATION_FRONT_LEFT
438+
*/
439+
ret = bt_audio_codec_cfg_get_chan_allocation(codec_cfg, &chan_allocation);
440+
if (ret == 0) {
441+
if (chan_allocation != BT_AUDIO_LOCATION_FRONT_LEFT) {
442+
FAIL("Unexpected channel allocation: 0x%08X", chan_allocation);
443+
444+
return;
445+
}
446+
447+
chan_cnt = count_bits(chan_allocation);
448+
} else {
449+
FAIL("Could not get subgroup channel allocation: %d\n", ret);
450+
451+
return;
452+
}
453+
454+
if (chan_cnt == 0 || (BIT(chan_cnt - 1) & SUPPORTED_CHAN_COUNTS) == 0) {
455+
FAIL("Unsupported channel count: %u\n", chan_cnt);
456+
457+
return;
458+
}
459+
460+
ret = bt_audio_codec_cfg_get_octets_per_frame(codec_cfg);
461+
if (ret > 0) {
462+
octets_per_frame = (uint16_t)ret;
463+
} else {
464+
FAIL("Could not get subgroup octets per frame: %d\n", ret);
465+
466+
return;
467+
}
468+
469+
if (!IN_RANGE(octets_per_frame, SUPPORTED_MIN_OCTETS_PER_FRAME,
470+
SUPPORTED_MAX_OCTETS_PER_FRAME)) {
471+
FAIL("Unsupported octets per frame: %u\n", octets_per_frame);
472+
473+
return;
474+
}
475+
476+
ret = bt_audio_codec_cfg_get_frame_blocks_per_sdu(codec_cfg, false);
477+
if (ret > 0) {
478+
frames_blocks_per_sdu = (uint8_t)ret;
479+
} else {
480+
printk("Could not get octets per frame: %d\n", ret);
481+
/* Frame blocks per SDU is optional and is implicitly 1 */
482+
frames_blocks_per_sdu = 1U;
483+
}
484+
485+
/* An SDU can consist of X frame blocks, each with Y frames (one per channel) of size Z in
486+
* them. The minimum SDU size required for this is X * Y * Z.
487+
*/
488+
min_sdu_size_required = chan_cnt * octets_per_frame * frames_blocks_per_sdu;
489+
if (min_sdu_size_required > stream->qos->sdu) {
490+
FAIL("With %zu channels and %u octets per frame and %u frames per block, SDUs "
491+
"shall be at minimum %zu, but the stream has been configured for %u\n",
492+
chan_cnt, octets_per_frame, frames_blocks_per_sdu, min_sdu_size_required,
493+
stream->qos->sdu);
494+
495+
return;
496+
}
497+
}
498+
261499
static void started_cb(struct bt_bap_stream *stream)
262500
{
263501
printk("Stream %p started\n", stream);
264502
k_sem_give(&sem_started);
503+
504+
validate_stream_codec_cfg(stream);
265505
}
266506

267507
static void stopped_cb(struct bt_bap_stream *stream, uint8_t reason)

0 commit comments

Comments
 (0)