2023-08-02 09:14:27

by Claudia Draghicescu

[permalink] [raw]
Subject: [PATCH BlueZ v3 0/6] Add support for BAP broadcast sink

This series of patches adds support for BAP broadcast sink.
It consists in registering a broadcastsink endpoint using the
Basic Audio Announcement Service UUID,
discovering of broadcast advertisers that announce the
Broadcast Audio Announcement Service, synchronizes to the Periodic
advertisements of the source and synchronizes to the BIG advertised
in the PA train.
To retrieve the BASE info advertised in the PA train, the patch
Bluetooth: ISO: Add support for periodic adv reports processing
was used.

This feature was tested using bluetoothctl with the following commands:

[bluetooth]# endpoint.register 00001851-0000-1000-8000-00805f9b34fb 0x06
[bluetooth]# scan on
[NEW] Endpoint /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/pac_bcast0
[bluetooth]# endpoint.config
/org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/pac_bcast0
/local/endpoint/ep0 16_2_1

Claudia Draghicescu (6):
client/player: Add broadcast sink endpoint registration
media: Add support for a broadcast sink media endpoint
transport: Update transport properties for a broadcast stream
btio: Add support for getsockopt(BT_ISO_BASE)
bap: Create synchronization with source and create BAP broadcast sink
stream
adapter: Trigger adapter driver when a broadcast source is discovered

btio/btio.c | 13 +-
client/player.c | 61 +++++++-
profiles/audio/bap.c | 300 +++++++++++++++++++++++++++++++++----
profiles/audio/media.c | 81 ++++++++--
profiles/audio/media.h | 3 +-
profiles/audio/transport.c | 245 +++++++++++++++++++++++++++++-
src/adapter.c | 48 ++++++
src/adapter.h | 2 +
src/shared/bap.c | 153 ++++++++++++++++---
src/shared/bap.h | 11 +-
10 files changed, 835 insertions(+), 82 deletions(-)


base-commit: 8eb1dee87e019f29b6c8233dfe0f9aef8ee44461
--
2.34.1



2023-08-02 09:14:28

by Claudia Draghicescu

[permalink] [raw]
Subject: [PATCH BlueZ v3 4/6] btio: Add support for getsockopt(BT_ISO_BASE)

This adds the posibility for a broadcast sink to retrieve the
BASE information received from a source afeter a PA synchronization,
using the getsockopt(BT_ISO_BASE) function.
This needs the patch from bluetooth-next:
Bluetooth: ISO: Add support for periodic adv reports processing

---
btio/btio.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/btio/btio.c b/btio/btio.c
index 179be6289..8178250d2 100644
--- a/btio/btio.c
+++ b/btio/btio.c
@@ -1638,6 +1638,7 @@ static gboolean iso_get(int sock, GError **err, BtIOOption opt1, va_list args)
BtIOOption opt = opt1;
struct sockaddr_iso src, dst;
struct bt_iso_qos qos;
+ struct bt_iso_base base;
socklen_t len;
uint32_t phy;

@@ -1648,6 +1649,11 @@ static gboolean iso_get(int sock, GError **err, BtIOOption opt1, va_list args)
return FALSE;
}

+ if (getsockopt(sock, SOL_BLUETOOTH, BT_ISO_BASE, &base, &len) < 0) {
+ ERROR_FAILED(err, "getsockopt(BT_ISO_BASE)", errno);
+ return FALSE;
+ }
+
if (!get_src(sock, &src, sizeof(src), err))
return FALSE;

