Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH BlueZ] adapter: Infer BR/EDR only at public LE addresses
@ 2026-07-16 20:45 Philipp Dunkel
  2026-07-16 22:20 ` [BlueZ] " bluez.test.bot
  0 siblings, 1 reply; 2+ messages in thread
From: Philipp Dunkel @ 2026-07-16 20:45 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Philipp Dunkel

btd_adapter_device_found() records BR/EDR support for any LE device
whose advertising Flags lack "BR/EDR Not Supported" (EIR_BREDR_UNSUP).
The address type is not considered:

	if (bdaddr_type != BDADDR_BREDR && eir_data.flags &&
				!(eir_data.flags & EIR_BREDR_UNSUP)) {
		device_set_bredr_support(dev);

When the advertisement uses a random address the device gets a BR/EDR
bearer whose address is that random address, and start_discovery_cb()
then prefers SDP over GATT:

	if (device->bredr)
		device_browse_sdp(device, NULL);
	else
		device_browse_gatt(device, NULL);

SDP requires a BR/EDR ACL, so bluetoothd pages the random address. A
random address is not a BD_ADDR and cannot be paged, so the attempt
always ends in Page Timeout, and the failure tears down the working LE
link:

  connect_failed_callback() hci0 5A:B4:98:1F:CC:04 status 4
  bonding_attempt_complete() hci0 bdaddr 5A:B4:98:1F:CC:04 type 0 status 0x4
  device_bonding_complete() bonding (nil) status 0x04
  browse_request_cancel()
  btd_gatt_database_att_disconnected()

Nothing requested the connection ("bonding (nil)") and the LE link was
healthy. Any LE association that outlives the page timeout is killed by
it; measured on one host, applications get about 4.7 s from connect
before the link disappears, of which GATT discovery already takes 2.3 s.

Current phones advertise Flags 0x1a (LE General Discoverable plus
Simultaneous LE and BR/EDR, with BR/EDR Not Supported clear) from
resolvable private addresses, so this triggers routinely rather than in
some corner case.

The Flags bits describe what the device supports. They do not promise
that the address it is advertising from is a BD_ADDR. A dual-mode device
uses the same Public Device Address for BR/EDR and LE, so the inference
is sound only for BDADDR_LE_PUBLIC. Restrict it to that.

The other two device_set_bredr_support() callers already require the
device to have been seen over BR/EDR (bdaddr_type == BDADDR_BREDR), so
they are unaffected. A device later seen over BR/EDR, or whose RPA is
resolved to a public identity, still gets BR/EDR support recorded there.

Assisted-by: Claude Code:claude-opus-4-8
---
Verified on a dual-mode controller with ControllerMode=dual, against iOS and
Android peers advertising Flags 0x1a from resolvable private addresses. A GATT
association that includes a ~7 s user prompt, which previously failed every
time at ~4.7 s with the Page Timeout above, now completes:

  before:  connect +0.0s, GATT resolved +2.3s, first exchange +2.7s,
           Page Timeout +4.7s -> LE link destroyed, transfer never completed
  after:   same host, same peers, classic still enabled, transfer completes
           with the user prompt taking 7.0s of it

Setting ControllerMode=le instead of applying the patch also makes the failure
go away, which independently confirms the mechanism: with no classic radio
there is no page to time out. The patch achieves the same without giving up
BR/EDR, and A2DP/HFP continue to work on the host afterwards.

The patch was reviewed line by line and the result above reproduced on real
hardware by the author, not inferred. make is clean with no new warnings in
src/adapter.c, and make check passes 39/39.

No unit test is included: src/adapter.c is linked only into bluetoothd and not
into any unit test target, so btd_adapter_device_found() cannot be exercised by
the existing harness. Extracting the check into a unit-testable helper looked
like scope creep for a bug fix, but I am happy to add that if preferred.
 src/adapter.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/src/adapter.c b/src/adapter.c
index 4ffa32a..30e7679 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -7415,8 +7415,17 @@ void btd_adapter_device_found(struct btd_adapter *adapter,
 	 * older kernels send separate adv_ind and scan_rsp. Newer
 	 * kernels send them merged, so once we know which mgmt version
 	 * supports this we can make the non-zero check conditional.
+	 *
+	 * Only infer BR/EDR support when the LE address is a Public Device
+	 * Address. A dual-mode device uses the same Public Device Address for
+	 * BR/EDR and LE, so in that case the advertised address is also a valid
+	 * BD_ADDR to page. A random address (static, resolvable or
+	 * non-resolvable) has no defined relationship to the device's BD_ADDR,
+	 * so recording BR/EDR support against it makes the device look pageable
+	 * at an address that can never be paged: SDP discovery then fails with
+	 * Page Timeout and takes the working LE link down with it.
 	 */
-	if (bdaddr_type != BDADDR_BREDR && eir_data.flags &&
+	if (bdaddr_type == BDADDR_LE_PUBLIC && eir_data.flags &&
 					!(eir_data.flags & EIR_BREDR_UNSUP)) {
 		device_set_bredr_support(dev);
 		/* Update last seen for BR/EDR in case its flag is set */
-- 
2.55.0


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

* RE: [BlueZ] adapter: Infer BR/EDR only at public LE addresses
  2026-07-16 20:45 [PATCH BlueZ] adapter: Infer BR/EDR only at public LE addresses Philipp Dunkel
@ 2026-07-16 22:20 ` bluez.test.bot
  0 siblings, 0 replies; 2+ messages in thread
