@@ -4,6 +4,7 @@
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2022 Intel Corporation.
+ * Copyright 2023 NXP
*
*/
@@ -119,10 +120,52 @@
#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) \
+{ \
+ .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) \
+{ \
+ .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;
@@ -141,7 +184,9 @@ struct test_data {
};
struct iso_client_data {
- struct bt_iso_qos qos;
+ struct bt_iso_unicast_qos unicast_qos;
+ struct bt_iso_bcast_sink_qos sink_qos;
+ struct bt_iso_bcast_source_qos source_qos;
int expect_err;
const struct iovec *send;
const struct iovec *recv;
@@ -369,182 +414,182 @@ static void test_data_free(void *test_data)
test_iso_full(name, data, setup, func, 1, reason)
static const struct iso_client_data connect_8_1_1 = {
- .qos = QOS_8_1_1,
+ .unicast_qos = QOS_8_1_1,
.expect_err = 0
};
static const struct iso_client_data connect_8_2_1 = {
- .qos = QOS_8_2_1,
+ .unicast_qos = QOS_8_2_1,
.expect_err = 0
};
static const struct iso_client_data connect_16_1_1 = {
- .qos = QOS_16_1_1,
+ .unicast_qos = QOS_16_1_1,
.expect_err = 0
};
static const struct iso_client_data connect_16_2_1 = {
- .qos = QOS_16_2_1,
+ .unicast_qos = QOS_16_2_1,
.expect_err = 0
};
static const struct iso_client_data connect_1_16_2_1 = {
- .qos = QOS_1_16_2_1,
+ .unicast_qos = QOS_1_16_2_1,
.expect_err = 0
};
static const struct iso_client_data connect_1_1_16_2_1 = {
- .qos = QOS_1_1_16_2_1,
+ .unicast_qos = QOS_1_1_16_2_1,
.expect_err = 0
};
static const struct iso_client_data connect_24_1_1 = {
- .qos = QOS_24_1_1,
+ .unicast_qos = QOS_24_1_1,
.expect_err = 0
};
static const struct iso_client_data connect_24_2_1 = {
- .qos = QOS_24_2_1,
+ .unicast_qos = QOS_24_2_1,
.expect_err = 0
};
static const struct iso_client_data connect_32_1_1 = {
- .qos = QOS_32_1_1,
+ .unicast_qos = QOS_32_1_1,
.expect_err = 0
};
static const struct iso_client_data connect_32_2_1 = {
- .qos = QOS_32_2_1,
+ .unicast_qos = QOS_32_2_1,
.expect_err = 0
};
static const struct iso_client_data connect_44_1_1 = {
- .qos = QOS_44_1_1,
+ .unicast_qos = QOS_44_1_1,
.expect_err = 0
};
static const struct iso_client_data connect_44_2_1 = {
- .qos = QOS_44_2_1,
+ .unicast_qos = QOS_44_2_1,
.expect_err = 0
};
static const struct iso_client_data connect_48_1_1 = {
- .qos = QOS_48_1_1,
+ .unicast_qos = QOS_48_1_1,
.expect_err = 0
};
static const struct iso_client_data connect_48_2_1 = {
- .qos = QOS_48_2_1,
+ .unicast_qos = QOS_48_2_1,
.expect_err = 0
};
static const struct iso_client_data connect_48_3_1 = {
- .qos = QOS_48_3_1,
+ .unicast_qos = QOS_48_3_1,
.expect_err = 0
};
static const struct iso_client_data connect_48_4_1 = {
- .qos = QOS_48_4_1,
+ .unicast_qos = QOS_48_4_1,
.expect_err = 0
};
static const struct iso_client_data connect_48_5_1 = {
- .qos = QOS_48_5_1,
+ .unicast_qos = QOS_48_5_1,
.expect_err = 0
};
static const struct iso_client_data connect_48_6_1 = {
- .qos = QOS_48_6_1,
+ .unicast_qos = QOS_48_6_1,
.expect_err = 0
};
static const struct iso_client_data connect_8_1_2 = {
- .qos = QOS_8_1_2,
+ .unicast_qos = QOS_8_1_2,
.expect_err = 0
};
static const struct iso_client_data connect_8_2_2 = {
- .qos = QOS_8_2_2,
+ .unicast_qos = QOS_8_2_2,
.expect_err = 0
};
static const struct iso_client_data connect_16_1_2 = {
- .qos = QOS_16_1_2,
+ .unicast_qos = QOS_16_1_2,
.expect_err = 0
};
static const struct iso_client_data connect_16_2_2 = {
- .qos = QOS_16_2_2,
+ .unicast_qos = QOS_16_2_2,
.expect_err = 0
};
static const struct iso_client_data connect_24_1_2 = {
- .qos = QOS_24_1_2,
+ .unicast_qos = QOS_24_1_2,
.expect_err = 0
};
static const struct iso_client_data connect_24_2_2 = {
- .qos = QOS_24_2_2,
+ .unicast_qos = QOS_24_2_2,
.expect_err = 0
};
static const struct iso_client_data connect_32_1_2 = {
- .qos = QOS_32_1_2,
+ .unicast_qos = QOS_32_1_2,
.expect_err = 0
};
static const struct iso_client_data connect_32_2_2 = {
- .qos = QOS_32_2_2,
+ .unicast_qos = QOS_32_2_2,
.expect_err = 0
};
static const struct iso_client_data connect_44_1_2 = {
- .qos = QOS_44_1_2,
+ .unicast_qos = QOS_44_1_2,
.expect_err = 0
};
static const struct iso_client_data connect_44_2_2 = {
- .qos = QOS_44_2_2,
+ .unicast_qos = QOS_44_2_2,
.expect_err = 0
};
static const struct iso_client_data connect_48_1_2 = {
- .qos = QOS_48_1_2,
+ .unicast_qos = QOS_48_1_2,
.expect_err = 0
};
static const struct iso_client_data connect_48_2_2 = {
- .qos = QOS_48_2_2,
+ .unicast_qos = QOS_48_2_2,
.expect_err = 0
};
static const struct iso_client_data connect_48_3_2 = {
- .qos = QOS_48_3_2,
+ .unicast_qos = QOS_48_3_2,
.expect_err = 0
};
static const struct iso_client_data connect_48_4_2 = {
- .qos = QOS_48_4_2,
+ .unicast_qos = QOS_48_4_2,
.expect_err = 0
};
static const struct iso_client_data connect_48_5_2 = {
- .qos = QOS_48_5_2,
+ .unicast_qos = QOS_48_5_2,
.expect_err = 0
};
static const struct iso_client_data connect_48_6_2 = {
- .qos = QOS_48_6_2,
+ .unicast_qos = QOS_48_6_2,
.expect_err = 0
};
static const struct iso_client_data connect_invalid = {
- .qos = QOS(0, 0, 0, 0, 0),
+ .unicast_qos = QOS(0, 0, 0, 0, 0),
.expect_err = -EINVAL
};
static const struct iso_client_data connect_reject = {
- .qos = QOS_16_1_2,
+ .unicast_qos = QOS_16_1_2,
.expect_err = -ENOSYS
};
@@ -561,20 +606,20 @@ static const struct iovec send_48_2_1 = {
};
static const struct iso_client_data connect_16_2_1_send = {
- .qos = QOS_16_2_1,
+ .unicast_qos = QOS_16_2_1,
.expect_err = 0,
.send = &send_16_2_1,
};
static const struct iso_client_data listen_16_2_1_recv = {
- .qos = QOS_16_2_1,
+ .unicast_qos = QOS_16_2_1,
.expect_err = 0,
.recv = &send_16_2_1,
.server = true,
};
static const struct iso_client_data listen_16_2_1_recv_ts = {
- .qos = QOS_16_2_1,
+ .unicast_qos = QOS_16_2_1,
.expect_err = 0,
.recv = &send_16_2_1,
.server = true,
@@ -582,27 +627,27 @@ static const struct iso_client_data listen_16_2_1_recv_ts = {
};
static const struct iso_client_data defer_16_2_1 = {
- .qos = QOS_16_2_1,
+ .unicast_qos = QOS_16_2_1,
.expect_err = 0,
.defer = true,
};
static const struct iso_client_data connect_16_2_1_defer_send = {
- .qos = QOS_16_2_1,
+ .unicast_qos = QOS_16_2_1,
.expect_err = 0,
.send = &send_16_2_1,
.defer = true,
};
static const struct iso_client_data connect_48_2_1_defer_send = {
- .qos = QOS_48_2_1,
+ .unicast_qos = QOS_48_2_1,
.expect_err = 0,
.send = &send_16_2_1,
.defer = true,
};
static const struct iso_client_data listen_16_2_1_defer_recv = {
- .qos = QOS_16_2_1,
+ .unicast_qos = QOS_16_2_1,
.expect_err = 0,
.recv = &send_16_2_1,
.server = true,
@@ -610,7 +655,7 @@ static const struct iso_client_data listen_16_2_1_defer_recv = {
};
static const struct iso_client_data listen_48_2_1_defer_recv = {
- .qos = QOS_48_2_1,
+ .unicast_qos = QOS_48_2_1,
.expect_err = 0,
.recv = &send_48_2_1,
.server = true,
@@ -618,7 +663,7 @@ static const struct iso_client_data listen_48_2_1_defer_recv = {
};
static const struct iso_client_data listen_16_2_1_defer_reject = {
- .qos = QOS_16_2_1,
+ .unicast_qos = QOS_16_2_1,
.expect_err = -1,
.recv = &send_16_2_1,
.server = true,
@@ -626,50 +671,51 @@ static const struct iso_client_data listen_16_2_1_defer_reject = {
};
static const struct iso_client_data connect_16_2_1_send_recv = {
- .qos = QOS_16_2_1,
+ .unicast_qos = QOS_16_2_1,
.expect_err = 0,
.send = &send_16_2_1,
.recv = &send_16_2_1,
};
static const struct iso_client_data disconnect_16_2_1 = {
- .qos = QOS_16_2_1,
+ .unicast_qos = QOS_16_2_1,
.expect_err = 0,
.disconnect = true,
};
static const struct iso_client_data reconnect_16_2_1 = {
- .qos = QOS_16_2_1,
+ .unicast_qos = QOS_16_2_1,
.expect_err = 0,
.disconnect = true,
};
static const struct iso_client_data bcast_16_2_1_send = {
- .qos = QOS_OUT_16_2_1,
+ .source_qos = QOS_OUT_16_2_1,
.expect_err = 0,
.send = &send_16_2_1,
.bcast = true,
};
static const struct iso_client_data bcast_1_16_2_1_send = {
- .qos = QOS_OUT_1_16_2_1,
+ .source_qos = QOS_OUT_1_16_2_1,
.expect_err = 0,
.send = &send_16_2_1,
.bcast = true,
};
static const struct iso_client_data bcast_1_1_16_2_1_send = {
- .qos = QOS_OUT_1_1_16_2_1,
+ .source_qos = QOS_OUT_1_1_16_2_1,
.expect_err = 0,
.send = &send_16_2_1,
.bcast = true,
};
static const struct iso_client_data bcast_16_2_1_recv = {
- .qos = QOS_IN_16_2_1,
+ .sink_qos = QOS_IN_16_2_1,
.expect_err = 0,
.recv = &send_16_2_1,
.bcast = true,
+ .server = true,
};
static void client_connectable_complete(uint16_t opcode, uint8_t status,
@@ -854,7 +900,7 @@ static void test_getsockopt(const void *test_data)
{
int sk, err;
socklen_t len;
- struct bt_iso_qos qos;
+ struct bt_iso_unicast_qos qos;
sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_ISO);
if (sk < 0) {
@@ -867,7 +913,7 @@ static void test_getsockopt(const void *test_data)
len = sizeof(qos);
memset(&qos, 0, len);
- err = getsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS, &qos, &len);
+ err = getsockopt(sk, SOL_BLUETOOTH, BT_ISO_UNICAST_QOS, &qos, &len);
if (err < 0) {
tester_warn("Can't get socket option : %s (%d)",
strerror(errno), errno);
@@ -885,7 +931,7 @@ static void test_setsockopt(const void *test_data)
{
int sk, err;
socklen_t len;
- struct bt_iso_qos qos = QOS_16_1_2;
+ struct bt_iso_unicast_qos qos = QOS_16_1_2;
sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_ISO);
if (sk < 0) {
@@ -895,7 +941,8 @@ static void test_setsockopt(const void *test_data)
goto end;
}
- err = setsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS, &qos, sizeof(qos));
+ err = setsockopt(sk, SOL_BLUETOOTH, BT_ISO_UNICAST_QOS,
+ &qos, sizeof(qos));
if (err < 0) {
tester_warn("Can't set socket option : %s (%d)",
strerror(errno), errno);
@@ -906,7 +953,7 @@ static void test_setsockopt(const void *test_data)
len = sizeof(qos);
memset(&qos, 0, len);
- err = getsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS, &qos, &len);
+ err = getsockopt(sk, SOL_BLUETOOTH, BT_ISO_UNICAST_QOS, &qos, &len);
if (err < 0) {
tester_warn("Can't get socket option : %s (%d)",
strerror(errno), errno);
@@ -1004,8 +1051,14 @@ static int connect_iso_sock(struct test_data *data, uint8_t num, int sk)
}
}
- err = setsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS, &isodata->qos,
- sizeof(isodata->qos));
+ if (!isodata->bcast)
+ err = setsockopt(sk, SOL_BLUETOOTH, BT_ISO_UNICAST_QOS,
+ &isodata->unicast_qos, sizeof(isodata->unicast_qos));
+ else {
+ err = setsockopt(sk, SOL_BLUETOOTH, BT_ISO_BCAST_SOURCE_QOS,
+ &isodata->source_qos, sizeof(isodata->source_qos));
+ }
+
if (err < 0) {
tester_warn("Can't set socket BT_ISO_QOS option : %s (%d)",
strerror(errno), errno);
@@ -1080,8 +1133,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_unicast_qos(const struct bt_iso_unicast_qos *qos1,
+ const struct bt_iso_unicast_qos *qos2)
{
if (qos1->cig != BT_ISO_QOS_CIG_UNSET &&
qos2->cig != BT_ISO_QOS_CIG_UNSET &&
@@ -1124,6 +1177,62 @@ static bool check_qos(const struct bt_iso_qos *qos1,
return true;
}
+static bool check_bcast_source_qos(const struct bt_iso_bcast_source_qos *qos1,
+ const struct bt_iso_bcast_source_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)
{
@@ -1249,14 +1358,28 @@ static gboolean iso_connect(GIOChannel *io, GIOCondition cond,
const struct iso_client_data *isodata = data->test_data;
int err, sk_err, sk;
socklen_t len;
- struct bt_iso_qos qos;
+ int optname;
+ bool ret = true;
+
+ union {
+ struct bt_iso_unicast_qos unicast_qos;
+ struct bt_iso_bcast_sink_qos sink_qos;
+ struct bt_iso_bcast_source_qos source_qos;
+ } qos;
sk = g_io_channel_unix_get_fd(io);
+ if (!isodata->bcast)
+ optname = BT_ISO_UNICAST_QOS;
+ else if (isodata->server)
+ optname = BT_ISO_BCAST_SINK_QOS;
+ else
+ optname = BT_ISO_BCAST_SOURCE_QOS;
+
len = sizeof(qos);
memset(&qos, 0, len);
- err = getsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS, &qos, &len);
+ err = getsockopt(sk, SOL_BLUETOOTH, optname, &qos, &len);
if (err < 0) {
tester_warn("Can't get socket option : %s (%d)",
strerror(errno), errno);
@@ -1264,7 +1387,14 @@ static gboolean iso_connect(GIOChannel *io, GIOCondition cond,
return FALSE;
}
- if (!check_qos(&qos, &isodata->qos)) {
+ if (!isodata->bcast)
+ ret = check_unicast_qos(&qos.unicast_qos,
+ &isodata->unicast_qos);
+ else if (!isodata->server)
+ ret = check_bcast_source_qos(&qos.source_qos,
+ &isodata->source_qos);
+
+ if (!ret) {
tester_warn("Unexpected QoS parameter");
tester_test_failed();
return FALSE;
@@ -1579,7 +1709,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->unicast_qos);
bthost_create_cis(host, 257, data->acl_handle);
}
}