[PATCH BlueZ v2 1/1] Split bt_iso_qos into dedicated structures

Iulia Tanasescu
2023-03-28T07:26:55Z

Split bt_iso_qos into dedicated unicast and broadcast
structures and add additional broadcast parameters.

---
btio/btio.c | 7 +-
client/player.c | 7 +-
emulator/bthost.c | 3 +-
emulator/bthost.h | 3 +-
lib/bluetooth.h | 59 +++++++++++----
profiles/audio/bap.c | 19 ++---
tools/btiotest.c | 17 +++--
tools/iso-tester.c | 144 +++++++++++++++++++++++++++++++----
tools/isotest.c | 177 +++++++++++++++++++++++++++++++------------
9 files changed, 336 insertions(+), 100 deletions(-)

diff --git a/btio/btio.c b/btio/btio.c
index 1ad42728d..6f6d76dc8 100644
--- a/btio/btio.c
+++ b/btio/btio.c
@@ -5,6 +5,7 @@
*
* Copyright (C) 2009-2010 Marcel Holtmann <marcel@holtmann.org>
* Copyright (C) 2009-2010 Nokia Corporation
+ * Copyright 2023 NXP
*
*
*/
@@ -1608,13 +1609,13 @@ static gboolean iso_get(int sock, GError **err, BtIOOption opt1, va_list args)
*(va_arg(args, uint8_t *)) = dst.iso_bdaddr_type;
break;
case BT_IO_OPT_MTU:
- *(va_arg(args, uint16_t *)) = qos.out.sdu;
+ *(va_arg(args, uint16_t *)) = qos.ucast.out.sdu;
break;
case BT_IO_OPT_IMTU:
- *(va_arg(args, uint16_t *)) = qos.in.sdu;
+ *(va_arg(args, uint16_t *)) = qos.ucast.in.sdu;
break;
case BT_IO_OPT_OMTU:
- *(va_arg(args, uint16_t *)) = qos.out.sdu;
+ *(va_arg(args, uint16_t *)) = qos.ucast.out.sdu;
break;
case BT_IO_OPT_PHY:
if (get_phy(sock, &phy) < 0) {
diff --git a/client/player.c b/client/player.c
index 63e11db09..5572cc566 100644
--- a/client/player.c
+++ b/client/player.c
@@ -4,6 +4,7 @@
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2020 Intel Corporation. All rights reserved.
+ * Copyright 2023 NXP
*
*
*/
@@ -3534,7 +3535,7 @@ static bool transport_timer_read(struct io *io, void *user_data)
}

/* num of packets = latency (ms) / interval (us) */
- num = (qos.out.latency * 1000 / qos.out.interval);
+ num = (qos.ucast.out.latency * 1000 / qos.ucast.out.interval);

ret = transport_send_seq(transport, transport->fd, num);
if (ret < 0) {
@@ -3570,8 +3571,8 @@ static int transport_send(struct transport *transport, int fd,
return -errno;

memset(&ts, 0, sizeof(ts));
- ts.it_value.tv_nsec = qos->out.latency * 1000000;
- ts.it_interval.tv_nsec = qos->out.latency * 1000000;
+ ts.it_value.tv_nsec = qos->ucast.out.latency * 1000000;
+ ts.it_interval.tv_nsec = qos->ucast.out.latency * 1000000;

if (timerfd_settime(timer_fd, TFD_TIMER_ABSTIME, &ts, NULL) < 0)
return -errno;
diff --git a/emulator/bthost.c b/emulator/bthost.c
index 4671fe17d..1b6847b81 100644
--- a/emulator/bthost.c
+++ b/emulator/bthost.c
@@ -5,6 +5,7 @@
*
* Copyright (C) 2011-2012 Intel Corporation
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
+ * Copyright 2023 NXP
*
*
*/
@@ -3171,7 +3172,7 @@ bool bthost_search_ext_adv_addr(struct bthost *bthost, const uint8_t *addr)
}

void bthost_set_cig_params(struct bthost *bthost, uint8_t cig_id,
- uint8_t cis_id, const struct bt_iso_qos *qos)
+ uint8_t cis_id, const struct bt_iso_ucast_qos *qos)
{
struct bt_hci_cmd_le_set_cig_params *cp;

diff --git a/emulator/bthost.h b/emulator/bthost.h
index 92182687f..779ca7d06 100644
--- a/emulator/bthost.h
+++ b/emulator/bthost.h
@@ -5,6 +5,7 @@
*
* Copyright (C) 2011-2012 Intel Corporation
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
+ * Copyright 2023 NXP
*
*
*/
@@ -106,7 +107,7 @@ void bthost_create_big(struct bthost *bthost, uint8_t num_bis);
bool bthost_search_ext_adv_addr(struct bthost *bthost, const uint8_t *addr);

void bthost_set_cig_params(struct bthost *bthost, uint8_t cig_id,
- uint8_t cis_id, const struct bt_iso_qos *qos);
+ uint8_t cis_id, const struct bt_iso_ucast_qos *qos);
void bthost_create_cis(struct bthost *bthost, uint16_t cis_handle,
uint16_t acl_handle);

