Linux bluetooth development
 help / color / mirror / Atom feed
From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
To: linux-bluetooth@vger.kernel.org
Subject: [PATCH BlueZ v1 2/2] monitor: Add decoding for Short Connection Interval feature
Date: Mon,  4 May 2026 17:13:02 -0400	[thread overview]
Message-ID: <20260504211303.1081876-2-luiz.dentz@gmail.com> (raw)
In-Reply-To: <20260504211303.1081876-1-luiz.dentz@gmail.com>

From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This adds deconding support for SCI related commands, command bits, event
event mask bit and feature bits:

Events:

HCI_LE_Connection_Rate_Change(0x37)

Commands:

HCI_LE_Connection_Rate_Request(0x20a1)
HCI_LE_Set_Default_Rate_Parameters(0x20a2)
HCI_LE_Read_Minimum_Supported_Connection_Interval(0x20a3)
---
 monitor/bt.h     |  54 ++++++++++++++++++++
 monitor/packet.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 184 insertions(+)

diff --git a/monitor/bt.h b/monitor/bt.h
index 147b76537e97..60fe2efbf143 100644
--- a/monitor/bt.h
+++ b/monitor/bt.h
@@ -3196,6 +3196,49 @@ struct bt_hci_cmd_le_fsu {
 	uint8_t  types;
 } __attribute__ ((packed));
 
