From 553647d79594dece5629fa8cfd50725b1b23bc89 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Wed, 28 Oct 2026 16:38:01 -0400 Subject: [PATCH] Fix EINVAL when connecting LE L2CAP client sockets lowEnergyClient set both the ATT PSM and the ATT CID on the destination address. l2cap_sock_connect() rejects an address with both l2_psm and l2_cid set, so every LE GATT connection failed immediately with EINVAL. LE ATT uses the fixed channel (CID 4) with PSM 0. --- Sources/BluetoothLinux/L2CAP/L2CAPSocket.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Sources/BluetoothLinux/L2CAP/L2CAPSocket.swift b/Sources/BluetoothLinux/L2CAP/L2CAPSocket.swift index 95de838..7622271 100755 --- a/Sources/BluetoothLinux/L2CAP/L2CAPSocket.swift +++ b/Sources/BluetoothLinux/L2CAP/L2CAPSocket.swift @@ -117,7 +117,9 @@ public struct L2CAPSocket: Sendable { let destinationSocketAddress = L2CAPSocketAddress( address: destinationAddress, addressType: AddressType(lowEnergy: destinationAddressType), - protocolServiceMultiplexer: .att, + // LE ATT connects over the fixed channel with no PSM; + // the kernel rejects an address with both l2_psm and l2_cid set (EINVAL) + protocolServiceMultiplexer: nil, channel: .att ) let fileDescriptor = try SocketDescriptor.l2cap(localSocketAddress, [.closeOnExec, .nonBlocking])