@@ -1694,6 +1700,8 @@ static gboolean iso_get(int sock, GError **err, BtIOOption opt1, va_list args)
*(va_arg(args, struct bt_iso_qos *)) = qos;
break;
case BT_IO_OPT_BASE:
+ *(va_arg(args, struct bt_iso_base *)) = base;
+ break;
case BT_IO_OPT_HANDLE:
case BT_IO_OPT_CLASS:
case BT_IO_OPT_DEFER_TIMEOUT:
@@ -1896,8 +1904,9 @@ static GIOChannel *create_io(gboolean server, struct set_opts *opts,
goto failed;
if (!iso_set_qos(sock, &opts->qos, err))
goto failed;
- if (!iso_set_base(sock, &opts->base, err))
- goto failed;
+ if (opts->base.base_len)
+ if (!iso_set_base(sock, &opts->base, err))
+ goto failed;
break;
case BT_IO_INVALID:
default:
--
2.34.1


2023-08-02 09:14:28

by Claudia Draghicescu

[permalink] [raw]
Subject: [PATCH BlueZ v3 2/6] media: Add broadcast sink media endpoint

This patch adds the possibility to register a broadcast
media endpoint if the controller has support for ISO Sync Receiver.

---
profiles/audio/media.c | 81 ++++++++++++++++++++++++++++++++++--------
profiles/audio/media.h | 3 +-
2 files changed, 68 insertions(+), 16 deletions(-)

diff --git a/profiles/audio/media.c b/profiles/audio/media.c
index 15c64c8d6..edf106a12 100644
--- a/profiles/audio/media.c
+++ b/profiles/audio/media.c
@@ -105,6 +105,7 @@ struct media_endpoint {
GSList *requests;
struct media_adapter *adapter;
GSList *transports;
+ bool broadcast;
};

struct media_player {
@@ -1059,6 +1060,9 @@ static struct media_transport *pac_bcast_config(struct bt_bap_stream *stream,
{
struct bt_bap *bap = bt_bap_stream_get_session(stream);
struct btd_adapter *adapter = bt_bap_get_user_data(bap);
+ struct btd_device *device =
+ btd_adapter_find_device_by_path(bt_bap_get_user_data(bap),
+ bt_bap_stream_get_remote_name(stream));
const char *path;

if (!adapter) {
@@ -1066,9 +1070,17 @@ static struct media_transport *pac_bcast_config(struct bt_bap_stream *stream,
return NULL;
}

+ if (!device) {
+ DBG("no device found");
+ } else {
+ char name[30];
+
+ device_get_name(device, name, 30);
+ DBG("device found name %s", name);
+ }
path = bt_bap_stream_get_user_data(stream);

- return media_transport_create(NULL, path, cfg->iov_base, cfg->iov_len,
+ return media_transport_create(device, path, cfg->iov_base, cfg->iov_len,
endpoint, stream);
}

@@ -1238,6 +1250,12 @@ static bool endpoint_init_broadcast_source(struct media_endpoint *endpoint,
return endpoint_init_pac(endpoint, BT_BAP_BCAST_SOURCE, err);
}

+static bool endpoint_init_broadcast_sink(struct media_endpoint *endpoint,
+ int *err)
+{
+ return endpoint_init_pac(endpoint, BT_BAP_BCAST_SINK, err);
+}
+
static bool endpoint_properties_exists(const char *uuid,
struct btd_device *dev,
void *user_data)
@@ -1351,6 +1369,17 @@ static bool experimental_broadcaster_ep_supported(struct btd_adapter *adapter)
return g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL;
}

+static bool experimental_bcast_sink_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_SYNC_RECEIVER))
+ 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);
@@ -1366,6 +1395,8 @@ static struct media_endpoint_init {
experimental_endpoint_supported },
{ BCAA_SERVICE_UUID, endpoint_init_broadcast_source,
experimental_broadcaster_ep_supported },
+ { BAA_SERVICE_UUID, endpoint_init_broadcast_sink,
+ experimental_bcast_sink_ep_supported },
};

