Convert the generic bt_iso_qos structure into dedicated ISO QoS structures for unicast or broadcast. --- tools/isotest.c | 159 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 125 insertions(+), 34 deletions(-) diff --git a/tools/isotest.c b/tools/isotest.c index 2b5f164de..f12658812 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 * */ @@ -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), -- 2.34.1