diff mbox series

[BlueZ,6/6] bap: Add initial support for BAP broadcast source

Message ID 20230523143504.3319-7-iulia.tanasescu@nxp.com (mailing list archive)
State New, archived
Headers show
Series Add initial support for BAP broadcast source | expand

Commit Message

Iulia Tanasescu May 23, 2023, 2:35 p.m. UTC
From: Silviu Florian Barbulescu <silviu.barbulescu@nxp.com>

This adds initial support for BAP broadcast source.

---
 profiles/audio/bap.c       | 460 ++++++++++++++++++++++++++++++++-----
 profiles/audio/media.c     | 129 +++++++++--
 profiles/audio/transport.c |  51 ++--
 src/shared/bap.c           | 324 +++++++++++++++++++-------
 src/shared/bap.h           |  81 +++++--
 unit/test-bap.c            |  83 +++----
 6 files changed, 886 insertions(+), 242 deletions(-)

Comments

Luiz Augusto von Dentz May 23, 2023, 4:46 p.m. UTC | #1
Hi Iulia, Silviu,

On Tue, May 23, 2023 at 7:49 AM Iulia Tanasescu <iulia.tanasescu@nxp.com> wrote:
>
> From: Silviu Florian Barbulescu <silviu.barbulescu@nxp.com>
>
> This adds initial support for BAP broadcast source.
>
> ---
>  profiles/audio/bap.c       | 460 ++++++++++++++++++++++++++++++++-----
>  profiles/audio/media.c     | 129 +++++++++--
>  profiles/audio/transport.c |  51 ++--
>  src/shared/bap.c           | 324 +++++++++++++++++++-------
>  src/shared/bap.h           |  81 +++++--
>  unit/test-bap.c            |  83 +++----
>  6 files changed, 886 insertions(+), 242 deletions(-)