From: bluez.test.bot @ 2026-07-16 22:20 UTC (permalink / raw)
  To: linux-bluetooth, pip

[-- Attachment #1: Type: text/plain, Size: 2720 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/project/bluetooth/list/?series=1129094

---Test result---

Test Summary:
CheckPatch                    FAIL      0.30 seconds
GitLint                       FAIL      0.22 seconds
BuildEll                      PASS      20.20 seconds
BluezMake                     PASS      550.48 seconds
CheckSmatch                   PASS      308.97 seconds
bluezmakeextell               PASS      100.80 seconds
IncrementalBuild              PASS      542.15 seconds
ScanBuild                     PASS      958.34 seconds

Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
[BlueZ] adapter: Infer BR/EDR only at public LE addresses
WARNING:COMMIT_LOG_LONG_LINE: Possible unwrapped commit description (prefer a maximum 75 chars per line)
#88: 
  bonding_attempt_complete() hci0 bdaddr 5A:B4:98:1F:CC:04 type 0 status 0x4

WARNING:BAD_SIGN_OFF: Non-standard signature: Assisted-by:
#113: 
Assisted-by: Claude Code:claude-opus-4-8

ERROR:BAD_SIGN_OFF: Unrecognized email address: 'Claude Code:claude-opus-4-8'
#113: 
Assisted-by: Claude Code:claude-opus-4-8

/github/workspace/src/patch/14692154.patch total: 1 errors, 2 warnings, 18 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/patch/14692154.patch has style problems, please review.

NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
[BlueZ] adapter: Infer BR/EDR only at public LE addresses

7: B3 Line contains hard tab characters (\t): "	if (bdaddr_type != BDADDR_BREDR && eir_data.flags &&"
8: B3 Line contains hard tab characters (\t): "				!(eir_data.flags & EIR_BREDR_UNSUP)) {"
9: B3 Line contains hard tab characters (\t): "		device_set_bredr_support(dev);"
15: B3 Line contains hard tab characters (\t): "	if (device->bredr)"
16: B3 Line contains hard tab characters (\t): "		device_browse_sdp(device, NULL);"
17: B3 Line contains hard tab characters (\t): "	else"
18: B3 Line contains hard tab characters (\t): "		device_browse_gatt(device, NULL);"


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

---
Regards,
Linux Bluetooth


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

end of thread, other threads:[~2026-07-16 22:20 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-16 20:45 [PATCH BlueZ] adapter: Infer BR/EDR only at public LE addresses Philipp Dunkel
2026-07-16 22:20 ` [BlueZ] " bluez.test.bot

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