linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH BlueZ 0/6] Add initial support for BAP broadcast source
@ 2023-05-23 14:34 Iulia Tanasescu
  2023-05-23 14:34 ` [PATCH BlueZ 1/6] doc: Update Docs " Iulia Tanasescu
                   ` (7 more replies)
  0 siblings, 8 replies; 17+ messages in thread
From: Iulia Tanasescu @ 2023-05-23 14:34 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Iulia Tanasescu

This patch adds initial support for BAP broadcast source.

The current implementation allows BAP source endpoint registration,
media transport creation, transport acquiring and sending broadcast ISO data.

Currently, one BIG containing one BIS is supported.

To test the current implementation use bluetoothctl with the following commands:
# endpoint.register 00001852-0000-1000-8000-00805f9b34fb 0x06
# transport.acquire /org/bluez/hci0/dev_00_00_00_00_00_00/pac_broadcast0/fd0
# transport.send /org/bluez/hci0/dev_00_00_00_00_00_00/pac_broadcast0/fd0 <file.wav>

The curent implementation checks that ISO_BROADCASTER is suported on the board so
"Check for ISO support in controller" patch is required
(https://patchwork.kernel.org/project/bluetooth/patch/20230510134557.11486-2-claudia.rosu@nxp.com/)

Silviu Florian Barbulescu (6):
  doc: Update Docs for BAP broadcast source
  lib: Add macro definitions for BAP broadcast source support
  monitor: Check for ISO broadcast support in controller
  btio: Add support for setsockopt (BT_IO_OPT_BASE)
  client/player: Update bluetoothctl with support for broadcast source
  bap: Add initial support for BAP broadcast source

 btio/btio.c                |  26 ++-
 btio/btio.h                |   2 +
 client/player.c            | 207 +++++++++++++++--
 doc/media-api.txt          |  11 +
 doc/mgmt-api.txt           |   2 +
 lib/bluetooth.h            |   9 +
 lib/mgmt.h                 |   2 +
 lib/uuid.h                 |   3 +
 monitor/packet.c           |   4 +-
 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 +++----
 15 files changed, 1123 insertions(+), 271 deletions(-)


base-commit: 8c452c2ec1739efe581273bacd738e5294d0ca0f
-- 
2.34.1


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH BlueZ 1/6] doc: Update Docs for BAP broadcast source
  2023-05-23 14:34 [PATCH BlueZ 0/6] Add initial support for BAP broadcast source Iulia Tanasescu
@ 2023-05-23 14:34 ` Iulia Tanasescu
  2023-05-23 15:14   ` Add initial support " bluez.test.bot
  2023-05-23 14:35 ` [PATCH BlueZ 2/6] lib: Add macro definitions for BAP broadcast source support Iulia Tanasescu
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 17+ messages in thread
From: Iulia Tanasescu @ 2023-05-23 14:34 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Silviu Florian Barbulescu

From: Silviu Florian Barbulescu <silviu.barbulescu@nxp.com>

This adds broadcast properties to the SetConfiguration method and
bits for Broadcast support to the Supported_Settings bitmask.

---
 doc/media-api.txt | 11 +++++++++++
 doc/mgmt-api.txt  |  2 ++
 2 files changed, 13 insertions(+)

diff --git a/doc/media-api.txt b/doc/media-api.txt
index 3746ccd55..3a0ec38e2 100644
--- a/doc/media-api.txt
+++ b/doc/media-api.txt
@@ -599,6 +599,17 @@ Methods		void SetConfiguration(object transport, dict properties)
 				uint16 Latency [ISO only]
 				uint32 Delay [ISO only]
 				uint8 TargetLatency [ISO Latency]
+				byte BIG [ISO broadcast only]
+				byte BIS [ISO broadcast only]
+				byte SyncInterval [ISO broadcast only]
+				byte Encryption [ISO broadcast only]
+				byte Options [ISO broadcast only]
+				uint16 Skip [ISO broadcast only]
+				uint16 SyncTimeout [ISO broadcast only]
+				byte SyncCteType [ISO broadcast only]
+				byte MSE [ISO broadcast only]
+				uint16 Timeout [ISO broadcast only]
+				array{byte} BroadcastCode [ISO broadcast only]
 
 		array{byte} SelectConfiguration(array{byte} capabilities)
 
diff --git a/doc/mgmt-api.txt b/doc/mgmt-api.txt
index 58395dc90..c7191a028 100644
--- a/doc/mgmt-api.txt
+++ b/doc/mgmt-api.txt
@@ -334,6 +334,8 @@ Read Controller Information Command
 		17	Wideband Speech
 		18	Connected Isochronous Stream - Central
 		19	Connected Isochronous Stream - Peripheral
+		20	Isochronous Broadcaster
+		21	Synchronized Receiver
 
 	This command generates a Command Complete event on success or
 	a Command Status event on failure.
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH BlueZ 2/6] lib: Add macro definitions for BAP broadcast source support
  2023-05-23 14:34 [PATCH BlueZ 0/6] Add initial support for BAP broadcast source Iulia Tanasescu
  2023-05-23 14:34 ` [PATCH BlueZ 1/6] doc: Update Docs " Iulia Tanasescu
@ 2023-05-23 14:35 ` Iulia Tanasescu
  2023-05-23 14:35 ` [PATCH BlueZ 3/6] monitor: Check for ISO broadcast support in controller Iulia Tanasescu
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 17+ messages in thread
From: Iulia Tanasescu @ 2023-05-23 14:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Silviu Florian Barbulescu

From: Silviu Florian Barbulescu <silviu.barbulescu@nxp.com>

This adds macro definitions for BAP broadcast source support.

---
 lib/bluetooth.h | 9 +++++++++
 lib/mgmt.h      | 2 ++
 lib/uuid.h      | 3 +++
 3 files changed, 14 insertions(+)

