diff mbox series

[BlueZ,v5,7/7] transport: Update transport properties for a broadcast stream

Message ID 20230808115040.4403-8-claudia.rosu@nxp.com
State Superseded
Headers show
Series Add support for BAP broadcast sink | expand

Commit Message

Claudia Draghicescu Aug. 8, 2023, 11:50 a.m. UTC
This patch gets the QOS broadcast stream parameters and passes them
to upper layers.
---
 profiles/audio/transport.c | 245 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 243 insertions(+), 2 deletions(-)

Comments

Luiz Augusto von Dentz Aug. 9, 2023, 6:06 p.m. UTC | #1
Hi Claudia,

On Tue, Aug 8, 2023 at 10:35 AM Claudia Draghicescu
<claudia.rosu@nxp.com> wrote:
>
> This patch gets the QOS broadcast stream parameters and passes them
> to upper layers.
> ---
>  profiles/audio/transport.c | 245 ++++++++++++++++++++++++++++++++++++-
>  1 file changed, 243 insertions(+), 2 deletions(-)
>
> diff --git a/profiles/audio/transport.c b/profiles/audio/transport.c
> index cf5662d1d..107339520 100644
> --- a/profiles/audio/transport.c
> +++ b/profiles/audio/transport.c
> @@ -552,6 +552,8 @@ static DBusMessage *acquire(DBusConnection *conn, DBusMessage *msg,
>         owner = media_owner_create(msg);
>
>         if (!strcmp(media_endpoint_get_uuid(transport->endpoint),
> +                                               BAA_SERVICE_UUID)
> +               || !strcmp(media_endpoint_get_uuid(transport->endpoint),
>                                                 BCAA_SERVICE_UUID)) {

This code above is probably what media_endpoint_is_broadcast should be
doing, so it matches by uuid.

>                 req = media_request_create(msg, 0x00);
>                 media_owner_add(owner, req);
> @@ -853,6 +855,9 @@ static gboolean qos_exists(const GDBusPropertyTable *property, void *data)
>         struct media_transport *transport = data;
>         struct bap_transport *bap = transport->data;
>
> +       if (media_endpoint_is_broadcast(transport->endpoint))
> +               return bap->qos.bcast.io_qos.sdu != 0x00;
> +
>         return bap->qos.ucast.io_qos.phy != 0x00;
>  }
>
> @@ -868,6 +873,18 @@ static gboolean get_cig(const GDBusPropertyTable *property,
>         return TRUE;
>  }
>
> +static gboolean get_big(const GDBusPropertyTable *property,
> +                                       DBusMessageIter *iter, void *data)
> +{
> +       struct media_transport *transport = data;
> +       struct bap_transport *bap = transport->data;
> +
> +       dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE,
> +                                                       &bap->qos.bcast.big);
> +
> +       return TRUE;
> +}
> +
>  static gboolean get_cis(const GDBusPropertyTable *property,
>                                         DBusMessageIter *iter, void *data)
>  {
> @@ -880,6 +897,18 @@ static gboolean get_cis(const GDBusPropertyTable *property,
>         return TRUE;
>  }
>
> +static gboolean get_bis(const GDBusPropertyTable *property,
> +                                       DBusMessageIter *iter, void *data)
> +{
> +       struct media_transport *transport = data;
> +       struct bap_transport *bap = transport->data;
> +
> +       dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE,
> +                                                       &bap->qos.bcast.bis);
> +
> +       return TRUE;
> +}
> +
>  static gboolean get_interval(const GDBusPropertyTable *property,
>                                         DBusMessageIter *iter, void *data)
>  {
> @@ -899,6 +928,9 @@ static gboolean get_framing(const GDBusPropertyTable *property,
>         struct bap_transport *bap = transport->data;
>         dbus_bool_t val = bap->qos.ucast.framing;
>
> +       if (media_endpoint_is_broadcast(transport->endpoint))
> +               val = bap->qos.bcast.framing;
> +
>         dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &val);
>
>         return TRUE;
> @@ -910,6 +942,12 @@ static gboolean get_phy(const GDBusPropertyTable *property,
>         struct media_transport *transport = data;
>         struct bap_transport *bap = transport->data;
>
> +       if (media_endpoint_is_broadcast(transport->endpoint)) {
> +               dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE,
> +                                       &bap->qos.bcast.io_qos.phy);
> +               return TRUE;
> +       }
> +
>         dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE,
>                                         &bap->qos.ucast.io_qos.phy);
>
> @@ -922,6 +960,12 @@ static gboolean get_sdu(const GDBusPropertyTable *property,
>         struct media_transport *transport = data;
>         struct bap_transport *bap = transport->data;
>
> +       if (media_endpoint_is_broadcast(transport->endpoint)) {
> +               dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
> +                                       &bap->qos.bcast.io_qos.sdu);
> +               return TRUE;
> +       }
> +
>         dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
>                                         &bap->qos.ucast.io_qos.sdu);
>
> @@ -1040,6 +1084,121 @@ static gboolean get_links(const GDBusPropertyTable *property,
>         return TRUE;
>  }
>
> +static gboolean get_sync_interval(const GDBusPropertyTable *property,
> +                                       DBusMessageIter *iter, void *data)
> +{
> +       struct media_transport *transport = data;
> +       struct bap_transport *bap = transport->data;
> +
> +       dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE,
> +                                               &bap->qos.bcast.sync_interval);
> +
> +       return TRUE;
> +}
> +
> +static gboolean get_packing(const GDBusPropertyTable *property,
> +                                       DBusMessageIter *iter, void *data)
> +{
> +       struct media_transport *transport = data;
> +       struct bap_transport *bap = transport->data;
> +
> +       dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE,
> +                                               &bap->qos.bcast.packing);
> +
> +       return TRUE;
> +}
> +
> +static gboolean get_bcode(const GDBusPropertyTable *property,
> +                                       DBusMessageIter *iter, void *data)
> +{
> +       struct media_transport *transport = data;
> +       struct bap_transport *bap = transport->data;
> +       DBusMessageIter array;
> +
> +       dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
> +                                       DBUS_TYPE_BYTE_AS_STRING, &array);
> +
> +       if (bap->qos.bcast.bcode && bap->qos.bcast.bcode->iov_len)
> +               dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
> +                                               &bap->qos.bcast.bcode->iov_base,
> +                                               bap->qos.bcast.bcode->iov_len);
> +
> +       dbus_message_iter_close_container(iter, &array);
> +       return TRUE;
> +}
> +
> +static gboolean get_options(const GDBusPropertyTable *property,
> +                                       DBusMessageIter *iter, void *data)
> +{
> +       struct media_transport *transport = data;
> +       struct bap_transport *bap = transport->data;
> +
> +       dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE,
> +                                       &bap->qos.bcast.options);
> +
> +       return TRUE;
> +}
> +
> +static gboolean get_skip(const GDBusPropertyTable *property,
> +                                       DBusMessageIter *iter, void *data)
> +{
> +       struct media_transport *transport = data;
> +       struct bap_transport *bap = transport->data;
> +
> +       dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
> +                                       &bap->qos.bcast.skip);
> +
> +       return TRUE;
> +}
> +
> +static gboolean get_sync_timeout(const GDBusPropertyTable *property,
> +                                       DBusMessageIter *iter, void *data)
> +{
> +       struct media_transport *transport = data;
> +       struct bap_transport *bap = transport->data;
> +
> +       dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
> +                                       &bap->qos.bcast.sync_timeout);
> +
> +       return TRUE;
> +}
> +
> +static gboolean get_sync_cte_type(const GDBusPropertyTable *property,
> +                                       DBusMessageIter *iter, void *data)
> +{
> +       struct media_transport *transport = data;
> +       struct bap_transport *bap = transport->data;
> +
> +       dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE,
> +                                       &bap->qos.bcast.sync_cte_type);
> +
> +       return TRUE;
> +}
> +
> +static gboolean get_mse(const GDBusPropertyTable *property,
> +                                       DBusMessageIter *iter, void *data)
> +{
> +       struct media_transport *transport = data;
> +       struct bap_transport *bap = transport->data;
> +
> +       dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE,
> +                                       &bap->qos.bcast.mse);
> +
> +       return TRUE;
> +}
> +
> +static gboolean get_timeout(const GDBusPropertyTable *property,
> +                                       DBusMessageIter *iter, void *data)
> +{
> +       struct media_transport *transport = data;
> +       struct bap_transport *bap = transport->data;
> +
> +       dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
> +                                       &bap->qos.bcast.timeout);
> +
> +       return TRUE;
> +}
> +
>  static const GDBusPropertyTable bap_properties[] = {
>         { "Device", "o", get_device },
>         { "UUID", "s", get_uuid },
> @@ -1059,6 +1218,17 @@ static const GDBusPropertyTable bap_properties[] = {
>         { "Location", "u", get_location },
>         { "Metadata", "ay", get_metadata },
>         { "Links", "ao", get_links, NULL, links_exists },
> +       { "BIG", "y", get_big, NULL, qos_exists },
> +       { "BIS", "y", get_bis, NULL, qos_exists },
> +       { "SyncInterval", "y", get_sync_interval, NULL, qos_exists },
> +       { "Packing", "y", get_packing, NULL, qos_exists },
> +       { "BCode", "ay", get_bcode, NULL, qos_exists },
> +       { "Options", "y", get_options, NULL, qos_exists },
> +       { "Skip", "q", get_skip, NULL, qos_exists },
> +       { "SyncTimeout", "q", get_sync_timeout, NULL, qos_exists },
> +       { "SyncCteType", "y", get_sync_cte_type, NULL, qos_exists },
> +       { "MSE", "y", get_mse, NULL, qos_exists },
> +       { "Timeout", "q", get_timeout, NULL, qos_exists },
>         { }
>  };
>
> @@ -1341,6 +1511,71 @@ static gboolean bap_resume_wait_cb(void *data)
>         return FALSE;
>  }
>
> +static void bap_update_bcast_qos(const struct media_transport *transport)
> +{
> +       struct bap_transport *bap = transport->data;
> +       struct bt_bap_qos *qos;
> +
> +       qos = bt_bap_stream_get_qos(bap->stream);
> +
> +       if (!memcmp(qos, &bap->qos, sizeof(struct bt_bap_qos)))
> +               return;
> +
> +       bap->qos = *qos;
> +
> +       g_dbus_emit_property_changed(btd_get_dbus_connection(),
> +                       transport->path, MEDIA_TRANSPORT_INTERFACE,
> +                       "BIG");
> +       g_dbus_emit_property_changed(btd_get_dbus_connection(),
> +                       transport->path, MEDIA_TRANSPORT_INTERFACE,
> +                       "BIS");
> +       g_dbus_emit_property_changed(btd_get_dbus_connection(),
> +                       transport->path, MEDIA_TRANSPORT_INTERFACE,
> +                       "SyncInterval");
> +       g_dbus_emit_property_changed(btd_get_dbus_connection(),
> +                       transport->path, MEDIA_TRANSPORT_INTERFACE,
> +                       "Packing");
> +       g_dbus_emit_property_changed(btd_get_dbus_connection(),
> +                       transport->path, MEDIA_TRANSPORT_INTERFACE,
> +                       "Framing");
> +       g_dbus_emit_property_changed(btd_get_dbus_connection(),
> +                       transport->path, MEDIA_TRANSPORT_INTERFACE,
> +                       "BCode");
> +       g_dbus_emit_property_changed(btd_get_dbus_connection(),
> +                       transport->path, MEDIA_TRANSPORT_INTERFACE,
> +                       "Options");
> +       g_dbus_emit_property_changed(btd_get_dbus_connection(),
> +                       transport->path, MEDIA_TRANSPORT_INTERFACE,
> +                       "Skip");
> +       g_dbus_emit_property_changed(btd_get_dbus_connection(),
> +                       transport->path, MEDIA_TRANSPORT_INTERFACE,
> +                       "SyncTimeout");
> +       g_dbus_emit_property_changed(btd_get_dbus_connection(),
> +                       transport->path, MEDIA_TRANSPORT_INTERFACE,
> +                       "SyncCteType");
> +       g_dbus_emit_property_changed(btd_get_dbus_connection(),
> +                       transport->path, MEDIA_TRANSPORT_INTERFACE,
> +                       "MSE");
> +       g_dbus_emit_property_changed(btd_get_dbus_connection(),
> +                       transport->path, MEDIA_TRANSPORT_INTERFACE,
> +                       "Timeout");
> +       g_dbus_emit_property_changed(btd_get_dbus_connection(),
> +                       transport->path, MEDIA_TRANSPORT_INTERFACE,
> +                       "Interval");
> +       g_dbus_emit_property_changed(btd_get_dbus_connection(),
> +                       transport->path, MEDIA_TRANSPORT_INTERFACE,
> +                       "Latency");
> +       g_dbus_emit_property_changed(btd_get_dbus_connection(),
> +                       transport->path, MEDIA_TRANSPORT_INTERFACE,
> +                       "PHY");
> +       g_dbus_emit_property_changed(btd_get_dbus_connection(),
> +                       transport->path, MEDIA_TRANSPORT_INTERFACE,
> +                       "SDU");
> +       g_dbus_emit_property_changed(btd_get_dbus_connection(),
> +                       transport->path, MEDIA_TRANSPORT_INTERFACE,
> +                       "RTN");
> +}
> +
>  static guint resume_bap(struct media_transport *transport,
>                                 struct media_owner *owner)
>  {
> @@ -1493,7 +1728,10 @@ static void bap_state_changed(struct bt_bap_stream *stream, uint8_t old_state,
>                 if (owner && owner->pending)
>                         return;
>                 bap_update_links(transport);
> -               bap_update_qos(transport);
> +               if (!media_endpoint_is_broadcast(transport->endpoint))
> +                       bap_update_qos(transport);
> +               else if (bt_bap_stream_io_dir(stream) != BT_BAP_BCAST_SOURCE)
> +                       bap_update_bcast_qos(transport);
>                 transport_update_playing(transport, FALSE);
>                 return;
>         case BT_BAP_STREAM_STATE_DISABLING:
> @@ -1503,6 +1741,8 @@ static void bap_state_changed(struct bt_bap_stream *stream, uint8_t old_state,
>                         return;
>                 break;
>         case BT_BAP_STREAM_STATE_STREAMING:
> +               if (bt_bap_stream_io_dir(stream) == BT_BAP_BCAST_SOURCE)
> +                       bap_update_bcast_qos(transport);
>                 break;
>         }
>
> @@ -1631,7 +1871,8 @@ struct media_transport *media_transport_create(struct btd_device *device,
>                 properties = a2dp_properties;
>         } else if (!strcasecmp(uuid, PAC_SINK_UUID) ||
>                                 !strcasecmp(uuid, PAC_SOURCE_UUID) ||
> -                               !strcasecmp(uuid, BCAA_SERVICE_UUID)) {
> +                               !strcasecmp(uuid, BCAA_SERVICE_UUID) ||
> +                               !strcasecmp(uuid, BAA_SERVICE_UUID)) {
>                 if (media_transport_init_bap(transport, stream) < 0)
>                         goto fail;
>                 properties = bap_properties;
> --
> 2.34.1
>
diff mbox series

Patch

diff --git a/profiles/audio/transport.c b/profiles/audio/transport.c
index cf5662d1d..107339520 100644
--- a/profiles/audio/transport.c
+++ b/profiles/audio/transport.c
@@ -552,6 +552,8 @@  static DBusMessage *acquire(DBusConnection *conn, DBusMessage *msg,
 	owner = media_owner_create(msg);
 
 	if (!strcmp(media_endpoint_get_uuid(transport->endpoint),
+						BAA_SERVICE_UUID)
+		|| !strcmp(media_endpoint_get_uuid(transport->endpoint),
 						BCAA_SERVICE_UUID)) {
 		req = media_request_create(msg, 0x00);
 		media_owner_add(owner, req);
@@ -853,6 +855,9 @@  static gboolean qos_exists(const GDBusPropertyTable *property, void *data)
 	struct media_transport *transport = data;
 	struct bap_transport *bap = transport->data;
 
+	if (media_endpoint_is_broadcast(transport->endpoint))
+		return bap->qos.bcast.io_qos.sdu != 0x00;
+
 	return bap->qos.ucast.io_qos.phy != 0x00;
 }
 
@@ -868,6 +873,18 @@  static gboolean get_cig(const GDBusPropertyTable *property,
 	return TRUE;
 }
 
+static gboolean get_big(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct media_transport *transport = data;
+	struct bap_transport *bap = transport->data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE,
+							&bap->qos.bcast.big);
+
+	return TRUE;
+}
+
 static gboolean get_cis(const GDBusPropertyTable *property,
 					DBusMessageIter *iter, void *data)
 {
@@ -880,6 +897,18 @@  static gboolean get_cis(const GDBusPropertyTable *property,
 	return TRUE;
 }
 
+static gboolean get_bis(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct media_transport *transport = data;
+	struct bap_transport *bap = transport->data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE,
+							&bap->qos.bcast.bis);
+
+	return TRUE;
+}
+
 static gboolean get_interval(const GDBusPropertyTable *property,
 					DBusMessageIter *iter, void *data)
 {
@@ -899,6 +928,9 @@  static gboolean get_framing(const GDBusPropertyTable *property,
 	struct bap_transport *bap = transport->data;
 	dbus_bool_t val = bap->qos.ucast.framing;
 
+	if (media_endpoint_is_broadcast(transport->endpoint))
+		val = bap->qos.bcast.framing;
+
 	dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &val);
 
 	return TRUE;
@@ -910,6 +942,12 @@  static gboolean get_phy(const GDBusPropertyTable *property,
 	struct media_transport *transport = data;
 	struct bap_transport *bap = transport->data;
 
+	if (media_endpoint_is_broadcast(transport->endpoint)) {
+		dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE,
+					&bap->qos.bcast.io_qos.phy);
+		return TRUE;
+	}
+
 	dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE,
 					&bap->qos.ucast.io_qos.phy);
 
@@ -922,6 +960,12 @@  static gboolean get_sdu(const GDBusPropertyTable *property,
 	struct media_transport *transport = data;
 	struct bap_transport *bap = transport->data;
 
+	if (media_endpoint_is_broadcast(transport->endpoint)) {
+		dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
+					&bap->qos.bcast.io_qos.sdu);
+		return TRUE;
+	}
+
 	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
 					&bap->qos.ucast.io_qos.sdu);
 
@@ -1040,6 +1084,121 @@  static gboolean get_links(const GDBusPropertyTable *property,
 	return TRUE;
 }
 
+static gboolean get_sync_interval(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct media_transport *transport = data;
+	struct bap_transport *bap = transport->data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE,
+						&bap->qos.bcast.sync_interval);
+
+	return TRUE;
+}
+
+static gboolean get_packing(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct media_transport *transport = data;
+	struct bap_transport *bap = transport->data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE,
+						&bap->qos.bcast.packing);
+
+	return TRUE;
+}
+
+static gboolean get_bcode(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct media_transport *transport = data;
+	struct bap_transport *bap = transport->data;
+	DBusMessageIter array;
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
+					DBUS_TYPE_BYTE_AS_STRING, &array);
+
+	if (bap->qos.bcast.bcode && bap->qos.bcast.bcode->iov_len)
+		dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
+						&bap->qos.bcast.bcode->iov_base,
+						bap->qos.bcast.bcode->iov_len);
+
+	dbus_message_iter_close_container(iter, &array);
+	return TRUE;
+}
+
+static gboolean get_options(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct media_transport *transport = data;
+	struct bap_transport *bap = transport->data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE,
+					&bap->qos.bcast.options);
+
+	return TRUE;
+}
+
+static gboolean get_skip(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct media_transport *transport = data;
+	struct bap_transport *bap = transport->data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
+					&bap->qos.bcast.skip);
+
+	return TRUE;
+}
+
+static gboolean get_sync_timeout(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct media_transport *transport = data;
+	struct bap_transport *bap = transport->data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
+					&bap->qos.bcast.sync_timeout);
+
+	return TRUE;
+}
+
+static gboolean get_sync_cte_type(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct media_transport *transport = data;
+	struct bap_transport *bap = transport->data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE,
+					&bap->qos.bcast.sync_cte_type);
+
+	return TRUE;
+}
+
+static gboolean get_mse(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct media_transport *transport = data;
+	struct bap_transport *bap = transport->data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE,
+					&bap->qos.bcast.mse);
+
+	return TRUE;
+}
+
+static gboolean get_timeout(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct media_transport *transport = data;
+	struct bap_transport *bap = transport->data;
+
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
+					&bap->qos.bcast.timeout);
+
+	return TRUE;
+}
+
 static const GDBusPropertyTable bap_properties[] = {
 	{ "Device", "o", get_device },
 	{ "UUID", "s", get_uuid },
@@ -1059,6 +1218,17 @@  static const GDBusPropertyTable bap_properties[] = {
 	{ "Location", "u", get_location },
 	{ "Metadata", "ay", get_metadata },
 	{ "Links", "ao", get_links, NULL, links_exists },
+	{ "BIG", "y", get_big, NULL, qos_exists },
+	{ "BIS", "y", get_bis, NULL, qos_exists },
+	{ "SyncInterval", "y", get_sync_interval, NULL, qos_exists },
+	{ "Packing", "y", get_packing, NULL, qos_exists },
+	{ "BCode", "ay", get_bcode, NULL, qos_exists },
+	{ "Options", "y", get_options, NULL, qos_exists },
+	{ "Skip", "q", get_skip, NULL, qos_exists },
+	{ "SyncTimeout", "q", get_sync_timeout, NULL, qos_exists },
+	{ "SyncCteType", "y", get_sync_cte_type, NULL, qos_exists },
+	{ "MSE", "y", get_mse, NULL, qos_exists },
+	{ "Timeout", "q", get_timeout, NULL, qos_exists },
 	{ }
 };
 
@@ -1341,6 +1511,71 @@  static gboolean bap_resume_wait_cb(void *data)
 	return FALSE;
 }
 
