Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH BlueZ v2 0/4] Bearer.LE1: Add ReadRSSI
@ 2026-11-13  5:14 Kevin Dewald
  2026-11-13  5:14 ` [PATCH BlueZ v2 1/4] org.bluez.Bearer: Add ReadRSSI method Kevin Dewald
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Kevin Dewald @ 2026-11-13  5:14 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Luiz Augusto von Dentz, Kevin Dewald

This adds ReadRSSI to Bearer.LE1 as a testing method, for diagnostics
and production testing, as discussed on v1 [1]. It is only available
when D-Bus testing interfaces are enabled, with bluetoothd -T or
Testing = true in main.conf.

Each call sends Get Connection Information, which the kernel answers
from the controller or with the value it read in the last 1 to 3
seconds. A call made right after Connect returns fails with NotReady
until the kernel has read the remote features.

Changes in v2:
- Make ReadRSSI a testing method and mark it [testing] in the
  documentation.
- Enable testing interfaces on one host in the functional test, and
  check that the other host does not export ReadRSSI.
- Rebase on master.

Tested with the functional test on bluetooth-next 3f425f95ba39, and on
an RTL8761BU connected to an nRF52840. With -T, ReadRSSI returned
-48 dBm; without it, the method was not exported.

[1] https://lore.kernel.org/linux-bluetooth/20261112032250.37687-1-kevin@simpleble.org/

Kevin Dewald (4):
  org.bluez.Bearer: Add ReadRSSI method
  adapter: Add btd_adapter_get_conn_info
  bearer: Add ReadRSSI method
  test: functional: add bearer ReadRSSI test

 doc/org.bluez.Bearer.LE.rst    |  19 ++++++
 src/adapter.c                  |  22 +++++++
 src/adapter.h                  |   7 +++
 src/bearer.c                   | 111 ++++++++++++++++++++++++++++++++-
 test/functional/test_bearer.py |  42 +++++++++++++
 5 files changed, 199 insertions(+), 2 deletions(-)


base-commit: 20ffd285b58facfd1f2478d159a5f941b09d5be1
-- 
2.54.0 (Apple Git-157)


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH BlueZ v2 1/4] org.bluez.Bearer: Add ReadRSSI method
  2026-11-13  5:14 [PATCH BlueZ v2 0/4] Bearer.LE1: Add ReadRSSI Kevin Dewald
@ 2026-11-13  5:14 ` Kevin Dewald
  2026-11-13 10:44   ` Bearer.LE1: Add ReadRSSI bluez.test.bot
  2026-11-13  5:14 ` [PATCH BlueZ v2 2/4] adapter: Add btd_adapter_get_conn_info Kevin Dewald
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 6+ messages in thread
From: Kevin Dewald @ 2026-11-13  5:14 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Luiz Augusto von Dentz, Kevin Dewald

Add a testing method to read the RSSI of the current connection on LE
bearer, for diagnostics and production testing. It is only available
when D-Bus testing interfaces are enabled.

Assisted-by: Claude:claude-opus-5.5
---
 doc/org.bluez.Bearer.LE.rst | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/doc/org.bluez.Bearer.LE.rst b/doc/org.bluez.Bearer.LE.rst
index 3db5237b4..803adb401 100644
--- a/doc/org.bluez.Bearer.LE.rst
+++ b/doc/org.bluez.Bearer.LE.rst
@@ -57,6 +57,25 @@ Possible errors:
 
 :org.bluez.Error.NotConnected:
 
+int16 ReadRSSI() [testing]
+``````````````````````````
+
+Reads the Received Signal Strength Indicator of the current connection on LE
+bearer from the controller, in dBm, for diagnostics and production testing.
+
+Available only when D-Bus testing interfaces are enabled.
+
+The kernel caches the value for a few seconds, so calls made in quick succession
+may return the same value. Right after the connection is established, while it
+is still being set up, the method fails with org.bluez.Error.NotReady.
+
+Possible errors:
+
+:org.bluez.Error.NotConnected:
+:org.bluez.Error.NotReady:
+:org.bluez.Error.NotAvailable:
+:org.bluez.Error.Failed:
+
 Signals
 -------
 
