From 73b3a2d18eb6ccfd8b29d7fb3234f084bcc180ef Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Fri, 17 Jul 2026 22:23:08 -0400 Subject: [PATCH 1/9] Convert RFCOMMFlag to native OptionSet --- .../BluetoothLinux/RFCOMM/RFCOMMFlag.swift | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/Sources/BluetoothLinux/RFCOMM/RFCOMMFlag.swift b/Sources/BluetoothLinux/RFCOMM/RFCOMMFlag.swift index 8d405e0..eccfdd1 100644 --- a/Sources/BluetoothLinux/RFCOMM/RFCOMMFlag.swift +++ b/Sources/BluetoothLinux/RFCOMM/RFCOMMFlag.swift @@ -1,6 +1,6 @@ // // File.swift -// +// // // Created by Alsey Coleman Miller on 27/10/21. // @@ -9,10 +9,16 @@ import Bluetooth /// RFCOMM Flags @frozen -public enum RFCOMMFlag: UInt32, CaseIterable, BitMaskOption { - - case reuseDLC = 0x01 // RFCOMM_REUSE_DLC - case releaseOnHangup = 0x02 // RFCOMM_RELEASE_ONHUP - case hangupNow = 0x04 // RFCOMM_HANGUP_NOW - case serialAttached = 0x08 // RFCOMM_TTY_ATTACHED +public struct RFCOMMFlag: OptionSet, Equatable, Hashable, Sendable { + + public let rawValue: UInt32 + + public init(rawValue: UInt32) { + self.rawValue = rawValue + } + + public static let reuseDLC = RFCOMMFlag(rawValue: 0x01) // RFCOMM_REUSE_DLC + public static let releaseOnHangup = RFCOMMFlag(rawValue: 0x02) // RFCOMM_RELEASE_ONHUP + public static let hangupNow = RFCOMMFlag(rawValue: 0x04) // RFCOMM_HANGUP_NOW + public static let serialAttached = RFCOMMFlag(rawValue: 0x08) // RFCOMM_TTY_ATTACHED } From 225bfecc7e7a6a080aeb31ac117b43b80a2830f5 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Fri, 17 Jul 2026 22:23:08 -0400 Subject: [PATCH 2/9] Convert RFCOMMLinkMode to native OptionSet --- .../RFCOMM/RFCOMMLinkMode.swift | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/Sources/BluetoothLinux/RFCOMM/RFCOMMLinkMode.swift b/Sources/BluetoothLinux/RFCOMM/RFCOMMLinkMode.swift index e750232..10484a8 100644 --- a/Sources/BluetoothLinux/RFCOMM/RFCOMMLinkMode.swift +++ b/Sources/BluetoothLinux/RFCOMM/RFCOMMLinkMode.swift @@ -1,6 +1,6 @@ // // RFCOMMLinkMode.swift -// +// // // Created by Alsey Coleman Miller on 27/10/21. // @@ -9,12 +9,18 @@ import Bluetooth /// RFCOMM Link Mode @frozen -public enum RFCOMMLinkMode: UInt16, CaseIterable, BitMaskOption { - - case master = 0x0001 - case authenticated = 0x0002 - case encrypted = 0x0004 - case trusted = 0x0008 - case reliable = 0x0010 - case secure = 0x0020 +public struct RFCOMMLinkMode: OptionSet, Equatable, Hashable, Sendable { + + public let rawValue: UInt16 + + public init(rawValue: UInt16) { + self.rawValue = rawValue + } + + public static let master = RFCOMMLinkMode(rawValue: 0x0001) + public static let authenticated = RFCOMMLinkMode(rawValue: 0x0002) + public static let encrypted = RFCOMMLinkMode(rawValue: 0x0004) + public static let trusted = RFCOMMLinkMode(rawValue: 0x0008) + public static let reliable = RFCOMMLinkMode(rawValue: 0x0010) + public static let secure = RFCOMMLinkMode(rawValue: 0x0020) } From 216a4d9f9adf0d088ecdc5b5cfc22fef8d636ece Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Fri, 17 Jul 2026 22:23:08 -0400 Subject: [PATCH 3/9] Convert HCIDeviceFlag to native OptionSet --- .../BluetoothLinux/HCI/HCIDeviceFlag.swift | 44 +++++++++++++------ 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/Sources/BluetoothLinux/HCI/HCIDeviceFlag.swift b/Sources/BluetoothLinux/HCI/HCIDeviceFlag.swift index eebcc81..424985e 100644 --- a/Sources/BluetoothLinux/HCI/HCIDeviceFlag.swift +++ b/Sources/BluetoothLinux/HCI/HCIDeviceFlag.swift @@ -1,6 +1,6 @@ // // HCIDeviceFlag.swift -// +// // // Created by Alsey Coleman Miller on 16/10/21. // @@ -8,17 +8,33 @@ import Bluetooth /// HCI device flags -public enum HCIDeviceFlag: Int32, BitMaskOption, CaseIterable { - - case up - case initialized - case running - - case passiveScan - case interactiveScan - case authenticated - case encrypt - case inquiry - - case raw +public struct HCIDeviceFlag: OptionSet, Equatable, Hashable, Sendable { + + public let rawValue: UInt32 + + public init(rawValue: UInt32) { + self.rawValue = rawValue + } + + public static let up = HCIDeviceFlag(rawValue: 1 << 0) + public static let initialized = HCIDeviceFlag(rawValue: 1 << 1) + public static let running = HCIDeviceFlag(rawValue: 1 << 2) + + public static let passiveScan = HCIDeviceFlag(rawValue: 1 << 3) + public static let interactiveScan = HCIDeviceFlag(rawValue: 1 << 4) + public static let authenticated = HCIDeviceFlag(rawValue: 1 << 5) + public static let encrypt = HCIDeviceFlag(rawValue: 1 << 6) + public static let inquiry = HCIDeviceFlag(rawValue: 1 << 7) + + public static let raw = HCIDeviceFlag(rawValue: 1 << 8) +} + +public extension HCIDeviceFlag { + + /// All defined HCI device flags. + static let all: HCIDeviceFlag = [ + .up, .initialized, .running, + .passiveScan, .interactiveScan, .authenticated, .encrypt, .inquiry, + .raw + ] } From bcd4d65032da527562953cb6bcfca99fb1d8b531 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Fri, 17 Jul 2026 22:23:08 -0400 Subject: [PATCH 4/9] Use OptionSet API for HCIDeviceOptions flags --- Sources/BluetoothLinux/HCI/HCIDeviceOptions.swift | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/Sources/BluetoothLinux/HCI/HCIDeviceOptions.swift b/Sources/BluetoothLinux/HCI/HCIDeviceOptions.swift index e531437..1fbd7ee 100644 --- a/Sources/BluetoothLinux/HCI/HCIDeviceOptions.swift +++ b/Sources/BluetoothLinux/HCI/HCIDeviceOptions.swift @@ -19,17 +19,11 @@ public struct HCIDeviceOptions: RawRepresentable, Equatable, Hashable { public extension HCIDeviceOptions { - var flags: BitMaskOptionSet { - var options = BitMaskOptionSet() - HCIDeviceFlag.allCases.forEach { - if contains($0) { - options.insert($0) - } - } - return options + var flags: HCIDeviceFlag { + HCIDeviceFlag(rawValue: rawValue).intersection(.all) } - + func contains(_ flag: HCIDeviceFlag) -> Bool { - return (self.rawValue + (UInt32(bitPattern: flag.rawValue) >> 5)) & (1 << (UInt32(bitPattern: flag.rawValue) & 31)) != 0 + HCIDeviceFlag(rawValue: rawValue).isSuperset(of: flag) } } From 76444519065edad88c475299aa8bde23875e9f0f Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Fri, 17 Jul 2026 22:23:08 -0400 Subject: [PATCH 5/9] Convert ScanOption to native OptionSet --- .../BluetoothLinux/HCI/IOCTL/HCIScan.swift | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/Sources/BluetoothLinux/HCI/IOCTL/HCIScan.swift b/Sources/BluetoothLinux/HCI/IOCTL/HCIScan.swift index 6e98a89..6cd4413 100644 --- a/Sources/BluetoothLinux/HCI/IOCTL/HCIScan.swift +++ b/Sources/BluetoothLinux/HCI/IOCTL/HCIScan.swift @@ -28,7 +28,7 @@ public extension HostController { func scan(duration: Int = 8, limit: Int = 255, deviceClass: (UInt8, UInt8, UInt8)? = nil, - options: BitMaskOptionSet = []) throws -> [InquiryResult] { + options: ScanOption = []) throws -> [InquiryResult] { assert(duration > 0, "Scan must be longer than 0 seconds") assert(limit > 0, "Must scan at least one device") @@ -66,12 +66,18 @@ public extension HostController { public extension HostController { /// Options for scanning Bluetooth devices - enum ScanOption: UInt16, BitMaskOption { - - /// The cache of previously detected devices is flushed before performing the current inquiry. - /// Otherwise, if flags is set to 0, then the results of previous inquiries may be returned, + struct ScanOption: OptionSet, Equatable, Hashable, Sendable { + + public let rawValue: UInt16 + + public init(rawValue: UInt16) { + self.rawValue = rawValue + } + + /// The cache of previously detected devices is flushed before performing the current inquiry. + /// Otherwise, if flags is set to 0, then the results of previous inquiries may be returned, /// even if the devices aren't in range anymore. - case flushCache = 0x0001 + public static let flushCache = ScanOption(rawValue: 0x0001) } struct InquiryResult { @@ -108,7 +114,7 @@ public extension HostControllerIO { public var deviceClass: (UInt8, UInt8, UInt8)? - public var options: BitMaskOptionSet + public var options: HostController.ScanOption public private(set) var response: [HostController.InquiryResult] @@ -117,7 +123,7 @@ public extension HostControllerIO { duration: UInt8 = 8, limit: UInt8 = 255, deviceClass: (UInt8, UInt8, UInt8)? = nil, - options: BitMaskOptionSet = [] + options: HostController.ScanOption = [] ) { self.device = device self.duration = duration @@ -183,7 +189,7 @@ internal extension SocketDescriptor { duration: UInt8 = 8, limit: UInt8 = 255, deviceClass: (UInt8, UInt8, UInt8)? = nil, - options: BitMaskOptionSet = [] + options: HostController.ScanOption = [] ) throws -> [HostController.InquiryResult] { var inquiry = HostControllerIO.Inquiry( device: id, From 97020b94c9a6acadb5961d96e4775163ffc3a35f Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Fri, 17 Jul 2026 22:23:08 -0400 Subject: [PATCH 6/9] Adopt RFCOMMFlag OptionSet in RFCOMMDevice --- Sources/BluetoothLinux/RFCOMM/RFCOMMDevice.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/BluetoothLinux/RFCOMM/RFCOMMDevice.swift b/Sources/BluetoothLinux/RFCOMM/RFCOMMDevice.swift index 6cd6ea5..c91e14d 100644 --- a/Sources/BluetoothLinux/RFCOMM/RFCOMMDevice.swift +++ b/Sources/BluetoothLinux/RFCOMM/RFCOMMDevice.swift @@ -14,7 +14,7 @@ public struct RFCOMMDevice: Equatable, Hashable { public let id: HostController.ID - public var flags: BitMaskOptionSet + public var flags: RFCOMMFlag public var state: RFCOMMState From 471f6ee08cf105893e7e71d8e41a2d5593b9a158 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Fri, 17 Jul 2026 22:23:08 -0400 Subject: [PATCH 7/9] Adopt RFCOMMFlag OptionSet in RFCOMMCreateDevice --- .../BluetoothLinux/RFCOMM/IOCTL/RFCOMMCreateDevice.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/BluetoothLinux/RFCOMM/IOCTL/RFCOMMCreateDevice.swift b/Sources/BluetoothLinux/RFCOMM/IOCTL/RFCOMMCreateDevice.swift index a3408ff..28f1e6a 100644 --- a/Sources/BluetoothLinux/RFCOMM/IOCTL/RFCOMMCreateDevice.swift +++ b/Sources/BluetoothLinux/RFCOMM/IOCTL/RFCOMMCreateDevice.swift @@ -28,7 +28,7 @@ public extension RFCOMMIO { @_alwaysEmitIntoClient public init( id: HostController.ID, - flags: BitMaskOptionSet, + flags: RFCOMMFlag, source: BluetoothAddress, destination: BluetoothAddress, channel: UInt8 = 1 @@ -59,7 +59,7 @@ public extension RFCOMMIO.CreateDevice { } @_alwaysEmitIntoClient - var flags: BitMaskOptionSet { + var flags: RFCOMMFlag { return .init(rawValue: bytes.flags) } @@ -87,7 +87,7 @@ internal extension SocketDescriptor { @usableFromInline func rfcommCreateDevice( id: HostController.ID, - flags: BitMaskOptionSet = [], + flags: RFCOMMFlag = [], source: BluetoothAddress, destination: BluetoothAddress, channel: UInt8 = 1 From 5bc9b2853f0c749e0500e94874c589edcff8cb4a Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Fri, 17 Jul 2026 22:23:08 -0400 Subject: [PATCH 8/9] Adopt RFCOMMFlag OptionSet in RFCOMMReleaseDevice --- .../BluetoothLinux/RFCOMM/IOCTL/RFCOMMReleaseDevice.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/BluetoothLinux/RFCOMM/IOCTL/RFCOMMReleaseDevice.swift b/Sources/BluetoothLinux/RFCOMM/IOCTL/RFCOMMReleaseDevice.swift index 3639a9a..b4f4a5e 100644 --- a/Sources/BluetoothLinux/RFCOMM/IOCTL/RFCOMMReleaseDevice.swift +++ b/Sources/BluetoothLinux/RFCOMM/IOCTL/RFCOMMReleaseDevice.swift @@ -28,7 +28,7 @@ public extension RFCOMMIO { @_alwaysEmitIntoClient public init( id: HostController.ID, - flags: BitMaskOptionSet + flags: RFCOMMFlag ) { self.init(CInterop.RFCOMMDeviceRequest( device: id.rawValue, @@ -56,7 +56,7 @@ public extension RFCOMMIO.ReleaseDevice { } @_alwaysEmitIntoClient - var flags: BitMaskOptionSet { + var flags: RFCOMMFlag { return .init(rawValue: bytes.flags) } } @@ -68,7 +68,7 @@ internal extension SocketDescriptor { @usableFromInline func rfcommReleaseDevice( id: HostController.ID, - flags: BitMaskOptionSet = [] + flags: RFCOMMFlag = [] ) throws { var request = RFCOMMIO.ReleaseDevice( id: id, From 6858cceff8460117027ea6ff47a759f48f2e5424 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Fri, 17 Jul 2026 22:23:08 -0400 Subject: [PATCH 9/9] Adopt RFCOMMLinkMode OptionSet in RFCOMMSocketOption --- Sources/BluetoothLinux/RFCOMM/RFCOMMSocketOption.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/BluetoothLinux/RFCOMM/RFCOMMSocketOption.swift b/Sources/BluetoothLinux/RFCOMM/RFCOMMSocketOption.swift index 7ce8098..9a007ce 100644 --- a/Sources/BluetoothLinux/RFCOMM/RFCOMMSocketOption.swift +++ b/Sources/BluetoothLinux/RFCOMM/RFCOMMSocketOption.swift @@ -64,9 +64,9 @@ public extension RFCOMMSocketOption { @_alwaysEmitIntoClient public static var id: RFCOMMSocketOption { .connectionInfo } - public var linkMode: BitMaskOptionSet + public var linkMode: RFCOMMLinkMode - public init(linkMode: BitMaskOptionSet = []) { + public init(linkMode: RFCOMMLinkMode = []) { self.linkMode = linkMode }