diff --git a/lib/bluetooth.h b/lib/bluetooth.h
index b4bb6748f..ca4b0115b 100644
--- a/lib/bluetooth.h
+++ b/lib/bluetooth.h
@@ -150,6 +150,9 @@ struct bt_voice {
 #define BT_ISO_QOS_BIG_UNSET	0xff
 #define BT_ISO_QOS_BIS_UNSET	0xff
 
+#define BT_ISO_QOS_GROUP_UNSET	0xff
+#define BT_ISO_QOS_STREAM_UNSET	0xff
+
 struct bt_iso_io_qos {
 	uint32_t interval;
 	uint16_t latency;
@@ -186,6 +189,12 @@ struct bt_iso_bcast_qos {
 	uint16_t timeout;
 };
 
+#define BASE_MAX_LENGTH 248 /* (HCI_MAX_PER_AD_LENGTH - EIR_SERVICE_DATA_LENGTH) */
+struct bt_iso_base {
+	uint8_t base_len;
+	uint8_t base[BASE_MAX_LENGTH];
+};
+
 struct bt_iso_qos {
 	union {
 		struct bt_iso_ucast_qos ucast;
diff --git a/lib/mgmt.h b/lib/mgmt.h
index 59273c85a..c3c905232 100644
--- a/lib/mgmt.h
+++ b/lib/mgmt.h
@@ -102,6 +102,8 @@ struct mgmt_rp_read_index_list {
 #define MGMT_SETTING_WIDEBAND_SPEECH	BIT(17)
 #define MGMT_SETTING_CIS_CENTRAL	BIT(18)
 #define MGMT_SETTING_CIS_PERIPHERAL	BIT(19)
+#define MGMT_SETTING_ISO_BROADCASTER	BIT(20)
+#define MGMT_SETTING_ISO_SYNC_RECEIVER	BIT(21)
 
 #define MGMT_OP_READ_INFO		0x0004
 struct mgmt_rp_read_info {
diff --git a/lib/uuid.h b/lib/uuid.h
index ddde4bfa3..8f2e23681 100644
--- a/lib/uuid.h
+++ b/lib/uuid.h
@@ -157,6 +157,9 @@ extern "C" {
 #define PAC_SOURCE_UUID		"00002bcb-0000-1000-8000-00805f9b34fb"
 #define PAC_SOURCE_LOC_CHRC_UUID			0x2bcc
 
+#define BROADCAST_AUDIO_ANNOUNCEMENT_SERVICE		0x1852
+#define BROADCAST_AUDIO_ANNOUNCEMENT_SERVICE_UUID	"00001852-0000-1000-8000-00805f9b34fb"
+
 #define PAC_CONTEXT					0x2bcd
 #define PAC_SUPPORTED_CONTEXT				0x2bce
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH BlueZ 3/6] monitor: Check for ISO broadcast support in controller
  2023-05-23 14:34 [PATCH BlueZ 0/6] Add initial support for BAP broadcast source Iulia Tanasescu
  2023-05-23 14:34 ` [PATCH BlueZ 1/6] doc: Update Docs " Iulia Tanasescu
  2023-05-23 14:35 ` [PATCH BlueZ 2/6] lib: Add macro definitions for BAP broadcast source support Iulia Tanasescu
@ 2023-05-23 14:35 ` Iulia Tanasescu
  2023-05-23 14:35 ` [PATCH BlueZ 4/6] btio: Add support for setsockopt (BT_IO_OPT_BASE) Iulia Tanasescu
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 17+ messages in thread
From: Iulia Tanasescu @ 2023-05-23 14:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Silviu Florian Barbulescu

From: Silviu Florian Barbulescu <silviu.barbulescu@nxp.com>

This adds bits for broadcast support to mgmt_settings_table.

---
 monitor/packet.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/monitor/packet.c b/monitor/packet.c
index 94561b65e..30bdcef4c 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -12653,7 +12653,9 @@ static const struct bitfield_data mgmt_settings_table[] = {
 	{ 17, "Wideband Speech"		},
 	{ 18, "CIS Central"		},
 	{ 19, "CIS Peripheral"		},
-	{ }
+	{ 20, "ISO Broadcaster"		},
+	{ 21, "Sync Receiver"		},
+	{}
 };
 
 static void mgmt_print_settings(const char *label, uint32_t settings)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH BlueZ 4/6] btio: Add support for setsockopt (BT_IO_OPT_BASE)
  2023-05-23 14:34 [PATCH BlueZ 0/6] Add initial support for BAP broadcast source Iulia Tanasescu
                   ` (2 preceding siblings ...)
  2023-05-23 14:35 ` [PATCH BlueZ 3/6] monitor: Check for ISO broadcast support in controller Iulia Tanasescu
@ 2023-05-23 14:35 ` Iulia Tanasescu
  2023-05-23 14:35 ` [PATCH BlueZ 5/6] client/player: Update bluetoothctl with support for broadcast source Iulia Tanasescu
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 17+ messages in thread
From: Iulia Tanasescu @ 2023-05-23 14:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Silviu Florian Barbulescu

From: Silviu Florian Barbulescu <silviu.barbulescu@nxp.com>

This adds btio support for setting the BT_IO_OPT_BASE socket option.

---
 btio/btio.c | 26 +++++++++++++++++++++++---
 btio/btio.h |  2 ++
 2 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/btio/btio.c b/btio/btio.c
index 6f6d76dc8..b68bfb14c 100644
--- a/btio/btio.c
+++ b/btio/btio.c
@@ -70,6 +70,7 @@ struct set_opts {
 	uint32_t priority;
 	uint16_t voice;
 	struct bt_iso_qos qos;
+	struct bt_iso_base base;
 };
 
 struct connect {
@@ -858,7 +859,7 @@ voice:
 	return TRUE;
 }
 
-static gboolean iso_set(int sock, struct bt_iso_qos *qos, GError **err)
+static gboolean iso_set_qos(int sock, struct bt_iso_qos *qos, GError **err)
 {
 	if (setsockopt(sock, SOL_BLUETOOTH, BT_ISO_QOS, qos,
 				sizeof(*qos)) < 0) {
@@ -869,6 +870,16 @@ static gboolean iso_set(int sock, struct bt_iso_qos *qos, GError **err)
 	return TRUE;
 }
 
+static gboolean iso_set_base(int sock, struct bt_iso_base *base, GError **err)
+{
+	if (setsockopt(sock, SOL_BLUETOOTH, BT_ISO_BASE, base->base,
+			base->base_len) < 0) {
+		ERROR_FAILED(err, "setsockopt(BT_ISO_BASE)", errno);
+		return FALSE;
+	}
+
+	return TRUE;
+}
 static gboolean parse_set_opts(struct set_opts *opts, GError **err,
 						BtIOOption opt1, va_list args)
 {
@@ -966,6 +977,9 @@ static gboolean parse_set_opts(struct set_opts *opts, GError **err,
 		case BT_IO_OPT_QOS:
 			opts->qos = *va_arg(args, struct bt_iso_qos *);
 			break;
+		case BT_IO_OPT_BASE:
+			opts->base = *va_arg(args, struct bt_iso_base *);
+			break;
 		case BT_IO_OPT_INVALID:
 		case BT_IO_OPT_KEY_SIZE:
 		case BT_IO_OPT_SOURCE_CHANNEL:
@@ -1290,6 +1304,7 @@ parse_opts:
 		case BT_IO_OPT_MTU:
 		case BT_IO_OPT_VOICE:
 		case BT_IO_OPT_QOS:
+		case BT_IO_OPT_BASE:
 		default:
 			g_set_error(err, BT_IO_ERROR, EINVAL,
 					"Unknown option %d", opt);
@@ -1444,6 +1459,7 @@ static gboolean rfcomm_get(int sock, GError **err, BtIOOption opt1,
 		case BT_IO_OPT_PRIORITY:
 		case BT_IO_OPT_VOICE:
 		case BT_IO_OPT_QOS:
+		case BT_IO_OPT_BASE:
 		case BT_IO_OPT_INVALID:
 		default:
 			g_set_error(err, BT_IO_ERROR, EINVAL,
@@ -1554,6 +1570,7 @@ static gboolean sco_get(int sock, GError **err, BtIOOption opt1, va_list args)
 		case BT_IO_OPT_PRIORITY:
 		case BT_IO_OPT_VOICE:
 		case BT_IO_OPT_QOS:
+		case BT_IO_OPT_BASE:
 		case BT_IO_OPT_INVALID:
 		default:
 			g_set_error(err, BT_IO_ERROR, EINVAL,
@@ -1627,6 +1644,7 @@ static gboolean iso_get(int sock, GError **err, BtIOOption opt1, va_list args)
 		case BT_IO_OPT_QOS:
 			*(va_arg(args, struct bt_iso_qos *)) = qos;
 			break;
+		case BT_IO_OPT_BASE:
 		case BT_IO_OPT_HANDLE:
 		case BT_IO_OPT_CLASS:
 		case BT_IO_OPT_DEFER_TIMEOUT:
@@ -1740,7 +1758,7 @@ gboolean bt_io_set(GIOChannel *io, GError **err, BtIOOption opt1, ...)
 	case BT_IO_SCO:
 		return sco_set(sock, opts.mtu, opts.voice, err);
 	case BT_IO_ISO:
-		return iso_set(sock, &opts.qos, err);
+		return iso_set_qos(sock, &opts.qos, err);
 	case BT_IO_INVALID:
 	default:
 		g_set_error(err, BT_IO_ERROR, EINVAL,
@@ -1820,7 +1838,9 @@ static GIOChannel *create_io(gboolean server, struct set_opts *opts,
 		}
 		if (iso_bind(sock, &opts->src, opts->src_type, err) < 0)
 			goto failed;
-		if (!iso_set(sock, &opts->qos, err))
+		if (!iso_set_qos(sock, &opts->qos, err))
+			goto failed;
+		if (!iso_set_base(sock, &opts->base, err))
 			goto failed;
 		break;
 	case BT_IO_INVALID:
diff --git a/btio/btio.h b/btio/btio.h
index 9636fd467..e9a8a01a3 100644
--- a/btio/btio.h
+++ b/btio/btio.h
@@ -5,6 +5,7 @@
  *
  *  Copyright (C) 2009-2010  Marcel Holtmann <marcel@holtmann.org>
  *  Copyright (C) 2009-2010  Nokia Corporation
+ *  Copyright 2023 NXP
  *
  *
  */
@@ -45,6 +46,7 @@ typedef enum {
 	BT_IO_OPT_VOICE,
 	BT_IO_OPT_PHY,
 	BT_IO_OPT_QOS,
+	BT_IO_OPT_BASE
 } BtIOOption;
 
 typedef enum {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH BlueZ 5/6] client/player: Update bluetoothctl with support for broadcast source
  2023-05-23 14:34 [PATCH BlueZ 0/6] Add initial support for BAP broadcast source Iulia Tanasescu
                   ` (3 preceding siblings ...)
  2023-05-23 14:35 ` [PATCH BlueZ 4/6] btio: Add support for setsockopt (BT_IO_OPT_BASE) Iulia Tanasescu
@ 2023-05-23 14:35 ` Iulia Tanasescu
  2023-05-23 16:31   ` Luiz Augusto von Dentz
  2023-05-23 14:35 ` [PATCH BlueZ 6/6] bap: Add initial support for BAP " Iulia Tanasescu
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 17+ messages in thread
From: Iulia Tanasescu @ 2023-05-23 14:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Silviu Florian Barbulescu

From: Silviu Florian Barbulescu <silviu.barbulescu@nxp.com>

This adds bluetoothctl support for broadcast source.

---
 client/player.c | 207 ++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 182 insertions(+), 25 deletions(-)

diff --git a/client/player.c b/client/player.c
index 7719076c8..1ba722150 100644
--- a/client/player.c
+++ b/client/player.c
@@ -73,10 +73,12 @@ struct endpoint {
 	struct iovec *meta;
 	bool auto_accept;
 	bool acquiring;
-	uint8_t cig;
-	uint8_t cis;
+	uint8_t iso_group;
+	uint8_t iso_stream;
 	char *transport;
 	DBusMessage *msg;
+	bool broadcast;
+	struct iovec *bcode;
 };
 
 static DBusConnection *dbus_conn;
@@ -102,6 +104,22 @@ struct transport {
 	struct io *timer_io;
 };
 
+static const uint8_t base_lc3_16_2_1[] = {
+	0x28, 0x00, 0x00, /* Presentation Delay */
+	0x01, /* Number of Subgroups */
+	0x01, /* Number of BIS */
+	0x06, 0x00, 0x00, 0x00, 0x00, /* Code ID = LC3 (0x06) */
+	0x11, /* Codec Specific Configuration */
+	0x02, 0x01, 0x03, /* 16 KHZ */
+	0x02, 0x02, 0x01, /* 10 ms */
+	0x05, 0x03, 0x01, 0x00, 0x00, 0x00,  /* Front Left */
+	0x03, 0x04, 0x28, 0x00, /* Frame Length 40 bytes */
+	0x04, /* Metadata */
+	0x03, 0x02, 0x02, 0x00, /* Audio Context: Convertional */
+	0x01, /* BIS */
+	0x00, /* Codec Specific Configuration */
+};
+
 static void endpoint_unregister(void *data)
 {
 	struct endpoint *ep = data;
@@ -1142,6 +1160,16 @@ static const struct capabilities {
 	CODEC_CAPABILITIES(PAC_SOURCE_UUID, LC3_ID,
 					LC3_DATA(LC3_FREQ_ANY, LC3_DURATION_ANY,
 						3u, 30, 240)),
+	/* Broadcast LC3 Source:
+	 *
+	 * Frequencies: 8Khz 11Khz 16Khz 22Khz 24Khz 32Khz 44.1Khz 48Khz
+	 * Duration: 7.5 ms 10 ms
+	 * Channel count: 3
+	 * Frame length: 30-240
+	 */
+	CODEC_CAPABILITIES(BROADCAST_AUDIO_ANNOUNCEMENT_SERVICE_UUID, LC3_ID,
+					LC3_DATA(LC3_FREQ_ANY, LC3_DURATION_ANY,
+						3u, 30, 240)),
 };
 
 struct codec_qos {
@@ -1419,6 +1447,7 @@ static struct preset {
 	PRESET(A2DP_SINK_UUID, sbc_presets, 6),
 	PRESET(PAC_SINK_UUID, lc3_presets, 3),
 	PRESET(PAC_SOURCE_UUID, lc3_presets, 3),
+	PRESET(BROADCAST_AUDIO_ANNOUNCEMENT_SERVICE_UUID, lc3_presets, 3),
 };
 
 static struct codec_preset *find_preset(const char *uuid, const char *name)
@@ -1588,6 +1617,27 @@ struct endpoint_config {
 	const struct codec_qos *qos;
 };
 
+#define BCODE {0x01, 0x02, 0x68, 0x05, 0x53, 0xf1, 0x41, 0x5a, \
+				0xa2, 0x65, 0xbb, 0xaf, 0xc6, 0xea, 0x03, 0xb8}
+
+static struct bt_iso_qos bcast_qos = {
+		.bcast = {
+			.big = BT_ISO_QOS_BIG_UNSET,
+			.bis = BT_ISO_QOS_BIS_UNSET,
+			.sync_interval = 0x07,
+			.packing = 0x00,
+			.framing = 0x00,
+			.encryption = 0x00,
+			.bcode = BCODE,
+			.options = 0x00,
+			.skip = 0x0000,
+			.sync_timeout = 0x4000,
+			.sync_cte_type = 0x00,
+			.mse = 0x00,
+			.timeout = 0x4000,
+		}
+	};
+
 static void append_properties(DBusMessageIter *iter,
 						struct endpoint_config *cfg)
 {
@@ -1595,6 +1645,7 @@ static void append_properties(DBusMessageIter *iter,
 	struct codec_qos *qos = (void *)cfg->qos;
 	const char *key = "Capabilities";
 	const char *meta = "Metadata";
+	const char *keyBCode = "BroadcastCode";
 
 	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{sv}", &dict);
 
@@ -1605,7 +1656,7 @@ static void append_properties(DBusMessageIter *iter,
 					DBUS_TYPE_BYTE, &cfg->caps->iov_base,
 					cfg->caps->iov_len);
 
-	if (cfg->meta->iov_len) {
+	if ((cfg->ep->meta) && (cfg->meta->iov_len)) {
 		g_dbus_dict_append_basic_array(&dict, DBUS_TYPE_STRING, &meta,
 				DBUS_TYPE_BYTE, &cfg->meta->iov_base,
 				cfg->meta->iov_len);
@@ -1623,16 +1674,25 @@ static void append_properties(DBusMessageIter *iter,
 					DBUS_TYPE_BYTE, &cfg->target_latency);
 	}
 
-	if (cfg->ep->cig != BT_ISO_QOS_CIG_UNSET) {
-		bt_shell_printf("CIG 0x%2.2x\n", cfg->ep->cig);
+	if ((!cfg->ep->broadcast) && (cfg->ep->iso_group != BT_ISO_QOS_GROUP_UNSET)) {
+		bt_shell_printf("CIG 0x%2.2x\n", cfg->ep->iso_group);
 		g_dbus_dict_append_entry(&dict, "CIG", DBUS_TYPE_BYTE,
-							&cfg->ep->cig);
+							&cfg->ep->iso_group);
+	} else {
+		bt_shell_printf("BIG 0x%2.2x\n", bcast_qos.bcast.big);
+		g_dbus_dict_append_entry(&dict, "BIG", DBUS_TYPE_BYTE,
+							&bcast_qos.bcast.big);
 	}
 
-	if (cfg->ep->cis != BT_ISO_QOS_CIS_UNSET) {
-		bt_shell_printf("CIS 0x%2.2x\n", cfg->ep->cis);
+	if ((!cfg->ep->broadcast) && (cfg->ep->iso_stream != BT_ISO_QOS_STREAM_UNSET)) {
+		bt_shell_printf("CIS 0x%2.2x\n", cfg->ep->iso_stream);
 		g_dbus_dict_append_entry(&dict, "CIS", DBUS_TYPE_BYTE,
-							&cfg->ep->cis);
+							&cfg->ep->iso_stream);
+
+	} else {
+		bt_shell_printf("BIS 0x%2.2x\n", bcast_qos.bcast.bis);
+		g_dbus_dict_append_entry(&dict, "BIS", DBUS_TYPE_BYTE,
+							&bcast_qos.bcast.bis);
 	}
 
 	bt_shell_printf("Interval %u\n", qos->interval);
@@ -1640,10 +1700,17 @@ static void append_properties(DBusMessageIter *iter,
 	g_dbus_dict_append_entry(&dict, "Interval", DBUS_TYPE_UINT32,
 						&qos->interval);
 
-	bt_shell_printf("Framing %s\n", qos->framing ? "true" : "false");
+	if (!cfg->ep->broadcast) {
+		bt_shell_printf("Framing %s\n", qos->framing ? "true" : "false");
 
-	g_dbus_dict_append_entry(&dict, "Framing", DBUS_TYPE_BOOLEAN,
-						&qos->framing);
+		g_dbus_dict_append_entry(&dict, "Framing", DBUS_TYPE_BOOLEAN,
+							&qos->framing);
+	} else {
+		bt_shell_printf("Framing %s\n", bcast_qos.bcast.framing ? "true" : "false");
+
+		g_dbus_dict_append_entry(&dict, "Framing", DBUS_TYPE_BOOLEAN,
+							&bcast_qos.bcast.framing);
+	}
 
 	bt_shell_printf("PHY %s\n", qos->phy);
 
@@ -1668,6 +1735,56 @@ static void append_properties(DBusMessageIter *iter,
 	g_dbus_dict_append_entry(&dict, "Delay", DBUS_TYPE_UINT32,
 						&qos->delay);
 
+	if (!cfg->ep->broadcast)
+		goto done;
+
+	bt_shell_printf("SyncInterval %u\n", bcast_qos.bcast.sync_interval);
+
+	g_dbus_dict_append_entry(&dict, "SyncInterval", DBUS_TYPE_BYTE,
+						&bcast_qos.bcast.sync_interval);
+
+	bt_shell_printf("Encryption %u\n", bcast_qos.bcast.encryption);
+
+	g_dbus_dict_append_entry(&dict, "Encryption", DBUS_TYPE_BYTE,
+						&bcast_qos.bcast.encryption);
+
+	bt_shell_printf("Options %u\n", bcast_qos.bcast.options);
+
+	g_dbus_dict_append_entry(&dict, "Options", DBUS_TYPE_BYTE,
+						&bcast_qos.bcast.options);
+
+	bt_shell_printf("Skip %u\n", bcast_qos.bcast.skip);
+
+	g_dbus_dict_append_entry(&dict, "Skip", DBUS_TYPE_UINT16,
+						&bcast_qos.bcast.skip);
+
+	bt_shell_printf("SyncTimeout %u\n", bcast_qos.bcast.sync_timeout);
+
+	g_dbus_dict_append_entry(&dict, "SyncTimeout", DBUS_TYPE_UINT16,
+						&bcast_qos.bcast.sync_timeout);
+
+	bt_shell_printf("SyncCteType %u\n", bcast_qos.bcast.sync_cte_type);
+
+	g_dbus_dict_append_entry(&dict, "SyncCteType", DBUS_TYPE_BYTE,
+						&bcast_qos.bcast.sync_cte_type);
+
+	bt_shell_printf("MSE %u\n", bcast_qos.bcast.mse);
+
+	g_dbus_dict_append_entry(&dict, "MSE", DBUS_TYPE_BYTE,
+						&bcast_qos.bcast.mse);
+
+	bt_shell_printf("Timeout %u\n", bcast_qos.bcast.timeout);
+
+	g_dbus_dict_append_entry(&dict, "Timeout", DBUS_TYPE_UINT16,
+						&bcast_qos.bcast.timeout);
+
+	bt_shell_printf("BroadcastCode:\n");
+	bt_shell_hexdump(cfg->ep->bcode->iov_base, cfg->ep->bcode->iov_len);
+
+	g_dbus_dict_append_basic_array(&dict, DBUS_TYPE_STRING, &keyBCode,
+								DBUS_TYPE_BYTE, &cfg->ep->bcode->iov_base,
+								cfg->ep->bcode->iov_len);
+
 done:
 	dbus_message_iter_close_container(iter, &dict);
 }
@@ -1707,12 +1824,20 @@ static DBusMessage *endpoint_select_properties_reply(struct endpoint *ep,
 	cfg = new0(struct endpoint_config, 1);
 	cfg->ep = ep;
 
-	/* Copy capabilities */
-	iov_append(&cfg->caps, preset->data.iov_base, preset->data.iov_len);
+	if (ep->broadcast) {
+		iov_append(&cfg->ep->bcode, bcast_qos.bcast.bcode, sizeof(bcast_qos.bcast.bcode));
+		/* Copy capabilities for broadcast*/
+		iov_append(&cfg->caps, base_lc3_16_2_1, sizeof(base_lc3_16_2_1));
+	} else {
+		/* Copy capabilities */
+		iov_append(&cfg->caps, preset->data.iov_base, preset->data.iov_len);
+	}
+
 	cfg->target_latency = preset->target_latency;
 
 	/* Copy metadata */
-	iov_append(&cfg->meta, cfg->ep->meta->iov_base, cfg->ep->meta->iov_len);
+	if (cfg->ep->meta)
+		iov_append(&cfg->meta, cfg->ep->meta->iov_base, cfg->ep->meta->iov_len);
 
 	if (preset->qos.phy)
 		/* Set QoS parameters */
@@ -2073,14 +2198,14 @@ fail:
 
 }
 
-static void endpoint_cis(const char *input, void *user_data)
+static void endpoint_iso_stream(const char *input, void *user_data)
 {
 	struct endpoint *ep = user_data;
 	char *endptr = NULL;
 	int value;
 
 	if (!strcasecmp(input, "a") || !strcasecmp(input, "auto")) {
-		ep->cis = BT_ISO_QOS_CIS_UNSET;
+		ep->iso_stream = BT_ISO_QOS_STREAM_UNSET;
 	} else {
 		value = strtol(input, &endptr, 0);
 
@@ -2089,20 +2214,20 @@ static void endpoint_cis(const char *input, void *user_data)
 			return bt_shell_noninteractive_quit(EXIT_FAILURE);
 		}
 
-		ep->cis = value;
+		ep->iso_stream = value;
 	}
 
 	endpoint_register(ep);
 }
 
-static void endpoint_cig(const char *input, void *user_data)
+static void endpoint_iso_group(const char *input, void *user_data)
 {
 	struct endpoint *ep = user_data;
 	char *endptr = NULL;
 	int value;
 
 	if (!strcasecmp(input, "a") || !strcasecmp(input, "auto")) {
-		ep->cig = BT_ISO_QOS_CIG_UNSET;
+		ep->iso_group = BT_ISO_QOS_GROUP_UNSET;
 	} else {
 		value = strtol(input, &endptr, 0);
 
@@ -2111,10 +2236,13 @@ static void endpoint_cig(const char *input, void *user_data)
 			return bt_shell_noninteractive_quit(EXIT_FAILURE);
 		}
 
-		ep->cig = value;
+		ep->iso_group = value;
 	}
 
-	bt_shell_prompt_input(ep->path, "CIS (auto/value):", endpoint_cis, ep);
+	if (!ep->broadcast)
+		bt_shell_prompt_input(ep->path, "CIS (auto/value):", endpoint_iso_stream, ep);
+	else
+		bt_shell_prompt_input(ep->path, "BIS (auto/value):", endpoint_iso_stream, ep);
 }
 
 static void endpoint_auto_accept(const char *input, void *user_data)
@@ -2130,7 +2258,13 @@ static void endpoint_auto_accept(const char *input, void *user_data)
 		return bt_shell_noninteractive_quit(EXIT_FAILURE);
 	}
 
-	bt_shell_prompt_input(ep->path, "CIG (auto/value):", endpoint_cig, ep);
+	if (!strcmp(ep->uuid, BROADCAST_AUDIO_ANNOUNCEMENT_SERVICE_UUID)) {
+		bt_shell_prompt_input(ep->path, "BIG (auto/value):", endpoint_iso_group, ep);
+		ep->broadcast = true;
+	} else {
+		bt_shell_prompt_input(ep->path, "CIG (auto/value):", endpoint_iso_group, ep);
+		ep->broadcast = false;
+	}
 }
 
 static void endpoint_set_metadata(const char *input, void *user_data)
@@ -2227,6 +2361,7 @@ static void cmd_register_endpoint(int argc, char *argv[])
 	char **list;
 
 	ep = g_new0(struct endpoint, 1);
+	ep->meta = NULL;
 	ep->uuid = g_strdup(argv[1]);
 	ep->codec = strtol(argv[2], &endptr, 0);
 	ep->cid = 0x0000;
@@ -2861,8 +2996,8 @@ static void register_endpoints(GDBusProxy *proxy)
 
 			ep = endpoint_new(cap);
 			ep->auto_accept = true;
-			ep->cig = BT_ISO_QOS_CIG_UNSET;
-			ep->cis = BT_ISO_QOS_CIS_UNSET;
+			ep->iso_group = BT_ISO_QOS_GROUP_UNSET;
+			ep->iso_stream = BT_ISO_QOS_STREAM_UNSET;
 			endpoint_register(ep);
 		}
 
@@ -3409,6 +3544,7 @@ static void cmd_acquire_transport(int argc, char *argv[])
 {
 	GDBusProxy *proxy;
 	int i;
+	struct endpoint *ep, *link;
 
 	for (i = 1; i < argc; i++) {
 		proxy = g_dbus_proxy_lookup(transports, NULL, argv[i],
@@ -3424,6 +3560,27 @@ static void cmd_acquire_transport(int argc, char *argv[])
 			return bt_shell_noninteractive_quit(EXIT_FAILURE);
 		}
 
+		ep = find_ep_by_transport(g_dbus_proxy_get_path(proxy));
+		if (!ep || ep->acquiring) {
+			bt_shell_printf("Transport %s already in acquiring process\n",
+					argv[i]);
+			return bt_shell_noninteractive_quit(EXIT_FAILURE);
+		}
+
+		ep->acquiring = true;
+
+		link = find_link_by_proxy(proxy);
+		if (link) {
+			bt_shell_printf("Link %s found\n", link->transport);
+			/* If link already acquiring wait it to be complete */
+			if (link->acquiring) {
+				bt_shell_printf("Link %s already in acquiring process\n",
+					argv[i]);
+				return bt_shell_noninteractive_quit(EXIT_FAILURE);
+			}
+			link->acquiring = true;
+		}
+
 		if (!g_dbus_proxy_method_call(proxy, "Acquire", NULL,
 						acquire_reply, proxy, NULL)) {
 			bt_shell_printf("Failed acquire transport\n");
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH BlueZ 6/6] bap: Add initial support for BAP broadcast source
  2023-05-23 14:34 [PATCH BlueZ 0/6] Add initial support for BAP broadcast source Iulia Tanasescu
                   ` (4 preceding siblings ...)
  2023-05-23 14:35 ` [PATCH BlueZ 5/6] client/player: Update bluetoothctl with support for broadcast source Iulia Tanasescu
@ 2023-05-23 14:35 ` Iulia Tanasescu
  2023-05-23 16:46   ` Luiz Augusto von Dentz
  2023-05-26 22:10 ` [PATCH BlueZ 0/6] " patchwork-bot+bluetooth
  2023-05-26 22:40 ` patchwork-bot+bluetooth
  7 siblings, 1 reply; 17+ messages in thread
From: Iulia Tanasescu @ 2023-05-23 14:35 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Silviu Florian Barbulescu

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

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,
 };
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* RE: Add initial support for BAP broadcast source
  2023-05-23 14:34 ` [PATCH BlueZ 1/6] doc: Update Docs " Iulia Tanasescu
@ 2023-05-23 15:14   ` bluez.test.bot
  0 siblings, 0 replies; 17+ messages in thread
From: bluez.test.bot @ 2023-05-23 15:14 UTC (permalink / raw)
  To: linux-bluetooth, iulia.tanasescu

[-- Attachment #1: Type: text/plain, Size: 531 bytes --]

This is an automated email and please do not reply to this email.

Dear Submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
While preparing the CI tests, the patches you submitted couldn't be applied to the current HEAD of the repository.

----- Output -----

error: patch failed: client/player.c:73
error: client/player.c: patch does not apply
hint: Use 'git am --show-current-patch' to see the failed patch

Please resolve the issue and submit the patches again.


---
Regards,
Linux Bluetooth


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH BlueZ 5/6] client/player: Update bluetoothctl with support for broadcast source
  2023-05-23 14:35 ` [PATCH BlueZ 5/6] client/player: Update bluetoothctl with support for broadcast source Iulia Tanasescu
@ 2023-05-23 16:31   ` Luiz Augusto von Dentz
  2023-05-24  8:38     ` Silviu Florian Barbulescu
  0 siblings, 1 reply; 17+ messages in thread
From: Luiz Augusto von Dentz @ 2023-05-23 16:31 UTC (permalink / raw)
  To: Iulia Tanasescu; +Cc: linux-bluetooth, Silviu Florian Barbulescu

Hi Iulia,

On Tue, May 23, 2023 at 7:45 AM Iulia Tanasescu <iulia.tanasescu@nxp.com> wrote:
>
> From: Silviu Florian Barbulescu <silviu.barbulescu@nxp.com>
>
> This adds bluetoothctl support for broadcast source.

Can we have an example of how the commands look?

> ---
>  client/player.c | 207 ++++++++++++++++++++++++++++++++++++++++++------
>  1 file changed, 182 insertions(+), 25 deletions(-)
>
> diff --git a/client/player.c b/client/player.c
> index 7719076c8..1ba722150 100644
> --- a/client/player.c
> +++ b/client/player.c
> @@ -73,10 +73,12 @@ struct endpoint {
>         struct iovec *meta;
>         bool auto_accept;
>         bool acquiring;
> -       uint8_t cig;
> -       uint8_t cis;
> +       uint8_t iso_group;
> +       uint8_t iso_stream;
>         char *transport;
>         DBusMessage *msg;
> +       bool broadcast;
> +       struct iovec *bcode;
>  };
>
>  static DBusConnection *dbus_conn;
> @@ -102,6 +104,22 @@ struct transport {
>         struct io *timer_io;
>  };
>
> +static const uint8_t base_lc3_16_2_1[] = {
> +       0x28, 0x00, 0x00, /* Presentation Delay */
> +       0x01, /* Number of Subgroups */
> +       0x01, /* Number of BIS */
> +       0x06, 0x00, 0x00, 0x00, 0x00, /* Code ID = LC3 (0x06) */
> +       0x11, /* Codec Specific Configuration */
> +       0x02, 0x01, 0x03, /* 16 KHZ */
> +       0x02, 0x02, 0x01, /* 10 ms */
> +       0x05, 0x03, 0x01, 0x00, 0x00, 0x00,  /* Front Left */
> +       0x03, 0x04, 0x28, 0x00, /* Frame Length 40 bytes */
> +       0x04, /* Metadata */
> +       0x03, 0x02, 0x02, 0x00, /* Audio Context: Convertional */
> +       0x01, /* BIS */
> +       0x00, /* Codec Specific Configuration */
> +};
> +
>  static void endpoint_unregister(void *data)
>  {
>         struct endpoint *ep = data;
> @@ -1142,6 +1160,16 @@ static const struct capabilities {
>         CODEC_CAPABILITIES(PAC_SOURCE_UUID, LC3_ID,
>                                         LC3_DATA(LC3_FREQ_ANY, LC3_DURATION_ANY,
>                                                 3u, 30, 240)),
> +       /* Broadcast LC3 Source:
> +        *
> +        * Frequencies: 8Khz 11Khz 16Khz 22Khz 24Khz 32Khz 44.1Khz 48Khz
> +        * Duration: 7.5 ms 10 ms
> +        * Channel count: 3
> +        * Frame length: 30-240
> +        */
> +       CODEC_CAPABILITIES(BROADCAST_AUDIO_ANNOUNCEMENT_SERVICE_UUID, LC3_ID,
> +                                       LC3_DATA(LC3_FREQ_ANY, LC3_DURATION_ANY,
> +                                               3u, 30, 240)),
>  };
>
>  struct codec_qos {
> @@ -1419,6 +1447,7 @@ static struct preset {
>         PRESET(A2DP_SINK_UUID, sbc_presets, 6),
>         PRESET(PAC_SINK_UUID, lc3_presets, 3),
>         PRESET(PAC_SOURCE_UUID, lc3_presets, 3),
> +       PRESET(BROADCAST_AUDIO_ANNOUNCEMENT_SERVICE_UUID, lc3_presets, 3),
>  };
>
>  static struct codec_preset *find_preset(const char *uuid, const char *name)
> @@ -1588,6 +1617,27 @@ struct endpoint_config {
>         const struct codec_qos *qos;
>  };
>
> +#define BCODE {0x01, 0x02, 0x68, 0x05, 0x53, 0xf1, 0x41, 0x5a, \
> +                               0xa2, 0x65, 0xbb, 0xaf, 0xc6, 0xea, 0x03, 0xb8}
> +
> +static struct bt_iso_qos bcast_qos = {
> +               .bcast = {
> +                       .big = BT_ISO_QOS_BIG_UNSET,
> +                       .bis = BT_ISO_QOS_BIS_UNSET,
> +                       .sync_interval = 0x07,
> +                       .packing = 0x00,
> +                       .framing = 0x00,
> +                       .encryption = 0x00,
> +                       .bcode = BCODE,
> +                       .options = 0x00,
> +                       .skip = 0x0000,
> +                       .sync_timeout = 0x4000,
> +                       .sync_cte_type = 0x00,
> +                       .mse = 0x00,
> +                       .timeout = 0x4000,
> +               }
> +       };
> +
>  static void append_properties(DBusMessageIter *iter,
>                                                 struct endpoint_config *cfg)
>  {
> @@ -1595,6 +1645,7 @@ static void append_properties(DBusMessageIter *iter,
>         struct codec_qos *qos = (void *)cfg->qos;
>         const char *key = "Capabilities";
>         const char *meta = "Metadata";
> +       const char *keyBCode = "BroadcastCode";
>
>         dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{sv}", &dict);
>
> @@ -1605,7 +1656,7 @@ static void append_properties(DBusMessageIter *iter,
>                                         DBUS_TYPE_BYTE, &cfg->caps->iov_base,
>                                         cfg->caps->iov_len);
>
> -       if (cfg->meta->iov_len) {
> +       if ((cfg->ep->meta) && (cfg->meta->iov_len)) {
>                 g_dbus_dict_append_basic_array(&dict, DBUS_TYPE_STRING, &meta,
>                                 DBUS_TYPE_BYTE, &cfg->meta->iov_base,
>                                 cfg->meta->iov_len);
> @@ -1623,16 +1674,25 @@ static void append_properties(DBusMessageIter *iter,
>                                         DBUS_TYPE_BYTE, &cfg->target_latency);
>         }
>
> -       if (cfg->ep->cig != BT_ISO_QOS_CIG_UNSET) {
> -               bt_shell_printf("CIG 0x%2.2x\n", cfg->ep->cig);
> +       if ((!cfg->ep->broadcast) && (cfg->ep->iso_group != BT_ISO_QOS_GROUP_UNSET)) {
> +               bt_shell_printf("CIG 0x%2.2x\n", cfg->ep->iso_group);
>                 g_dbus_dict_append_entry(&dict, "CIG", DBUS_TYPE_BYTE,
> -                                                       &cfg->ep->cig);
> +                                                       &cfg->ep->iso_group);
> +       } else {
> +               bt_shell_printf("BIG 0x%2.2x\n", bcast_qos.bcast.big);
> +               g_dbus_dict_append_entry(&dict, "BIG", DBUS_TYPE_BYTE,
> +                                                       &bcast_qos.bcast.big);
>         }
>
> -       if (cfg->ep->cis != BT_ISO_QOS_CIS_UNSET) {
> -               bt_shell_printf("CIS 0x%2.2x\n", cfg->ep->cis);
> +       if ((!cfg->ep->broadcast) && (cfg->ep->iso_stream != BT_ISO_QOS_STREAM_UNSET)) {
> +               bt_shell_printf("CIS 0x%2.2x\n", cfg->ep->iso_stream);
>                 g_dbus_dict_append_entry(&dict, "CIS", DBUS_TYPE_BYTE,
> -                                                       &cfg->ep->cis);
> +                                                       &cfg->ep->iso_stream);
> +
> +       } else {
> +               bt_shell_printf("BIS 0x%2.2x\n", bcast_qos.bcast.bis);
> +               g_dbus_dict_append_entry(&dict, "BIS", DBUS_TYPE_BYTE,
> +                                                       &bcast_qos.bcast.bis);
>         }
>
>         bt_shell_printf("Interval %u\n", qos->interval);
> @@ -1640,10 +1700,17 @@ static void append_properties(DBusMessageIter *iter,
>         g_dbus_dict_append_entry(&dict, "Interval", DBUS_TYPE_UINT32,
>                                                 &qos->interval);
>
> -       bt_shell_printf("Framing %s\n", qos->framing ? "true" : "false");
> +       if (!cfg->ep->broadcast) {
> +               bt_shell_printf("Framing %s\n", qos->framing ? "true" : "false");
>
> -       g_dbus_dict_append_entry(&dict, "Framing", DBUS_TYPE_BOOLEAN,
> -                                               &qos->framing);
> +               g_dbus_dict_append_entry(&dict, "Framing", DBUS_TYPE_BOOLEAN,
> +                                                       &qos->framing);
> +       } else {
> +               bt_shell_printf("Framing %s\n", bcast_qos.bcast.framing ? "true" : "false");
> +
> +               g_dbus_dict_append_entry(&dict, "Framing", DBUS_TYPE_BOOLEAN,
> +                                                       &bcast_qos.bcast.framing);
> +       }
>
>         bt_shell_printf("PHY %s\n", qos->phy);
>
> @@ -1668,6 +1735,56 @@ static void append_properties(DBusMessageIter *iter,
>         g_dbus_dict_append_entry(&dict, "Delay", DBUS_TYPE_UINT32,
>                                                 &qos->delay);
>
> +       if (!cfg->ep->broadcast)
> +               goto done;
> +
> +       bt_shell_printf("SyncInterval %u\n", bcast_qos.bcast.sync_interval);
> +
> +       g_dbus_dict_append_entry(&dict, "SyncInterval", DBUS_TYPE_BYTE,
> +                                               &bcast_qos.bcast.sync_interval);
> +
> +       bt_shell_printf("Encryption %u\n", bcast_qos.bcast.encryption);
> +
> +       g_dbus_dict_append_entry(&dict, "Encryption", DBUS_TYPE_BYTE,
> +                                               &bcast_qos.bcast.encryption);
> +
> +       bt_shell_printf("Options %u\n", bcast_qos.bcast.options);
> +
> +       g_dbus_dict_append_entry(&dict, "Options", DBUS_TYPE_BYTE,
> +                                               &bcast_qos.bcast.options);
> +
> +       bt_shell_printf("Skip %u\n", bcast_qos.bcast.skip);
> +
> +       g_dbus_dict_append_entry(&dict, "Skip", DBUS_TYPE_UINT16,
> +                                               &bcast_qos.bcast.skip);
> +
> +       bt_shell_printf("SyncTimeout %u\n", bcast_qos.bcast.sync_timeout);
> +
> +       g_dbus_dict_append_entry(&dict, "SyncTimeout", DBUS_TYPE_UINT16,
> +                                               &bcast_qos.bcast.sync_timeout);
> +
> +       bt_shell_printf("SyncCteType %u\n", bcast_qos.bcast.sync_cte_type);
> +
> +       g_dbus_dict_append_entry(&dict, "SyncCteType", DBUS_TYPE_BYTE,
> +                                               &bcast_qos.bcast.sync_cte_type);
> +
> +       bt_shell_printf("MSE %u\n", bcast_qos.bcast.mse);
> +
> +       g_dbus_dict_append_entry(&dict, "MSE", DBUS_TYPE_BYTE,
> +                                               &bcast_qos.bcast.mse);
> +
> +       bt_shell_printf("Timeout %u\n", bcast_qos.bcast.timeout);
> +
> +       g_dbus_dict_append_entry(&dict, "Timeout", DBUS_TYPE_UINT16,
> +                                               &bcast_qos.bcast.timeout);
> +
> +       bt_shell_printf("BroadcastCode:\n");
> +       bt_shell_hexdump(cfg->ep->bcode->iov_base, cfg->ep->bcode->iov_len);
> +
> +       g_dbus_dict_append_basic_array(&dict, DBUS_TYPE_STRING, &keyBCode,
> +                                                               DBUS_TYPE_BYTE, &cfg->ep->bcode->iov_base,
> +                                                               cfg->ep->bcode->iov_len);
> +
>  done:
>         dbus_message_iter_close_container(iter, &dict);
>  }
> @@ -1707,12 +1824,20 @@ static DBusMessage *endpoint_select_properties_reply(struct endpoint *ep,
>         cfg = new0(struct endpoint_config, 1);
>         cfg->ep = ep;
>
> -       /* Copy capabilities */
> -       iov_append(&cfg->caps, preset->data.iov_base, preset->data.iov_len);
> +       if (ep->broadcast) {
> +               iov_append(&cfg->ep->bcode, bcast_qos.bcast.bcode, sizeof(bcast_qos.bcast.bcode));
> +               /* Copy capabilities for broadcast*/
> +               iov_append(&cfg->caps, base_lc3_16_2_1, sizeof(base_lc3_16_2_1));
> +       } else {
> +               /* Copy capabilities */
> +               iov_append(&cfg->caps, preset->data.iov_base, preset->data.iov_len);
> +       }
> +
>         cfg->target_latency = preset->target_latency;
>
>         /* Copy metadata */
> -       iov_append(&cfg->meta, cfg->ep->meta->iov_base, cfg->ep->meta->iov_len);
> +       if (cfg->ep->meta)
> +               iov_append(&cfg->meta, cfg->ep->meta->iov_base, cfg->ep->meta->iov_len);
>
>         if (preset->qos.phy)
>                 /* Set QoS parameters */
> @@ -2073,14 +2198,14 @@ fail:
>
>  }
>
> -static void endpoint_cis(const char *input, void *user_data)
> +static void endpoint_iso_stream(const char *input, void *user_data)
>  {
>         struct endpoint *ep = user_data;
>         char *endptr = NULL;
>         int value;
>
>         if (!strcasecmp(input, "a") || !strcasecmp(input, "auto")) {
> -               ep->cis = BT_ISO_QOS_CIS_UNSET;
> +               ep->iso_stream = BT_ISO_QOS_STREAM_UNSET;
>         } else {
>                 value = strtol(input, &endptr, 0);
>
> @@ -2089,20 +2214,20 @@ static void endpoint_cis(const char *input, void *user_data)
>                         return bt_shell_noninteractive_quit(EXIT_FAILURE);
>                 }
>
> -               ep->cis = value;
> +               ep->iso_stream = value;
>         }
>
>         endpoint_register(ep);
>  }
>
> -static void endpoint_cig(const char *input, void *user_data)
> +static void endpoint_iso_group(const char *input, void *user_data)
>  {
>         struct endpoint *ep = user_data;
>         char *endptr = NULL;
>         int value;
>
>         if (!strcasecmp(input, "a") || !strcasecmp(input, "auto")) {
> -               ep->cig = BT_ISO_QOS_CIG_UNSET;
> +               ep->iso_group = BT_ISO_QOS_GROUP_UNSET;
>         } else {
>                 value = strtol(input, &endptr, 0);
>
> @@ -2111,10 +2236,13 @@ static void endpoint_cig(const char *input, void *user_data)
>                         return bt_shell_noninteractive_quit(EXIT_FAILURE);
>                 }
>
> -               ep->cig = value;
> +               ep->iso_group = value;
>         }
>
> -       bt_shell_prompt_input(ep->path, "CIS (auto/value):", endpoint_cis, ep);
> +       if (!ep->broadcast)
> +               bt_shell_prompt_input(ep->path, "CIS (auto/value):", endpoint_iso_stream, ep);
> +       else
> +               bt_shell_prompt_input(ep->path, "BIS (auto/value):", endpoint_iso_stream, ep);
>  }
>
>  static void endpoint_auto_accept(const char *input, void *user_data)
> @@ -2130,7 +2258,13 @@ static void endpoint_auto_accept(const char *input, void *user_data)
>                 return bt_shell_noninteractive_quit(EXIT_FAILURE);
>         }
>
> -       bt_shell_prompt_input(ep->path, "CIG (auto/value):", endpoint_cig, ep);
> +       if (!strcmp(ep->uuid, BROADCAST_AUDIO_ANNOUNCEMENT_SERVICE_UUID)) {
> +               bt_shell_prompt_input(ep->path, "BIG (auto/value):", endpoint_iso_group, ep);
> +               ep->broadcast = true;
> +       } else {
> +               bt_shell_prompt_input(ep->path, "CIG (auto/value):", endpoint_iso_group, ep);
> +               ep->broadcast = false;
> +       }
>  }
>
>  static void endpoint_set_metadata(const char *input, void *user_data)
> @@ -2227,6 +2361,7 @@ static void cmd_register_endpoint(int argc, char *argv[])
>         char **list;
>
>         ep = g_new0(struct endpoint, 1);
> +       ep->meta = NULL;
>         ep->uuid = g_strdup(argv[1]);
>         ep->codec = strtol(argv[2], &endptr, 0);
>         ep->cid = 0x0000;
> @@ -2861,8 +2996,8 @@ static void register_endpoints(GDBusProxy *proxy)
>
>                         ep = endpoint_new(cap);
>                         ep->auto_accept = true;
> -                       ep->cig = BT_ISO_QOS_CIG_UNSET;
> -                       ep->cis = BT_ISO_QOS_CIS_UNSET;
> +                       ep->iso_group = BT_ISO_QOS_GROUP_UNSET;
> +                       ep->iso_stream = BT_ISO_QOS_STREAM_UNSET;
>                         endpoint_register(ep);
>                 }
>
> @@ -3409,6 +3544,7 @@ static void cmd_acquire_transport(int argc, char *argv[])
>  {
>         GDBusProxy *proxy;
>         int i;
> +       struct endpoint *ep, *link;
>
>         for (i = 1; i < argc; i++) {
>                 proxy = g_dbus_proxy_lookup(transports, NULL, argv[i],
> @@ -3424,6 +3560,27 @@ static void cmd_acquire_transport(int argc, char *argv[])
>                         return bt_shell_noninteractive_quit(EXIT_FAILURE);
>                 }
>
> +               ep = find_ep_by_transport(g_dbus_proxy_get_path(proxy));
> +               if (!ep || ep->acquiring) {
> +                       bt_shell_printf("Transport %s already in acquiring process\n",
> +                                       argv[i]);
> +                       return bt_shell_noninteractive_quit(EXIT_FAILURE);
> +               }
> +
> +               ep->acquiring = true;
> +
> +               link = find_link_by_proxy(proxy);
> +               if (link) {
> +                       bt_shell_printf("Link %s found\n", link->transport);
> +                       /* If link already acquiring wait it to be complete */
> +                       if (link->acquiring) {
> +                               bt_shell_printf("Link %s already in acquiring process\n",
> +                                       argv[i]);
> +                               return bt_shell_noninteractive_quit(EXIT_FAILURE);
> +                       }
> +                       link->acquiring = true;
> +               }
> +
>                 if (!g_dbus_proxy_method_call(proxy, "Acquire", NULL,
>                                                 acquire_reply, proxy, NULL)) {
>                         bt_shell_printf("Failed acquire transport\n");
> --
> 2.34.1
>


-- 
Luiz Augusto von Dentz

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH BlueZ 6/6] bap: Add initial support for BAP broadcast source
  2023-05-23 14:35 ` [PATCH BlueZ 6/6] bap: Add initial support for BAP " Iulia Tanasescu
@ 2023-05-23 16:46   ` Luiz Augusto von Dentz
  2023-05-24 11:44     ` Silviu Florian Barbulescu
  0 siblings, 1 reply; 17+ messages in thread
From: Luiz Augusto von Dentz @ 2023-05-23 16:46 UTC (permalink / raw)
  To: Iulia Tanasescu; +Cc: linux-bluetooth, Silviu Florian Barbulescu

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
>


-- 
Luiz Augusto von Dentz

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH BlueZ 5/6] client/player: Update bluetoothctl with support for broadcast source
  2023-05-23 16:31   ` Luiz Augusto von Dentz
@ 2023-05-24  8:38     ` Silviu Florian Barbulescu
  0 siblings, 0 replies; 17+ messages in thread
From: Silviu Florian Barbulescu @ 2023-05-24  8:38 UTC (permalink / raw)
  To: luiz.dentz; +Cc: iulia.tanasescu, linux-bluetooth, silviu.barbulescu


Hi Luiz,

To test BAP Broadcast Source support implementation use bluetoothctl with the following commands:

# endpoint.register 00001852-0000-1000-8000-00805f9b34fb 0x06

# transport.acquire /org/bluez/hci0/dev_00_00_00_00_00_00/pac_broadcast0/fd0

# transport.send /org/bluez/hci0/dev_00_00_00_00_00_00/pac_broadcast0/fd0 <file.wav>

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH BlueZ 6/6] bap: Add initial support for BAP broadcast source
  2023-05-23 16:46   ` Luiz Augusto von Dentz
@ 2023-05-24 11:44     ` Silviu Florian Barbulescu
  0 siblings, 0 replies; 17+ messages in thread
From: Silviu Florian Barbulescu @ 2023-05-24 11:44 UTC (permalink / raw)
  To: luiz.dentz; +Cc: iulia.tanasescu, linux-bluetooth, silviu.barbulescu


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

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH BlueZ 0/6] Add initial support for BAP broadcast source
  2023-05-23 14:34 [PATCH BlueZ 0/6] Add initial support for BAP broadcast source Iulia Tanasescu
                   ` (5 preceding siblings ...)
  2023-05-23 14:35 ` [PATCH BlueZ 6/6] bap: Add initial support for BAP " Iulia Tanasescu
@ 2023-05-26 22:10 ` patchwork-bot+bluetooth
  2023-05-26 22:40 ` patchwork-bot+bluetooth
  7 siblings, 0 replies; 17+ messages in thread
From: patchwork-bot+bluetooth @ 2023-05-26 22:10 UTC (permalink / raw)
  To: Iulia Tanasescu; +Cc: linux-bluetooth

Hello:

This series was applied to bluetooth/bluez.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:

On Tue, 23 May 2023 17:34:58 +0300 you wrote:
> This patch adds initial support for BAP broadcast source.
> 
> The current implementation allows BAP source endpoint registration,
> media transport creation, transport acquiring and sending broadcast ISO data.
> 
> Currently, one BIG containing one BIS is supported.
> 
> [...]

Here is the summary with links:
  - [BlueZ,1/6] doc: Update Docs for BAP broadcast source
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=f808fa065396
  - [BlueZ,2/6] lib: Add macro definitions for BAP broadcast source support
    (no matching commit)
  - [BlueZ,3/6] monitor: Check for ISO broadcast support in controller
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=97f3386268fa
  - [BlueZ,4/6] btio: Add support for setsockopt (BT_IO_OPT_BASE)
    (no matching commit)
  - [BlueZ,5/6] client/player: Update bluetoothctl with support for broadcast source
    (no matching commit)
  - [BlueZ,6/6] bap: Add initial support for BAP broadcast source
    (no matching commit)

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH BlueZ 0/6] Add initial support for BAP broadcast source
  2023-05-23 14:34 [PATCH BlueZ 0/6] Add initial support for BAP broadcast source Iulia Tanasescu
                   ` (6 preceding siblings ...)
  2023-05-26 22:10 ` [PATCH BlueZ 0/6] " patchwork-bot+bluetooth
@ 2023-05-26 22:40 ` patchwork-bot+bluetooth
  7 siblings, 0 replies; 17+ messages in thread
From: patchwork-bot+bluetooth @ 2023-05-26 22:40 UTC (permalink / raw)
  To: Iulia Tanasescu; +Cc: linux-bluetooth

Hello:

This series was applied to bluetooth/bluez.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:

On Tue, 23 May 2023 17:34:58 +0300 you wrote:
> This patch adds initial support for BAP broadcast source.
> 
> The current implementation allows BAP source endpoint registration,
> media transport creation, transport acquiring and sending broadcast ISO data.
> 
> Currently, one BIG containing one BIS is supported.
> 
> [...]

Here is the summary with links:
  - [BlueZ,1/6] doc: Update Docs for BAP broadcast source
    (no matching commit)
  - [BlueZ,2/6] lib: Add macro definitions for BAP broadcast source support
    (no matching commit)
  - [BlueZ,3/6] monitor: Check for ISO broadcast support in controller
    (no matching commit)
  - [BlueZ,4/6] btio: Add support for setsockopt (BT_IO_OPT_BASE)
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=7002ecc8914a
  - [BlueZ,5/6] client/player: Update bluetoothctl with support for broadcast source
    (no matching commit)
  - [BlueZ,6/6] bap: Add initial support for BAP broadcast source
    (no matching commit)

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: Add initial support for BAP broadcast source
  2023-06-07  8:22 [PATCH v4 1/4] Split bt_bap_qos structure into unicast and broadcast structures Silviu Florian Barbulescu
@ 2023-06-07 10:05 ` bluez.test.bot
  0 siblings, 0 replies; 17+ messages in thread
From: bluez.test.bot @ 2023-06-07 10:05 UTC (permalink / raw)
  To: linux-bluetooth, silviu.barbulescu

[-- Attachment #1: Type: text/plain, Size: 948 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=754766

---Test result---

Test Summary:
CheckPatch                    PASS      3.28 seconds
GitLint                       PASS      1.37 seconds
BuildEll                      PASS      26.70 seconds
BluezMake                     PASS      782.50 seconds
MakeCheck                     PASS      11.91 seconds
MakeDistcheck                 PASS      153.78 seconds
CheckValgrind                 PASS      248.53 seconds
CheckSmatch                   PASS      334.32 seconds
bluezmakeextell               PASS      101.15 seconds
IncrementalBuild              PASS      2619.13 seconds
ScanBuild                     PASS      1009.30 seconds



---
Regards,
Linux Bluetooth


^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: Add initial support for BAP broadcast source
  2023-05-30 14:13 [PATCH BlueZ v3 1/4] Split bt_bap_qos structure into unicast and broadcast structures Silviu Florian Barbulescu
@ 2023-05-30 16:25 ` bluez.test.bot
  0 siblings, 0 replies; 17+ messages in thread
From: bluez.test.bot @ 2023-05-30 16:25 UTC (permalink / raw)
  To: linux-bluetooth, silviu.barbulescu

[-- Attachment #1: Type: text/plain, Size: 4008 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=752257

---Test result---

Test Summary:
CheckPatch                    FAIL      3.69 seconds
GitLint                       FAIL      1.58 seconds
BuildEll                      PASS      31.72 seconds
BluezMake                     PASS      988.14 seconds
MakeCheck                     PASS      12.89 seconds
MakeDistcheck                 PASS      176.46 seconds
CheckValgrind                 PASS      292.44 seconds
CheckSmatch                   PASS      390.18 seconds
bluezmakeextell               PASS      118.95 seconds
IncrementalBuild              PASS      3260.03 seconds
ScanBuild                     PASS      1198.85 seconds

Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
[BlueZ,v3,2/4] Update bluetoothctl with support for broadcast source
WARNING:COMMIT_LOG_LONG_LINE: Possible unwrapped commit description (prefer a maximum 75 chars per line)
#99: 
To test the current implementation use bluetoothctl with the following commands:

WARNING:LONG_LINE_STRING: line length of 86 exceeds 80 columns
#471: FILE: client/player.c:3769:
+			bt_shell_printf("Transport %s already in acquiring process\n",

WARNING:LONG_LINE_STRING: line length of 89 exceeds 80 columns
#483: FILE: client/player.c:3781:
+				bt_shell_printf("Link %s already in acquiring process\n",

WARNING:LONG_LINE: line length of 82 exceeds 80 columns
#485: FILE: client/player.c:3783:
+				return bt_shell_noninteractive_quit(EXIT_FAILURE);

/github/workspace/src/src/13260177.patch total: 0 errors, 4 warnings, 364 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/src/13260177.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


[BlueZ,v3,4/4] Update BAP plugin with broadcast source support
WARNING:LONG_LINE: line length of 82 exceeds 80 columns
#431: FILE: profiles/audio/bap.c:1170:
+			iso_qos.bcast.sync_interval = ep->qos.bcast.sync_interval;

WARNING:LONG_LINE: line length of 82 exceeds 80 columns
#440: FILE: profiles/audio/bap.c:1179:
+			iso_qos.bcast.sync_cte_type = ep->qos.bcast.sync_cte_type;

/github/workspace/src/src/13260180.patch total: 0 errors, 2 warnings, 832 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/src/13260180.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
[BlueZ,v3,2/4] Update bluetoothctl with support for broadcast source

WARNING: I3 - ignore-body-lines: gitlint will be switching from using Python regex 'match' (match beginning) to 'search' (match anywhere) semantics. Please review your ignore-body-lines.regex option accordingly. To remove this warning, set general.regex-style-search=True. More details: https://jorisroovers.github.io/gitlint/configuration/#regex-style-search
8: B1 Line exceeds max length (84>80): "  transport.send /org/bluez/hci0/dev_00_00_00_00_00_00/pac_broadcast0/fd0 <file.wav>"


---
Regards,
Linux Bluetooth


^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: Add initial support for BAP broadcast source
  2023-05-25 15:34 [PATCH v2 1/6] Update Docs " Silviu Florian Barbulescu
@ 2023-05-25 18:41 ` bluez.test.bot
  0 siblings, 0 replies; 17+ messages in thread
From: bluez.test.bot @ 2023-05-25 18:41 UTC (permalink / raw)
  To: linux-bluetooth, silviu.barbulescu

[-- Attachment #1: Type: text/plain, Size: 18108 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=751029

---Test result---

Test Summary:
CheckPatch                    FAIL      3.83 seconds
GitLint                       PASS      1.51 seconds
BuildEll                      PASS      29.80 seconds
BluezMake                     PASS      1071.96 seconds
MakeCheck                     PASS      12.70 seconds
MakeDistcheck                 PASS      169.42 seconds
CheckValgrind                 PASS      254.47 seconds
CheckSmatch                   WARNING   374.11 seconds
bluezmakeextell               PASS      103.93 seconds
IncrementalBuild              PASS      5483.91 seconds
ScanBuild                     WARNING   1144.31 seconds

Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
[v2,2/6] Add macro definitions for BAP broadcast source support
WARNING:LONG_LINE_COMMENT: line length of 83 exceeds 80 columns
#121: FILE: lib/bluetooth.h:192:
+#define BASE_MAX_LENGTH 248 /* (HCI_MAX_PER_AD_LENGTH - EIR_SERVICE_DATA_LENGTH) */

/github/workspace/src/src/13255384.patch total: 0 errors, 1 warnings, 38 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/src/13255384.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


[v2,5/6] Update bluetoothctl with support for broadcast source
WARNING:LONG_LINE: line length of 86 exceeds 80 columns
#211: FILE: client/player.c:1796:
+	if ((!cfg->ep->broadcast) && (cfg->ep->iso_group != BT_ISO_QOS_GROUP_UNSET)) {

WARNING:LONG_LINE: line length of 88 exceeds 80 columns
#224: FILE: client/player.c:1806:
+	if ((!cfg->ep->broadcast) && (cfg->ep->iso_stream != BT_ISO_QOS_STREAM_UNSET)) {

WARNING:LONG_LINE_STRING: line length of 81 exceeds 80 columns
#243: FILE: client/player.c:1823:
+		bt_shell_printf("Framing %s\n", qos->framing ? "true" : "false");

WARNING:LONG_LINE: line length of 92 exceeds 80 columns
#250: FILE: client/player.c:1828:
+		bt_shell_printf("Framing %s\n", bcast_qos.bcast.framing ? "true" : "false");

WARNING:LONG_LINE: line length of 82 exceeds 80 columns
#253: FILE: client/player.c:1831:
+							&bcast_qos.bcast.framing);

WARNING:LONG_LINE: line length of 106 exceeds 80 columns
#309: FILE: client/player.c:1904:
+								DBUS_TYPE_BYTE, &cfg->ep->bcode->iov_base,

WARNING:LONG_LINE: line length of 89 exceeds 80 columns
#310: FILE: client/player.c:1905:
+								cfg->ep->bcode->iov_len);

WARNING:LONG_LINE: line length of 98 exceeds 80 columns
#322: FILE: client/player.c:1947:
+		iov_append(&cfg->ep->bcode, bcast_qos.bcast.bcode, sizeof(bcast_qos.bcast.bcode));

WARNING:LONG_LINE: line length of 81 exceeds 80 columns
#324: FILE: client/player.c:1949:
+		iov_append(&cfg->caps, base_lc3_16_2_1, sizeof(base_lc3_16_2_1));

WARNING:LONG_LINE: line length of 84 exceeds 80 columns
#327: FILE: client/player.c:1952:
+		iov_append(&cfg->caps, preset->data.iov_base, preset->data.iov_len);

WARNING:LONG_LINE: line length of 94 exceeds 80 columns
#384: FILE: client/player.c:2408:
+		bt_shell_prompt_input(ep->path, "CIS (auto/value):", endpoint_iso_stream, ep);

WARNING:LONG_LINE: line length of 94 exceeds 80 columns
#386: FILE: client/player.c:2410:
+		bt_shell_prompt_input(ep->path, "BIS (auto/value):", endpoint_iso_stream, ep);

WARNING:LONG_LINE: line length of 93 exceeds 80 columns
#396: FILE: client/player.c:2433:
+		bt_shell_prompt_input(ep->path, "BIG (auto/value):", endpoint_iso_group, ep);

WARNING:LONG_LINE: line length of 93 exceeds 80 columns
#398: FILE: client/player.c:2435:
+		bt_shell_prompt_input(ep->path, "CIG (auto/value):", endpoint_iso_group, ep);

WARNING:LONG_LINE: line length of 93 exceeds 80 columns
#420: FILE: client/player.c:2461:
+		bt_shell_prompt_input(ep->path, "BIG (auto/value):", endpoint_iso_group, ep);

WARNING:LONG_LINE: line length of 93 exceeds 80 columns
#422: FILE: client/player.c:2463:
+		bt_shell_prompt_input(ep->path, "CIG (auto/value):", endpoint_iso_group, ep);

WARNING:LONG_LINE_STRING: line length of 86 exceeds 80 columns
#451: FILE: client/player.c:3755:
+			bt_shell_printf("Transport %s already in acquiring process\n",

WARNING:LONG_LINE_STRING: line length of 89 exceeds 80 columns
#463: FILE: client/player.c:3767:
+				bt_shell_printf("Link %s already in acquiring process\n",

WARNING:LONG_LINE: line length of 82 exceeds 80 columns
#465: FILE: client/player.c:3769:
+				return bt_shell_noninteractive_quit(EXIT_FAILURE);

/github/workspace/src/src/13255387.patch total: 0 errors, 19 warnings, 350 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/src/13255387.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


[v2,6/6] Add initial support for BAP broadcast source
WARNING:LONG_LINE: line length of 84 exceeds 80 columns
#238: FILE: profiles/audio/bap.c:370:
+							&qos->ucast.target_latency);

WARNING:LONG_LINE: line length of 82 exceeds 80 columns
#264: FILE: profiles/audio/bap.c:396:
+							&qos->bcast.sync_timeout);

WARNING:LONG_LINE: line length of 83 exceeds 80 columns
#270: FILE: profiles/audio/bap.c:402:
+							&qos->bcast.sync_cte_type);

WARNING:LONG_LINE: line length of 84 exceeds 80 columns
#387: FILE: profiles/audio/bap.c:797:
+	} else if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST) {

WARNING:LONG_LINE_COMMENT: line length of 87 exceeds 80 columns
#440: FILE: profiles/audio/bap.c:1051:
+	/* If IO already set and we are in the creation step, skip creating it again */

WARNING:LONG_LINE_COMMENT: line length of 88 exceeds 80 columns
#455: FILE: profiles/audio/bap.c:1066:
+	/* Just create socket and advance to the configured state (when defer = true) */

WARNING:LONG_LINE: line length of 82 exceeds 80 columns
#481: FILE: profiles/audio/bap.c:1092:
+		bt_bap_stream_io_connecting(stream, g_io_channel_unix_get_fd(io));

WARNING:LONG_LINE: line length of 82 exceeds 80 columns
#512: FILE: profiles/audio/bap.c:1157:
+			iso_qos.bcast.sync_interval = ep->qos.bcast.sync_interval;

WARNING:LONG_LINE: line length of 86 exceeds 80 columns
#516: FILE: profiles/audio/bap.c:1161:
+			memcpy(iso_qos.bcast.bcode, ep->qos.bcast.bcode.iov_base, 16);

WARNING:LONG_LINE: line length of 82 exceeds 80 columns
#520: FILE: profiles/audio/bap.c:1165:
+			iso_qos.bcast.sync_cte_type = ep->qos.bcast.sync_cte_type;

WARNING:LONG_LINE: line length of 104 exceeds 80 columns
#523: FILE: profiles/audio/bap.c:1168:
+			memcpy(&iso_qos.bcast.out, &ep->qos.bcast.io_qos, sizeof(struct bt_iso_io_qos));

WARNING:LONG_LINE: line length of 89 exceeds 80 columns
#526: FILE: profiles/audio/bap.c:1171:
+		iso_qos.ucast.cig = qos[0] ? qos[0]->ucast.cig_id : qos[1]->ucast.cig_id;

WARNING:LONG_LINE: line length of 89 exceeds 80 columns
#527: FILE: profiles/audio/bap.c:1172:
+		iso_qos.ucast.cis = qos[0] ? qos[0]->ucast.cis_id : qos[1]->ucast.cis_id;

WARNING:LONG_LINE: line length of 83 exceeds 80 columns
#537: FILE: profiles/audio/bap.c:1179:
+		if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST)

WARNING:LONG_LINE: line length of 84 exceeds 80 columns
#538: FILE: profiles/audio/bap.c:1180:
+			bap_connect_io_broadcast(data, ep, stream, &iso_qos, defer);

WARNING:LONG_LINE: line length of 91 exceeds 80 columns
#554: FILE: profiles/audio/bap.c:1221:
+			if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_UNICAST) {

WARNING:LONG_LINE: line length of 84 exceeds 80 columns
#556: FILE: profiles/audio/bap.c:1223:
+				ep->id = bt_bap_stream_qos(stream, &ep->qos, qos_cb,

WARNING:LONG_LINE: line length of 84 exceeds 80 columns
#557: FILE: profiles/audio/bap.c:1224:
+										ep);

WARNING:LONG_LINE: line length of 82 exceeds 80 columns
#560: FILE: profiles/audio/bap.c:1227:
+					bt_bap_stream_release(stream, NULL, NULL);

WARNING:LONG_LINE: line length of 85 exceeds 80 columns
#570: FILE: profiles/audio/bap.c:1240:
+		if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST) {

WARNING:LONG_LINE: line length of 91 exceeds 80 columns
#592: FILE: profiles/audio/bap.c:1274:
+		bt_bap_foreach_pac(data->bap, BT_BAP_BROADCAST_SOURCE, pac_found, service);

WARNING:LONG_LINE: line length of 87 exceeds 80 columns
#673: FILE: profiles/audio/bap.c:1426:
+					ep->qos.ucast.cis_id == BT_ISO_QOS_CIS_UNSET) {

WARNING:LONG_LINE: line length of 92 exceeds 80 columns
#699: FILE: profiles/audio/bap.c:1443:
+						ep->qos.ucast.cig_id, ep->qos.ucast.cis_id);

WARNING:LONG_LINE: line length of 88 exceeds 80 columns
#700: FILE: profiles/audio/bap.c:1444:
+	} else if (bt_bap_stream_get_type(ep->stream) == BT_BAP_STREAM_TYPE_BROADCAST) {

WARNING:LONG_LINE: line length of 84 exceeds 80 columns
#703: FILE: profiles/audio/bap.c:1447:
+					ep->qos.bcast.bis == BT_ISO_QOS_BIS_UNSET) {

WARNING:LONG_LINE: line length of 86 exceeds 80 columns
#722: FILE: profiles/audio/bap.c:1464:
+						ep->qos.bcast.big, ep->qos.bcast.bis);

WARNING:LONG_LINE: line length of 98 exceeds 80 columns
#734: FILE: profiles/audio/bap.c:1616:
+	struct btd_device *device = btd_adapter_get_device(adapter, BDADDR_ANY, BDADDR_LE_PUBLIC);

WARNING:LONG_LINE: line length of 86 exceeds 80 columns
#769: FILE: profiles/audio/bap.c:1651:
+						pac_removed_broadcast, service, NULL);

WARNING:LONG_LINE: line length of 83 exceeds 80 columns
#779: FILE: profiles/audio/bap.c:1661:
+	struct bap_data *data = queue_find(sessions, match_data_bap_data, adapter);

WARNING:LONG_LINE: line length of 84 exceeds 80 columns
#911: FILE: profiles/audio/media.c:853:
+							&qos->ucast.target_latency);

WARNING:LONG_LINE: line length of 82 exceeds 80 columns
#936: FILE: profiles/audio/media.c:878:
+							&qos->bcast.sync_timeout);

WARNING:LONG_LINE: line length of 83 exceeds 80 columns
#942: FILE: profiles/audio/media.c:884:
+							&qos->bcast.sync_cte_type);

WARNING:LONG_LINE: line length of 83 exceeds 80 columns
#949: FILE: profiles/audio/media.c:891:
+							&qos->bcast.sync_interval);

WARNING:LONG_LINE: line length of 85 exceeds 80 columns
#1016: FILE: profiles/audio/media.c:1272:
+static bool endpoint_init_broadcast_source(struct media_endpoint *endpoint, int *err)

WARNING:LONG_LINE: line length of 96 exceeds 80 columns
#1082: FILE: profiles/audio/transport.c:551:
+	if (bt_bap_stream_get_type(get_stream_bap(transport)) == BT_BAP_STREAM_TYPE_BROADCAST) {

WARNING:LONG_LINE: line length of 94 exceeds 80 columns
#1096: FILE: profiles/audio/transport.c:562:
+	if (bt_bap_stream_get_type(get_stream_bap(transport)) == BT_BAP_STREAM_TYPE_UNICAST) {

WARNING:LONG_LINE: line length of 89 exceeds 80 columns
#1136: FILE: profiles/audio/transport.c:880:
+							&bap->qos.ucast.io_qos.interval);

WARNING:LONG_LINE: line length of 89 exceeds 80 columns
#1154: FILE: profiles/audio/transport.c:903:
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &bap->qos.ucast.io_qos.phy);

WARNING:LONG_LINE: line length of 91 exceeds 80 columns
#1163: FILE: profiles/audio/transport.c:914:
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &bap->qos.ucast.io_qos.sdu);

WARNING:LONG_LINE: line length of 89 exceeds 80 columns
#1172: FILE: profiles/audio/transport.c:925:
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &bap->qos.ucast.io_qos.rtn);

WARNING:LONG_LINE: line length of 88 exceeds 80 columns
#1181: FILE: profiles/audio/transport.c:937:
+							&bap->qos.ucast.io_qos.latency);

WARNING:LONG_LINE: line length of 86 exceeds 80 columns
#1190: FILE: profiles/audio/transport.c:948:
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &bap->qos.ucast.delay);

WARNING:LONG_LINE: line length of 82 exceeds 80 columns
#1262: FILE: src/shared/bap.c:662:
+static struct bt_bap_endpoint *bap_get_endpoint_broadcast(struct queue *endpoints,

WARNING:LONG_LINE: line length of 83 exceeds 80 columns
#1325: FILE: src/shared/bap.c:1298:
+static void stream_set_state_broadcast(struct bt_bap_stream *stream, uint8_t state)

WARNING:LONG_LINE: line length of 81 exceeds 80 columns
#1362: FILE: src/shared/bap.c:1464:
+	if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST)	{

WARNING:LONG_LINE: line length of 111 exceeds 80 columns
#1397: FILE: src/shared/bap.c:1660:
+			req->cig, req->cis, qos.ucast.io_qos.interval, qos.ucast.framing, qos.ucast.io_qos.phy,

WARNING:LONG_LINE: line length of 111 exceeds 80 columns
#1398: FILE: src/shared/bap.c:1661:
+			qos.ucast.io_qos.sdu, qos.ucast.io_qos.rtn, qos.ucast.io_qos.latency, qos.ucast.delay);

WARNING:LONG_LINE: line length of 94 exceeds 80 columns
#1449: FILE: src/shared/bap.c:2533:
+		pac_brodcast_sink = bap_pac_new(bdb, name, type, &codec, qos, data, metadata);

WARNING:LONG_LINE: line length of 92 exceeds 80 columns
#1472: FILE: src/shared/bap.c:2556:
+							data, metadata, pac_ops, user_data);

WARNING:LONG_LINE: line length of 82 exceeds 80 columns
#1488: FILE: src/shared/bap.c:2589:
+	else if ((bt_bap_pac_get_type(stream->lpac) == BT_BAP_BROADCAST_SOURCE) ||

WARNING:LONG_LINE: line length of 85 exceeds 80 columns
#1489: FILE: src/shared/bap.c:2590:
+			(bt_bap_pac_get_type(stream->lpac) == BT_BAP_BROADCAST_SINK))

WARNING:LONG_LINE: line length of 94 exceeds 80 columns
#1562: FILE: src/shared/bap.c:4214:
+		return bap_foreach_pac(bap->ldb->broadcast_sources, bap->ldb->broadcast_sinks,

WARNING:LONG_LINE: line length of 81 exceeds 80 columns
#1563: FILE: src/shared/bap.c:4215:
+								func, user_data);

WARNING:LONG_LINE: line length of 88 exceeds 80 columns
#1619: FILE: src/shared/bap.c:4355:
+		req = bap_req_new(stream, BT_ASCS_CONFIG, iov, iovlen, func, user_data);

WARNING:LONG_LINE: line length of 84 exceeds 80 columns
#1635: FILE: src/shared/bap.c:4365:
+	} else if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST) {

WARNING:LONG_LINE: line length of 103 exceeds 80 columns
#1659: FILE: src/shared/bap.c:4498:
+								ep_config_cb, stream->lpac->user_data);

WARNING:LONG_LINE: line length of 81 exceeds 80 columns
#1707: FILE: src/shared/bap.c:4618:
+		ret = bap_stream_metadata(stream, BT_ASCS_ENABLE, metadata, func,

WARNING:LONG_LINE: line length of 84 exceeds 80 columns
#1714: FILE: src/shared/bap.c:4624:
+	} else if (bt_bap_stream_get_type(stream) == BT_BAP_STREAM_TYPE_BROADCAST) {

WARNING:LONG_LINE: line length of 82 exceeds 80 columns
#1715: FILE: src/shared/bap.c:4625:
+		stream_set_state_broadcast(stream, BT_BAP_STREAM_STATE_STREAMING);

WARNING:LONG_LINE: line length of 85 exceeds 80 columns
#1728: FILE: src/shared/bap.c:4809:
+			stream_set_state_broadcast(stream, BT_BAP_STREAM_STATE_IDLE);

WARNING:LONG_LINE_COMMENT: line length of 91 exceeds 80 columns
#1745: FILE: src/shared/bap.c:4853:
+		// TO DO get the location values from metadata for brodcast source and sink

WARNING:LONG_LINE: line length of 92 exceeds 80 columns
#1775: FILE: src/shared/bap.c:5008:
+	if (!qos || *qos || stream->ep->dir != BT_BAP_SINK || !stream->qos.ucast.io_qos.sdu)

WARNING:LONG_LINE: line length of 92 exceeds 80 columns
#1931: FILE: unit/test-bap.c:380:
+							NULL, data->caps, NULL, NULL, NULL);

WARNING:LONG_LINE: line length of 92 exceeds 80 columns
#1936: FILE: unit/test-bap.c:384:
+							NULL, data->caps, NULL, NULL, NULL);

WARNING:LONG_LINE: line length of 92 exceeds 80 columns
#1945: FILE: unit/test-bap.c:394:
+							NULL, data->caps, NULL, NULL, NULL);

WARNING:LONG_LINE: line length of 92 exceeds 80 columns
#1950: FILE: unit/test-bap.c:398:
+							NULL, data->caps, NULL, NULL, NULL);

/github/workspace/src/src/13255388.patch total: 0 errors, 66 warnings, 2017 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/src/13255388.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


##############################
Test: CheckSmatch - WARNING
Desc: Run smatch tool with source
Output:
monitor/packet.c: note: in included file:monitor/display.h:82:26: warning: Variable length array is used.monitor/packet.c:1806:26: warning: Variable length array is used.monitor/packet.c: note: in included file:monitor/bt.h:3552:52: warning: array of flexible structuresmonitor/bt.h:3540:40: warning: array of flexible structures
##############################
Test: ScanBuild - WARNING
Desc: Run Scan Build
Output:
profiles/audio/bap.c:1094:3: warning: Value stored to 'io' is never read
                io = ep->io;
                ^    ~~~~~~
profiles/audio/bap.c:1171:55: warning: Dereference of null pointer
                iso_qos.ucast.cig = qos[0] ? qos[0]->ucast.cig_id : qos[1]->ucast.cig_id;
                                                                    ^~~~~~~~~~~~~~~~~~~~
2 warnings generated.
src/shared/bap.c:4626:10: warning: Although the value stored to 'ret' is used in the enclosing expression, the value is never actually read from 'ret'
                return ret = 1;
                       ^     ~
1 warning generated.



---
Regards,
Linux Bluetooth


^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2023-06-07 10:05 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-23 14:34 [PATCH BlueZ 0/6] Add initial support for BAP broadcast source Iulia Tanasescu
2023-05-23 14:34 ` [PATCH BlueZ 1/6] doc: Update Docs " Iulia Tanasescu
2023-05-23 15:14   ` Add initial support " bluez.test.bot
2023-05-23 14:35 ` [PATCH BlueZ 2/6] lib: Add macro definitions for BAP broadcast source support Iulia Tanasescu
2023-05-23 14:35 ` [PATCH BlueZ 3/6] monitor: Check for ISO broadcast support in controller Iulia Tanasescu
2023-05-23 14:35 ` [PATCH BlueZ 4/6] btio: Add support for setsockopt (BT_IO_OPT_BASE) Iulia Tanasescu
2023-05-23 14:35 ` [PATCH BlueZ 5/6] client/player: Update bluetoothctl with support for broadcast source Iulia Tanasescu
2023-05-23 16:31   ` Luiz Augusto von Dentz
2023-05-24  8:38     ` Silviu Florian Barbulescu
2023-05-23 14:35 ` [PATCH BlueZ 6/6] bap: Add initial support for BAP " Iulia Tanasescu
2023-05-23 16:46   ` Luiz Augusto von Dentz
2023-05-24 11:44     ` Silviu Florian Barbulescu
2023-05-26 22:10 ` [PATCH BlueZ 0/6] " patchwork-bot+bluetooth
2023-05-26 22:40 ` patchwork-bot+bluetooth
2023-05-25 15:34 [PATCH v2 1/6] Update Docs " Silviu Florian Barbulescu
2023-05-25 18:41 ` Add initial support " bluez.test.bot
2023-05-30 14:13 [PATCH BlueZ v3 1/4] Split bt_bap_qos structure into unicast and broadcast structures Silviu Florian Barbulescu
2023-05-30 16:25 ` Add initial support for BAP broadcast source bluez.test.bot
2023-06-07  8:22 [PATCH v4 1/4] Split bt_bap_qos structure into unicast and broadcast structures Silviu Florian Barbulescu
2023-06-07 10:05 ` Add initial support for BAP broadcast source bluez.test.bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).