-- 
2.54.0 (Apple Git-157)


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH BlueZ v2 2/4] adapter: Add btd_adapter_get_conn_info
  2026-11-13  5:14 [PATCH BlueZ v2 0/4] Bearer.LE1: Add ReadRSSI Kevin Dewald
  2026-11-13  5:14 ` [PATCH BlueZ v2 1/4] org.bluez.Bearer: Add ReadRSSI method Kevin Dewald
@ 2026-11-13  5:14 ` Kevin Dewald
  2026-11-13  5:14 ` [PATCH BlueZ v2 3/4] bearer: Add ReadRSSI method Kevin Dewald
  2026-11-13  5:14 ` [PATCH BlueZ v2 4/4] test: functional: add bearer ReadRSSI test Kevin Dewald
  3 siblings, 0 replies; 6+ messages in thread
From: Kevin Dewald @ 2026-11-13  5:14 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Luiz Augusto von Dentz, Kevin Dewald

Add a function to send Get Connection Information for a connection, and
one to cancel a pending mgmt request.

Assisted-by: Claude:claude-opus-5.5
---
 src/adapter.c | 22 ++++++++++++++++++++++
 src/adapter.h |  7 +++++++
 2 files changed, 29 insertions(+)

diff --git a/src/adapter.c b/src/adapter.c
index ea438375c..fa55bd87c 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -11628,3 +11628,25 @@ unsigned int btd_adapter_send_cmd_event_sync(struct btd_adapter *adapter,
 				adapter->dev_id, sizeof(pkt.cp) + length,
 				&pkt, callback, user_data, destroy);
 }
+
+unsigned int btd_adapter_get_conn_info(struct btd_adapter *adapter,
+					const bdaddr_t *bdaddr,
+					uint8_t bdaddr_type,
+					btd_adapter_reply_event_t callback,
+					void *user_data)
+{
+	struct mgmt_cp_get_conn_info cp;
+
+	memset(&cp, 0, sizeof(cp));
+	bacpy(&cp.addr.bdaddr, bdaddr);
+	cp.addr.type = bdaddr_type;
+
+	return mgmt_send(adapter->mgmt, MGMT_OP_GET_CONN_INFO,
+				adapter->dev_id, sizeof(cp), &cp,
+				callback, user_data, NULL);
+}
+
+void btd_adapter_cancel_request(struct btd_adapter *adapter, unsigned int id)
+{
+	mgmt_cancel(adapter->mgmt, id);
+}
diff --git a/src/adapter.h b/src/adapter.h
index 583168f4b..3c777afe1 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -328,3 +328,10 @@ unsigned int btd_adapter_send_cmd_event_sync(struct btd_adapter *adapter,
 					void *user_data,
 					btd_adapter_destroy_func_t destroy,
 					uint8_t timeout);
+
+unsigned int btd_adapter_get_conn_info(struct btd_adapter *adapter,
+					const bdaddr_t *bdaddr,
+					uint8_t bdaddr_type,
+					btd_adapter_reply_event_t callback,
+					void *user_data);
+void btd_adapter_cancel_request(struct btd_adapter *adapter, unsigned int id);
-- 
2.54.0 (Apple Git-157)


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH BlueZ v2 3/4] bearer: Add ReadRSSI method
  2026-11-13  5:14 [PATCH BlueZ v2 0/4] Bearer.LE1: Add ReadRSSI Kevin Dewald
  2026-11-13  5:14 ` [PATCH BlueZ v2 1/4] org.bluez.Bearer: Add ReadRSSI method Kevin Dewald
  2026-11-13  5:14 ` [PATCH BlueZ v2 2/4] adapter: Add btd_adapter_get_conn_info Kevin Dewald
@ 2026-11-13  5:14 ` Kevin Dewald
  2026-11-13  5:14 ` [PATCH BlueZ v2 4/4] test: functional: add bearer ReadRSSI test Kevin Dewald
  3 siblings, 0 replies; 6+ messages in thread
From: Kevin Dewald @ 2026-11-13  5:14 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Luiz Augusto von Dentz, Kevin Dewald

