* [RFC PATCH BlueZ 0/4] Bearer.LE1: Add ReadRSSI
@ 2026-11-12 3:22 Kevin Dewald
2026-11-12 3:22 ` [RFC PATCH BlueZ 1/4] org.bluez.Bearer: Add ReadRSSI method Kevin Dewald
` (4 more replies)
0 siblings, 5 replies; 9+ messages in thread
From: Kevin Dewald @ 2026-11-12 3:22 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Luiz Augusto von Dentz, Kevin Dewald
Device1.RSSI only covers inquiry and advertising, so once a device is
connected and no longer advertising, there is no way to follow its
signal strength over D-Bus. Applications want it to warn about a link
that is getting weak before it drops. Android (readRemoteRssi) and iOS
and macOS (readRSSI) offer it, and the kernel has Get Connection
Information for it, which only btmgmt uses today.
This adds ReadRSSI to Bearer.LE1. It is a method rather than a property,
so bluetoothd does not poll: 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.
This was proposed in 2014 as ConnectionRSSI with Start and
StopConnectionMonitor on Device1 [1], and you found raw RSSI too low
level and suggested a normalized link quality instead. I went with the
raw value because it is what the other platforms expose, and what
applications compare with the advertising RSSI that Device1.RSSI already
gives in dBm. A normalized value depends on the controller and antenna,
and it can be derived from dBm but not the other way round. If you would
rather have a quality value, or the TX power from Get Connection
Information as well, I can rework it.
The kernel reports a connection as soon as it is established, but
refuses Get Connection Information until it has read the remote
features. A ReadRSSI made right after Connect returns therefore fails
with NotReady for a few tens of milliseconds. Letting get_conn_info()
accept BT_CONFIG would avoid that, and I can send that to the kernel
separately if you agree.
I tested it with the functional test in patch 4 on bluetooth-next
3f425f95ba39, and on real hardware: an RTL8761BU connected to an
nRF52840 with a random static address. ReadRSSI returned -50 to -52 dBm
while the advertising RSSI was -50 dBm, and the kernel sent HCI Read
RSSI about every 2 seconds however often ReadRSSI was called.
I left out a bluetoothctl command and can add one if you want it.
[1] https://lore.kernel.org/linux-bluetooth/1401177171-19994-2-git-send-email-andrzej.kaczmarek@tieto.com/
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 | 17 +++++
src/adapter.c | 22 +++++++
src/adapter.h | 7 +++
src/bearer.c | 110 ++++++++++++++++++++++++++++++++-
test/functional/test_bearer.py | 23 +++++++
5 files changed, 177 insertions(+), 2 deletions(-)
base-commit: 9659adb6819d7e0284d0d2ba226a3894423d8db4
--
2.54.0 (Apple Git-157)
^ permalink raw reply [flat|nested] 9+ messages in thread* [RFC PATCH BlueZ 1/4] org.bluez.Bearer: Add ReadRSSI method 2026-11-12 3:22 [RFC PATCH BlueZ 0/4] Bearer.LE1: Add ReadRSSI Kevin Dewald @ 2026-11-12 3:22 ` Kevin Dewald 2026-11-12 9:03 ` Bearer.LE1: Add ReadRSSI bluez.test.bot 2026-11-12 3:22 ` [RFC PATCH BlueZ 2/4] adapter: Add btd_adapter_get_conn_info Kevin Dewald ` (3 subsequent siblings) 4 siblings, 1 reply; 9+ messages in thread From: Kevin Dewald @ 2026-11-12 3:22 UTC (permalink / raw) To: linux-bluetooth; +Cc: Luiz Augusto von Dentz, Kevin Dewald Add a method to read the RSSI of the current connection on LE bearer. Device1.RSSI only covers inquiry and advertising, so an application cannot follow the signal strength of a device once it is connected and no longer advertising. Assisted-by: Claude:claude-opus-5.5 --- doc/org.bluez.Bearer.LE.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/doc/org.bluez.Bearer.LE.rst b/doc/org.bluez.Bearer.LE.rst index 3db5237b4..589b54873 100644 --- a/doc/org.bluez.Bearer.LE.rst +++ b/doc/org.bluez.Bearer.LE.rst @@ -57,6 +57,23 @@ Possible errors: :org.bluez.Error.NotConnected: +int16 ReadRSSI() +```````````````` + +Reads the Received Signal Strength Indicator of the current connection on LE +bearer from the controller, in dBm. + +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] 9+ messages in thread
* RE: Bearer.LE1: Add ReadRSSI 2026-11-12 3:22 ` [RFC PATCH BlueZ 1/4] org.bluez.Bearer: Add ReadRSSI method Kevin Dewald @ 2026-11-12 9:03 ` bluez.test.bot 0 siblings, 0 replies; 9+ messages in thread From: bluez.test.bot @ 2026-11-12 9:03 UTC (permalink / raw) To: linux-bluetooth, kevin [-- Attachment #1: Type: text/plain, Size: 32239 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/1209013/ ---Test result--- Test Summary: CheckPatch PASS 1.47 seconds GitLint PASS 1.05 seconds BuildEll PASS 14.70 seconds BluezMake PASS 188.93 seconds MakeCheck PASS 12.97 seconds MakeDistcheck PASS 109.45 seconds CheckValgrind PASS 255.55 seconds CheckSmatch PASS 197.73 seconds bluezmakeextell PASS 70.16 seconds TestFunctional FAIL 3051.58 seconds IncrementalBuild PASS 204.66 seconds ScanBuild PASS 628.35 seconds Details ############################## Test: TestFunctional - FAIL Desc: Run test-functional Output: FAIL functional.test_adv_monitor::test_adv_monitor_GHSA_hhgc_hfgf_8m4x[hosts1-vm1]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bluetoothctl::test_bluetoothctl_show[hosts16-vm1]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bluetoothctl::test_bluetoothctl_list[hosts16-vm1]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bluetoothctl::test_bluetoothctl_script_show[hosts16-vm1]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bluetoothctl::test_bluetoothctl_script_list[hosts16-vm1]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_btmgmt::test_btmgmt_info[hosts19-vm1]: AssertionError: assert 'addr 00:00:00:00:00:00' in '\x1b[0;91mReading hci0 info failed with status 0x11 (Invalid Index)\n\x1b[0m' + where '\x1b[0;91mReading hci0 info failed with status 0x11 (Invalid Index)\n\x1b[0m' = CompletedProcess(args=['/home/runner/work/bluez/bluez/src/src/tools/btmgmt', '--index', '0', 'info'], returncode=0, stdout='\x1b[0;91mReading hci0 info failed with status 0x11 (Invalid Index)\n\x1b[0m').stdout FAIL functional.test_a2dp::test_a2dp_transport_created[hosts0-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_a2dp::test_a2dp_transport_acquire[hosts0-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_a2dp::test_a2dp_disconnect_during_setconf[hosts0-vm2-accept]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_a2dp::test_a2dp_disconnect_during_setconf[hosts0-vm2-reject]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_a2dp::test_a2dp_reconnect_pending_disconnect[hosts0-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bearer::test_bearer_le_connect[hosts12-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bearer::test_bearer_le_conn_params[hosts12-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bearer::test_bearer_le_read_rssi[hosts12-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bearer::test_bearer_le_connectable[hosts12-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bearer::test_bearer_le_pair[hosts12-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bearer::test_bearer_bredr_pair[hosts13-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bearer::test_bearer_le_conn_update[hosts14-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bearer::test_bearer_le_not_connectable[hosts15-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bluetoothctl::test_bluetoothctl_pair_bredr[hosts17-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bluetoothctl::test_bluetoothctl_pair_le[hosts18-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_agent::test_agent_pair_bredr[accept-hosts2-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_agent::test_agent_pair_bredr[reject-hosts2-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_hog::test_hog[no-sci-hosts20-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_hog::test_hog[sci-hosts20-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_mpris_proxy::test_mpris_proxy_playback_control[bredr-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_mpris_proxy::test_mpris_proxy_track_control[bredr-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_obex::test_obex_ftp_list[hosts24-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_obex::test_obex_ftp_get[hosts24-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_obex::test_obexctl_list[hosts24-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_avrcp::test_avrcp_GHSA_m2vx_pw5f_rc8v[hosts3-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bap::test_bap_unicast_transport_created[hosts4-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bap::test_bap_unicast_transport_acquire[hosts4-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bap::test_bap_unicast_transport_resume[0-hosts4-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bap::test_bap_unicast_transport_resume[0.1-hosts4-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bap::test_bap_unicast_transport_resume[1.0-hosts4-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bap::test_bap_unicast_reconfigure_metadata[empty-hosts5-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bap::test_bap_unicast_reconfigure_metadata[media-hosts5-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bap::test_bap_unicast_desync[hosts6-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bap::test_bap_unicast_duplex_enable_one[hosts6-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bap::test_bap_broadcast_transport_created[lc3-hosts7-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bap::test_bap_broadcast_transport_created[pbp-hosts7-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bap::test_bap_broadcast_transport_acquire[lc3-hosts7-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bap::test_bap_broadcast_transport_acquire[pbp-hosts7-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bap::test_bass_past_transport_acquire[hosts9-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bap::test_bap_unicast_set_transport_created[hosts10-vm3-sc]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bap::test_bap_unicast_set_transport_created[hosts10-vm3-legacy]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bap::test_bap_unicast_set_transport_acquire[hosts10-vm3]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bap::test_bass_past_earbuds_transport_acquire[hosts11-vm3]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bap::test_bap_broadcast_earbuds_transport_created[hosts8-vm3]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_bap::test_bap_broadcast_earbuds_transport_acquire[hosts8-vm3]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_mpris_proxy::test_mpris_proxy_playback_control[le-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" FAIL functional.test_mpris_proxy::test_mpris_proxy_track_control[le-vm2]: failed on setup with "pytest_bluezenv.rpc.RemoteError: load failed Remote traceback: Traceback (most recent call last): File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/rpc.py", line 102, in server_stream result = method(*msg["a"], **msg["kw"]) File "/usr/local/lib/python3.14/dist-packages/pytest_bluezenv/../pytest_bluezenv/env.py", line 238, in wait_load raise RuntimeError("load failed") RuntimeError: load failed" https://github.com/bluez/bluez/pull/2813 --- Regards, Linux Bluetooth ^ permalink raw reply [flat|nested] 9+ messages in thread
* [RFC PATCH BlueZ 2/4] adapter: Add btd_adapter_get_conn_info 2026-11-12 3:22 [RFC PATCH BlueZ 0/4] Bearer.LE1: Add ReadRSSI Kevin Dewald 2026-11-12 3:22 ` [RFC PATCH BlueZ 1/4] org.bluez.Bearer: Add ReadRSSI method Kevin Dewald @ 2026-11-12 3:22 ` Kevin Dewald 2026-11-12 3:22 ` [RFC PATCH BlueZ 3/4] bearer: Add ReadRSSI method Kevin Dewald ` (2 subsequent siblings) 4 siblings, 0 replies; 9+ messages in thread From: Kevin Dewald @ 2026-11-12 3:22 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 6588a6e2b..c4258fd76 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -11600,3 +11600,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] 9+ messages in thread
* [RFC PATCH BlueZ 3/4] bearer: Add ReadRSSI method 2026-11-12 3:22 [RFC PATCH BlueZ 0/4] Bearer.LE1: Add ReadRSSI Kevin Dewald 2026-11-12 3:22 ` [RFC PATCH BlueZ 1/4] org.bluez.Bearer: Add ReadRSSI method Kevin Dewald 2026-11-12 3:22 ` [RFC PATCH BlueZ 2/4] adapter: Add btd_adapter_get_conn_info Kevin Dewald @ 2026-11-12 3:22 ` Kevin Dewald 2026-11-12 3:22 ` [RFC PATCH BlueZ 4/4] test: functional: add bearer ReadRSSI test Kevin Dewald 2026-11-12 16:07 ` [RFC PATCH BlueZ 0/4] Bearer.LE1: Add ReadRSSI Luiz Augusto von Dentz 4 siblings, 0 replies; 9+ messages in thread From: Kevin Dewald @ 2026-11-12 3:22 UTC (permalink / raw) To: linux-bluetooth; +Cc: Luiz Augusto von Dentz, Kevin Dewald Implement Bearer.LE1.ReadRSSI with Get Connection Information. 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 | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 108 insertions(+), 2 deletions(-) diff --git a/src/bearer.c b/src/bearer.c index ebcdc2b4c..51075cdb7 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,92 @@ 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_ASYNC_METHOD("ReadRSSI", NULL, GDBUS_ARGS({ "rssi", "n" }), + bearer_read_rssi) }, {} }; @@ -404,6 +490,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 +520,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 +554,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] 9+ messages in thread
* [RFC PATCH BlueZ 4/4] test: functional: add bearer ReadRSSI test 2026-11-12 3:22 [RFC PATCH BlueZ 0/4] Bearer.LE1: Add ReadRSSI Kevin Dewald ` (2 preceding siblings ...) 2026-11-12 3:22 ` [RFC PATCH BlueZ 3/4] bearer: Add ReadRSSI method Kevin Dewald @ 2026-11-12 3:22 ` Kevin Dewald 2026-11-12 16:07 ` [RFC PATCH BlueZ 0/4] Bearer.LE1: Add ReadRSSI Luiz Augusto von Dentz 4 siblings, 0 replies; 9+ messages in thread From: Kevin Dewald @ 2026-11-12 3:22 UTC (permalink / raw) To: linux-bluetooth; +Cc: Luiz Augusto von Dentz, Kevin Dewald Read the RSSI of the LE connection from both hosts, and check ReadRSSI fails with NotConnected once disconnected. Assisted-by: Claude:claude-opus-5.5 --- test/functional/test_bearer.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/functional/test_bearer.py b/test/functional/test_bearer.py index 59ce8ef7d..36b614348 100644 --- a/test/functional/test_bearer.py +++ b/test/functional/test_bearer.py @@ -283,6 +283,29 @@ def test_bearer_le_conn_params(hosts): assert host.bearers.get(remote.bdaddr, LE_INTERFACE, name) is None +@le_config +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 + host.bearers.call(remote.bdaddr, LE_INTERFACE, "ReadRSSI") + reply = host.bearers.expect(f"{LE_INTERFACE}.ReadRSSI:reply") + assert reply.values == (-1,) + + 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] 9+ messages in thread
* Re: [RFC PATCH BlueZ 0/4] Bearer.LE1: Add ReadRSSI 2026-11-12 3:22 [RFC PATCH BlueZ 0/4] Bearer.LE1: Add ReadRSSI Kevin Dewald ` (3 preceding siblings ...) 2026-11-12 3:22 ` [RFC PATCH BlueZ 4/4] test: functional: add bearer ReadRSSI test Kevin Dewald @ 2026-11-12 16:07 ` Luiz Augusto von Dentz 2026-11-12 17:40 ` Kevin Dewald 4 siblings, 1 reply; 9+ messages in thread From: Luiz Augusto von Dentz @ 2026-11-12 16:07 UTC (permalink / raw) To: Kevin Dewald; +Cc: linux-bluetooth Hi Kevin, On Wed, Nov 11, 2026 at 10:22 PM Kevin Dewald <kevin@simpleble.org> wrote: > > Device1.RSSI only covers inquiry and advertising, so once a device is > connected and no longer advertising, there is no way to follow its > signal strength over D-Bus. Applications want it to warn about a link > that is getting weak before it drops. Android (readRemoteRssi) and iOS > and macOS (readRSSI) offer it, and the kernel has Get Connection > Information for it, which only btmgmt uses today. > > This adds ReadRSSI to Bearer.LE1. It is a method rather than a property, > so bluetoothd does not poll: 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. That still a poll in my book, not bluetoothd directly but I bet application will start to just poll it on their own. > This was proposed in 2014 as ConnectionRSSI with Start and > StopConnectionMonitor on Device1 [1], and you found raw RSSI too low > level and suggested a normalized link quality instead. I went with the > raw value because it is what the other platforms expose, and what > applications compare with the advertising RSSI that Device1.RSSI already > gives in dBm. A normalized value depends on the controller and antenna, > and it can be derived from dBm but not the other way round. If you would > rather have a quality value, or the TX power from Get Connection > Information as well, I can rework it. Well the reported values are vendor dependent, so I'm not sure how much it would help since you can't use a measurement of link degradation in a generic manner, it needs hardware details to go along. We need a clear motivation for why this would be useful apart from just covering what other OSes might have since they may use a vendor command, or in Apple's case, probably deal with an exclusive vendor which makes things a lot more simpler. > The kernel reports a connection as soon as it is established, but > refuses Get Connection Information until it has read the remote > features. A ReadRSSI made right after Connect returns therefore fails > with NotReady for a few tens of milliseconds. Letting get_conn_info() > accept BT_CONFIG would avoid that, and I can send that to the kernel > separately if you agree. > > I tested it with the functional test in patch 4 on bluetooth-next > 3f425f95ba39, and on real hardware: an RTL8761BU connected to an > nRF52840 with a random static address. ReadRSSI returned -50 to -52 dBm > while the advertising RSSI was -50 dBm, and the kernel sent HCI Read > RSSI about every 2 seconds however often ReadRSSI was called. Which means every btmon trace will now grow just with RSSI reports, I mean I could live with an event generated if RSSI drops below a certain threshold, not a command and event, every 2 seconds. > I left out a bluetoothctl command and can add one if you want it. > > [1] https://lore.kernel.org/linux-bluetooth/1401177171-19994-2-git-send-email-andrzej.kaczmarek@tieto.com/ > > 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 | 17 +++++ > src/adapter.c | 22 +++++++ > src/adapter.h | 7 +++ > src/bearer.c | 110 ++++++++++++++++++++++++++++++++- > test/functional/test_bearer.py | 23 +++++++ > 5 files changed, 177 insertions(+), 2 deletions(-) > > > base-commit: 9659adb6819d7e0284d0d2ba226a3894423d8db4 > -- > 2.54.0 (Apple Git-157) > -- Luiz Augusto von Dentz ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC PATCH BlueZ 0/4] Bearer.LE1: Add ReadRSSI 2026-11-12 16:07 ` [RFC PATCH BlueZ 0/4] Bearer.LE1: Add ReadRSSI Luiz Augusto von Dentz @ 2026-11-12 17:40 ` Kevin Dewald 2026-11-12 19:12 ` Luiz Augusto von Dentz 0 siblings, 1 reply; 9+ messages in thread From: Kevin Dewald @ 2026-11-12 17:40 UTC (permalink / raw) To: Luiz Augusto von Dentz; +Cc: linux-bluetooth, Kevin Dewald Hi Luiz, On Thu, Nov 12, 2026 at 8:07 AM Luiz Augusto von Dentz <luiz.dentz@gmail.com> wrote: > > That still a poll in my book, not bluetoothd directly but I bet > application will start to just poll it on their own. They will, and Get Connection Information was designed for that: the kernel caches the values for a random 1 to 3 seconds "to avoid client trying to guess when to poll again". Applications that need the value poll today anyway, as root through mgmt [1] or with raw HCI sockets that bypass bluetoothd and the cache. Blueman still reads it through libbluetooth for its signal bars, which only works on BR/EDR [2]. > Well the reported values are vendor dependent, so I'm not sure how > much it would help since you can't use a measurement of link > degradation in a generic manner, it needs hardware details to go > along. We need a clear motivation for why this would be useful apart > from just covering what other OSes might have since they may use a > vendor command, or in Apple's case, probably deal with an exclusive > vendor which makes things a lot more simpler. For LE the spec fixes the value: Read RSSI returns the absolute received signal strength in dBm to +/-6 dB accuracy (Vol 4, Part E, 7.5.4), the same unit as the advertising RSSI in Device1.RSSI. BR/EDR is the one relative to the golden range, which is why the method is only on Bearer.LE1. Android's readRemoteRssi sends the standard Read RSSI command, and BlueZ's own Android port implemented it with Get Connection Information. What the value gives that a threshold event can't: - Choosing between links. A device in range of several gateways should stay connected to the one with the best link, and a hub with redundant sensors should read from the strongest. That needs numbers that can be compared, not a crossing per link. - Diagnostics. Logging the RSSI next to throughput and packet loss is how support tells a weak link from a firmware bug, after the fact. - Production test. Test stations connect to every unit and check its RSSI against a reference unit, to catch a bad antenna or enclosure. - Trends. An application streaming data can see the RSSI falling and lower its rate before the link drops, instead of finding out from a threshold picked in advance. > Which means every btmon trace will now grow just with RSSI reports, I > mean I could live with an event generated if RSSI drops below a > certain threshold, not a command and event, every 2 seconds. Only while an application reads it. A threshold event needs the same Read RSSI every 2 seconds underneath, as the RSSI Monitor RFC did in 2011, unless the controller monitors it itself: LE Path Loss Monitoring, which also needs LE Power Control on the peripheral, or the MSFT extension's LE connection RSSI monitor, which the kernel does not use yet. BlueZ already has both for advertising: Device1.RSSI for the value and AdvertisementMonitor1 for thresholds. ReadRSSI is the value half for connections, and I'm happy to add thresholds on top where the controller can monitor the link itself. [1] https://lore.kernel.org/linux-bluetooth/aa77c035-d2aa-f227-bfcd-358b5f063b21@labapart.com/ [2] https://github.com/blueman-project/blueman/pull/1642 -- Kevin ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC PATCH BlueZ 0/4] Bearer.LE1: Add ReadRSSI 2026-11-12 17:40 ` Kevin Dewald @ 2026-11-12 19:12 ` Luiz Augusto von Dentz 0 siblings, 0 replies; 9+ messages in thread From: Luiz Augusto von Dentz @ 2026-11-12 19:12 UTC (permalink / raw) To: Kevin Dewald; +Cc: linux-bluetooth Hi Kevin, On Thu, Nov 12, 2026 at 12:40 PM Kevin Dewald <kevin@simpleble.org> wrote: > > Hi Luiz, > > On Thu, Nov 12, 2026 at 8:07 AM Luiz Augusto von Dentz > <luiz.dentz@gmail.com> wrote: > > > > That still a poll in my book, not bluetoothd directly but I bet > > application will start to just poll it on their own. > > They will, and Get Connection Information was designed for that: the > kernel caches the values for a random 1 to 3 seconds "to avoid client > trying to guess when to poll again". Applications that need the value > poll today anyway, as root through mgmt [1] or with raw HCI sockets > that bypass bluetoothd and the cache. Blueman still reads it through > libbluetooth for its signal bars, which only works on BR/EDR [2]. > > > Well the reported values are vendor dependent, so I'm not sure how > > much it would help since you can't use a measurement of link > > degradation in a generic manner, it needs hardware details to go > > along. We need a clear motivation for why this would be useful apart > > from just covering what other OSes might have since they may use a > > vendor command, or in Apple's case, probably deal with an exclusive > > vendor which makes things a lot more simpler. > > For LE the spec fixes the value: Read RSSI returns the absolute > received signal strength in dBm to +/-6 dB accuracy (Vol 4, Part E, > 7.5.4), the same unit as the advertising RSSI in Device1.RSSI. BR/EDR > is the one relative to the golden range, which is why the method is > only on Bearer.LE1. Android's readRemoteRssi sends the standard Read > RSSI command, and BlueZ's own Android port implemented it with Get > Connection Information. > > What the value gives that a threshold event can't: > > - Choosing between links. A device in range of several gateways should > stay connected to the one with the best link, and a hub with > redundant sensors should read from the strongest. That needs numbers > that can be compared, not a crossing per link. This sounds like something mesh was designed for. Yes, you can do it, but it will be inefficient and probably error prone to juggle between links, Bluetooth is typically a point-to-point/star topology; adding a hub as a middle man is a pretty bad idea. > - Diagnostics. Logging the RSSI next to throughput and packet loss is > how support tells a weak link from a firmware bug, after the fact. > - Production test. Test stations connect to every unit and check its > RSSI against a reference unit, to catch a bad antenna or enclosure. Yeah, that would be acceptable if this is behaving as a testing flag, though. Otherwise, we will have people trying to use RSSI for other purposes, like proximity, which is not really the intent of these metrics. > - Trends. An application streaming data can see the RSSI falling and > lower its rate before the link drops, instead of finding out from a > threshold picked in advance. RSSI values tend to fluctuate a lot. Even if that would make sense why wouldn't we deal with that directly at bluetoothd rather than leaving the decision to an application? Applications like PipeWire already scale the SBC bitpool if the audio starts skipping. We also have TX completion nowadays to measure how long each buffer takes to transmit, and I would be very surprised if using RSSI instead would be a better metric. > > Which means every btmon trace will now grow just with RSSI reports, I > > mean I could live with an event generated if RSSI drops below a > > certain threshold, not a command and event, every 2 seconds. > > Only while an application reads it. A threshold event needs the same > Read RSSI every 2 seconds underneath, as the RSSI Monitor RFC did in > 2011, unless the controller monitors it itself: LE Path Loss > Monitoring, which also needs LE Power Control on the peripheral, or > the MSFT extension's LE connection RSSI monitor, which the kernel does > not use yet. > > BlueZ already has both for advertising: Device1.RSSI for the value and > AdvertisementMonitor1 for thresholds. ReadRSSI is the value half for > connections, and I'm happy to add thresholds on top where the > controller can monitor the link itself. > > [1] https://lore.kernel.org/linux-bluetooth/aa77c035-d2aa-f227-bfcd-358b5f063b21@labapart.com/ > [2] https://github.com/blueman-project/blueman/pull/1642 If a vendor command can monitor the RSSI of a link, perhaps we can use it. However, in that case we could gain much more with proper metrics, etc., but that opens another can of worms because vendors may not agree on all the fields of their telemetry events, and these events are typically for vendor diagnosis, not applications. There is also the likes of Read Link Quality, which is probably more subjective to vendor implementation, and also requires polling, also if you read more about what is required to get a _proper_ link quality then you will see this needs to be enable over the air: https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core_v7.0/out/en/low-energy-controller/linklayer-ll--specification.html#UUID-83754739-8b1b-4943-b310-0477faf28c45 Otherwise you will only get a one sided value from the local controller while the problem could be at the remote end. But if I'm not mistaken this was introduced with HDT as Link Quality Feedback; see: https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core_v7.0/out/en/low-energy-controller/linklayer-ll--specification.html#UUID-edb79691-f7ea-9136-357c-6533d2cb77e0 -- Luiz Augusto von Dentz ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-11-12 19:12 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-11-12 3:22 [RFC PATCH BlueZ 0/4] Bearer.LE1: Add ReadRSSI Kevin Dewald 2026-11-12 3:22 ` [RFC PATCH BlueZ 1/4] org.bluez.Bearer: Add ReadRSSI method Kevin Dewald 2026-11-12 9:03 ` Bearer.LE1: Add ReadRSSI bluez.test.bot 2026-11-12 3:22 ` [RFC PATCH BlueZ 2/4] adapter: Add btd_adapter_get_conn_info Kevin Dewald 2026-11-12 3:22 ` [RFC PATCH BlueZ 3/4] bearer: Add ReadRSSI method Kevin Dewald 2026-11-12 3:22 ` [RFC PATCH BlueZ 4/4] test: functional: add bearer ReadRSSI test Kevin Dewald 2026-11-12 16:07 ` [RFC PATCH BlueZ 0/4] Bearer.LE1: Add ReadRSSI Luiz Augusto von Dentz 2026-11-12 17:40 ` Kevin Dewald 2026-11-12 19:12 ` Luiz Augusto von Dentz
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.