feat: Intel BT firmware download, A2dp & Bluetooth audio progress

This commit is contained in:
daniel committed 2026-06-03 18:05:17 +02:00
1 parent ee6d1a388e
commit 0f16785c9f
22 files changed
+6452 -273

No files matched your search

+124 -9
View File
@@ -25,6 +25,15 @@ namespace Drivers::USB::Bluetooth::L2cap {
static bool g_initialized = false;
static uint8_t g_sigIdentifier = 1;
// Diagnostic: result of the most recent L2CAP Connection Response we got for
// an outgoing connection (0=success, 1=pending, 2=PSM-unsupported,
// 3=security-block, 4=no-resources). 0xFFFF = none received yet.
static volatile uint16_t g_lastConnRspResult = 0xFFFF;
// Diagnostic: how many incoming AVDTP connection requests the remote has
// made (tells us whether the headset wants to initiate the audio channel).
static volatile uint16_t g_incomingAvdtpReqs = 0;
// Channel table
static ChannelInfo g_channels[MAX_CHANNELS] = {};
static uint16_t g_nextCid = CID_DYNAMIC_START;
@@ -116,14 +125,24 @@ namespace Drivers::USB::Bluetooth::L2cap {
if (l2len + sizeof(L2capHeader) > len) return;
if (cid == CID_SIGNALING) {
// L2CAP signaling channel
if (l2len < sizeof(SignalHeader)) return;
// L2CAP signaling channel. One packet may carry MULTIPLE commands
// back to back -- a headset commonly bundles its Config Response
// (to our request) with its own Config Request in a single packet.
// Loop over all of them, or we'd handle one and silently drop the
// rest (which left our channel half-configured: localCfg=0).
uint16_t sOff = 0;
while (sOff + sizeof(SignalHeader) <= l2len) {
auto* sig = (const SignalHeader*)(payload + sOff);
const uint8_t* sigPayload = payload + sOff + sizeof(SignalHeader);
uint16_t sigPayloadLen = sig->Length;
// Clamp (don't bail) so a length that doesn't exactly match the
// packet never skips this command -- the cases bounds-check their
// own reads. Advancing by the clamped length ends the loop after
// the last real command.
uint16_t avail = (uint16_t)(l2len - sOff - sizeof(SignalHeader));
if (sigPayloadLen > avail) sigPayloadLen = avail;
auto* sig = (const SignalHeader*)payload;
const uint8_t* sigPayload = payload + sizeof(SignalHeader);
uint16_t sigPayloadLen = sig->Length;
switch (sig->Code) {
switch (sig->Code) {
case SIG_CONN_REQ: {
if (sigPayloadLen >= 4) {
uint16_t psm = (uint16_t)sigPayload[0] | ((uint16_t)sigPayload[1] << 8);
@@ -134,6 +153,7 @@ namespace Drivers::USB::Bluetooth::L2cap {
// Accept connections for AVDTP
if (psm == PSM_AVDTP || psm == PSM_SDP) {
if (psm == PSM_AVDTP) g_incomingAvdtpReqs++;
auto* ch = AllocChannel(psm);
if (ch) {
ch->RemoteCid = srcCid;
@@ -147,6 +167,17 @@ namespace Drivers::USB::Bluetooth::L2cap {
rsp[4] = 0; rsp[5] = 0; // Result: success
rsp[6] = 0; rsp[7] = 0; // Status: no info
SendSignal(SIG_CONN_RSP, sig->Identifier, rsp, 8);
// As the acceptor we must ALSO send our own
// Configuration Request -- otherwise our side
// never reaches LocalConfigDone and the channel
// never becomes Configured (OnChannelReady never
// fires). Address the remote's CID.
uint8_t cfgReq[4] = {};
cfgReq[0] = (uint8_t)(srcCid & 0xFF);
cfgReq[1] = (uint8_t)(srcCid >> 8);
cfgReq[2] = 0; cfgReq[3] = 0; // Flags
SendSignal(SIG_CONFIG_REQ, g_sigIdentifier++, cfgReq, 4);
}
} else {
// Reject: PSM not supported
@@ -167,9 +198,15 @@ namespace Drivers::USB::Bluetooth::L2cap {
uint16_t dstCid = (uint16_t)sigPayload[0] | ((uint16_t)sigPayload[1] << 8);
uint16_t srcCid = (uint16_t)sigPayload[2] | ((uint16_t)sigPayload[3] << 8);
uint16_t result = (uint16_t)sigPayload[4] | ((uint16_t)sigPayload[5] << 8);
// Status (bytes 6-7) explains a PENDING (result=1): 0=no
// info, 1=authentication pending, 2=authorization pending.
uint16_t status = (sigPayloadLen >= 8)
? ((uint16_t)sigPayload[6] | ((uint16_t)sigPayload[7] << 8)) : 0;
g_lastConnRspResult = result;
KernelLogStream(INFO, "BT-L2CAP") << "Connection Response: dstCID="
<< base::hex << (uint64_t)dstCid << " result=" << (uint64_t)result;
<< base::hex << (uint64_t)dstCid << " result=" << (uint64_t)result
<< " status=" << (uint64_t)status << base::dec;
if (result == CONN_SUCCESS) {
// Find our channel by srcCid (which is our local CID)
@@ -239,12 +276,29 @@ namespace Drivers::USB::Bluetooth::L2cap {
case SIG_CONFIG_RSP: {
if (sigPayloadLen >= 6) {
// The Config Response's first field is the "Source CID".
// In a RECEIVED Config Response it echoes back OUR local
// channel endpoint (the device that sent the Config
// Request -- us), NOT the remote's CID -- exactly like the
// SIG_CONN_RSP handler above matches srcCid to LocalCid.
// Matching RemoteCid here was THE bug that pinned every
// AVDTP channel at localCfg=0: a success Config Response
// arrived but matched no channel, so LocalConfigDone never
// got set and the channel never became Configured.
uint16_t srcCid = (uint16_t)sigPayload[0] | ((uint16_t)sigPayload[1] << 8);
uint16_t result = (uint16_t)sigPayload[4] | ((uint16_t)sigPayload[5] << 8);
if (result != CFG_SUCCESS) {
KernelLogStream(WARNING, "BT-L2CAP") << "Config Response result="
<< base::hex << (uint64_t)result << base::dec
<< " (our config rejected)";
}
if (result == CFG_SUCCESS) {
bool matched = false;
for (int i = 0; i < MAX_CHANNELS; i++) {
if (g_channels[i].Active && g_channels[i].RemoteCid == srcCid) {
if (g_channels[i].Active && g_channels[i].LocalCid == srcCid) {
matched = true;
g_channels[i].LocalConfigDone = true;
if (g_channels[i].LocalConfigDone && g_channels[i].RemoteConfigDone) {
g_channels[i].Configured = true;
@@ -258,6 +312,11 @@ namespace Drivers::USB::Bluetooth::L2cap {
break;
}
}
if (!matched) {
KernelLogStream(WARNING, "BT-L2CAP")
<< "Config Response (success) for unknown CID="
<< base::hex << (uint64_t)srcCid << base::dec;
}
}
}
break;
@@ -312,6 +371,8 @@ namespace Drivers::USB::Bluetooth::L2cap {
default:
break;
}
sOff += sizeof(SignalHeader) + sigPayloadLen;
}
} else {
// Data on a dynamic channel
@@ -319,6 +380,8 @@ namespace Drivers::USB::Bluetooth::L2cap {
if (g_channels[i].Active && g_channels[i].LocalCid == cid) {
if (g_channels[i].Psm == PSM_AVDTP) {
A2dp::ProcessAvdtp(payload, l2len);
} else if (g_channels[i].Psm == PSM_SDP) {
A2dp::ProcessSdp(payload, l2len);
}
break;
}
@@ -333,6 +396,8 @@ namespace Drivers::USB::Bluetooth::L2cap {
uint16_t Connect(uint16_t psm) {
if (!g_initialized) return 0;
g_lastConnRspResult = 0xFFFF; // reset diagnostic for this attempt
auto* ch = AllocChannel(psm);
if (!ch) return 0;
@@ -356,6 +421,7 @@ namespace Drivers::USB::Bluetooth::L2cap {
while (Timekeeping::GetMilliseconds() - start < timeoutMs) {
Xhci::PollEvents();
Hci::DrainEvents(); // process incoming ACL (the Connection Response!)
auto* ch = GetChannel(localCid);
if (ch && ch->Configured) return true;
@@ -406,6 +472,36 @@ namespace Drivers::USB::Bluetooth::L2cap {
return nullptr;
}
bool FreeChannel(uint16_t localCid) {
// Reclaim a channel slot from a failed/abandoned dial during A2DP
// bring-up retries. Two cases:
// - RemoteCid == 0: the remote never acknowledged our CONN_REQ (ignored,
// or answered only with a stuck PENDING that never completed), so its
// side was never created and no Disconnect is owed -- just free it.
// - RemoteCid != 0: a CONN_RSP success arrived (the peer allocated its
// CID) but the channel never finished configuring, so the peer holds a
// half-open channel. Send it a Disconnect Request before freeing, or
// BOTH our slot leaks (the old RemoteCid==0-only guard left it Active)
// AND the peer keeps a dangling channel.
// We deliberately do NOT reset g_nextCid, so a late response for this
// (now freed) CID matches nothing rather than cross-wiring the retry.
for (int i = 0; i < MAX_CHANNELS; i++) {
if (g_channels[i].Active && g_channels[i].LocalCid == localCid) {
if (g_channels[i].RemoteCid != 0) {
uint8_t req[4] = {};
req[0] = (uint8_t)(g_channels[i].RemoteCid & 0xFF);
req[1] = (uint8_t)(g_channels[i].RemoteCid >> 8);
req[2] = (uint8_t)(g_channels[i].LocalCid & 0xFF);
req[3] = (uint8_t)(g_channels[i].LocalCid >> 8);
SendSignal(SIG_DISCONN_REQ, g_sigIdentifier++, req, 4);
}
g_channels[i].Active = false;
return true;
}
}
return false;
}
ChannelInfo* FindChannelByPsm(uint16_t psm) {
for (int i = 0; i < MAX_CHANNELS; i++) {
if (g_channels[i].Active && g_channels[i].Psm == psm) {
@@ -415,8 +511,27 @@ namespace Drivers::USB::Bluetooth::L2cap {
return nullptr;
}
uint16_t FindConfiguredAvdtpChannelExcept(uint16_t exceptCid) {
for (int i = 0; i < MAX_CHANNELS; i++) {
if (g_channels[i].Active && g_channels[i].Configured
&& g_channels[i].Psm == PSM_AVDTP
&& g_channels[i].LocalCid != exceptCid) {
return g_channels[i].LocalCid;
}
}
return 0;
}
uint16_t GetAclHandle() {
return g_aclHandle;
}
uint16_t LastConnRspResult() {
return g_lastConnRspResult;
}
uint16_t IncomingAvdtpReqCount() {
return g_incomingAvdtpReqs;
}
}