feat: reliable Bluetooth pairing, reconnection, and A2DP setup
Four fixes, each a root cause verified on hardware (AX211 + Bose QC Ultra):
1. Link Key Request Reply TRUNCATED: the pending-command queue's params
buffer was 16 bytes; the reply is 22 (addr 6 + key 16). The controller
got 10 key bytes -> every stored-key reconnection failed authentication
(status 5) since 2026-06-03 (0f16785). Fresh pairings never touch this
path, which kept the bug perfectly disguised as a headset quirk.
2. Secure Connections host support (0x0C7A) now enabled: bonds are minted
as P-256 (Type=7), interoperable with BlueZ's, and SC-bonded peers can
actually authenticate us.
3. Never write the BD_ADDR override (0xFC31) with the factory address:
it desyncs the firmware's crypto address from the on-air one and ALL
SSP pairing fails with status 5. (The spoofing feature itself was
already known-cosmetic: the baseband answers pages on the factory
address regardless.) import-bluez-bond.sh now removes the override.
4. A2DP channel setup: wait for Encryption Change before dialing L2CAP
(post-SSP sinks ignore unencrypted CONN_REQ), and LISTEN 2.5s first --
on reconnection the sink dials AVDTP itself and ignores our dials while
doing so. Ends the historical connRsp=FFFF retry-then-give-up failures.
Plus: queued security replies now log delivery + controller status.
Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
@@ -334,6 +334,18 @@ namespace Drivers::USB::Bluetooth {
|
||||
// Enable Simple Secure Pairing
|
||||
Hci::WriteSSPMode(1);
|
||||
|
||||
// Enable Secure Connections host support (P-256 / AES-CCM). Link
|
||||
// keys are procedure-bound: a bond minted over Secure Connections
|
||||
// (BlueZ always negotiates SC -> key Type=7) CANNOT authenticate a
|
||||
// legacy link -- the controller must fail with status 5. Without
|
||||
// this, a key shared with a Linux install (dual boot, see
|
||||
// scripts/import-bluez-bond.sh) is cryptographically fine yet
|
||||
// unusable, and our own pairings mint legacy P-192 keys that Linux
|
||||
// then silently replaces. Must follow Write SSP Mode.
|
||||
uint8_t scOn = 0x01;
|
||||
Hci::SendCommand(Hci::OP_WRITE_SC_HOST_SUPPORT, &scOn, 1);
|
||||
Hci::WaitCommandComplete(Hci::OP_WRITE_SC_HOST_SUPPORT);
|
||||
|
||||
// Allow role switch + sniff on new connections. The controller default
|
||||
// link policy is 0x0000 (deny both). A multipoint headset (Bose QC
|
||||
// Ultra) that also holds a link to a phone requests a role switch to
|
||||
|
||||
Reference in New Issue
Block a user