Skip to content

Skip Master-role unpair to avoid blocking the HCI management channel - #1

Open
vkolotov wants to merge 1 commit into
sgothel:masterfrom
vkolotov:directbt-no-unpair-fix
Open

Skip Master-role unpair to avoid blocking the HCI management channel#1
vkolotov wants to merge 1 commit into
sgothel:masterfrom
vkolotov:directbt-no-unpair-fix

Conversation

@vkolotov

Copy link
Copy Markdown
Contributor

When acting as a Master/Central, Direct-BT issues a management UNPAIR_DEVICE command in two places: on every disconnect (BTDevice::unpair via notifyDisconnected) and for every newly discovered device (BTAdapter::mgmtEvDeviceFoundHCI). In a busy RF environment with several nearby BLE devices, those management commands frequently time out (around 10 seconds each) and block the single HCI management channel. While the channel is blocked, GATT reads on the actually connected device stall, and the read timeout then forces a disconnect. The device also re-bonds on every reconnect, adding churn.

The comment in the slave_unpair block explains that unpair is needed in SC mode (or with key pre-pairing) so the peripheral does not fail the DHKey check. That reasoning applies to the Slave/peripheral role. As a Master connecting to a peripheral it does not, so the unconditional unpair is unnecessary work there.

This change guards both unpair sites with BTRole::Master. When we are the Master we skip the management round trip and keep only the local SMP state cleanup (clearSMPStates). The Slave path is unchanged.

Effect in testing: with this change a CSR BT4 adapter talking to an nRF peripheral went from a read stall and disconnect roughly every 47 seconds to fully stable. Wire captures (btmon) showed 61 of 61 and 45 of 45 ATT reads answered with zero host disconnects, matching the in kernel BlueZ stack on the same hardware. Confirmed on both a CSR BT4 and a Realtek BT5 adapter.

Scope: two files, BTDevice.cpp and BTAdapter.cpp, both guarded so only the Master role behavior changes.

In Master role, unpairDevice() is issued on every disconnect and for every
newly discovered device. Each mgmt UNPAIR_DEVICE can time out (around 10s)
and block the single HCI management channel, which stalls GATT traffic on
the connected device. The unpair is only required for the Slave SC DHKey
path, so guard both call sites with BTRole::Master and keep just the local
SMP state cleanup for Masters.
@vkolotov
vkolotov force-pushed the directbt-no-unpair-fix branch from 10cb1a0 to ba510d8 Compare June 25, 2026 20:35
@vkolotov
vkolotov marked this pull request as ready for review June 25, 2026 20:36
@sgothel

sgothel commented Jun 26, 2026

Copy link
Copy Markdown
Owner

Thank you Vlad, will check this later. Great stuff.
Edit: Looks good, will test next days.

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.

2 participants