Implement Bearer.LE1.ReadRSSI with Get Connection Information, as a
testing method. The kernel reads the RSSI from the controller, or
returns the value it read last if that is recent enough
(conn_info_min_age and conn_info_max_age, 1 to 3 seconds by default).

The kernel reports a connection as soon as it is established but only
answers Get Connection Information once it has set it up, so a call made
right after Connect returns fails with NotReady rather than NotConnected.

Calls made while a request is pending get its result rather than sending
another one, as the kernel would answer that with its cached value,
which a new connection does not have yet.

The method is only on Bearer.LE1, as the RSSI of a BR/EDR connection is
relative to the golden receive power range rather than in dBm.

Assisted-by: Claude:claude-opus-5.5
---
 src/bearer.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 109 insertions(+), 2 deletions(-)

diff --git a/src/bearer.c b/src/bearer.c
index ebcdc2b4c..3cbb74bcc 100644
--- a/src/bearer.c
+++ b/src/bearer.c
@@ -57,6 +57,10 @@ struct btd_bearer {
 	 */
 	DBusMessage *connect; /* connect message */
 
+	/* ReadRSSI calls waiting for the Get Connection Information reply */
+	unsigned int conn_info_id;
+	struct queue *rssi_reads;
+
 	/* LE connection parameters, only valid while connected */
 	bool conn_params;
 	uint32_t interval; /* in microseconds */
@@ -213,10 +217,93 @@ static DBusMessage *bearer_disconnect(DBusConnection *conn, DBusMessage *msg,
 	return NULL;
 }
 
-static const GDBusMethodTable bearer_methods[] = {
+static DBusMessage *rssi_reply(struct btd_bearer *bearer, DBusMessage *msg,
+					uint8_t status, uint16_t length,
+					const struct mgmt_rp_get_conn_info *rp)
+{
+	dbus_int16_t rssi;
+
+	/* The kernel reports the connection as soon as it is established, but
+	 * only answers once it has set it up, e.g. read the remote features.
+	 */
+	if (status == MGMT_STATUS_NOT_CONNECTED) {
+		if (btd_device_bdaddr_type_connected(bearer->device,
+							bearer->type))
+			return btd_error_not_ready(msg);
+
+		return btd_error_not_connected(msg);
+	}
+
+	if (status != MGMT_STATUS_SUCCESS)
+		return btd_error_failed(msg, mgmt_errstr(status));
+
+	if (length < sizeof(*rp))
+		return btd_error_failed(msg, "Invalid response");
+
+	/* 127 means the controller has no RSSI for the connection */
+	if (rp->rssi == 127)
+		return btd_error_not_available(msg);
+
+	rssi = rp->rssi;
+
+	return g_dbus_create_reply(msg, DBUS_TYPE_INT16, &rssi,
+							DBUS_TYPE_INVALID);
+}
+
+static void conn_info_complete(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct btd_bearer *bearer = user_data;
+	DBusMessage *msg;
+
+	bearer->conn_info_id = 0;
+
+	while ((msg = queue_pop_head(bearer->rssi_reads))) {
+		g_dbus_send_message(btd_get_dbus_connection(),
+				rssi_reply(bearer, msg, status, length, param));
+		dbus_message_unref(msg);
+	}
+}
+
+static DBusMessage *bearer_read_rssi(DBusConnection *conn, DBusMessage *msg,
+							void *user_data)
+{
+	struct btd_bearer *bearer = user_data;
+	struct btd_device *device = bearer->device;
+
+	if (!btd_device_bdaddr_type_connected(device, bearer->type))
+		return btd_error_not_connected(msg);
+
+	/* Calls made while a read is pending get the same result */
+	if (!bearer->conn_info_id) {
+		bearer->conn_info_id = btd_adapter_get_conn_info(
+					device_get_adapter(device),
+					device_get_address(device),
+					device_get_le_address_type(device),
+					conn_info_complete, bearer);
+		if (!bearer->conn_info_id)
+			return btd_error_failed(msg, "Unable to read RSSI");
+	}
+
+	queue_push_tail(bearer->rssi_reads, dbus_message_ref(msg));
+
+	return NULL;
+}
+
+static const GDBusMethodTable bearer_bredr_methods[] = {
+	{ GDBUS_ASYNC_METHOD("Connect", NULL, NULL, bearer_connect) },
+	{ GDBUS_ASYNC_METHOD("Disconnect", NULL, NULL,
+						bearer_disconnect) },
+	{}
+};
+
+static const GDBusMethodTable bearer_le_methods[] = {
 	{ GDBUS_ASYNC_METHOD("Connect", NULL, NULL, bearer_connect) },
 	{ GDBUS_ASYNC_METHOD("Disconnect", NULL, NULL,
 						bearer_disconnect) },
+	{ GDBUS_TESTING_ASYNC_METHOD("ReadRSSI", NULL,
+					GDBUS_ARGS({ "rssi", "n" }),
+					bearer_read_rssi) },
 	{}
 };
 
@@ -404,6 +491,14 @@ static const char *bearer_interface(uint8_t type)
 		return BTD_BEARER_LE_INTERFACE;
 }
 
+static const GDBusMethodTable *bearer_methods(uint8_t type)
+{
+	if (type == BDADDR_BREDR)
+		return bearer_bredr_methods;
+	else
+		return bearer_le_methods;
+}
+
 struct btd_bearer *btd_bearer_new(struct btd_device *device, uint8_t type)
 {
 	struct btd_bearer *bearer;
@@ -426,10 +521,11 @@ struct btd_bearer *btd_bearer_new(struct btd_device *device, uint8_t type)
 	bearer->type = type;
 	bearer->path = device_get_path(device);
 	bearer->disconnects = queue_new();
+	bearer->rssi_reads = queue_new();
 
 	if (!g_dbus_register_interface(btd_get_dbus_connection(),
 					bearer->path, bearer_interface(type),
-					bearer_methods, bearer_signals,
+					bearer_methods(type), bearer_signals,
 					bearer_properties,
 					bearer, bearer_free)) {
 		error("Unable to register BREDR interface");
@@ -459,6 +555,17 @@ void btd_bearer_destroy(struct btd_bearer *bearer)
 		bearer->connect = NULL;
 	}
 
+	if (bearer->conn_info_id) {
+		btd_adapter_cancel_request(device_get_adapter(bearer->device),
+							bearer->conn_info_id);
+		bearer->conn_info_id = 0;
+	}
+
+	if (bearer->rssi_reads) {
+		queue_destroy(bearer->rssi_reads, bearer_free_dbus_message);
+		bearer->rssi_reads = NULL;
+	}
+
 	g_dbus_unregister_interface(btd_get_dbus_connection(), bearer->path,
 					bearer_interface(bearer->type));
 }
-- 
2.54.0 (Apple Git-157)


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH BlueZ v2 4/4] test: functional: add bearer ReadRSSI test
  2026-11-13  5:14 [PATCH BlueZ v2 0/4] Bearer.LE1: Add ReadRSSI Kevin Dewald
                   ` (2 preceding siblings ...)
  2026-11-13  5:14 ` [PATCH BlueZ v2 3/4] bearer: Add ReadRSSI method Kevin Dewald