+static void bap_update_bcast_qos(const struct media_transport *transport)
+{
+	struct bap_transport *bap = transport->data;
+	struct bt_bap_qos *qos;
+
+	qos = bt_bap_stream_get_qos(bap->stream);
+
+	if (!memcmp(qos, &bap->qos, sizeof(struct bt_bap_qos)))
+		return;
+
+	bap->qos = *qos;
+
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+			transport->path, MEDIA_TRANSPORT_INTERFACE,
+			"BIG");
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+			transport->path, MEDIA_TRANSPORT_INTERFACE,
+			"BIS");
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+			transport->path, MEDIA_TRANSPORT_INTERFACE,
+			"SyncInterval");
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+			transport->path, MEDIA_TRANSPORT_INTERFACE,
+			"Packing");
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+			transport->path, MEDIA_TRANSPORT_INTERFACE,
+			"Framing");
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+			transport->path, MEDIA_TRANSPORT_INTERFACE,
+			"BCode");
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+			transport->path, MEDIA_TRANSPORT_INTERFACE,
+			"Options");
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+			transport->path, MEDIA_TRANSPORT_INTERFACE,
+			"Skip");
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+			transport->path, MEDIA_TRANSPORT_INTERFACE,
+			"SyncTimeout");
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+			transport->path, MEDIA_TRANSPORT_INTERFACE,
+			"SyncCteType");
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+			transport->path, MEDIA_TRANSPORT_INTERFACE,
+			"MSE");
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+			transport->path, MEDIA_TRANSPORT_INTERFACE,
+			"Timeout");
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+			transport->path, MEDIA_TRANSPORT_INTERFACE,
+			"Interval");
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+			transport->path, MEDIA_TRANSPORT_INTERFACE,
+			"Latency");
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+			transport->path, MEDIA_TRANSPORT_INTERFACE,
+			"PHY");
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+			transport->path, MEDIA_TRANSPORT_INTERFACE,
+			"SDU");
+	g_dbus_emit_property_changed(btd_get_dbus_connection(),
+			transport->path, MEDIA_TRANSPORT_INTERFACE,
+			"RTN");
+}
+
 static guint resume_bap(struct media_transport *transport,
 				struct media_owner *owner)
 {
@@ -1493,7 +1728,10 @@  static void bap_state_changed(struct bt_bap_stream *stream, uint8_t old_state,
 		if (owner && owner->pending)
 			return;
 		bap_update_links(transport);
-		bap_update_qos(transport);
+		if (!media_endpoint_is_broadcast(transport->endpoint))
+			bap_update_qos(transport);
+		else if (bt_bap_stream_io_dir(stream) != BT_BAP_BCAST_SOURCE)
+			bap_update_bcast_qos(transport);
 		transport_update_playing(transport, FALSE);
 		return;
 	case BT_BAP_STREAM_STATE_DISABLING:
@@ -1503,6 +1741,8 @@  static void bap_state_changed(struct bt_bap_stream *stream, uint8_t old_state,
 			return;
 		break;
 	case BT_BAP_STREAM_STATE_STREAMING:
+		if (bt_bap_stream_io_dir(stream) == BT_BAP_BCAST_SOURCE)
+			bap_update_bcast_qos(transport);
 		break;
 	}
 
@@ -1631,7 +1871,8 @@  struct media_transport *media_transport_create(struct btd_device *device,
 		properties = a2dp_properties;
 	} else if (!strcasecmp(uuid, PAC_SINK_UUID) ||
 				!strcasecmp(uuid, PAC_SOURCE_UUID) ||
-				!strcasecmp(uuid, BCAA_SERVICE_UUID)) {
+				!strcasecmp(uuid, BCAA_SERVICE_UUID) ||
+				!strcasecmp(uuid, BAA_SERVICE_UUID)) {
 		if (media_transport_init_bap(transport, stream) < 0)
 			goto fail;
 		properties = bap_properties;