Skip to content

Commit

Permalink
#139 Add OptionSet conformance to GAPFlags
Browse files Browse the repository at this point in the history
  • Loading branch information
colemancda committed Nov 6, 2024
1 parent 57095e8 commit 0056f05
Showing 1 changed file with 60 additions and 75 deletions.
135 changes: 60 additions & 75 deletions Sources/BluetoothGAP/GAPFlags.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,47 @@

import Bluetooth

/// GAP Flag
/**
GAP Flag

The Flags data type contains one bit Boolean flags. The Flags data type shall be included when any of the Flag bits are non-zero and the advertising packet is connectable, otherwise the Flags data type may be omitted. All 0x00 octets after the last non-zero octet shall be omitted from the value transmitted.

- Note: If the Flags AD type is not present in a non-connectable advertisement, the Flags should be considered as unknown and no assumptions should be made by the scanner.

Flags used over the LE physical channel are:

• Limited Discoverable Mode

• General Discoverable Mode

• BR/EDR Not Supported

• Simultaneous LE and BR/EDR to Same Device Capable (Controller)

• Simultaneous LE and BR/EDR to Same Device Capable (Host)

The LE Limited Discoverable Mode and LE General Discoverable Mode flags shall be ignored when received over the BR/EDR physical channel. The ‘BR/ EDR Not Supported’ flag shall be set to 0 when sent over the BR/EDR physical channel.

The Flags field may be zero or more octets long. This allows the Flags field to be extended while using the minimum number of octets within the data packet.
*/
@frozen
public struct GAPFlags: GAPData, Equatable, Hashable {
public struct GAPFlags: GAPData, Equatable, Hashable, OptionSet, Sendable {

public static var dataType: GAPDataType { .flags }

public var flags: BitMaskOptionSet<GAPFlag>
public var rawValue: UInt8

public init(flags: BitMaskOptionSet<GAPFlag> = 0) {
self.flags = flags
public init(rawValue: UInt8) {
self.rawValue = rawValue
}
}

public extension GAPFlags {

init?<Data>(data: Data) where Data : Bluetooth.DataContainer {

guard data.count == 1
else { return nil }

self.flags = BitMaskOptionSet<GAPFlag>(rawValue: data[0])
self.init(rawValue: data[0])
}

func append<Data>(to data: inout Data) where Data : Bluetooth.DataContainer {
Expand All @@ -45,65 +65,26 @@ public extension GAPFlags {
extension GAPFlags: DataConvertible {

static func += <T: DataContainer> (data: inout T, value: GAPFlags) {
data += value.flags.rawValue
}
}

// MARK: - CustomStringConvertible

extension GAPFlags: CustomStringConvertible {

public var description: String {
return flags.description
data += value.rawValue
}
}

// MARK: - ExpressibleByIntegerLiteral

extension GAPFlags: ExpressibleByIntegerLiteral {

public init(integerLiteral rawValue: GAPFlag.RawValue) {
self.init(flags: BitMaskOptionSet<GAPFlag>(rawValue: rawValue))
public init(integerLiteral rawValue: RawValue) {
self.init(rawValue: rawValue)
}
}

// MARK: - ExpressibleByArrayLiteral

extension GAPFlags: ExpressibleByArrayLiteral {

public init(arrayLiteral elements: GAPFlag...) {

self.init(flags: BitMaskOptionSet<GAPFlag>(elements))
}
}

// MARK: - Supporting Types
extension GAPFlags: ExpressibleByArrayLiteral { }

/**
GAP Flag

The Flags data type contains one bit Boolean flags. The Flags data type shall be included when any of the Flag bits are non-zero and the advertising packet is connectable, otherwise the Flags data type may be omitted. All 0x00 octets after the last non-zero octet shall be omitted from the value transmitted.

- Note: If the Flags AD type is not present in a non-connectable advertisement, the Flags should be considered as unknown and no assumptions should be made by the scanner.

Flags used over the LE physical channel are:

• Limited Discoverable Mode

• General Discoverable Mode

• BR/EDR Not Supported

• Simultaneous LE and BR/EDR to Same Device Capable (Controller)

• Simultaneous LE and BR/EDR to Same Device Capable (Host)

The LE Limited Discoverable Mode and LE General Discoverable Mode flags shall be ignored when received over the BR/EDR physical channel. The ‘BR/ EDR Not Supported’ flag shall be set to 0 when sent over the BR/EDR physical channel.

The Flags field may be zero or more octets long. This allows the Flags field to be extended while using the minimum number of octets within the data packet.
*/
// MARK: - Constants

public enum GAPFlag: UInt8, BitMaskOption {
public extension GAPFlags {

/**
LE Limited Discoverable Mode
Expand All @@ -112,47 +93,51 @@ public enum GAPFlag: UInt8, BitMaskOption {

- SeeAlso: [Bluetooth Advertising Works](https://blog.bluetooth.com/advertising-works-part-2)
*/
case lowEnergyLimitedDiscoverableMode = 0b00000001
static var lowEnergyLimitedDiscoverableMode: GAPFlags { 0b00000001 }

/// LE General Discoverable Mode
///
/// Use general discoverable mode to advertise indefinitely.
case lowEnergyGeneralDiscoverableMode = 0b00000010
static var lowEnergyGeneralDiscoverableMode: GAPFlags { 0b00000010 }

/// BR/EDR Not Supported.
///
/// Bit 37 of LMP Feature Mask Definitions (Page 0)
case notSupportedBREDR = 0b00000100
static var notSupportedBREDR: GAPFlags { 0b00000100 }

/// Simultaneous LE and BR/EDR to Same Device Capable (Controller).
///
/// Bit 49 of LMP Feature Mask Definitions (Page 0)
case simultaneousController = 0b00001000
static var simultaneousController: GAPFlags { 0b00001000 }

/// Simultaneous LE and BR/EDR to Same Device Capable (Host).
///
/// Bit 66 of LMP Feature Mask Definitions (Page 1)
case simultaneousHost = 0b00010000

public static let allCases: [GAPFlag] = [
.lowEnergyLimitedDiscoverableMode,
.lowEnergyGeneralDiscoverableMode,
.notSupportedBREDR,
.simultaneousController,
.simultaneousHost
]
static var simultaneousHost: GAPFlags { 0b00010000 }
}

extension GAPFlag: CustomStringConvertible {
// MARK: - CustomStringConvertible

extension GAPFlags: CustomStringConvertible, CustomDebugStringConvertible {

#if hasFeature(Embedded)
public var description: String {
rawValue.description
}
#else
@inline(never)
public var description: String {

switch self {
case .lowEnergyLimitedDiscoverableMode: return "LE Limited Discoverable Mode"
case .lowEnergyGeneralDiscoverableMode: return "LE General Discoverable Mode"
case .notSupportedBREDR: return "BR/EDR Not Supported"
case .simultaneousController: return "Simultaneous LE and BR/EDR Controller"
case .simultaneousHost: return "Simultaneous LE and BR/EDR Host"
}
let descriptions: [(GAPFlags, StaticString)] = [
(.lowEnergyLimitedDiscoverableMode, ".lowEnergyLimitedDiscoverableMode"),
(.lowEnergyGeneralDiscoverableMode, ".lowEnergyGeneralDiscoverableMode"),
(.notSupportedBREDR, ".notSupportedBREDR"),
(.simultaneousController, ".simultaneousController"),
(.simultaneousHost, ".simultaneousHost")
]
return buildDescription(descriptions)
}
#endif

/// A textual representation of the file permissions, suitable for debugging.
public var debugDescription: String { self.description }
}

0 comments on commit 0056f05

Please sign in to comment.