@ 2026-11-13  5:14 ` Kevin Dewald
  3 siblings, 0 replies; 6+ messages in thread
From: Kevin Dewald @ 2026-11-13  5:14 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Luiz Augusto von Dentz, Kevin Dewald

Read the RSSI of the LE connection from a host with testing interfaces
enabled, check ReadRSSI fails with NotConnected once disconnected, and
check a host without testing interfaces does not expose it.

Assisted-by: Claude:claude-opus-5.5
---
 test/functional/test_bearer.py | 42 ++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/test/functional/test_bearer.py b/test/functional/test_bearer.py
index 59ce8ef7d..41134221a 100644
--- a/test/functional/test_bearer.py
+++ b/test/functional/test_bearer.py
@@ -54,6 +54,9 @@ UPDATE_CONF = LE_CONF + "[LE]\nMinConnectionInterval = 80\nMaxConnectionInterval
 
 CONN_PARAMS = ("Interval", "Latency", "SupervisionTimeout", "Subrate")
 
+# ReadRSSI is a testing method
+TESTING_CONF = LE_CONF + "Testing = true\n"
+
 
 class Bearers(HostPlugin, EventPluginMixin):
     """
@@ -283,6 +286,45 @@ def test_bearer_le_conn_params(hosts):
             assert host.bearers.get(remote.bdaddr, LE_INTERFACE, name) is None
 
 
+@host_config(
+    [
+        Bluetoothd(conf=TESTING_CONF, args=ARGS),
+        Agent(capability="NoInputNoOutput"),
+        Bearers(),
+    ],
+    [
+        Bluetoothd(conf=LE_CONF, args=ARGS),
+        LeAdvertiser(),
+        Agent(capability="NoInputNoOutput"),
+        Bearers(),
+    ],
+)
+def test_bearer_le_read_rssi(hosts):
+    host0, host1 = hosts
+
+    connect_le(host0, host1)
+
+    for host, remote in peers(host0, host1):
+        wait_until(
+            lambda: host.bearers.get(remote.bdaddr, LE_INTERFACE, "Connected") is True
+        )
+
+    # The emulated controller reports -1 dBm for every connection
+    host0.bearers.call(host1.bdaddr, LE_INTERFACE, "ReadRSSI")
+    reply = host0.bearers.expect(f"{LE_INTERFACE}.ReadRSSI:reply")
+    assert reply.values == (-1,)
+
+    host1.bearers.call(host0.bdaddr, LE_INTERFACE, "ReadRSSI")
+    error = host1.bearers.expect(f"{LE_INTERFACE}.ReadRSSI:error").error
+    assert error.get_dbus_name() == "org.freedesktop.DBus.Error.UnknownMethod"
+
+    disconnect(host0, host1, LE_INTERFACE)
+
+    host0.bearers.call(host1.bdaddr, LE_INTERFACE, "ReadRSSI")
+    error = host0.bearers.expect(f"{LE_INTERFACE}.ReadRSSI:error").error
+    assert error.get_dbus_name() == "org.bluez.Error.NotConnected"
+
+
 @host_config(
     [
         Bluetoothd(conf=LE_CONF, args=ARGS),
-- 
2.54.0 (Apple Git-157)


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* RE: Bearer.LE1: Add ReadRSSI
  2026-11-13  5:14 ` [PATCH BlueZ v2 1/4] org.bluez.Bearer: Add ReadRSSI method Kevin Dewald