static struct media_endpoint *
@@ -1382,6 +1413,7 @@ media_endpoint_create(struct media_adapter *adapter,
int size,
uint8_t *metadata,
int metadata_size,
+ bool broadcast,
int *err)
{
struct media_endpoint *endpoint;
@@ -1397,6 +1429,7 @@ media_endpoint_create(struct media_adapter *adapter,
endpoint->cid = cid;
endpoint->vid = vid;
endpoint->delay_reporting = delay_reporting;
+ endpoint->broadcast = broadcast;

if (qos)
endpoint->qos = *qos;
@@ -1458,11 +1491,11 @@ struct vendor {
} __packed;

static int parse_properties(DBusMessageIter *props, const char **uuid,
- gboolean *delay_reporting, uint8_t *codec,
- uint16_t *cid, uint16_t *vid,
- struct bt_bap_pac_qos *qos,
- uint8_t **capabilities, int *size,
- uint8_t **metadata, int *metadata_size)
+ gboolean *delay_reporting, uint8_t *codec,
+ uint16_t *cid, uint16_t *vid,
+ struct bt_bap_pac_qos *qos,
+ uint8_t **capabilities, int *size,
+ uint8_t **metadata, int *metadata_size, bool *broadcast)
{
gboolean has_uuid = FALSE;
gboolean has_codec = FALSE;
@@ -1546,6 +1579,10 @@ static int parse_properties(DBusMessageIter *props, const char **uuid,
if (var != DBUS_TYPE_UINT16)
return -EINVAL;
dbus_message_iter_get_basic(&value, &qos->ppd_max);
+ } else if (strcasecmp(key, "Broadcast") == 0) {
+ if (var != DBUS_TYPE_BOOLEAN)
+ return -EINVAL;
+ dbus_message_iter_get_basic(&value, broadcast);
}

dbus_message_iter_next(props);
@@ -1569,6 +1606,7 @@ static DBusMessage *register_endpoint(DBusConnection *conn, DBusMessage *msg,
uint8_t *metadata = NULL;
int size = 0;
int metadata_size = 0;
+ bool broadcast = false;
int err;

sender = dbus_message_get_sender(msg);
@@ -1587,13 +1625,13 @@ static DBusMessage *register_endpoint(DBusConnection *conn, DBusMessage *msg,

if (parse_properties(&props, &uuid, &delay_reporting, &codec, &cid,
&vid, &qos, &capabilities, &size, &metadata,
- &metadata_size) < 0)
+ &metadata_size, &broadcast) < 0)
return btd_error_invalid_args(msg);

if (media_endpoint_create(adapter, sender, path, uuid, delay_reporting,
- codec, cid, vid, &qos, capabilities,
- size, metadata, metadata_size,
- &err) == NULL) {
+ codec, cid, vid, &qos, capabilities,
+ size, metadata, metadata_size, broadcast,
+ &err) == NULL) {
if (err == -EPROTONOSUPPORT)
return btd_error_not_supported(msg);
else
@@ -2627,6 +2665,7 @@ static void app_register_endpoint(void *data, void *user_data)
int metadata_size = 0;
DBusMessageIter iter, array;
struct media_endpoint *endpoint;
+ bool broadcast = false;

if (app->err)
return;
@@ -2736,12 +2775,18 @@ static void app_register_endpoint(void *data, void *user_data)
dbus_message_iter_get_basic(&iter, &qos.ppd_min);
}

+ if (g_dbus_proxy_get_property(proxy, "Broadcast", &iter)) {
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
+ goto fail;
+ dbus_message_iter_get_basic(&iter, &broadcast);
+ }
+
endpoint = media_endpoint_create(app->adapter, app->sender, path, uuid,
- delay_reporting, codec,
- vendor.cid, vendor.vid, &qos,
- capabilities, size,
- metadata, metadata_size,
- &app->err);
+ delay_reporting, codec,
+ vendor.cid, vendor.vid, &qos,
+ capabilities, size,
+ metadata, metadata_size, broadcast,
+ &app->err);
if (!endpoint) {
error("Unable to register endpoint %s:%s: %s", app->sender,
path, strerror(-app->err));
@@ -3245,3 +3290,9 @@ struct btd_adapter *media_endpoint_get_btd_adapter(
{
return endpoint->adapter->btd_adapter;
}
+
+bool media_endpoint_is_broadcast(
+ struct media_endpoint *endpoint)
+{
+ return endpoint->broadcast;
+}
diff --git a/profiles/audio/media.h b/profiles/audio/media.h
index 1de84a8ff..0eeb5746a 100644
--- a/profiles/audio/media.h
+++ b/profiles/audio/media.h
@@ -22,5 +22,6 @@ const char *media_endpoint_get_uuid(struct media_endpoint *endpoint);
uint8_t media_endpoint_get_codec(struct media_endpoint *endpoint);
struct btd_adapter *media_endpoint_get_btd_adapter(
struct media_endpoint *endpoint);
-
+bool media_endpoint_is_broadcast(
+ struct media_endpoint *endpoint);
int8_t media_player_get_device_volume(struct btd_device *device);
--
2.34.1