diff mbox series

[BlueZ,7/8] tools/isotest: Use dedicated ISO QoS options for unicast and broadcast

Message ID 20230320143713.25449-8-iulia.tanasescu@nxp.com
State New
Headers show
Series [BlueZ,1/8] btio: Use unicast structure for ISO QoS options | expand

Commit Message

Iulia Tanasescu March 20, 2023, 2:37 p.m. UTC
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 mbox series

Patch

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),