diff --git a/Sources/BluetoothLinux/Internal/CInterop.swift b/Sources/BluetoothLinux/Internal/CInterop.swift index b5ed39e..bddf54c 100644 --- a/Sources/BluetoothLinux/Internal/CInterop.swift +++ b/Sources/BluetoothLinux/Internal/CInterop.swift @@ -589,8 +589,15 @@ internal extension CInterop.HCIFilterSocketOption { @usableFromInline mutating func setEvent(_ event: UInt8) { - let bit = (CInt(event) & 63) - HCISetBit(bit, &eventMask.0) + // Events 0-31 use eventMask.0, events 32-63 use eventMask.1 + // Bug fix: was always using eventMask.0 even for events >= 32 + if event >= 32 { + let bit = CInt(event) - 32 + HCISetBit(bit, &eventMask.1) + } else { + let bit = CInt(event) + HCISetBit(bit, &eventMask.0) + } } @usableFromInline diff --git a/Sources/BluetoothLinux/L2CAP/L2CAPSocket.swift b/Sources/BluetoothLinux/L2CAP/L2CAPSocket.swift index 576682f..95de838 100755 --- a/Sources/BluetoothLinux/L2CAP/L2CAPSocket.swift +++ b/Sources/BluetoothLinux/L2CAP/L2CAPSocket.swift @@ -121,7 +121,33 @@ public struct L2CAPSocket: Sendable { channel: .att ) let fileDescriptor = try SocketDescriptor.l2cap(localSocketAddress, [.closeOnExec, .nonBlocking]) - try? fileDescriptor.connect(to: destinationSocketAddress) // ignore result, async socket always throws + + // Start async connect - for non-blocking sockets this returns EINPROGRESS + do { + try fileDescriptor.connect(to: destinationSocketAddress) + } catch Errno.nowInProgress { + // Expected for non-blocking socket - connection is in progress + // Wait for socket to become writable (indicates connect completed) + let timeout: Int = 30_000 // 30 seconds in milliseconds + let events = try fileDescriptor.poll(for: [.write, .error, .hangup], timeout: timeout) + + // Check for errors + if events.contains(.error) || events.contains(.hangup) { + try? fileDescriptor.close() + throw Errno.connectionRefused + } + + // Check if we timed out (no events returned) + if !events.contains(.write) { + try? fileDescriptor.close() + throw Errno.timedOut + } + } catch { + // Other errors during connect + try? fileDescriptor.close() + throw error + } + return Self.init(fileDescriptor: fileDescriptor, address: localSocketAddress) }