Skip to content

Send the LE Enhanced Connection Complete event when the host unmasks it - #1025

Merged
zxzxwu merged 1 commit into
google:mainfrom
Thanatos9404:le-enhanced-connection-complete
Nov 5, 2026
Merged

zxzxwu merged 1 commit into
google:mainfrom
Thanatos9404:le-enhanced-connection-complete

Conversation

@Thanatos9404

Copy link
Copy Markdown
Contributor

Fixes #841.

The controller always sent HCI_LE_Connection_Complete_Event, both when it creates a connection as central and when it accepts one as peripheral. It ignored the LE event mask the host sets. Per Vol 4, Part E 7.7.65.1 and 7.7.65.10, only the enhanced event should be sent when the host has unmasked it. The controller advertises LL Privacy by default, so the Linux kernel unmasks and waits for the enhanced event, and connecting through VHCI hits the 20 second timeout described in the issue.

Both places now go through send_le_connection_complete_event:

  • Bit 9 of the LE event mask set: it sends HCI_LE_Enhanced_Connection_Complete_Event, with all-zero resolvable private addresses, which Device already treats as "none".
  • Otherwise: it sends HCI_LE_Connection_Complete_Event, unchanged.

Notes on the behaviour:

  • v1, not v2. v2 is excluded unless Periodic Advertising with Responses is supported (C.69), and the controller doesn't support it. Rootcanal also sends v1.
  • Legacy event not gated on bit 0. The controller starts with le_event_mask = 0 rather than the spec default 0x1F, so gating it would leave hosts that never set the mask with no event at all.
  • Out of scope: LE Create Connection Cancel still sends no completion event. That is a separate, existing issue.

test_le_connection_complete_event_follows_le_event_mask in tests/device_test.py sets the LE event mask on two devices, connects them, and checks the event type, role and peer address each controller sends. With the enhanced bit set it fails on main and passes with this change. Bumble's own Host unmasks the enhanced event, so the other device tests now exchange it end to end, and they still pass.

The controller always sent LE Connection Complete, even when the host
had unmasked LE Enhanced Connection Complete, so a host such as Linux,
which expects the enhanced event when LL Privacy is supported, waited
until its connection timeout. Send the v1 enhanced event when bit 9 of
the LE event mask is set, and the legacy event otherwise.

Fixes google#841
@zxzxwu zxzxwu closed this Nov 5, 2026
@zxzxwu zxzxwu reopened this Nov 5, 2026
@zxzxwu
zxzxwu merged commit 8c0df84 into google:main Nov 5, 2026
65 of 66 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HCI_LE_Connection_Complete_Event is sent when HCI_LE_Enhanced_Connection_Complete should be sent.

2 participants