Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions Sources/BluetoothLinux/Internal/CInterop.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
28 changes: 27 additions & 1 deletion Sources/BluetoothLinux/L2CAP/L2CAPSocket.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down