If a BIS is reconfigured, the metadata and codec capabilities are updated. Also, the BASE is updated to reflect the update. --- profiles/audio/bap.c | 76 ++++++++++++++++++++++++++++++++++++++ profiles/audio/transport.c | 6 ++- src/shared/bap.c | 11 +++++- 3 files changed, 91 insertions(+), 2 deletions(-) diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c index 964ba9c21..e508e03ba 100644 --- a/profiles/audio/bap.c +++ b/profiles/audio/bap.c @@ -580,6 +580,11 @@ static int setup_parse_bcast_qos(struct bap_setup *setup, const char *key, return -EINVAL; dbus_message_iter_get_basic(iter, &qos->bcast.big); + } else if (!strcasecmp(key, "BIS")) { + if (var != DBUS_TYPE_BYTE) + return -EINVAL; + + dbus_message_iter_get_basic(iter, &qos->bcast.bis); } else if (!strcasecmp(key, "Options")) { if (var != DBUS_TYPE_BYTE) return -EINVAL; @@ -884,6 +889,53 @@ static void setup_free(void *data) free(setup); } +static void iterate_setups(struct bap_setup *setup) +{ + const struct queue_entry *entry; + struct bap_setup *ent_setup; + uint8_t bis_cnt = 1; + + for (entry = queue_get_entries(setup->ep->setups); + entry; entry = entry->next) { + ent_setup = entry->data; + + if (setup->qos.bcast.big != ent_setup->qos.bcast.big) + continue; + + util_iov_free(ent_setup->base, 1); + ent_setup->base = NULL; + + if (setup->qos.bcast.bis == bis_cnt) { + bt_bap_stream_config(ent_setup->stream, &setup->qos, + setup->caps, NULL, NULL); + bt_bap_stream_metadata(ent_setup->stream, + setup->metadata, NULL, NULL); + } + + bis_cnt++; + } +} + +static bool verify_state(struct bap_setup *setup) +{ + const struct queue_entry *entry; + struct bap_setup *ent_setup; + + for (entry = queue_get_entries(setup->ep->setups); + entry; entry = entry->next) { + ent_setup = entry->data; + + if (setup->qos.bcast.big != ent_setup->qos.bcast.big) + continue; + + if (bt_bap_stream_get_state(ent_setup->stream) == + BT_BAP_STREAM_STATE_STREAMING) + return false; + } + + return true; +} + static DBusMessage *set_configuration(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -925,6 +977,30 @@ static DBusMessage *set_configuration(DBusConnection *conn, DBusMessage *msg, util_iov_free(setup->metadata, 1); setup->metadata = util_iov_dup( bt_bap_pac_get_metadata(ep->rpac), 1); + } else if (bt_bap_pac_get_type(ep->lpac) == BT_BAP_BCAST_SOURCE) { + if (setup->qos.bcast.bis != BT_ISO_QOS_BIS_UNSET) { + if ((setup->qos.bcast.bis > queue_length(ep->setups)) || + (setup->qos.bcast.bis == 0)) { + setup_free(setup); + return btd_error_invalid_args(msg); + } + + /* Verify that no BIS in the BIG is in streaming state + */ + if (!verify_state(setup)) { + setup_free(setup); + return btd_error_not_permitted(msg, + "Broadcast Audio Stream state is invalid"); + } + + /* Find and update the BIS specified in + * set_configuration command + */ + iterate_setups(setup); + + setup_free(setup); + return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); + } } setup->stream = bt_bap_stream_new(ep->data->bap, ep->lpac, ep->rpac, diff --git a/profiles/audio/transport.c b/profiles/audio/transport.c index 122c3339e..a060f8c61 100644 --- a/profiles/audio/transport.c +++ b/profiles/audio/transport.c @@ -1643,8 +1643,12 @@ static void bap_state_changed(struct bt_bap_stream *stream, uint8_t old_state, bap_update_links(transport); if (!media_endpoint_is_broadcast(transport->endpoint)) bap_update_qos(transport); - else if (bt_bap_stream_io_dir(stream) != BT_BAP_BCAST_SOURCE) + else if (bt_bap_stream_io_dir(stream) != BT_BAP_BCAST_SOURCE) { bap_update_bcast_qos(transport); + if (old_state == BT_BAP_STREAM_STATE_QOS) + bap_update_bcast_config(transport); + } + transport_update_playing(transport, FALSE); return; case BT_BAP_STREAM_STATE_DISABLING: diff --git a/src/shared/bap.c b/src/shared/bap.c index fd99cbbca..603d6d646 100644 --- a/src/shared/bap.c +++ b/src/shared/bap.c @@ -1701,7 +1701,16 @@ static unsigned int bap_bcast_config(struct bt_bap_stream *stream, struct bt_bap_qos *qos, struct iovec *data, bt_bap_stream_func_t func, void *user_data) { - stream->qos = *qos; + if (qos) { + stream->qos = *qos; + stream->qos.bcast.bcode = util_iov_dup(qos->bcast.bcode, 1); + } + + if (data) { + util_iov_free(stream->cc, 1); + stream->cc = util_iov_dup(data, 1); + } + stream->lpac->ops->config(stream, stream->cc, &stream->qos, ep_config_cb, stream->lpac->user_data); -- 2.39.2