diff mbox series

[BlueZ,v4,3/5] bap: Broadcast source reconfiguration support added

Message ID 20240318163853.68598-4-silviu.barbulescu@nxp.com (mailing list archive)
State New, archived
Headers show
Series Broadcast source reconfiguration support | expand

Checks

Context Check Description
tedd_an/pre-ci_am success Success
tedd_an/CheckPatch success CheckPatch PASS
tedd_an/GitLint success Gitlint PASS

Commit Message

Silviu Florian Barbulescu March 18, 2024, 4:38 p.m. UTC
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(-)

Comments

Luiz Augusto von Dentz March 18, 2024, 5:38 p.m. UTC | #1
Hi Silviu,

On Mon, Mar 18, 2024 at 4:39 PM Silviu Florian Barbulescu
<silviu.barbulescu@nxp.com> wrote:
>
> 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;

I do wonder why we need to store the base as part of the setup? Can't
we just generate it later when it is actually about to be configured
into the socket like I did?

> +               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");
> +                       }

I was thinking we could delay the BASE setup until later when the code
actually needs it then the code for stream_get_base can actually
detect what are the streams with the same BIG and generate the BASE
just once.

> +                       /* 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

These changes to shared/bap shall be submitted in a separate patch
with a proper description.
diff mbox series

Patch

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);