Please split these changes into shared/bap.*, unit/test-bap.c and
profiles/audio/*.

> diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c
> index 8f12fc410..3858eb1d9 100644
> --- a/profiles/audio/bap.c
> +++ b/profiles/audio/bap.c
> @@ -82,13 +82,25 @@ struct bap_data {
>         unsigned int pac_id;
>         struct queue *srcs;
>         struct queue *snks;
> +       struct queue *broadcast;

Lets rename broadcast to bcast to make it shorter.

>         struct queue *streams;
>         GIOChannel *listen_io;
>         int selecting;
> +       void *user_data;
>  };
>
>  static struct queue *sessions;
>
> +static bool bap_data_set_user_data(struct bap_data *data, void *user_data)
> +{
> +       if (!data)
> +               return false;
> +
> +       data->user_data = user_data;
> +
> +       return true;
> +}
> +
>  static void bap_debug(const char *str, void *user_data)
>  {
>         DBG_IDX(0xffff, "%s", str);
> @@ -167,8 +179,10 @@ static gboolean get_uuid(const GDBusPropertyTable *property,
>
>         if (queue_find(ep->data->snks, NULL, ep))
>                 uuid = PAC_SINK_UUID;
> -       else
> +       if (queue_find(ep->data->srcs, NULL, ep))
>                 uuid = PAC_SOURCE_UUID;
> +       else
> +               uuid = BROADCAST_AUDIO_ANNOUNCEMENT_SERVICE_UUID;

How about using BAA_SERVICE_UUID here?

>         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &uuid);
>
> @@ -253,6 +267,8 @@ static int parse_properties(DBusMessageIter *props, struct iovec **caps,
>                                 struct iovec **metadata, struct bt_bap_qos *qos)
>  {
>         const char *key;
> +       struct bt_bap_io_qos io_qos;
> +       bool broadcast = false;
>
>         while (dbus_message_iter_get_arg_type(props) == DBUS_TYPE_DICT_ENTRY) {
>                 DBusMessageIter value, entry;
> @@ -282,17 +298,27 @@ static int parse_properties(DBusMessageIter *props, struct iovec **caps,
>                         if (var != DBUS_TYPE_BYTE)
>                                 goto fail;
>
> -                       dbus_message_iter_get_basic(&value, &qos->cig_id);
> +                       dbus_message_iter_get_basic(&value, &qos->ucast.cig_id);
> +               } else if (!strcasecmp(key, "BIG")) {
> +                       if (var != DBUS_TYPE_BYTE)
> +                               goto fail;
> +
> +                       dbus_message_iter_get_basic(&value, &qos->bcast.big);
>                 } else if (!strcasecmp(key, "CIS")) {
>                         if (var != DBUS_TYPE_BYTE)
>                                 goto fail;
>
> -                       dbus_message_iter_get_basic(&value, &qos->cis_id);
> +                       dbus_message_iter_get_basic(&value, &qos->ucast.cis_id);
> +               } else if (!strcasecmp(key, "BIS")) {
> +                       if (var != DBUS_TYPE_BYTE)
> +                               goto fail;
> +
> +                       dbus_message_iter_get_basic(&value, &qos->bcast.bis);
>                 } else if (!strcasecmp(key, "Interval")) {
>                         if (var != DBUS_TYPE_UINT32)
>                                 goto fail;
>
> -                       dbus_message_iter_get_basic(&value, &qos->interval);
> +                       dbus_message_iter_get_basic(&value, &io_qos.interval);
>                 } else if (!strcasecmp(key, "Framing")) {
>                         dbus_bool_t val;
>
> @@ -301,7 +327,7 @@ static int parse_properties(DBusMessageIter *props, struct iovec **caps,
>
>                         dbus_message_iter_get_basic(&value, &val);
>
> -                       qos->framing = val;
> +                       qos->ucast.framing = val;
>                 } else if (!strcasecmp(key, "PHY")) {
>                         const char *str;
>
> @@ -311,42 +337,91 @@ static int parse_properties(DBusMessageIter *props, struct iovec **caps,
>                         dbus_message_iter_get_basic(&value, &str);
>
>                         if (!strcasecmp(str, "1M"))
> -                               qos->phy = 0x01;
> +                               io_qos.phy = 0x01;
>                         else if (!strcasecmp(str, "2M"))
> -                               qos->phy = 0x02;
> +                               io_qos.phy = 0x02;
>                         else
>                                 goto fail;
>                 } else if (!strcasecmp(key, "SDU")) {
>                         if (var != DBUS_TYPE_UINT16)
>                                 goto fail;
>
> -                       dbus_message_iter_get_basic(&value, &qos->sdu);
> +                       dbus_message_iter_get_basic(&value, &io_qos.sdu);
>                 } else if (!strcasecmp(key, "Retransmissions")) {
>                         if (var != DBUS_TYPE_BYTE)
>                                 goto fail;
>
> -                       dbus_message_iter_get_basic(&value, &qos->rtn);
> +                       dbus_message_iter_get_basic(&value, &io_qos.rtn);
>                 } else if (!strcasecmp(key, "Latency")) {
>                         if (var != DBUS_TYPE_UINT16)
>                                 goto fail;
>
> -                       dbus_message_iter_get_basic(&value, &qos->latency);
> +                       dbus_message_iter_get_basic(&value, &io_qos.latency);
>                 } else if (!strcasecmp(key, "Delay")) {
>                         if (var != DBUS_TYPE_UINT32)
>                                 goto fail;
>
> -                       dbus_message_iter_get_basic(&value, &qos->delay);
> +                       dbus_message_iter_get_basic(&value, &qos->ucast.delay);
>                 } else if (!strcasecmp(key, "TargetLatency")) {
>                         if (var != DBUS_TYPE_BYTE)
>                                 goto fail;
>
>                         dbus_message_iter_get_basic(&value,
> -                                                       &qos->target_latency);
> +                                                       &qos->ucast.target_latency);
> +               } else if (!strcasecmp(key, "Encryption")) {
> +                       if (var != DBUS_TYPE_BYTE)
> +                               goto fail;
> +
> +                       dbus_message_iter_get_basic(&value,
> +                                                       &qos->bcast.encryption);
> +                       DBG("Got Encryption for bcast");
> +                       broadcast = true;
> +               } else if (!strcasecmp(key, "Options")) {
> +                       if (var != DBUS_TYPE_BYTE)
> +                               goto fail;
> +
> +                       dbus_message_iter_get_basic(&value,
> +                                                       &qos->bcast.options);
> +               } else if (!strcasecmp(key, "Skip")) {
> +                       if (var != DBUS_TYPE_UINT16)
> +                               goto fail;
> +
> +                       dbus_message_iter_get_basic(&value,
> +                                                       &qos->bcast.skip);
> +               } else if (!strcasecmp(key, "SyncTimeout")) {
> +                       if (var != DBUS_TYPE_UINT16)
> +                               goto fail;
> +
> +                       dbus_message_iter_get_basic(&value,
> +                                                       &qos->bcast.sync_timeout);
> +               } else if (!strcasecmp(key, "SyncCteType")) {
> +                       if (var != DBUS_TYPE_BYTE)
> +                               goto fail;
> +
> +                       dbus_message_iter_get_basic(&value,
> +                                                       &qos->bcast.sync_cte_type);
> +               } else if (!strcasecmp(key, "MSE")) {
> +                       if (var != DBUS_TYPE_BYTE)
> +                               goto fail;
> +
> +                       dbus_message_iter_get_basic(&value,
> +                                                       &qos->bcast.mse);
> +               } else if (!strcasecmp(key, "Timeout")) {
> +                       if (var != DBUS_TYPE_UINT16)
> +                               goto fail;
> +
> +                       dbus_message_iter_get_basic(&value,
> +                                                       &qos->bcast.timeout);
>                 }
>
>                 dbus_message_iter_next(props);
>         }
>
> +       if (broadcast)
> +               memcpy(&qos->bcast.io_qos, &io_qos, sizeof(io_qos));
> +       else
> +               memcpy(&qos->ucast.io_qos, &io_qos, sizeof(io_qos));
> +
>         return 0;
>
>  fail:
> @@ -456,8 +531,8 @@ static DBusMessage *set_configuration(DBusConnection *conn, DBusMessage *msg,
>         }
>
>         /* Mark CIG and CIS to be auto assigned */
> -       ep->qos.cig_id = BT_ISO_QOS_CIG_UNSET;
> -       ep->qos.cis_id = BT_ISO_QOS_CIS_UNSET;
> +       ep->qos.ucast.cig_id = BT_ISO_QOS_CIG_UNSET;
> +       ep->qos.ucast.cis_id = BT_ISO_QOS_CIS_UNSET;
>
>         if (parse_properties(&props, &ep->caps, &ep->metadata, &ep->qos) < 0) {
>                 DBG("Unable to parse properties");
> @@ -508,6 +583,8 @@ static void ep_free(void *data)
>
>         util_iov_free(ep->caps, 1);
>         util_iov_free(ep->metadata, 1);
> +       if (bt_bap_stream_get_type(ep->stream) == BT_BAP_STREAM_TYPE_BROADCAST)
> +               util_iov_free(&ep->qos.bcast.bcode, 1);
>         free(ep->path);
>         free(ep);
>  }
> @@ -551,6 +628,11 @@ static struct bap_ep *ep_register(struct btd_service *service,
>                 i = queue_length(data->srcs);
>                 suffix = "source";
>                 break;
> +       case BT_BAP_BROADCAST_SOURCE:
> +               queue = data->broadcast;
> +               i = queue_length(data->broadcast);
> +               suffix = "broadcast";
> +               break;
>         default:
>                 return NULL;
>         }
> @@ -609,12 +691,14 @@ static void bap_config(void *data, void *user_data)
>
>         ep->id = bt_bap_stream_config(ep->stream, &ep->qos, ep->caps,
>                                                 config_cb, ep);
> -       if (!ep->id) {
> -               DBG("Unable to config stream");
> -               util_iov_free(ep->caps, 1);
> -               ep->caps = NULL;
> -               util_iov_free(ep->metadata, 1);
> -               ep->metadata = NULL;
> +       if (bt_bap_stream_get_type(ep->stream) == BT_BAP_STREAM_TYPE_UNICAST) {
> +               if (!ep->id) {
> +                       DBG("Unable to config stream");
> +                       util_iov_free(ep->caps, 1);
> +                       ep->caps = NULL;
> +                       util_iov_free(ep->metadata, 1);
> +                       ep->metadata = NULL;
> +               }
>         }
>
>         bt_bap_stream_set_user_data(ep->stream, ep->path);
> @@ -650,6 +734,7 @@ done:
>
>         queue_foreach(ep->data->srcs, bap_config, NULL);
>         queue_foreach(ep->data->snks, bap_config, NULL);
> +       queue_foreach(ep->data->broadcast, bap_config, NULL);
>  }
>
>  static bool pac_found(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
> @@ -666,8 +751,13 @@ static bool pac_found(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
>                 return true;
>         }
>
> -       /* TODO: Cache LRU? */
> -       if (btd_service_is_initiator(service)) {
> +       if (bt_bap_pac_get_type(lpac) != BT_BAP_BROADCAST_SOURCE) {
> +               /* TODO: Cache LRU? */
> +               if (btd_service_is_initiator(service)) {
> +                       if (!bt_bap_select(lpac, rpac, select_cb, ep))
> +                               ep->data->selecting++;
> +                       }
> +       } else {
>                 if (!bt_bap_select(lpac, rpac, select_cb, ep))
>                         ep->data->selecting++;
>         }
> @@ -698,11 +788,17 @@ static struct bap_ep *bap_find_ep_by_stream(struct bap_data *data,
>  {
>         struct bap_ep *ep;
>
> -       ep = queue_find(data->snks, match_ep_by_stream, stream);
> -       if (ep)
> -               return ep;
> +       if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_UNICAST) {
> +               ep = queue_find(data->snks, match_ep_by_stream, stream);
> +               if (ep)
> +                       return ep;
>
> -       return queue_find(data->srcs, match_ep_by_stream, stream);
> +               return queue_find(data->srcs, match_ep_by_stream, stream);
> +       } else if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST) {
> +
> +               return queue_find(data->broadcast, match_ep_by_stream, stream);
> +       } else
> +               return NULL;
>  }
>
>  static void iso_connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
> @@ -734,11 +830,11 @@ static void bap_iso_qos(struct bt_bap_qos *qos, struct bt_iso_io_qos *io)
>         if (!qos)
>                 return;
>
> -       io->interval = qos->interval;
> -       io->latency = qos->latency;
> -       io->sdu = qos->sdu;
> -       io->phy = qos->phy;
> -       io->rtn = qos->rtn;
> +       io->interval = qos->ucast.io_qos.interval;
> +       io->latency = qos->ucast.io_qos.latency;
> +       io->sdu = qos->ucast.io_qos.sdu;
> +       io->phy = qos->ucast.io_qos.phy;
> +       io->rtn = qos->ucast.io_qos.rtn;
>  }
>
>  static bool match_stream_qos(const void *data, const void *user_data)
> @@ -749,10 +845,10 @@ static bool match_stream_qos(const void *data, const void *user_data)
>
>         qos = bt_bap_stream_get_qos((void *)stream);
>
> -       if (iso_qos->ucast.cig != qos->cig_id)
> +       if (iso_qos->ucast.cig != qos->ucast.cig_id)
>                 return false;
>
> -       return iso_qos->ucast.cis == qos->cis_id;
> +       return iso_qos->ucast.cis == qos->ucast.cis_id;
>  }
>
>  static void iso_confirm_cb(GIOChannel *io, void *user_data)
> @@ -941,6 +1037,70 @@ static void bap_connect_io(struct bap_data *data, struct bap_ep *ep,
>         bt_bap_stream_io_connecting(stream, g_io_channel_unix_get_fd(io));
>  }
>
> +static void bap_connect_io_broadcast(struct bap_data *data, struct bap_ep *ep,
> +                               struct bt_bap_stream *stream,
> +                               struct bt_iso_qos *qos, int defer)
> +{
> +       struct btd_adapter *adapter = device_get_adapter(data->device);
> +       GIOChannel *io = NULL;
> +       GError *err = NULL;
> +       bdaddr_t dst_addr = {0};
> +       char addr[18];
> +       struct bt_iso_base base;
> +
> +       /* If IO already set and we are in the creation step, skip creating it again */
> +       if (bt_bap_stream_get_io(stream) && (defer == true))
> +               return;
> +
> +       if (ep->io_id) {
> +               g_source_remove(ep->io_id);
> +               ep->io_id = 0;
> +       }
> +       base.base_len = ep->caps->iov_len;
> +
> +       memset(base.base, 0, 248);
> +       memcpy(base.base, ep->caps->iov_base, base.base_len);
> +       DBG("ep %p stream %p defer %s", ep, stream, defer ? "true" : "false");
> +       ba2str(btd_adapter_get_address(adapter), addr);
> +
> +       /* Just create socket and advance to the configured state (when defer = true) */
> +       if (defer == true) {
> +               io = bt_io_connect(bap_connect_io_cb, ep, NULL, &err,
> +                               BT_IO_OPT_SOURCE_BDADDR,
> +                               btd_adapter_get_address(adapter),
> +                               BT_IO_OPT_DEST_BDADDR,
> +                               &dst_addr,
> +                               BT_IO_OPT_DEST_TYPE,
> +                               BDADDR_LE_PUBLIC,
> +                               BT_IO_OPT_MODE, BT_IO_MODE_ISO,
> +                               BT_IO_OPT_QOS, qos,
> +                               BT_IO_OPT_BASE, &base,
> +                               BT_IO_OPT_DEFER_TIMEOUT, defer,
> +                               BT_IO_OPT_INVALID);
> +
> +               if (!io) {
> +                       error("%s", err->message);
> +                       g_error_free(err);
> +                       return;
> +               }
> +
> +               ep->io_id = g_io_add_watch(io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
> +                               bap_io_disconnected, ep);
> +
> +               ep->io = io;
> +
> +               bt_bap_stream_io_connecting(stream, g_io_channel_unix_get_fd(io));
> +       } else { /* Advance stream state to Streaming */
> +               io = ep->io;
> +//             de-comment when streaming state is working in kernel
> +//             bt_io_broadcast_stream(&err, g_io_channel_unix_get_fd(io),
> +//                             BT_IO_OPT_DEST_BDADDR, device_get_address(ep->data->device),
> +//                             BT_IO_OPT_DEST_TYPE, device_get_le_address_type(ep->data->device),
> +//                             BT_IO_OPT_QOS, qos,
> +//                             BT_IO_OPT_INVALID);

If code is not ready then Id just remove it and leave a TODO.

> +       }
> +}
> +
>  static void bap_listen_io(struct bap_data *data, struct bt_bap_stream *stream,
>                                                 struct bt_iso_qos *qos)
>  {
> @@ -987,20 +1147,44 @@ static void bap_create_io(struct bap_data *data, struct bap_ep *ep,
>         if (!queue_find(data->streams, NULL, stream))
>                 queue_push_tail(data->streams, stream);
>
> -       if (!bt_bap_stream_io_get_qos(stream, &qos[0], &qos[1])) {
> -               error("bt_bap_stream_get_qos_links: failed");
> -               return;
> +       if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_UNICAST) {
> +               if (!bt_bap_stream_io_get_qos(stream, &qos[0], &qos[1])) {
> +                       error("bt_bap_stream_get_qos_links: failed");
> +                       return;
> +               }
>         }
>
>         memset(&iso_qos, 0, sizeof(iso_qos));
> -       iso_qos.ucast.cig = qos[0] ? qos[0]->cig_id : qos[1]->cig_id;
> -       iso_qos.ucast.cis = qos[0] ? qos[0]->cis_id : qos[1]->cis_id;
> +       if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST) {
> +               if (defer == true) {
> +                       iso_qos.bcast.big = ep->qos.bcast.big;
> +                       iso_qos.bcast.bis = ep->qos.bcast.bis;
> +                       iso_qos.bcast.sync_interval = ep->qos.bcast.sync_interval;
> +                       iso_qos.bcast.packing = ep->qos.bcast.packing;
> +                       iso_qos.bcast.framing = ep->qos.bcast.framing;
> +                       iso_qos.bcast.encryption = ep->qos.bcast.encryption;
> +                       memcpy(iso_qos.bcast.bcode, ep->qos.bcast.bcode.iov_base, 16);
> +                       iso_qos.bcast.options = ep->qos.bcast.options;
> +                       iso_qos.bcast.skip = ep->qos.bcast.skip;
> +                       iso_qos.bcast.sync_timeout = ep->qos.bcast.sync_timeout;
> +                       iso_qos.bcast.sync_cte_type = ep->qos.bcast.sync_cte_type;
> +                       iso_qos.bcast.mse = ep->qos.bcast.mse;
> +                       iso_qos.bcast.timeout = ep->qos.bcast.timeout;
> +                       memcpy(&iso_qos.bcast.out, &ep->qos.bcast.io_qos, sizeof(struct bt_iso_io_qos));
> +               }
> +       } else {
> +               iso_qos.ucast.cig = qos[0] ? qos[0]->ucast.cig_id : qos[1]->ucast.cig_id;
> +               iso_qos.ucast.cis = qos[0] ? qos[0]->ucast.cis_id : qos[1]->ucast.cis_id;
>
> -       bap_iso_qos(qos[0], &iso_qos.ucast.in);
> -       bap_iso_qos(qos[1], &iso_qos.ucast.out);
> +               bap_iso_qos(qos[0], &iso_qos.ucast.in);
> +               bap_iso_qos(qos[1], &iso_qos.ucast.out);
> +       }
>
>         if (ep)
> -               bap_connect_io(data, ep, stream, &iso_qos, defer);
> +               if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST)
> +                       bap_connect_io_broadcast(data, ep, stream, &iso_qos, defer);
> +               else
> +                       bap_connect_io(data, ep, stream, &iso_qos, defer);
>         else
>                 bap_listen_io(data, stream, &iso_qos);
>  }
> @@ -1039,12 +1223,14 @@ static void bap_state(struct bt_bap_stream *stream, uint8_t old_state,
>                         }
>
>
> -                       /* Wait QoS response to respond */
> -                       ep->id = bt_bap_stream_qos(stream, &ep->qos, qos_cb,
> -                                                                       ep);
> -                       if (!ep->id) {
> -                               error("Failed to Configure QoS");
> -                               bt_bap_stream_release(stream, NULL, NULL);
> +                       if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_UNICAST) {
> +                               /* Wait QoS response to respond */
> +                               ep->id = bt_bap_stream_qos(stream, &ep->qos, qos_cb,
> +                                                                               ep);
> +                               if (!ep->id) {
> +                                       error("Failed to Configure QoS");
> +                                       bt_bap_stream_release(stream, NULL, NULL);
> +                               }
>                         }
>                 }
>                 break;
> @@ -1055,6 +1241,12 @@ static void bap_state(struct bt_bap_stream *stream, uint8_t old_state,
>                 if (ep)
>                         bap_create_io(data, ep, stream, false);
>                 break;
> +       case BT_BAP_STREAM_STATE_STREAMING:
> +               if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST) {
> +                       if (ep)
> +                               bap_create_io(data, ep, stream, false);
> +               }
> +               break;
>         }
>  }
>
> @@ -1074,6 +1266,20 @@ static void pac_added(struct bt_bap_pac *pac, void *user_data)
>         bt_bap_foreach_pac(data->bap, BT_BAP_SINK, pac_found, service);
>  }
>
> +static void pac_added_broadcast(struct bt_bap_pac *pac, void *user_data)
> +{
> +       struct btd_service *service = user_data;
> +       struct bap_data *data;
> +
> +       if (bt_bap_pac_get_type(pac) == BT_BAP_BROADCAST_SOURCE) {
> +               DBG("pac %p", pac);
> +
> +               data = btd_service_get_user_data(service);
> +
> +               bt_bap_foreach_pac(data->bap, BT_BAP_BROADCAST_SOURCE, pac_found, service);
> +       }
> +}
> +
>  static bool ep_match_pac(const void *data, const void *match_data)
>  {
>         const struct bap_ep *ep = data;
> @@ -1114,6 +1320,38 @@ static void pac_removed(struct bt_bap_pac *pac, void *user_data)
>         ep_unregister(ep);
>  }
>
> +static void pac_removed_broadcast(struct bt_bap_pac *pac, void *user_data)
> +{
> +       struct btd_service *service = user_data;
> +       struct bap_data *data;
> +       struct queue *queue;
> +       struct bap_ep *ep;
> +
> +       DBG("pac %p", pac);
> +
> +       data = btd_service_get_user_data(service);
> +
> +       switch (bt_bap_pac_get_type(pac)) {
> +       case BT_BAP_SINK:
> +               queue = data->srcs;
> +               break;
> +       case BT_BAP_SOURCE:
> +               queue = data->snks;
> +               break;
> +       case BT_BAP_BROADCAST_SOURCE:
> +               queue = data->broadcast;
> +               break;
> +       default:
> +               return;
> +       }
> +
> +       ep = queue_remove_if(queue, ep_match_pac, pac);
> +       if (!ep)
> +               return;
> +
> +       ep_unregister(ep);
> +}
> +
>  static struct bap_data *bap_data_new(struct btd_device *device)
>  {
>         struct bap_data *data;
> @@ -1122,6 +1360,7 @@ static struct bap_data *bap_data_new(struct btd_device *device)
>         data->device = device;
>         data->srcs = queue_new();
>         data->snks = queue_new();
> +       data->broadcast = queue_new();
>
>         return data;
>  }
> @@ -1154,6 +1393,14 @@ static bool match_data(const void *data, const void *match_data)
>         return bdata->bap == bap;
>  }
>
> +static bool match_data_bap_data(const void *data, const void *match_data)
> +{
> +       const struct bap_data *bdata = data;
> +       const struct btd_adapter *adapter = match_data;
> +
> +       return bdata->user_data == adapter;
> +}
> +
>  static void bap_connecting(struct bt_bap_stream *stream, bool state, int fd,
>                                                         void *user_data)
>  {
> @@ -1178,26 +1425,49 @@ static void bap_connecting(struct bt_bap_stream *stream, bool state, int fd,
>
>         g_io_channel_set_close_on_unref(io, FALSE);
>
> -       /* Attempt to get CIG/CIS if they have not been set */
> -       if (ep->qos.cig_id == BT_ISO_QOS_CIG_UNSET ||
> -                               ep->qos.cis_id == BT_ISO_QOS_CIS_UNSET) {
> -               struct bt_iso_qos qos;
> -               GError *err = NULL;
> +       if (bt_bap_stream_get_type(ep->stream) == BT_BAP_STREAM_TYPE_UNICAST) {
> +               /* Attempt to get CIG/CIS if they have not been set */
> +               if (ep->qos.ucast.cig_id == BT_ISO_QOS_CIG_UNSET ||
> +                                       ep->qos.ucast.cis_id == BT_ISO_QOS_CIS_UNSET) {
> +                       struct bt_iso_qos qos;
> +                       GError *err = NULL;
> +
> +                       if (!bt_io_get(io, &err, BT_IO_OPT_QOS, &qos,
> +                                               BT_IO_OPT_INVALID)) {
> +                               error("%s", err->message);
> +                               g_error_free(err);
> +                               g_io_channel_unref(io);
> +                               return;
> +                       }
>
> -               if (!bt_io_get(io, &err, BT_IO_OPT_QOS, &qos,
> -                                       BT_IO_OPT_INVALID)) {
> -                       error("%s", err->message);
> -                       g_error_free(err);
> -                       g_io_channel_unref(io);
> -                       return;
> +                       ep->qos.ucast.cig_id = qos.ucast.cig;
> +                       ep->qos.ucast.cis_id = qos.ucast.cis;
>                 }
>
> -               ep->qos.cig_id = qos.ucast.cig;
> -               ep->qos.cis_id = qos.ucast.cis;
> -       }
> +               DBG("stream %p fd %d: CIG 0x%02x CIS 0x%02x", stream, fd,
> +                                               ep->qos.ucast.cig_id, ep->qos.ucast.cis_id);
> +       } else if (bt_bap_stream_get_type(ep->stream) == BT_BAP_STREAM_TYPE_BROADCAST) {
> +               /* Attempt to get BIG/BIS if they have not been set */
> +               if (ep->qos.bcast.big == BT_ISO_QOS_BIG_UNSET ||
> +                                       ep->qos.bcast.bis == BT_ISO_QOS_BIS_UNSET) {
> +                       struct bt_iso_qos qos;
> +                       GError *err = NULL;
> +
> +                       if (!bt_io_get(io, &err, BT_IO_OPT_QOS, &qos,
> +                                               BT_IO_OPT_INVALID)) {
> +                               error("%s", err->message);
> +                               g_error_free(err);
> +                               g_io_channel_unref(io);
> +                               return;
> +                       }
> +
> +                       ep->qos.bcast.big = qos.bcast.big;
> +                       ep->qos.bcast.bis = qos.bcast.bis;
> +               }
>
> -       DBG("stream %p fd %d: CIG 0x%02x CIS 0x%02x", stream, fd,
> -                                       ep->qos.cig_id, ep->qos.cis_id);
> +               DBG("stream %p fd %d: BIG 0x%02x BIS 0x%02x", stream, fd,
> +                                               ep->qos.bcast.big, ep->qos.bcast.bis);
> +       }
>  }
>
>  static void bap_attached(struct bt_bap *bap, void *user_data)
> @@ -1345,6 +1615,68 @@ static int bap_disconnect(struct btd_service *service)
>         return 0;
>  }
>
> +static int bap_adapter_probe(struct btd_profile *p,
> +                               struct btd_adapter *adapter)
> +{
> +       struct btd_device *device = btd_adapter_get_device(adapter, BDADDR_ANY, BDADDR_LE_PUBLIC);
> +       struct btd_gatt_database *database = btd_adapter_get_database(adapter);
> +       struct btd_service *service = service_create(device, p);
> +       struct bap_data *data;
> +       char addr[18];
> +
> +       ba2str(device_get_address(device), addr);
> +       DBG("%s", addr);
> +
> +       if (!btd_adapter_has_exp_feature(adapter, EXP_FEAT_ISO_SOCKET)) {
> +               error("BAP requires ISO Socket which is not enabled");
> +               return -ENOTSUP;
> +       }
> +
> +       data = bap_data_new(device);
> +       data->service = service;
> +
> +       data->bap = bt_bap_new(btd_gatt_database_get_db(database),
> +                                       btd_device_get_gatt_db(device));
> +       if (!data->bap) {
> +               error("Unable to create BAP instance");
> +               free(data);
> +               return -EINVAL;
> +       }
> +
> +       bap_data_add(data);
> +
> +       if (!bt_bap_attach_broadcast(data->bap)) {
> +               error("BAP unable to attach");
> +               return -EINVAL;
> +       }
> +
> +       data->state_id = bt_bap_state_register(data->bap, bap_state,
> +                                               bap_connecting, data, NULL);
> +       data->pac_id = bt_bap_pac_register(data->bap, pac_added_broadcast,
> +                                               pac_removed_broadcast, service, NULL);
> +
> +       bt_bap_set_user_data(data->bap, service);
> +       bap_data_set_user_data(data, adapter);
> +       return 0;
> +}
> +
> +static void bap_adapter_remove(struct btd_profile *p,
> +                                       struct btd_adapter *adapter)
> +{
> +       struct bap_data *data = queue_find(sessions, match_data_bap_data, adapter);
> +       char addr[18];
> +
> +       ba2str(btd_adapter_get_address(adapter), addr);
> +       DBG("%s", addr);
> +
> +       if (!data) {
> +               error("BAP service not handled by profile");
> +               return;
> +       }
> +
> +       bap_data_remove(data);
> +}
> +
>  static struct btd_profile bap_profile = {
>         .name           = "bap",
>         .priority       = BTD_PROFILE_PRIORITY_MEDIUM,
> @@ -1353,6 +1685,8 @@ static struct btd_profile bap_profile = {
>         .device_remove  = bap_remove,
>         .accept         = bap_accept,
>         .disconnect     = bap_disconnect,
> +       .adapter_probe  = bap_adapter_probe,
> +       .adapter_remove = bap_adapter_remove,
>         .auto_connect   = true,
>  };
>
> diff --git a/profiles/audio/media.c b/profiles/audio/media.c
> index 6ce668e31..4c7402fe9 100644
> --- a/profiles/audio/media.c
> +++ b/profiles/audio/media.c
> @@ -6,7 +6,7 @@
>   *  Copyright (C) 2006-2007  Nokia Corporation
>   *  Copyright (C) 2004-2009  Marcel Holtmann <marcel@holtmann.org>
>   *  Copyright (C) 2011  BMW Car IT GmbH. All rights reserved.
> - *
> + *  Copyright 2023 NXP
>   *
>   */
>
> @@ -748,7 +748,11 @@ static int parse_select_properties(DBusMessageIter *props, struct iovec *caps,
>                                         struct bt_bap_qos *qos)
>  {
>         const char *key;
> +       struct bt_bap_io_qos io_qos;
> +       uint8_t framing = 0;
> +       bool broadcast = false;
>
> +       memset(&io_qos, 0, sizeof(io_qos));
>         while (dbus_message_iter_get_arg_type(props) == DBUS_TYPE_DICT_ENTRY) {
>                 DBusMessageIter value, entry;
>                 int var;
> @@ -777,17 +781,27 @@ static int parse_select_properties(DBusMessageIter *props, struct iovec *caps,
>                         if (var != DBUS_TYPE_BYTE)
>                                 goto fail;
>
> -                       dbus_message_iter_get_basic(&value, &qos->cig_id);
> +                       dbus_message_iter_get_basic(&value, &qos->ucast.cig_id);
> +               } else if (!strcasecmp(key, "BIG")) {
> +                       if (var != DBUS_TYPE_BYTE)
> +                               goto fail;
> +
> +                       dbus_message_iter_get_basic(&value, &qos->bcast.big);
>                 } else if (!strcasecmp(key, "CIS")) {
>                         if (var != DBUS_TYPE_BYTE)
>                                 goto fail;
>
> -                       dbus_message_iter_get_basic(&value, &qos->cis_id);
> +                       dbus_message_iter_get_basic(&value, &qos->ucast.cig_id);
> +               } else if (!strcasecmp(key, "BIS")) {
> +                       if (var != DBUS_TYPE_BYTE)
> +                               goto fail;
> +
> +                       dbus_message_iter_get_basic(&value, &qos->bcast.bis);
>                 } else if (!strcasecmp(key, "Interval")) {
>                         if (var != DBUS_TYPE_UINT32)
>                                 goto fail;
>
> -                       dbus_message_iter_get_basic(&value, &qos->interval);
> +                       dbus_message_iter_get_basic(&value, &io_qos.interval);
>                 } else if (!strcasecmp(key, "Framing")) {
>                         dbus_bool_t val;
>
> @@ -796,7 +810,7 @@ static int parse_select_properties(DBusMessageIter *props, struct iovec *caps,
>
>                         dbus_message_iter_get_basic(&value, &val);
>
> -                       qos->framing = val;
> +                       framing = val;
>                 } else if (!strcasecmp(key, "PHY")) {
>                         const char *str;
>
> @@ -806,42 +820,106 @@ static int parse_select_properties(DBusMessageIter *props, struct iovec *caps,
>                         dbus_message_iter_get_basic(&value, &str);
>
>                         if (!strcasecmp(str, "1M"))
> -                               qos->phy = 0x01;
> +                               io_qos.phy = 0x01;
>                         else if (!strcasecmp(str, "2M"))
> -                               qos->phy = 0x02;
> +                               io_qos.phy = 0x02;
>                         else
>                                 goto fail;
>                 } else if (!strcasecmp(key, "SDU")) {
>                         if (var != DBUS_TYPE_UINT16)
>                                 goto fail;
>
> -                       dbus_message_iter_get_basic(&value, &qos->sdu);
> +                       dbus_message_iter_get_basic(&value, &io_qos.sdu);
>                 } else if (!strcasecmp(key, "Retransmissions")) {
>                         if (var != DBUS_TYPE_BYTE)
>                                 goto fail;
>
> -                       dbus_message_iter_get_basic(&value, &qos->rtn);
> +                       dbus_message_iter_get_basic(&value, &io_qos.rtn);
>                 } else if (!strcasecmp(key, "Latency")) {
>                         if (var != DBUS_TYPE_UINT16)
>                                 goto fail;
>
> -                       dbus_message_iter_get_basic(&value, &qos->latency);
> +                       dbus_message_iter_get_basic(&value, &io_qos.latency);
>                 } else if (!strcasecmp(key, "Delay")) {
>                         if (var != DBUS_TYPE_UINT32)
>                                 goto fail;
>
> -                       dbus_message_iter_get_basic(&value, &qos->delay);
> +                       dbus_message_iter_get_basic(&value, &qos->ucast.delay);
>                 } else if (!strcasecmp(key, "TargetLatency")) {
>                         if (var != DBUS_TYPE_BYTE)
>                                 goto fail;
>
>                         dbus_message_iter_get_basic(&value,
> -                                                       &qos->target_latency);
> +                                                       &qos->ucast.target_latency);
> +               } else if (!strcasecmp(key, "Encryption")) {
> +                       if (var != DBUS_TYPE_BYTE)
> +                               goto fail;
> +
> +                       dbus_message_iter_get_basic(&value,
> +                                                       &qos->bcast.encryption);
> +                       broadcast = true;
> +               } else if (!strcasecmp(key, "Options")) {
> +                       if (var != DBUS_TYPE_BYTE)
> +                               goto fail;
> +
> +                       dbus_message_iter_get_basic(&value,
> +                                                       &qos->bcast.options);
> +               } else if (!strcasecmp(key, "Skip")) {
> +                       if (var != DBUS_TYPE_UINT16)
> +                               goto fail;
> +
> +                       dbus_message_iter_get_basic(&value,
> +                                                       &qos->bcast.skip);
> +               } else if (!strcasecmp(key, "SyncTimeout")) {
> +                       if (var != DBUS_TYPE_UINT16)
> +                               goto fail;
> +
> +                       dbus_message_iter_get_basic(&value,
> +                                                       &qos->bcast.sync_timeout);
> +               } else if (!strcasecmp(key, "SyncCteType")) {
> +                       if (var != DBUS_TYPE_BYTE)
> +                               goto fail;
> +
> +                       dbus_message_iter_get_basic(&value,
> +                                                       &qos->bcast.sync_cte_type);
> +
> +               } else if (!strcasecmp(key, "SyncInterval")) {
> +                       if (var != DBUS_TYPE_BYTE)
> +                               goto fail;
> +
> +                       dbus_message_iter_get_basic(&value,
> +                                                       &qos->bcast.sync_interval);
> +               } else if (!strcasecmp(key, "MSE")) {
> +                       if (var != DBUS_TYPE_BYTE)
> +                               goto fail;
> +
> +                       dbus_message_iter_get_basic(&value,
> +                                                       &qos->bcast.mse);
> +               } else if (!strcasecmp(key, "Timeout")) {
> +                       if (var != DBUS_TYPE_UINT16)
> +                               goto fail;
> +
> +                       dbus_message_iter_get_basic(&value,
> +                                                       &qos->bcast.timeout);
> +               } else if (!strcasecmp(key, "BroadcastCode")) {
> +                       if (var != DBUS_TYPE_ARRAY)
> +                               goto fail;
> +
> +                       parse_array(&value, &qos->bcast.bcode);
>                 }
>
>                 dbus_message_iter_next(props);
>         }
>
> +       if (broadcast) {
> +               memcpy(&qos->bcast.io_qos, &io_qos, sizeof(io_qos));
> +               qos->bcast.framing = framing;
> +
> +       } else {
> +               memcpy(&qos->ucast.io_qos, &io_qos, sizeof(io_qos));
> +               qos->ucast.framing = framing;
> +       }
> +
>         return 0;
>
>  fail:
> @@ -875,8 +953,8 @@ static void pac_select_cb(struct media_endpoint *endpoint, void *ret, int size,
>         memset(&qos, 0, sizeof(qos));
>
>         /* Mark CIG and CIS to be auto assigned */
> -       qos.cig_id = BT_ISO_QOS_CIG_UNSET;
> -       qos.cis_id = BT_ISO_QOS_CIS_UNSET;
> +       qos.ucast.cig_id = BT_ISO_QOS_CIG_UNSET;
> +       qos.ucast.cis_id = BT_ISO_QOS_CIS_UNSET;
>
>         memset(&caps, 0, sizeof(caps));
>         memset(&meta, 0, sizeof(meta));
> @@ -1166,15 +1244,13 @@ static bool endpoint_init_pac(struct media_endpoint *endpoint, uint8_t type,
>
>         endpoint->pac = bt_bap_add_vendor_pac(db, name, type, endpoint->codec,
>                                 endpoint->cid, endpoint->vid, &endpoint->qos,
> -                               &data, metadata);
> +                               &data, metadata, &pac_ops, endpoint);
>         if (!endpoint->pac) {
>                 error("Unable to create PAC");
>                 free(metadata);
>                 return false;
>         }
>
> -       bt_bap_pac_set_ops(endpoint->pac, &pac_ops, endpoint);
> -
>         DBG("PAC %s registered", name);
>
>         free(name);
> @@ -1193,6 +1269,11 @@ static bool endpoint_init_pac_source(struct media_endpoint *endpoint, int *err)
>         return endpoint_init_pac(endpoint, BT_BAP_SOURCE, err);
>  }
>
> +static bool endpoint_init_broadcast_source(struct media_endpoint *endpoint, int *err)
> +{
> +       return endpoint_init_pac(endpoint, BT_BAP_BROADCAST_SOURCE, err);
> +}
> +
>  static bool endpoint_properties_exists(const char *uuid,
>                                                 struct btd_device *dev,
>                                                 void *user_data)
> @@ -1295,6 +1376,18 @@ static bool experimental_endpoint_supported(struct btd_adapter *adapter)
>         return g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL;
>  }
>
> +static bool experimental_broadcaster_ep_supported(struct btd_adapter *adapter)
> +{
> +
> +       if (!btd_adapter_has_exp_feature(adapter, EXP_FEAT_ISO_SOCKET))
> +               return false;
> +
> +       if (!btd_adapter_has_settings(adapter, MGMT_SETTING_ISO_BROADCASTER))
> +               return false;
> +
> +       return g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL;
> +}
> +
>  static struct media_endpoint_init {
>         const char *uuid;
>         bool (*func)(struct media_endpoint *endpoint, int *err);
> @@ -1308,6 +1401,8 @@ static struct media_endpoint_init {
>                                 experimental_endpoint_supported },
>         { PAC_SOURCE_UUID, endpoint_init_pac_source,
>                                 experimental_endpoint_supported },
> +       { BROADCAST_AUDIO_ANNOUNCEMENT_SERVICE_UUID, endpoint_init_broadcast_source,
> +                       experimental_broadcaster_ep_supported },
>  };
>
>  static struct media_endpoint *
> diff --git a/profiles/audio/transport.c b/profiles/audio/transport.c
> index 9172d167e..a055e4f05 100644
> --- a/profiles/audio/transport.c
> +++ b/profiles/audio/transport.c
> @@ -5,6 +5,7 @@
>   *
>   *  Copyright (C) 2006-2007  Nokia Corporation
>   *  Copyright (C) 2004-2009  Marcel Holtmann <marcel@holtmann.org>
> + *  Copyright 2023 NXP
>   *
>   *
>   */
> @@ -525,6 +526,13 @@ static void media_owner_add(struct media_owner *owner,
>         owner->pending = req;
>  }
>
> +static void *get_stream_bap(struct media_transport *transport)
> +{
> +       struct bap_transport *bap = transport->data;
> +
> +       return bap->stream;
> +}
> +
>  static DBusMessage *acquire(DBusConnection *conn, DBusMessage *msg,
>                                         void *data)
>  {
> @@ -540,15 +548,22 @@ static DBusMessage *acquire(DBusConnection *conn, DBusMessage *msg,
>                 return btd_error_not_authorized(msg);
>
>         owner = media_owner_create(msg);
> +       if (bt_bap_stream_get_type(get_stream_bap(transport)) == BT_BAP_STREAM_TYPE_BROADCAST) {
> +               req = media_request_create(msg, 0x00);
> +               media_owner_add(owner, req);
> +               media_transport_set_owner(transport, owner);
> +       }
>         id = transport->resume(transport, owner);
>         if (id == 0) {
>                 media_owner_free(owner);
>                 return btd_error_not_authorized(msg);
>         }
>
> -       req = media_request_create(msg, id);
> -       media_owner_add(owner, req);
> -       media_transport_set_owner(transport, owner);
> +       if (bt_bap_stream_get_type(get_stream_bap(transport)) == BT_BAP_STREAM_TYPE_UNICAST) {
> +               req = media_request_create(msg, id);
> +               media_owner_add(owner, req);
> +               media_transport_set_owner(transport, owner);
> +       }
>
>         return NULL;
>  }
> @@ -828,7 +843,7 @@ static gboolean qos_exists(const GDBusPropertyTable *property, void *data)
>         struct media_transport *transport = data;
>         struct bap_transport *bap = transport->data;
>
> -       return bap->qos.phy != 0x00;
> +       return bap->qos.ucast.io_qos.phy != 0x00;
>  }
>
>  static gboolean get_cig(const GDBusPropertyTable *property,
> @@ -838,7 +853,7 @@ static gboolean get_cig(const GDBusPropertyTable *property,
>         struct bap_transport *bap = transport->data;
>
>         dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE,
> -                                                       &bap->qos.cig_id);
> +                                                       &bap->qos.ucast.cig_id);
>
>         return TRUE;
>  }
> @@ -850,7 +865,7 @@ static gboolean get_cis(const GDBusPropertyTable *property,
>         struct bap_transport *bap = transport->data;
>
>         dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE,
> -                                                       &bap->qos.cis_id);
> +                                                       &bap->qos.ucast.cis_id);
>
>         return TRUE;
>  }
> @@ -862,7 +877,7 @@ static gboolean get_interval(const GDBusPropertyTable *property,
>         struct bap_transport *bap = transport->data;
>
>         dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32,
> -                                                       &bap->qos.interval);
> +                                                       &bap->qos.ucast.io_qos.interval);
>
>         return TRUE;
>  }
> @@ -872,7 +887,7 @@ static gboolean get_framing(const GDBusPropertyTable *property,
>  {
>         struct media_transport *transport = data;
>         struct bap_transport *bap = transport->data;
> -       dbus_bool_t val = bap->qos.framing;
> +       dbus_bool_t val = bap->qos.ucast.framing;
>
>         dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &val);
>
> @@ -885,7 +900,7 @@ static gboolean get_phy(const GDBusPropertyTable *property,
>         struct media_transport *transport = data;
>         struct bap_transport *bap = transport->data;
>
> -       dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &bap->qos.phy);
> +       dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &bap->qos.ucast.io_qos.phy);
>
>         return TRUE;
>  }
> @@ -896,7 +911,7 @@ static gboolean get_sdu(const GDBusPropertyTable *property,
>         struct media_transport *transport = data;
>         struct bap_transport *bap = transport->data;
>
> -       dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &bap->qos.sdu);
> +       dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &bap->qos.ucast.io_qos.sdu);
>
>         return TRUE;
>  }
> @@ -907,7 +922,7 @@ static gboolean get_retransmissions(const GDBusPropertyTable *property,
>         struct media_transport *transport = data;
>         struct bap_transport *bap = transport->data;
>
> -       dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &bap->qos.rtn);
> +       dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &bap->qos.ucast.io_qos.rtn);
>
>         return TRUE;
>  }
> @@ -919,7 +934,7 @@ static gboolean get_latency(const GDBusPropertyTable *property,
>         struct bap_transport *bap = transport->data;
>
>         dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
> -                                                       &bap->qos.latency);
> +                                                       &bap->qos.ucast.io_qos.latency);
>
>         return TRUE;
>  }
> @@ -930,7 +945,7 @@ static gboolean get_delay(const GDBusPropertyTable *property,
>         struct media_transport *transport = data;
>         struct bap_transport *bap = transport->data;
>
> -       dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &bap->qos.delay);
> +       dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &bap->qos.ucast.delay);
>
>         return TRUE;
>  }
> @@ -1478,13 +1493,6 @@ static void bap_connecting(struct bt_bap_stream *stream, bool state, int fd,
>         bap_update_links(transport);
>  }
>
> -static void *get_stream_bap(struct media_transport *transport)
> -{
> -       struct bap_transport *bap = transport->data;
> -
> -       return bap->stream;
> -}
> -
>  static void free_bap(void *data)
>  {
>         struct bap_transport *bap = data;
> @@ -1555,7 +1563,8 @@ struct media_transport *media_transport_create(struct btd_device *device,
>                         goto fail;
>                 properties = a2dp_properties;
>         } else if (!strcasecmp(uuid, PAC_SINK_UUID) ||
> -                               !strcasecmp(uuid, PAC_SOURCE_UUID)) {
> +                               !strcasecmp(uuid, PAC_SOURCE_UUID) ||
> +                               !strcasecmp(uuid, BROADCAST_AUDIO_ANNOUNCEMENT_SERVICE_UUID)) {
>                 if (media_transport_init_bap(transport, stream) < 0)
>                         goto fail;
>                 properties = bap_properties;
> diff --git a/src/shared/bap.c b/src/shared/bap.c
> index 6131c3128..54d72cf35 100644
> --- a/src/shared/bap.c
> +++ b/src/shared/bap.c
> @@ -4,6 +4,7 @@
>   *  BlueZ - Bluetooth protocol stack for Linux
>   *
>   *  Copyright (C) 2022  Intel Corporation. All rights reserved.
> + *  Copyright 2023 NXP
>   *
>   */
>
> @@ -120,6 +121,8 @@ struct bt_bap_db {
>         struct bt_ascs *ascs;
>         struct queue *sinks;
>         struct queue *sources;
> +       struct queue *broadcast_sources;
> +       struct queue *broadcast_sinks;
>  };
>
>  struct bt_bap_req {
> @@ -622,6 +625,18 @@ static struct bt_bap_endpoint *bap_endpoint_new(struct bt_bap_db *bdb,
>         return ep;
>  }
>
> +static struct bt_bap_endpoint *bap_endpoint_new_broacast(struct bt_bap_db *bdb)
> +{
> +       struct bt_bap_endpoint *ep;
> +
> +       ep = new0(struct bt_bap_endpoint, 1);
> +       ep->bdb = bdb;
> +       ep->attr = NULL;
> +       ep->dir = BT_BAP_BROADCAST_SOURCE;
> +
> +       return ep;
> +}
> +
>  static struct bt_bap_endpoint *bap_get_endpoint(struct queue *endpoints,
>                                                 struct bt_bap_db *db,
>                                                 struct gatt_db_attribute *attr)
> @@ -644,6 +659,26 @@ static struct bt_bap_endpoint *bap_get_endpoint(struct queue *endpoints,
>         return ep;
>  }
>
> +static struct bt_bap_endpoint *bap_get_endpoint_broadcast(struct queue *endpoints,
> +                                               struct bt_bap_db *db)
> +{
> +       struct bt_bap_endpoint *ep;
> +
> +       if (!db)
> +               return NULL;
> +
> +       if (queue_length(endpoints) > 0)
> +               return queue_peek_head(endpoints);
> +
> +       ep = bap_endpoint_new_broacast(db);
> +       if (!ep)
> +               return NULL;
> +
> +       queue_push_tail(endpoints, ep);
> +
> +       return ep;
> +}
> +
>  static bool bap_endpoint_match_id(const void *data, const void *match_data)
>  {
>         const struct bt_bap_endpoint *ep = data;
> @@ -861,15 +896,15 @@ static void stream_notify_qos(struct bt_bap_stream *stream)
>         status->state = ep->state;
>
>         qos = (void *)status->params;
> -       qos->cis_id = stream->qos.cis_id;
> -       qos->cig_id = stream->qos.cig_id;
> -       put_le24(stream->qos.interval, qos->interval);
> -       qos->framing = stream->qos.framing;
> -       qos->phy = stream->qos.phy;
> -       qos->sdu = cpu_to_le16(stream->qos.sdu);
> -       qos->rtn = stream->qos.rtn;
> -       qos->latency = cpu_to_le16(stream->qos.latency);
> -       put_le24(stream->qos.delay, qos->pd);
> +       qos->cis_id = stream->qos.ucast.cis_id;
> +       qos->cig_id = stream->qos.ucast.cig_id;
> +       put_le24(stream->qos.ucast.io_qos.interval, qos->interval);
> +       qos->framing = stream->qos.ucast.framing;
> +       qos->phy = stream->qos.ucast.io_qos.phy;
> +       qos->sdu = cpu_to_le16(stream->qos.ucast.io_qos.sdu);
> +       qos->rtn = stream->qos.ucast.io_qos.rtn;
> +       qos->latency = cpu_to_le16(stream->qos.ucast.io_qos.latency);
> +       put_le24(stream->qos.ucast.delay, qos->pd);
>
>         gatt_db_attribute_notify(ep->attr, (void *) status, len,
>                                         bt_bap_get_att(stream->bap));
> @@ -898,8 +933,8 @@ static void stream_notify_metadata(struct bt_bap_stream *stream)
>         status->state = ep->state;
>
>         meta = (void *)status->params;
> -       meta->cis_id = stream->qos.cis_id;
> -       meta->cig_id = stream->qos.cig_id;
> +       meta->cis_id = stream->qos.ucast.cis_id;
> +       meta->cig_id = stream->qos.ucast.cig_id;
>
>         if (stream->meta) {
>                 meta->len = stream->meta->iov_len;
> @@ -1245,6 +1280,36 @@ static void bap_stream_state_changed(struct bt_bap_stream *stream)
>         bt_bap_unref(bap);
>  }
>
> +static void stream_set_state_broadcast(struct bt_bap_stream *stream, uint8_t state)
> +{
> +       struct bt_bap_endpoint *ep = stream->ep;
> +       struct bt_bap *bap = stream->bap;
> +       const struct queue_entry *entry;
> +
> +       ep->old_state = ep->state;
> +       ep->state = state;
> +
> +       bt_bap_ref(bap);
> +
> +       for (entry = queue_get_entries(bap->state_cbs); entry;
> +                                                       entry = entry->next) {
> +               struct bt_bap_state *state = entry->data;
> +
> +               if (state->func)
> +                       state->func(stream, stream->ep->old_state,
> +                                       stream->ep->state, state->data);
> +       }
> +
> +       /* Post notification updates */
> +       switch (stream->ep->state) {
> +       case BT_ASCS_ASE_STATE_IDLE:
> +               bap_stream_detach(stream);
> +               break;
> +       }
> +
> +       bt_bap_unref(bap);
> +}
> +
>  static void stream_set_state(struct bt_bap_stream *stream, uint8_t state)
>  {
>         struct bt_bap_endpoint *ep = stream->ep;
> @@ -1381,6 +1446,11 @@ static void ep_config_cb(struct bt_bap_stream *stream, int err)
>         if (err)
>                 return;
>
> +       if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST)     {
> +               stream_set_state_broadcast(stream, BT_BAP_STREAM_STATE_CONFIG);
> +               return;
> +       }
> +
>         stream_set_state(stream, BT_BAP_STREAM_STATE_CONFIG);
>  }
>
> @@ -1560,20 +1630,20 @@ static uint8_t ascs_qos(struct bt_ascs *ascs, struct bt_bap *bap,
>
>         memset(&qos, 0, sizeof(qos));
>
> -       qos.cig_id = req->cig;
> -       qos.cis_id = req->cis;
> -       qos.interval = get_le24(req->interval);
> -       qos.framing = req->framing;
> -       qos.phy = req->phy;
> -       qos.sdu = le16_to_cpu(req->sdu);
> -       qos.rtn = req->rtn;
> -       qos.latency = le16_to_cpu(req->latency);
> -       qos.delay = get_le24(req->pd);
> +       qos.ucast.cig_id = req->cig;
> +       qos.ucast.cis_id = req->cis;
> +       qos.ucast.io_qos.interval = get_le24(req->interval);
> +       qos.ucast.framing = req->framing;
> +       qos.ucast.io_qos.phy = req->phy;
> +       qos.ucast.io_qos.sdu = le16_to_cpu(req->sdu);
> +       qos.ucast.io_qos.rtn = req->rtn;
> +       qos.ucast.io_qos.latency = le16_to_cpu(req->latency);
> +       qos.ucast.delay = get_le24(req->pd);
>
>         DBG(bap, "CIG 0x%02x CIS 0x%02x interval %u framing 0x%02x "
>                         "phy 0x%02x SDU %u rtn %u latency %u pd %u",
> -                       req->cig, req->cis, qos.interval, qos.framing, qos.phy,
> -                       qos.sdu, qos.rtn, qos.latency, qos.delay);
> +                       req->cig, req->cis, qos.ucast.io_qos.interval, qos.ucast.framing, qos.ucast.io_qos.phy,
> +                       qos.ucast.io_qos.sdu, qos.ucast.io_qos.rtn, qos.ucast.io_qos.latency, qos.ucast.delay);
>
>         ep = bap_get_local_endpoint_id(bap, req->ase);
>         if (!ep) {
> @@ -2204,6 +2274,8 @@ static struct bt_bap_db *bap_db_new(struct gatt_db *db)
>         bdb->db = gatt_db_ref(db);
>         bdb->sinks = queue_new();
>         bdb->sources = queue_new();
> +       bdb->broadcast_sources = queue_new();
> +       bdb->broadcast_sinks = queue_new();
>
>         if (!bap_db)
>                 bap_db = queue_new();
> @@ -2379,6 +2451,16 @@ static void bap_add_source(struct bt_bap_pac *pac)
>                                 iov.iov_len, NULL);
>  }
>
> +static void bap_add_broadcast_source(struct bt_bap_pac *pac)
> +{
> +       queue_push_tail(pac->bdb->broadcast_sources, pac);
> +}
> +
> +static void bap_add_broadcast_sink(struct bt_bap_pac *pac)
> +{
> +       queue_push_tail(pac->bdb->broadcast_sinks, pac);
> +}
> +
>  static void notify_pac_added(void *data, void *user_data)
>  {
>         struct bt_bap_pac_changed *changed = data;
> @@ -2400,10 +2482,12 @@ struct bt_bap_pac *bt_bap_add_vendor_pac(struct gatt_db *db,
>                                         uint8_t id, uint16_t cid, uint16_t vid,
>                                         struct bt_bap_pac_qos *qos,
>                                         struct iovec *data,
> -                                       struct iovec *metadata)
> +                                       struct iovec *metadata,
> +                                       struct bt_bap_pac_ops *pac_ops,
> +                                       void *user_data)
>  {
>         struct bt_bap_db *bdb;
> -       struct bt_bap_pac *pac;
> +       struct bt_bap_pac *pac, *pac_brodcast_sink;
>         struct bt_bap_codec codec;
>
>         if (!db)
> @@ -2429,11 +2513,17 @@ struct bt_bap_pac *bt_bap_add_vendor_pac(struct gatt_db *db,
>         case BT_BAP_SOURCE:
>                 bap_add_source(pac);
>                 break;
> +       case BT_BAP_BROADCAST_SOURCE:
> +               bap_add_broadcast_source(pac);
> +               pac_brodcast_sink = bap_pac_new(bdb, name, type, &codec, qos, data, metadata);
> +               bap_add_broadcast_sink(pac_brodcast_sink);
> +               break;
>         default:
>                 bap_pac_free(pac);
>                 return NULL;
>         }
>
> +       bt_bap_pac_set_ops(pac, pac_ops, user_data);
>         queue_foreach(sessions, notify_session_pac_added, pac);
>
>         return pac;
> @@ -2443,10 +2533,12 @@ struct bt_bap_pac *bt_bap_add_pac(struct gatt_db *db, const char *name,
>                                         uint8_t type, uint8_t id,
>                                         struct bt_bap_pac_qos *qos,
>                                         struct iovec *data,
> -                                       struct iovec *metadata)
> +                                       struct iovec *metadata,
> +                                       struct bt_bap_pac_ops *pac_ops,
> +                                       void *user_data)
>  {
>         return bt_bap_add_vendor_pac(db, name, type, id, 0x0000, 0x0000, qos,
> -                                                       data, metadata);
> +                                                       data, metadata, pac_ops, user_data);
>  }
>
>  uint8_t bt_bap_pac_get_type(struct bt_bap_pac *pac)
> @@ -2471,6 +2563,21 @@ uint32_t bt_bap_pac_get_locations(struct bt_bap_pac *pac)
>         }
>  }
>
> +uint8_t bt_bap_stream_get_type(struct bt_bap_stream *stream)
> +{
> +       if (!stream)
> +               return BT_BAP_STREAM_TYPE_UNKNOWN;
> +
> +       if ((bt_bap_pac_get_type(stream->lpac) == BT_BAP_SINK) ||
> +               (bt_bap_pac_get_type(stream->lpac) == BT_BAP_SOURCE))
> +               return BT_BAP_STREAM_TYPE_UNICAST;
> +       else if ((bt_bap_pac_get_type(stream->lpac) == BT_BAP_BROADCAST_SOURCE) ||
> +                       (bt_bap_pac_get_type(stream->lpac) == BT_BAP_BROADCAST_SINK))
> +               return BT_BAP_STREAM_TYPE_BROADCAST;
> +       else
> +               return BT_BAP_STREAM_TYPE_UNKNOWN;
> +}
> +
>  static void notify_pac_removed(void *data, void *user_data)
>  {
>         struct bt_bap_pac_changed *changed = data;
> @@ -2529,6 +2636,9 @@ bool bt_bap_remove_pac(struct bt_bap_pac *pac)
>         if (queue_remove_if(pac->bdb->sources, NULL, pac))
>                 goto found;
>
> +       if (queue_remove_if(pac->bdb->broadcast_sources, NULL, pac))
> +               goto found;
> +
>         return false;
>
>  found:
> @@ -3280,13 +3390,13 @@ static void ep_status_qos(struct bt_bap *bap, struct bt_bap_endpoint *ep,
>         if (!ep->stream)
>                 return;
>
> -       ep->stream->qos.interval = interval;
> -       ep->stream->qos.framing = qos->framing;
> -       ep->stream->qos.phy = qos->phy;
> -       ep->stream->qos.sdu = sdu;
> -       ep->stream->qos.rtn = qos->rtn;
> -       ep->stream->qos.latency = latency;
> -       ep->stream->qos.delay = pd;
> +       ep->stream->qos.ucast.io_qos.interval = interval;
> +       ep->stream->qos.ucast.framing = qos->framing;
> +       ep->stream->qos.ucast.io_qos.phy = qos->phy;
> +       ep->stream->qos.ucast.io_qos.sdu = sdu;
> +       ep->stream->qos.ucast.io_qos.rtn = qos->rtn;
> +       ep->stream->qos.ucast.io_qos.latency = latency;
> +       ep->stream->qos.ucast.delay = pd;
>
>         if (ep->old_state == BT_ASCS_ASE_STATE_CONFIG)
>                 bap_stream_config_cfm(ep->stream);
> @@ -3861,6 +3971,25 @@ clone:
>         return true;
>  }
>
> +bool bt_bap_attach_broadcast(struct bt_bap *bap)
> +{
> +       struct bt_bap_endpoint *ep;
> +
> +       if (queue_find(sessions, NULL, bap))
> +               return true;
> +
> +       if (!sessions)
> +               sessions = queue_new();
> +
> +       queue_push_tail(sessions, bap);
> +
> +       ep = bap_get_endpoint_broadcast(bap->remote_eps, bap->ldb);
> +       if (ep)
> +               ep->bap = bap;
> +
> +       return true;
> +}
> +
>  static void stream_foreach_detach(void *data, void *user_data)
>  {
>         struct bt_bap_stream *stream = data;
> @@ -4065,7 +4194,10 @@ void bt_bap_foreach_pac(struct bt_bap *bap, uint8_t type,
>                                                         func, user_data);
>         case BT_BAP_SOURCE:
>                 return bap_foreach_pac(bap->ldb->sinks, bap->rdb->sources,
> -                                                       func, user_data);
> +                                                          func, user_data);
> +       case BT_BAP_BROADCAST_SOURCE:
> +               return bap_foreach_pac(bap->ldb->broadcast_sources, bap->ldb->broadcast_sinks,
> +                                                               func, user_data);
>         }
>  }
>
> @@ -4178,42 +4310,49 @@ unsigned int bt_bap_stream_config(struct bt_bap_stream *stream,
>         if (!bap_stream_valid(stream))
>                 return 0;
>
> -       if (!stream->client) {
> -               stream_config(stream, data, NULL);
> -               return 0;
> -       }
> +       if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_UNICAST) {
> +               if (!stream->client) {
> +                       stream_config(stream, data, NULL);
> +                       return 0;
> +               }
>
> -       memset(&config, 0, sizeof(config));
> +               memset(&config, 0, sizeof(config));
>
> -       config.ase = stream->ep->id;
> -       config.latency = qos->target_latency;
> -       config.phy = qos->phy;
> -       config.codec = stream->rpac->codec;
> +               config.ase = stream->ep->id;
> +               config.latency = qos->ucast.target_latency;
> +               config.phy = qos->ucast.io_qos.phy;
> +               config.codec = stream->rpac->codec;
>
> -       iov[0].iov_base = &config;
> -       iov[0].iov_len = sizeof(config);
> +               iov[0].iov_base = &config;
> +               iov[0].iov_len = sizeof(config);
>
> -       if (data) {
> -               if (!bap_print_cc(data->iov_base, data->iov_len,
> -                                       stream->bap->debug_func,
> -                                       stream->bap->debug_data))
> -                       return 0;
> +               if (data) {
> +                       if (!bap_print_cc(data->iov_base, data->iov_len,
> +                                               stream->bap->debug_func,
> +                                               stream->bap->debug_data))
> +                               return 0;
>
> -               config.cc_len = data->iov_len;
> -               iov[1] = *data;
> -               iovlen++;
> -       }
> +                       config.cc_len = data->iov_len;
> +                       iov[1] = *data;
> +                       iovlen++;
> +               }
>
> -       req = bap_req_new(stream, BT_ASCS_CONFIG, iov, iovlen, func, user_data);
> +               req = bap_req_new(stream, BT_ASCS_CONFIG, iov, iovlen, func, user_data);
>
> -       if (!bap_queue_req(stream->bap, req)) {
> -               bap_req_free(req);
> -               return 0;
> -       }
> +               if (!bap_queue_req(stream->bap, req)) {
> +                       bap_req_free(req);
> +                       return 0;
> +               }
>
> -       stream->qos = *qos;
> +               stream->qos = *qos;
>
> -       return req->id;
> +               return req->id;
> +       } else if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST) {
> +               stream->qos = *qos;
> +               return 0;
> +       } else {
> +               return 0;
> +       }
>  }
>
>  static bool match_pac(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
> @@ -4274,7 +4413,7 @@ struct bt_bap_stream *bt_bap_stream_new(struct bt_bap *bap,
>                 if (rpac)
>                         type = rpac->type;
>                 else if (lpac) {
> -                       switch(lpac->type) {
> +                       switch (lpac->type) {
>                         case BT_BAP_SINK:
>                                 type = BT_BAP_SOURCE;
>                                 break;
> @@ -4339,6 +4478,10 @@ bool bt_bap_stream_set_user_data(struct bt_bap_stream *stream, void *user_data)
>
>         stream->user_data = user_data;
>
> +       if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST)
> +               stream->lpac->ops->config(stream, stream->cc, &stream->qos,
> +                                                               ep_config_cb, stream->lpac->user_data);
> +
>         return true;
>  }
>
> @@ -4369,15 +4512,15 @@ unsigned int bt_bap_stream_qos(struct bt_bap_stream *stream,
>
>         /* TODO: Figure out how to pass these values around */
>         qos.ase = stream->ep->id;
> -       qos.cig = data->cig_id;
> -       qos.cis = data->cis_id;
> -       put_le24(data->interval, qos.interval);
> -       qos.framing = data->framing;
> -       qos.phy = data->phy;
> -       qos.sdu = cpu_to_le16(data->sdu);
> -       qos.rtn = data->rtn;
> -       qos.latency = cpu_to_le16(data->latency);
> -       put_le24(data->delay, qos.pd);
> +       qos.cig = data->ucast.cig_id;
> +       qos.cis = data->ucast.cis_id;
> +       put_le24(data->ucast.io_qos.interval, qos.interval);
> +       qos.framing = data->ucast.framing;
> +       qos.phy = data->ucast.io_qos.phy;
> +       qos.sdu = cpu_to_le16(data->ucast.io_qos.sdu);
> +       qos.rtn = data->ucast.io_qos.rtn;
> +       qos.latency = cpu_to_le16(data->ucast.io_qos.latency);
> +       put_le24(data->ucast.delay, qos.pd);
>
>         iov.iov_base = &qos;
>         iov.iov_len = sizeof(qos);
> @@ -4448,7 +4591,7 @@ unsigned int bt_bap_stream_enable(struct bt_bap_stream *stream,
>                                         bt_bap_stream_func_t func,
>                                         void *user_data)
>  {
> -       int ret;
> +       int ret = 0;
>
>         /* Table 3.2: ASE state machine transition
>          * Initiating device - client Only
> @@ -4456,12 +4599,17 @@ unsigned int bt_bap_stream_enable(struct bt_bap_stream *stream,
>         if (!bap_stream_valid(stream) || !stream->client)
>                 return 0;
>
> -       ret = bap_stream_metadata(stream, BT_ASCS_ENABLE, metadata, func,
> -                                                               user_data);
> -       if (!ret || !enable_links)
> -               return ret;
> +       if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_UNICAST) {
> +               ret = bap_stream_metadata(stream, BT_ASCS_ENABLE, metadata, func,
> +                                                         user_data);
> +               if (!ret || !enable_links)
> +                       return ret;
>
> -       queue_foreach(stream->links, bap_stream_enable_link, metadata);
> +               queue_foreach(stream->links, bap_stream_enable_link, metadata);
> +       } else if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST) {
> +               stream_set_state_broadcast(stream, BT_BAP_STREAM_STATE_STREAMING);
> +               return ret = 1;
> +       }
>
>         return ret;
>  }
> @@ -4640,6 +4788,15 @@ unsigned int bt_bap_stream_release(struct bt_bap_stream *stream,
>
>         bap = stream->bap;
>
> +       /* If stream is broadcast, no BT_ASCS_RELEASE is required */
> +       if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST) {
> +               if (!bap_stream_valid(stream)) {
> +                       stream_set_state_broadcast(stream, BT_BAP_STREAM_STATE_IDLE);
> +                       stream = NULL;
> +               }
> +               return 0;
> +       }
> +
>         /* If stream does not belong to a client session, clean it up now */
>         if (!bap_stream_valid(stream)) {
>                 stream_set_state(stream, BT_BAP_STREAM_STATE_IDLE);
> @@ -4675,8 +4832,11 @@ uint32_t bt_bap_stream_get_location(struct bt_bap_stream *stream)
>
>         if (stream->ep->dir == BT_BAP_SOURCE)
>                 return pacs->source_loc_value;
> -       else
> +       else if (stream->ep->dir == BT_BAP_SINK)
>                 return pacs->sink_loc_value;
> +       else
> +               // TO DO get the location values from metadata for brodcast source and sink
> +               return stream->bap->ldb->pacs->source_loc_value;
>  }
>
>  struct iovec *bt_bap_stream_get_config(struct bt_bap_stream *stream)
> @@ -4781,8 +4941,8 @@ int bt_bap_stream_io_link(struct bt_bap_stream *stream,
>                 return -EALREADY;
>
>         if (stream->client != link->client ||
> -                       stream->qos.cig_id != link->qos.cig_id ||
> -                       stream->qos.cis_id != link->qos.cis_id)
> +                       stream->qos.ucast.cig_id != link->qos.ucast.cig_id ||
> +                       stream->qos.ucast.cis_id != link->qos.ucast.cis_id)
>                 return -EINVAL;
>
>         if (!stream->links)
> @@ -4819,7 +4979,7 @@ static void bap_stream_get_in_qos(void *data, void *user_data)
>         struct bt_bap_qos **qos = user_data;
>
>         if (!qos || *qos || stream->ep->dir != BT_BAP_SOURCE ||
> -                                               !stream->qos.sdu)
> +                                               !stream->qos.ucast.io_qos.sdu)
>                 return;
>
>         *qos = &stream->qos;
> @@ -4830,7 +4990,7 @@ static void bap_stream_get_out_qos(void *data, void *user_data)
>         struct bt_bap_stream *stream = data;
>         struct bt_bap_qos **qos = user_data;
>
> -       if (!qos || *qos || stream->ep->dir != BT_BAP_SINK || !stream->qos.sdu)
> +       if (!qos || *qos || stream->ep->dir != BT_BAP_SINK || !stream->qos.ucast.io_qos.sdu)
>                 return;
>
>         *qos = &stream->qos;
> diff --git a/src/shared/bap.h b/src/shared/bap.h
> index e9f769d0e..3b07df158 100644
> --- a/src/shared/bap.h
> +++ b/src/shared/bap.h
> @@ -4,6 +4,7 @@
>   *  BlueZ - Bluetooth protocol stack for Linux
>   *
>   *  Copyright (C) 2022  Intel Corporation. All rights reserved.
> + *  Copyright 2023 NXP
>   *
>   */
>
> @@ -14,8 +15,14 @@
>  #define __packed __attribute__((packed))
>  #endif
>
> -#define BT_BAP_SINK                    0x01
> +#define BT_BAP_SINK                            0x01
>  #define        BT_BAP_SOURCE                   0x02
> +#define        BT_BAP_BROADCAST_SOURCE 0x03
> +#define        BT_BAP_BROADCAST_SINK   0x04
> +
> +#define BT_BAP_STREAM_TYPE_UNICAST             0x01
> +#define        BT_BAP_STREAM_TYPE_BROADCAST    0x02
> +#define        BT_BAP_STREAM_TYPE_UNKNOWN              0x03
>
>  #define BT_BAP_STREAM_STATE_IDLE       0x00
>  #define BT_BAP_STREAM_STATE_CONFIG     0x01
> @@ -49,17 +56,46 @@ struct bt_ltv {
>         uint8_t  value[0];
>  } __packed;
>
> -struct bt_bap_qos {
> +struct bt_bap_io_qos {
> +       uint32_t interval;      /* Frame interval */
> +       uint16_t latency;       /* Transport Latency */
> +       uint16_t sdu;           /* Maximum SDU Size */
> +       uint8_t  phy;           /* PHY */
> +       uint8_t  rtn;           /* Retransmission Effort */
> +};
> +
> +struct bt_bap_ucast_qos {
>         uint8_t  cig_id;
>         uint8_t  cis_id;
> -       uint32_t interval;              /* Frame interval */
>         uint8_t  framing;               /* Frame framing */
> -       uint8_t  phy;                   /* PHY */
> -       uint16_t sdu;                   /* Maximum SDU Size */
> -       uint8_t  rtn;                   /* Retransmission Effort */
> -       uint16_t latency;               /* Transport Latency */
>         uint32_t delay;                 /* Presentation Delay */
>         uint8_t  target_latency;        /* Target Latency */
> +       struct bt_bap_io_qos io_qos;
> +};
> +
> +struct bt_bap_bcast_qos {
> +       uint8_t  big;
> +       uint8_t  bis;
> +       uint8_t  sync_interval;
> +       uint8_t  packing;
> +       uint8_t  framing;
> +       uint8_t  encryption;
> +       struct iovec bcode;
> +       uint8_t  options;
> +       uint16_t skip;
> +       uint16_t sync_timeout;
> +       uint8_t  sync_cte_type;
> +       uint8_t  mse;
> +       uint16_t timeout;
> +       uint8_t  pa_sync;
> +       struct bt_bap_io_qos io_qos;
> +};
> +
> +struct bt_bap_qos {
> +       union {
> +                       struct bt_bap_ucast_qos ucast;
> +                       struct bt_bap_bcast_qos bcast;
> +               };
>  };
>
>  typedef void (*bt_bap_ready_func_t)(struct bt_bap *bap, void *user_data);
> @@ -98,28 +134,32 @@ struct bt_bap_pac_qos {
>         uint32_t ppd_max;
>  };
>
> +struct bt_bap_pac_ops {
> +       int (*select)(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
> +                       struct bt_bap_pac_qos *qos,
> +                       bt_bap_pac_select_t cb, void *cb_data, void *user_data);
> +       int (*config)(struct bt_bap_stream *stream, struct iovec *cfg,
> +                       struct bt_bap_qos *qos, bt_bap_pac_config_t cb,
> +                       void *user_data);
> +       void (*clear)(struct bt_bap_stream *stream, void *user_data);
> +};
> +
>  struct bt_bap_pac *bt_bap_add_vendor_pac(struct gatt_db *db,
>                                         const char *name, uint8_t type,
>                                         uint8_t id, uint16_t cid, uint16_t vid,
>                                         struct bt_bap_pac_qos *qos,
>                                         struct iovec *data,
> -                                       struct iovec *metadata);
> +                                       struct iovec *metadata,
> +                                       struct bt_bap_pac_ops *pac_ops,
> +                                       void *user_data);
>
>  struct bt_bap_pac *bt_bap_add_pac(struct gatt_db *db, const char *name,
>                                         uint8_t type, uint8_t id,
>                                         struct bt_bap_pac_qos *qos,
>                                         struct iovec *data,
> -                                       struct iovec *metadata);
> -
> -struct bt_bap_pac_ops {
> -       int (*select)(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
> -                       struct bt_bap_pac_qos *qos,
> -                       bt_bap_pac_select_t cb, void *cb_data, void *user_data);
> -       int (*config)(struct bt_bap_stream *stream, struct iovec *cfg,
> -                       struct bt_bap_qos *qos, bt_bap_pac_config_t cb,
> -                       void *user_data);
> -       void (*clear)(struct bt_bap_stream *stream, void *user_data);
> -};
> +                                       struct iovec *metadata,
> +                                       struct bt_bap_pac_ops *pac_ops,
> +                                       void *user_data);
>
>  bool bt_bap_pac_set_ops(struct bt_bap_pac *pac, struct bt_bap_pac_ops *ops,
>                                         void *user_data);
> @@ -130,6 +170,8 @@ uint8_t bt_bap_pac_get_type(struct bt_bap_pac *pac);
>
>  uint32_t bt_bap_pac_get_locations(struct bt_bap_pac *pac);
>
> +uint8_t bt_bap_stream_get_type(struct bt_bap_stream *stream);
> +
>  struct bt_bap_stream *bt_bap_pac_get_stream(struct bt_bap_pac *pac);
>
>  /* Session related function */
> @@ -149,6 +191,7 @@ struct bt_bap *bt_bap_ref(struct bt_bap *bap);
>  void bt_bap_unref(struct bt_bap *bap);
>
>  bool bt_bap_attach(struct bt_bap *bap, struct bt_gatt_client *client);
> +bool bt_bap_attach_broadcast(struct bt_bap *bap);
>  void bt_bap_detach(struct bt_bap *bap);
>
>  bool bt_bap_set_debug(struct bt_bap *bap, bt_bap_debug_func_t cb,
> diff --git a/unit/test-bap.c b/unit/test-bap.c
> index bf525742d..8d1b3fd52 100644
> --- a/unit/test-bap.c
> +++ b/unit/test-bap.c
> @@ -377,11 +377,11 @@ static void test_client_config(struct test_data *data)
>                                                         "test-bap-snk",
>                                                         BT_BAP_SINK, 0x0ff,
>                                                         0x0001, 0x0001,
> -                                                       NULL, data->caps, NULL);
> +                                                       NULL, data->caps, NULL, NULL, NULL);
>                 else
>                         data->snk = bt_bap_add_pac(data->db, "test-bap-snk",
>                                                         BT_BAP_SINK, LC3_ID,
> -                                                       NULL, data->caps, NULL);
> +                                                       NULL, data->caps, NULL, NULL, NULL);
>                 g_assert(data->snk);
>         }
>
> @@ -391,11 +391,11 @@ static void test_client_config(struct test_data *data)
>                                                         "test-bap-src",
>                                                         BT_BAP_SOURCE, 0x0ff,
>                                                         0x0001, 0x0001,
> -                                                       NULL, data->caps, NULL);
> +                                                       NULL, data->caps, NULL, NULL, NULL);
>                 else
>                         data->src = bt_bap_add_pac(data->db, "test-bap-src",
>                                                         BT_BAP_SOURCE, LC3_ID,
> -                                                       NULL, data->caps, NULL);
> +                                                       NULL, data->caps, NULL, NULL, NULL);
>                 g_assert(data->src);
>         }
>  }
> @@ -712,12 +712,15 @@ static void test_disc(void)
>  #define QOS_BALANCED_2M \
>         { \
>                 .target_latency = BT_BAP_CONFIG_LATENCY_BALANCED, \
> -               .phy = BT_BAP_CONFIG_PHY_2M, \
> +               .io_qos.phy = BT_BAP_CONFIG_PHY_2M, \
>         }
> -
> +#define QOS_UCAST \
> +{\
> +       .ucast = QOS_BALANCED_2M, \
> +}
>  static struct test_config cfg_snk_8_1 = {
>         .cc = LC3_CONFIG_8_1,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .snk = true,
>  };
>
> @@ -727,7 +730,7 @@ static struct test_config cfg_snk_8_1 = {
>
>  static struct test_config cfg_snk_8_2 = {
>         .cc = LC3_CONFIG_8_2,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .snk = true,
>  };
>
> @@ -737,7 +740,7 @@ static struct test_config cfg_snk_8_2 = {
>
>  static struct test_config cfg_snk_16_1 = {
>         .cc = LC3_CONFIG_16_1,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .snk = true,
>  };
>
> @@ -747,7 +750,7 @@ static struct test_config cfg_snk_16_1 = {
>
>  static struct test_config cfg_snk_16_2 = {
>         .cc = LC3_CONFIG_16_2,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .snk = true,
>  };
>
> @@ -757,7 +760,7 @@ static struct test_config cfg_snk_16_2 = {
>
>  static struct test_config cfg_snk_24_1 = {
>         .cc = LC3_CONFIG_24_1,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .snk = true,
>  };
>
> @@ -767,7 +770,7 @@ static struct test_config cfg_snk_24_1 = {
>
>  static struct test_config cfg_snk_24_2 = {
>         .cc = LC3_CONFIG_24_2,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .snk = true,
>  };
>
> @@ -777,7 +780,7 @@ static struct test_config cfg_snk_24_2 = {
>
>  static struct test_config cfg_snk_32_1 = {
>         .cc = LC3_CONFIG_32_1,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .snk = true,
>  };
>
> @@ -787,7 +790,7 @@ static struct test_config cfg_snk_32_1 = {
>
>  static struct test_config cfg_snk_32_2 = {
>         .cc = LC3_CONFIG_32_2,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .snk = true,
>  };
>
> @@ -797,7 +800,7 @@ static struct test_config cfg_snk_32_2 = {
>
>  static struct test_config cfg_snk_44_1 = {
>         .cc = LC3_CONFIG_44_1,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .snk = true,
>  };
>
> @@ -807,7 +810,7 @@ static struct test_config cfg_snk_44_1 = {
>
>  static struct test_config cfg_snk_44_2 = {
>         .cc = LC3_CONFIG_44_2,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .snk = true,
>  };
>
> @@ -817,7 +820,7 @@ static struct test_config cfg_snk_44_2 = {
>
>  static struct test_config cfg_snk_48_1 = {
>         .cc = LC3_CONFIG_48_1,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .snk = true,
>  };
>
> @@ -827,7 +830,7 @@ static struct test_config cfg_snk_48_1 = {
>
>  static struct test_config cfg_snk_48_2 = {
>         .cc = LC3_CONFIG_48_2,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .snk = true,
>  };
>
> @@ -837,7 +840,7 @@ static struct test_config cfg_snk_48_2 = {
>
>  static struct test_config cfg_snk_48_3 = {
>         .cc = LC3_CONFIG_48_3,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .snk = true,
>  };
>
> @@ -847,7 +850,7 @@ static struct test_config cfg_snk_48_3 = {
>
>  static struct test_config cfg_snk_48_4 = {
>         .cc = LC3_CONFIG_48_4,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .snk = true,
>  };
>
> @@ -857,7 +860,7 @@ static struct test_config cfg_snk_48_4 = {
>
>  static struct test_config cfg_snk_48_5 = {
>         .cc = LC3_CONFIG_48_5,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .snk = true,
>  };
>
> @@ -867,7 +870,7 @@ static struct test_config cfg_snk_48_5 = {
>
>  static struct test_config cfg_snk_48_6 = {
>         .cc = LC3_CONFIG_48_6,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .snk = true,
>  };
>
> @@ -899,7 +902,7 @@ static struct test_config cfg_snk_48_6 = {
>
>  static struct test_config cfg_src_8_1 = {
>         .cc = LC3_CONFIG_8_1,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .src = true,
>  };
>
> @@ -909,7 +912,7 @@ static struct test_config cfg_src_8_1 = {
>
>  static struct test_config cfg_src_8_2 = {
>         .cc = LC3_CONFIG_8_2,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .src = true,
>  };
>
> @@ -919,7 +922,7 @@ static struct test_config cfg_src_8_2 = {
>
>  static struct test_config cfg_src_16_1 = {
>         .cc = LC3_CONFIG_16_1,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .src = true,
>  };
>
> @@ -929,7 +932,7 @@ static struct test_config cfg_src_16_1 = {
>
>  static struct test_config cfg_src_16_2 = {
>         .cc = LC3_CONFIG_16_2,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .src = true,
>  };
>
> @@ -939,7 +942,7 @@ static struct test_config cfg_src_16_2 = {
>
>  static struct test_config cfg_src_24_1 = {
>         .cc = LC3_CONFIG_24_1,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .src = true,
>  };
>
> @@ -949,7 +952,7 @@ static struct test_config cfg_src_24_1 = {
>
>  static struct test_config cfg_src_24_2 = {
>         .cc = LC3_CONFIG_24_2,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .src = true,
>  };
>
> @@ -959,7 +962,7 @@ static struct test_config cfg_src_24_2 = {
>
>  static struct test_config cfg_src_32_1 = {
>         .cc = LC3_CONFIG_32_1,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .src = true,
>  };
>
> @@ -969,7 +972,7 @@ static struct test_config cfg_src_32_1 = {
>
>  static struct test_config cfg_src_32_2 = {
>         .cc = LC3_CONFIG_32_2,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .src = true,
>  };
>
> @@ -979,7 +982,7 @@ static struct test_config cfg_src_32_2 = {
>
>  static struct test_config cfg_src_44_1 = {
>         .cc = LC3_CONFIG_44_1,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .src = true,
>  };
>
> @@ -989,7 +992,7 @@ static struct test_config cfg_src_44_1 = {
>
>  static struct test_config cfg_src_44_2 = {
>         .cc = LC3_CONFIG_44_2,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .src = true,
>  };
>
> @@ -999,7 +1002,7 @@ static struct test_config cfg_src_44_2 = {
>
>  static struct test_config cfg_src_48_1 = {
>         .cc = LC3_CONFIG_48_1,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .src = true,
>  };
>
> @@ -1009,7 +1012,7 @@ static struct test_config cfg_src_48_1 = {
>
>  static struct test_config cfg_src_48_2 = {
>         .cc = LC3_CONFIG_48_2,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .src = true,
>  };
>
> @@ -1019,7 +1022,7 @@ static struct test_config cfg_src_48_2 = {
>
>  static struct test_config cfg_src_48_3 = {
>         .cc = LC3_CONFIG_48_3,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .src = true,
>  };
>
> @@ -1029,7 +1032,7 @@ static struct test_config cfg_src_48_3 = {
>
>  static struct test_config cfg_src_48_4 = {
>         .cc = LC3_CONFIG_48_4,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .src = true,
>  };
>
> @@ -1039,7 +1042,7 @@ static struct test_config cfg_src_48_4 = {
>
>  static struct test_config cfg_src_48_5 = {
>         .cc = LC3_CONFIG_48_5,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .src = true,
>  };
>
> @@ -1049,7 +1052,7 @@ static struct test_config cfg_src_48_5 = {
>
>  static struct test_config cfg_src_48_6 = {
>         .cc = LC3_CONFIG_48_6,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .src = true,
>  };
>
> @@ -1141,7 +1144,7 @@ static void test_scc_cc_lc3(void)
>
>  static struct test_config cfg_snk_vs = {
>         .cc = IOV_NULL,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .snk = true,
>         .vs = true,
>  };
> @@ -1155,7 +1158,7 @@ static struct test_config cfg_snk_vs = {
>
>  static struct test_config cfg_src_vs = {
>         .cc = IOV_NULL,
> -       .qos = QOS_BALANCED_2M,
> +       .qos = QOS_UCAST,
>         .src = true,
>         .vs = true,
>  };
> --
> 2.34.1
>
Silviu Florian Barbulescu May 24, 2023, 11:44 a.m. UTC | #2
Hi Luiz,

>Hi Iulia, Silviu,
>
>On Tue, May 23, 2023 at 7:49 AM Iulia Tanasescu <iulia.tanasescu@nxp.com> wrote:
>>
>> From: Silviu Florian Barbulescu <silviu.barbulescu@nxp.com>
>>
>> This adds initial support for BAP broadcast source.
>>
>> ---
>>  profiles/audio/bap.c       | 460 ++++++++++++++++++++++++++++++++-----
>>  profiles/audio/media.c     | 129 +++++++++--
>>  profiles/audio/transport.c |  51 ++--
>>  src/shared/bap.c           | 324 +++++++++++++++++++-------
>>  src/shared/bap.h           |  81 +++++--
>>  unit/test-bap.c            |  83 +++----
>>  6 files changed, 886 insertions(+), 242 deletions(-)
>
>Please split these changes into shared/bap.*, unit/test-bap.c and
>profiles/audio/*.

The reason for doing a single commit for all these files is that the bt_bap_qos structure has been modified
to a union containing unicast or broadcast qos. This breaks compilation if not all occurrences are resolved.

>
>> diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c
>> index 8f12fc410..3858eb1d9 100644
>> --- a/profiles/audio/bap.c
>> +++ b/profiles/audio/bap.c
>> @@ -82,13 +82,25 @@ struct bap_data {
>>         unsigned int pac_id;
>>         struct queue *srcs;
>>         struct queue *snks;
>> +       struct queue *broadcast;
>
>Lets rename broadcast to bcast to make it shorter.

We will update this in the next patch. 

>
>>         struct queue *streams;
>>         GIOChannel *listen_io;
>>         int selecting;
>> +       void *user_data;
>>  };
>>
>>  static struct queue *sessions;
>>
>> +static bool bap_data_set_user_data(struct bap_data *data, void *user_data)
>> +{
>> +       if (!data)
>> +               return false;
>> +
>> +       data->user_data = user_data;
>> +
>> +       return true;
>> +}
>> +
>>  static void bap_debug(const char *str, void *user_data)
>>  {
>>         DBG_IDX(0xffff, "%s", str);
>> @@ -167,8 +179,10 @@ static gboolean get_uuid(const GDBusPropertyTable *property,
>>
>>         if (queue_find(ep->data->snks, NULL, ep))
>>                 uuid = PAC_SINK_UUID;
>> -       else
>> +       if (queue_find(ep->data->srcs, NULL, ep))
>>                 uuid = PAC_SOURCE_UUID;
>> +       else
>> +               uuid = BROADCAST_AUDIO_ANNOUNCEMENT_SERVICE_UUID;
>
>How about using BAA_SERVICE_UUID here?

We will update this in the next patch.

>
>>         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &uuid);
>>
>> @@ -253,6 +267,8 @@ static int parse_properties(DBusMessageIter *props, struct iovec **caps,
>>                                 struct iovec **metadata, struct bt_bap_qos *qos)
>>  {
>>         const char *key;
>> +       struct bt_bap_io_qos io_qos;
>> +       bool broadcast = false;
>>
>>         while (dbus_message_iter_get_arg_type(props) == DBUS_TYPE_DICT_ENTRY) {
>>                 DBusMessageIter value, entry;
>> @@ -282,17 +298,27 @@ static int parse_properties(DBusMessageIter *props, struct iovec **caps,
>>                         if (var != DBUS_TYPE_BYTE)
>>                                 goto fail;
>>
>> -                       dbus_message_iter_get_basic(&value, &qos->cig_id);
>> +                       dbus_message_iter_get_basic(&value, &qos->ucast.cig_id);
>> +               } else if (!strcasecmp(key, "BIG")) {
>> +                       if (var != DBUS_TYPE_BYTE)
>> +                               goto fail;
>> +
>> +                       dbus_message_iter_get_basic(&value, &qos->bcast.big);
>>                 } else if (!strcasecmp(key, "CIS")) {
>>                         if (var != DBUS_TYPE_BYTE)
>>                                 goto fail;
>>
>> -                       dbus_message_iter_get_basic(&value, &qos->cis_id);
>> +                       dbus_message_iter_get_basic(&value, &qos->ucast.cis_id);
>> +               } else if (!strcasecmp(key, "BIS")) {
>> +                       if (var != DBUS_TYPE_BYTE)
>> +                               goto fail;
>> +
>> +                       dbus_message_iter_get_basic(&value, &qos->bcast.bis);
>>                 } else if (!strcasecmp(key, "Interval")) {
>>                         if (var != DBUS_TYPE_UINT32)
>>                                 goto fail;
>>
>> -                       dbus_message_iter_get_basic(&value, &qos->interval);
>> +                       dbus_message_iter_get_basic(&value, &io_qos.interval);
>>                 } else if (!strcasecmp(key, "Framing")) {
>>                         dbus_bool_t val;
>>
>> @@ -301,7 +327,7 @@ static int parse_properties(DBusMessageIter *props, struct iovec **caps,
>>
>>                         dbus_message_iter_get_basic(&value, &val);
>>
>> -                       qos->framing = val;
>> +                       qos->ucast.framing = val;
>>                 } else if (!strcasecmp(key, "PHY")) {
>>                         const char *str;
>>
>> @@ -311,42 +337,91 @@ static int parse_properties(DBusMessageIter *props, struct iovec **caps,
>>                         dbus_message_iter_get_basic(&value, &str);
>>
>>                         if (!strcasecmp(str, "1M"))
>> -                               qos->phy = 0x01;
>> +                               io_qos.phy = 0x01;
>>                         else if (!strcasecmp(str, "2M"))
>> -                               qos->phy = 0x02;
>> +                               io_qos.phy = 0x02;
>>                         else
>>                                 goto fail;
>>                 } else if (!strcasecmp(key, "SDU")) {
>>                         if (var != DBUS_TYPE_UINT16)
>>                                 goto fail;
>>
>> -                       dbus_message_iter_get_basic(&value, &qos->sdu);
>> +                       dbus_message_iter_get_basic(&value, &io_qos.sdu);
>>                 } else if (!strcasecmp(key, "Retransmissions")) {
>>                         if (var != DBUS_TYPE_BYTE)
>>                                 goto fail;
>>
>> -                       dbus_message_iter_get_basic(&value, &qos->rtn);
>> +                       dbus_message_iter_get_basic(&value, &io_qos.rtn);
>>                 } else if (!strcasecmp(key, "Latency")) {
>>                         if (var != DBUS_TYPE_UINT16)
>>                                 goto fail;
>>
>> -                       dbus_message_iter_get_basic(&value, &qos->latency);
>> +                       dbus_message_iter_get_basic(&value, &io_qos.latency);
>>                 } else if (!strcasecmp(key, "Delay")) {
>>                         if (var != DBUS_TYPE_UINT32)
>>                                 goto fail;
>>
>> -                       dbus_message_iter_get_basic(&value, &qos->delay);
>> +                       dbus_message_iter_get_basic(&value, &qos->ucast.delay);
>>                 } else if (!strcasecmp(key, "TargetLatency")) {
>>                         if (var != DBUS_TYPE_BYTE)
>>                                 goto fail;
>>
>>                         dbus_message_iter_get_basic(&value,
>> -                                                       &qos->target_latency);
>> +                                                       &qos->ucast.target_latency);
>> +               } else if (!strcasecmp(key, "Encryption")) {
>> +                       if (var != DBUS_TYPE_BYTE)
>> +                               goto fail;
>> +
>> +                       dbus_message_iter_get_basic(&value,
>> +                                                       &qos->bcast.encryption);
>> +                       DBG("Got Encryption for bcast");
>> +                       broadcast = true;
>> +               } else if (!strcasecmp(key, "Options")) {
>> +                       if (var != DBUS_TYPE_BYTE)
>> +                               goto fail;
>> +
>> +                       dbus_message_iter_get_basic(&value,
>> +                                                       &qos->bcast.options);
>> +               } else if (!strcasecmp(key, "Skip")) {
>> +                       if (var != DBUS_TYPE_UINT16)
>> +                               goto fail;
>> +
>> +                       dbus_message_iter_get_basic(&value,
>> +                                                       &qos->bcast.skip);
>> +               } else if (!strcasecmp(key, "SyncTimeout")) {
>> +                       if (var != DBUS_TYPE_UINT16)
>> +                               goto fail;
>> +
>> +                       dbus_message_iter_get_basic(&value,
>> +                                                       &qos->bcast.sync_timeout);
>> +               } else if (!strcasecmp(key, "SyncCteType")) {
>> +                       if (var != DBUS_TYPE_BYTE)
>> +                               goto fail;
>> +
>> +                       dbus_message_iter_get_basic(&value,
>> +                                                       &qos->bcast.sync_cte_type);
>> +               } else if (!strcasecmp(key, "MSE")) {
>> +                       if (var != DBUS_TYPE_BYTE)
>> +                               goto fail;
>> +
>> +                       dbus_message_iter_get_basic(&value,
>> +                                                       &qos->bcast.mse);
>> +               } else if (!strcasecmp(key, "Timeout")) {
>> +                       if (var != DBUS_TYPE_UINT16)
>> +                               goto fail;
>> +
>> +                       dbus_message_iter_get_basic(&value,
>> +                                                       &qos->bcast.timeout);
>>                 }
>>
>>                 dbus_message_iter_next(props);
>>         }
>>
>> +       if (broadcast)
>> +               memcpy(&qos->bcast.io_qos, &io_qos, sizeof(io_qos));
>> +       else
>> +               memcpy(&qos->ucast.io_qos, &io_qos, sizeof(io_qos));
>> +
>>         return 0;
>>
>>  fail:
>> @@ -456,8 +531,8 @@ static DBusMessage *set_configuration(DBusConnection *conn, DBusMessage *msg,
>>         }
>>
>>         /* Mark CIG and CIS to be auto assigned */
>> -       ep->qos.cig_id = BT_ISO_QOS_CIG_UNSET;
>> -       ep->qos.cis_id = BT_ISO_QOS_CIS_UNSET;
>> +       ep->qos.ucast.cig_id = BT_ISO_QOS_CIG_UNSET;
>> +       ep->qos.ucast.cis_id = BT_ISO_QOS_CIS_UNSET;
>>
>>         if (parse_properties(&props, &ep->caps, &ep->metadata, &ep->qos) < 0) {
>>                 DBG("Unable to parse properties");
>> @@ -508,6 +583,8 @@ static void ep_free(void *data)
>>
>>         util_iov_free(ep->caps, 1);
>>         util_iov_free(ep->metadata, 1);
>> +       if (bt_bap_stream_get_type(ep->stream) == BT_BAP_STREAM_TYPE_BROADCAST)
>> +               util_iov_free(&ep->qos.bcast.bcode, 1);
>>         free(ep->path);
>>         free(ep);
>>  }
>> @@ -551,6 +628,11 @@ static struct bap_ep *ep_register(struct btd_service *service,
>>                 i = queue_length(data->srcs);
>>                 suffix = "source";
>>                 break;
>> +       case BT_BAP_BROADCAST_SOURCE:
>> +               queue = data->broadcast;
>> +               i = queue_length(data->broadcast);
>> +               suffix = "broadcast";
>> +               break;
>>         default:
>>                 return NULL;
>>         }
>> @@ -609,12 +691,14 @@ static void bap_config(void *data, void *user_data)
>>
>>         ep->id = bt_bap_stream_config(ep->stream, &ep->qos, ep->caps,
>>                                                 config_cb, ep);
>> -       if (!ep->id) {
>> -               DBG("Unable to config stream");
>> -               util_iov_free(ep->caps, 1);
>> -               ep->caps = NULL;
>> -               util_iov_free(ep->metadata, 1);
>> -               ep->metadata = NULL;
>> +       if (bt_bap_stream_get_type(ep->stream) == BT_BAP_STREAM_TYPE_UNICAST) {
>> +               if (!ep->id) {
>> +                       DBG("Unable to config stream");
>> +                       util_iov_free(ep->caps, 1);
>> +                       ep->caps = NULL;
>> +                       util_iov_free(ep->metadata, 1);
>> +                       ep->metadata = NULL;
>> +               }
>>         }
>>
>>         bt_bap_stream_set_user_data(ep->stream, ep->path);
>> @@ -650,6 +734,7 @@ done:
>>
>>         queue_foreach(ep->data->srcs, bap_config, NULL);
>>         queue_foreach(ep->data->snks, bap_config, NULL);
>> +       queue_foreach(ep->data->broadcast, bap_config, NULL);
>>  }
>>
>>  static bool pac_found(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
>> @@ -666,8 +751,13 @@ static bool pac_found(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
>>                 return true;
>>         }
>>
>> -       /* TODO: Cache LRU? */
>> -       if (btd_service_is_initiator(service)) {
>> +       if (bt_bap_pac_get_type(lpac) != BT_BAP_BROADCAST_SOURCE) {
>> +               /* TODO: Cache LRU? */
>> +               if (btd_service_is_initiator(service)) {
>> +                       if (!bt_bap_select(lpac, rpac, select_cb, ep))
>> +                               ep->data->selecting++;
>> +                       }
>> +       } else {
>>                 if (!bt_bap_select(lpac, rpac, select_cb, ep))
>>                         ep->data->selecting++;
>>         }
>> @@ -698,11 +788,17 @@ static struct bap_ep *bap_find_ep_by_stream(struct bap_data *data,
>>  {
>>         struct bap_ep *ep;
>>
>> -       ep = queue_find(data->snks, match_ep_by_stream, stream);
>> -       if (ep)
>> -               return ep;
>> +       if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_UNICAST) {
>> +               ep = queue_find(data->snks, match_ep_by_stream, stream);
>> +               if (ep)
>> +                       return ep;
>>
>> -       return queue_find(data->srcs, match_ep_by_stream, stream);
>> +               return queue_find(data->srcs, match_ep_by_stream, stream);
>> +       } else if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST) {
>> +
>> +               return queue_find(data->broadcast, match_ep_by_stream, stream);
>> +       } else
>> +               return NULL;
>>  }
>>
>>  static void iso_connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
>> @@ -734,11 +830,11 @@ static void bap_iso_qos(struct bt_bap_qos *qos, struct bt_iso_io_qos *io)
>>         if (!qos)
>>                 return;
>>
>> -       io->interval = qos->interval;
>> -       io->latency = qos->latency;
>> -       io->sdu = qos->sdu;
>> -       io->phy = qos->phy;
>> -       io->rtn = qos->rtn;
>> +       io->interval = qos->ucast.io_qos.interval;
>> +       io->latency = qos->ucast.io_qos.latency;
>> +       io->sdu = qos->ucast.io_qos.sdu;
>> +       io->phy = qos->ucast.io_qos.phy;
>> +       io->rtn = qos->ucast.io_qos.rtn;
>>  }
>>
>>  static bool match_stream_qos(const void *data, const void *user_data)
>> @@ -749,10 +845,10 @@ static bool match_stream_qos(const void *data, const void *user_data)
>>
>>         qos = bt_bap_stream_get_qos((void *)stream);
>>
>> -       if (iso_qos->ucast.cig != qos->cig_id)
>> +       if (iso_qos->ucast.cig != qos->ucast.cig_id)
>>                 return false;
>>
>> -       return iso_qos->ucast.cis == qos->cis_id;
>> +       return iso_qos->ucast.cis == qos->ucast.cis_id;
>>  }
>>
>>  static void iso_confirm_cb(GIOChannel *io, void *user_data)
>> @@ -941,6 +1037,70 @@ static void bap_connect_io(struct bap_data *data, struct bap_ep *ep,
>>         bt_bap_stream_io_connecting(stream, g_io_channel_unix_get_fd(io));
>>  }
>>
>> +static void bap_connect_io_broadcast(struct bap_data *data, struct bap_ep *ep,
>> +                               struct bt_bap_stream *stream,
>> +                               struct bt_iso_qos *qos, int defer)
>> +{
>> +       struct btd_adapter *adapter = device_get_adapter(data->device);
>> +       GIOChannel *io = NULL;
>> +       GError *err = NULL;
>> +       bdaddr_t dst_addr = {0};
>> +       char addr[18];
>> +       struct bt_iso_base base;
>> +
>> +       /* If IO already set and we are in the creation step, skip creating it again */
>> +       if (bt_bap_stream_get_io(stream) && (defer == true))
>> +               return;
>> +
>> +       if (ep->io_id) {
>> +               g_source_remove(ep->io_id);
>> +               ep->io_id = 0;
>> +       }
>> +       base.base_len = ep->caps->iov_len;
>> +
>> +       memset(base.base, 0, 248);
>> +       memcpy(base.base, ep->caps->iov_base, base.base_len);
>> +       DBG("ep %p stream %p defer %s", ep, stream, defer ? "true" : "false");
>> +       ba2str(btd_adapter_get_address(adapter), addr);
>> +
>> +       /* Just create socket and advance to the configured state (when defer = true) */
>> +       if (defer == true) {
>> +               io = bt_io_connect(bap_connect_io_cb, ep, NULL, &err,
>> +                               BT_IO_OPT_SOURCE_BDADDR,
>> +                               btd_adapter_get_address(adapter),
>> +                               BT_IO_OPT_DEST_BDADDR,
>> +                               &dst_addr,
>> +                               BT_IO_OPT_DEST_TYPE,
>> +                               BDADDR_LE_PUBLIC,
>> +                               BT_IO_OPT_MODE, BT_IO_MODE_ISO,
>> +                               BT_IO_OPT_QOS, qos,
>> +                               BT_IO_OPT_BASE, &base,
>> +                               BT_IO_OPT_DEFER_TIMEOUT, defer,
>> +                               BT_IO_OPT_INVALID);
>> +
>> +               if (!io) {
>> +                       error("%s", err->message);
>> +                       g_error_free(err);
>> +                       return;
>> +               }
>> +
>> +               ep->io_id = g_io_add_watch(io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
>> +                               bap_io_disconnected, ep);
>> +
>> +               ep->io = io;
>> +
>> +               bt_bap_stream_io_connecting(stream, g_io_channel_unix_get_fd(io));
>> +       } else { /* Advance stream state to Streaming */
>> +               io = ep->io;
>> +//             de-comment when streaming state is working in kernel
>> +//             bt_io_broadcast_stream(&err, g_io_channel_unix_get_fd(io),
>> +//                             BT_IO_OPT_DEST_BDADDR, device_get_address(ep->data->device),
>> +//                             BT_IO_OPT_DEST_TYPE, device_get_le_address_type(ep->data->device),
>> +//                             BT_IO_OPT_QOS, qos,
>> +//                             BT_IO_OPT_INVALID);
>
>If code is not ready then Id just remove it and leave a TODO.

We will update this in the next patch.

>
>> +       }
>> +}
>> +
>>  static void bap_listen_io(struct bap_data *data, struct bt_bap_stream *stream,
>>                                                 struct bt_iso_qos *qos)
>>  {
>> @@ -987,20 +1147,44 @@ static void bap_create_io(struct bap_data *data, struct bap_ep *ep,
>>         if (!queue_find(data->streams, NULL, stream))
>>                 queue_push_tail(data->streams, stream);
>>
>> -       if (!bt_bap_stream_io_get_qos(stream, &qos[0], &qos[1])) {
>> -               error("bt_bap_stream_get_qos_links: failed");
>> -               return;
>> +       if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_UNICAST) {
>> +               if (!bt_bap_stream_io_get_qos(stream, &qos[0], &qos[1])) {
>> +                       error("bt_bap_stream_get_qos_links: failed");
>> +                       return;
>> +               }
>>         }
>>
>>         memset(&iso_qos, 0, sizeof(iso_qos));
>> -       iso_qos.ucast.cig = qos[0] ? qos[0]->cig_id : qos[1]->cig_id;
>> -       iso_qos.ucast.cis = qos[0] ? qos[0]->cis_id : qos[1]->cis_id;
>> +       if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST) {
>> +               if (defer == true) {
>> +                       iso_qos.bcast.big = ep->qos.bcast.big;
>> +                       iso_qos.bcast.bis = ep->qos.bcast.bis;
>> +                       iso_qos.bcast.sync_interval = ep->qos.bcast.sync_interval;
>> +                       iso_qos.bcast.packing = ep->qos.bcast.packing;
>> +                       iso_qos.bcast.framing = ep->qos.bcast.framing;
>> +                       iso_qos.bcast.encryption = ep->qos.bcast.encryption;
>> +                       memcpy(iso_qos.bcast.bcode, ep->qos.bcast.bcode.iov_base, 16);
>> +                       iso_qos.bcast.options = ep->qos.bcast.options;
>> +                       iso_qos.bcast.skip = ep->qos.bcast.skip;
>> +                       iso_qos.bcast.sync_timeout = ep->qos.bcast.sync_timeout;
>> +                       iso_qos.bcast.sync_cte_type = ep->qos.bcast.sync_cte_type;
>> +                       iso_qos.bcast.mse = ep->qos.bcast.mse;
>> +                       iso_qos.bcast.timeout = ep->qos.bcast.timeout;
>> +                       memcpy(&iso_qos.bcast.out, &ep->qos.bcast.io_qos, sizeof(struct bt_iso_io_qos));
>> +               }
>> +       } else {
>> +               iso_qos.ucast.cig = qos[0] ? qos[0]->ucast.cig_id : qos[1]->ucast.cig_id;
>> +               iso_qos.ucast.cis = qos[0] ? qos[0]->ucast.cis_id : qos[1]->ucast.cis_id;
>>
>> -       bap_iso_qos(qos[0], &iso_qos.ucast.in);
>> -       bap_iso_qos(qos[1], &iso_qos.ucast.out);
>> +               bap_iso_qos(qos[0], &iso_qos.ucast.in);
>> +               bap_iso_qos(qos[1], &iso_qos.ucast.out);
>> +       }
>>
>>         if (ep)
>> -               bap_connect_io(data, ep, stream, &iso_qos, defer);
>> +               if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST)
>> +                       bap_connect_io_broadcast(data, ep, stream, &iso_qos, defer);
>> +               else
>> +                       bap_connect_io(data, ep, stream, &iso_qos, defer);
>>         else
>>                 bap_listen_io(data, stream, &iso_qos);
>>  }
>> @@ -1039,12 +1223,14 @@ static void bap_state(struct bt_bap_stream *stream, uint8_t old_state,
>>                         }
>>
>>
>> -                       /* Wait QoS response to respond */
>> -                       ep->id = bt_bap_stream_qos(stream, &ep->qos, qos_cb,
>> -                                                                       ep);
>> -                       if (!ep->id) {
>> -                               error("Failed to Configure QoS");
>> -                               bt_bap_stream_release(stream, NULL, NULL);
>> +                       if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_UNICAST) {
>> +                               /* Wait QoS response to respond */
>> +                               ep->id = bt_bap_stream_qos(stream, &ep->qos, qos_cb,
>> +                                                                               ep);
>> +                               if (!ep->id) {
>> +                                       error("Failed to Configure QoS");
>> +                                       bt_bap_stream_release(stream, NULL, NULL);
>> +                               }
>>                         }
>>                 }
>>                 break;
>> @@ -1055,6 +1241,12 @@ static void bap_state(struct bt_bap_stream *stream, uint8_t old_state,
>>                 if (ep)
>>                         bap_create_io(data, ep, stream, false);
>>                 break;
>> +       case BT_BAP_STREAM_STATE_STREAMING:
>> +               if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST) {
>> +                       if (ep)
>> +                               bap_create_io(data, ep, stream, false);
>> +               }
>> +               break;
>>         }
>>  }
>>
>> @@ -1074,6 +1266,20 @@ static void pac_added(struct bt_bap_pac *pac, void *user_data)
>>         bt_bap_foreach_pac(data->bap, BT_BAP_SINK, pac_found, service);
>>  }
>>
>> +static void pac_added_broadcast(struct bt_bap_pac *pac, void *user_data)
>> +{
>> +       struct btd_service *service = user_data;
>> +       struct bap_data *data;
>> +
>> +       if (bt_bap_pac_get_type(pac) == BT_BAP_BROADCAST_SOURCE) {
>> +               DBG("pac %p", pac);
>> +
>> +               data = btd_service_get_user_data(service);
>> +
>> +               bt_bap_foreach_pac(data->bap, BT_BAP_BROADCAST_SOURCE, pac_found, service);
>> +       }
>> +}
>> +
>>  static bool ep_match_pac(const void *data, const void *match_data)
>>  {
>>         const struct bap_ep *ep = data;
>> @@ -1114,6 +1320,38 @@ static void pac_removed(struct bt_bap_pac *pac, void *user_data)
>>         ep_unregister(ep);
>>  }
>>
>> +static void pac_removed_broadcast(struct bt_bap_pac *pac, void *user_data)
>> +{
>> +       struct btd_service *service = user_data;
>> +       struct bap_data *data;
>> +       struct queue *queue;
>> +       struct bap_ep *ep;
>> +
>> +       DBG("pac %p", pac);
>> +
>> +       data = btd_service_get_user_data(service);
>> +
>> +       switch (bt_bap_pac_get_type(pac)) {
>> +       case BT_BAP_SINK:
>> +               queue = data->srcs;
>> +               break;
>> +       case BT_BAP_SOURCE:
>> +               queue = data->snks;
>> +               break;
>> +       case BT_BAP_BROADCAST_SOURCE:
>> +               queue = data->broadcast;
>> +               break;
>> +       default:
>> +               return;
>> +       }
>> +
>> +       ep = queue_remove_if(queue, ep_match_pac, pac);
>> +       if (!ep)
>> +               return;
>> +
>> +       ep_unregister(ep);
>> +}
>> +
>>  static struct bap_data *bap_data_new(struct btd_device *device)
>>  {
>>         struct bap_data *data;
>> @@ -1122,6 +1360,7 @@ static struct bap_data *bap_data_new(struct btd_device *device)
>>         data->device = device;
>>         data->srcs = queue_new();
>>         data->snks = queue_new();
>> +       data->broadcast = queue_new();
>>
>>         return data;
>>  }
>> @@ -1154,6 +1393,14 @@ static bool match_data(const void *data, const void *match_data)
>>         return bdata->bap == bap;
>>  }
>>
>> +static bool match_data_bap_data(const void *data, const void *match_data)
>> +{
>> +       const struct bap_data *bdata = data;
>> +       const struct btd_adapter *adapter = match_data;
>> +
>> +       return bdata->user_data == adapter;
>> +}
>> +
>>  static void bap_connecting(struct bt_bap_stream *stream, bool state, int fd,
>>                                                         void *user_data)
>>  {
>> @@ -1178,26 +1425,49 @@ static void bap_connecting(struct bt_bap_stream *stream, bool state, int fd,
>>
>>         g_io_channel_set_close_on_unref(io, FALSE);
>>
>> -       /* Attempt to get CIG/CIS if they have not been set */
>> -       if (ep->qos.cig_id == BT_ISO_QOS_CIG_UNSET ||
>> -                               ep->qos.cis_id == BT_ISO_QOS_CIS_UNSET) {
>> -               struct bt_iso_qos qos;
>> -               GError *err = NULL;
>> +       if (bt_bap_stream_get_type(ep->stream) == BT_BAP_STREAM_TYPE_UNICAST) {
>> +               /* Attempt to get CIG/CIS if they have not been set */
>> +               if (ep->qos.ucast.cig_id == BT_ISO_QOS_CIG_UNSET ||
>> +                                       ep->qos.ucast.cis_id == BT_ISO_QOS_CIS_UNSET) {
>> +                       struct bt_iso_qos qos;
>> +                       GError *err = NULL;
>> +
>> +                       if (!bt_io_get(io, &err, BT_IO_OPT_QOS, &qos,
>> +                                               BT_IO_OPT_INVALID)) {
>> +                               error("%s", err->message);
>> +                               g_error_free(err);
>> +                               g_io_channel_unref(io);
>> +                               return;
>> +                       }
>>
>> -               if (!bt_io_get(io, &err, BT_IO_OPT_QOS, &qos,
>> -                                       BT_IO_OPT_INVALID)) {
>> -                       error("%s", err->message);
>> -                       g_error_free(err);
>> -                       g_io_channel_unref(io);
>> -                       return;
>> +                       ep->qos.ucast.cig_id = qos.ucast.cig;
>> +                       ep->qos.ucast.cis_id = qos.ucast.cis;
>>                 }
>>
>> -               ep->qos.cig_id = qos.ucast.cig;
>> -               ep->qos.cis_id = qos.ucast.cis;
>> -       }
>> +               DBG("stream %p fd %d: CIG 0x%02x CIS 0x%02x", stream, fd,
>> +                                               ep->qos.ucast.cig_id, ep->qos.ucast.cis_id);
>> +       } else if (bt_bap_stream_get_type(ep->stream) == BT_BAP_STREAM_TYPE_BROADCAST) {
>> +               /* Attempt to get BIG/BIS if they have not been set */
>> +               if (ep->qos.bcast.big == BT_ISO_QOS_BIG_UNSET ||
>> +                                       ep->qos.bcast.bis == BT_ISO_QOS_BIS_UNSET) {
>> +                       struct bt_iso_qos qos;
>> +                       GError *err = NULL;
>> +
>> +                       if (!bt_io_get(io, &err, BT_IO_OPT_QOS, &qos,
>> +                                               BT_IO_OPT_INVALID)) {
>> +                               error("%s", err->message);
>> +                               g_error_free(err);
>> +                               g_io_channel_unref(io);
>> +                               return;
>> +                       }
>> +
>> +                       ep->qos.bcast.big = qos.bcast.big;
>> +                       ep->qos.bcast.bis = qos.bcast.bis;
>> +               }
>>
>> -       DBG("stream %p fd %d: CIG 0x%02x CIS 0x%02x", stream, fd,
>> -                                       ep->qos.cig_id, ep->qos.cis_id);
>> +               DBG("stream %p fd %d: BIG 0x%02x BIS 0x%02x", stream, fd,
>> +                                               ep->qos.bcast.big, ep->qos.bcast.bis);
>> +       }
>>  }
>>
>>  static void bap_attached(struct bt_bap *bap, void *user_data)
>> @@ -1345,6 +1615,68 @@ static int bap_disconnect(struct btd_service *service)
>>         return 0;
>>  }
>>
>> +static int bap_adapter_probe(struct btd_profile *p,
>> +                               struct btd_adapter *adapter)
>> +{
>> +       struct btd_device *device = btd_adapter_get_device(adapter, BDADDR_ANY, BDADDR_LE_PUBLIC);
>> +       struct btd_gatt_database *database = btd_adapter_get_database(adapter);
>> +       struct btd_service *service = service_create(device, p);
>> +       struct bap_data *data;
>> +       char addr[18];
>> +
>> +       ba2str(device_get_address(device), addr);
>> +       DBG("%s", addr);
>> +
>> +       if (!btd_adapter_has_exp_feature(adapter, EXP_FEAT_ISO_SOCKET)) {
>> +               error("BAP requires ISO Socket which is not enabled");
>> +               return -ENOTSUP;
>> +       }
>> +
>> +       data = bap_data_new(device);
>> +       data->service = service;
>> +
>> +       data->bap = bt_bap_new(btd_gatt_database_get_db(database),
>> +                                       btd_device_get_gatt_db(device));
>> +       if (!data->bap) {
>> +               error("Unable to create BAP instance");
>> +               free(data);
>> +               return -EINVAL;
>> +       }
>> +
>> +       bap_data_add(data);
>> +
>> +       if (!bt_bap_attach_broadcast(data->bap)) {
>> +               error("BAP unable to attach");
>> +               return -EINVAL;
>> +       }
>> +
>> +       data->state_id = bt_bap_state_register(data->bap, bap_state,
>> +                                               bap_connecting, data, NULL);
>> +       data->pac_id = bt_bap_pac_register(data->bap, pac_added_broadcast,
>> +                                               pac_removed_broadcast, service, NULL);
>> +
>> +       bt_bap_set_user_data(data->bap, service);
>> +       bap_data_set_user_data(data, adapter);
>> +       return 0;
>> +}
>> +
>> +static void bap_adapter_remove(struct btd_profile *p,
>> +                                       struct btd_adapter *adapter)
>> +{
>> +       struct bap_data *data = queue_find(sessions, match_data_bap_data, adapter);
>> +       char addr[18];
>> +
>> +       ba2str(btd_adapter_get_address(adapter), addr);
>> +       DBG("%s", addr);
>> +
>> +       if (!data) {
>> +               error("BAP service not handled by profile");
>> +               return;
>> +       }
>> +
>> +       bap_data_remove(data);
>> +}
>> +
>>  static struct btd_profile bap_profile = {
>>         .name           = "bap",
>>         .priority       = BTD_PROFILE_PRIORITY_MEDIUM,
>> @@ -1353,6 +1685,8 @@ static struct btd_profile bap_profile = {
>>         .device_remove  = bap_remove,
>>         .accept         = bap_accept,
>>         .disconnect     = bap_disconnect,
>> +       .adapter_probe  = bap_adapter_probe,
>> +       .adapter_remove = bap_adapter_remove,
>>         .auto_connect   = true,
>>  };
>>
>> diff --git a/profiles/audio/media.c b/profiles/audio/media.c
>> index 6ce668e31..4c7402fe9 100644
>> --- a/profiles/audio/media.c
>> +++ b/profiles/audio/media.c
>> @@ -6,7 +6,7 @@
>>   *  Copyright (C) 2006-2007  Nokia Corporation
>>   *  Copyright (C) 2004-2009  Marcel Holtmann <marcel@holtmann.org>
>>   *  Copyright (C) 2011  BMW Car IT GmbH. All rights reserved.
>> - *
>> + *  Copyright 2023 NXP
>>   *
>>   */
>>
>> @@ -748,7 +748,11 @@ static int parse_select_properties(DBusMessageIter *props, struct iovec *caps,
>>                                         struct bt_bap_qos *qos)
>>  {
>>         const char *key;
>> +       struct bt_bap_io_qos io_qos;
>> +       uint8_t framing = 0;
>> +       bool broadcast = false;
>>
>> +       memset(&io_qos, 0, sizeof(io_qos));
>>         while (dbus_message_iter_get_arg_type(props) == DBUS_TYPE_DICT_ENTRY) {
>>                 DBusMessageIter value, entry;
>>                 int var;
>> @@ -777,17 +781,27 @@ static int parse_select_properties(DBusMessageIter *props, struct iovec *caps,
>>                         if (var != DBUS_TYPE_BYTE)
>>                                 goto fail;
>>
>> -                       dbus_message_iter_get_basic(&value, &qos->cig_id);
>> +                       dbus_message_iter_get_basic(&value, &qos->ucast.cig_id);
>> +               } else if (!strcasecmp(key, "BIG")) {
>> +                       if (var != DBUS_TYPE_BYTE)
>> +                               goto fail;
>> +
>> +                       dbus_message_iter_get_basic(&value, &qos->bcast.big);
>>                 } else if (!strcasecmp(key, "CIS")) {
>>                         if (var != DBUS_TYPE_BYTE)
>>                                 goto fail;
>>
>> -                       dbus_message_iter_get_basic(&value, &qos->cis_id);
>> +                       dbus_message_iter_get_basic(&value, &qos->ucast.cig_id);
>> +               } else if (!strcasecmp(key, "BIS")) {
>> +                       if (var != DBUS_TYPE_BYTE)
>> +                               goto fail;
>> +
>> +                       dbus_message_iter_get_basic(&value, &qos->bcast.bis);
>>                 } else if (!strcasecmp(key, "Interval")) {
>>                         if (var != DBUS_TYPE_UINT32)
>>                                 goto fail;
>>
>> -                       dbus_message_iter_get_basic(&value, &qos->interval);
>> +                       dbus_message_iter_get_basic(&value, &io_qos.interval);
>>                 } else if (!strcasecmp(key, "Framing")) {
>>                         dbus_bool_t val;
>>
>> @@ -796,7 +810,7 @@ static int parse_select_properties(DBusMessageIter *props, struct iovec *caps,
>>
>>                         dbus_message_iter_get_basic(&value, &val);
>>
>> -                       qos->framing = val;
>> +                       framing = val;
>>                 } else if (!strcasecmp(key, "PHY")) {
>>                         const char *str;
>>
>> @@ -806,42 +820,106 @@ static int parse_select_properties(DBusMessageIter *props, struct iovec *caps,
>>                         dbus_message_iter_get_basic(&value, &str);
>>
>>                         if (!strcasecmp(str, "1M"))
>> -                               qos->phy = 0x01;
>> +                               io_qos.phy = 0x01;
>>                         else if (!strcasecmp(str, "2M"))
>> -                               qos->phy = 0x02;
>> +                               io_qos.phy = 0x02;
>>                         else
>>                                 goto fail;
>>                 } else if (!strcasecmp(key, "SDU")) {
>>                         if (var != DBUS_TYPE_UINT16)
>>                                 goto fail;
>>
>> -                       dbus_message_iter_get_basic(&value, &qos->sdu);
>> +                       dbus_message_iter_get_basic(&value, &io_qos.sdu);
>>                 } else if (!strcasecmp(key, "Retransmissions")) {
>>                         if (var != DBUS_TYPE_BYTE)
>>                                 goto fail;
>>
>> -                       dbus_message_iter_get_basic(&value, &qos->rtn);
>> +                       dbus_message_iter_get_basic(&value, &io_qos.rtn);
>>                 } else if (!strcasecmp(key, "Latency")) {
>>                         if (var != DBUS_TYPE_UINT16)
>>                                 goto fail;
>>
>> -                       dbus_message_iter_get_basic(&value, &qos->latency);
>> +                       dbus_message_iter_get_basic(&value, &io_qos.latency);
>>                 } else if (!strcasecmp(key, "Delay")) {
>>                         if (var != DBUS_TYPE_UINT32)
>>                                 goto fail;
>>
>> -                       dbus_message_iter_get_basic(&value, &qos->delay);
>> +                       dbus_message_iter_get_basic(&value, &qos->ucast.delay);
>>                 } else if (!strcasecmp(key, "TargetLatency")) {
>>                         if (var != DBUS_TYPE_BYTE)
>>                                 goto fail;
>>
>>                         dbus_message_iter_get_basic(&value,
>> -                                                       &qos->target_latency);
>> +                                                       &qos->ucast.target_latency);
>> +               } else if (!strcasecmp(key, "Encryption")) {
>> +                       if (var != DBUS_TYPE_BYTE)
>> +                               goto fail;
>> +
>> +                       dbus_message_iter_get_basic(&value,
>> +                                                       &qos->bcast.encryption);
>> +                       broadcast = true;
>> +               } else if (!strcasecmp(key, "Options")) {
>> +                       if (var != DBUS_TYPE_BYTE)
>> +                               goto fail;
>> +
>> +                       dbus_message_iter_get_basic(&value,
>> +                                                       &qos->bcast.options);
>> +               } else if (!strcasecmp(key, "Skip")) {
>> +                       if (var != DBUS_TYPE_UINT16)
>> +                               goto fail;
>> +
>> +                       dbus_message_iter_get_basic(&value,
>> +                                                       &qos->bcast.skip);
>> +               } else if (!strcasecmp(key, "SyncTimeout")) {
>> +                       if (var != DBUS_TYPE_UINT16)
>> +                               goto fail;
>> +
>> +                       dbus_message_iter_get_basic(&value,
>> +                                                       &qos->bcast.sync_timeout);
>> +               } else if (!strcasecmp(key, "SyncCteType")) {
>> +                       if (var != DBUS_TYPE_BYTE)
>> +                               goto fail;
>> +
>> +                       dbus_message_iter_get_basic(&value,
>> +                                                       &qos->bcast.sync_cte_type);
>> +
>> +               } else if (!strcasecmp(key, "SyncInterval")) {
>> +                       if (var != DBUS_TYPE_BYTE)
>> +                               goto fail;
>> +
>> +                       dbus_message_iter_get_basic(&value,
>> +                                                       &qos->bcast.sync_interval);
>> +               } else if (!strcasecmp(key, "MSE")) {
>> +                       if (var != DBUS_TYPE_BYTE)
>> +                               goto fail;
>> +
>> +                       dbus_message_iter_get_basic(&value,
>> +                                                       &qos->bcast.mse);
>> +               } else if (!strcasecmp(key, "Timeout")) {
>> +                       if (var != DBUS_TYPE_UINT16)
>> +                               goto fail;
>> +
>> +                       dbus_message_iter_get_basic(&value,
>> +                                                       &qos->bcast.timeout);
>> +               } else if (!strcasecmp(key, "BroadcastCode")) {
>> +                       if (var != DBUS_TYPE_ARRAY)
>> +                               goto fail;
>> +
>> +                       parse_array(&value, &qos->bcast.bcode);
>>                 }
>>
>>                 dbus_message_iter_next(props);
>>         }
>>
>> +       if (broadcast) {
>> +               memcpy(&qos->bcast.io_qos, &io_qos, sizeof(io_qos));
>> +               qos->bcast.framing = framing;
>> +
>> +       } else {
>> +               memcpy(&qos->ucast.io_qos, &io_qos, sizeof(io_qos));
>> +               qos->ucast.framing = framing;
>> +       }
>> +
>>         return 0;
>>
>>  fail:
>> @@ -875,8 +953,8 @@ static void pac_select_cb(struct media_endpoint *endpoint, void *ret, int size,
>>         memset(&qos, 0, sizeof(qos));
>>
>>         /* Mark CIG and CIS to be auto assigned */
>> -       qos.cig_id = BT_ISO_QOS_CIG_UNSET;
>> -       qos.cis_id = BT_ISO_QOS_CIS_UNSET;
>> +       qos.ucast.cig_id = BT_ISO_QOS_CIG_UNSET;
>> +       qos.ucast.cis_id = BT_ISO_QOS_CIS_UNSET;
>>
>>         memset(&caps, 0, sizeof(caps));
>>         memset(&meta, 0, sizeof(meta));
>> @@ -1166,15 +1244,13 @@ static bool endpoint_init_pac(struct media_endpoint *endpoint, uint8_t type,
>>
>>         endpoint->pac = bt_bap_add_vendor_pac(db, name, type, endpoint->codec,
>>                                 endpoint->cid, endpoint->vid, &endpoint->qos,
>> -                               &data, metadata);
>> +                               &data, metadata, &pac_ops, endpoint);
>>         if (!endpoint->pac) {
>>                 error("Unable to create PAC");
>>                 free(metadata);
>>                 return false;
>>         }
>>
>> -       bt_bap_pac_set_ops(endpoint->pac, &pac_ops, endpoint);
>> -
>>         DBG("PAC %s registered", name);
>>
>>         free(name);
>> @@ -1193,6 +1269,11 @@ static bool endpoint_init_pac_source(struct media_endpoint *endpoint, int *err)
>>         return endpoint_init_pac(endpoint, BT_BAP_SOURCE, err);
>>  }
>>
>> +static bool endpoint_init_broadcast_source(struct media_endpoint *endpoint, int *err)
>> +{
>> +       return endpoint_init_pac(endpoint, BT_BAP_BROADCAST_SOURCE, err);
>> +}
>> +
>>  static bool endpoint_properties_exists(const char *uuid,
>>                                                 struct btd_device *dev,
>>                                                 void *user_data)
>> @@ -1295,6 +1376,18 @@ static bool experimental_endpoint_supported(struct btd_adapter *adapter)
>>         return g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL;
>>  }
>>
>> +static bool experimental_broadcaster_ep_supported(struct btd_adapter *adapter)
>> +{
>> +
>> +       if (!btd_adapter_has_exp_feature(adapter, EXP_FEAT_ISO_SOCKET))
>> +               return false;
>> +
>> +       if (!btd_adapter_has_settings(adapter, MGMT_SETTING_ISO_BROADCASTER))
>> +               return false;
>> +
>> +       return g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL;
>> +}
>> +
>>  static struct media_endpoint_init {
>>         const char *uuid;
>>         bool (*func)(struct media_endpoint *endpoint, int *err);
>> @@ -1308,6 +1401,8 @@ static struct media_endpoint_init {
>>                                 experimental_endpoint_supported },
>>         { PAC_SOURCE_UUID, endpoint_init_pac_source,
>>                                 experimental_endpoint_supported },
>> +       { BROADCAST_AUDIO_ANNOUNCEMENT_SERVICE_UUID, endpoint_init_broadcast_source,
>> +                       experimental_broadcaster_ep_supported },
>>  };
>>
>>  static struct media_endpoint *
>> diff --git a/profiles/audio/transport.c b/profiles/audio/transport.c
>> index 9172d167e..a055e4f05 100644
>> --- a/profiles/audio/transport.c
>> +++ b/profiles/audio/transport.c
>> @@ -5,6 +5,7 @@
>>   *
>>   *  Copyright (C) 2006-2007  Nokia Corporation
>>   *  Copyright (C) 2004-2009  Marcel Holtmann <marcel@holtmann.org>
>> + *  Copyright 2023 NXP
>>   *
>>   *
>>   */
>> @@ -525,6 +526,13 @@ static void media_owner_add(struct media_owner *owner,
>>         owner->pending = req;
>>  }
>>
>> +static void *get_stream_bap(struct media_transport *transport)
>> +{
>> +       struct bap_transport *bap = transport->data;
>> +
>> +       return bap->stream;
>> +}
>> +
>>  static DBusMessage *acquire(DBusConnection *conn, DBusMessage *msg,
>>                                         void *data)
>>  {
>> @@ -540,15 +548,22 @@ static DBusMessage *acquire(DBusConnection *conn, DBusMessage *msg,
>>                 return btd_error_not_authorized(msg);
>>
>>         owner = media_owner_create(msg);
>> +       if (bt_bap_stream_get_type(get_stream_bap(transport)) == BT_BAP_STREAM_TYPE_BROADCAST) {
>> +               req = media_request_create(msg, 0x00);
>> +               media_owner_add(owner, req);
>> +               media_transport_set_owner(transport, owner);
>> +       }
>>         id = transport->resume(transport, owner);
>>         if (id == 0) {
>>                 media_owner_free(owner);
>>                 return btd_error_not_authorized(msg);
>>         }
>>
>> -       req = media_request_create(msg, id);
>> -       media_owner_add(owner, req);
>> -       media_transport_set_owner(transport, owner);
>> +       if (bt_bap_stream_get_type(get_stream_bap(transport)) == BT_BAP_STREAM_TYPE_UNICAST) {
>> +               req = media_request_create(msg, id);
>> +               media_owner_add(owner, req);
>> +               media_transport_set_owner(transport, owner);
>> +       }
>>
>>         return NULL;
>>  }
>> @@ -828,7 +843,7 @@ static gboolean qos_exists(const GDBusPropertyTable *property, void *data)
>>         struct media_transport *transport = data;
>>         struct bap_transport *bap = transport->data;
>>
>> -       return bap->qos.phy != 0x00;
>> +       return bap->qos.ucast.io_qos.phy != 0x00;
>>  }
>>
>>  static gboolean get_cig(const GDBusPropertyTable *property,
>> @@ -838,7 +853,7 @@ static gboolean get_cig(const GDBusPropertyTable *property,
>>         struct bap_transport *bap = transport->data;
>>
>>         dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE,
>> -                                                       &bap->qos.cig_id);
>> +                                                       &bap->qos.ucast.cig_id);
>>
>>         return TRUE;
>>  }
>> @@ -850,7 +865,7 @@ static gboolean get_cis(const GDBusPropertyTable *property,
>>         struct bap_transport *bap = transport->data;
>>
>>         dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE,
>> -                                                       &bap->qos.cis_id);
>> +                                                       &bap->qos.ucast.cis_id);
>>
>>         return TRUE;
>>  }
>> @@ -862,7 +877,7 @@ static gboolean get_interval(const GDBusPropertyTable *property,
>>         struct bap_transport *bap = transport->data;
>>
>>         dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32,
>> -                                                       &bap->qos.interval);
>> +                                                       &bap->qos.ucast.io_qos.interval);
>>
>>         return TRUE;
>>  }
>> @@ -872,7 +887,7 @@ static gboolean get_framing(const GDBusPropertyTable *property,
>>  {
>>         struct media_transport *transport = data;
>>         struct bap_transport *bap = transport->data;
>> -       dbus_bool_t val = bap->qos.framing;
>> +       dbus_bool_t val = bap->qos.ucast.framing;
>>
>>         dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &val);
>>
>> @@ -885,7 +900,7 @@ static gboolean get_phy(const GDBusPropertyTable *property,
>>         struct media_transport *transport = data;
>>         struct bap_transport *bap = transport->data;
>>
>> -       dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &bap->qos.phy);
>> +       dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &bap->qos.ucast.io_qos.phy);
>>
>>         return TRUE;
>>  }
>> @@ -896,7 +911,7 @@ static gboolean get_sdu(const GDBusPropertyTable *property,
>>         struct media_transport *transport = data;
>>         struct bap_transport *bap = transport->data;
>>
>> -       dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &bap->qos.sdu);
>> +       dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &bap->qos.ucast.io_qos.sdu);
>>
>>         return TRUE;
>>  }
>> @@ -907,7 +922,7 @@ static gboolean get_retransmissions(const GDBusPropertyTable *property,
>>         struct media_transport *transport = data;
>>         struct bap_transport *bap = transport->data;
>>
>> -       dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &bap->qos.rtn);
>> +       dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &bap->qos.ucast.io_qos.rtn);
>>
>>         return TRUE;
>>  }
>> @@ -919,7 +934,7 @@ static gboolean get_latency(const GDBusPropertyTable *property,
>>         struct bap_transport *bap = transport->data;
>>
>>         dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
>> -                                                       &bap->qos.latency);
>> +                                                       &bap->qos.ucast.io_qos.latency);
>>
>>         return TRUE;
>>  }
>> @@ -930,7 +945,7 @@ static gboolean get_delay(const GDBusPropertyTable *property,
>>         struct media_transport *transport = data;
>>         struct bap_transport *bap = transport->data;
>>
>> -       dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &bap->qos.delay);
>> +       dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &bap->qos.ucast.delay);
>>
>>         return TRUE;
>>  }
>> @@ -1478,13 +1493,6 @@ static void bap_connecting(struct bt_bap_stream *stream, bool state, int fd,
>>         bap_update_links(transport);
>>  }
>>
>> -static void *get_stream_bap(struct media_transport *transport)
>> -{
>> -       struct bap_transport *bap = transport->data;
>> -
>> -       return bap->stream;
>> -}
>> -
>>  static void free_bap(void *data)
>>  {
>>         struct bap_transport *bap = data;
>> @@ -1555,7 +1563,8 @@ struct media_transport *media_transport_create(struct btd_device *device,
>>                         goto fail;
>>                 properties = a2dp_properties;
>>         } else if (!strcasecmp(uuid, PAC_SINK_UUID) ||
>> -                               !strcasecmp(uuid, PAC_SOURCE_UUID)) {
>> +                               !strcasecmp(uuid, PAC_SOURCE_UUID) ||
>> +                               !strcasecmp(uuid, BROADCAST_AUDIO_ANNOUNCEMENT_SERVICE_UUID)) {
>>                 if (media_transport_init_bap(transport, stream) < 0)
>>                         goto fail;
>>                 properties = bap_properties;
>> diff --git a/src/shared/bap.c b/src/shared/bap.c
>> index 6131c3128..54d72cf35 100644
>> --- a/src/shared/bap.c
>> +++ b/src/shared/bap.c
>> @@ -4,6 +4,7 @@
>>   *  BlueZ - Bluetooth protocol stack for Linux
>>   *
>>   *  Copyright (C) 2022  Intel Corporation. All rights reserved.
>> + *  Copyright 2023 NXP
>>   *
>>   */
>>
>> @@ -120,6 +121,8 @@ struct bt_bap_db {
>>         struct bt_ascs *ascs;
>>         struct queue *sinks;
>>         struct queue *sources;
>> +       struct queue *broadcast_sources;
>> +       struct queue *broadcast_sinks;
>>  };
>>
>>  struct bt_bap_req {
>> @@ -622,6 +625,18 @@ static struct bt_bap_endpoint *bap_endpoint_new(struct bt_bap_db *bdb,
>>         return ep;
>>  }
>>
>> +static struct bt_bap_endpoint *bap_endpoint_new_broacast(struct bt_bap_db *bdb)
>> +{
>> +       struct bt_bap_endpoint *ep;
>> +
>> +       ep = new0(struct bt_bap_endpoint, 1);
>> +       ep->bdb = bdb;
>> +       ep->attr = NULL;
>> +       ep->dir = BT_BAP_BROADCAST_SOURCE;
>> +
>> +       return ep;
>> +}
>> +
>>  static struct bt_bap_endpoint *bap_get_endpoint(struct queue *endpoints,
>>                                                 struct bt_bap_db *db,
>>                                                 struct gatt_db_attribute *attr)
>> @@ -644,6 +659,26 @@ static struct bt_bap_endpoint *bap_get_endpoint(struct queue *endpoints,
>>         return ep;
>>  }
>>
>> +static struct bt_bap_endpoint *bap_get_endpoint_broadcast(struct queue *endpoints,
>> +                                               struct bt_bap_db *db)
>> +{
>> +       struct bt_bap_endpoint *ep;
>> +
>> +       if (!db)
>> +               return NULL;
>> +
>> +       if (queue_length(endpoints) > 0)
>> +               return queue_peek_head(endpoints);
>> +
>> +       ep = bap_endpoint_new_broacast(db);
>> +       if (!ep)
>> +               return NULL;
>> +
>> +       queue_push_tail(endpoints, ep);
>> +
>> +       return ep;
>> +}
>> +
>>  static bool bap_endpoint_match_id(const void *data, const void *match_data)
>>  {
>>         const struct bt_bap_endpoint *ep = data;
>> @@ -861,15 +896,15 @@ static void stream_notify_qos(struct bt_bap_stream *stream)
>>         status->state = ep->state;
>>
>>         qos = (void *)status->params;
>> -       qos->cis_id = stream->qos.cis_id;
>> -       qos->cig_id = stream->qos.cig_id;
>> -       put_le24(stream->qos.interval, qos->interval);
>> -       qos->framing = stream->qos.framing;
>> -       qos->phy = stream->qos.phy;
>> -       qos->sdu = cpu_to_le16(stream->qos.sdu);
>> -       qos->rtn = stream->qos.rtn;
>> -       qos->latency = cpu_to_le16(stream->qos.latency);
>> -       put_le24(stream->qos.delay, qos->pd);
>> +       qos->cis_id = stream->qos.ucast.cis_id;
>> +       qos->cig_id = stream->qos.ucast.cig_id;
>> +       put_le24(stream->qos.ucast.io_qos.interval, qos->interval);
>> +       qos->framing = stream->qos.ucast.framing;
>> +       qos->phy = stream->qos.ucast.io_qos.phy;
>> +       qos->sdu = cpu_to_le16(stream->qos.ucast.io_qos.sdu);
>> +       qos->rtn = stream->qos.ucast.io_qos.rtn;
>> +       qos->latency = cpu_to_le16(stream->qos.ucast.io_qos.latency);
>> +       put_le24(stream->qos.ucast.delay, qos->pd);
>>
>>         gatt_db_attribute_notify(ep->attr, (void *) status, len,
>>                                         bt_bap_get_att(stream->bap));
>> @@ -898,8 +933,8 @@ static void stream_notify_metadata(struct bt_bap_stream *stream)
>>         status->state = ep->state;
>>
>>         meta = (void *)status->params;
>> -       meta->cis_id = stream->qos.cis_id;
>> -       meta->cig_id = stream->qos.cig_id;
>> +       meta->cis_id = stream->qos.ucast.cis_id;
>> +       meta->cig_id = stream->qos.ucast.cig_id;
>>
>>         if (stream->meta) {
>>                 meta->len = stream->meta->iov_len;
>> @@ -1245,6 +1280,36 @@ static void bap_stream_state_changed(struct bt_bap_stream *stream)
>>         bt_bap_unref(bap);
>>  }
>>
>> +static void stream_set_state_broadcast(struct bt_bap_stream *stream, uint8_t state)
>> +{
>> +       struct bt_bap_endpoint *ep = stream->ep;
>> +       struct bt_bap *bap = stream->bap;
>> +       const struct queue_entry *entry;
>> +
>> +       ep->old_state = ep->state;
>> +       ep->state = state;
>> +
>> +       bt_bap_ref(bap);
>> +
>> +       for (entry = queue_get_entries(bap->state_cbs); entry;
>> +                                                       entry = entry->next) {
>> +               struct bt_bap_state *state = entry->data;
>> +
>> +               if (state->func)
>> +                       state->func(stream, stream->ep->old_state,
>> +                                       stream->ep->state, state->data);
>> +       }
>> +
>> +       /* Post notification updates */
>> +       switch (stream->ep->state) {
>> +       case BT_ASCS_ASE_STATE_IDLE:
>> +               bap_stream_detach(stream);
>> +               break;
>> +       }
>> +
>> +       bt_bap_unref(bap);
>> +}
>> +
>>  static void stream_set_state(struct bt_bap_stream *stream, uint8_t state)
>>  {
>>         struct bt_bap_endpoint *ep = stream->ep;
>> @@ -1381,6 +1446,11 @@ static void ep_config_cb(struct bt_bap_stream *stream, int err)
>>         if (err)
>>                 return;
>>
>> +       if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST)     {
>> +               stream_set_state_broadcast(stream, BT_BAP_STREAM_STATE_CONFIG);
>> +               return;
>> +       }
>> +
>>         stream_set_state(stream, BT_BAP_STREAM_STATE_CONFIG);
>>  }
>>
>> @@ -1560,20 +1630,20 @@ static uint8_t ascs_qos(struct bt_ascs *ascs, struct bt_bap *bap,
>>
>>         memset(&qos, 0, sizeof(qos));
>>
>> -       qos.cig_id = req->cig;
>> -       qos.cis_id = req->cis;
>> -       qos.interval = get_le24(req->interval);
>> -       qos.framing = req->framing;
>> -       qos.phy = req->phy;
>> -       qos.sdu = le16_to_cpu(req->sdu);
>> -       qos.rtn = req->rtn;
>> -       qos.latency = le16_to_cpu(req->latency);
>> -       qos.delay = get_le24(req->pd);
>> +       qos.ucast.cig_id = req->cig;
>> +       qos.ucast.cis_id = req->cis;
>> +       qos.ucast.io_qos.interval = get_le24(req->interval);
>> +       qos.ucast.framing = req->framing;
>> +       qos.ucast.io_qos.phy = req->phy;
>> +       qos.ucast.io_qos.sdu = le16_to_cpu(req->sdu);
>> +       qos.ucast.io_qos.rtn = req->rtn;
>> +       qos.ucast.io_qos.latency = le16_to_cpu(req->latency);
>> +       qos.ucast.delay = get_le24(req->pd);
>>
>>         DBG(bap, "CIG 0x%02x CIS 0x%02x interval %u framing 0x%02x "
>>                         "phy 0x%02x SDU %u rtn %u latency %u pd %u",
>> -                       req->cig, req->cis, qos.interval, qos.framing, qos.phy,
>> -                       qos.sdu, qos.rtn, qos.latency, qos.delay);
>> +                       req->cig, req->cis, qos.ucast.io_qos.interval, qos.ucast.framing, qos.ucast.io_qos.phy,
>> +                       qos.ucast.io_qos.sdu, qos.ucast.io_qos.rtn, qos.ucast.io_qos.latency, qos.ucast.delay);
>>
>>         ep = bap_get_local_endpoint_id(bap, req->ase);
>>         if (!ep) {
>> @@ -2204,6 +2274,8 @@ static struct bt_bap_db *bap_db_new(struct gatt_db *db)
>>         bdb->db = gatt_db_ref(db);
>>         bdb->sinks = queue_new();
>>         bdb->sources = queue_new();
>> +       bdb->broadcast_sources = queue_new();
>> +       bdb->broadcast_sinks = queue_new();
>>
>>         if (!bap_db)
>>                 bap_db = queue_new();
>> @@ -2379,6 +2451,16 @@ static void bap_add_source(struct bt_bap_pac *pac)
>>                                 iov.iov_len, NULL);
>>  }
>>
>> +static void bap_add_broadcast_source(struct bt_bap_pac *pac)
>> +{
>> +       queue_push_tail(pac->bdb->broadcast_sources, pac);
>> +}
>> +
>> +static void bap_add_broadcast_sink(struct bt_bap_pac *pac)
>> +{
>> +       queue_push_tail(pac->bdb->broadcast_sinks, pac);
>> +}
>> +
>>  static void notify_pac_added(void *data, void *user_data)
>>  {
>>         struct bt_bap_pac_changed *changed = data;
>> @@ -2400,10 +2482,12 @@ struct bt_bap_pac *bt_bap_add_vendor_pac(struct gatt_db *db,
>>                                         uint8_t id, uint16_t cid, uint16_t vid,
>>                                         struct bt_bap_pac_qos *qos,
>>                                         struct iovec *data,
>> -                                       struct iovec *metadata)
>> +                                       struct iovec *metadata,
>> +                                       struct bt_bap_pac_ops *pac_ops,
>> +                                       void *user_data)
>>  {
>>         struct bt_bap_db *bdb;
>> -       struct bt_bap_pac *pac;
>> +       struct bt_bap_pac *pac, *pac_brodcast_sink;
>>         struct bt_bap_codec codec;
>>
>>         if (!db)
>> @@ -2429,11 +2513,17 @@ struct bt_bap_pac *bt_bap_add_vendor_pac(struct gatt_db *db,
>>         case BT_BAP_SOURCE:
>>                 bap_add_source(pac);
>>                 break;
>> +       case BT_BAP_BROADCAST_SOURCE:
>> +               bap_add_broadcast_source(pac);
>> +               pac_brodcast_sink = bap_pac_new(bdb, name, type, &codec, qos, data, metadata);
>> +               bap_add_broadcast_sink(pac_brodcast_sink);
>> +               break;
>>         default:
>>                 bap_pac_free(pac);
>>                 return NULL;
>>         }
>>
>> +       bt_bap_pac_set_ops(pac, pac_ops, user_data);
>>         queue_foreach(sessions, notify_session_pac_added, pac);
>>
>>         return pac;
>> @@ -2443,10 +2533,12 @@ struct bt_bap_pac *bt_bap_add_pac(struct gatt_db *db, const char *name,
>>                                         uint8_t type, uint8_t id,
>>                                         struct bt_bap_pac_qos *qos,
>>                                         struct iovec *data,
>> -                                       struct iovec *metadata)
>> +                                       struct iovec *metadata,
>> +                                       struct bt_bap_pac_ops *pac_ops,
>> +                                       void *user_data)
>>  {
>>         return bt_bap_add_vendor_pac(db, name, type, id, 0x0000, 0x0000, qos,
>> -                                                       data, metadata);
>> +                                                       data, metadata, pac_ops, user_data);
>>  }
>>
>>  uint8_t bt_bap_pac_get_type(struct bt_bap_pac *pac)
>> @@ -2471,6 +2563,21 @@ uint32_t bt_bap_pac_get_locations(struct bt_bap_pac *pac)
>>         }
>>  }
>>
>> +uint8_t bt_bap_stream_get_type(struct bt_bap_stream *stream)
>> +{
>> +       if (!stream)
>> +               return BT_BAP_STREAM_TYPE_UNKNOWN;
>> +
>> +       if ((bt_bap_pac_get_type(stream->lpac) == BT_BAP_SINK) ||
>> +               (bt_bap_pac_get_type(stream->lpac) == BT_BAP_SOURCE))
>> +               return BT_BAP_STREAM_TYPE_UNICAST;
>> +       else if ((bt_bap_pac_get_type(stream->lpac) == BT_BAP_BROADCAST_SOURCE) ||
>> +                       (bt_bap_pac_get_type(stream->lpac) == BT_BAP_BROADCAST_SINK))
>> +               return BT_BAP_STREAM_TYPE_BROADCAST;
>> +       else
>> +               return BT_BAP_STREAM_TYPE_UNKNOWN;
>> +}
>> +
>>  static void notify_pac_removed(void *data, void *user_data)
>>  {
>>         struct bt_bap_pac_changed *changed = data;
>> @@ -2529,6 +2636,9 @@ bool bt_bap_remove_pac(struct bt_bap_pac *pac)
>>         if (queue_remove_if(pac->bdb->sources, NULL, pac))
>>                 goto found;
>>
>> +       if (queue_remove_if(pac->bdb->broadcast_sources, NULL, pac))
>> +               goto found;
>> +
>>         return false;
>>
>>  found:
>> @@ -3280,13 +3390,13 @@ static void ep_status_qos(struct bt_bap *bap, struct bt_bap_endpoint *ep,
>>         if (!ep->stream)
>>                 return;
>>
>> -       ep->stream->qos.interval = interval;
>> -       ep->stream->qos.framing = qos->framing;
>> -       ep->stream->qos.phy = qos->phy;
>> -       ep->stream->qos.sdu = sdu;
>> -       ep->stream->qos.rtn = qos->rtn;
>> -       ep->stream->qos.latency = latency;
>> -       ep->stream->qos.delay = pd;
>> +       ep->stream->qos.ucast.io_qos.interval = interval;
>> +       ep->stream->qos.ucast.framing = qos->framing;
>> +       ep->stream->qos.ucast.io_qos.phy = qos->phy;
>> +       ep->stream->qos.ucast.io_qos.sdu = sdu;
>> +       ep->stream->qos.ucast.io_qos.rtn = qos->rtn;
>> +       ep->stream->qos.ucast.io_qos.latency = latency;
>> +       ep->stream->qos.ucast.delay = pd;
>>
>>         if (ep->old_state == BT_ASCS_ASE_STATE_CONFIG)
>>                 bap_stream_config_cfm(ep->stream);
>> @@ -3861,6 +3971,25 @@ clone:
>>         return true;
>>  }
>>
>> +bool bt_bap_attach_broadcast(struct bt_bap *bap)
>> +{
>> +       struct bt_bap_endpoint *ep;
>> +
>> +       if (queue_find(sessions, NULL, bap))
>> +               return true;
>> +
>> +       if (!sessions)
>> +               sessions = queue_new();
>> +
>> +       queue_push_tail(sessions, bap);
>> +
>> +       ep = bap_get_endpoint_broadcast(bap->remote_eps, bap->ldb);
>> +       if (ep)
>> +               ep->bap = bap;
>> +
>> +       return true;
>> +}
>> +
>>  static void stream_foreach_detach(void *data, void *user_data)
>>  {
>>         struct bt_bap_stream *stream = data;
>> @@ -4065,7 +4194,10 @@ void bt_bap_foreach_pac(struct bt_bap *bap, uint8_t type,
>>                                                         func, user_data);
>>         case BT_BAP_SOURCE:
>>                 return bap_foreach_pac(bap->ldb->sinks, bap->rdb->sources,
>> -                                                       func, user_data);
>> +                                                          func, user_data);
>> +       case BT_BAP_BROADCAST_SOURCE:
>> +               return bap_foreach_pac(bap->ldb->broadcast_sources, bap->ldb->broadcast_sinks,
>> +                                                               func, user_data);
>>         }
>>  }
>>
>> @@ -4178,42 +4310,49 @@ unsigned int bt_bap_stream_config(struct bt_bap_stream *stream,
>>         if (!bap_stream_valid(stream))
>>                 return 0;
>>
>> -       if (!stream->client) {
>> -               stream_config(stream, data, NULL);
>> -               return 0;
>> -       }
>> +       if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_UNICAST) {
>> +               if (!stream->client) {
>> +                       stream_config(stream, data, NULL);
>> +                       return 0;
>> +               }
>>
>> -       memset(&config, 0, sizeof(config));
>> +               memset(&config, 0, sizeof(config));
>>
>> -       config.ase = stream->ep->id;
>> -       config.latency = qos->target_latency;
>> -       config.phy = qos->phy;
>> -       config.codec = stream->rpac->codec;
>> +               config.ase = stream->ep->id;
>> +               config.latency = qos->ucast.target_latency;
>> +               config.phy = qos->ucast.io_qos.phy;
>> +               config.codec = stream->rpac->codec;
>>
>> -       iov[0].iov_base = &config;
>> -       iov[0].iov_len = sizeof(config);
>> +               iov[0].iov_base = &config;
>> +               iov[0].iov_len = sizeof(config);
>>
>> -       if (data) {
>> -               if (!bap_print_cc(data->iov_base, data->iov_len,
>> -                                       stream->bap->debug_func,
>> -                                       stream->bap->debug_data))
>> -                       return 0;
>> +               if (data) {
>> +                       if (!bap_print_cc(data->iov_base, data->iov_len,
>> +                                               stream->bap->debug_func,
>> +                                               stream->bap->debug_data))
>> +                               return 0;
>>
>> -               config.cc_len = data->iov_len;
>> -               iov[1] = *data;
>> -               iovlen++;
>> -       }
>> +                       config.cc_len = data->iov_len;
>> +                       iov[1] = *data;
>> +                       iovlen++;
>> +               }
>>
>> -       req = bap_req_new(stream, BT_ASCS_CONFIG, iov, iovlen, func, user_data);
>> +               req = bap_req_new(stream, BT_ASCS_CONFIG, iov, iovlen, func, user_data);
>>
>> -       if (!bap_queue_req(stream->bap, req)) {
>> -               bap_req_free(req);
>> -               return 0;
>> -       }
>> +               if (!bap_queue_req(stream->bap, req)) {
>> +                       bap_req_free(req);
>> +                       return 0;
>> +               }
>>
>> -       stream->qos = *qos;
>> +               stream->qos = *qos;
>>
>> -       return req->id;
>> +               return req->id;
>> +       } else if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST) {
>> +               stream->qos = *qos;
>> +               return 0;
>> +       } else {
>> +               return 0;
>> +       }
>>  }
>>
>>  static bool match_pac(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
>> @@ -4274,7 +4413,7 @@ struct bt_bap_stream *bt_bap_stream_new(struct bt_bap *bap,
>>                 if (rpac)
>>                         type = rpac->type;
>>                 else if (lpac) {
>> -                       switch(lpac->type) {
>> +                       switch (lpac->type) {
>>                         case BT_BAP_SINK:
>>                                 type = BT_BAP_SOURCE;
>>                                 break;
>> @@ -4339,6 +4478,10 @@ bool bt_bap_stream_set_user_data(struct bt_bap_stream *stream, void *user_data)
>>
>>         stream->user_data = user_data;
>>
>> +       if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST)
>> +               stream->lpac->ops->config(stream, stream->cc, &stream->qos,
>> +                                                               ep_config_cb, stream->lpac->user_data);
>> +
>>         return true;
>>  }
>>
>> @@ -4369,15 +4512,15 @@ unsigned int bt_bap_stream_qos(struct bt_bap_stream *stream,
>>
>>         /* TODO: Figure out how to pass these values around */
>>         qos.ase = stream->ep->id;
>> -       qos.cig = data->cig_id;
>> -       qos.cis = data->cis_id;
>> -       put_le24(data->interval, qos.interval);
>> -       qos.framing = data->framing;
>> -       qos.phy = data->phy;
>> -       qos.sdu = cpu_to_le16(data->sdu);
>> -       qos.rtn = data->rtn;
>> -       qos.latency = cpu_to_le16(data->latency);
>> -       put_le24(data->delay, qos.pd);
>> +       qos.cig = data->ucast.cig_id;
>> +       qos.cis = data->ucast.cis_id;
>> +       put_le24(data->ucast.io_qos.interval, qos.interval);
>> +       qos.framing = data->ucast.framing;
>> +       qos.phy = data->ucast.io_qos.phy;
>> +       qos.sdu = cpu_to_le16(data->ucast.io_qos.sdu);
>> +       qos.rtn = data->ucast.io_qos.rtn;
>> +       qos.latency = cpu_to_le16(data->ucast.io_qos.latency);
>> +       put_le24(data->ucast.delay, qos.pd);
>>
>>         iov.iov_base = &qos;
>>         iov.iov_len = sizeof(qos);
>> @@ -4448,7 +4591,7 @@ unsigned int bt_bap_stream_enable(struct bt_bap_stream *stream,
>>                                         bt_bap_stream_func_t func,
>>                                         void *user_data)
>>  {
>> -       int ret;
>> +       int ret = 0;
>>
>>         /* Table 3.2: ASE state machine transition
>>          * Initiating device - client Only
>> @@ -4456,12 +4599,17 @@ unsigned int bt_bap_stream_enable(struct bt_bap_stream *stream,
>>         if (!bap_stream_valid(stream) || !stream->client)
>>                 return 0;
>>
>> -       ret = bap_stream_metadata(stream, BT_ASCS_ENABLE, metadata, func,
>> -                                                               user_data);
>> -       if (!ret || !enable_links)
>> -               return ret;
>> +       if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_UNICAST) {
>> +               ret = bap_stream_metadata(stream, BT_ASCS_ENABLE, metadata, func,
>> +                                                         user_data);
>> +               if (!ret || !enable_links)
>> +                       return ret;
>>
>> -       queue_foreach(stream->links, bap_stream_enable_link, metadata);
>> +               queue_foreach(stream->links, bap_stream_enable_link, metadata);
>> +       } else if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST) {
>> +               stream_set_state_broadcast(stream, BT_BAP_STREAM_STATE_STREAMING);
>> +               return ret = 1;
>> +       }
>>
>>         return ret;
>>  }
>> @@ -4640,6 +4788,15 @@ unsigned int bt_bap_stream_release(struct bt_bap_stream *stream,
>>
>>         bap = stream->bap;
>>
>> +       /* If stream is broadcast, no BT_ASCS_RELEASE is required */
>> +       if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST) {
>> +               if (!bap_stream_valid(stream)) {
>> +                       stream_set_state_broadcast(stream, BT_BAP_STREAM_STATE_IDLE);
>> +                       stream = NULL;
>> +               }
>> +               return 0;
>> +       }
>> +
>>         /* If stream does not belong to a client session, clean it up now */
>>         if (!bap_stream_valid(stream)) {
>>                 stream_set_state(stream, BT_BAP_STREAM_STATE_IDLE);
>> @@ -4675,8 +4832,11 @@ uint32_t bt_bap_stream_get_location(struct bt_bap_stream *stream)
>>
>>         if (stream->ep->dir == BT_BAP_SOURCE)
>>                 return pacs->source_loc_value;
>> -       else
>> +       else if (stream->ep->dir == BT_BAP_SINK)
>>                 return pacs->sink_loc_value;
>> +       else
>> +               // TO DO get the location values from metadata for brodcast source and sink
>> +               return stream->bap->ldb->pacs->source_loc_value;
>>  }
>>
>>  struct iovec *bt_bap_stream_get_config(struct bt_bap_stream *stream)
>> @@ -4781,8 +4941,8 @@ int bt_bap_stream_io_link(struct bt_bap_stream *stream,
>>                 return -EALREADY;
>>
>>         if (stream->client != link->client ||
>> -                       stream->qos.cig_id != link->qos.cig_id ||
>> -                       stream->qos.cis_id != link->qos.cis_id)
>> +                       stream->qos.ucast.cig_id != link->qos.ucast.cig_id ||
>> +                       stream->qos.ucast.cis_id != link->qos.ucast.cis_id)
>>                 return -EINVAL;
>>
>>         if (!stream->links)
>> @@ -4819,7 +4979,7 @@ static void bap_stream_get_in_qos(void *data, void *user_data)
>>         struct bt_bap_qos **qos = user_data;
>>
>>         if (!qos || *qos || stream->ep->dir != BT_BAP_SOURCE ||
>> -                                               !stream->qos.sdu)
>> +                                               !stream->qos.ucast.io_qos.sdu)
>>                 return;
>>
>>         *qos = &stream->qos;
>> @@ -4830,7 +4990,7 @@ static void bap_stream_get_out_qos(void *data, void *user_data)
>>         struct bt_bap_stream *stream = data;
>>         struct bt_bap_qos **qos = user_data;
>>
>> -       if (!qos || *qos || stream->ep->dir != BT_BAP_SINK || !stream->qos.sdu)
>> +       if (!qos || *qos || stream->ep->dir != BT_BAP_SINK || !stream->qos.ucast.io_qos.sdu)
>>                 return;
>>
>>         *qos = &stream->qos;
>> diff --git a/src/shared/bap.h b/src/shared/bap.h
>> index e9f769d0e..3b07df158 100644
>> --- a/src/shared/bap.h
>> +++ b/src/shared/bap.h
>> @@ -4,6 +4,7 @@
>>   *  BlueZ - Bluetooth protocol stack for Linux
>>   *
>>   *  Copyright (C) 2022  Intel Corporation. All rights reserved.
>> + *  Copyright 2023 NXP
>>   *
>>   */
>>
>> @@ -14,8 +15,14 @@
>>  #define __packed __attribute__((packed))
>>  #endif
>>
>> -#define BT_BAP_SINK                    0x01
>> +#define BT_BAP_SINK                            0x01
>>  #define        BT_BAP_SOURCE                   0x02
>> +#define        BT_BAP_BROADCAST_SOURCE 0x03
>> +#define        BT_BAP_BROADCAST_SINK   0x04
>> +
>> +#define BT_BAP_STREAM_TYPE_UNICAST             0x01
>> +#define        BT_BAP_STREAM_TYPE_BROADCAST    0x02
>> +#define        BT_BAP_STREAM_TYPE_UNKNOWN              0x03
>>
>>  #define BT_BAP_STREAM_STATE_IDLE       0x00
>>  #define BT_BAP_STREAM_STATE_CONFIG     0x01
>> @@ -49,17 +56,46 @@ struct bt_ltv {
>>         uint8_t  value[0];
>>  } __packed;
>>
>> -struct bt_bap_qos {
>> +struct bt_bap_io_qos {
>> +       uint32_t interval;      /* Frame interval */
>> +       uint16_t latency;       /* Transport Latency */
>> +       uint16_t sdu;           /* Maximum SDU Size */
>> +       uint8_t  phy;           /* PHY */
>> +       uint8_t  rtn;           /* Retransmission Effort */
>> +};
>> +
>> +struct bt_bap_ucast_qos {
>>         uint8_t  cig_id;
>>         uint8_t  cis_id;
>> -       uint32_t interval;              /* Frame interval */
>>         uint8_t  framing;               /* Frame framing */
>> -       uint8_t  phy;                   /* PHY */
>> -       uint16_t sdu;                   /* Maximum SDU Size */
>> -       uint8_t  rtn;                   /* Retransmission Effort */
>> -       uint16_t latency;               /* Transport Latency */
>>         uint32_t delay;                 /* Presentation Delay */
>>         uint8_t  target_latency;        /* Target Latency */
>> +       struct bt_bap_io_qos io_qos;
>> +};
>> +
>> +struct bt_bap_bcast_qos {
>> +       uint8_t  big;
>> +       uint8_t  bis;
>> +       uint8_t  sync_interval;
>> +       uint8_t  packing;
>> +       uint8_t  framing;
>> +       uint8_t  encryption;
>> +       struct iovec bcode;
>> +       uint8_t  options;
>> +       uint16_t skip;
>> +       uint16_t sync_timeout;
>> +       uint8_t  sync_cte_type;
>> +       uint8_t  mse;
>> +       uint16_t timeout;
>> +       uint8_t  pa_sync;
>> +       struct bt_bap_io_qos io_qos;
>> +};
>> +
>> +struct bt_bap_qos {
>> +       union {
>> +                       struct bt_bap_ucast_qos ucast;
>> +                       struct bt_bap_bcast_qos bcast;
>> +               };
>>  };
>>
>>  typedef void (*bt_bap_ready_func_t)(struct bt_bap *bap, void *user_data);
>> @@ -98,28 +134,32 @@ struct bt_bap_pac_qos {
>>         uint32_t ppd_max;
>>  };
>>
>> +struct bt_bap_pac_ops {
>> +       int (*select)(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
>> +                       struct bt_bap_pac_qos *qos,
>> +                       bt_bap_pac_select_t cb, void *cb_data, void *user_data);
>> +       int (*config)(struct bt_bap_stream *stream, struct iovec *cfg,
>> +                       struct bt_bap_qos *qos, bt_bap_pac_config_t cb,
>> +                       void *user_data);
>> +       void (*clear)(struct bt_bap_stream *stream, void *user_data);
>> +};
>> +
>>  struct bt_bap_pac *bt_bap_add_vendor_pac(struct gatt_db *db,
>>                                         const char *name, uint8_t type,
>>                                         uint8_t id, uint16_t cid, uint16_t vid,
>>                                         struct bt_bap_pac_qos *qos,
>>                                         struct iovec *data,
>> -                                       struct iovec *metadata);
>> +                                       struct iovec *metadata,
>> +                                       struct bt_bap_pac_ops *pac_ops,
>> +                                       void *user_data);
>>
>>  struct bt_bap_pac *bt_bap_add_pac(struct gatt_db *db, const char *name,
>>                                         uint8_t type, uint8_t id,
>>                                         struct bt_bap_pac_qos *qos,
>>                                         struct iovec *data,
>> -                                       struct iovec *metadata);
>> -
>> -struct bt_bap_pac_ops {
>> -       int (*select)(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
>> -                       struct bt_bap_pac_qos *qos,
>> -                       bt_bap_pac_select_t cb, void *cb_data, void *user_data);
>> -       int (*config)(struct bt_bap_stream *stream, struct iovec *cfg,
>> -                       struct bt_bap_qos *qos, bt_bap_pac_config_t cb,
>> -                       void *user_data);
>> -       void (*clear)(struct bt_bap_stream *stream, void *user_data);
>> -};
>> +                                       struct iovec *metadata,
>> +                                       struct bt_bap_pac_ops *pac_ops,
>> +                                       void *user_data);
>>
>>  bool bt_bap_pac_set_ops(struct bt_bap_pac *pac, struct bt_bap_pac_ops *ops,
>>                                         void *user_data);
>> @@ -130,6 +170,8 @@ uint8_t bt_bap_pac_get_type(struct bt_bap_pac *pac);
>>
>>  uint32_t bt_bap_pac_get_locations(struct bt_bap_pac *pac);
>>
>> +uint8_t bt_bap_stream_get_type(struct bt_bap_stream *stream);
>> +
>>  struct bt_bap_stream *bt_bap_pac_get_stream(struct bt_bap_pac *pac);
>>
>>  /* Session related function */
>> @@ -149,6 +191,7 @@ struct bt_bap *bt_bap_ref(struct bt_bap *bap);
>>  void bt_bap_unref(struct bt_bap *bap);
>>
>>  bool bt_bap_attach(struct bt_bap *bap, struct bt_gatt_client *client);
>> +bool bt_bap_attach_broadcast(struct bt_bap *bap);
>>  void bt_bap_detach(struct bt_bap *bap);
>>
>>  bool bt_bap_set_debug(struct bt_bap *bap, bt_bap_debug_func_t cb,
>> diff --git a/unit/test-bap.c b/unit/test-bap.c
>> index bf525742d..8d1b3fd52 100644
>> --- a/unit/test-bap.c
>> +++ b/unit/test-bap.c
>> @@ -377,11 +377,11 @@ static void test_client_config(struct test_data *data)
>>                                                         "test-bap-snk",
>>                                                         BT_BAP_SINK, 0x0ff,
>>                                                         0x0001, 0x0001,
>> -                                                       NULL, data->caps, NULL);
>> +                                                       NULL, data->caps, NULL, NULL, NULL);
>>                 else
>>                         data->snk = bt_bap_add_pac(data->db, "test-bap-snk",
>>                                                         BT_BAP_SINK, LC3_ID,
>> -                                                       NULL, data->caps, NULL);
>> +                                                       NULL, data->caps, NULL, NULL, NULL);
>>                 g_assert(data->snk);
>>         }
>>
>> @@ -391,11 +391,11 @@ static void test_client_config(struct test_data *data)
>>                                                         "test-bap-src",
>>                                                         BT_BAP_SOURCE, 0x0ff,
>>                                                         0x0001, 0x0001,
>> -                                                       NULL, data->caps, NULL);
>> +                                                       NULL, data->caps, NULL, NULL, NULL);
>>                 else
>>                         data->src = bt_bap_add_pac(data->db, "test-bap-src",
>>                                                         BT_BAP_SOURCE, LC3_ID,
>> -                                                       NULL, data->caps, NULL);
>> +                                                       NULL, data->caps, NULL, NULL, NULL);
>>                 g_assert(data->src);
>>         }
>>  }
>> @@ -712,12 +712,15 @@ static void test_disc(void)
>>  #define QOS_BALANCED_2M \
>>         { \
>>                 .target_latency = BT_BAP_CONFIG_LATENCY_BALANCED, \
>> -               .phy = BT_BAP_CONFIG_PHY_2M, \
>> +               .io_qos.phy = BT_BAP_CONFIG_PHY_2M, \
>>         }
>> -
>> +#define QOS_UCAST \
>> +{\
>> +       .ucast = QOS_BALANCED_2M, \
>> +}
>>  static struct test_config cfg_snk_8_1 = {
>>         .cc = LC3_CONFIG_8_1,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .snk = true,
>>  };
>>
>> @@ -727,7 +730,7 @@ static struct test_config cfg_snk_8_1 = {
>>
>>  static struct test_config cfg_snk_8_2 = {
>>         .cc = LC3_CONFIG_8_2,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .snk = true,
>>  };
>>
>> @@ -737,7 +740,7 @@ static struct test_config cfg_snk_8_2 = {
>>
>>  static struct test_config cfg_snk_16_1 = {
>>         .cc = LC3_CONFIG_16_1,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .snk = true,
>>  };
>>
>> @@ -747,7 +750,7 @@ static struct test_config cfg_snk_16_1 = {
>>
>>  static struct test_config cfg_snk_16_2 = {
>>         .cc = LC3_CONFIG_16_2,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .snk = true,
>>  };
>>
>> @@ -757,7 +760,7 @@ static struct test_config cfg_snk_16_2 = {
>>
>>  static struct test_config cfg_snk_24_1 = {
>>         .cc = LC3_CONFIG_24_1,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .snk = true,
>>  };
>>
>> @@ -767,7 +770,7 @@ static struct test_config cfg_snk_24_1 = {
>>
>>  static struct test_config cfg_snk_24_2 = {
>>         .cc = LC3_CONFIG_24_2,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .snk = true,
>>  };
>>
>> @@ -777,7 +780,7 @@ static struct test_config cfg_snk_24_2 = {
>>
>>  static struct test_config cfg_snk_32_1 = {
>>         .cc = LC3_CONFIG_32_1,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .snk = true,
>>  };
>>
>> @@ -787,7 +790,7 @@ static struct test_config cfg_snk_32_1 = {
>>
>>  static struct test_config cfg_snk_32_2 = {
>>         .cc = LC3_CONFIG_32_2,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .snk = true,
>>  };
>>
>> @@ -797,7 +800,7 @@ static struct test_config cfg_snk_32_2 = {
>>
>>  static struct test_config cfg_snk_44_1 = {
>>         .cc = LC3_CONFIG_44_1,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .snk = true,
>>  };
>>
>> @@ -807,7 +810,7 @@ static struct test_config cfg_snk_44_1 = {
>>
>>  static struct test_config cfg_snk_44_2 = {
>>         .cc = LC3_CONFIG_44_2,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .snk = true,
>>  };
>>
>> @@ -817,7 +820,7 @@ static struct test_config cfg_snk_44_2 = {
>>
>>  static struct test_config cfg_snk_48_1 = {
>>         .cc = LC3_CONFIG_48_1,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .snk = true,
>>  };
>>
>> @@ -827,7 +830,7 @@ static struct test_config cfg_snk_48_1 = {
>>
>>  static struct test_config cfg_snk_48_2 = {
>>         .cc = LC3_CONFIG_48_2,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .snk = true,
>>  };
>>
>> @@ -837,7 +840,7 @@ static struct test_config cfg_snk_48_2 = {
>>
>>  static struct test_config cfg_snk_48_3 = {
>>         .cc = LC3_CONFIG_48_3,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .snk = true,
>>  };
>>
>> @@ -847,7 +850,7 @@ static struct test_config cfg_snk_48_3 = {
>>
>>  static struct test_config cfg_snk_48_4 = {
>>         .cc = LC3_CONFIG_48_4,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .snk = true,
>>  };
>>
>> @@ -857,7 +860,7 @@ static struct test_config cfg_snk_48_4 = {
>>
>>  static struct test_config cfg_snk_48_5 = {
>>         .cc = LC3_CONFIG_48_5,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .snk = true,
>>  };
>>
>> @@ -867,7 +870,7 @@ static struct test_config cfg_snk_48_5 = {
>>
>>  static struct test_config cfg_snk_48_6 = {
>>         .cc = LC3_CONFIG_48_6,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .snk = true,
>>  };
>>
>> @@ -899,7 +902,7 @@ static struct test_config cfg_snk_48_6 = {
>>
>>  static struct test_config cfg_src_8_1 = {
>>         .cc = LC3_CONFIG_8_1,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .src = true,
>>  };
>>
>> @@ -909,7 +912,7 @@ static struct test_config cfg_src_8_1 = {
>>
>>  static struct test_config cfg_src_8_2 = {
>>         .cc = LC3_CONFIG_8_2,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .src = true,
>>  };
>>
>> @@ -919,7 +922,7 @@ static struct test_config cfg_src_8_2 = {
>>
>>  static struct test_config cfg_src_16_1 = {
>>         .cc = LC3_CONFIG_16_1,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .src = true,
>>  };
>>
>> @@ -929,7 +932,7 @@ static struct test_config cfg_src_16_1 = {
>>
>>  static struct test_config cfg_src_16_2 = {
>>         .cc = LC3_CONFIG_16_2,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .src = true,
>>  };
>>
>> @@ -939,7 +942,7 @@ static struct test_config cfg_src_16_2 = {
>>
>>  static struct test_config cfg_src_24_1 = {
>>         .cc = LC3_CONFIG_24_1,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .src = true,
>>  };
>>
>> @@ -949,7 +952,7 @@ static struct test_config cfg_src_24_1 = {
>>
>>  static struct test_config cfg_src_24_2 = {
>>         .cc = LC3_CONFIG_24_2,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .src = true,
>>  };
>>
>> @@ -959,7 +962,7 @@ static struct test_config cfg_src_24_2 = {
>>
>>  static struct test_config cfg_src_32_1 = {
>>         .cc = LC3_CONFIG_32_1,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .src = true,
>>  };
>>
>> @@ -969,7 +972,7 @@ static struct test_config cfg_src_32_1 = {
>>
>>  static struct test_config cfg_src_32_2 = {
>>         .cc = LC3_CONFIG_32_2,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .src = true,
>>  };
>>
>> @@ -979,7 +982,7 @@ static struct test_config cfg_src_32_2 = {
>>
>>  static struct test_config cfg_src_44_1 = {
>>         .cc = LC3_CONFIG_44_1,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .src = true,
>>  };
>>
>> @@ -989,7 +992,7 @@ static struct test_config cfg_src_44_1 = {
>>
>>  static struct test_config cfg_src_44_2 = {
>>         .cc = LC3_CONFIG_44_2,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .src = true,
>>  };
>>
>> @@ -999,7 +1002,7 @@ static struct test_config cfg_src_44_2 = {
>>
>>  static struct test_config cfg_src_48_1 = {
>>         .cc = LC3_CONFIG_48_1,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .src = true,
>>  };
>>
>> @@ -1009,7 +1012,7 @@ static struct test_config cfg_src_48_1 = {
>>
>>  static struct test_config cfg_src_48_2 = {
>>         .cc = LC3_CONFIG_48_2,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .src = true,
>>  };
>>
>> @@ -1019,7 +1022,7 @@ static struct test_config cfg_src_48_2 = {
>>
>>  static struct test_config cfg_src_48_3 = {
>>         .cc = LC3_CONFIG_48_3,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .src = true,
>>  };
>>
>> @@ -1029,7 +1032,7 @@ static struct test_config cfg_src_48_3 = {
>>
>>  static struct test_config cfg_src_48_4 = {
>>         .cc = LC3_CONFIG_48_4,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .src = true,
>>  };
>>
>> @@ -1039,7 +1042,7 @@ static struct test_config cfg_src_48_4 = {
>>
>>  static struct test_config cfg_src_48_5 = {
>>         .cc = LC3_CONFIG_48_5,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .src = true,
>>  };
>>
>> @@ -1049,7 +1052,7 @@ static struct test_config cfg_src_48_5 = {
>>
>>  static struct test_config cfg_src_48_6 = {
>>         .cc = LC3_CONFIG_48_6,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .src = true,
>>  };
>>
>> @@ -1141,7 +1144,7 @@ static void test_scc_cc_lc3(void)
>>
>>  static struct test_config cfg_snk_vs = {
>>         .cc = IOV_NULL,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .snk = true,
>>         .vs = true,
>>  };
>> @@ -1155,7 +1158,7 @@ static struct test_config cfg_snk_vs = {
>>
>>  static struct test_config cfg_src_vs = {
>>         .cc = IOV_NULL,
>> -       .qos = QOS_BALANCED_2M,
>> +       .qos = QOS_UCAST,
>>         .src = true,
>>         .vs = true,
>>  };
>> --
>> 2.34.1
>>
>
>
>-- 
>Luiz Augusto von Dentz

Silviu Barbulescu
diff mbox series

Patch

diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c
index 8f12fc410..3858eb1d9 100644
--- a/profiles/audio/bap.c
+++ b/profiles/audio/bap.c
@@ -82,13 +82,25 @@  struct bap_data {
 	unsigned int pac_id;
 	struct queue *srcs;
 	struct queue *snks;
+	struct queue *broadcast;
 	struct queue *streams;
 	GIOChannel *listen_io;
 	int selecting;
+	void *user_data;
 };
 
 static struct queue *sessions;
 
+static bool bap_data_set_user_data(struct bap_data *data, void *user_data)
+{
+	if (!data)
+		return false;
+
+	data->user_data = user_data;
+
+	return true;
+}
+
 static void bap_debug(const char *str, void *user_data)
 {
 	DBG_IDX(0xffff, "%s", str);
@@ -167,8 +179,10 @@  static gboolean get_uuid(const GDBusPropertyTable *property,
 
 	if (queue_find(ep->data->snks, NULL, ep))
 		uuid = PAC_SINK_UUID;
-	else
+	if (queue_find(ep->data->srcs, NULL, ep))
 		uuid = PAC_SOURCE_UUID;
+	else
+		uuid = BROADCAST_AUDIO_ANNOUNCEMENT_SERVICE_UUID;
 
 	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &uuid);
 
@@ -253,6 +267,8 @@  static int parse_properties(DBusMessageIter *props, struct iovec **caps,
 				struct iovec **metadata, struct bt_bap_qos *qos)
 {
 	const char *key;
+	struct bt_bap_io_qos io_qos;
+	bool broadcast = false;
 
 	while (dbus_message_iter_get_arg_type(props) == DBUS_TYPE_DICT_ENTRY) {
 		DBusMessageIter value, entry;
@@ -282,17 +298,27 @@  static int parse_properties(DBusMessageIter *props, struct iovec **caps,
 			if (var != DBUS_TYPE_BYTE)
 				goto fail;
 
-			dbus_message_iter_get_basic(&value, &qos->cig_id);
+			dbus_message_iter_get_basic(&value, &qos->ucast.cig_id);
+		} else if (!strcasecmp(key, "BIG")) {
+			if (var != DBUS_TYPE_BYTE)
+				goto fail;
+
+			dbus_message_iter_get_basic(&value, &qos->bcast.big);
 		} else if (!strcasecmp(key, "CIS")) {
 			if (var != DBUS_TYPE_BYTE)
 				goto fail;
 
-			dbus_message_iter_get_basic(&value, &qos->cis_id);
+			dbus_message_iter_get_basic(&value, &qos->ucast.cis_id);
+		} else if (!strcasecmp(key, "BIS")) {
+			if (var != DBUS_TYPE_BYTE)
+				goto fail;
+
+			dbus_message_iter_get_basic(&value, &qos->bcast.bis);
 		} else if (!strcasecmp(key, "Interval")) {
 			if (var != DBUS_TYPE_UINT32)
 				goto fail;
 
-			dbus_message_iter_get_basic(&value, &qos->interval);
+			dbus_message_iter_get_basic(&value, &io_qos.interval);
 		} else if (!strcasecmp(key, "Framing")) {
 			dbus_bool_t val;
 
@@ -301,7 +327,7 @@  static int parse_properties(DBusMessageIter *props, struct iovec **caps,
 
 			dbus_message_iter_get_basic(&value, &val);
 
-			qos->framing = val;
+			qos->ucast.framing = val;
 		} else if (!strcasecmp(key, "PHY")) {
 			const char *str;
 
@@ -311,42 +337,91 @@  static int parse_properties(DBusMessageIter *props, struct iovec **caps,
 			dbus_message_iter_get_basic(&value, &str);
 
 			if (!strcasecmp(str, "1M"))
-				qos->phy = 0x01;
+				io_qos.phy = 0x01;
 			else if (!strcasecmp(str, "2M"))
-				qos->phy = 0x02;
+				io_qos.phy = 0x02;
 			else
 				goto fail;
 		} else if (!strcasecmp(key, "SDU")) {
 			if (var != DBUS_TYPE_UINT16)
 				goto fail;
 
-			dbus_message_iter_get_basic(&value, &qos->sdu);
+			dbus_message_iter_get_basic(&value, &io_qos.sdu);
 		} else if (!strcasecmp(key, "Retransmissions")) {
 			if (var != DBUS_TYPE_BYTE)
 				goto fail;
 
-			dbus_message_iter_get_basic(&value, &qos->rtn);
+			dbus_message_iter_get_basic(&value, &io_qos.rtn);
 		} else if (!strcasecmp(key, "Latency")) {
 			if (var != DBUS_TYPE_UINT16)
 				goto fail;
 
-			dbus_message_iter_get_basic(&value, &qos->latency);
+			dbus_message_iter_get_basic(&value, &io_qos.latency);
 		} else if (!strcasecmp(key, "Delay")) {
 			if (var != DBUS_TYPE_UINT32)
 				goto fail;
 
-			dbus_message_iter_get_basic(&value, &qos->delay);
+			dbus_message_iter_get_basic(&value, &qos->ucast.delay);
 		} else if (!strcasecmp(key, "TargetLatency")) {
 			if (var != DBUS_TYPE_BYTE)
 				goto fail;
 
 			dbus_message_iter_get_basic(&value,
-							&qos->target_latency);
+							&qos->ucast.target_latency);
+		} else if (!strcasecmp(key, "Encryption")) {
+			if (var != DBUS_TYPE_BYTE)
+				goto fail;
+
+			dbus_message_iter_get_basic(&value,
+							&qos->bcast.encryption);
+			DBG("Got Encryption for bcast");
+			broadcast = true;
+		} else if (!strcasecmp(key, "Options")) {
+			if (var != DBUS_TYPE_BYTE)
+				goto fail;
+
+			dbus_message_iter_get_basic(&value,
+							&qos->bcast.options);
+		} else if (!strcasecmp(key, "Skip")) {
+			if (var != DBUS_TYPE_UINT16)
+				goto fail;
+
+			dbus_message_iter_get_basic(&value,
+							&qos->bcast.skip);
+		} else if (!strcasecmp(key, "SyncTimeout")) {
+			if (var != DBUS_TYPE_UINT16)
+				goto fail;
+
+			dbus_message_iter_get_basic(&value,
+							&qos->bcast.sync_timeout);
+		} else if (!strcasecmp(key, "SyncCteType")) {
+			if (var != DBUS_TYPE_BYTE)
+				goto fail;
+
+			dbus_message_iter_get_basic(&value,
+							&qos->bcast.sync_cte_type);
+		} else if (!strcasecmp(key, "MSE")) {
+			if (var != DBUS_TYPE_BYTE)
+				goto fail;
+
+			dbus_message_iter_get_basic(&value,
+							&qos->bcast.mse);
+		} else if (!strcasecmp(key, "Timeout")) {
+			if (var != DBUS_TYPE_UINT16)
+				goto fail;
+
+			dbus_message_iter_get_basic(&value,
+							&qos->bcast.timeout);
 		}
 
 		dbus_message_iter_next(props);
 	}
 
+	if (broadcast)
+		memcpy(&qos->bcast.io_qos, &io_qos, sizeof(io_qos));
+	else
+		memcpy(&qos->ucast.io_qos, &io_qos, sizeof(io_qos));
+
 	return 0;
 
 fail:
@@ -456,8 +531,8 @@  static DBusMessage *set_configuration(DBusConnection *conn, DBusMessage *msg,
 	}
 
 	/* Mark CIG and CIS to be auto assigned */
-	ep->qos.cig_id = BT_ISO_QOS_CIG_UNSET;
-	ep->qos.cis_id = BT_ISO_QOS_CIS_UNSET;
+	ep->qos.ucast.cig_id = BT_ISO_QOS_CIG_UNSET;
+	ep->qos.ucast.cis_id = BT_ISO_QOS_CIS_UNSET;
 
 	if (parse_properties(&props, &ep->caps, &ep->metadata, &ep->qos) < 0) {
 		DBG("Unable to parse properties");
@@ -508,6 +583,8 @@  static void ep_free(void *data)
 
 	util_iov_free(ep->caps, 1);
 	util_iov_free(ep->metadata, 1);
+	if (bt_bap_stream_get_type(ep->stream) == BT_BAP_STREAM_TYPE_BROADCAST)
+		util_iov_free(&ep->qos.bcast.bcode, 1);
 	free(ep->path);
 	free(ep);
 }
@@ -551,6 +628,11 @@  static struct bap_ep *ep_register(struct btd_service *service,
 		i = queue_length(data->srcs);
 		suffix = "source";
 		break;
+	case BT_BAP_BROADCAST_SOURCE:
+		queue = data->broadcast;
+		i = queue_length(data->broadcast);
+		suffix = "broadcast";
+		break;
 	default:
 		return NULL;
 	}
@@ -609,12 +691,14 @@  static void bap_config(void *data, void *user_data)
 
 	ep->id = bt_bap_stream_config(ep->stream, &ep->qos, ep->caps,
 						config_cb, ep);
-	if (!ep->id) {
-		DBG("Unable to config stream");
-		util_iov_free(ep->caps, 1);
-		ep->caps = NULL;
-		util_iov_free(ep->metadata, 1);
-		ep->metadata = NULL;
+	if (bt_bap_stream_get_type(ep->stream) == BT_BAP_STREAM_TYPE_UNICAST) {
+		if (!ep->id) {
+			DBG("Unable to config stream");
+			util_iov_free(ep->caps, 1);
+			ep->caps = NULL;
+			util_iov_free(ep->metadata, 1);
+			ep->metadata = NULL;
+		}
 	}
 
 	bt_bap_stream_set_user_data(ep->stream, ep->path);
@@ -650,6 +734,7 @@  done:
 
 	queue_foreach(ep->data->srcs, bap_config, NULL);
 	queue_foreach(ep->data->snks, bap_config, NULL);
+	queue_foreach(ep->data->broadcast, bap_config, NULL);
 }
 
 static bool pac_found(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
@@ -666,8 +751,13 @@  static bool pac_found(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
 		return true;
 	}
 
-	/* TODO: Cache LRU? */
-	if (btd_service_is_initiator(service)) {
+	if (bt_bap_pac_get_type(lpac) != BT_BAP_BROADCAST_SOURCE) {
+		/* TODO: Cache LRU? */
+		if (btd_service_is_initiator(service)) {
+			if (!bt_bap_select(lpac, rpac, select_cb, ep))
+				ep->data->selecting++;
+			}
+	} else {
 		if (!bt_bap_select(lpac, rpac, select_cb, ep))
 			ep->data->selecting++;
 	}
@@ -698,11 +788,17 @@  static struct bap_ep *bap_find_ep_by_stream(struct bap_data *data,
 {
 	struct bap_ep *ep;
 
-	ep = queue_find(data->snks, match_ep_by_stream, stream);
-	if (ep)
-		return ep;
+	if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_UNICAST) {
+		ep = queue_find(data->snks, match_ep_by_stream, stream);
+		if (ep)
+			return ep;
 
-	return queue_find(data->srcs, match_ep_by_stream, stream);
+		return queue_find(data->srcs, match_ep_by_stream, stream);
+	} else if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST) {
+
+		return queue_find(data->broadcast, match_ep_by_stream, stream);
+	} else
+		return NULL;
 }
 
 static void iso_connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
@@ -734,11 +830,11 @@  static void bap_iso_qos(struct bt_bap_qos *qos, struct bt_iso_io_qos *io)
 	if (!qos)
 		return;
 
-	io->interval = qos->interval;
-	io->latency = qos->latency;
-	io->sdu = qos->sdu;
-	io->phy = qos->phy;
-	io->rtn = qos->rtn;
+	io->interval = qos->ucast.io_qos.interval;
+	io->latency = qos->ucast.io_qos.latency;
+	io->sdu = qos->ucast.io_qos.sdu;
+	io->phy = qos->ucast.io_qos.phy;
+	io->rtn = qos->ucast.io_qos.rtn;
 }
 
 static bool match_stream_qos(const void *data, const void *user_data)
@@ -749,10 +845,10 @@  static bool match_stream_qos(const void *data, const void *user_data)
 
 	qos = bt_bap_stream_get_qos((void *)stream);
 
-	if (iso_qos->ucast.cig != qos->cig_id)
+	if (iso_qos->ucast.cig != qos->ucast.cig_id)
 		return false;
 
-	return iso_qos->ucast.cis == qos->cis_id;
+	return iso_qos->ucast.cis == qos->ucast.cis_id;
 }
 
 static void iso_confirm_cb(GIOChannel *io, void *user_data)
@@ -941,6 +1037,70 @@  static void bap_connect_io(struct bap_data *data, struct bap_ep *ep,
 	bt_bap_stream_io_connecting(stream, g_io_channel_unix_get_fd(io));
 }
 
+static void bap_connect_io_broadcast(struct bap_data *data, struct bap_ep *ep,
+				struct bt_bap_stream *stream,
+				struct bt_iso_qos *qos, int defer)
+{
+	struct btd_adapter *adapter = device_get_adapter(data->device);
+	GIOChannel *io = NULL;
+	GError *err = NULL;
+	bdaddr_t dst_addr = {0};
+	char addr[18];
+	struct bt_iso_base base;
+
+	/* If IO already set and we are in the creation step, skip creating it again */
+	if (bt_bap_stream_get_io(stream) && (defer == true))
+		return;
+
+	if (ep->io_id) {
+		g_source_remove(ep->io_id);
+		ep->io_id = 0;
+	}
+	base.base_len = ep->caps->iov_len;
+
+	memset(base.base, 0, 248);
+	memcpy(base.base, ep->caps->iov_base, base.base_len);
+	DBG("ep %p stream %p defer %s", ep, stream, defer ? "true" : "false");
+	ba2str(btd_adapter_get_address(adapter), addr);
+
+	/* Just create socket and advance to the configured state (when defer = true) */
+	if (defer == true) {
+		io = bt_io_connect(bap_connect_io_cb, ep, NULL, &err,
+				BT_IO_OPT_SOURCE_BDADDR,
+				btd_adapter_get_address(adapter),
+				BT_IO_OPT_DEST_BDADDR,
+				&dst_addr,
+				BT_IO_OPT_DEST_TYPE,
+				BDADDR_LE_PUBLIC,
+				BT_IO_OPT_MODE, BT_IO_MODE_ISO,
+				BT_IO_OPT_QOS, qos,
+				BT_IO_OPT_BASE, &base,
+				BT_IO_OPT_DEFER_TIMEOUT, defer,
+				BT_IO_OPT_INVALID);
+
+		if (!io) {
+			error("%s", err->message);
+			g_error_free(err);
+			return;
+		}
+
+		ep->io_id = g_io_add_watch(io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				bap_io_disconnected, ep);
+
+		ep->io = io;
+
+		bt_bap_stream_io_connecting(stream, g_io_channel_unix_get_fd(io));
+	} else { /* Advance stream state to Streaming */
+		io = ep->io;
+//		de-comment when streaming state is working in kernel
+//		bt_io_broadcast_stream(&err, g_io_channel_unix_get_fd(io),
+//				BT_IO_OPT_DEST_BDADDR, device_get_address(ep->data->device),
+//				BT_IO_OPT_DEST_TYPE, device_get_le_address_type(ep->data->device),
+//				BT_IO_OPT_QOS, qos,
+//				BT_IO_OPT_INVALID);
+	}
+}
+
 static void bap_listen_io(struct bap_data *data, struct bt_bap_stream *stream,
 						struct bt_iso_qos *qos)
 {
@@ -987,20 +1147,44 @@  static void bap_create_io(struct bap_data *data, struct bap_ep *ep,
 	if (!queue_find(data->streams, NULL, stream))
 		queue_push_tail(data->streams, stream);
 
-	if (!bt_bap_stream_io_get_qos(stream, &qos[0], &qos[1])) {
-		error("bt_bap_stream_get_qos_links: failed");
-		return;
+	if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_UNICAST) {
+		if (!bt_bap_stream_io_get_qos(stream, &qos[0], &qos[1])) {
+			error("bt_bap_stream_get_qos_links: failed");
+			return;
+		}
 	}
 
 	memset(&iso_qos, 0, sizeof(iso_qos));
-	iso_qos.ucast.cig = qos[0] ? qos[0]->cig_id : qos[1]->cig_id;
-	iso_qos.ucast.cis = qos[0] ? qos[0]->cis_id : qos[1]->cis_id;
+	if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST) {
+		if (defer == true) {
+			iso_qos.bcast.big = ep->qos.bcast.big;
+			iso_qos.bcast.bis = ep->qos.bcast.bis;
+			iso_qos.bcast.sync_interval = ep->qos.bcast.sync_interval;
+			iso_qos.bcast.packing = ep->qos.bcast.packing;
+			iso_qos.bcast.framing = ep->qos.bcast.framing;
+			iso_qos.bcast.encryption = ep->qos.bcast.encryption;
+			memcpy(iso_qos.bcast.bcode, ep->qos.bcast.bcode.iov_base, 16);
+			iso_qos.bcast.options = ep->qos.bcast.options;
+			iso_qos.bcast.skip = ep->qos.bcast.skip;
+			iso_qos.bcast.sync_timeout = ep->qos.bcast.sync_timeout;
+			iso_qos.bcast.sync_cte_type = ep->qos.bcast.sync_cte_type;
+			iso_qos.bcast.mse = ep->qos.bcast.mse;
+			iso_qos.bcast.timeout = ep->qos.bcast.timeout;
+			memcpy(&iso_qos.bcast.out, &ep->qos.bcast.io_qos, sizeof(struct bt_iso_io_qos));
+		}
+	} else {
+		iso_qos.ucast.cig = qos[0] ? qos[0]->ucast.cig_id : qos[1]->ucast.cig_id;
+		iso_qos.ucast.cis = qos[0] ? qos[0]->ucast.cis_id : qos[1]->ucast.cis_id;
 
-	bap_iso_qos(qos[0], &iso_qos.ucast.in);
-	bap_iso_qos(qos[1], &iso_qos.ucast.out);
+		bap_iso_qos(qos[0], &iso_qos.ucast.in);
+		bap_iso_qos(qos[1], &iso_qos.ucast.out);
+	}
 
 	if (ep)
-		bap_connect_io(data, ep, stream, &iso_qos, defer);
+		if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST)
+			bap_connect_io_broadcast(data, ep, stream, &iso_qos, defer);
+		else
+			bap_connect_io(data, ep, stream, &iso_qos, defer);
 	else
 		bap_listen_io(data, stream, &iso_qos);
 }
@@ -1039,12 +1223,14 @@  static void bap_state(struct bt_bap_stream *stream, uint8_t old_state,
 			}
 
 
-			/* Wait QoS response to respond */
-			ep->id = bt_bap_stream_qos(stream, &ep->qos, qos_cb,
-									ep);
-			if (!ep->id) {
-				error("Failed to Configure QoS");
-				bt_bap_stream_release(stream, NULL, NULL);
+			if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_UNICAST) {
+				/* Wait QoS response to respond */
+				ep->id = bt_bap_stream_qos(stream, &ep->qos, qos_cb,
+										ep);
+				if (!ep->id) {
+					error("Failed to Configure QoS");
+					bt_bap_stream_release(stream, NULL, NULL);
+				}
 			}
 		}
 		break;
@@ -1055,6 +1241,12 @@  static void bap_state(struct bt_bap_stream *stream, uint8_t old_state,
 		if (ep)
 			bap_create_io(data, ep, stream, false);
 		break;
+	case BT_BAP_STREAM_STATE_STREAMING:
+		if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST) {
+			if (ep)
+				bap_create_io(data, ep, stream, false);
+		}
+		break;
 	}
 }
 
@@ -1074,6 +1266,20 @@  static void pac_added(struct bt_bap_pac *pac, void *user_data)
 	bt_bap_foreach_pac(data->bap, BT_BAP_SINK, pac_found, service);
 }
 
+static void pac_added_broadcast(struct bt_bap_pac *pac, void *user_data)
+{
+	struct btd_service *service = user_data;
+	struct bap_data *data;
+
+	if (bt_bap_pac_get_type(pac) == BT_BAP_BROADCAST_SOURCE) {
+		DBG("pac %p", pac);
+
+		data = btd_service_get_user_data(service);
+
+		bt_bap_foreach_pac(data->bap, BT_BAP_BROADCAST_SOURCE, pac_found, service);
+	}
+}
+
 static bool ep_match_pac(const void *data, const void *match_data)
 {
 	const struct bap_ep *ep = data;
@@ -1114,6 +1320,38 @@  static void pac_removed(struct bt_bap_pac *pac, void *user_data)
 	ep_unregister(ep);
 }
 
+static void pac_removed_broadcast(struct bt_bap_pac *pac, void *user_data)
+{
+	struct btd_service *service = user_data;
+	struct bap_data *data;
+	struct queue *queue;
+	struct bap_ep *ep;
+
+	DBG("pac %p", pac);
+
+	data = btd_service_get_user_data(service);
+
+	switch (bt_bap_pac_get_type(pac)) {
+	case BT_BAP_SINK:
+		queue = data->srcs;
+		break;
+	case BT_BAP_SOURCE:
+		queue = data->snks;
+		break;
+	case BT_BAP_BROADCAST_SOURCE:
+		queue = data->broadcast;
+		break;
+	default:
+		return;
+	}
+
+	ep = queue_remove_if(queue, ep_match_pac, pac);
+	if (!ep)
+		return;
+
+	ep_unregister(ep);
+}
+
 static struct bap_data *bap_data_new(struct btd_device *device)
 {
 	struct bap_data *data;
@@ -1122,6 +1360,7 @@  static struct bap_data *bap_data_new(struct btd_device *device)
 	data->device = device;
 	data->srcs = queue_new();
 	data->snks = queue_new();
+	data->broadcast = queue_new();
 
 	return data;
 }
@@ -1154,6 +1393,14 @@  static bool match_data(const void *data, const void *match_data)
 	return bdata->bap == bap;
 }
 
+static bool match_data_bap_data(const void *data, const void *match_data)
+{
+	const struct bap_data *bdata = data;
+	const struct btd_adapter *adapter = match_data;
+
+	return bdata->user_data == adapter;
+}
+
 static void bap_connecting(struct bt_bap_stream *stream, bool state, int fd,
 							void *user_data)
 {
@@ -1178,26 +1425,49 @@  static void bap_connecting(struct bt_bap_stream *stream, bool state, int fd,
 
 	g_io_channel_set_close_on_unref(io, FALSE);
 
-	/* Attempt to get CIG/CIS if they have not been set */
-	if (ep->qos.cig_id == BT_ISO_QOS_CIG_UNSET ||
-				ep->qos.cis_id == BT_ISO_QOS_CIS_UNSET) {
-		struct bt_iso_qos qos;
-		GError *err = NULL;
+	if (bt_bap_stream_get_type(ep->stream) == BT_BAP_STREAM_TYPE_UNICAST) {
+		/* Attempt to get CIG/CIS if they have not been set */
+		if (ep->qos.ucast.cig_id == BT_ISO_QOS_CIG_UNSET ||
+					ep->qos.ucast.cis_id == BT_ISO_QOS_CIS_UNSET) {
+			struct bt_iso_qos qos;
+			GError *err = NULL;
+
+			if (!bt_io_get(io, &err, BT_IO_OPT_QOS, &qos,
+						BT_IO_OPT_INVALID)) {
+				error("%s", err->message);
+				g_error_free(err);
+				g_io_channel_unref(io);
+				return;
+			}
 
-		if (!bt_io_get(io, &err, BT_IO_OPT_QOS, &qos,
-					BT_IO_OPT_INVALID)) {
-			error("%s", err->message);
-			g_error_free(err);
-			g_io_channel_unref(io);
-			return;
+			ep->qos.ucast.cig_id = qos.ucast.cig;
+			ep->qos.ucast.cis_id = qos.ucast.cis;
 		}
 
-		ep->qos.cig_id = qos.ucast.cig;
-		ep->qos.cis_id = qos.ucast.cis;
-	}
+		DBG("stream %p fd %d: CIG 0x%02x CIS 0x%02x", stream, fd,
+						ep->qos.ucast.cig_id, ep->qos.ucast.cis_id);
+	} else if (bt_bap_stream_get_type(ep->stream) == BT_BAP_STREAM_TYPE_BROADCAST) {
+		/* Attempt to get BIG/BIS if they have not been set */
+		if (ep->qos.bcast.big == BT_ISO_QOS_BIG_UNSET ||
+					ep->qos.bcast.bis == BT_ISO_QOS_BIS_UNSET) {
+			struct bt_iso_qos qos;
+			GError *err = NULL;
+
+			if (!bt_io_get(io, &err, BT_IO_OPT_QOS, &qos,
+						BT_IO_OPT_INVALID)) {
+				error("%s", err->message);
+				g_error_free(err);
+				g_io_channel_unref(io);
+				return;
+			}
+
+			ep->qos.bcast.big = qos.bcast.big;
+			ep->qos.bcast.bis = qos.bcast.bis;
+		}
 
-	DBG("stream %p fd %d: CIG 0x%02x CIS 0x%02x", stream, fd,
-					ep->qos.cig_id, ep->qos.cis_id);
+		DBG("stream %p fd %d: BIG 0x%02x BIS 0x%02x", stream, fd,
+						ep->qos.bcast.big, ep->qos.bcast.bis);
+	}
 }
 
 static void bap_attached(struct bt_bap *bap, void *user_data)
@@ -1345,6 +1615,68 @@  static int bap_disconnect(struct btd_service *service)
 	return 0;
 }
 
+static int bap_adapter_probe(struct btd_profile *p,
+				struct btd_adapter *adapter)
+{
+	struct btd_device *device = btd_adapter_get_device(adapter, BDADDR_ANY, BDADDR_LE_PUBLIC);
+	struct btd_gatt_database *database = btd_adapter_get_database(adapter);
+	struct btd_service *service = service_create(device, p);
+	struct bap_data *data;
+	char addr[18];
+
+	ba2str(device_get_address(device), addr);
+	DBG("%s", addr);
+
+	if (!btd_adapter_has_exp_feature(adapter, EXP_FEAT_ISO_SOCKET)) {
+		error("BAP requires ISO Socket which is not enabled");
+		return -ENOTSUP;
+	}
+
+	data = bap_data_new(device);
+	data->service = service;
+
+	data->bap = bt_bap_new(btd_gatt_database_get_db(database),
+					btd_device_get_gatt_db(device));
+	if (!data->bap) {
+		error("Unable to create BAP instance");
+		free(data);
+		return -EINVAL;
+	}
+
+	bap_data_add(data);
+
+	if (!bt_bap_attach_broadcast(data->bap)) {
+		error("BAP unable to attach");
+		return -EINVAL;
+	}
+
+	data->state_id = bt_bap_state_register(data->bap, bap_state,
+						bap_connecting, data, NULL);
+	data->pac_id = bt_bap_pac_register(data->bap, pac_added_broadcast,
+						pac_removed_broadcast, service, NULL);
+
+	bt_bap_set_user_data(data->bap, service);
+	bap_data_set_user_data(data, adapter);
+	return 0;
+}
+
+static void bap_adapter_remove(struct btd_profile *p,
+					struct btd_adapter *adapter)
+{
+	struct bap_data *data = queue_find(sessions, match_data_bap_data, adapter);
+	char addr[18];
+
+	ba2str(btd_adapter_get_address(adapter), addr);
+	DBG("%s", addr);
+
+	if (!data) {
+		error("BAP service not handled by profile");
+		return;
+	}
+
+	bap_data_remove(data);
+}
+
 static struct btd_profile bap_profile = {
 	.name		= "bap",
 	.priority	= BTD_PROFILE_PRIORITY_MEDIUM,
@@ -1353,6 +1685,8 @@  static struct btd_profile bap_profile = {
 	.device_remove	= bap_remove,
 	.accept		= bap_accept,
 	.disconnect	= bap_disconnect,
+	.adapter_probe	= bap_adapter_probe,
+	.adapter_remove	= bap_adapter_remove,
 	.auto_connect	= true,
 };
 
diff --git a/profiles/audio/media.c b/profiles/audio/media.c
index 6ce668e31..4c7402fe9 100644
--- a/profiles/audio/media.c
+++ b/profiles/audio/media.c
@@ -6,7 +6,7 @@ 
  *  Copyright (C) 2006-2007  Nokia Corporation
  *  Copyright (C) 2004-2009  Marcel Holtmann <marcel@holtmann.org>
  *  Copyright (C) 2011  BMW Car IT GmbH. All rights reserved.
- *
+ *  Copyright 2023 NXP
  *
  */
 
@@ -748,7 +748,11 @@  static int parse_select_properties(DBusMessageIter *props, struct iovec *caps,
 					struct bt_bap_qos *qos)
 {
 	const char *key;
+	struct bt_bap_io_qos io_qos;
+	uint8_t framing = 0;
+	bool broadcast = false;
 
+	memset(&io_qos, 0, sizeof(io_qos));
 	while (dbus_message_iter_get_arg_type(props) == DBUS_TYPE_DICT_ENTRY) {
 		DBusMessageIter value, entry;
 		int var;
@@ -777,17 +781,27 @@  static int parse_select_properties(DBusMessageIter *props, struct iovec *caps,
 			if (var != DBUS_TYPE_BYTE)
 				goto fail;
 
-			dbus_message_iter_get_basic(&value, &qos->cig_id);
+			dbus_message_iter_get_basic(&value, &qos->ucast.cig_id);
+		} else if (!strcasecmp(key, "BIG")) {
+			if (var != DBUS_TYPE_BYTE)
+				goto fail;
+
+			dbus_message_iter_get_basic(&value, &qos->bcast.big);
 		} else if (!strcasecmp(key, "CIS")) {
 			if (var != DBUS_TYPE_BYTE)
 				goto fail;
 
-			dbus_message_iter_get_basic(&value, &qos->cis_id);
+			dbus_message_iter_get_basic(&value, &qos->ucast.cig_id);
+		} else if (!strcasecmp(key, "BIS")) {
+			if (var != DBUS_TYPE_BYTE)
+				goto fail;
+
+			dbus_message_iter_get_basic(&value, &qos->bcast.bis);
 		} else if (!strcasecmp(key, "Interval")) {
 			if (var != DBUS_TYPE_UINT32)
 				goto fail;
 
-			dbus_message_iter_get_basic(&value, &qos->interval);
+			dbus_message_iter_get_basic(&value, &io_qos.interval);
 		} else if (!strcasecmp(key, "Framing")) {
 			dbus_bool_t val;
 
@@ -796,7 +810,7 @@  static int parse_select_properties(DBusMessageIter *props, struct iovec *caps,
 
 			dbus_message_iter_get_basic(&value, &val);
 
-			qos->framing = val;
+			framing = val;
 		} else if (!strcasecmp(key, "PHY")) {
 			const char *str;
 
@@ -806,42 +820,106 @@  static int parse_select_properties(DBusMessageIter *props, struct iovec *caps,
 			dbus_message_iter_get_basic(&value, &str);
 
 			if (!strcasecmp(str, "1M"))
-				qos->phy = 0x01;
+				io_qos.phy = 0x01;
 			else if (!strcasecmp(str, "2M"))
-				qos->phy = 0x02;
+				io_qos.phy = 0x02;
 			else
 				goto fail;
 		} else if (!strcasecmp(key, "SDU")) {
 			if (var != DBUS_TYPE_UINT16)
 				goto fail;
 
-			dbus_message_iter_get_basic(&value, &qos->sdu);
+			dbus_message_iter_get_basic(&value, &io_qos.sdu);
 		} else if (!strcasecmp(key, "Retransmissions")) {
 			if (var != DBUS_TYPE_BYTE)
 				goto fail;
 
-			dbus_message_iter_get_basic(&value, &qos->rtn);
+			dbus_message_iter_get_basic(&value, &io_qos.rtn);
 		} else if (!strcasecmp(key, "Latency")) {
 			if (var != DBUS_TYPE_UINT16)
 				goto fail;
 
-			dbus_message_iter_get_basic(&value, &qos->latency);
+			dbus_message_iter_get_basic(&value, &io_qos.latency);
 		} else if (!strcasecmp(key, "Delay")) {
 			if (var != DBUS_TYPE_UINT32)
 				goto fail;
 
-			dbus_message_iter_get_basic(&value, &qos->delay);
+			dbus_message_iter_get_basic(&value, &qos->ucast.delay);
 		} else if (!strcasecmp(key, "TargetLatency")) {
 			if (var != DBUS_TYPE_BYTE)
 				goto fail;
 
 			dbus_message_iter_get_basic(&value,
-							&qos->target_latency);
+							&qos->ucast.target_latency);
+		} else if (!strcasecmp(key, "Encryption")) {
+			if (var != DBUS_TYPE_BYTE)
+				goto fail;
+
+			dbus_message_iter_get_basic(&value,
+							&qos->bcast.encryption);
+			broadcast = true;
+		} else if (!strcasecmp(key, "Options")) {
+			if (var != DBUS_TYPE_BYTE)
+				goto fail;
+
+			dbus_message_iter_get_basic(&value,
+							&qos->bcast.options);
+		} else if (!strcasecmp(key, "Skip")) {
+			if (var != DBUS_TYPE_UINT16)
+				goto fail;
+
+			dbus_message_iter_get_basic(&value,
+							&qos->bcast.skip);
+		} else if (!strcasecmp(key, "SyncTimeout")) {
+			if (var != DBUS_TYPE_UINT16)
+				goto fail;
+
+			dbus_message_iter_get_basic(&value,
+							&qos->bcast.sync_timeout);
+		} else if (!strcasecmp(key, "SyncCteType")) {
+			if (var != DBUS_TYPE_BYTE)
+				goto fail;
+
+			dbus_message_iter_get_basic(&value,
+							&qos->bcast.sync_cte_type);
+
+		} else if (!strcasecmp(key, "SyncInterval")) {
+			if (var != DBUS_TYPE_BYTE)
+				goto fail;
+
+			dbus_message_iter_get_basic(&value,
+							&qos->bcast.sync_interval);
+		} else if (!strcasecmp(key, "MSE")) {
+			if (var != DBUS_TYPE_BYTE)
+				goto fail;
+
+			dbus_message_iter_get_basic(&value,
+							&qos->bcast.mse);
+		} else if (!strcasecmp(key, "Timeout")) {
+			if (var != DBUS_TYPE_UINT16)
+				goto fail;
+
+			dbus_message_iter_get_basic(&value,
+							&qos->bcast.timeout);
+		} else if (!strcasecmp(key, "BroadcastCode")) {
+			if (var != DBUS_TYPE_ARRAY)
+				goto fail;
+
+			parse_array(&value, &qos->bcast.bcode);
 		}
 
 		dbus_message_iter_next(props);
 	}
 
+	if (broadcast) {
+		memcpy(&qos->bcast.io_qos, &io_qos, sizeof(io_qos));
+		qos->bcast.framing = framing;
+
+	} else {
+		memcpy(&qos->ucast.io_qos, &io_qos, sizeof(io_qos));
+		qos->ucast.framing = framing;
+	}
+
 	return 0;
 
 fail:
@@ -875,8 +953,8 @@  static void pac_select_cb(struct media_endpoint *endpoint, void *ret, int size,
 	memset(&qos, 0, sizeof(qos));
 
 	/* Mark CIG and CIS to be auto assigned */
-	qos.cig_id = BT_ISO_QOS_CIG_UNSET;
-	qos.cis_id = BT_ISO_QOS_CIS_UNSET;
+	qos.ucast.cig_id = BT_ISO_QOS_CIG_UNSET;
+	qos.ucast.cis_id = BT_ISO_QOS_CIS_UNSET;
 
 	memset(&caps, 0, sizeof(caps));
 	memset(&meta, 0, sizeof(meta));
@@ -1166,15 +1244,13 @@  static bool endpoint_init_pac(struct media_endpoint *endpoint, uint8_t type,
 
 	endpoint->pac = bt_bap_add_vendor_pac(db, name, type, endpoint->codec,
 				endpoint->cid, endpoint->vid, &endpoint->qos,
-				&data, metadata);
+				&data, metadata, &pac_ops, endpoint);
 	if (!endpoint->pac) {
 		error("Unable to create PAC");
 		free(metadata);
 		return false;
 	}
 
-	bt_bap_pac_set_ops(endpoint->pac, &pac_ops, endpoint);
-
 	DBG("PAC %s registered", name);
 
 	free(name);
@@ -1193,6 +1269,11 @@  static bool endpoint_init_pac_source(struct media_endpoint *endpoint, int *err)
 	return endpoint_init_pac(endpoint, BT_BAP_SOURCE, err);
 }
 
+static bool endpoint_init_broadcast_source(struct media_endpoint *endpoint, int *err)
+{
+	return endpoint_init_pac(endpoint, BT_BAP_BROADCAST_SOURCE, err);
+}
+
 static bool endpoint_properties_exists(const char *uuid,
 						struct btd_device *dev,
 						void *user_data)
@@ -1295,6 +1376,18 @@  static bool experimental_endpoint_supported(struct btd_adapter *adapter)
 	return g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL;
 }
 
+static bool experimental_broadcaster_ep_supported(struct btd_adapter *adapter)
+{
+
+	if (!btd_adapter_has_exp_feature(adapter, EXP_FEAT_ISO_SOCKET))
+		return false;
+
+	if (!btd_adapter_has_settings(adapter, MGMT_SETTING_ISO_BROADCASTER))
+		return false;
+
+	return g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL;
+}
+
 static struct media_endpoint_init {
 	const char *uuid;
 	bool (*func)(struct media_endpoint *endpoint, int *err);
@@ -1308,6 +1401,8 @@  static struct media_endpoint_init {
 				experimental_endpoint_supported },
 	{ PAC_SOURCE_UUID, endpoint_init_pac_source,
 				experimental_endpoint_supported },
+	{ BROADCAST_AUDIO_ANNOUNCEMENT_SERVICE_UUID, endpoint_init_broadcast_source,
+			experimental_broadcaster_ep_supported },
 };
 
 static struct media_endpoint *
diff --git a/profiles/audio/transport.c b/profiles/audio/transport.c
index 9172d167e..a055e4f05 100644
--- a/profiles/audio/transport.c
+++ b/profiles/audio/transport.c
@@ -5,6 +5,7 @@ 
  *
  *  Copyright (C) 2006-2007  Nokia Corporation
  *  Copyright (C) 2004-2009  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright 2023 NXP
  *
  *
  */
@@ -525,6 +526,13 @@  static void media_owner_add(struct media_owner *owner,
 	owner->pending = req;
 }
 
+static void *get_stream_bap(struct media_transport *transport)
+{
+	struct bap_transport *bap = transport->data;
+
+	return bap->stream;
+}
+
 static DBusMessage *acquire(DBusConnection *conn, DBusMessage *msg,
 					void *data)
 {
@@ -540,15 +548,22 @@  static DBusMessage *acquire(DBusConnection *conn, DBusMessage *msg,
 		return btd_error_not_authorized(msg);
 
 	owner = media_owner_create(msg);
+	if (bt_bap_stream_get_type(get_stream_bap(transport)) == BT_BAP_STREAM_TYPE_BROADCAST) {
+		req = media_request_create(msg, 0x00);
+		media_owner_add(owner, req);
+		media_transport_set_owner(transport, owner);
+	}
 	id = transport->resume(transport, owner);
 	if (id == 0) {
 		media_owner_free(owner);
 		return btd_error_not_authorized(msg);
 	}
 
-	req = media_request_create(msg, id);
-	media_owner_add(owner, req);
-	media_transport_set_owner(transport, owner);
+	if (bt_bap_stream_get_type(get_stream_bap(transport)) == BT_BAP_STREAM_TYPE_UNICAST) {
+		req = media_request_create(msg, id);
+		media_owner_add(owner, req);
+		media_transport_set_owner(transport, owner);
+	}
 
 	return NULL;
 }
@@ -828,7 +843,7 @@  static gboolean qos_exists(const GDBusPropertyTable *property, void *data)
 	struct media_transport *transport = data;
 	struct bap_transport *bap = transport->data;
 
-	return bap->qos.phy != 0x00;
+	return bap->qos.ucast.io_qos.phy != 0x00;
 }
 
 static gboolean get_cig(const GDBusPropertyTable *property,
@@ -838,7 +853,7 @@  static gboolean get_cig(const GDBusPropertyTable *property,
 	struct bap_transport *bap = transport->data;
 
 	dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE,
-							&bap->qos.cig_id);
+							&bap->qos.ucast.cig_id);
 
 	return TRUE;
 }
@@ -850,7 +865,7 @@  static gboolean get_cis(const GDBusPropertyTable *property,
 	struct bap_transport *bap = transport->data;
 
 	dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE,
-							&bap->qos.cis_id);
+							&bap->qos.ucast.cis_id);
 
 	return TRUE;
 }
@@ -862,7 +877,7 @@  static gboolean get_interval(const GDBusPropertyTable *property,
 	struct bap_transport *bap = transport->data;
 
 	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32,
-							&bap->qos.interval);
+							&bap->qos.ucast.io_qos.interval);
 
 	return TRUE;
 }
@@ -872,7 +887,7 @@  static gboolean get_framing(const GDBusPropertyTable *property,
 {
 	struct media_transport *transport = data;
 	struct bap_transport *bap = transport->data;
-	dbus_bool_t val = bap->qos.framing;
+	dbus_bool_t val = bap->qos.ucast.framing;
 
 	dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &val);
 
@@ -885,7 +900,7 @@  static gboolean get_phy(const GDBusPropertyTable *property,
 	struct media_transport *transport = data;
 	struct bap_transport *bap = transport->data;
 
-	dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &bap->qos.phy);
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &bap->qos.ucast.io_qos.phy);
 
 	return TRUE;
 }
@@ -896,7 +911,7 @@  static gboolean get_sdu(const GDBusPropertyTable *property,
 	struct media_transport *transport = data;
 	struct bap_transport *bap = transport->data;
 
-	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &bap->qos.sdu);
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &bap->qos.ucast.io_qos.sdu);
 
 	return TRUE;
 }
@@ -907,7 +922,7 @@  static gboolean get_retransmissions(const GDBusPropertyTable *property,
 	struct media_transport *transport = data;
 	struct bap_transport *bap = transport->data;
 
-	dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &bap->qos.rtn);
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &bap->qos.ucast.io_qos.rtn);
 
 	return TRUE;
 }
@@ -919,7 +934,7 @@  static gboolean get_latency(const GDBusPropertyTable *property,
 	struct bap_transport *bap = transport->data;
 
 	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16,
-							&bap->qos.latency);
+							&bap->qos.ucast.io_qos.latency);
 
 	return TRUE;
 }
@@ -930,7 +945,7 @@  static gboolean get_delay(const GDBusPropertyTable *property,
 	struct media_transport *transport = data;
 	struct bap_transport *bap = transport->data;
 
-	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &bap->qos.delay);
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &bap->qos.ucast.delay);
 
 	return TRUE;
 }
@@ -1478,13 +1493,6 @@  static void bap_connecting(struct bt_bap_stream *stream, bool state, int fd,
 	bap_update_links(transport);
 }
 
-static void *get_stream_bap(struct media_transport *transport)
-{
-	struct bap_transport *bap = transport->data;
-
-	return bap->stream;
-}
-
 static void free_bap(void *data)
 {
 	struct bap_transport *bap = data;
@@ -1555,7 +1563,8 @@  struct media_transport *media_transport_create(struct btd_device *device,
 			goto fail;
 		properties = a2dp_properties;
 	} else if (!strcasecmp(uuid, PAC_SINK_UUID) ||
-				!strcasecmp(uuid, PAC_SOURCE_UUID)) {
+				!strcasecmp(uuid, PAC_SOURCE_UUID) ||
+				!strcasecmp(uuid, BROADCAST_AUDIO_ANNOUNCEMENT_SERVICE_UUID)) {
 		if (media_transport_init_bap(transport, stream) < 0)
 			goto fail;
 		properties = bap_properties;
diff --git a/src/shared/bap.c b/src/shared/bap.c
index 6131c3128..54d72cf35 100644
--- a/src/shared/bap.c
+++ b/src/shared/bap.c
@@ -4,6 +4,7 @@ 
  *  BlueZ - Bluetooth protocol stack for Linux
  *
  *  Copyright (C) 2022  Intel Corporation. All rights reserved.
+ *  Copyright 2023 NXP
  *
  */
 
@@ -120,6 +121,8 @@  struct bt_bap_db {
 	struct bt_ascs *ascs;
 	struct queue *sinks;
 	struct queue *sources;
+	struct queue *broadcast_sources;
+	struct queue *broadcast_sinks;
 };
 
 struct bt_bap_req {
@@ -622,6 +625,18 @@  static struct bt_bap_endpoint *bap_endpoint_new(struct bt_bap_db *bdb,
 	return ep;
 }
 
+static struct bt_bap_endpoint *bap_endpoint_new_broacast(struct bt_bap_db *bdb)
+{
+	struct bt_bap_endpoint *ep;
+
+	ep = new0(struct bt_bap_endpoint, 1);
+	ep->bdb = bdb;
+	ep->attr = NULL;
+	ep->dir = BT_BAP_BROADCAST_SOURCE;
+
+	return ep;
+}
+
 static struct bt_bap_endpoint *bap_get_endpoint(struct queue *endpoints,
 						struct bt_bap_db *db,
 						struct gatt_db_attribute *attr)
@@ -644,6 +659,26 @@  static struct bt_bap_endpoint *bap_get_endpoint(struct queue *endpoints,
 	return ep;
 }
 
+static struct bt_bap_endpoint *bap_get_endpoint_broadcast(struct queue *endpoints,
+						struct bt_bap_db *db)
+{
+	struct bt_bap_endpoint *ep;
+
+	if (!db)
+		return NULL;
+
+	if (queue_length(endpoints) > 0)
+		return queue_peek_head(endpoints);
+
+	ep = bap_endpoint_new_broacast(db);
+	if (!ep)
+		return NULL;
+
+	queue_push_tail(endpoints, ep);
+
+	return ep;
+}
+
 static bool bap_endpoint_match_id(const void *data, const void *match_data)
 {
 	const struct bt_bap_endpoint *ep = data;
@@ -861,15 +896,15 @@  static void stream_notify_qos(struct bt_bap_stream *stream)
 	status->state = ep->state;
 
 	qos = (void *)status->params;
-	qos->cis_id = stream->qos.cis_id;
-	qos->cig_id = stream->qos.cig_id;
-	put_le24(stream->qos.interval, qos->interval);
-	qos->framing = stream->qos.framing;
-	qos->phy = stream->qos.phy;
-	qos->sdu = cpu_to_le16(stream->qos.sdu);
-	qos->rtn = stream->qos.rtn;
-	qos->latency = cpu_to_le16(stream->qos.latency);
-	put_le24(stream->qos.delay, qos->pd);
+	qos->cis_id = stream->qos.ucast.cis_id;
+	qos->cig_id = stream->qos.ucast.cig_id;
+	put_le24(stream->qos.ucast.io_qos.interval, qos->interval);
+	qos->framing = stream->qos.ucast.framing;
+	qos->phy = stream->qos.ucast.io_qos.phy;
+	qos->sdu = cpu_to_le16(stream->qos.ucast.io_qos.sdu);
+	qos->rtn = stream->qos.ucast.io_qos.rtn;
+	qos->latency = cpu_to_le16(stream->qos.ucast.io_qos.latency);
+	put_le24(stream->qos.ucast.delay, qos->pd);
 
 	gatt_db_attribute_notify(ep->attr, (void *) status, len,
 					bt_bap_get_att(stream->bap));
@@ -898,8 +933,8 @@  static void stream_notify_metadata(struct bt_bap_stream *stream)
 	status->state = ep->state;
 
 	meta = (void *)status->params;
-	meta->cis_id = stream->qos.cis_id;
-	meta->cig_id = stream->qos.cig_id;
+	meta->cis_id = stream->qos.ucast.cis_id;
+	meta->cig_id = stream->qos.ucast.cig_id;
 
 	if (stream->meta) {
 		meta->len = stream->meta->iov_len;
@@ -1245,6 +1280,36 @@  static void bap_stream_state_changed(struct bt_bap_stream *stream)
 	bt_bap_unref(bap);
 }
 
+static void stream_set_state_broadcast(struct bt_bap_stream *stream, uint8_t state)
+{
+	struct bt_bap_endpoint *ep = stream->ep;
+	struct bt_bap *bap = stream->bap;
+	const struct queue_entry *entry;
+
+	ep->old_state = ep->state;
+	ep->state = state;
+
+	bt_bap_ref(bap);
+
+	for (entry = queue_get_entries(bap->state_cbs); entry;
+							entry = entry->next) {
+		struct bt_bap_state *state = entry->data;
+
+		if (state->func)
+			state->func(stream, stream->ep->old_state,
+					stream->ep->state, state->data);
+	}
+
+	/* Post notification updates */
+	switch (stream->ep->state) {
+	case BT_ASCS_ASE_STATE_IDLE:
+		bap_stream_detach(stream);
+		break;
+	}
+
+	bt_bap_unref(bap);
+}
+
 static void stream_set_state(struct bt_bap_stream *stream, uint8_t state)
 {
 	struct bt_bap_endpoint *ep = stream->ep;
@@ -1381,6 +1446,11 @@  static void ep_config_cb(struct bt_bap_stream *stream, int err)
 	if (err)
 		return;
 
+	if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST)	{
+		stream_set_state_broadcast(stream, BT_BAP_STREAM_STATE_CONFIG);
+		return;
+	}
+
 	stream_set_state(stream, BT_BAP_STREAM_STATE_CONFIG);
 }
 
@@ -1560,20 +1630,20 @@  static uint8_t ascs_qos(struct bt_ascs *ascs, struct bt_bap *bap,
 
 	memset(&qos, 0, sizeof(qos));
 
-	qos.cig_id = req->cig;
-	qos.cis_id = req->cis;
-	qos.interval = get_le24(req->interval);
-	qos.framing = req->framing;
-	qos.phy = req->phy;
-	qos.sdu = le16_to_cpu(req->sdu);
-	qos.rtn = req->rtn;
-	qos.latency = le16_to_cpu(req->latency);
-	qos.delay = get_le24(req->pd);
+	qos.ucast.cig_id = req->cig;
+	qos.ucast.cis_id = req->cis;
+	qos.ucast.io_qos.interval = get_le24(req->interval);
+	qos.ucast.framing = req->framing;
+	qos.ucast.io_qos.phy = req->phy;
+	qos.ucast.io_qos.sdu = le16_to_cpu(req->sdu);
+	qos.ucast.io_qos.rtn = req->rtn;
+	qos.ucast.io_qos.latency = le16_to_cpu(req->latency);
+	qos.ucast.delay = get_le24(req->pd);
 
 	DBG(bap, "CIG 0x%02x CIS 0x%02x interval %u framing 0x%02x "
 			"phy 0x%02x SDU %u rtn %u latency %u pd %u",
-			req->cig, req->cis, qos.interval, qos.framing, qos.phy,
-			qos.sdu, qos.rtn, qos.latency, qos.delay);
+			req->cig, req->cis, qos.ucast.io_qos.interval, qos.ucast.framing, qos.ucast.io_qos.phy,
+			qos.ucast.io_qos.sdu, qos.ucast.io_qos.rtn, qos.ucast.io_qos.latency, qos.ucast.delay);
 
 	ep = bap_get_local_endpoint_id(bap, req->ase);
 	if (!ep) {
@@ -2204,6 +2274,8 @@  static struct bt_bap_db *bap_db_new(struct gatt_db *db)
 	bdb->db = gatt_db_ref(db);
 	bdb->sinks = queue_new();
 	bdb->sources = queue_new();
+	bdb->broadcast_sources = queue_new();
+	bdb->broadcast_sinks = queue_new();
 
 	if (!bap_db)
 		bap_db = queue_new();
@@ -2379,6 +2451,16 @@  static void bap_add_source(struct bt_bap_pac *pac)
 				iov.iov_len, NULL);
 }
 
+static void bap_add_broadcast_source(struct bt_bap_pac *pac)
+{
+	queue_push_tail(pac->bdb->broadcast_sources, pac);
+}
+
+static void bap_add_broadcast_sink(struct bt_bap_pac *pac)
+{
+	queue_push_tail(pac->bdb->broadcast_sinks, pac);
+}
+
 static void notify_pac_added(void *data, void *user_data)
 {
 	struct bt_bap_pac_changed *changed = data;
@@ -2400,10 +2482,12 @@  struct bt_bap_pac *bt_bap_add_vendor_pac(struct gatt_db *db,
 					uint8_t id, uint16_t cid, uint16_t vid,
 					struct bt_bap_pac_qos *qos,
 					struct iovec *data,
-					struct iovec *metadata)
+					struct iovec *metadata,
+					struct bt_bap_pac_ops *pac_ops,
+					void *user_data)
 {
 	struct bt_bap_db *bdb;
-	struct bt_bap_pac *pac;
+	struct bt_bap_pac *pac, *pac_brodcast_sink;
 	struct bt_bap_codec codec;
 
 	if (!db)
@@ -2429,11 +2513,17 @@  struct bt_bap_pac *bt_bap_add_vendor_pac(struct gatt_db *db,
 	case BT_BAP_SOURCE:
 		bap_add_source(pac);
 		break;
+	case BT_BAP_BROADCAST_SOURCE:
+		bap_add_broadcast_source(pac);
+		pac_brodcast_sink = bap_pac_new(bdb, name, type, &codec, qos, data, metadata);
+		bap_add_broadcast_sink(pac_brodcast_sink);
+		break;
 	default:
 		bap_pac_free(pac);
 		return NULL;
 	}
 
+	bt_bap_pac_set_ops(pac, pac_ops, user_data);
 	queue_foreach(sessions, notify_session_pac_added, pac);
 
 	return pac;
@@ -2443,10 +2533,12 @@  struct bt_bap_pac *bt_bap_add_pac(struct gatt_db *db, const char *name,
 					uint8_t type, uint8_t id,
 					struct bt_bap_pac_qos *qos,
 					struct iovec *data,
-					struct iovec *metadata)
+					struct iovec *metadata,
+					struct bt_bap_pac_ops *pac_ops,
+					void *user_data)
 {
 	return bt_bap_add_vendor_pac(db, name, type, id, 0x0000, 0x0000, qos,
-							data, metadata);
+							data, metadata, pac_ops, user_data);
 }
 
 uint8_t bt_bap_pac_get_type(struct bt_bap_pac *pac)
@@ -2471,6 +2563,21 @@  uint32_t bt_bap_pac_get_locations(struct bt_bap_pac *pac)
 	}
 }
 
+uint8_t bt_bap_stream_get_type(struct bt_bap_stream *stream)
+{
+	if (!stream)
+		return BT_BAP_STREAM_TYPE_UNKNOWN;
+
+	if ((bt_bap_pac_get_type(stream->lpac) == BT_BAP_SINK) ||
+		(bt_bap_pac_get_type(stream->lpac) == BT_BAP_SOURCE))
+		return BT_BAP_STREAM_TYPE_UNICAST;
+	else if ((bt_bap_pac_get_type(stream->lpac) == BT_BAP_BROADCAST_SOURCE) ||
+			(bt_bap_pac_get_type(stream->lpac) == BT_BAP_BROADCAST_SINK))
+		return BT_BAP_STREAM_TYPE_BROADCAST;
+	else
+		return BT_BAP_STREAM_TYPE_UNKNOWN;
+}
+
 static void notify_pac_removed(void *data, void *user_data)
 {
 	struct bt_bap_pac_changed *changed = data;
@@ -2529,6 +2636,9 @@  bool bt_bap_remove_pac(struct bt_bap_pac *pac)
 	if (queue_remove_if(pac->bdb->sources, NULL, pac))
 		goto found;
 
+	if (queue_remove_if(pac->bdb->broadcast_sources, NULL, pac))
+		goto found;
+
 	return false;
 
 found:
@@ -3280,13 +3390,13 @@  static void ep_status_qos(struct bt_bap *bap, struct bt_bap_endpoint *ep,
 	if (!ep->stream)
 		return;
 
-	ep->stream->qos.interval = interval;
-	ep->stream->qos.framing = qos->framing;
-	ep->stream->qos.phy = qos->phy;
-	ep->stream->qos.sdu = sdu;
-	ep->stream->qos.rtn = qos->rtn;
-	ep->stream->qos.latency = latency;
-	ep->stream->qos.delay = pd;
+	ep->stream->qos.ucast.io_qos.interval = interval;
+	ep->stream->qos.ucast.framing = qos->framing;
+	ep->stream->qos.ucast.io_qos.phy = qos->phy;
+	ep->stream->qos.ucast.io_qos.sdu = sdu;
+	ep->stream->qos.ucast.io_qos.rtn = qos->rtn;
+	ep->stream->qos.ucast.io_qos.latency = latency;
+	ep->stream->qos.ucast.delay = pd;
 
 	if (ep->old_state == BT_ASCS_ASE_STATE_CONFIG)
 		bap_stream_config_cfm(ep->stream);
@@ -3861,6 +3971,25 @@  clone:
 	return true;
 }
 
+bool bt_bap_attach_broadcast(struct bt_bap *bap)
+{
+	struct bt_bap_endpoint *ep;
+
+	if (queue_find(sessions, NULL, bap))
+		return true;
+
+	if (!sessions)
+		sessions = queue_new();
+
+	queue_push_tail(sessions, bap);
+
+	ep = bap_get_endpoint_broadcast(bap->remote_eps, bap->ldb);
+	if (ep)
+		ep->bap = bap;
+
+	return true;
+}
+
 static void stream_foreach_detach(void *data, void *user_data)
 {
 	struct bt_bap_stream *stream = data;
@@ -4065,7 +4194,10 @@  void bt_bap_foreach_pac(struct bt_bap *bap, uint8_t type,
 							func, user_data);
 	case BT_BAP_SOURCE:
 		return bap_foreach_pac(bap->ldb->sinks, bap->rdb->sources,
-							func, user_data);
+							   func, user_data);
+	case BT_BAP_BROADCAST_SOURCE:
+		return bap_foreach_pac(bap->ldb->broadcast_sources, bap->ldb->broadcast_sinks,
+								func, user_data);
 	}
 }
 
@@ -4178,42 +4310,49 @@  unsigned int bt_bap_stream_config(struct bt_bap_stream *stream,
 	if (!bap_stream_valid(stream))
 		return 0;
 
-	if (!stream->client) {
-		stream_config(stream, data, NULL);
-		return 0;
-	}
+	if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_UNICAST) {
+		if (!stream->client) {
+			stream_config(stream, data, NULL);
+			return 0;
+		}
 
-	memset(&config, 0, sizeof(config));
+		memset(&config, 0, sizeof(config));
 
-	config.ase = stream->ep->id;
-	config.latency = qos->target_latency;
-	config.phy = qos->phy;
-	config.codec = stream->rpac->codec;
+		config.ase = stream->ep->id;
+		config.latency = qos->ucast.target_latency;
+		config.phy = qos->ucast.io_qos.phy;
+		config.codec = stream->rpac->codec;
 
-	iov[0].iov_base = &config;
-	iov[0].iov_len = sizeof(config);
+		iov[0].iov_base = &config;
+		iov[0].iov_len = sizeof(config);
 
-	if (data) {
-		if (!bap_print_cc(data->iov_base, data->iov_len,
-					stream->bap->debug_func,
-					stream->bap->debug_data))
-			return 0;
+		if (data) {
+			if (!bap_print_cc(data->iov_base, data->iov_len,
+						stream->bap->debug_func,
+						stream->bap->debug_data))
+				return 0;
 
-		config.cc_len = data->iov_len;
-		iov[1] = *data;
-		iovlen++;
-	}
+			config.cc_len = data->iov_len;
+			iov[1] = *data;
+			iovlen++;
+		}
 
-	req = bap_req_new(stream, BT_ASCS_CONFIG, iov, iovlen, func, user_data);
+		req = bap_req_new(stream, BT_ASCS_CONFIG, iov, iovlen, func, user_data);
 
-	if (!bap_queue_req(stream->bap, req)) {
-		bap_req_free(req);
-		return 0;
-	}
+		if (!bap_queue_req(stream->bap, req)) {
+			bap_req_free(req);
+			return 0;
+		}
 
-	stream->qos = *qos;
+		stream->qos = *qos;
 
-	return req->id;
+		return req->id;
+	} else if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST) {
+		stream->qos = *qos;
+		return 0;
+	} else {
+		return 0;
+	}
 }
 
 static bool match_pac(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
@@ -4274,7 +4413,7 @@  struct bt_bap_stream *bt_bap_stream_new(struct bt_bap *bap,
 		if (rpac)
 			type = rpac->type;
 		else if (lpac) {
-			switch(lpac->type) {
+			switch (lpac->type) {
 			case BT_BAP_SINK:
 				type = BT_BAP_SOURCE;
 				break;
@@ -4339,6 +4478,10 @@  bool bt_bap_stream_set_user_data(struct bt_bap_stream *stream, void *user_data)
 
 	stream->user_data = user_data;
 
+	if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST)
+		stream->lpac->ops->config(stream, stream->cc, &stream->qos,
+								ep_config_cb, stream->lpac->user_data);
+
 	return true;
 }
 
@@ -4369,15 +4512,15 @@  unsigned int bt_bap_stream_qos(struct bt_bap_stream *stream,
 
 	/* TODO: Figure out how to pass these values around */
 	qos.ase = stream->ep->id;
-	qos.cig = data->cig_id;
-	qos.cis = data->cis_id;
-	put_le24(data->interval, qos.interval);
-	qos.framing = data->framing;
-	qos.phy = data->phy;
-	qos.sdu = cpu_to_le16(data->sdu);
-	qos.rtn = data->rtn;
-	qos.latency = cpu_to_le16(data->latency);
-	put_le24(data->delay, qos.pd);
+	qos.cig = data->ucast.cig_id;
+	qos.cis = data->ucast.cis_id;
+	put_le24(data->ucast.io_qos.interval, qos.interval);
+	qos.framing = data->ucast.framing;
+	qos.phy = data->ucast.io_qos.phy;
+	qos.sdu = cpu_to_le16(data->ucast.io_qos.sdu);
+	qos.rtn = data->ucast.io_qos.rtn;
+	qos.latency = cpu_to_le16(data->ucast.io_qos.latency);
+	put_le24(data->ucast.delay, qos.pd);
 
 	iov.iov_base = &qos;
 	iov.iov_len = sizeof(qos);
@@ -4448,7 +4591,7 @@  unsigned int bt_bap_stream_enable(struct bt_bap_stream *stream,
 					bt_bap_stream_func_t func,
 					void *user_data)
 {
-	int ret;
+	int ret = 0;
 
 	/* Table 3.2: ASE state machine transition
 	 * Initiating device - client Only
@@ -4456,12 +4599,17 @@  unsigned int bt_bap_stream_enable(struct bt_bap_stream *stream,
 	if (!bap_stream_valid(stream) || !stream->client)
 		return 0;
 
-	ret = bap_stream_metadata(stream, BT_ASCS_ENABLE, metadata, func,
-								user_data);
-	if (!ret || !enable_links)
-		return ret;
+	if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_UNICAST) {
+		ret = bap_stream_metadata(stream, BT_ASCS_ENABLE, metadata, func,
+							  user_data);
+		if (!ret || !enable_links)
+			return ret;
 
-	queue_foreach(stream->links, bap_stream_enable_link, metadata);
+		queue_foreach(stream->links, bap_stream_enable_link, metadata);
+	} else if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST) {
+		stream_set_state_broadcast(stream, BT_BAP_STREAM_STATE_STREAMING);
+		return ret = 1;
+	}
 
 	return ret;
 }
@@ -4640,6 +4788,15 @@  unsigned int bt_bap_stream_release(struct bt_bap_stream *stream,
 
 	bap = stream->bap;
 
+	/* If stream is broadcast, no BT_ASCS_RELEASE is required */
+	if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST) {
+		if (!bap_stream_valid(stream)) {
+			stream_set_state_broadcast(stream, BT_BAP_STREAM_STATE_IDLE);
+			stream = NULL;
+		}
+		return 0;
+	}
+
 	/* If stream does not belong to a client session, clean it up now */
 	if (!bap_stream_valid(stream)) {
 		stream_set_state(stream, BT_BAP_STREAM_STATE_IDLE);
@@ -4675,8 +4832,11 @@  uint32_t bt_bap_stream_get_location(struct bt_bap_stream *stream)
 
 	if (stream->ep->dir == BT_BAP_SOURCE)
 		return pacs->source_loc_value;
-	else
+	else if (stream->ep->dir == BT_BAP_SINK)
 		return pacs->sink_loc_value;
+	else
+		// TO DO get the location values from metadata for brodcast source and sink
+		return stream->bap->ldb->pacs->source_loc_value;
 }
 
 struct iovec *bt_bap_stream_get_config(struct bt_bap_stream *stream)
@@ -4781,8 +4941,8 @@  int bt_bap_stream_io_link(struct bt_bap_stream *stream,
 		return -EALREADY;
 
 	if (stream->client != link->client ||
-			stream->qos.cig_id != link->qos.cig_id ||
-			stream->qos.cis_id != link->qos.cis_id)
+			stream->qos.ucast.cig_id != link->qos.ucast.cig_id ||
+			stream->qos.ucast.cis_id != link->qos.ucast.cis_id)
 		return -EINVAL;
 
 	if (!stream->links)
@@ -4819,7 +4979,7 @@  static void bap_stream_get_in_qos(void *data, void *user_data)
 	struct bt_bap_qos **qos = user_data;
 
 	if (!qos || *qos || stream->ep->dir != BT_BAP_SOURCE ||
-						!stream->qos.sdu)
+						!stream->qos.ucast.io_qos.sdu)
 		return;
 
 	*qos = &stream->qos;
@@ -4830,7 +4990,7 @@  static void bap_stream_get_out_qos(void *data, void *user_data)
 	struct bt_bap_stream *stream = data;
 	struct bt_bap_qos **qos = user_data;
 
-	if (!qos || *qos || stream->ep->dir != BT_BAP_SINK || !stream->qos.sdu)
+	if (!qos || *qos || stream->ep->dir != BT_BAP_SINK || !stream->qos.ucast.io_qos.sdu)
 		return;
 
 	*qos = &stream->qos;
diff --git a/src/shared/bap.h b/src/shared/bap.h
index e9f769d0e..3b07df158 100644
--- a/src/shared/bap.h
+++ b/src/shared/bap.h
@@ -4,6 +4,7 @@ 
  *  BlueZ - Bluetooth protocol stack for Linux
  *
  *  Copyright (C) 2022  Intel Corporation. All rights reserved.
+ *  Copyright 2023 NXP
  *
  */
 
@@ -14,8 +15,14 @@ 
 #define __packed __attribute__((packed))
 #endif
 
-#define BT_BAP_SINK			0x01
+#define BT_BAP_SINK				0x01
 #define	BT_BAP_SOURCE			0x02
+#define	BT_BAP_BROADCAST_SOURCE	0x03
+#define	BT_BAP_BROADCAST_SINK	0x04
+
+#define BT_BAP_STREAM_TYPE_UNICAST		0x01
+#define	BT_BAP_STREAM_TYPE_BROADCAST	0x02
+#define	BT_BAP_STREAM_TYPE_UNKNOWN		0x03
 
 #define BT_BAP_STREAM_STATE_IDLE	0x00
 #define BT_BAP_STREAM_STATE_CONFIG	0x01
@@ -49,17 +56,46 @@  struct bt_ltv {
 	uint8_t  value[0];
 } __packed;
 
-struct bt_bap_qos {
+struct bt_bap_io_qos {
+	uint32_t interval;	/* Frame interval */
+	uint16_t latency;	/* Transport Latency */
+	uint16_t sdu;		/* Maximum SDU Size */
+	uint8_t  phy;		/* PHY */
+	uint8_t  rtn;		/* Retransmission Effort */
+};
+
+struct bt_bap_ucast_qos {
 	uint8_t  cig_id;
 	uint8_t  cis_id;
-	uint32_t interval;		/* Frame interval */
 	uint8_t  framing;		/* Frame framing */
-	uint8_t  phy;			/* PHY */
-	uint16_t sdu;			/* Maximum SDU Size */
-	uint8_t  rtn;			/* Retransmission Effort */
-	uint16_t latency;		/* Transport Latency */
 	uint32_t delay;			/* Presentation Delay */
 	uint8_t  target_latency;	/* Target Latency */
+	struct bt_bap_io_qos io_qos;
+};
+
+struct bt_bap_bcast_qos {
+	uint8_t  big;
+	uint8_t  bis;
+	uint8_t  sync_interval;
+	uint8_t  packing;
+	uint8_t  framing;
+	uint8_t  encryption;
+	struct iovec bcode;
+	uint8_t  options;
+	uint16_t skip;
+	uint16_t sync_timeout;
+	uint8_t  sync_cte_type;
+	uint8_t  mse;
+	uint16_t timeout;
+	uint8_t  pa_sync;
+	struct bt_bap_io_qos io_qos;
+};
+
+struct bt_bap_qos {
+	union {
+			struct bt_bap_ucast_qos ucast;
+			struct bt_bap_bcast_qos bcast;
+		};
 };
 
 typedef void (*bt_bap_ready_func_t)(struct bt_bap *bap, void *user_data);
@@ -98,28 +134,32 @@  struct bt_bap_pac_qos {
 	uint32_t ppd_max;
 };
 
+struct bt_bap_pac_ops {
+	int (*select)(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
+			struct bt_bap_pac_qos *qos,
+			bt_bap_pac_select_t cb, void *cb_data, void *user_data);
+	int (*config)(struct bt_bap_stream *stream, struct iovec *cfg,
+			struct bt_bap_qos *qos, bt_bap_pac_config_t cb,
+			void *user_data);
+	void (*clear)(struct bt_bap_stream *stream, void *user_data);
+};
+
 struct bt_bap_pac *bt_bap_add_vendor_pac(struct gatt_db *db,
 					const char *name, uint8_t type,
 					uint8_t id, uint16_t cid, uint16_t vid,
 					struct bt_bap_pac_qos *qos,
 					struct iovec *data,
-					struct iovec *metadata);
+					struct iovec *metadata,
+					struct bt_bap_pac_ops *pac_ops,
+					void *user_data);
 
 struct bt_bap_pac *bt_bap_add_pac(struct gatt_db *db, const char *name,
 					uint8_t type, uint8_t id,
 					struct bt_bap_pac_qos *qos,
 					struct iovec *data,
-					struct iovec *metadata);
-
-struct bt_bap_pac_ops {
-	int (*select)(struct bt_bap_pac *lpac, struct bt_bap_pac *rpac,
-			struct bt_bap_pac_qos *qos,
-			bt_bap_pac_select_t cb, void *cb_data, void *user_data);
-	int (*config)(struct bt_bap_stream *stream, struct iovec *cfg,
-			struct bt_bap_qos *qos, bt_bap_pac_config_t cb,
-			void *user_data);
-	void (*clear)(struct bt_bap_stream *stream, void *user_data);
-};
+					struct iovec *metadata,
+					struct bt_bap_pac_ops *pac_ops,
+					void *user_data);
 
 bool bt_bap_pac_set_ops(struct bt_bap_pac *pac, struct bt_bap_pac_ops *ops,
 					void *user_data);
@@ -130,6 +170,8 @@  uint8_t bt_bap_pac_get_type(struct bt_bap_pac *pac);
 
 uint32_t bt_bap_pac_get_locations(struct bt_bap_pac *pac);
 
+uint8_t bt_bap_stream_get_type(struct bt_bap_stream *stream);
+
 struct bt_bap_stream *bt_bap_pac_get_stream(struct bt_bap_pac *pac);
 
 /* Session related function */
@@ -149,6 +191,7 @@  struct bt_bap *bt_bap_ref(struct bt_bap *bap);
 void bt_bap_unref(struct bt_bap *bap);
 
 bool bt_bap_attach(struct bt_bap *bap, struct bt_gatt_client *client);
+bool bt_bap_attach_broadcast(struct bt_bap *bap);
 void bt_bap_detach(struct bt_bap *bap);
 
 bool bt_bap_set_debug(struct bt_bap *bap, bt_bap_debug_func_t cb,
diff --git a/unit/test-bap.c b/unit/test-bap.c
index bf525742d..8d1b3fd52 100644
--- a/unit/test-bap.c
+++ b/unit/test-bap.c
@@ -377,11 +377,11 @@  static void test_client_config(struct test_data *data)
 							"test-bap-snk",
 							BT_BAP_SINK, 0x0ff,
 							0x0001, 0x0001,
-							NULL, data->caps, NULL);
+							NULL, data->caps, NULL, NULL, NULL);
 		else
 			data->snk = bt_bap_add_pac(data->db, "test-bap-snk",
 							BT_BAP_SINK, LC3_ID,
-							NULL, data->caps, NULL);
+							NULL, data->caps, NULL, NULL, NULL);
 		g_assert(data->snk);
 	}
 
@@ -391,11 +391,11 @@  static void test_client_config(struct test_data *data)
 							"test-bap-src",
 							BT_BAP_SOURCE, 0x0ff,
 							0x0001, 0x0001,
-							NULL, data->caps, NULL);
+							NULL, data->caps, NULL, NULL, NULL);
 		else
 			data->src = bt_bap_add_pac(data->db, "test-bap-src",
 							BT_BAP_SOURCE, LC3_ID,
-							NULL, data->caps, NULL);
+							NULL, data->caps, NULL, NULL, NULL);
 		g_assert(data->src);
 	}
 }
@@ -712,12 +712,15 @@  static void test_disc(void)
 #define QOS_BALANCED_2M \
 	{ \
 		.target_latency = BT_BAP_CONFIG_LATENCY_BALANCED, \
-		.phy = BT_BAP_CONFIG_PHY_2M, \
+		.io_qos.phy = BT_BAP_CONFIG_PHY_2M, \
 	}
-
+#define QOS_UCAST \
+{\
+	.ucast = QOS_BALANCED_2M, \
+}
 static struct test_config cfg_snk_8_1 = {
 	.cc = LC3_CONFIG_8_1,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.snk = true,
 };
 
@@ -727,7 +730,7 @@  static struct test_config cfg_snk_8_1 = {
 
 static struct test_config cfg_snk_8_2 = {
 	.cc = LC3_CONFIG_8_2,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.snk = true,
 };
 
@@ -737,7 +740,7 @@  static struct test_config cfg_snk_8_2 = {
 
 static struct test_config cfg_snk_16_1 = {
 	.cc = LC3_CONFIG_16_1,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.snk = true,
 };
 
@@ -747,7 +750,7 @@  static struct test_config cfg_snk_16_1 = {
 
 static struct test_config cfg_snk_16_2 = {
 	.cc = LC3_CONFIG_16_2,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.snk = true,
 };
 
@@ -757,7 +760,7 @@  static struct test_config cfg_snk_16_2 = {
 
 static struct test_config cfg_snk_24_1 = {
 	.cc = LC3_CONFIG_24_1,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.snk = true,
 };
 
@@ -767,7 +770,7 @@  static struct test_config cfg_snk_24_1 = {
 
 static struct test_config cfg_snk_24_2 = {
 	.cc = LC3_CONFIG_24_2,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.snk = true,
 };
 
@@ -777,7 +780,7 @@  static struct test_config cfg_snk_24_2 = {
 
 static struct test_config cfg_snk_32_1 = {
 	.cc = LC3_CONFIG_32_1,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.snk = true,
 };
 
@@ -787,7 +790,7 @@  static struct test_config cfg_snk_32_1 = {
 
 static struct test_config cfg_snk_32_2 = {
 	.cc = LC3_CONFIG_32_2,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.snk = true,
 };
 
@@ -797,7 +800,7 @@  static struct test_config cfg_snk_32_2 = {
 
 static struct test_config cfg_snk_44_1 = {
 	.cc = LC3_CONFIG_44_1,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.snk = true,
 };
 
@@ -807,7 +810,7 @@  static struct test_config cfg_snk_44_1 = {
 
 static struct test_config cfg_snk_44_2 = {
 	.cc = LC3_CONFIG_44_2,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.snk = true,
 };
 
@@ -817,7 +820,7 @@  static struct test_config cfg_snk_44_2 = {
 
 static struct test_config cfg_snk_48_1 = {
 	.cc = LC3_CONFIG_48_1,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.snk = true,
 };
 
@@ -827,7 +830,7 @@  static struct test_config cfg_snk_48_1 = {
 
 static struct test_config cfg_snk_48_2 = {
 	.cc = LC3_CONFIG_48_2,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.snk = true,
 };
 
@@ -837,7 +840,7 @@  static struct test_config cfg_snk_48_2 = {
 
 static struct test_config cfg_snk_48_3 = {
 	.cc = LC3_CONFIG_48_3,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.snk = true,
 };
 
@@ -847,7 +850,7 @@  static struct test_config cfg_snk_48_3 = {
 
 static struct test_config cfg_snk_48_4 = {
 	.cc = LC3_CONFIG_48_4,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.snk = true,
 };
 
@@ -857,7 +860,7 @@  static struct test_config cfg_snk_48_4 = {
 
 static struct test_config cfg_snk_48_5 = {
 	.cc = LC3_CONFIG_48_5,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.snk = true,
 };
 
@@ -867,7 +870,7 @@  static struct test_config cfg_snk_48_5 = {
 
 static struct test_config cfg_snk_48_6 = {
 	.cc = LC3_CONFIG_48_6,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.snk = true,
 };
 
@@ -899,7 +902,7 @@  static struct test_config cfg_snk_48_6 = {
 
 static struct test_config cfg_src_8_1 = {
 	.cc = LC3_CONFIG_8_1,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.src = true,
 };
 
@@ -909,7 +912,7 @@  static struct test_config cfg_src_8_1 = {
 
 static struct test_config cfg_src_8_2 = {
 	.cc = LC3_CONFIG_8_2,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.src = true,
 };
 
@@ -919,7 +922,7 @@  static struct test_config cfg_src_8_2 = {
 
 static struct test_config cfg_src_16_1 = {
 	.cc = LC3_CONFIG_16_1,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.src = true,
 };
 
@@ -929,7 +932,7 @@  static struct test_config cfg_src_16_1 = {
 
 static struct test_config cfg_src_16_2 = {
 	.cc = LC3_CONFIG_16_2,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.src = true,
 };
 
@@ -939,7 +942,7 @@  static struct test_config cfg_src_16_2 = {
 
 static struct test_config cfg_src_24_1 = {
 	.cc = LC3_CONFIG_24_1,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.src = true,
 };
 
@@ -949,7 +952,7 @@  static struct test_config cfg_src_24_1 = {
 
 static struct test_config cfg_src_24_2 = {
 	.cc = LC3_CONFIG_24_2,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.src = true,
 };
 
@@ -959,7 +962,7 @@  static struct test_config cfg_src_24_2 = {
 
 static struct test_config cfg_src_32_1 = {
 	.cc = LC3_CONFIG_32_1,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.src = true,
 };
 
@@ -969,7 +972,7 @@  static struct test_config cfg_src_32_1 = {
 
 static struct test_config cfg_src_32_2 = {
 	.cc = LC3_CONFIG_32_2,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.src = true,
 };
 
@@ -979,7 +982,7 @@  static struct test_config cfg_src_32_2 = {
 
 static struct test_config cfg_src_44_1 = {
 	.cc = LC3_CONFIG_44_1,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.src = true,
 };
 
@@ -989,7 +992,7 @@  static struct test_config cfg_src_44_1 = {
 
 static struct test_config cfg_src_44_2 = {
 	.cc = LC3_CONFIG_44_2,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.src = true,
 };
 
@@ -999,7 +1002,7 @@  static struct test_config cfg_src_44_2 = {
 
 static struct test_config cfg_src_48_1 = {
 	.cc = LC3_CONFIG_48_1,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.src = true,
 };
 
@@ -1009,7 +1012,7 @@  static struct test_config cfg_src_48_1 = {
 
 static struct test_config cfg_src_48_2 = {
 	.cc = LC3_CONFIG_48_2,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.src = true,
 };
 
@@ -1019,7 +1022,7 @@  static struct test_config cfg_src_48_2 = {
 
 static struct test_config cfg_src_48_3 = {
 	.cc = LC3_CONFIG_48_3,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.src = true,
 };
 
@@ -1029,7 +1032,7 @@  static struct test_config cfg_src_48_3 = {
 
 static struct test_config cfg_src_48_4 = {
 	.cc = LC3_CONFIG_48_4,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.src = true,
 };
 
@@ -1039,7 +1042,7 @@  static struct test_config cfg_src_48_4 = {
 
 static struct test_config cfg_src_48_5 = {
 	.cc = LC3_CONFIG_48_5,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.src = true,
 };
 
@@ -1049,7 +1052,7 @@  static struct test_config cfg_src_48_5 = {
 
 static struct test_config cfg_src_48_6 = {
 	.cc = LC3_CONFIG_48_6,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.src = true,
 };
 
@@ -1141,7 +1144,7 @@  static void test_scc_cc_lc3(void)
 
 static struct test_config cfg_snk_vs = {
 	.cc = IOV_NULL,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.snk = true,
 	.vs = true,
 };
@@ -1155,7 +1158,7 @@  static struct test_config cfg_snk_vs = {
 
 static struct test_config cfg_src_vs = {
 	.cc = IOV_NULL,
-	.qos = QOS_BALANCED_2M,
+	.qos = QOS_UCAST,
 	.src = true,
 	.vs = true,
 };