--- profiles/audio/bap.c | 85 ++++++++++++++++++++++++++++++++++++++++++ profiles/audio/media.c | 3 +- src/shared/bap.c | 9 ++++- 3 files changed, 95 insertions(+), 2 deletions(-) diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c index 1b8a47c52..c07506c45 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; @@ -881,6 +886,62 @@ 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(setup->base, 1); + setup->base = NULL; + + if (setup->qos.bcast.bis == bis_cnt) { + util_iov_free(ent_setup->caps, 1); + ent_setup->caps = util_iov_dup(setup->caps, 1); + util_iov_free(ent_setup->metadata, 1); + ent_setup->metadata = util_iov_dup(setup->metadata, 1); + memcpy(&ent_setup->qos, &setup->qos, + sizeof(struct bt_bap_bcast_qos)); + ent_setup->qos.bcast.bcode = util_iov_dup( + setup->qos.bcast.bcode, 1); + + 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) { @@ -922,6 +983,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 updated 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/media.c b/profiles/audio/media.c index edaff7867..084c09fc7 100644 --- a/profiles/audio/media.c +++ b/profiles/audio/media.c @@ -1154,7 +1154,8 @@ static int pac_config(struct bt_bap_stream *stream, struct iovec *cfg, endpoint->transports = g_slist_append(endpoint->transports, transport); - } + } else if (bt_bap_stream_get_dir(stream) == BT_BAP_BCAST_SINK) + bap_update_bcast_config(transport); msg = dbus_message_new_method_call(endpoint->sender, endpoint->path, MEDIA_ENDPOINT_INTERFACE, diff --git a/src/shared/bap.c b/src/shared/bap.c index 37fc1de4e..07f5671e4 100644 --- a/src/shared/bap.c +++ b/src/shared/bap.c @@ -1701,7 +1701,14 @@ 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; + + 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