@ 2026-11-13 10:44   ` bluez.test.bot
  0 siblings, 0 replies; 6+ messages in thread
From: bluez.test.bot @ 2026-11-13 10:44 UTC (permalink / raw)
  To: linux-bluetooth, kevin

[-- Attachment #1: Type: text/plain, Size: 1020 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/series/1210165/

---Test result---

Test Summary:
CheckPatch                    PASS      1.24 seconds
GitLint                       PASS      0.91 seconds
BuildEll                      PASS      13.79 seconds
BluezMake                     PASS      182.37 seconds
MakeCheck                     PASS      12.80 seconds
MakeDistcheck                 PASS      103.53 seconds
CheckValgrind                 PASS      228.31 seconds
CheckSmatch                   PASS      180.57 seconds
bluezmakeextell               PASS      63.29 seconds
TestFunctional                PASS      841.13 seconds
IncrementalBuild              PASS      197.45 seconds
ScanBuild                     PASS      607.53 seconds



https://github.com/bluez/bluez/pull/2820

---
Regards,
Linux Bluetooth


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-11-13 10:44 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-13  5:14 [PATCH BlueZ v2 0/4] Bearer.LE1: Add ReadRSSI Kevin Dewald
2026-11-13  5:14 ` [PATCH BlueZ v2 1/4] org.bluez.Bearer: Add ReadRSSI method Kevin Dewald
2026-11-13 10:44   ` Bearer.LE1: Add ReadRSSI bluez.test.bot
2026-11-13  5:14 ` [PATCH BlueZ v2 2/4] adapter: Add btd_adapter_get_conn_info Kevin Dewald
2026-11-13  5:14 ` [PATCH BlueZ v2 3/4] bearer: Add ReadRSSI method Kevin Dewald
2026-11-13  5:14 ` [PATCH BlueZ v2 4/4] test: functional: add bearer ReadRSSI test Kevin Dewald

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox