@@ -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) {
@@ -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;
@@ -5,6 +5,7 @@
*
* Copyright (C) 2011-2012 Intel Corporation
* Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
+ * Copyright 2023 NXP
*
*
*/
@@ -3178,22 +3179,24 @@ void bthost_set_cig_params(struct bthost *bthost, uint8_t cig_id,
cp = malloc(sizeof(*cp) + sizeof(*cp->cis));
memset(cp, 0, sizeof(*cp) + sizeof(*cp->cis));
cp->cig_id = cig_id;
- put_le24(qos->in.interval ? qos->in.interval : qos->out.interval,
- cp->c_interval);
- put_le24(qos->out.interval ? qos->out.interval : qos->in.interval,
- cp->p_interval);
- cp->c_latency = cpu_to_le16(qos->in.latency ? qos->in.latency :
- qos->out.latency);
- cp->p_latency = cpu_to_le16(qos->out.latency ? qos->out.latency :
- qos->in.latency);
+ put_le24(qos->ucast.in.interval ? qos->ucast.in.interval :
+ qos->ucast.out.interval, cp->c_interval);
+ put_le24(qos->ucast.out.interval ? qos->ucast.out.interval :
+ qos->ucast.in.interval, cp->p_interval);
+ cp->c_latency = cpu_to_le16(qos->ucast.in.latency ?
+ qos->ucast.in.latency : qos->ucast.out.latency);
+ cp->p_latency = cpu_to_le16(qos->ucast.out.latency ?
+ qos->ucast.out.latency : qos->ucast.in.latency);
cp->num_cis = 0x01;
cp->cis[0].cis_id = cis_id;
- cp->cis[0].c_sdu = qos->in.sdu;
- cp->cis[0].p_sdu = qos->out.sdu;
- cp->cis[0].c_phy = qos->in.phy ? qos->in.phy : qos->out.phy;
- cp->cis[0].p_phy = qos->out.phy ? qos->out.phy : qos->in.phy;
- cp->cis[0].c_rtn = qos->in.rtn;
- cp->cis[0].p_rtn = qos->out.rtn;
+ cp->cis[0].c_sdu = qos->ucast.in.sdu;
+ cp->cis[0].p_sdu = qos->ucast.out.sdu;
+ cp->cis[0].c_phy = qos->ucast.in.phy ? qos->ucast.in.phy :
+ qos->ucast.out.phy;
+ cp->cis[0].p_phy = qos->ucast.out.phy ? qos->ucast.out.phy :
+ qos->ucast.in.phy;
+ cp->cis[0].c_rtn = qos->ucast.in.rtn;
+ cp->cis[0].p_rtn = qos->ucast.out.rtn;
send_command(bthost, BT_HCI_CMD_LE_SET_CIG_PARAMS, cp,
sizeof(*cp) + sizeof(*cp->cis));
@@ -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,41 @@ 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_qos {
+ uint8_t big;
+ uint8_t bis;
+ uint8_t sync_interval;
+ uint8_t packing;
+ uint8_t framing;
+ struct bt_iso_io_qos in;
+ struct bt_iso_io_qos out;
+ uint8_t encryption;
+ uint8_t bcode[16];
+ uint8_t options;
+ uint16_t skip;
+ uint16_t sync_timeout;
+ uint8_t sync_cte_type;
+ uint8_t mse;
+ uint16_t timeout;
+};
+
+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;
@@ -4,6 +4,7 @@
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2022 Intel Corporation. All rights reserved.
+ * Copyright 2023 NXP
*
*
*/
@@ -748,10 +749,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)
@@ -773,7 +774,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) {
@@ -992,11 +993,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);
@@ -1191,8 +1192,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,
@@ -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 {
@@ -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,47 @@
#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_BCAST_FULL(_big, _bis, _in, _out) \
+{ \
+ .bcast = { \
+ .big = _big, \
+ .bis = _bis, \
+ .sync_interval = 0x07, \
+ .packing = 0x00, \
+ .framing = 0x00, \
+ .in = _in, \
+ .out = _out, \
+ .encryption = 0x00, \
+ .bcode = {0}, \
+ .options = 0x00, \
+ .skip = 0x0000, \
+ .sync_timeout = 0x4000, \
+ .sync_cte_type = 0x00, \
+ .mse = 0x00, \
+ .timeout = 0x4000, \
+ }, \
+}
+
+#define BCAST_QOS_OUT(_interval, _latency, _sdu, _phy, _rtn) \
+ QOS_BCAST_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_BCAST_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_BCAST_FULL(0x01, 0x01, \
+ {}, QOS_IO(_interval, _latency, _sdu, _phy, _rtn))
+
+#define BCAST_QOS_IN(_interval, _latency, _sdu, _phy, _rtn) \
+ QOS_BCAST_FULL(BT_ISO_QOS_BIG_UNSET, BT_ISO_QOS_BIS_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 +710,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,43 +1121,43 @@ static bool check_io_qos(const struct bt_iso_io_qos *io1,
return true;
}
-static bool check_qos(const struct bt_iso_qos *qos1,
+static bool check_ucast_qos(const struct bt_iso_qos *qos1,
const struct bt_iso_qos *qos2)
{
- if (qos1->cig != BT_ISO_QOS_CIG_UNSET &&
- qos2->cig != BT_ISO_QOS_CIG_UNSET &&
- qos1->cig != qos2->cig) {
+ if (qos1->ucast.cig != BT_ISO_QOS_CIG_UNSET &&
+ qos2->ucast.cig != BT_ISO_QOS_CIG_UNSET &&
+ qos1->ucast.cig != qos2->ucast.cig) {
tester_warn("Unexpected CIG ID: 0x%02x != 0x%02x",
- qos1->cig, qos2->cig);
+ qos1->ucast.cig, qos2->ucast.cig);
return false;
}
- if (qos1->cis != BT_ISO_QOS_CIS_UNSET &&
- qos2->cis != BT_ISO_QOS_CIS_UNSET &&
- qos1->cis != qos2->cis) {
+ if (qos1->ucast.cis != BT_ISO_QOS_CIS_UNSET &&
+ qos2->ucast.cis != BT_ISO_QOS_CIS_UNSET &&
+ qos1->ucast.cis != qos2->ucast.cis) {
tester_warn("Unexpected CIS ID: 0x%02x != 0x%02x",
- qos1->cis, qos2->cis);
+ qos1->ucast.cis, qos2->ucast.cis);
return false;
}
- if (qos1->packing != qos2->packing) {
+ if (qos1->ucast.packing != qos2->ucast.packing) {
tester_warn("Unexpected QoS packing: 0x%02x != 0x%02x",
- qos1->packing, qos2->packing);
+ qos1->ucast.packing, qos2->ucast.packing);
return false;
}
- if (qos1->framing != qos2->framing) {
+ if (qos1->ucast.framing != qos2->ucast.framing) {
tester_warn("Unexpected QoS framing: 0x%02x != 0x%02x",
- qos1->framing, qos2->framing);
+ qos1->ucast.framing, qos2->ucast.framing);
return false;
}
- if (!check_io_qos(&qos1->in, &qos2->in)) {
+ if (!check_io_qos(&qos1->ucast.in, &qos2->ucast.in)) {
tester_warn("Unexpected Input QoS");
return false;
}
- if (!check_io_qos(&qos1->out, &qos2->out)) {
+ if (!check_io_qos(&qos1->ucast.out, &qos2->ucast.out)) {
tester_warn("Unexpected Output QoS");
return false;
}
@@ -1124,6 +1165,104 @@ static bool check_qos(const struct bt_iso_qos *qos1,
return true;
}
+static bool check_bcast_qos(const struct bt_iso_qos *qos1,
+ const struct bt_iso_qos *qos2)
+{
+ if (qos1->bcast.big != BT_ISO_QOS_BIG_UNSET &&
+ qos2->bcast.big != BT_ISO_QOS_BIG_UNSET &&
+ qos1->bcast.big != qos2->bcast.big) {
+ tester_warn("Unexpected BIG ID: 0x%02x != 0x%02x",
+ qos1->bcast.big, qos2->bcast.big);
+ return false;
+ }
+
+ if (qos1->bcast.bis != BT_ISO_QOS_BIS_UNSET &&
+ qos2->bcast.bis != BT_ISO_QOS_BIS_UNSET &&
+ qos1->bcast.bis != qos2->bcast.bis) {
+ tester_warn("Unexpected BIS ID: 0x%02x != 0x%02x",
+ qos1->bcast.bis, qos2->bcast.bis);
+ return false;
+ }
+
+ if (qos1->bcast.sync_interval != qos2->bcast.sync_interval) {
+ tester_warn("Unexpected QoS sync interval: 0x%02x != 0x%02x",
+ qos1->bcast.sync_interval, qos2->bcast.sync_interval);
+ return false;
+ }
+
+ if (qos1->bcast.packing != qos2->bcast.packing) {
+ tester_warn("Unexpected QoS packing: 0x%02x != 0x%02x",
+ qos1->bcast.packing, qos2->bcast.packing);
+ return false;
+ }
+
+ if (qos1->bcast.framing != qos2->bcast.framing) {
+ tester_warn("Unexpected QoS framing: 0x%02x != 0x%02x",
+ qos1->bcast.framing, qos2->bcast.framing);
+ return false;
+ }
+
+ if (!check_io_qos(&qos1->ucast.in, &qos2->ucast.in)) {
+ tester_warn("Unexpected Input QoS");
+ return false;
+ }
+
+ if (!check_io_qos(&qos1->ucast.out, &qos2->ucast.out)) {
+ tester_warn("Unexpected Output QoS");
+ return false;
+ }
+
+ if (qos1->bcast.encryption != qos2->bcast.encryption) {
+ tester_warn("Unexpected QoS encryption: 0x%02x != 0x%02x",
+ qos1->bcast.encryption, qos2->bcast.encryption);
+ return false;
+ }
+
+ if (memcmp(qos1->bcast.bcode, qos2->bcast.bcode,
+ sizeof(qos1->bcast.bcode))) {
+ tester_warn("Unexpected QoS Broadcast Code");
+ return false;
+ }
+
+ if (qos1->bcast.options != qos2->bcast.options) {
+ tester_warn("Unexpected QoS options: 0x%02x != 0x%02x",
+ qos1->bcast.options, qos2->bcast.options);
+ return false;
+ }
+
+ if (qos1->bcast.skip != qos2->bcast.skip) {
+ tester_warn("Unexpected QoS skip: 0x%04x != 0x%04x",
+ qos1->bcast.skip, qos2->bcast.skip);
+ return false;
+ }
+
+ if (qos1->bcast.sync_timeout != qos2->bcast.sync_timeout) {
+ tester_warn("Unexpected QoS sync timeout: 0x%04x != 0x%04x",
+ qos1->bcast.sync_timeout, qos2->bcast.sync_timeout);
+ return false;
+ }
+
+ if (qos1->bcast.sync_cte_type != qos2->bcast.sync_cte_type) {
+ tester_warn("Unexpected QoS sync cte type: 0x%02x != 0x%02x",
+ qos1->bcast.sync_cte_type, qos2->bcast.sync_cte_type);
+ return false;
+ }
+
+ if (qos1->bcast.mse != qos2->bcast.mse) {
+ tester_warn("Unexpected QoS MSE: 0x%02x != 0x%02x",
+ qos1->bcast.mse, qos2->bcast.mse);
+ return false;
+ }
+
+ if (qos1->bcast.timeout != qos2->bcast.timeout) {
+ tester_warn("Unexpected QoS MSE: 0x%04x != 0x%04x",
+ qos1->bcast.timeout, qos2->bcast.timeout);
+ return false;
+ }
+
+ return true;
+}
+
static gboolean iso_recv_data(GIOChannel *io, GIOCondition cond,
gpointer user_data)
{
@@ -1250,6 +1389,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 +1404,12 @@ static gboolean iso_connect(GIOChannel *io, GIOCondition cond,
return FALSE;
}
- if (!check_qos(&qos, &isodata->qos)) {
+ if (!isodata->bcast)
+ ret = check_ucast_qos(&qos, &isodata->qos);
+ else if (!isodata->server)
+ ret = check_bcast_qos(&qos, &isodata->qos);
+
+ if (!ret) {
tester_warn("Unexpected QoS parameter");
tester_test_failed();
return FALSE;
@@ -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,63 @@ 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_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.big, qos.bcast.bis,
+ qos.bcast.packing, qos.bcast.framing);
+
+ syslog(LOG_INFO, "Input QoS [Interval %u us Latency %u "
+ "ms SDU %u PHY 0x%02x RTN %u]", qos.bcast.in.interval,
+ qos.bcast.in.latency, qos.bcast.in.sdu,
+ qos.bcast.in.phy, qos.bcast.in.rtn);
+
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.out.interval,
+ qos.bcast.out.latency, qos.bcast.out.sdu,
+ qos.bcast.out.phy, qos.bcast.out.rtn);
+}
+
+static void convert_ucast_qos_to_bcast(struct bt_iso_qos *qos)
+{
+ iso_qos->bcast.in.phy = 0x00;
+ iso_qos->bcast.in.sdu = 0;
+ qos->bcast.encryption = 0x00;
+ memset(qos->bcast.bcode, 0, sizeof(qos->bcast.bcode));
+ qos->bcast.options = 0x00;
+ qos->bcast.skip = 0x0000;
+ qos->bcast.sync_timeout = 0x4000;
+ qos->bcast.sync_cte_type = 0x00;
+ qos->bcast.mse = 0x00;
+ qos->bcast.timeout = 0x4000;
}
static int do_connect(char *peer)
@@ -301,9 +344,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")) {
+ convert_ucast_qos_to_bcast(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 +385,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_qos(sk);
+ else
+ print_ucast_qos(sk);
return sk;
@@ -441,7 +491,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_qos(nsk);
+ else
+ print_ucast_qos(nsk);
/* Handle deferred setup */
if (defer_setup) {
@@ -648,7 +701,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 +715,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 +739,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 +749,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 +782,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.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 +805,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 +827,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 +885,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 +1118,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 +1173,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 +1189,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);