@@ -4,6 +4,7 @@
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2022 Intel Corporation.
+ * Copyright 2023 NXP
*
*/
@@ -68,7 +69,7 @@ static int sndbuf;
static struct timeval sndto;
static bool quiet;
-struct bt_iso_qos *iso_qos;
+struct bt_iso_unicast_qos *iso_qos;
static bool inout;
struct lookup_table {
@@ -239,38 +240,94 @@ fail:
return err < 0 ? err : 0;
}
-static void print_qos(int sk, struct sockaddr_iso *addr)
+static void print_unicast_qos(int sk)
{
- struct bt_iso_qos qos;
+ struct bt_iso_unicast_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) {
+ if (getsockopt(sk, SOL_BLUETOOTH, BT_ISO_UNICAST_QOS, &qos, &len) < 0) {
syslog(LOG_ERR, "Can't get QoS socket option: %s (%d)",
strerror(errno), errno);
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.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, "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);
+}
+
+static void print_bcast_source_qos(int sk)
+{
+ struct bt_iso_bcast_source_qos qos;
+ socklen_t len;
+
+ /* Read Out QOS */
+ memset(&qos, 0, sizeof(qos));
+ len = sizeof(qos);
+
+ if (getsockopt(sk, SOL_BLUETOOTH, BT_ISO_BCAST_SOURCE_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.big, qos.bis, qos.packing,
+ qos.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);
}
+static void print_bcast_sink_qos(int sk)
+{
+ struct bt_iso_bcast_sink_qos qos;
+ socklen_t len;
+
+ /* Read Out QOS */
+ memset(&qos, 0, sizeof(qos));
+ len = sizeof(qos);
+
+ if (getsockopt(sk, SOL_BLUETOOTH, BT_ISO_BCAST_SINK_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.big);
+
+ 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);
+}
+
+static void unicast_qos_to_bcast_source(struct bt_iso_unicast_qos *unicast_qos,
+ struct bt_iso_bcast_source_qos *source_qos)
+{
+ memset(source_qos, 0, sizeof(*source_qos));
+
+ source_qos->sync_interval = unicast_qos->sca;
+ source_qos->big = unicast_qos->cig;
+ source_qos->bis = unicast_qos->cis;
+ source_qos->packing = unicast_qos->packing;
+ source_qos->framing = unicast_qos->framing;
+ source_qos->out = unicast_qos->out;
+}
+
static int do_connect(char *peer)
{
struct sockaddr_iso addr;
@@ -306,11 +363,25 @@ static int do_connect(char *peer)
iso_qos->in.sdu = 0;
}
- if (setsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS, iso_qos,
- sizeof(*iso_qos)) < 0) {
- syslog(LOG_ERR, "Can't set QoS socket option: "
+ if (!strcmp(peer, "00:00:00:00:00:00")) {
+ struct bt_iso_bcast_source_qos source_qos;
+
+ unicast_qos_to_bcast_source(iso_qos, &source_qos);
+
+ if (setsockopt(sk, SOL_BLUETOOTH,
+ BT_ISO_BCAST_SOURCE_QOS, &source_qos,
+ sizeof(source_qos)) < 0) {
+ syslog(LOG_ERR, "Can't set QoS socket option: "
"%s (%d)", strerror(errno), errno);
- goto error;
+ goto error;
+ }
+ } else {
+ if (setsockopt(sk, SOL_BLUETOOTH, BT_ISO_UNICAST_QOS,
+ iso_qos, sizeof(*iso_qos)) < 0) {
+ syslog(LOG_ERR, "Can't set QoS socket option: "
+ "%s (%d)", strerror(errno), errno);
+ goto error;
+ }
}
}
@@ -338,7 +409,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_source_qos(sk);
+ else
+ print_unicast_qos(sk);
return sk;
@@ -441,7 +515,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_sink_qos(nsk);
+ else
+ print_unicast_qos(nsk);
/* Handle deferred setup */
if (defer_setup) {
@@ -648,7 +725,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 +739,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,16 +763,22 @@ 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);
}
}
static void send_mode(char *filename, char *peer, int i, bool repeat)
{
- struct bt_iso_qos qos;
+ struct bt_iso_io_qos *out;
socklen_t len;
int sk, fd = -1;
uint32_t num;
+ int optname;
+
+ union {
+ struct bt_iso_bcast_source_qos source_qos;
+ struct bt_iso_unicast_qos unicast_qos;
+ } qos;
if (filename) {
char altername[PATH_MAX];
@@ -728,16 +811,24 @@ 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")) {
+ optname = BT_ISO_BCAST_SOURCE_QOS;
+ out = &qos.source_qos.out;
+ } else {
+ optname = BT_ISO_UNICAST_QOS;
+ out = &qos.unicast_qos.out;
+ }
+
memset(&qos, 0, sizeof(qos));
len = sizeof(qos);
- if (getsockopt(sk, SOL_BLUETOOTH, BT_ISO_QOS, &qos, &len) < 0) {
+ if (getsockopt(sk, SOL_BLUETOOTH, optname, &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 +837,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 +859,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)
@@ -844,7 +935,7 @@ static void multy_connect_mode(char *peer)
static struct qos_preset {
const char *name;
bool inout;
- struct bt_iso_qos qos;
+ struct bt_iso_unicast_qos qos;
} presets[] = {
/* QoS Configuration settings for low latency audio data */
QOS_PRESET("8_1_1", true, 7500, 8, 26, 0x02, 2),