[PATCH BlueZ v1 11/12] emulator/bthost: Add LE Connection Rate Request support

Luiz Augusto von Dentz <[email protected]> Fri, 24 Jul 2026 15:12:24 -0400
Newsgroups org.kernel.vger.linux-bluetooth
Message-ID <[email protected]>
From: Luiz Augusto von Dentz <[email protected]>

Add bthost_le_conn_rate() to send the LE Connection Rate Request
(0x20a1) command for a given connection handle.

Also handle the LE Connection Rate Change event (0x37).

This allows testing a peripheral (server) handling of the Shorter
Connection Interval feature by having the emulated central initiate
the connection rate request on connect.
---
 emulator/bthost.c | 36 ++++++++++++++++++++++++++++++++++++
 emulator/bthost.h | 14 ++++++++++++++
 2 files changed, 50 insertions(+)

diff --git a/emulator/bthost.c b/emulator/bthost.c
index 2732b7f83f8b..46c6a52f5729 100644
--- a/emulator/bthost.c
+++ b/emulator/bthost.c
@@ -1729,6 +1729,21 @@ static void evt_le_conn_update_complete(struct bthost *bthost, const void *data,
 		return;
 }
 
+static void evt_le_conn_rate_change(struct bthost *bthost, const void *data,
+								uint8_t len)
+{
+	const struct bt_hci_evt_le_conn_rate_change *ev = data;
+
+	if (len < sizeof(*ev))
+		return;
+
+	if (ev->status)
+		return;
+
+	bthost_debug(bthost, "conn rate change: handle %u subrate %u",
+			le16_to_cpu(ev->handle), le16_to_cpu(ev->subrate));
+}
+
 static void evt_le_remote_features_complete(struct bthost *bthost,
 						const void *data, uint8_t len)
 {
@@ -1963,6 +1978,9 @@ static void evt_le_meta_event(struct bthost *bthost, const void *data,
 	case BT_HCI_EVT_LE_BIG_INFO_ADV_REPORT:
 		evt_le_big_info_adv_report(bthost, evt_data, len - 1);
 		break;
+	case BT_HCI_EVT_LE_CONN_RATE_CHANGE:
+		evt_le_conn_rate_change(bthost, evt_data, len - 1);
+		break;
 	default:
 		bthost_debug(bthost, "Unsupported LE Meta event 0x%2.2x",
 								*event);
@@ -3999,6 +4017,24 @@ void bthost_le_start_encrypt(struct bthost *bthost, uint16_t handle,
 	send_command(bthost, BT_HCI_CMD_LE_START_ENCRYPT, &cmd, sizeof(cmd));
 }
 
+void bthost_le_conn_rate(struct bthost *bthost, uint16_t handle,
+					const struct bthost_conn_rate *rate)
+{
+	struct bt_hci_cmd_le_conn_rate cmd;
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.handle = cpu_to_le16(handle);
+	cmd.interval_min = cpu_to_le16(rate->interval_min);
+	cmd.interval_max = cpu_to_le16(rate->interval_max);
+	cmd.subrate_min = cpu_to_le16(rate->subrate_min);
+	cmd.subrate_max = cpu_to_le16(rate->subrate_max);
+	cmd.max_latency = cpu_to_le16(rate->max_latency);
+	cmd.cont_num = cpu_to_le16(rate->cont_num);
+	cmd.supv_timeout = cpu_to_le16(rate->supv_timeout);
+
+	send_command(bthost, BT_HCI_CMD_LE_CONN_RATE, &cmd, sizeof(cmd));
+}
+
 uint64_t bthost_conn_get_fixed_chan(struct bthost *bthost, uint16_t handle)
 {
 	struct btconn *conn;
diff --git a/emulator/bthost.h b/emulator/bthost.h
index c88ea0329a65..e104e68af782 100644
--- a/emulator/bthost.h
+++ b/emulator/bthost.h
@@ -66,6 +66,20 @@ void bthost_hci_connect(struct bthost *bthost, const uint8_t *bdaddr,
 void bthost_hci_ext_connect(struct bthost *bthost, const uint8_t *bdaddr,
 							uint8_t addr_type);
 
+struct bthost_conn_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;
+};
+
+/* Send LE Connection Rate Request for the given connection handle. */
+void bthost_le_conn_rate(struct bthost *bthost, uint16_t handle,
+					const struct bthost_conn_rate *rate);
+
 void bthost_hci_disconnect(struct bthost *bthost, uint16_t handle,
 								uint8_t reason);
 
-- 
2.54.0