+#define BT_HCI_CMD_LE_CONN_RATE		0x20a1
+#define BT_HCI_BIT_LE_CONN_RATE		BT_HCI_CMD_BIT(48, 5)
+struct bt_hci_cmd_le_conn_rate {
+	uint16_t handle;
+	uint16_t interval_min;
+	uint16_t interval_max;
+	uint16_t subrate_min;
+	uint16_t subrate_max;
+	uint16_t max_latency;
+	uint16_t cont_num;
+	uint16_t supv_timeout;
+	uint16_t min_ce_len;
+	uint16_t max_ce_len;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_SET_DEF_RATE		0x20a2
+#define BT_HCI_BIT_LE_SET_DEF_RATE		BT_HCI_CMD_BIT(48, 6)
+struct bt_hci_cmd_le_set_def_rate {
+	uint16_t interval_min;
+	uint16_t interval_max;
+	uint16_t subrate_min;
+	uint16_t subrate_max;
+	uint16_t max_latency;
+	uint16_t cont_num;
+	uint16_t supv_timeout;
+	uint16_t min_ce_len;
+	uint16_t max_ce_len;
+} __attribute__ ((packed));
+
+#define BT_HCI_CMD_LE_READ_CONN_INTERVAL	0x20a3
+#define BT_HCI_BIT_LE_READ_CONN_INTERVAL	BT_HCI_CMD_BIT(48, 7)
+struct bt_hci_le_conn_interval_group {
+	uint16_t min;
+	uint16_t max;
+	uint16_t stride;
+} __attribute__ ((packed));
+
+struct bt_hci_rsp_le_read_conn_interval {
+	uint8_t  status;
+	uint8_t  num_grps;
+	struct bt_hci_le_conn_interval_group grps[0];
+} __attribute__ ((packed));
+
 #define BT_HCI_EVT_INQUIRY_COMPLETE		0x01
 struct bt_hci_evt_inquiry_complete {
 	uint8_t  status;
@@ -4154,6 +4197,17 @@ struct bt_hci_evt_le_fsu_complete {
 	uint8_t  types;
 } __attribute__ ((packed));
 
+#define BT_HCI_EVT_LE_CONN_RATE_CHANGE		0x37
+struct bt_hci_evt_le_conn_rate_change {
+	uint8_t  status;
+	uint16_t handle;
+	uint16_t interval;
+	uint16_t subrate;
+	uint16_t latency;
+	uint16_t cont_number;
+	uint16_t supv_timeout;
+} __attribute__ ((packed));
+
 #define BT_HCI_ERR_SUCCESS			0x00
 #define BT_HCI_ERR_UNKNOWN_COMMAND		0x01
 #define BT_HCI_ERR_UNKNOWN_CONN_ID		0x02
diff --git a/monitor/packet.c b/monitor/packet.c
index 4697eea099a9..a0bf7a70987e 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -2415,6 +2415,12 @@ static void print_rssi(int8_t rssi)
 	packet_print_rssi("RSSI", rssi);
 }
 
+static void print_slot_125u(const char *label, uint16_t value)
+{
+	 print_field("%s: %.3f msec (0x%4.4x)", label,
+				le16_to_cpu(value) * 0.125, le16_to_cpu(value));
+}
+
 static void print_slot_625(const char *label, uint16_t value)
 {
 	 print_field("%s: %.3f msec (0x%4.4x)", label,
@@ -3341,6 +3347,8 @@ static const struct bitfield_data events_le_table[] = {
 	{ 50, "LE CS Test End Complete"			},
 	{ 51, "LE Monitored Advertisers Report"		},
 	{ 52, "LE Frame Space Update Complete"		},
+	{ 53, "LE UTP Received"				},
+	{ 54, "LE Connection Rate Change"		},
 	{ }
 };
 
@@ -9836,6 +9844,89 @@ static void le_fsu_cmd(uint16_t index, const void *data, uint8_t size)
 	print_fsu_types(cmd->types);
 }
 
+static void le_conn_rate_cmd(uint16_t index, const void *data, uint8_t size)
+{
+	const struct bt_hci_cmd_le_conn_rate *cmd = data;
+
+	print_handle(cmd->handle);
+	print_slot_125u("Connection Interval Min", cmd->interval_min);
+	print_slot_125u("Connection Interval Max", cmd->interval_max);
+	print_field("Subrate Min: %u (0x%4.4x)",
+				le16_to_cpu(cmd->subrate_min),
+				le16_to_cpu(cmd->subrate_min));
+	print_field("Subrate Max: %u (0x%4.4x)",
+				le16_to_cpu(cmd->subrate_max),
+				le16_to_cpu(cmd->subrate_max));
+	print_field("Max Latency: %u (0x%4.4x)",
+				le16_to_cpu(cmd->max_latency),
+				le16_to_cpu(cmd->max_latency));
+	print_field("Continuation Number: %u (0x%4.4x)",
+				le16_to_cpu(cmd->cont_num),
+				le16_to_cpu(cmd->cont_num));
+	print_field("Supervision Timeout: %d ms (0x%4.4x)",
+				le16_to_cpu(cmd->supv_timeout) * 10,
+				le16_to_cpu(cmd->supv_timeout));
+	print_slot_125u("Minimum CE Length", cmd->min_ce_len);
+	print_slot_125u("Maximum CE Length", cmd->max_ce_len);
+}
+
+static void le_set_def_rate_cmd(uint16_t index, const void *data, uint8_t size)
+{
+	const struct bt_hci_cmd_le_set_def_rate *cmd = data;
+
+	print_slot_125u("Connection Interval Min", cmd->interval_min);
+	print_slot_125u("Connection Interval Max", cmd->interval_max);
+	print_field("Subrate Min: %u (0x%4.4x)",
+				le16_to_cpu(cmd->subrate_min),
+				le16_to_cpu(cmd->subrate_min));
+	print_field("Subrate Max: %u (0x%4.4x)",
+				le16_to_cpu(cmd->subrate_max),
+				le16_to_cpu(cmd->subrate_max));
+	print_field("Max Latency: %u (0x%4.4x)",
+				le16_to_cpu(cmd->max_latency),
+				le16_to_cpu(cmd->max_latency));
+	print_field("Continuation Number: %u (0x%4.4x)",
+				le16_to_cpu(cmd->cont_num),
+				le16_to_cpu(cmd->cont_num));
+	print_field("Supervision Timeout: %d ms (0x%4.4x)",
+				le16_to_cpu(cmd->supv_timeout) * 10,
+				le16_to_cpu(cmd->supv_timeout));
+	print_slot_125u("Minimum CE Length", cmd->min_ce_len);
+	print_slot_125u("Maximum CE Length", cmd->max_ce_len);
+}
+
+static void le_read_conn_interval_rsp(uint16_t index, const void *data,
+					uint8_t size)
+{
+	const struct bt_hci_rsp_le_read_conn_interval *rsp = data;
+	struct iovec iov;
+	uint8_t i;
+
+	print_status(rsp->status);
+	print_field("Number of Groups: %u", rsp->num_grps);
+
+	if (!rsp->num_grps)
+		return;
+
+	iov.iov_base = (void *)rsp->grps;
+	iov.iov_len = size - sizeof(*rsp);
+
+	for (i = 0; i < rsp->num_grps; i++) {
+		const struct bt_hci_le_conn_interval_group *grp;
+
+		grp = util_iov_pull(&iov, sizeof(*grp));
+		if (!grp) {
+			print_text(COLOR_ERROR, "  invalid group");
+			break;
+		}
+
+		print_field("Group %u:", i);
+		print_slot_125u("  Interval Min", grp->min);
+		print_slot_125u("  Interval Max", grp->max);
+		print_slot_125u("  Interval Stride", grp->stride);
+	}
+}
+
 struct opcode_data {
 	uint16_t opcode;
 	int bit;
@@ -10907,6 +10998,21 @@ static const struct opcode_data opcode_table[] = {
 				"LE Frame Space Update", le_fsu_cmd,
 				sizeof(struct bt_hci_cmd_le_fsu),
 				true, status_rsp, 1, true },
+	{ BT_HCI_CMD_LE_CONN_RATE, BT_HCI_BIT_LE_CONN_RATE,
+				"LE Connection Rate Request", le_conn_rate_cmd,
+				sizeof(struct bt_hci_cmd_le_conn_rate),
+				true, status_rsp, 1, true },
+	{ BT_HCI_CMD_LE_SET_DEF_RATE, BT_HCI_BIT_LE_SET_DEF_RATE,
+				"LE Set Default Rate Parameteres",
+				le_set_def_rate_cmd,
+				sizeof(struct bt_hci_cmd_le_set_def_rate),
+				true, status_rsp, 1, true },
+	{ BT_HCI_CMD_LE_READ_CONN_INTERVAL,
+				BT_HCI_BIT_LE_READ_CONN_INTERVAL,
+				"LE Read Minimum Supported Connection Interval",
+				null_cmd, 0, true, le_read_conn_interval_rsp,
+				sizeof(struct bt_hci_rsp_le_read_conn_interval),
+				true },
 	{ }
 };
 
@@ -13400,6 +13506,26 @@ static void le_fsu_evt(struct timeval *tv, uint16_t index,
 	print_fsu_types(evt->types);
 }
 
+static void le_conn_rate_change_evt(struct timeval *tv, uint16_t index,
+					const void *data, uint8_t size)
+{
+	const struct bt_hci_evt_le_conn_rate_change *evt = data;
+
+	print_handle(evt->handle);
+	print_slot_125u("Connection Interval", le16_to_cpu(evt->interval));
+	print_field("Subrate Factor: %u (0x%4.4x)", le16_to_cpu(evt->subrate),
+					le16_to_cpu(evt->subrate));
+	print_field("Peripheral Latency: %u (0x%4.4x)",
+					le16_to_cpu(evt->latency),
+					le16_to_cpu(evt->latency));
+	print_field("Continuation Number: %u (0x%4.4x)",
+					le16_to_cpu(evt->cont_number),
+					le16_to_cpu(evt->cont_number));
+	print_field("Supervision Timeout: %u ms (0x%4.4X)",
+					le16_to_cpu(evt->supv_timeout),
+					le16_to_cpu(evt->supv_timeout));
+}
+
 struct subevent_data {
 	uint8_t subevent;
 	const char *str;
@@ -13566,6 +13692,10 @@ static const struct subevent_data le_meta_event_table[] = {
 	{ BT_HCI_EVT_LE_FSU_COMPLETE,
 		"LE Frame Space Update Complete",
 		le_fsu_evt, sizeof(struct bt_hci_evt_le_fsu_complete) },
+	{ BT_HCI_EVT_LE_CONN_RATE_CHANGE,
+		"LE Connection Rate Change",
+		le_conn_rate_change_evt,
+		sizeof(struct bt_hci_evt_le_conn_rate_change) },
 	{ }
 };
 
-- 
2.53.0


  reply	other threads:[~2026-05-04 21:13 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-04 21:13 [PATCH BlueZ v1 1/2] monitor: Add features bits defined in 6.2 Luiz Augusto von Dentz
2026-05-04 21:13 ` Luiz Augusto von Dentz [this message]
2026-05-04 22:42 ` [BlueZ,v1,1/2] " bluez.test.bot
2026-05-06 13:30 ` [PATCH BlueZ v1 1/2] " patchwork-bot+bluetooth

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260504211303.1081876-2-luiz.dentz@gmail.com \
    --to=luiz.dentz@gmail.com \
    --cc=linux-bluetooth@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox