Skip to content

Commit e08301b

Browse files
Thalleyaescolar
authored andcommitted
Bluetooth: BAP: Fix missing cfg data in stream->codec_cfg for BIS
The codec configuration data from the BIS in the BASE was not properly copied to the stream->codec_cfg, and thus it only contained the subgroup codec configuration values. This commit fixes that by first copying the subgroup codec configuration to the stream, and then setting or overwriting any fields (if they exist). This requires that each stream have their own codec configuration struct allocated, so this will slightly increase memory usage. This also adds verification of the SDU size from the BIGInfo in the ISO receive callback. Signed-off-by: Emil Gydesen <[email protected]>
1 parent a4af2ac commit e08301b

File tree

2 files changed

+145
-34
lines changed

2 files changed

+145
-34
lines changed

subsys/bluetooth/audio/bap_broadcast_sink.c

Lines changed: 139 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ static struct bt_bap_broadcast_sink *broadcast_sink_lookup_iso_chan(
186186
{
187187
for (size_t i = 0U; i < ARRAY_SIZE(broadcast_sinks); i++) {
188188
for (uint8_t j = 0U; j < broadcast_sinks[i].stream_count; j++) {
189-
if (broadcast_sinks[i].bis[j] == chan) {
189+
if (broadcast_sinks[i].bis[j].chan == chan) {
190190
return &broadcast_sinks[i];
191191
}
192192
}
@@ -251,6 +251,7 @@ static void broadcast_sink_iso_recv(struct bt_iso_chan *chan,
251251
const struct bt_bap_stream_ops *ops;
252252
struct bt_bap_stream *stream;
253253
struct bt_bap_ep *ep = iso->rx.ep;
254+
size_t buf_len;
254255

255256
if (ep == NULL) {
256257
LOG_ERR("iso %p not bound with ep", chan);
@@ -265,8 +266,14 @@ static void broadcast_sink_iso_recv(struct bt_iso_chan *chan,
265266

266267
ops = stream->ops;
267268

269+
buf_len = net_buf_frags_len(buf);
268270
if (IS_ENABLED(CONFIG_BT_BAP_DEBUG_STREAM_DATA)) {
269-
LOG_DBG("stream %p ep %p len %zu", stream, stream->ep, net_buf_frags_len(buf));
271+
LOG_DBG("stream %p ep %p len %zu", stream, stream->ep, buf_len);
272+
}
273+
274+
if (buf_len > stream->qos->sdu) {
275+
LOG_WRN("Received %u octets but stream %p was only configured for %u", buf_len,
276+
stream, stream->qos->sdu);
270277
}
271278

272279
if (ops != NULL && ops->recv != NULL) {
@@ -522,79 +529,171 @@ static bool codec_lookup_id(const struct bt_pacs_cap *cap, void *user_data)
522529
return true;
523530
}
524531

532+
struct store_base_info_data {
533+
struct bt_bap_broadcast_sink_bis bis[CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT];
534+
struct bt_bap_broadcast_sink_subgroup subgroups[CONFIG_BT_BAP_BROADCAST_SNK_SUBGROUP_COUNT];
535+
struct bt_audio_codec_cfg *subgroup_codec_cfg;
536+
uint32_t valid_indexes_bitfield;
537+
uint8_t subgroup_count;
538+
uint8_t bis_count;
539+
};
540+
541+
static bool merge_bis_and_subgroup_data_cb(struct bt_data *data, void *user_data)
542+
{
543+
struct bt_audio_codec_cfg *codec_cfg = user_data;
544+
int err;
545+
546+
err = bt_audio_codec_cfg_set_val(codec_cfg, data->type, data->data, data->data_len);
547+
if (err < 0) {
548+
LOG_DBG("Failed to set type %u with len %u in codec_cfg: %d", data->type,
549+
data->data_len, err);
550+
551+
return false;
552+
}
553+
554+
return true;
555+
}
556+
525557
static bool base_subgroup_bis_index_cb(const struct bt_bap_base_subgroup_bis *bis, void *user_data)
526558
{
527-
uint32_t *bis_indexes = user_data;
559+
struct bt_bap_broadcast_sink_subgroup *sink_subgroup;
560+
struct store_base_info_data *data = user_data;
561+
struct bt_bap_broadcast_sink_bis *sink_bis;
562+
563+
if (data->bis_count == ARRAY_SIZE(data->bis)) {
564+
/* We've parsed as many subgroups as we support */
565+
LOG_DBG("Could only store %u BIS", data->bis_count);
566+
return false;
567+
}
568+
569+
sink_bis = &data->bis[data->bis_count];
570+
sink_subgroup = &data->subgroups[data->subgroup_count];
571+
572+
sink_bis->index = bis->index;
573+
sink_subgroup->bis_indexes |= BIT(bis->index);
574+
575+
#if CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0
576+
int err;
577+
578+
memcpy(&sink_bis->codec_cfg, data->subgroup_codec_cfg, sizeof(sink_bis->codec_cfg));
579+
580+
/* Merge subgroup codec configuration with the BIS configuration
581+
* As per the BAP spec, if a value exist at level 2 (subgroup) and 3 (BIS), then it is
582+
* the value at level 3 that shall be used
583+
*/
584+
if (sink_bis->codec_cfg.id == BT_HCI_CODING_FORMAT_LC3) {
585+
memcpy(&sink_bis->codec_cfg, data->subgroup_codec_cfg, sizeof(sink_bis->codec_cfg));
586+
587+
err = bt_audio_data_parse(bis->data, bis->data_len, merge_bis_and_subgroup_data_cb,
588+
&sink_bis->codec_cfg);
589+
if (err != 0) {
590+
LOG_DBG("Could not merge BIS and subgroup config in codec_cfg: %d", err);
591+
592+
return false;
593+
}
594+
} else {
595+
/* If it is not LC3, then we don't know how to merge the subgroup and BIS codecs,
596+
* so we just append them
597+
*/
598+
if (sink_bis->codec_cfg.data_len + bis->data_len >
599+
sizeof(sink_bis->codec_cfg.data)) {
600+
LOG_DBG("Could not store BIS and subgroup config in codec_cfg (%u > %u)",
601+
sink_bis->codec_cfg.data_len + bis->data_len,
602+
sizeof(sink_bis->codec_cfg.data));
528603

529-
*bis_indexes |= BIT(bis->index);
604+
return false;
605+
}
606+
607+
memcpy(&sink_bis->codec_cfg.data[sink_bis->codec_cfg.data_len], bis->data,
608+
bis->data_len);
609+
}
610+
#endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_SIZE > 0 */
611+
612+
data->bis_count++;
530613

531614
return true;
532615
}
533616

534617
static bool base_subgroup_cb(const struct bt_bap_base_subgroup *subgroup, void *user_data)
535618
{
536-
struct bt_bap_broadcast_sink *sink = user_data;
537-
struct bt_bap_broadcast_sink_subgroup *sink_subgroup =
538-
&sink->subgroups[sink->subgroup_count];
619+
struct bt_bap_broadcast_sink_subgroup *sink_subgroup;
539620
struct codec_cap_lookup_id_data lookup_data = {0};
621+
struct store_base_info_data *data = user_data;
622+
struct bt_audio_codec_cfg codec_cfg;
540623
int ret;
541624

542-
if (sink->subgroup_count == ARRAY_SIZE(sink->subgroups)) {
625+
if (data->subgroup_count == ARRAY_SIZE(data->subgroups)) {
543626
/* We've parsed as many subgroups as we support */
544-
LOG_DBG("Could only store %u subgroups", sink->subgroup_count);
627+
LOG_DBG("Could only store %u subgroups", data->subgroup_count);
545628
return false;
546629
}
547630

548-
ret = bt_bap_base_subgroup_codec_to_codec_cfg(subgroup, &sink_subgroup->codec_cfg);
549-
if (ret < 0) {
550-
LOG_DBG("Could not store codec_cfg: %d", ret);
551-
return false;
552-
}
631+
sink_subgroup = &data->subgroups[data->subgroup_count];
553632

554-
ret = bt_bap_base_subgroup_foreach_bis(subgroup, base_subgroup_bis_index_cb,
555-
&sink_subgroup->bis_indexes);
633+
ret = bt_bap_base_subgroup_codec_to_codec_cfg(subgroup, &codec_cfg);
556634
if (ret < 0) {
557-
LOG_DBG("Could not parse BISes: %d", ret);
635+
LOG_DBG("Could not store codec_cfg: %d", ret);
558636
return false;
559637
}
560638

561639
/* Lookup and assign path_id based on capabilities */
562-
lookup_data.id = sink_subgroup->codec_cfg.id;
640+
lookup_data.id = codec_cfg.id;
563641

564642
bt_pacs_cap_foreach(BT_AUDIO_DIR_SINK, codec_lookup_id, &lookup_data);
565643
if (lookup_data.codec_cap == NULL) {
566644
LOG_DBG("Codec with id %u is not supported by our capabilities", lookup_data.id);
567645
} else {
646+
codec_cfg.path_id = lookup_data.codec_cap->path_id;
647+
codec_cfg.ctlr_transcode = lookup_data.codec_cap->ctlr_transcode;
648+
649+
data->subgroup_codec_cfg = &codec_cfg;
650+
651+
ret = bt_bap_base_subgroup_foreach_bis(subgroup, base_subgroup_bis_index_cb, data);
652+
if (ret < 0) {
653+
LOG_DBG("Could not parse BISes: %d", ret);
654+
return false;
655+
}
656+
568657
/* Add BIS to bitfield of valid BIS indexes we support */
569-
sink->valid_indexes_bitfield |= sink_subgroup->bis_indexes;
658+
data->valid_indexes_bitfield |= sink_subgroup->bis_indexes;
659+
data->subgroup_count++;
570660
}
571661

572-
sink->subgroup_count++;
573-
574662
return true;
575663
}
576664

577665
static int store_base_info(struct bt_bap_broadcast_sink *sink, const struct bt_bap_base *base)
578666
{
667+
/* data is static due to its size, which easily can exceed the stack size */
668+
static struct store_base_info_data data;
669+
uint32_t pres_delay;
579670
int ret;
580671

581-
sink->valid_indexes_bitfield = 0U;
582-
sink->subgroup_count = 0U;
583-
584672
ret = bt_bap_base_get_pres_delay(base);
585673
if (ret < 0) {
586674
LOG_DBG("Could not get presentation delay: %d", ret);
587675
return ret;
588676
}
589677

590-
sink->codec_qos.pd = (uint32_t)ret;
678+
pres_delay = (uint32_t)ret;
591679

592-
ret = bt_bap_base_foreach_subgroup(base, base_subgroup_cb, sink);
680+
memset(&data, 0, sizeof(data));
681+
682+
ret = bt_bap_base_foreach_subgroup(base, base_subgroup_cb, &data);
593683
if (ret != 0) {
594684
LOG_DBG("Failed to parse all subgroups: %d", ret);
595685
return ret;
596686
}
597687

688+
/* Ensure that we have not synced while parsing the BASE */
689+
if (sink->big == NULL) {
690+
sink->codec_qos.pd = pres_delay;
691+
memcpy(sink->bis, data.bis, sizeof(sink->bis));
692+
memcpy(sink->subgroups, data.subgroups, sizeof(sink->subgroups));
693+
sink->subgroup_count = data.subgroup_count;
694+
sink->valid_indexes_bitfield = data.valid_indexes_bitfield;
695+
}
696+
598697
return 0;
599698
}
600699

@@ -940,14 +1039,18 @@ static void broadcast_sink_cleanup(struct bt_bap_broadcast_sink *sink)
9401039

9411040
(void)memset(sink, 0, sizeof(*sink)); /* also clears flags */
9421041
}
1042+
9431043
static struct bt_audio_codec_cfg *codec_cfg_from_base_by_index(struct bt_bap_broadcast_sink *sink,
9441044
uint8_t index)
9451045
{
946-
for (size_t i = 0U; i < sink->subgroup_count; i++) {
947-
struct bt_bap_broadcast_sink_subgroup *subgroup = &sink->subgroups[i];
1046+
for (size_t i = 0U; i < ARRAY_SIZE(sink->bis); i++) {
1047+
struct bt_bap_broadcast_sink_bis *bis = &sink->bis[i];
9481048

949-
if ((subgroup->bis_indexes & BIT(index)) != 0) {
950-
return &subgroup->codec_cfg;
1049+
if (bis->index == index) {
1050+
return &bis->codec_cfg;
1051+
} else if (bis->index == 0) {
1052+
/* index 0 is invalid, so we can use that as a terminator in the array */
1053+
break;
9511054
}
9521055
}
9531056

@@ -1015,7 +1118,8 @@ int bt_bap_broadcast_sink_sync(struct bt_bap_broadcast_sink *sink, uint32_t inde
10151118
struct bt_bap_stream *streams[], const uint8_t broadcast_code[16])
10161119
{
10171120
struct bt_iso_big_sync_param param;
1018-
struct bt_audio_codec_cfg *codec_cfgs[CONFIG_BT_BAP_BROADCAST_SNK_SUBGROUP_COUNT] = {NULL};
1121+
struct bt_audio_codec_cfg *codec_cfgs[CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT] = {NULL};
1122+
struct bt_iso_chan *bis_channels[CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT];
10191123
uint8_t stream_count;
10201124
int err;
10211125

@@ -1110,12 +1214,14 @@ int bt_bap_broadcast_sink_sync(struct bt_bap_broadcast_sink *sink, uint32_t inde
11101214
return err;
11111215
}
11121216

1113-
sink->bis[i] = bt_bap_stream_iso_chan_get(stream);
1217+
sink->bis[i].chan = bt_bap_stream_iso_chan_get(stream);
11141218
sys_slist_append(&sink->streams, &stream->_node);
11151219
sink->stream_count++;
1220+
1221+
bis_channels[i] = sink->bis[i].chan;
11161222
}
11171223

1118-
param.bis_channels = sink->bis;
1224+
param.bis_channels = bis_channels;
11191225
param.num_bis = sink->stream_count;
11201226
param.bis_bitfield = indexes_bitfield;
11211227
param.mse = 0; /* Let controller decide */

subsys/bluetooth/audio/bap_endpoint.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ enum bt_bap_broadcast_sink_flag {
126126

127127
struct bt_bap_broadcast_sink_subgroup {
128128
uint32_t bis_indexes;
129+
};
130+
131+
struct bt_bap_broadcast_sink_bis {
132+
uint8_t index;
133+
struct bt_iso_chan *chan;
129134
struct bt_audio_codec_cfg codec_cfg;
130135
};
131136

@@ -143,7 +148,7 @@ struct bt_bap_broadcast_sink {
143148
struct bt_audio_codec_qos codec_qos;
144149
struct bt_le_per_adv_sync *pa_sync;
145150
struct bt_iso_big *big;
146-
struct bt_iso_chan *bis[CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT];
151+
struct bt_bap_broadcast_sink_bis bis[CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT];
147152
struct bt_bap_broadcast_sink_subgroup subgroups[CONFIG_BT_BAP_BROADCAST_SNK_SUBGROUP_COUNT];
148153
const struct bt_bap_scan_delegator_recv_state *recv_state;
149154
/* The streams used to create the broadcast sink */

0 commit comments

Comments
 (0)