diff --git a/lib/bluetooth.h b/lib/bluetooth.h
index af5fbcfbc..660a529d8 100644
--- a/lib/bluetooth.h
+++ b/lib/bluetooth.h
@@ -6,6 +6,7 @@
* Copyright (C) 2000-2001 Qualcomm Incorporated
* Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
* Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
+ * Copyright 2023 NXP
*
*
*/
@@ -146,6 +147,9 @@ struct bt_voice {
#define BT_ISO_QOS_CIG_UNSET 0xff
#define BT_ISO_QOS_CIS_UNSET 0xff

+#define BT_ISO_QOS_BIG_UNSET 0xff
+#define BT_ISO_QOS_BIS_UNSET 0xff
+
struct bt_iso_io_qos {
uint32_t interval;
uint16_t latency;
@@ -154,25 +158,54 @@ struct bt_iso_io_qos {
uint8_t rtn;
};

-struct bt_iso_qos {
- union {
- uint8_t cig;
- uint8_t big;
- };
- union {
- uint8_t cis;
- uint8_t bis;
- };
- union {
- uint8_t sca;
- uint8_t sync_interval;
- };
+struct bt_iso_ucast_qos {
+ uint8_t cig;
+ uint8_t cis;
+ uint8_t sca;
uint8_t packing;
uint8_t framing;
struct bt_iso_io_qos in;
struct bt_iso_io_qos out;
};

+struct bt_iso_bcast_src_qos {
+ uint8_t sync_interval;
+ uint8_t big;
+ uint8_t bis;
+ uint8_t packing;
+ uint8_t framing;
+ uint8_t encryption;
+ uint8_t bcode[16];
+ struct bt_iso_io_qos out;
+};
+
+struct bt_iso_bcast_snk_qos {
+ uint8_t options;
+ uint16_t skip;
+ uint16_t sync_timeout;
+ uint8_t sync_cte_type;
+ uint8_t big;
+ uint8_t encryption;
+ uint8_t bcode[16];
+ uint8_t mse;
+ uint16_t timeout;
+ struct bt_iso_io_qos in;
+};
+
+struct bt_iso_bcast_qos {
+ union {
+ struct bt_iso_bcast_src_qos bsrc;
+ struct bt_iso_bcast_snk_qos bsnk;
+ };
+};
+
+struct bt_iso_qos {
+ union {
+ struct bt_iso_ucast_qos ucast;
+ struct bt_iso_bcast_qos bcast;
+ };
+};
+
#define BT_CODEC 19
struct bt_codec {
uint8_t id;
diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c
index dfdf87255..afc87d85f 100644
--- a/profiles/audio/bap.c
+++ b/profiles/audio/bap.c
@@ -4,6 +4,7 @@
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2022 Intel Corporation. All rights reserved.
+ * Copyright 2023 NXP
*
*
*/
@@ -746,10 +747,10 @@ static bool match_stream_qos(const void *data, const void *user_data)

qos = bt_bap_stream_get_qos((void *)stream);

- if (iso_qos->cig != qos->cig_id)
+ if (iso_qos->ucast.cig != qos->cig_id)
return false;

- return iso_qos->cis == qos->cis_id;
+ return iso_qos->ucast.cis == qos->cis_id;
}

static void iso_confirm_cb(GIOChannel *io, void *user_data)
@@ -771,7 +772,7 @@ static void iso_confirm_cb(GIOChannel *io, void *user_data)
}

DBG("ISO: incoming connect from %s (CIG 0x%02x CIS 0x%02x)",
- address, qos.cig, qos.cis);
+ address, qos.ucast.cig, qos.ucast.cis);

stream = queue_remove_if(data->streams, match_stream_qos, &qos);
if (!stream) {
@@ -990,11 +991,11 @@ static void bap_create_io(struct bap_data *data, struct bap_ep *ep,
}

memset(&iso_qos, 0, sizeof(iso_qos));
- iso_qos.cig = qos[0] ? qos[0]->cig_id : qos[1]->cig_id;
- iso_qos.cis = qos[0] ? qos[0]->cis_id : qos[1]->cis_id;
+ 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;

- bap_iso_qos(qos[0], &iso_qos.in);
- bap_iso_qos(qos[1], &iso_qos.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);
@@ -1189,8 +1190,8 @@ static void bap_connecting(struct bt_bap_stream *stream, bool state, int fd,
return;
}

- ep->qos.cig_id = qos.cig;
- ep->qos.cis_id = qos.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,
diff --git a/tools/btiotest.c b/tools/btiotest.c
index 193e1395b..75af90543 100644
--- a/tools/btiotest.c
+++ b/tools/btiotest.c
@@ -5,6 +5,7 @@
*
* Copyright (C) 2009-2010 Marcel Holtmann <marcel@holtmann.org>
* Copyright (C) 2009-2010 Nokia Corporation
+ * Copyright 2023 NXP
*
*
*/
@@ -39,13 +40,15 @@ static int opt_update_sec = 0;
}

struct bt_iso_qos qos = {
- .cig = BT_ISO_QOS_CIG_UNSET,
- .cis = BT_ISO_QOS_CIG_UNSET,
- .sca = 0x07,
- .packing = 0x00,
- .framing = 0x00,
- .in = DEFAULT_IO_QOS,
- .out = DEFAULT_IO_QOS,
+ .ucast = {
+ .cig = BT_ISO_QOS_CIG_UNSET,
+ .cis = BT_ISO_QOS_CIG_UNSET,
+ .sca = 0x07,
+ .packing = 0x00,
+ .framing = 0x00,
+ .in = DEFAULT_IO_QOS,
+ .out = DEFAULT_IO_QOS,
+ },
};

struct io_data {
diff --git a/tools/iso-tester.c b/tools/iso-tester.c
index e4582573a..2dd90c14e 100644
--- a/tools/iso-tester.c
+++ b/tools/iso-tester.c
@@ -4,6 +4,7 @@
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2022 Intel Corporation.
+ * Copyright 2023 NXP
*
*/

@@ -42,13 +43,15 @@

#define QOS_FULL(_cig, _cis, _in, _out) \
{ \
- .cig = _cig, \
- .cis = _cis, \
- .sca = 0x07, \
- .packing = 0x00, \
- .framing = 0x00, \
- .in = _in, \
- .out = _out, \
+ .ucast = { \
+ .cig = _cig, \
+ .cis = _cis, \
+ .sca = 0x07, \
+ .packing = 0x00, \
+ .framing = 0x00, \
+ .in = _in, \
+ .out = _out, \
+ },\
}

#define QOS(_interval, _latency, _sdu, _phy, _rtn) \
@@ -119,10 +122,56 @@
#define QOS_48_5_2 QOS_OUT(7500, 75, 117, 0x02, 13)
#define QOS_48_6_2 QOS_OUT(10000, 100, 155, 0x02, 13)

-#define QOS_OUT_16_2_1 QOS_OUT(10000, 10, 40, 0x02, 2)
-#define QOS_OUT_1_16_2_1 QOS_OUT_1(10000, 10, 40, 0x02, 2)
-#define QOS_OUT_1_1_16_2_1 QOS_OUT_1_1(10000, 10, 40, 0x02, 2)
-#define QOS_IN_16_2_1 QOS_IN(10000, 10, 40, 0x02, 2)
+#define QOS_SINK_FULL(_big, _in) \
+{ \
+ .bcast.bsnk = { \
+ .options = 0x00, \
+ .skip = 0x0000, \
+ .sync_timeout = 0x4000, \
+ .sync_cte_type = 0x00, \
+ .big = _big, \
+ .encryption = 0x00, \
+ .bcode = {0}, \
+ .mse = 0x00, \
+ .timeout = 0x4000, \
+ .in = _in, \
+ }, \
+}
+
+#define QOS_SOURCE_FULL(_big, _bis, _out) \
+{ \
+ .bcast.bsrc = { \
+ .sync_interval = 0x07, \
+ .big = _big, \
+ .bis = _bis, \
+ .packing = 0x00, \
+ .framing = 0x00, \
+ .encryption = 0x00, \
+ .bcode = {0}, \
+ .out = _out, \
+ }, \
+}
+
+#define BCAST_QOS_OUT(_interval, _latency, _sdu, _phy, _rtn) \
+ QOS_SOURCE_FULL(BT_ISO_QOS_BIG_UNSET, BT_ISO_QOS_BIS_UNSET, \
+ QOS_IO(_interval, _latency, _sdu, _phy, _rtn))
+
+#define BCAST_QOS_OUT_1(_interval, _latency, _sdu, _phy, _rtn) \
+ QOS_SOURCE_FULL(0x01, BT_ISO_QOS_BIS_UNSET, \
+ QOS_IO(_interval, _latency, _sdu, _phy, _rtn))
+
+#define BCAST_QOS_OUT_1_1(_interval, _latency, _sdu, _phy, _rtn) \
+ QOS_SOURCE_FULL(0x01, 0x01, \
+ QOS_IO(_interval, _latency, _sdu, _phy, _rtn))
+
+#define BCAST_QOS_IN(_interval, _latency, _sdu, _phy, _rtn) \
+ QOS_SINK_FULL(BT_ISO_QOS_BIG_UNSET, \
+ QOS_IO(_interval, _latency, _sdu, _phy, _rtn))
+
+#define QOS_OUT_16_2_1 BCAST_QOS_OUT(10000, 10, 40, 0x02, 2)
+#define QOS_OUT_1_16_2_1 BCAST_QOS_OUT_1(10000, 10, 40, 0x02, 2)
+#define QOS_OUT_1_1_16_2_1 BCAST_QOS_OUT_1_1(10000, 10, 40, 0x02, 2)
+#define QOS_IN_16_2_1 BCAST_QOS_IN(10000, 10, 40, 0x02, 2)

struct test_data {
const void *test_data;
@@ -670,6 +719,7 @@ static const struct iso_client_data bcast_16_2_1_recv = {
.expect_err = 0,
.recv = &send_16_2_1,
.bcast = true,
+ .server = true,
};

static void client_connectable_complete(uint16_t opcode, uint8_t status,
@@ -1080,8 +1130,8 @@ static bool check_io_qos(const struct bt_iso_io_qos *io1,
return true;
}

-static bool check_qos(const struct bt_iso_qos *qos1,
- const struct bt_iso_qos *qos2)
+static bool check_ucast_qos(const struct bt_iso_ucast_qos *qos1,
+ const struct bt_iso_ucast_qos *qos2)
{
if (qos1->cig != BT_ISO_QOS_CIG_UNSET &&
qos2->cig != BT_ISO_QOS_CIG_UNSET &&
@@ -1124,6 +1174,63 @@ static bool check_qos(const struct bt_iso_qos *qos1,
return true;
}

+static bool check_bcast_src_qos(const struct bt_iso_bcast_src_qos *qos1,
+ const struct bt_iso_bcast_src_qos *qos2)
+{
+ if (qos1->sync_interval != qos2->sync_interval) {
+ tester_warn("Unexpected QoS sync interval: 0x%02x != 0x%02x",
+ qos1->sync_interval, qos2->sync_interval);
+ return false;
+ }
+
+ if (qos1->big != BT_ISO_QOS_BIG_UNSET &&
+ qos2->big != BT_ISO_QOS_BIG_UNSET &&
+ qos1->big != qos2->big) {
+ tester_warn("Unexpected BIG ID: 0x%02x != 0x%02x",
+ qos1->big, qos2->big);
+ return false;
+ }
+
+ if (qos1->bis != BT_ISO_QOS_BIS_UNSET &&
+ qos2->bis != BT_ISO_QOS_BIS_UNSET &&
+ qos1->bis != qos2->bis) {
+ tester_warn("Unexpected BIS ID: 0x%02x != 0x%02x",
+ qos1->bis, qos2->bis);
+ return false;
+ }
+
+ if (qos1->packing != qos2->packing) {
+ tester_warn("Unexpected QoS packing: 0x%02x != 0x%02x",
+ qos1->packing, qos2->packing);
+ return false;
+ }
+
+ if (qos1->framing != qos2->framing) {
+ tester_warn("Unexpected QoS framing: 0x%02x != 0x%02x",
+ qos1->framing, qos2->framing);
+ return false;
+ }
+
+ if (qos1->encryption != qos2->encryption) {
+ tester_warn("Unexpected QoS encryption: 0x%02x != 0x%02x",
+ qos1->encryption, qos2->encryption);
+ return false;
+ }
+
+
+ if (memcmp(qos1->bcode, qos2->bcode, sizeof(qos1->bcode))) {
+ tester_warn("Unexpected QoS Broadcast Code");
+ return false;
+ }
+
+ if (!check_io_qos(&qos1->out, &qos2->out)) {
+ tester_warn("Unexpected Output QoS");
+ return false;
+ }
+
+ return true;
+}
+
static gboolean iso_recv_data(GIOChannel *io, GIOCondition cond,
gpointer user_data)
{
@@ -1250,6 +1357,7 @@ static gboolean iso_connect(GIOChannel *io, GIOCondition cond,
int err, sk_err, sk;
socklen_t len;
struct bt_iso_qos qos;
+ bool ret = true;

sk = g_io_channel_unix_get_fd(io);

@@ -1264,7 +1372,13 @@ static gboolean iso_connect(GIOChannel *io, GIOCondition cond,
return FALSE;
}

- if (!check_qos(&qos, &isodata->qos)) {
+ if (!isodata->bcast)
+ ret = check_ucast_qos(&qos.ucast, &isodata->qos.ucast);
+ else if (!isodata->server)
+ ret = check_bcast_src_qos(&qos.bcast.bsrc,
+ &isodata->qos.bcast.bsrc);
+
+ if (!ret) {
tester_warn("Unexpected QoS parameter");
tester_test_failed();
return FALSE;
@@ -1579,7 +1693,7 @@ static void setup_listen(struct test_data *data, uint8_t num, GIOFunc func)
client = hciemu_get_client(data->hciemu, 0);
host = hciemu_client_host(client);

- bthost_set_cig_params(host, 0x01, 0x01, &isodata->qos);
+ bthost_set_cig_params(host, 0x01, 0x01, &isodata->qos.ucast);
bthost_create_cis(host, 257, data->acl_handle);
}
}
diff --git a/tools/isotest.c b/tools/isotest.c
index 2b5f164de..f00f03249 100644
--- a/tools/isotest.c
+++ b/tools/isotest.c
@@ -4,6 +4,7 @@
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2022 Intel Corporation.
+ * Copyright 2023 NXP
*
*/

@@ -239,7 +240,7 @@ fail:
return err < 0 ? err : 0;
}

-static void print_qos(int sk, struct sockaddr_iso *addr)
+static void print_ucast_qos(int sk)
{
struct bt_iso_qos qos;
socklen_t len;
@@ -254,21 +255,83 @@ static void print_qos(int sk, struct sockaddr_iso *addr)
return;
}

- if (!bacmp(&addr->iso_bdaddr, BDADDR_ANY)) {
- syslog(LOG_INFO, "QoS BIG 0x%02x BIS 0x%02x Packing 0x%02x "
- "Framing 0x%02x]", qos.big, qos.bis, qos.packing,
- qos.framing);
- } else {
- syslog(LOG_INFO, "QoS CIG 0x%02x CIS 0x%02x Packing 0x%02x "
- "Framing 0x%02x]", qos.cig, qos.cis, qos.packing,
- qos.framing);
- syslog(LOG_INFO, "Input QoS [Interval %u us Latency %u "
- "ms SDU %u PHY 0x%02x RTN %u]", qos.in.interval,
- qos.in.latency, qos.in.sdu, qos.in.phy, qos.in.rtn);
+ syslog(LOG_INFO, "QoS CIG 0x%02x CIS 0x%02x Packing 0x%02x "
+ "Framing 0x%02x]", qos.ucast.cig, qos.ucast.cis,
+ qos.ucast.packing, qos.ucast.framing);
+
+ syslog(LOG_INFO, "Input QoS [Interval %u us Latency %u "
+ "ms SDU %u PHY 0x%02x RTN %u]", qos.ucast.in.interval,
+ qos.ucast.in.latency, qos.ucast.in.sdu, qos.ucast.in.phy,
+ qos.ucast.in.rtn);
+
+ syslog(LOG_INFO, "Output QoS [Interval %u us Latency %u "
+ "ms SDU %u PHY 0x%02x RTN %u]", qos.ucast.out.interval,
+ qos.ucast.out.latency, qos.ucast.out.sdu, qos.ucast.out.phy,
+ qos.ucast.out.rtn);
+}
+
+static void print_bcast_src_qos(int sk)
+{
+ struct bt_iso_qos qos;
+ socklen_t len;
+
+ /* Read Out QOS */
+ memset(&qos, 0, sizeof(qos));
+ len = sizeof(qos);
+
+ if (getsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS, &qos, &len) < 0) {
+ syslog(LOG_ERR, "Can't get QoS socket option: %s (%d)",
+ strerror(errno), errno);
+ return;
}
+
+ syslog(LOG_INFO, "QoS BIG 0x%02x BIS 0x%02x Packing 0x%02x "
+ "Framing 0x%02x]", qos.bcast.bsrc.big, qos.bcast.bsrc.bis,
+ qos.bcast.bsrc.packing, qos.bcast.bsrc.framing);
+
syslog(LOG_INFO, "Output QoS [Interval %u us Latency %u "
- "ms SDU %u PHY 0x%02x RTN %u]", qos.out.interval,
- qos.out.latency, qos.out.sdu, qos.out.phy, qos.out.rtn);
+ "ms SDU %u PHY 0x%02x RTN %u]", qos.bcast.bsrc.out.interval,
+ qos.bcast.bsrc.out.latency, qos.bcast.bsrc.out.sdu,
+ qos.bcast.bsrc.out.phy, qos.bcast.bsrc.out.rtn);
+}
+
+static void print_bcast_snk_qos(int sk)
+{
+ struct bt_iso_qos qos;
+ socklen_t len;
+
+ /* Read Out QOS */
+ memset(&qos, 0, sizeof(qos));
+ len = sizeof(qos);
+
+ if (getsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS, &qos, &len) < 0) {
+ syslog(LOG_ERR, "Can't get QoS socket option: %s (%d)",
+ strerror(errno), errno);
+ return;
+ }
+
+ syslog(LOG_INFO, "QoS BIG 0x%02x", qos.bcast.bsnk.big);
+
+ syslog(LOG_INFO, "Input QoS [Interval %u us Latency %u "
+ "ms SDU %u PHY 0x%02x RTN %u]", qos.bcast.bsnk.in.interval,
+ qos.bcast.bsnk.in.latency, qos.bcast.bsnk.in.sdu,
+ qos.bcast.bsnk.in.phy, qos.bcast.bsnk.in.rtn);
+}
+
+static void ucast_qos_to_bcast_src(struct bt_iso_qos *qos)
+{
+ struct bt_iso_qos src_qos;
+
+ memset(&src_qos, 0, sizeof(src_qos));
+
+ src_qos.bcast.bsrc.sync_interval = qos->ucast.sca;
+ src_qos.bcast.bsrc.big = qos->ucast.cig;
+ src_qos.bcast.bsrc.bis = qos->ucast.cis;
+ src_qos.bcast.bsrc.packing = qos->ucast.packing;
+ src_qos.bcast.bsrc.framing = qos->ucast.framing;
+ src_qos.bcast.bsrc.out = qos->ucast.out;
+
+ *qos = src_qos;
}

static int do_connect(char *peer)
@@ -301,9 +364,13 @@ static int do_connect(char *peer)

/* Set QoS if available */
if (iso_qos) {
- if (!inout || !strcmp(peer, "00:00:00:00:00:00")) {
- iso_qos->in.phy = 0x00;
- iso_qos->in.sdu = 0;
+ if (!strcmp(peer, "00:00:00:00:00:00")) {
+ ucast_qos_to_bcast_src(iso_qos);
+ } else {
+ if (!inout) {
+ iso_qos->ucast.in.phy = 0x00;
+ iso_qos->ucast.in.sdu = 0;
+ }
}

if (setsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS, iso_qos,
@@ -338,7 +405,10 @@ static int do_connect(char *peer)

syslog(LOG_INFO, "Connected [%s]", peer);

- print_qos(sk, &addr);
+ if (!strcmp(peer, "00:00:00:00:00:00"))
+ print_bcast_src_qos(sk);
+ else
+ print_ucast_qos(sk);

return sk;

@@ -441,7 +511,10 @@ static void do_listen(char *filename, void (*handler)(int fd, int sk),
ba2str(&addr->iso_bdaddr, ba);
syslog(LOG_INFO, "Connected [%s]", ba);

- print_qos(nsk, addr);
+ if (peer)
+ print_bcast_snk_qos(nsk);
+ else
+ print_ucast_qos(nsk);

/* Handle deferred setup */
if (defer_setup) {
@@ -648,7 +721,7 @@ static int read_file(int fd, ssize_t count, bool rewind)
return len;
}

-static void do_send(int sk, int fd, struct bt_iso_qos *qos, uint32_t num,
+static void do_send(int sk, int fd, struct bt_iso_io_qos *out, uint32_t num,
bool repeat)
{
uint32_t seq;
@@ -662,14 +735,14 @@ static void do_send(int sk, int fd, struct bt_iso_qos *qos, uint32_t num,

for (seq = 0; ; seq++) {
if (fd >= 0) {
- len = read_file(fd, qos->out.sdu, repeat);
+ len = read_file(fd, out->sdu, repeat);
if (len < 0) {
syslog(LOG_ERR, "read failed: %s (%d)",
strerror(-len), -len);
exit(1);
}
} else
- len = qos->out.sdu;
+ len = out->sdu;

len = send(sk, buf, len, 0);
if (len <= 0) {
@@ -686,7 +759,7 @@ static void do_send(int sk, int fd, struct bt_iso_qos *qos, uint32_t num,
seq, len, used / len, used);

if (seq && !((seq + 1) % num))
- send_wait(&t_start, num * qos->out.interval);
+ send_wait(&t_start, num * out->interval);
}
}

@@ -696,6 +769,7 @@ static void send_mode(char *filename, char *peer, int i, bool repeat)
socklen_t len;
int sk, fd = -1;
uint32_t num;
+ struct bt_iso_io_qos *out;

if (filename) {
char altername[PATH_MAX];
@@ -728,16 +802,21 @@ static void send_mode(char *filename, char *peer, int i, bool repeat)
syslog(LOG_INFO, "Sending ...");

/* Read QoS */
+ if (!strcmp(peer, "00:00:00:00:00:00"))
+ out = &qos.bcast.bsrc.out;
+ else
+ out = &qos.ucast.out;
+
memset(&qos, 0, sizeof(qos));
len = sizeof(qos);
if (getsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS, &qos, &len) < 0) {
syslog(LOG_ERR, "Can't get Output QoS socket option: %s (%d)",
strerror(errno), errno);
- qos.out.sdu = ISO_DEFAULT_MTU;
+ out->sdu = ISO_DEFAULT_MTU;
}

/* num of packets = latency (ms) / interval (us) */
- num = (qos.out.latency * 1000 / qos.out.interval);
+ num = (out->latency * 1000 / out->interval);

syslog(LOG_INFO, "Number of packets: %d", num);

@@ -746,8 +825,8 @@ static void send_mode(char *filename, char *peer, int i, bool repeat)
* latency:
* jitter buffer = 2 * (SDU * subevents)
*/
- sndbuf = 2 * ((qos.out.latency * 1000 / qos.out.interval) *
- qos.out.sdu);
+ sndbuf = 2 * ((out->latency * 1000 / out->interval) *
+ out->sdu);

len = sizeof(sndbuf);
if (setsockopt(sk, SOL_SOCKET, SO_SNDBUF, &sndbuf, len) < 0) {
@@ -768,10 +847,10 @@ static void send_mode(char *filename, char *peer, int i, bool repeat)
}
}

- for (i = 6; i < qos.out.sdu; i++)
+ for (i = 6; i < out->sdu; i++)
buf[i] = 0x7f;

- do_send(sk, fd, &qos, num, repeat);
+ do_send(sk, fd, out, num, repeat);
}

static void reconnect_mode(char *peer)
@@ -826,12 +905,14 @@ static void multy_connect_mode(char *peer)

#define QOS(_interval, _latency, _sdu, _phy, _rtn) \
{ \
- .cig = BT_ISO_QOS_CIG_UNSET, \
- .cis = BT_ISO_QOS_CIS_UNSET, \
- .sca = 0x07, \
- .packing = 0x00, \
- .framing = 0x00, \
- .out = QOS_IO(_interval, _latency, _sdu, _phy, _rtn), \
+ .ucast = { \
+ .cig = BT_ISO_QOS_CIG_UNSET, \
+ .cis = BT_ISO_QOS_CIS_UNSET, \
+ .sca = 0x07, \
+ .packing = 0x00, \
+ .framing = 0x00, \
+ .out = QOS_IO(_interval, _latency, _sdu, _phy, _rtn), \
+ }, \
}

#define QOS_PRESET(_name, _inout, _interval, _latency, _sdu, _phy, _rtn) \
@@ -1057,43 +1138,43 @@ int main(int argc, char *argv[])

case 'M':
if (optarg)
- iso_qos->out.sdu = atoi(optarg);
+ iso_qos->ucast.out.sdu = atoi(optarg);
break;

case 'S':
if (optarg)
- iso_qos->sca = atoi(optarg);
+ iso_qos->ucast.sca = atoi(optarg);
break;

case 'P':
if (optarg)
- iso_qos->packing = atoi(optarg);
+ iso_qos->ucast.packing = atoi(optarg);
break;

case 'F':
if (optarg)
- iso_qos->framing = atoi(optarg);
+ iso_qos->ucast.framing = atoi(optarg);
break;

case 'I':
if (optarg)
- iso_qos->out.interval = atoi(optarg);
+ iso_qos->ucast.out.interval = atoi(optarg);
break;

case 'L':
if (optarg)
- iso_qos->out.latency = atoi(optarg);
+ iso_qos->ucast.out.latency = atoi(optarg);
break;

case 'Y':
if (optarg)
- iso_qos->out.phy = atoi(optarg);
+ iso_qos->ucast.out.phy = atoi(optarg);
break;

case 'R':
if (optarg)
- iso_qos->out.rtn = atoi(optarg);
+ iso_qos->ucast.out.rtn = atoi(optarg);
break;

case 'B':
@@ -1112,12 +1193,12 @@ int main(int argc, char *argv[])

case 'G':
if (optarg)
- iso_qos->cig = atoi(optarg);
+ iso_qos->ucast.cig = atoi(optarg);
break;

case 'T':
if (optarg)
- iso_qos->cis = atoi(optarg);
+ iso_qos->ucast.cis = atoi(optarg);
break;

/* fall through */
@@ -1128,11 +1209,11 @@ int main(int argc, char *argv[])
}

if (inout) {
- iso_qos->in = iso_qos->out;
+ iso_qos->ucast.in = iso_qos->ucast.out;
} else {
/* Align interval and latency even if is unidirectional */
- iso_qos->in.interval = iso_qos->out.interval;
- iso_qos->in.latency = iso_qos->out.latency;
+ iso_qos->ucast.in.interval = iso_qos->ucast.out.interval;
+ iso_qos->ucast.in.latency = iso_qos->ucast.out.latency;
}

buf = malloc(data_size);
--
2.34.1