From 75f9f5362cc3bafd05840e03e3c1fbe0d1290217 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Sun, 28 Feb 2016 14:03:28 -0500 Subject: [PATCH 01/18] refactored project MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removed “Bluetooth” namespace and made unit tests separate command line tools --- Sources/BlueZ/Adapter.swift | 9 +- Sources/BlueZ/Address.swift | 32 ++-- Sources/BlueZ/Bluetooth.swift | 25 --- Sources/BlueZ/Darwin.swift | 17 ++ Sources/BlueZ/DeviceCommand.swift | 2 +- Sources/BlueZ/DeviceRequest.swift | 4 +- Sources/BlueZ/Error.swift | 9 +- Sources/BlueZ/HCICommand.swift | 6 +- Sources/BlueZ/HCIError.swift | 75 ++++---- Sources/BlueZ/LinkControlCommand.swift | 165 +++++++++--------- Sources/BlueZ/LinkMode.swift | 19 +- Sources/BlueZ/LowEnergyAddressType.swift | 2 +- Sources/BlueZ/LowEnergyCommand.swift | 79 ++++----- Sources/BlueZ/LowEnergyCommandParameter.swift | 4 +- Sources/BlueZ/LowEnergyEvent.swift | 1 - Sources/BlueZ/OpcodeCommandField.swift | 5 +- Sources/BlueZ/OpcodeGroupField.swift | 55 +++--- Sources/BlueZ/Scan.swift | 6 +- Sources/BlueZ/iBeacon.swift | 23 ++- .../{UnitTests => ScanTest}/ScanTest.swift | 2 +- .../{UnitTests => ScanTest}/TestError.swift | 0 Sources/ScanTest/main.swift | 30 ++++ Sources/iBeaconTest/TestError.swift | 22 +++ .../iBeaconTest.swift | 2 +- Sources/{UnitTests => iBeaconTest}/main.swift | 10 +- Xcode/BlueZ.xcodeproj/project.pbxproj | 77 +++++--- 26 files changed, 350 insertions(+), 331 deletions(-) delete mode 100644 Sources/BlueZ/Bluetooth.swift create mode 100644 Sources/BlueZ/Darwin.swift rename Sources/{UnitTests => ScanTest}/ScanTest.swift (95%) rename Sources/{UnitTests => ScanTest}/TestError.swift (100%) create mode 100644 Sources/ScanTest/main.swift create mode 100644 Sources/iBeaconTest/TestError.swift rename Sources/{UnitTests => iBeaconTest}/iBeaconTest.swift (92%) rename Sources/{UnitTests => iBeaconTest}/main.swift (77%) diff --git a/Sources/BlueZ/Adapter.swift b/Sources/BlueZ/Adapter.swift index 6de0543..4a55c0f 100644 --- a/Sources/BlueZ/Adapter.swift +++ b/Sources/BlueZ/Adapter.swift @@ -13,13 +13,8 @@ import Darwin.C #endif -public extension Bluetooth { - - typealias Adapter = BluetoothAdapter -} - /// Manages connection / communication to the underlying Bluetooth hardware. -public final class BluetoothAdapter { +public final class Adapter { // MARK: - Properties @@ -40,7 +35,7 @@ public final class BluetoothAdapter { /// Initializes the Bluetooth Adapter with the specified address. /// /// If no address is specified then it tries to intialize the first Bluetooth adapter. - public init?(address: Bluetooth.Address? = nil) { + public init?(address: Address? = nil) { // get device ID let addressPointer = UnsafeMutablePointer.alloc(1) diff --git a/Sources/BlueZ/Address.swift b/Sources/BlueZ/Address.swift index 4163dbe..5eb83ab 100644 --- a/Sources/BlueZ/Address.swift +++ b/Sources/BlueZ/Address.swift @@ -20,16 +20,11 @@ import SwiftFoundation /// Bluetooth Address type. /// /// Typealias for `bdaddr_t` from the BlueZ C API. -public typealias BluetoothAddress = bdaddr_t - -public extension Bluetooth { - - typealias Address = BluetoothAddress -} +public typealias Address = bdaddr_t // MARK: - ByteValue -extension Bluetooth.Address: ByteValueType { +extension Address: ByteValueType { /// Raw Bluetooth Address 6 byte (48 bit) value. public typealias ByteValue = (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8) @@ -53,16 +48,15 @@ extension Bluetooth.Address: ByteValueType { // MARK: - RawRepresentable -extension Bluetooth.Address: RawRepresentable { +extension Address: RawRepresentable { public init?(rawValue: String) { - let resultPointer = UnsafeMutablePointer.alloc(1) - defer { resultPointer.dealloc(1) } + var address = bdaddr_t() - guard str2ba(rawValue, resultPointer) == 0 else { return nil } + guard str2ba(rawValue, &address) == 0 else { return nil } - self = resultPointer.memory + self = address } public var rawValue: String { @@ -82,9 +76,9 @@ extension Bluetooth.Address: RawRepresentable { // MARK: - Equatable -extension Bluetooth.Address: Equatable { } +extension Address: Equatable { } -public func == (lhs: Bluetooth.Address, rhs: Bluetooth.Address) { +public func == (lhs: Address, rhs: Address) { var copy1 = lhs var copy2 = rhs @@ -94,14 +88,14 @@ public func == (lhs: Bluetooth.Address, rhs: Bluetooth.Address) { // MARK: - CustomStringConvertible -extension Bluetooth.Address: CustomStringConvertible { +extension Address: CustomStringConvertible { public var description: String { return rawValue } } // MARK: - Adapter Extensions -public extension Bluetooth.Address { +public extension Address { /// Extracts the Bluetooth address from the device ID. public init?(deviceIdentifier: CInt) { @@ -114,14 +108,14 @@ public extension Bluetooth.Address { } } -public extension BluetoothAdapter { +public extension Adapter { /// Attempts to get the address from the underlying Bluetooth hardware. /// /// Fails if the Bluetooth adapter was disconnected or hardware failure. - public var address: Bluetooth.Address? { + public var address: Address? { - return Bluetooth.Address(deviceIdentifier: deviceIdentifier) + return Address(deviceIdentifier: deviceIdentifier) } } diff --git a/Sources/BlueZ/Bluetooth.swift b/Sources/BlueZ/Bluetooth.swift deleted file mode 100644 index 48609cc..0000000 --- a/Sources/BlueZ/Bluetooth.swift +++ /dev/null @@ -1,25 +0,0 @@ -// -// Bluetooth.swift -// BlueZ -// -// Created by Alsey Coleman Miller on 12/6/15. -// Copyright © 2015 PureSwift. All rights reserved. -// - -#if os(Linux) - import CBlueZ -#endif - -public struct Bluetooth { } - -// MARK: - Darwin - -#if os(OSX) || os(iOS) - - @noreturn - internal func stub() { - - fatalError("Method not implemented. This code only runs on Linux.") - } - -#endif diff --git a/Sources/BlueZ/Darwin.swift b/Sources/BlueZ/Darwin.swift new file mode 100644 index 0000000..c5e047a --- /dev/null +++ b/Sources/BlueZ/Darwin.swift @@ -0,0 +1,17 @@ +// +// Darwin.swift +// BlueZ +// +// Created by Alsey Coleman Miller on 2/28/16. +// Copyright © 2016 PureSwift. All rights reserved. +// + +#if os(OSX) || os(iOS) + + @noreturn + internal func stub() { + + fatalError("Method not implemented. This code only runs on Linux.") + } + +#endif \ No newline at end of file diff --git a/Sources/BlueZ/DeviceCommand.swift b/Sources/BlueZ/DeviceCommand.swift index 5fe35be..aa73163 100644 --- a/Sources/BlueZ/DeviceCommand.swift +++ b/Sources/BlueZ/DeviceCommand.swift @@ -15,7 +15,7 @@ import SwiftFoundation -public extension BluetoothAdapter { +public extension Adapter { /// Sends a command to the device. /// diff --git a/Sources/BlueZ/DeviceRequest.swift b/Sources/BlueZ/DeviceRequest.swift index 6f190d1..9b296ae 100644 --- a/Sources/BlueZ/DeviceRequest.swift +++ b/Sources/BlueZ/DeviceRequest.swift @@ -15,7 +15,7 @@ import SwiftFoundation -public extension BluetoothAdapter { +public extension Adapter { /// Sends a command to the device and waits for a response. No specific event is expected. func deviceRequest(command: Command, parameter: CommandParameter? = nil, timeout: Int = 1000) throws { @@ -55,7 +55,7 @@ public extension BluetoothAdapter { else { throw POSIXError.fromErrorNumber! } } - guard status == 0x00 else { throw Bluetooth.HCIError(rawValue: status)! } + guard status == 0x00 else { throw HCIError(rawValue: status)! } } /* diff --git a/Sources/BlueZ/Error.swift b/Sources/BlueZ/Error.swift index aaffe56..d3762d9 100644 --- a/Sources/BlueZ/Error.swift +++ b/Sources/BlueZ/Error.swift @@ -6,11 +6,8 @@ // Copyright © 2016 PureSwift. All rights reserved. // -public extension Bluetooth { +public enum BlueZError: ErrorType { - public enum Error: ErrorType { - - /// The error status byte used with `deviceRequest()`. - case DeviceRequestStatus(UInt8) - } + /// The error status byte used with `deviceRequest()`. + case DeviceRequestStatus(UInt8) } \ No newline at end of file diff --git a/Sources/BlueZ/HCICommand.swift b/Sources/BlueZ/HCICommand.swift index 6236b3f..525c201 100644 --- a/Sources/BlueZ/HCICommand.swift +++ b/Sources/BlueZ/HCICommand.swift @@ -9,9 +9,9 @@ /// HCI Command that can be send to the Bluetooth Adapter. public protocol HCICommand: RawRepresentable { - static var opcodeGroupField: Bluetooth.OpcodeGroupField { get } + static var opcodeGroupField: OpcodeGroupField { get } - init?(rawValue: Bluetooth.OpcodeCommandField) + init?(rawValue: OpcodeCommandField) - var rawValue: Bluetooth.OpcodeCommandField { get } + var rawValue: OpcodeCommandField { get } } \ No newline at end of file diff --git a/Sources/BlueZ/HCIError.swift b/Sources/BlueZ/HCIError.swift index 15c563b..4aea310 100644 --- a/Sources/BlueZ/HCIError.swift +++ b/Sources/BlueZ/HCIError.swift @@ -6,45 +6,40 @@ // Copyright © 2016 PureSwift. All rights reserved. // -import SwiftFoundation - -public extension Bluetooth { +/// HCI Errors +public enum HCIError: UInt8, ErrorType { + + case UnknownCommand = 0x01 + case NoConnection + case HardwareFailure + case PageTimeout + case AuthenticationFailure + case KeyMissing + case MemoryFull + case ConnectionTimeout + case MaxConnections + case MaxSCOConnections + case ACLConnectionExists + case CommandDisallowed + case RejectedLimitedResources + case RejectedSecurity + case RejectedPersonal + case HostTimeout + case UnsupportedFeature + case InvalidParameters + case OEUserEndedConnection + case OELowResources + case OEPowerOff + case ConnectionTerminated + case RepeatedAttempts + case PairingNotAllowed + + // ... Add More + + case TransactionCollision = 0x2a + case QOSUnacceptableParameter = 0x2c + + // TODO: Add all errors - /// HCI Errors - public enum HCIError: Byte, ErrorType { - - case UnknownCommand = 0x01 - case NoConnection - case HardwareFailure - case PageTimeout - case AuthenticationFailure - case KeyMissing - case MemoryFull - case ConnectionTimeout - case MaxConnections - case MaxSCOConnections - case ACLConnectionExists - case CommandDisallowed - case RejectedLimitedResources - case RejectedSecurity - case RejectedPersonal - case HostTimeout - case UnsupportedFeature - case InvalidParameters - case OEUserEndedConnection - case OELowResources - case OEPowerOff - case ConnectionTerminated - case RepeatedAttempts - case PairingNotAllowed - - // ... Add More - - case TransactionCollision = 0x2a - case QOSUnacceptableParameter = 0x2c - - // TODO: Add all errors - - case HostBusyPairing = 0x38 - } + case HostBusyPairing = 0x38 } diff --git a/Sources/BlueZ/LinkControlCommand.swift b/Sources/BlueZ/LinkControlCommand.swift index 04fecc8..4ab9d19 100644 --- a/Sources/BlueZ/LinkControlCommand.swift +++ b/Sources/BlueZ/LinkControlCommand.swift @@ -6,89 +6,86 @@ // Copyright © 2016 PureSwift. All rights reserved. // -public extension Bluetooth { - - public enum LinkControlCommand: UInt16, HCICommand { - - public static let opcodeGroupField = OpcodeGroupField.LinkControl - - /// Command used to enter Inquiry mode where it discovers other Bluetooth devices. - case Inquiry = 0x0001 - - /// Command to cancel the Inquiry mode in which the Bluetooth device is in. - case InquiryCancel = 0x0002 - - /// Command to set the device to enter Inquiry modes periodically according to the time interval set. - case PeriodicInquiry = 0x0003 - - /// Command to exit the periodic Inquiry mode. - case ExitPeriodicInquiry = 0x0004 - - /// Command to create an ACL connection to the device specified by the BD_ADDR in the parameters. - case CreateConnection = 0x0005 - - /// Command to terminate the existing connection to a device. - case Disconnect = 0x0006 - - /// Create an SCO connection defined by the connection handle parameters. - case AddSCOConnection = 0x0007 - - /// Cancel Create Connection - case CreateConnectionCancel = 0x0008 - - /// Command to accept a new connection request. - case AcceptConnection = 0x0009 - - /// Command to reject a new connection request. - case RejectConnection = 0x000A - - /// Reply command to a link key request event sent from controller to the host. - case LinkKeyReply = 0x000B - - /// Reply command to a link key request event from the controller to the host if there is no link key associated with the connection. - case LinkKeyNegativeReply = 0x000C - - /// Reply command to a PIN code request event sent from a controller to the host. - case PinCodeReply = 0x000D - - /// Reply command to a PIN code request event sent from the controller to the host if there is no PIN associated with the connection. - case PinCodeNegativeReply = 0x000E - - /// Command to change the type of packets to be sent for an existing connection. - case SetConnectionPacketType = 0x000F - - /// Command to establish authentication between two devices specified by the connection handle. - case AuthenticationRequested = 0x0011 - - /// Command to enable or disable the link level encryption. - case SetConnectionEncryption = 0x0013 - - /// Command to force the change of a link key to a new one between two connected devices. - case ChangeConnectionLinkKey = 0x0015 - - /// Command to force two devices to use the master's link key temporarily. - case MasterLinkKey = 0x0017 - - /// Command to determine the user friendly name of the connected device. - case RemoteNameRequest = 0x0019 - - /// Cancels the remote name request. - case RemoteNameRequestCancel = 0x001A - - /// Command to determine the features supported by the connected device. - case ReadRemoteFeatures = 0x001B - - /// Command to determine the extended features supported by the connected device. - case ReadRemoteExtendedFeatures = 0x001C - - /// Command to determine the version information of the connected device. - case ReadRemoteVersion = 0x001D - - /// Command to read the clock offset of the remote device. - case ReadClockOffset = 0x001F - - /// Read LMP Handle - case ReadLMPHandle = 0x0020 - } +public enum LinkControlCommand: UInt16, HCICommand { + + public static let opcodeGroupField = OpcodeGroupField.LinkControl + + /// Command used to enter Inquiry mode where it discovers other Bluetooth devices. + case Inquiry = 0x0001 + + /// Command to cancel the Inquiry mode in which the Bluetooth device is in. + case InquiryCancel = 0x0002 + + /// Command to set the device to enter Inquiry modes periodically according to the time interval set. + case PeriodicInquiry = 0x0003 + + /// Command to exit the periodic Inquiry mode. + case ExitPeriodicInquiry = 0x0004 + + /// Command to create an ACL connection to the device specified by the BD_ADDR in the parameters. + case CreateConnection = 0x0005 + + /// Command to terminate the existing connection to a device. + case Disconnect = 0x0006 + + /// Create an SCO connection defined by the connection handle parameters. + case AddSCOConnection = 0x0007 + + /// Cancel Create Connection + case CreateConnectionCancel = 0x0008 + + /// Command to accept a new connection request. + case AcceptConnection = 0x0009 + + /// Command to reject a new connection request. + case RejectConnection = 0x000A + + /// Reply command to a link key request event sent from controller to the host. + case LinkKeyReply = 0x000B + + /// Reply command to a link key request event from the controller to the host if there is no link key associated with the connection. + case LinkKeyNegativeReply = 0x000C + + /// Reply command to a PIN code request event sent from a controller to the host. + case PinCodeReply = 0x000D + + /// Reply command to a PIN code request event sent from the controller to the host if there is no PIN associated with the connection. + case PinCodeNegativeReply = 0x000E + + /// Command to change the type of packets to be sent for an existing connection. + case SetConnectionPacketType = 0x000F + + /// Command to establish authentication between two devices specified by the connection handle. + case AuthenticationRequested = 0x0011 + + /// Command to enable or disable the link level encryption. + case SetConnectionEncryption = 0x0013 + + /// Command to force the change of a link key to a new one between two connected devices. + case ChangeConnectionLinkKey = 0x0015 + + /// Command to force two devices to use the master's link key temporarily. + case MasterLinkKey = 0x0017 + + /// Command to determine the user friendly name of the connected device. + case RemoteNameRequest = 0x0019 + + /// Cancels the remote name request. + case RemoteNameRequestCancel = 0x001A + + /// Command to determine the features supported by the connected device. + case ReadRemoteFeatures = 0x001B + + /// Command to determine the extended features supported by the connected device. + case ReadRemoteExtendedFeatures = 0x001C + + /// Command to determine the version information of the connected device. + case ReadRemoteVersion = 0x001D + + /// Command to read the clock offset of the remote device. + case ReadClockOffset = 0x001F + + /// Read LMP Handle + case ReadLMPHandle = 0x0020 } diff --git a/Sources/BlueZ/LinkMode.swift b/Sources/BlueZ/LinkMode.swift index 19f03af..a045cbe 100644 --- a/Sources/BlueZ/LinkMode.swift +++ b/Sources/BlueZ/LinkMode.swift @@ -8,16 +8,13 @@ import SwiftFoundation -public extension Bluetooth { +public enum LinkMode: UInt16 { - public enum LinkMode: UInt16 { - - case Accept = 0x8000 - case Master = 0x0001 - case Authenticated = 0x0002 - case Encrypted = 0x0004 - case Trusted = 0x0008 - case Reliable = 0x0010 - case Secure = 0x0020 - } + case Accept = 0x8000 + case Master = 0x0001 + case Authenticated = 0x0002 + case Encrypted = 0x0004 + case Trusted = 0x0008 + case Reliable = 0x0010 + case Secure = 0x0020 } \ No newline at end of file diff --git a/Sources/BlueZ/LowEnergyAddressType.swift b/Sources/BlueZ/LowEnergyAddressType.swift index c3a934a..41cf47b 100644 --- a/Sources/BlueZ/LowEnergyAddressType.swift +++ b/Sources/BlueZ/LowEnergyAddressType.swift @@ -8,7 +8,7 @@ import SwiftFoundation -public extension BluetoothAddress { +public extension Address { public enum LowEnergyAddressType: CInt { diff --git a/Sources/BlueZ/LowEnergyCommand.swift b/Sources/BlueZ/LowEnergyCommand.swift index ef13664..320ffb2 100644 --- a/Sources/BlueZ/LowEnergyCommand.swift +++ b/Sources/BlueZ/LowEnergyCommand.swift @@ -8,46 +8,43 @@ -public extension Bluetooth { +public enum LowEnergyCommand: UInt16, HCICommand { - public enum LowEnergyCommand: UInt16, HCICommand { - - public static let opcodeGroupField = OpcodeGroupField.LowEnergy - - case SetEventMask = 0x0001 - case ReadBufferSize = 0x0002 - case ReadLocalSupportedFeatures = 0x0003 - case SetRandomAddress = 0x0005 - case SetAdvertisingParameters = 0x0006 - case ReadAdvertisingChannelTXPower = 0x0007 - case SetAdvertisingData = 0x0008 - case SetScanResponseData = 0x0009 - case SetAdvertiseEnable = 0x000A - case SetScanParameters = 0x000B - case SetScanEnable = 0x000C - case CreateConnection = 0x000D - case CreateConnectionCancel = 0x000E - case ReadWhiteListSize = 0x000F - case ClearWhiteList = 0x0010 - case AddDeviceToWhiteList = 0x0011 - case RemoveDeviceFromWhiteList = 0x0012 - case ConnectionUpdate = 0x0013 - case SetHostChannelClassification = 0x0014 - case ReadChannelMap = 0x0015 - case ReadRemoteUsedFeatures = 0x0016 - case Encrypt = 0x0017 - case Random = 0x0018 - case StartEncryption = 0x0019 - case LTKReply = 0x001A - case LTKNegativeReply = 0x001B - case ReadSupportedStates = 0x001C - case ReceiverTest = 0x001D - case TransmitterTest = 0x001E - case TestEnd = 0x001F - case AddDeviceToResolvedList = 0x0027 - case RemoveDeviceFromResolvedList = 0x0028 - case ClearResolvedList = 0x0029 - case ReadResolvedListSize = 0x002A - case SetAddressResolutionEnable = 0x002D - } + public static let opcodeGroupField = OpcodeGroupField.LowEnergy + + case SetEventMask = 0x0001 + case ReadBufferSize = 0x0002 + case ReadLocalSupportedFeatures = 0x0003 + case SetRandomAddress = 0x0005 + case SetAdvertisingParameters = 0x0006 + case ReadAdvertisingChannelTXPower = 0x0007 + case SetAdvertisingData = 0x0008 + case SetScanResponseData = 0x0009 + case SetAdvertiseEnable = 0x000A + case SetScanParameters = 0x000B + case SetScanEnable = 0x000C + case CreateConnection = 0x000D + case CreateConnectionCancel = 0x000E + case ReadWhiteListSize = 0x000F + case ClearWhiteList = 0x0010 + case AddDeviceToWhiteList = 0x0011 + case RemoveDeviceFromWhiteList = 0x0012 + case ConnectionUpdate = 0x0013 + case SetHostChannelClassification = 0x0014 + case ReadChannelMap = 0x0015 + case ReadRemoteUsedFeatures = 0x0016 + case Encrypt = 0x0017 + case Random = 0x0018 + case StartEncryption = 0x0019 + case LTKReply = 0x001A + case LTKNegativeReply = 0x001B + case ReadSupportedStates = 0x001C + case ReceiverTest = 0x001D + case TransmitterTest = 0x001E + case TestEnd = 0x001F + case AddDeviceToResolvedList = 0x0027 + case RemoveDeviceFromResolvedList = 0x0028 + case ClearResolvedList = 0x0029 + case ReadResolvedListSize = 0x002A + case SetAddressResolutionEnable = 0x002D } \ No newline at end of file diff --git a/Sources/BlueZ/LowEnergyCommandParameter.swift b/Sources/BlueZ/LowEnergyCommandParameter.swift index cd9e25e..5176b84 100644 --- a/Sources/BlueZ/LowEnergyCommandParameter.swift +++ b/Sources/BlueZ/LowEnergyCommandParameter.swift @@ -95,7 +95,7 @@ extension le_read_advertising_channel_tx_power_rp: HCICommandParameter { #if os(OSX) public struct le_set_advertising_data_cp { public var length: UInt8 - public var data: Bluetooth.LowEnergyAdvertisingData + public var data: LowEnergyAdvertisingData public init() { stub() } } #endif @@ -107,7 +107,7 @@ extension le_set_advertising_data_cp: HCICommandParameter { #if os(OSX) public struct le_set_scan_response_data_cp { public var length: UInt8 - public var data: Bluetooth.LowEnergyAdvertisingData + public var data: LowEnergyAdvertisingData public init() { stub() } } #endif diff --git a/Sources/BlueZ/LowEnergyEvent.swift b/Sources/BlueZ/LowEnergyEvent.swift index 91cca33..d8bf08b 100644 --- a/Sources/BlueZ/LowEnergyEvent.swift +++ b/Sources/BlueZ/LowEnergyEvent.swift @@ -6,4 +6,3 @@ // Copyright © 2016 PureSwift. All rights reserved. // -import Foundation diff --git a/Sources/BlueZ/OpcodeCommandField.swift b/Sources/BlueZ/OpcodeCommandField.swift index 196a24a..493081a 100644 --- a/Sources/BlueZ/OpcodeCommandField.swift +++ b/Sources/BlueZ/OpcodeCommandField.swift @@ -6,7 +6,4 @@ // Copyright © 2016 PureSwift. All rights reserved. // -public extension Bluetooth { - - public typealias OpcodeCommandField = UInt16 -} \ No newline at end of file +public typealias OpcodeCommandField = UInt16 \ No newline at end of file diff --git a/Sources/BlueZ/OpcodeGroupField.swift b/Sources/BlueZ/OpcodeGroupField.swift index 70fb7db..ca07790 100644 --- a/Sources/BlueZ/OpcodeGroupField.swift +++ b/Sources/BlueZ/OpcodeGroupField.swift @@ -6,35 +6,30 @@ // Copyright © 2016 PureSwift. All rights reserved. // -import SwiftFoundation - -public extension Bluetooth { - - public enum OpcodeGroupField: UInt16 { - - /// Link Control - case LinkControl = 0x01 - - /// Link Policy - case LinkPolicy = 0x02 - - /// Host Controller and Baseband - case HostController = 0x03 - - /// Informational Parameters - case InformationalParameters = 0x04 - - /// Status Parameters - case StatusParameters = 0x05 - - /// Low Energy - case LowEnergy = 0x08 - - /// Testing Commands - case Testing = 0x3e - - /// Vendor specific commands - case Vendor = 0x3f - } +public enum OpcodeGroupField: UInt16 { + + /// Link Control + case LinkControl = 0x01 + + /// Link Policy + case LinkPolicy = 0x02 + + /// Host Controller and Baseband + case HostController = 0x03 + + /// Informational Parameters + case InformationalParameters = 0x04 + + /// Status Parameters + case StatusParameters = 0x05 + + /// Low Energy + case LowEnergy = 0x08 + + /// Testing Commands + case Testing = 0x3e + + /// Vendor specific commands + case Vendor = 0x3f } diff --git a/Sources/BlueZ/Scan.swift b/Sources/BlueZ/Scan.swift index 64faa31..44fb2e3 100644 --- a/Sources/BlueZ/Scan.swift +++ b/Sources/BlueZ/Scan.swift @@ -17,7 +17,7 @@ import SwiftFoundation // MARK: - Methods -public extension BluetoothAdapter { +public extension Adapter { /// Scans for nearby Bluetooth devices. /// @@ -70,7 +70,7 @@ public extension BluetoothAdapter { } /// Requests the remote device for its user-friendly name. - func requestDeviceName(deviceAddress: Bluetooth.Address, timeout: Int = 0) throws -> String? { + func requestDeviceName(deviceAddress: Address, timeout: Int = 0) throws -> String? { let maxNameLength = 248 @@ -90,7 +90,7 @@ public extension BluetoothAdapter { // MARK: - Supporting Types -public extension BluetoothAdapter { +public extension Adapter { /// Options for scanning Bluetooth devices public enum ScanOption: Int32, BitMaskOption { diff --git a/Sources/BlueZ/iBeacon.swift b/Sources/BlueZ/iBeacon.swift index ef7af3f..6627208 100644 --- a/Sources/BlueZ/iBeacon.swift +++ b/Sources/BlueZ/iBeacon.swift @@ -15,13 +15,10 @@ import SwiftFoundation -public extension Bluetooth { - - /// 31 Byte String - public typealias LowEnergyAdvertisingData = (Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte) -} +/// 31 Byte String +public typealias LowEnergyAdvertisingData = (Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte) -public extension BluetoothAdapter { +public extension Adapter { /// Enable iBeacon functionality. func enableBeacon(UUID: SwiftFoundation.UUID = UUID(), mayor: UInt16, minor: UInt16, RSSI: Byte, interval: Int = 100, commandTimeout: Int = 1000) throws { @@ -37,7 +34,7 @@ public extension BluetoothAdapter { //advertisingParameters.advtype = 3 // advertising non-connectable advertisingParameters.chan_map = 7 // // all three advertising channels - try self.deviceRequest(Bluetooth.LowEnergyCommand.SetAdvertisingParameters, parameter: advertisingParameters, timeout: commandTimeout) + try self.deviceRequest(LowEnergyCommand.SetAdvertisingParameters, parameter: advertisingParameters, timeout: commandTimeout) // start advertising var enableAdvertise = le_set_advertise_enable_cp() @@ -45,7 +42,7 @@ public extension BluetoothAdapter { enableAdvertise.enable = 0x01 // true - try self.deviceRequest(Bluetooth.LowEnergyCommand.SetAdvertiseEnable, parameter: enableAdvertise, timeout: commandTimeout) + try self.deviceRequest(LowEnergyCommand.SetAdvertiseEnable, parameter: enableAdvertise, timeout: commandTimeout) // set iBeacon data var advertisingDataCommand = le_set_advertising_data_cp() @@ -55,7 +52,7 @@ public extension BluetoothAdapter { advertisingDataCommand.length = beaconData.length advertisingDataCommand.data = beaconData.data - try self.deviceRequest(Bluetooth.LowEnergyCommand.SetAdvertisingData, parameter: advertisingDataCommand, timeout: commandTimeout) + try self.deviceRequest(LowEnergyCommand.SetAdvertisingData, parameter: advertisingDataCommand, timeout: commandTimeout) } func disableBeacon() throws { @@ -64,13 +61,13 @@ public extension BluetoothAdapter { var enableAdvertise = le_set_advertise_enable_cp() enableAdvertise.enable = 0x00 // false - try self.deviceRequest(Bluetooth.LowEnergyCommand.SetAdvertiseEnable, parameter: enableAdvertise) + try self.deviceRequest(LowEnergyCommand.SetAdvertiseEnable, parameter: enableAdvertise) } } // MARK: - Private -private func GenerateBeaconData(UUID: SwiftFoundation.UUID, mayor: UInt16, minor: UInt16, RSSI: Byte) -> (data: Bluetooth.LowEnergyAdvertisingData, length: Byte) { +private func GenerateBeaconData(UUID: SwiftFoundation.UUID, mayor: UInt16, minor: UInt16, RSSI: Byte) -> (data: LowEnergyAdvertisingData, length: Byte) { let length = 30 @@ -102,9 +99,9 @@ private func GenerateBeaconData(UUID: SwiftFoundation.UUID, mayor: UInt16, minor data[29] = RSSI - let byteTuple: Bluetooth.LowEnergyAdvertisingData = withUnsafePointer(&data) { (pointer) in + let byteTuple: LowEnergyAdvertisingData = withUnsafePointer(&data) { (pointer) in - let convertedPointer = UnsafePointer(pointer) + let convertedPointer = UnsafePointer(pointer) return convertedPointer.memory } diff --git a/Sources/UnitTests/ScanTest.swift b/Sources/ScanTest/ScanTest.swift similarity index 95% rename from Sources/UnitTests/ScanTest.swift rename to Sources/ScanTest/ScanTest.swift index 02b4450..9c2d96e 100644 --- a/Sources/UnitTests/ScanTest.swift +++ b/Sources/ScanTest/ScanTest.swift @@ -17,7 +17,7 @@ import SwiftFoundation /// Tests the Scanning functionality -func ScanTest(adapter: BluetoothAdapter, timeout: Int) { +func ScanTest(adapter: Adapter, timeout: Int) { let scanDate = Date() diff --git a/Sources/UnitTests/TestError.swift b/Sources/ScanTest/TestError.swift similarity index 100% rename from Sources/UnitTests/TestError.swift rename to Sources/ScanTest/TestError.swift diff --git a/Sources/ScanTest/main.swift b/Sources/ScanTest/main.swift new file mode 100644 index 0000000..6557fec --- /dev/null +++ b/Sources/ScanTest/main.swift @@ -0,0 +1,30 @@ +// +// main.swift +// BlueZ +// +// Created by Alsey Coleman Miller on 12/6/15. +// Copyright © 2015 PureSwift. All rights reserved. +// + +#if os(Linux) + import CBlueZ + import Glibc + import BlueZ +#elseif os(OSX) || os(iOS) + import Darwin.C +#endif + +import SwiftFoundation + +// get Bluetooth device + +guard let adapter = Adapter() + else { Error("No Bluetooth adapters found") } + +print("Found Bluetooth adapter with device ID: \(adapter.deviceIdentifier)") + +print("Address: \(adapter.address!)") + +/// Perform Test +ScanTest(adapter, timeout: 3) + diff --git a/Sources/iBeaconTest/TestError.swift b/Sources/iBeaconTest/TestError.swift new file mode 100644 index 0000000..249f925 --- /dev/null +++ b/Sources/iBeaconTest/TestError.swift @@ -0,0 +1,22 @@ +// +// Error.swift +// BlueZ +// +// Created by Alsey Coleman Miller on 1/12/16. +// Copyright © 2016 PureSwift. All rights reserved. +// + +#if os(Linux) + import CBlueZ + import Glibc + import BlueZ +#elseif os(OSX) || os(iOS) + import Darwin.C +#endif + +@noreturn func Error(text: String) { + + print(text) + + exit(1) +} \ No newline at end of file diff --git a/Sources/UnitTests/iBeaconTest.swift b/Sources/iBeaconTest/iBeaconTest.swift similarity index 92% rename from Sources/UnitTests/iBeaconTest.swift rename to Sources/iBeaconTest/iBeaconTest.swift index b979b65..d99a07f 100644 --- a/Sources/UnitTests/iBeaconTest.swift +++ b/Sources/iBeaconTest/iBeaconTest.swift @@ -19,7 +19,7 @@ import SwiftFoundation let iBeaconUUID = UUID(rawValue: "E2C56DB5-DFFB-48D2-B060-D0F5A71096E0")! /// Test iBeacon -func iBeaconTest(adapter: BluetoothAdapter, timeout: Int) { +func iBeaconTest(adapter: Adapter, timeout: Int) { print("Enabling iBeacon \(iBeaconUUID) for \(timeout) seconds") diff --git a/Sources/UnitTests/main.swift b/Sources/iBeaconTest/main.swift similarity index 77% rename from Sources/UnitTests/main.swift rename to Sources/iBeaconTest/main.swift index 5665712..777bf1c 100644 --- a/Sources/UnitTests/main.swift +++ b/Sources/iBeaconTest/main.swift @@ -18,17 +18,13 @@ import SwiftFoundation // get Bluetooth device -guard let adapter = BluetoothAdapter() else { - - print("No Bluetooth adapters found") - - exit(0) -} +guard let adapter = Adapter() + else { Error("No Bluetooth adapters found") } print("Found Bluetooth adapter with device ID: \(adapter.deviceIdentifier)") print("Address: \(adapter.address!)") +/// Perform Test iBeaconTest(adapter, timeout: 10) -ScanTest(adapter, timeout: 3) diff --git a/Xcode/BlueZ.xcodeproj/project.pbxproj b/Xcode/BlueZ.xcodeproj/project.pbxproj index c1b7c55..62d24f0 100644 --- a/Xcode/BlueZ.xcodeproj/project.pbxproj +++ b/Xcode/BlueZ.xcodeproj/project.pbxproj @@ -7,19 +7,20 @@ objects = { /* Begin PBXBuildFile section */ + 6E0C5BB91C8373DB00AF63E5 /* Darwin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BB81C8373DB00AF63E5 /* Darwin.swift */; }; + 6E0C5BC21C837AA700AF63E5 /* ScanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BBE1C8379D100AF63E5 /* ScanTest.swift */; }; + 6E0C5BC31C837AAA00AF63E5 /* iBeaconTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BC01C837A9F00AF63E5 /* iBeaconTest.swift */; }; + 6E0C5BC51C837B7700AF63E5 /* TestError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BC41C837B7700AF63E5 /* TestError.swift */; }; 6E1552461C39A045002CC322 /* HCIEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E1552451C39A045002CC322 /* HCIEvent.swift */; }; 6E1552481C39A18A002CC322 /* HCIError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E1552471C39A18A002CC322 /* HCIError.swift */; }; 6E15524A1C39A284002CC322 /* LowEnergyAddressType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E1552491C39A284002CC322 /* LowEnergyAddressType.swift */; }; 6E15524C1C39C08A002CC322 /* OpcodeCommandField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E15524B1C39C08A002CC322 /* OpcodeCommandField.swift */; }; - 6E15524E1C39E4BA002CC322 /* iBeaconTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E15524D1C39E4BA002CC322 /* iBeaconTest.swift */; }; 6E1552501C3A42FE002CC322 /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E15524F1C3A42FE002CC322 /* Error.swift */; }; 6E795E891C47EC90002377FE /* LowEnergyCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E795E881C47EC8F002377FE /* LowEnergyCommand.swift */; }; - 6E795E8A1C47FAF2002377FE /* TestError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E9793921C45BEB4000B9FB9 /* TestError.swift */; }; 6E795E901C489FE7002377FE /* LowEnergyCommandParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E795E8F1C489FE7002377FE /* LowEnergyCommandParameter.swift */; }; 6E795E921C48A186002377FE /* LinkControlCommandParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E795E911C48A186002377FE /* LinkControlCommandParameter.swift */; }; 6E795E941C48B80F002377FE /* LowEnergyEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E795E931C48B80F002377FE /* LowEnergyEvent.swift */; }; 6E795E9B1C49821B002377FE /* LinkMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E795E9A1C49821B002377FE /* LinkMode.swift */; }; - 6E881D7A1C386E8F00E509A9 /* ScanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E881D791C386E8F00E509A9 /* ScanTest.swift */; }; 6E881D7C1C38832400E509A9 /* DeviceCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E881D7B1C38832400E509A9 /* DeviceCommand.swift */; }; 6E881D821C389F4B00E509A9 /* iBeacon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E881D811C389F4B00E509A9 /* iBeacon.swift */; }; 6E881DA21C39812F00E509A9 /* DeviceRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E881D831C39783F00E509A9 /* DeviceRequest.swift */; }; @@ -28,26 +29,29 @@ 6E92A4281C15309B007BC4E9 /* BlueZ.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E92A4271C15309B007BC4E9 /* BlueZ.h */; settings = {ATTRIBUTES = (Public, ); }; }; 6E92A4371C1530EF007BC4E9 /* Adapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E92A4321C1530EF007BC4E9 /* Adapter.swift */; }; 6E92A4381C1530EF007BC4E9 /* Address.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E92A4331C1530EF007BC4E9 /* Address.swift */; }; - 6E92A4391C1530EF007BC4E9 /* Bluetooth.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E92A4341C1530EF007BC4E9 /* Bluetooth.swift */; }; 6E92A43B1C1530EF007BC4E9 /* Scan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E92A4361C1530EF007BC4E9 /* Scan.swift */; }; - 6E92A43F1C153121007BC4E9 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E92A43E1C153121007BC4E9 /* main.swift */; }; 6ECB305D1C47613F004CCA68 /* LinkControlCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6ECB305C1C47613F004CCA68 /* LinkControlCommand.swift */; }; 6ECB30601C47618E004CCA68 /* HCICommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6ECB305F1C47618E004CCA68 /* HCICommand.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 6E0C5BB81C8373DB00AF63E5 /* Darwin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Darwin.swift; sourceTree = ""; }; + 6E0C5BBD1C8379D100AF63E5 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; + 6E0C5BBE1C8379D100AF63E5 /* ScanTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanTest.swift; sourceTree = ""; }; + 6E0C5BC01C837A9F00AF63E5 /* iBeaconTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iBeaconTest.swift; sourceTree = ""; }; + 6E0C5BC11C837A9F00AF63E5 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; + 6E0C5BC41C837B7700AF63E5 /* TestError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestError.swift; sourceTree = ""; }; + 6E0C5BC61C837B8300AF63E5 /* TestError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TestError.swift; path = ../ScanTest/TestError.swift; sourceTree = ""; }; 6E1552451C39A045002CC322 /* HCIEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HCIEvent.swift; sourceTree = ""; }; 6E1552471C39A18A002CC322 /* HCIError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HCIError.swift; sourceTree = ""; }; 6E1552491C39A284002CC322 /* LowEnergyAddressType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LowEnergyAddressType.swift; sourceTree = ""; }; 6E15524B1C39C08A002CC322 /* OpcodeCommandField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpcodeCommandField.swift; sourceTree = ""; }; - 6E15524D1C39E4BA002CC322 /* iBeaconTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = iBeaconTest.swift; sourceTree = ""; }; 6E15524F1C3A42FE002CC322 /* Error.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Error.swift; sourceTree = ""; }; 6E795E881C47EC8F002377FE /* LowEnergyCommand.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LowEnergyCommand.swift; sourceTree = ""; }; 6E795E8F1C489FE7002377FE /* LowEnergyCommandParameter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LowEnergyCommandParameter.swift; sourceTree = ""; }; 6E795E911C48A186002377FE /* LinkControlCommandParameter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LinkControlCommandParameter.swift; sourceTree = ""; }; 6E795E931C48B80F002377FE /* LowEnergyEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LowEnergyEvent.swift; sourceTree = ""; }; 6E795E9A1C49821B002377FE /* LinkMode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LinkMode.swift; sourceTree = ""; }; - 6E881D791C386E8F00E509A9 /* ScanTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScanTest.swift; sourceTree = ""; }; 6E881D7B1C38832400E509A9 /* DeviceCommand.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceCommand.swift; sourceTree = ""; }; 6E881D811C389F4B00E509A9 /* iBeacon.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = iBeacon.swift; sourceTree = ""; }; 6E881D831C39783F00E509A9 /* DeviceRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceRequest.swift; sourceTree = ""; }; @@ -60,10 +64,7 @@ 6E92A42F1C1530DC007BC4E9 /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Package.swift; path = ../Package.swift; sourceTree = ""; }; 6E92A4321C1530EF007BC4E9 /* Adapter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Adapter.swift; sourceTree = ""; }; 6E92A4331C1530EF007BC4E9 /* Address.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Address.swift; sourceTree = ""; }; - 6E92A4341C1530EF007BC4E9 /* Bluetooth.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Bluetooth.swift; sourceTree = ""; }; 6E92A4361C1530EF007BC4E9 /* Scan.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Scan.swift; sourceTree = ""; }; - 6E92A43E1C153121007BC4E9 /* main.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; - 6E9793921C45BEB4000B9FB9 /* TestError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestError.swift; sourceTree = ""; }; 6ECB305C1C47613F004CCA68 /* LinkControlCommand.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LinkControlCommand.swift; sourceTree = ""; }; 6ECB305F1C47618E004CCA68 /* HCICommand.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HCICommand.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -79,6 +80,37 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 6E0C5BBA1C83794700AF63E5 /* Tests */ = { + isa = PBXGroup; + children = ( + 6E0C5BBF1C837A9F00AF63E5 /* iBeaconTest */, + 6E0C5BBC1C8379D100AF63E5 /* ScanTest */, + ); + name = Tests; + sourceTree = ""; + }; + 6E0C5BBC1C8379D100AF63E5 /* ScanTest */ = { + isa = PBXGroup; + children = ( + 6E0C5BBD1C8379D100AF63E5 /* main.swift */, + 6E0C5BBE1C8379D100AF63E5 /* ScanTest.swift */, + 6E0C5BC41C837B7700AF63E5 /* TestError.swift */, + ); + name = ScanTest; + path = ../Sources/ScanTest; + sourceTree = ""; + }; + 6E0C5BBF1C837A9F00AF63E5 /* iBeaconTest */ = { + isa = PBXGroup; + children = ( + 6E0C5BC01C837A9F00AF63E5 /* iBeaconTest.swift */, + 6E0C5BC11C837A9F00AF63E5 /* main.swift */, + 6E0C5BC61C837B8300AF63E5 /* TestError.swift */, + ); + name = iBeaconTest; + path = ../Sources/iBeaconTest; + sourceTree = ""; + }; 6E795E951C48B815002377FE /* HCI Event */ = { isa = PBXGroup; children = ( @@ -91,10 +123,10 @@ 6E92A41A1C15309B007BC4E9 = { isa = PBXGroup; children = ( + 6E0C5BBA1C83794700AF63E5 /* Tests */, 6E881DA51C398D0C00E509A9 /* Headers */, 6E92A42F1C1530DC007BC4E9 /* Package.swift */, 6E92A4311C1530EF007BC4E9 /* Source */, - 6E92A43D1C153121007BC4E9 /* UnitTests */, 6E92A4261C15309B007BC4E9 /* BlueZ */, 6E92A4251C15309B007BC4E9 /* Products */, ); @@ -120,7 +152,7 @@ 6E92A4311C1530EF007BC4E9 /* Source */ = { isa = PBXGroup; children = ( - 6E92A4341C1530EF007BC4E9 /* Bluetooth.swift */, + 6E0C5BB81C8373DB00AF63E5 /* Darwin.swift */, 6E92A4331C1530EF007BC4E9 /* Address.swift */, 6E92A4321C1530EF007BC4E9 /* Adapter.swift */, 6E15524F1C3A42FE002CC322 /* Error.swift */, @@ -140,18 +172,6 @@ path = ../Sources/BlueZ; sourceTree = ""; }; - 6E92A43D1C153121007BC4E9 /* UnitTests */ = { - isa = PBXGroup; - children = ( - 6E92A43E1C153121007BC4E9 /* main.swift */, - 6E9793921C45BEB4000B9FB9 /* TestError.swift */, - 6E881D791C386E8F00E509A9 /* ScanTest.swift */, - 6E15524D1C39E4BA002CC322 /* iBeaconTest.swift */, - ); - name = UnitTests; - path = ../Sources/UnitTests; - sourceTree = ""; - }; 6ECB305E1C476145004CCA68 /* HCI Commands */ = { isa = PBXGroup; children = ( @@ -247,26 +267,25 @@ 6E15524C1C39C08A002CC322 /* OpcodeCommandField.swift in Sources */, 6E881DAC1C3996A200E509A9 /* OpcodeGroupField.swift in Sources */, 6E15524A1C39A284002CC322 /* LowEnergyAddressType.swift in Sources */, + 6E0C5BC31C837AAA00AF63E5 /* iBeaconTest.swift in Sources */, 6E92A43B1C1530EF007BC4E9 /* Scan.swift in Sources */, 6E795E941C48B80F002377FE /* LowEnergyEvent.swift in Sources */, - 6E92A43F1C153121007BC4E9 /* main.swift in Sources */, 6E881D821C389F4B00E509A9 /* iBeacon.swift in Sources */, 6E92A4381C1530EF007BC4E9 /* Address.swift in Sources */, 6E881DAA1C39934200E509A9 /* HCICommandParameter.swift in Sources */, 6E881DA21C39812F00E509A9 /* DeviceRequest.swift in Sources */, 6E1552501C3A42FE002CC322 /* Error.swift in Sources */, - 6E92A4391C1530EF007BC4E9 /* Bluetooth.swift in Sources */, - 6E795E8A1C47FAF2002377FE /* TestError.swift in Sources */, + 6E0C5BC51C837B7700AF63E5 /* TestError.swift in Sources */, 6E1552481C39A18A002CC322 /* HCIError.swift in Sources */, 6E795E901C489FE7002377FE /* LowEnergyCommandParameter.swift in Sources */, 6E795E9B1C49821B002377FE /* LinkMode.swift in Sources */, 6E795E921C48A186002377FE /* LinkControlCommandParameter.swift in Sources */, - 6E881D7A1C386E8F00E509A9 /* ScanTest.swift in Sources */, + 6E0C5BC21C837AA700AF63E5 /* ScanTest.swift in Sources */, 6ECB305D1C47613F004CCA68 /* LinkControlCommand.swift in Sources */, 6ECB30601C47618E004CCA68 /* HCICommand.swift in Sources */, - 6E15524E1C39E4BA002CC322 /* iBeaconTest.swift in Sources */, 6E1552461C39A045002CC322 /* HCIEvent.swift in Sources */, 6E92A4371C1530EF007BC4E9 /* Adapter.swift in Sources */, + 6E0C5BB91C8373DB00AF63E5 /* Darwin.swift in Sources */, 6E881D7C1C38832400E509A9 /* DeviceCommand.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; From 1617cafbaa6406dc182ac9694bc7b8137d4aeeec Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Sun, 28 Feb 2016 14:31:28 -0500 Subject: [PATCH 02/18] working on tests --- Package.swift | 5 ++++- Sources/BlueZ/DaemonAdapter.swift | 17 +++++++++++++++++ Sources/ScanTest/TestError.swift | 3 --- Xcode/BlueZ.xcodeproj/project.pbxproj | 18 ++++++++++++++---- 4 files changed, 35 insertions(+), 8 deletions(-) create mode 100644 Sources/BlueZ/DaemonAdapter.swift diff --git a/Package.swift b/Package.swift index e2e3678..83970da 100644 --- a/Package.swift +++ b/Package.swift @@ -8,7 +8,10 @@ let package = Package( ], targets: [ Target( - name: "UnitTests", + name: "ScanTest", + dependencies: [.Target(name: "BlueZ")]), + Target( + name: "iBeaconTest", dependencies: [.Target(name: "BlueZ")]), Target( name: "BlueZ") diff --git a/Sources/BlueZ/DaemonAdapter.swift b/Sources/BlueZ/DaemonAdapter.swift new file mode 100644 index 0000000..6c1b5b5 --- /dev/null +++ b/Sources/BlueZ/DaemonAdapter.swift @@ -0,0 +1,17 @@ +// +// DaemonAdapter.swift +// BlueZ +// +// Created by Alsey Coleman Miller on 2/28/16. +// Copyright © 2016 PureSwift. All rights reserved. +// + +#if os(Linux) + import CBlueZ + import Glibc +#elseif os(OSX) || os(iOS) + import Darwin.C +#endif + +import SwiftFoundation + diff --git a/Sources/ScanTest/TestError.swift b/Sources/ScanTest/TestError.swift index 249f925..f21a384 100644 --- a/Sources/ScanTest/TestError.swift +++ b/Sources/ScanTest/TestError.swift @@ -7,9 +7,7 @@ // #if os(Linux) - import CBlueZ import Glibc - import BlueZ #elseif os(OSX) || os(iOS) import Darwin.C #endif @@ -17,6 +15,5 @@ @noreturn func Error(text: String) { print(text) - exit(1) } \ No newline at end of file diff --git a/Xcode/BlueZ.xcodeproj/project.pbxproj b/Xcode/BlueZ.xcodeproj/project.pbxproj index 62d24f0..2a34dfe 100644 --- a/Xcode/BlueZ.xcodeproj/project.pbxproj +++ b/Xcode/BlueZ.xcodeproj/project.pbxproj @@ -11,6 +11,7 @@ 6E0C5BC21C837AA700AF63E5 /* ScanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BBE1C8379D100AF63E5 /* ScanTest.swift */; }; 6E0C5BC31C837AAA00AF63E5 /* iBeaconTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BC01C837A9F00AF63E5 /* iBeaconTest.swift */; }; 6E0C5BC51C837B7700AF63E5 /* TestError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BC41C837B7700AF63E5 /* TestError.swift */; }; + 6E0C5BC91C83807700AF63E5 /* DaemonAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BC81C83807700AF63E5 /* DaemonAdapter.swift */; }; 6E1552461C39A045002CC322 /* HCIEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E1552451C39A045002CC322 /* HCIEvent.swift */; }; 6E1552481C39A18A002CC322 /* HCIError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E1552471C39A18A002CC322 /* HCIError.swift */; }; 6E15524A1C39A284002CC322 /* LowEnergyAddressType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E1552491C39A284002CC322 /* LowEnergyAddressType.swift */; }; @@ -41,7 +42,7 @@ 6E0C5BC01C837A9F00AF63E5 /* iBeaconTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iBeaconTest.swift; sourceTree = ""; }; 6E0C5BC11C837A9F00AF63E5 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; 6E0C5BC41C837B7700AF63E5 /* TestError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestError.swift; sourceTree = ""; }; - 6E0C5BC61C837B8300AF63E5 /* TestError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TestError.swift; path = ../ScanTest/TestError.swift; sourceTree = ""; }; + 6E0C5BC81C83807700AF63E5 /* DaemonAdapter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DaemonAdapter.swift; sourceTree = ""; }; 6E1552451C39A045002CC322 /* HCIEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HCIEvent.swift; sourceTree = ""; }; 6E1552471C39A18A002CC322 /* HCIError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HCIError.swift; sourceTree = ""; }; 6E1552491C39A284002CC322 /* LowEnergyAddressType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LowEnergyAddressType.swift; sourceTree = ""; }; @@ -105,12 +106,19 @@ children = ( 6E0C5BC01C837A9F00AF63E5 /* iBeaconTest.swift */, 6E0C5BC11C837A9F00AF63E5 /* main.swift */, - 6E0C5BC61C837B8300AF63E5 /* TestError.swift */, ); name = iBeaconTest; path = ../Sources/iBeaconTest; sourceTree = ""; }; + 6E0C5BC71C83805200AF63E5 /* Daemon */ = { + isa = PBXGroup; + children = ( + 6E0C5BC81C83807700AF63E5 /* DaemonAdapter.swift */, + ); + name = Daemon; + sourceTree = ""; + }; 6E795E951C48B815002377FE /* HCI Event */ = { isa = PBXGroup; children = ( @@ -123,9 +131,9 @@ 6E92A41A1C15309B007BC4E9 = { isa = PBXGroup; children = ( - 6E0C5BBA1C83794700AF63E5 /* Tests */, - 6E881DA51C398D0C00E509A9 /* Headers */, 6E92A42F1C1530DC007BC4E9 /* Package.swift */, + 6E881DA51C398D0C00E509A9 /* Headers */, + 6E0C5BBA1C83794700AF63E5 /* Tests */, 6E92A4311C1530EF007BC4E9 /* Source */, 6E92A4261C15309B007BC4E9 /* BlueZ */, 6E92A4251C15309B007BC4E9 /* Products */, @@ -152,6 +160,7 @@ 6E92A4311C1530EF007BC4E9 /* Source */ = { isa = PBXGroup; children = ( + 6E0C5BC71C83805200AF63E5 /* Daemon */, 6E0C5BB81C8373DB00AF63E5 /* Darwin.swift */, 6E92A4331C1530EF007BC4E9 /* Address.swift */, 6E92A4321C1530EF007BC4E9 /* Adapter.swift */, @@ -275,6 +284,7 @@ 6E881DAA1C39934200E509A9 /* HCICommandParameter.swift in Sources */, 6E881DA21C39812F00E509A9 /* DeviceRequest.swift in Sources */, 6E1552501C3A42FE002CC322 /* Error.swift in Sources */, + 6E0C5BC91C83807700AF63E5 /* DaemonAdapter.swift in Sources */, 6E0C5BC51C837B7700AF63E5 /* TestError.swift in Sources */, 6E1552481C39A18A002CC322 /* HCIError.swift in Sources */, 6E795E901C489FE7002377FE /* LowEnergyCommandParameter.swift in Sources */, From 1ab7163dfe7e4bdb473ec155dec4838c620cd974 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Sun, 28 Feb 2016 15:57:42 -0500 Subject: [PATCH 03/18] working on DaemonAdapter --- Sources/BlueZ/Adapter.swift | 8 +- Sources/BlueZ/DaemonAdapter.swift | 165 ++++++++++++++++++++++++++ Sources/BlueZ/DaemonDevice.swift | 20 ++++ Sources/BlueZ/GattDatabase.swift | 30 +++++ Sources/BlueZ/GattServer.swift | 19 +++ Xcode/BlueZ.xcodeproj/project.pbxproj | 12 ++ 6 files changed, 250 insertions(+), 4 deletions(-) create mode 100644 Sources/BlueZ/DaemonDevice.swift create mode 100644 Sources/BlueZ/GattDatabase.swift create mode 100644 Sources/BlueZ/GattServer.swift diff --git a/Sources/BlueZ/Adapter.swift b/Sources/BlueZ/Adapter.swift index 4a55c0f..de1e378 100644 --- a/Sources/BlueZ/Adapter.swift +++ b/Sources/BlueZ/Adapter.swift @@ -19,7 +19,7 @@ public final class Adapter { // MARK: - Properties /// The device identifier of the Bluetooth adapter. - public let deviceIdentifier: CInt + public let identifier: CInt // MARK: - Private Properties @@ -46,12 +46,12 @@ public final class Adapter { addressPointer.memory = address } - self.deviceIdentifier = hci_get_route(addressPointer) + self.identifier = hci_get_route(addressPointer) - guard self.deviceIdentifier != -1 + guard self.identifier != -1 else { self.socket = -1; return nil } // cant be -1 - self.socket = hci_open_dev(deviceIdentifier) + self.socket = hci_open_dev(identifier) guard socket != -1 else { return nil } // cant be -1 } diff --git a/Sources/BlueZ/DaemonAdapter.swift b/Sources/BlueZ/DaemonAdapter.swift index 6c1b5b5..dbfe434 100644 --- a/Sources/BlueZ/DaemonAdapter.swift +++ b/Sources/BlueZ/DaemonAdapter.swift @@ -15,3 +15,168 @@ import SwiftFoundation +/// Adapter interface used in `bluetoothd`. +public final class DaemonAdapter { + + // MARK: - Class Properties + + public var defaultAdapter: DaemonAdapter? { + + let internalPointer = btd_adapter_get_default() + + guard internalPointer != nil else { return nil } + + let adapter = DaemonAdapter(internalPointer) + + return adapter + } + + /// Check if workaround for broken ATT server socket behavior is needed + /// where we need to connect an ATT client socket before pairing to get + /// early access to the ATT channel. + public var lowEnergyConnectBeforePairing: Bool { + + return btd_le_connect_before_pairing() + } + + // MARK: - Internal Properties + + internal let internalPointer: COpaquePointer + + // MARK: - Initialization + + internal init(_ internalPointer: COpaquePointer) { + + assert(internalPointer != nil) + + self.internalPointer = internalPointer + } + + public init?(address: Address) { + + var addressCopy = address + + self.internalPointer = withUnsafeMutablePointer(&addressCopy) { adapter_find(COpaquePointer($0)) } + + guard internalPointer != nil else { return nil } + } + + public init?(identifier: CInt) { + + self.internalPointer = adapter_find_by_id(identifier) + + guard internalPointer != nil else { return nil } + } + + // MARK: - Class Methods + + public static func initialize() throws { + + let errorCode = adapter_init() + + guard errorCode != 0 else { throw POSIXError(rawValue: errorCode)! } + } + + public static func cleanup() { adapter_cleanup() } + + public static func shutdown() { adapter_shutdown() } + + // MARK: - Methods + + + + // MARK: - Dynamic Properties + + public var index: UInt16 { + + return btd_adapter_get_index(internalPointer) + } + + public var isDefault: Bool { + + return btd_adapter_is_default(internalPointer) + } + + public var pairable: Bool { + + return btd_adapter_get_pairable(internalPointer) + } + + public var powered: Bool { + + return btd_adapter_get_powered(internalPointer) + } + + public var connectable: Bool { + + return btd_adapter_get_connectable(internalPointer) + } + + public var deviceClass: UInt32 { + + return btd_adapter_get_class(internalPointer) + } + + public var database: GattDatabase? { + + let databaseInternalPointer = btd_adapter_get_database(internalPointer) + + guard databaseInternalPointer != nil else { return nil } + + let database = GattDatabase(databaseInternalPointer) + + return database + } + + +} + +// MARK: - Private + + + +// MARK: - Darwin Stubs + +#if os(OSX) || os(iOS) + + func btd_adapter_unref(adapter: COpaquePointer) { stub() } + + func btd_adapter_get_default(_: Void) -> COpaquePointer { stub() } + + func adapter_find(address: COpaquePointer) -> COpaquePointer { stub() } + + func adapter_find_by_id(id: CInt) -> COpaquePointer { stub() } + + func adapter_init(_: Void) -> CInt { stub() } + + func adapter_cleanup(_: Void) { stub() } + + func adapter_shutdown(_: Void) { stub() } + + func btd_adapter_is_default(adapter: COpaquePointer) -> CBool { stub() } + + func btd_adapter_get_index(adapter: COpaquePointer) -> UInt16 { stub() } + + func btd_adapter_get_pairable(adapter: COpaquePointer) -> CBool { stub() } + + func btd_adapter_get_powered(adapter: COpaquePointer) -> CBool { stub() } + + func btd_adapter_get_connectable(adapter: COpaquePointer) -> CBool { stub() } + + func btd_adapter_get_database(adapter: COpaquePointer) -> COpaquePointer { stub() } + + func btd_adapter_get_class(adapter: COpaquePointer) -> UInt32 { stub() } + + func btd_adapter_get_name(adapter: COpaquePointer) -> UnsafePointer { stub() } + + func adapter_get_path(adapter: COpaquePointer) -> UnsafePointer { stub() } + + func btd_adapter_get_address(adapter: COpaquePointer) -> COpaquePointer { stub() } + + func adapter_set_name(adapter: COpaquePointer, _ name: UnsafePointer) -> CInt { stub() } + + func btd_adapter_set_class(adapter: COpaquePointer, _ major: UInt8, _ minor: UInt8) { stub() } + + func btd_le_connect_before_pairing(_: Void) -> CBool { stub() } + +#endif \ No newline at end of file diff --git a/Sources/BlueZ/DaemonDevice.swift b/Sources/BlueZ/DaemonDevice.swift new file mode 100644 index 0000000..bb365a9 --- /dev/null +++ b/Sources/BlueZ/DaemonDevice.swift @@ -0,0 +1,20 @@ +// +// DaemonDevice.swift +// BlueZ +// +// Created by Alsey Coleman Miller on 2/28/16. +// Copyright © 2016 PureSwift. All rights reserved. +// + +#if os(Linux) + import CBlueZ + import Glibc +#elseif os(OSX) || os(iOS) + import Darwin.C +#endif + +/// Device interface used in `bluetoothd`. +public final class DaemonDevice { + + +} \ No newline at end of file diff --git a/Sources/BlueZ/GattDatabase.swift b/Sources/BlueZ/GattDatabase.swift new file mode 100644 index 0000000..c6b2fc5 --- /dev/null +++ b/Sources/BlueZ/GattDatabase.swift @@ -0,0 +1,30 @@ +// +// GattDatabase.swift +// BlueZ +// +// Created by Alsey Coleman Miller on 2/28/16. +// Copyright © 2016 PureSwift. All rights reserved. +// + +#if os(Linux) + import CBlueZ + import Glibc +#elseif os(OSX) || os(iOS) + import Darwin.C +#endif + +public final class GattDatabase { + + // MARK: - Internal Properties + + internal let internalPointer: COpaquePointer + + // MARK: - Initialization + + internal init(_ internalPointer: COpaquePointer) { + + assert(internalPointer != nil) + + self.internalPointer = internalPointer + } +} \ No newline at end of file diff --git a/Sources/BlueZ/GattServer.swift b/Sources/BlueZ/GattServer.swift new file mode 100644 index 0000000..9cbe414 --- /dev/null +++ b/Sources/BlueZ/GattServer.swift @@ -0,0 +1,19 @@ +// +// GattServer.swift +// BlueZ +// +// Created by Alsey Coleman Miller on 2/28/16. +// Copyright © 2016 PureSwift. All rights reserved. +// + +#if os(Linux) + import CBlueZ + import Glibc +#elseif os(OSX) || os(iOS) + import Darwin.C +#endif + +public final class GattServer { + + +} diff --git a/Xcode/BlueZ.xcodeproj/project.pbxproj b/Xcode/BlueZ.xcodeproj/project.pbxproj index 2a34dfe..85cd75b 100644 --- a/Xcode/BlueZ.xcodeproj/project.pbxproj +++ b/Xcode/BlueZ.xcodeproj/project.pbxproj @@ -12,6 +12,9 @@ 6E0C5BC31C837AAA00AF63E5 /* iBeaconTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BC01C837A9F00AF63E5 /* iBeaconTest.swift */; }; 6E0C5BC51C837B7700AF63E5 /* TestError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BC41C837B7700AF63E5 /* TestError.swift */; }; 6E0C5BC91C83807700AF63E5 /* DaemonAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BC81C83807700AF63E5 /* DaemonAdapter.swift */; }; + 6E0C5BCB1C83865000AF63E5 /* GattDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BCA1C83865000AF63E5 /* GattDatabase.swift */; }; + 6E0C5BCD1C83865B00AF63E5 /* GattServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BCC1C83865B00AF63E5 /* GattServer.swift */; }; + 6E0C5BCF1C83889900AF63E5 /* DaemonDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BCE1C83889900AF63E5 /* DaemonDevice.swift */; }; 6E1552461C39A045002CC322 /* HCIEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E1552451C39A045002CC322 /* HCIEvent.swift */; }; 6E1552481C39A18A002CC322 /* HCIError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E1552471C39A18A002CC322 /* HCIError.swift */; }; 6E15524A1C39A284002CC322 /* LowEnergyAddressType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E1552491C39A284002CC322 /* LowEnergyAddressType.swift */; }; @@ -43,6 +46,9 @@ 6E0C5BC11C837A9F00AF63E5 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; 6E0C5BC41C837B7700AF63E5 /* TestError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestError.swift; sourceTree = ""; }; 6E0C5BC81C83807700AF63E5 /* DaemonAdapter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DaemonAdapter.swift; sourceTree = ""; }; + 6E0C5BCA1C83865000AF63E5 /* GattDatabase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GattDatabase.swift; sourceTree = ""; }; + 6E0C5BCC1C83865B00AF63E5 /* GattServer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GattServer.swift; sourceTree = ""; }; + 6E0C5BCE1C83889900AF63E5 /* DaemonDevice.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DaemonDevice.swift; sourceTree = ""; }; 6E1552451C39A045002CC322 /* HCIEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HCIEvent.swift; sourceTree = ""; }; 6E1552471C39A18A002CC322 /* HCIError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HCIError.swift; sourceTree = ""; }; 6E1552491C39A284002CC322 /* LowEnergyAddressType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LowEnergyAddressType.swift; sourceTree = ""; }; @@ -115,6 +121,9 @@ isa = PBXGroup; children = ( 6E0C5BC81C83807700AF63E5 /* DaemonAdapter.swift */, + 6E0C5BCE1C83889900AF63E5 /* DaemonDevice.swift */, + 6E0C5BCA1C83865000AF63E5 /* GattDatabase.swift */, + 6E0C5BCC1C83865B00AF63E5 /* GattServer.swift */, ); name = Daemon; sourceTree = ""; @@ -278,8 +287,10 @@ 6E15524A1C39A284002CC322 /* LowEnergyAddressType.swift in Sources */, 6E0C5BC31C837AAA00AF63E5 /* iBeaconTest.swift in Sources */, 6E92A43B1C1530EF007BC4E9 /* Scan.swift in Sources */, + 6E0C5BCB1C83865000AF63E5 /* GattDatabase.swift in Sources */, 6E795E941C48B80F002377FE /* LowEnergyEvent.swift in Sources */, 6E881D821C389F4B00E509A9 /* iBeacon.swift in Sources */, + 6E0C5BCF1C83889900AF63E5 /* DaemonDevice.swift in Sources */, 6E92A4381C1530EF007BC4E9 /* Address.swift in Sources */, 6E881DAA1C39934200E509A9 /* HCICommandParameter.swift in Sources */, 6E881DA21C39812F00E509A9 /* DeviceRequest.swift in Sources */, @@ -294,6 +305,7 @@ 6ECB305D1C47613F004CCA68 /* LinkControlCommand.swift in Sources */, 6ECB30601C47618E004CCA68 /* HCICommand.swift in Sources */, 6E1552461C39A045002CC322 /* HCIEvent.swift in Sources */, + 6E0C5BCD1C83865B00AF63E5 /* GattServer.swift in Sources */, 6E92A4371C1530EF007BC4E9 /* Adapter.swift in Sources */, 6E0C5BB91C8373DB00AF63E5 /* Darwin.swift in Sources */, 6E881D7C1C38832400E509A9 /* DeviceCommand.swift in Sources */, From e6e3984d8c50f75c3f15e79352446bf34682b3f8 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Sun, 28 Feb 2016 16:32:58 -0500 Subject: [PATCH 04/18] working on GATT --- Sources/BlueZ/ATT.swift | 14 +++++ Sources/BlueZ/Address.swift | 3 +- Sources/BlueZ/DaemonAdapter.swift | 51 +++++++++++++++-- Sources/BlueZ/GATT.swift | 16 ++++++ Sources/BlueZ/GATTDatabase.swift | 55 +++++++++++++++++++ Sources/BlueZ/GATTDatabaseAttribute.swift | 38 +++++++++++++ .../{GattDatabase.swift => GATTServer.swift} | 14 ++++- Sources/BlueZ/GattServer.swift | 19 ------- Sources/BlueZ/Scan.swift | 4 +- Xcode/BlueZ.xcodeproj/project.pbxproj | 36 +++++++++--- 10 files changed, 212 insertions(+), 38 deletions(-) create mode 100644 Sources/BlueZ/ATT.swift create mode 100644 Sources/BlueZ/GATT.swift create mode 100644 Sources/BlueZ/GATTDatabase.swift create mode 100644 Sources/BlueZ/GATTDatabaseAttribute.swift rename Sources/BlueZ/{GattDatabase.swift => GATTServer.swift} (78%) delete mode 100644 Sources/BlueZ/GattServer.swift diff --git a/Sources/BlueZ/ATT.swift b/Sources/BlueZ/ATT.swift new file mode 100644 index 0000000..a24c38b --- /dev/null +++ b/Sources/BlueZ/ATT.swift @@ -0,0 +1,14 @@ +// +// ATT.swift +// BlueZ +// +// Created by Alsey Coleman Miller on 2/28/16. +// Copyright © 2016 PureSwift. All rights reserved. +// + +/// Handles the transport and encoding/decoding for the ATT protocol. +public final class ATT { + + +} + diff --git a/Sources/BlueZ/Address.swift b/Sources/BlueZ/Address.swift index 5eb83ab..3664e2a 100644 --- a/Sources/BlueZ/Address.swift +++ b/Sources/BlueZ/Address.swift @@ -115,7 +115,7 @@ public extension Adapter { /// Fails if the Bluetooth adapter was disconnected or hardware failure. public var address: Address? { - return Address(deviceIdentifier: deviceIdentifier) + return Address(deviceIdentifier: identifier) } } @@ -132,6 +132,7 @@ public extension Adapter { func ba2str(bytes: UnsafePointer, _ str: UnsafeMutablePointer) -> CInt { stub() } + /// Attempts to get the device address. func hci_devba(dev_id: CInt, _ bdaddr: UnsafeMutablePointer) -> CInt { stub() } #endif diff --git a/Sources/BlueZ/DaemonAdapter.swift b/Sources/BlueZ/DaemonAdapter.swift index dbfe434..f5226ec 100644 --- a/Sources/BlueZ/DaemonAdapter.swift +++ b/Sources/BlueZ/DaemonAdapter.swift @@ -45,6 +45,11 @@ public final class DaemonAdapter { // MARK: - Initialization + deinit { + + btd_adapter_unref(internalPointer) + } + internal init(_ internalPointer: COpaquePointer) { assert(internalPointer != nil) @@ -74,7 +79,7 @@ public final class DaemonAdapter { let errorCode = adapter_init() - guard errorCode != 0 else { throw POSIXError(rawValue: errorCode)! } + guard errorCode == 0 else { throw POSIXError(rawValue: errorCode)! } } public static func cleanup() { adapter_cleanup() } @@ -83,7 +88,29 @@ public final class DaemonAdapter { // MARK: - Methods + public func setDeviceClass(mayor mayor: UInt8, minor: UInt8) { + + btd_adapter_set_class(internalPointer, mayor, minor) + } + + public func setDeviceName(name: String) throws { + + let errorCode = adapter_set_name(internalPointer, name) + + guard errorCode == 0 else { throw POSIXError(rawValue: errorCode)! } + } + public func GATTServerStart() throws { + + let errorCode = btd_adapter_gatt_server_start(internalPointer) + + guard errorCode == 0 else { throw POSIXError(rawValue: errorCode)! } + } + + public func GATTServerStop() { + + btd_adapter_gatt_server_stop(internalPointer) + } // MARK: - Dynamic Properties @@ -128,13 +155,23 @@ public final class DaemonAdapter { return database } + public var deviceName: String { + + return String.fromCString(UnsafePointer(btd_adapter_get_name(internalPointer))) ?? "" + } + public var address: Address { + + let addressOpaquePointer = btd_adapter_get_address(internalPointer) + + assert(addressOpaquePointer != nil, "Nil address pointer") + + let addressPointer = UnsafePointer
(addressOpaquePointer) + + return addressPointer.memory + } } -// MARK: - Private - - - // MARK: - Darwin Stubs #if os(OSX) || os(iOS) @@ -179,4 +216,8 @@ public final class DaemonAdapter { func btd_le_connect_before_pairing(_: Void) -> CBool { stub() } + func btd_adapter_gatt_server_start(adapter: COpaquePointer) -> CInt { stub() } + + func btd_adapter_gatt_server_stop(adapter: COpaquePointer) { stub() } + #endif \ No newline at end of file diff --git a/Sources/BlueZ/GATT.swift b/Sources/BlueZ/GATT.swift new file mode 100644 index 0000000..bbfd75b --- /dev/null +++ b/Sources/BlueZ/GATT.swift @@ -0,0 +1,16 @@ +// +// GATT.swift +// BlueZ +// +// Created by Alsey Coleman Miller on 2/28/16. +// Copyright © 2016 PureSwift. All rights reserved. +// + +// Provides namespace for GATT related types. +/// BlueZ GATT +public struct GATT { + + typealias Server = GATTServer + + typealias Database = GATTDatabase +} \ No newline at end of file diff --git a/Sources/BlueZ/GATTDatabase.swift b/Sources/BlueZ/GATTDatabase.swift new file mode 100644 index 0000000..63f049c --- /dev/null +++ b/Sources/BlueZ/GATTDatabase.swift @@ -0,0 +1,55 @@ +// +// GattDatabase.swift +// BlueZ +// +// Created by Alsey Coleman Miller on 2/28/16. +// Copyright © 2016 PureSwift. All rights reserved. +// + +#if os(Linux) + import CBlueZ + import Glibc +#elseif os(OSX) || os(iOS) + import Darwin.C +#endif + +public final class GATTDatabase { + + // MARK: - Internal Properties + + internal let internalPointer: COpaquePointer + + // MARK: - Initialization + + internal init(_ internalPointer: COpaquePointer) { + + assert(internalPointer != nil) + + self.internalPointer = internalPointer + } + + public init?() { + + self.internalPointer = gatt_db_new() + + guard internalPointer != nil else { return } + } + + // MARK: - Methods + + + + // MARK: - Dynamic Properties + + +} + +// MARK: - Darwin Stubs + +#if os(OSX) || os(iOS) + + func gatt_db_new(_: Void) -> COpaquePointer { stub() } + + func + +#endif diff --git a/Sources/BlueZ/GATTDatabaseAttribute.swift b/Sources/BlueZ/GATTDatabaseAttribute.swift new file mode 100644 index 0000000..e475e14 --- /dev/null +++ b/Sources/BlueZ/GATTDatabaseAttribute.swift @@ -0,0 +1,38 @@ +// +// GattDatabaseAttribute.swift +// BlueZ +// +// Created by Alsey Coleman Miller on 2/28/16. +// Copyright © 2016 PureSwift. All rights reserved. +// + +import Foundation + +public extension GATTDatabase { + + typealias Attribute = GATTDatabaseAttribute +} + +public final class GATTDatabaseAttribute { + + // MARK: - Internal Properties + + internal let internalPointer: COpaquePointer + + // MARK: - Initialization + + internal init(_ internalPointer: COpaquePointer) { + + assert(internalPointer != nil) + + self.internalPointer = internalPointer + } + + // MARK: - Methods + + + + // MARK: - Dynamic Properties + + +} \ No newline at end of file diff --git a/Sources/BlueZ/GattDatabase.swift b/Sources/BlueZ/GATTServer.swift similarity index 78% rename from Sources/BlueZ/GattDatabase.swift rename to Sources/BlueZ/GATTServer.swift index c6b2fc5..92f391a 100644 --- a/Sources/BlueZ/GattDatabase.swift +++ b/Sources/BlueZ/GATTServer.swift @@ -1,5 +1,5 @@ // -// GattDatabase.swift +// GattServer.swift // BlueZ // // Created by Alsey Coleman Miller on 2/28/16. @@ -13,7 +13,7 @@ import Darwin.C #endif -public final class GattDatabase { +public final class GATTServer { // MARK: - Internal Properties @@ -27,4 +27,12 @@ public final class GattDatabase { self.internalPointer = internalPointer } -} \ No newline at end of file + + // MARK: - Methods + + + + // MARK: - Dynamic Properties + + +} diff --git a/Sources/BlueZ/GattServer.swift b/Sources/BlueZ/GattServer.swift deleted file mode 100644 index 9cbe414..0000000 --- a/Sources/BlueZ/GattServer.swift +++ /dev/null @@ -1,19 +0,0 @@ -// -// GattServer.swift -// BlueZ -// -// Created by Alsey Coleman Miller on 2/28/16. -// Copyright © 2016 PureSwift. All rights reserved. -// - -#if os(Linux) - import CBlueZ - import Glibc -#elseif os(OSX) || os(iOS) - import Darwin.C -#endif - -public final class GattServer { - - -} diff --git a/Sources/BlueZ/Scan.swift b/Sources/BlueZ/Scan.swift index 44fb2e3..f38f371 100644 --- a/Sources/BlueZ/Scan.swift +++ b/Sources/BlueZ/Scan.swift @@ -53,13 +53,13 @@ public extension Adapter { } else { deviceClassPointer = nil } - let foundDevicesCount = hci_inquiry(deviceIdentifier, CInt(duration), CInt(scanLimit), deviceClassPointer, inquiryInfoPointers, Int(flags)) + let foundDevicesCount = hci_inquiry(identifier, CInt(duration), CInt(scanLimit), deviceClassPointer, inquiryInfoPointers, Int(flags)) guard foundDevicesCount >= 0 else { throw POSIXError.fromErrorNumber! } var results = [inquiry_info]() - for i in 0.. Date: Sun, 28 Feb 2016 16:58:10 -0500 Subject: [PATCH 05/18] working on ATT --- Sources/BlueZ/ATT.swift | 62 +++++++++++++++++++++++ Sources/BlueZ/DaemonAdapter.swift | 4 +- Sources/BlueZ/GATT.swift | 6 +++ Sources/BlueZ/GATTDatabase.swift | 4 +- Sources/BlueZ/GATTDatabaseAttribute.swift | 22 +++++--- Sources/BlueZ/LowEnergyAddressType.swift | 4 +- Sources/BlueZ/SecurityType.swift | 16 ++++++ Xcode/BlueZ.xcodeproj/project.pbxproj | 6 ++- 8 files changed, 108 insertions(+), 16 deletions(-) create mode 100644 Sources/BlueZ/SecurityType.swift diff --git a/Sources/BlueZ/ATT.swift b/Sources/BlueZ/ATT.swift index a24c38b..513e6e3 100644 --- a/Sources/BlueZ/ATT.swift +++ b/Sources/BlueZ/ATT.swift @@ -9,6 +9,68 @@ /// Handles the transport and encoding/decoding for the ATT protocol. public final class ATT { + /// Whether the file descriptor will be closed on deallocation. + public var closeFileDescriptor: Bool = false { + + willSet { bt_att_set_close_on_unref(internalPointer, newValue) } + } + // MARK: - Internal Properties + + internal let internalPointer: COpaquePointer + + // MARK: - Initialization + + deinit { + + bt_att_unref(internalPointer) + } + + internal init(_ internalPointer: COpaquePointer) { + + assert(internalPointer != nil) + + self.internalPointer = internalPointer + } + + public init?(fileDescriptor: CInt, externalCrypto: Bool = false) { + + self.internalPointer = bt_att_new(fileDescriptor, externalCrypto) + + guard internalPointer != nil else { return nil } + } + + // MARK: - Methods + + + + // MARK: - Dynamic Properties + + public var fileDescriptor: CInt { + + return bt_att_get_fd(internalPointer) + } + + public var hasCrypto: Bool { + + return bt_att_has_crypto(internalPointer) + } } +// MARK: - Darwin Stubs + +#if os(OSX) || os(iOS) + + func bt_att_new(fd: CInt, _ externalCrypto: CBool) -> COpaquePointer { stub() } + + func bt_att_unref(att: COpaquePointer) { stub() } + + func bt_att_set_close_on_unref(att: COpaquePointer, _ doClose: CBool) { stub() } + + func bt_att_get_fd(att: COpaquePointer) -> CInt { stub() } + + func bt_att_has_crypto(att: COpaquePointer) -> CBool { stub() } + + + +#endif diff --git a/Sources/BlueZ/DaemonAdapter.swift b/Sources/BlueZ/DaemonAdapter.swift index f5226ec..f2a8f64 100644 --- a/Sources/BlueZ/DaemonAdapter.swift +++ b/Sources/BlueZ/DaemonAdapter.swift @@ -144,13 +144,13 @@ public final class DaemonAdapter { return btd_adapter_get_class(internalPointer) } - public var database: GattDatabase? { + public var database: GATTDatabase? { let databaseInternalPointer = btd_adapter_get_database(internalPointer) guard databaseInternalPointer != nil else { return nil } - let database = GattDatabase(databaseInternalPointer) + let database = GATTDatabase(databaseInternalPointer) return database } diff --git a/Sources/BlueZ/GATT.swift b/Sources/BlueZ/GATT.swift index bbfd75b..f255773 100644 --- a/Sources/BlueZ/GATT.swift +++ b/Sources/BlueZ/GATT.swift @@ -7,10 +7,16 @@ // // Provides namespace for GATT related types. + /// BlueZ GATT public struct GATT { typealias Server = GATTServer typealias Database = GATTDatabase +} + +public extension GATTDatabase { + + typealias Attribute = GATTDatabaseAttribute } \ No newline at end of file diff --git a/Sources/BlueZ/GATTDatabase.swift b/Sources/BlueZ/GATTDatabase.swift index 63f049c..fc87d07 100644 --- a/Sources/BlueZ/GATTDatabase.swift +++ b/Sources/BlueZ/GATTDatabase.swift @@ -50,6 +50,6 @@ public final class GATTDatabase { func gatt_db_new(_: Void) -> COpaquePointer { stub() } - func - + + #endif diff --git a/Sources/BlueZ/GATTDatabaseAttribute.swift b/Sources/BlueZ/GATTDatabaseAttribute.swift index e475e14..dbf8664 100644 --- a/Sources/BlueZ/GATTDatabaseAttribute.swift +++ b/Sources/BlueZ/GATTDatabaseAttribute.swift @@ -6,12 +6,12 @@ // Copyright © 2016 PureSwift. All rights reserved. // -import Foundation - -public extension GATTDatabase { - - typealias Attribute = GATTDatabaseAttribute -} +#if os(Linux) + import CBlueZ + import Glibc +#elseif os(OSX) || os(iOS) + import Darwin.C +#endif public final class GATTDatabaseAttribute { @@ -35,4 +35,12 @@ public final class GATTDatabaseAttribute { // MARK: - Dynamic Properties -} \ No newline at end of file +} + +// MARK: - Darwin Stubs + +#if os(OSX) || os(iOS) + + //func btd_adapter_unref(adapter: COpaquePointer) { stub() } + +#endif diff --git a/Sources/BlueZ/LowEnergyAddressType.swift b/Sources/BlueZ/LowEnergyAddressType.swift index 41cf47b..33487f2 100644 --- a/Sources/BlueZ/LowEnergyAddressType.swift +++ b/Sources/BlueZ/LowEnergyAddressType.swift @@ -6,11 +6,9 @@ // Copyright © 2016 PureSwift. All rights reserved. // -import SwiftFoundation - public extension Address { - public enum LowEnergyAddressType: CInt { + public enum LowEnergyType: UInt8 { case Public = 0x00 case Random = 0x01 diff --git a/Sources/BlueZ/SecurityType.swift b/Sources/BlueZ/SecurityType.swift new file mode 100644 index 0000000..3d91126 --- /dev/null +++ b/Sources/BlueZ/SecurityType.swift @@ -0,0 +1,16 @@ +// +// SecurityType.swift +// BlueZ +// +// Created by Alsey Coleman Miller on 2/28/16. +// Copyright © 2016 PureSwift. All rights reserved. +// + +/// Bluetooth security type. +public enum SecurityType: UInt8 { + + case SDP + case Low + case Medium + case High +} \ No newline at end of file diff --git a/Xcode/BlueZ.xcodeproj/project.pbxproj b/Xcode/BlueZ.xcodeproj/project.pbxproj index aada779..e10a89c 100644 --- a/Xcode/BlueZ.xcodeproj/project.pbxproj +++ b/Xcode/BlueZ.xcodeproj/project.pbxproj @@ -17,7 +17,7 @@ 6E0C5BCF1C83889900AF63E5 /* DaemonDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BCE1C83889900AF63E5 /* DaemonDevice.swift */; }; 6E0C5BD11C839C5D00AF63E5 /* GATTDatabaseAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BD01C839C5D00AF63E5 /* GATTDatabaseAttribute.swift */; }; 6E0C5BD41C839E1C00AF63E5 /* ATT.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BD31C839E1C00AF63E5 /* ATT.swift */; }; - 6E0C5BD61C839E9400AF63E5 /* GATT.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BD51C839E9400AF63E5 /* GATT.swift */; }; + 6E0C5BD81C83A45100AF63E5 /* SecurityType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BD71C83A45100AF63E5 /* SecurityType.swift */; }; 6E1552461C39A045002CC322 /* HCIEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E1552451C39A045002CC322 /* HCIEvent.swift */; }; 6E1552481C39A18A002CC322 /* HCIError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E1552471C39A18A002CC322 /* HCIError.swift */; }; 6E15524A1C39A284002CC322 /* LowEnergyAddressType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E1552491C39A284002CC322 /* LowEnergyAddressType.swift */; }; @@ -55,6 +55,7 @@ 6E0C5BD01C839C5D00AF63E5 /* GATTDatabaseAttribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GATTDatabaseAttribute.swift; sourceTree = ""; }; 6E0C5BD31C839E1C00AF63E5 /* ATT.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ATT.swift; sourceTree = ""; }; 6E0C5BD51C839E9400AF63E5 /* GATT.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GATT.swift; sourceTree = ""; }; + 6E0C5BD71C83A45100AF63E5 /* SecurityType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecurityType.swift; sourceTree = ""; }; 6E1552451C39A045002CC322 /* HCIEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HCIEvent.swift; sourceTree = ""; }; 6E1552471C39A18A002CC322 /* HCIError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HCIError.swift; sourceTree = ""; }; 6E1552491C39A284002CC322 /* LowEnergyAddressType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LowEnergyAddressType.swift; sourceTree = ""; }; @@ -197,6 +198,7 @@ 6E881D811C389F4B00E509A9 /* iBeacon.swift */, 6E1552471C39A18A002CC322 /* HCIError.swift */, 6E1552491C39A284002CC322 /* LowEnergyAddressType.swift */, + 6E0C5BD71C83A45100AF63E5 /* SecurityType.swift */, 6E881DAB1C3996A200E509A9 /* OpcodeGroupField.swift */, 6E15524B1C39C08A002CC322 /* OpcodeCommandField.swift */, 6E795E9A1C49821B002377FE /* LinkMode.swift */, @@ -305,6 +307,7 @@ 6E881DAC1C3996A200E509A9 /* OpcodeGroupField.swift in Sources */, 6E15524A1C39A284002CC322 /* LowEnergyAddressType.swift in Sources */, 6E0C5BC31C837AAA00AF63E5 /* iBeaconTest.swift in Sources */, + 6E0C5BD81C83A45100AF63E5 /* SecurityType.swift in Sources */, 6E92A43B1C1530EF007BC4E9 /* Scan.swift in Sources */, 6E0C5BCB1C83865000AF63E5 /* GATTDatabase.swift in Sources */, 6E795E941C48B80F002377FE /* LowEnergyEvent.swift in Sources */, @@ -320,7 +323,6 @@ 6E795E901C489FE7002377FE /* LowEnergyCommandParameter.swift in Sources */, 6E795E9B1C49821B002377FE /* LinkMode.swift in Sources */, 6E795E921C48A186002377FE /* LinkControlCommandParameter.swift in Sources */, - 6E0C5BD61C839E9400AF63E5 /* GATT.swift in Sources */, 6E0C5BC21C837AA700AF63E5 /* ScanTest.swift in Sources */, 6ECB305D1C47613F004CCA68 /* LinkControlCommand.swift in Sources */, 6ECB30601C47618E004CCA68 /* HCICommand.swift in Sources */, From a6d6820d510c349180be565c5f82ff1436ee21e8 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Sun, 28 Feb 2016 17:39:33 -0500 Subject: [PATCH 06/18] added BlueZUUID --- Sources/BlueZ/GATTDatabase.swift | 9 ++++- Sources/BlueZ/UUID.swift | 56 +++++++++++++++++++++++++++ Sources/iBeaconTest/iBeaconTest.swift | 2 +- Xcode/BlueZ.xcodeproj/project.pbxproj | 4 ++ 4 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 Sources/BlueZ/UUID.swift diff --git a/Sources/BlueZ/GATTDatabase.swift b/Sources/BlueZ/GATTDatabase.swift index fc87d07..47e6cf1 100644 --- a/Sources/BlueZ/GATTDatabase.swift +++ b/Sources/BlueZ/GATTDatabase.swift @@ -41,7 +41,10 @@ public final class GATTDatabase { // MARK: - Dynamic Properties - + public var isEmpty: Bool { + + return gatt_db_isempty(internalPointer) + } } // MARK: - Darwin Stubs @@ -50,6 +53,10 @@ public final class GATTDatabase { func gatt_db_new(_: Void) -> COpaquePointer { stub() } + func gatt_db_unref(db: COpaquePointer) { stub() } + + func gatt_db_isempty(db: COpaquePointer) -> CBool { stub() } + func gatt_db_add_service() { stub() } #endif diff --git a/Sources/BlueZ/UUID.swift b/Sources/BlueZ/UUID.swift new file mode 100644 index 0000000..5c83ac1 --- /dev/null +++ b/Sources/BlueZ/UUID.swift @@ -0,0 +1,56 @@ +// +// UUID.swift +// BlueZ +// +// Created by Alsey Coleman Miller on 2/28/16. +// Copyright © 2016 PureSwift. All rights reserved. +// + +#if os(Linux) + import CBlueZ + import Glibc +#elseif os(OSX) || os(iOS) + import Darwin.C +#endif + +import SwiftFoundation + +public typealias BluezUUID = bt_uuid_t + +public extension BluezUUID { + + public init(_ value: UInt16) { + + + } + + public init(_ value: UInt32) { + + + } + + /* + public init(_ value: _uint128_t) { + + + }*/ +} + +/// Type of Bluetooth UUID. +public enum UUIDType: Int { + + case Bit16 = 16 + case Bit32 = 32 + case Bit128 = 128 +} + +// MARK: - Darwin Stubs + +#if os(OSX) || os(iOS) + + public struct bt_uuid_t { + + public init() { stub() } + } + +#endif \ No newline at end of file diff --git a/Sources/iBeaconTest/iBeaconTest.swift b/Sources/iBeaconTest/iBeaconTest.swift index d99a07f..d95c0d3 100644 --- a/Sources/iBeaconTest/iBeaconTest.swift +++ b/Sources/iBeaconTest/iBeaconTest.swift @@ -16,7 +16,7 @@ import SwiftFoundation -let iBeaconUUID = UUID(rawValue: "E2C56DB5-DFFB-48D2-B060-D0F5A71096E0")! +let iBeaconUUID = SwiftFoundation.UUID(rawValue: "E2C56DB5-DFFB-48D2-B060-D0F5A71096E0")! /// Test iBeacon func iBeaconTest(adapter: Adapter, timeout: Int) { diff --git a/Xcode/BlueZ.xcodeproj/project.pbxproj b/Xcode/BlueZ.xcodeproj/project.pbxproj index e10a89c..ba267b6 100644 --- a/Xcode/BlueZ.xcodeproj/project.pbxproj +++ b/Xcode/BlueZ.xcodeproj/project.pbxproj @@ -18,6 +18,7 @@ 6E0C5BD11C839C5D00AF63E5 /* GATTDatabaseAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BD01C839C5D00AF63E5 /* GATTDatabaseAttribute.swift */; }; 6E0C5BD41C839E1C00AF63E5 /* ATT.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BD31C839E1C00AF63E5 /* ATT.swift */; }; 6E0C5BD81C83A45100AF63E5 /* SecurityType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BD71C83A45100AF63E5 /* SecurityType.swift */; }; + 6E0C5BDA1C83AAC000AF63E5 /* UUID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BD91C83AAC000AF63E5 /* UUID.swift */; }; 6E1552461C39A045002CC322 /* HCIEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E1552451C39A045002CC322 /* HCIEvent.swift */; }; 6E1552481C39A18A002CC322 /* HCIError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E1552471C39A18A002CC322 /* HCIError.swift */; }; 6E15524A1C39A284002CC322 /* LowEnergyAddressType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E1552491C39A284002CC322 /* LowEnergyAddressType.swift */; }; @@ -56,6 +57,7 @@ 6E0C5BD31C839E1C00AF63E5 /* ATT.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ATT.swift; sourceTree = ""; }; 6E0C5BD51C839E9400AF63E5 /* GATT.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GATT.swift; sourceTree = ""; }; 6E0C5BD71C83A45100AF63E5 /* SecurityType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecurityType.swift; sourceTree = ""; }; + 6E0C5BD91C83AAC000AF63E5 /* UUID.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UUID.swift; sourceTree = ""; }; 6E1552451C39A045002CC322 /* HCIEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HCIEvent.swift; sourceTree = ""; }; 6E1552471C39A18A002CC322 /* HCIError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HCIError.swift; sourceTree = ""; }; 6E1552491C39A284002CC322 /* LowEnergyAddressType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LowEnergyAddressType.swift; sourceTree = ""; }; @@ -190,6 +192,7 @@ 6E0C5BC71C83805200AF63E5 /* Daemon */, 6E0C5BB81C8373DB00AF63E5 /* Darwin.swift */, 6E92A4331C1530EF007BC4E9 /* Address.swift */, + 6E0C5BD91C83AAC000AF63E5 /* UUID.swift */, 6E92A4321C1530EF007BC4E9 /* Adapter.swift */, 6E15524F1C3A42FE002CC322 /* Error.swift */, 6E92A4361C1530EF007BC4E9 /* Scan.swift */, @@ -328,6 +331,7 @@ 6ECB30601C47618E004CCA68 /* HCICommand.swift in Sources */, 6E1552461C39A045002CC322 /* HCIEvent.swift in Sources */, 6E0C5BCD1C83865B00AF63E5 /* GATTServer.swift in Sources */, + 6E0C5BDA1C83AAC000AF63E5 /* UUID.swift in Sources */, 6E92A4371C1530EF007BC4E9 /* Adapter.swift in Sources */, 6E0C5BB91C8373DB00AF63E5 /* Darwin.swift in Sources */, 6E881D7C1C38832400E509A9 /* DeviceCommand.swift in Sources */, From db147ba29af4877df82963077d9494c5ba7caf2e Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Sun, 28 Feb 2016 18:51:11 -0500 Subject: [PATCH 07/18] working on CBlueZInternal --- Package.swift | 1 + Sources/BlueZ/ATT.swift | 8 ++++++ Sources/BlueZ/Adapter.swift | 1 + Sources/BlueZ/AddressType.swift | 27 +++++++++++++++++++ Sources/BlueZ/DaemonAdapter.swift | 13 +++++---- Sources/BlueZ/DaemonDevice.swift | 1 + Sources/BlueZ/GATTDatabase.swift | 1 + Sources/BlueZ/GATTDatabaseAttribute.swift | 1 + Sources/BlueZ/GATTServer.swift | 1 + Sources/BlueZ/UUID.swift | 33 ++++++++++++++++++++--- Sources/ScanTest/main.swift | 2 +- Sources/iBeaconTest/main.swift | 2 +- Xcode/BlueZ.xcodeproj/project.pbxproj | 4 +++ 13 files changed, 83 insertions(+), 12 deletions(-) create mode 100644 Sources/BlueZ/AddressType.swift diff --git a/Package.swift b/Package.swift index 83970da..a6a8d53 100644 --- a/Package.swift +++ b/Package.swift @@ -4,6 +4,7 @@ let package = Package( name: "BlueZ", dependencies: [ .Package(url: "https://github.com/PureSwift/CBlueZ.git", majorVersion: 1), + .Package(url: "https://github.com/PureSwift/CBlueZInternal.git", majorVersion: 1), .Package(url: "https://github.com/PureSwift/SwiftFoundation.git", majorVersion: 1), ], targets: [ diff --git a/Sources/BlueZ/ATT.swift b/Sources/BlueZ/ATT.swift index 513e6e3..9d76ad6 100644 --- a/Sources/BlueZ/ATT.swift +++ b/Sources/BlueZ/ATT.swift @@ -6,6 +6,14 @@ // Copyright © 2016 PureSwift. All rights reserved. // +#if os(Linux) + import CBlueZ + import CBlueZInternal + import Glibc +#elseif os(OSX) || os(iOS) + import Darwin.C +#endif + /// Handles the transport and encoding/decoding for the ATT protocol. public final class ATT { diff --git a/Sources/BlueZ/Adapter.swift b/Sources/BlueZ/Adapter.swift index de1e378..8f8d6e1 100644 --- a/Sources/BlueZ/Adapter.swift +++ b/Sources/BlueZ/Adapter.swift @@ -8,6 +8,7 @@ #if os(Linux) import CBlueZ + import CBlueZInternal import Glibc #elseif os(OSX) || os(iOS) import Darwin.C diff --git a/Sources/BlueZ/AddressType.swift b/Sources/BlueZ/AddressType.swift new file mode 100644 index 0000000..b85efc9 --- /dev/null +++ b/Sources/BlueZ/AddressType.swift @@ -0,0 +1,27 @@ +// +// AddressType.swift +// BlueZ +// +// Created by Alsey Coleman Miller on 2/28/16. +// Copyright © 2016 PureSwift. All rights reserved. +// + +public enum AddressType { + + case BDR + case LowEnergyRandom + case LowEnergyPublic + + /// Whether the Bluetooth address type is LE. + public var isLowEnergy: Bool { + + switch self { + + case .LowEnergyPublic, .LowEnergyRandom: + return true + + default: + return false + } + } +} \ No newline at end of file diff --git a/Sources/BlueZ/DaemonAdapter.swift b/Sources/BlueZ/DaemonAdapter.swift index f2a8f64..d6bb839 100644 --- a/Sources/BlueZ/DaemonAdapter.swift +++ b/Sources/BlueZ/DaemonAdapter.swift @@ -8,6 +8,7 @@ #if os(Linux) import CBlueZ + import CBlueZInternal import Glibc #elseif os(OSX) || os(iOS) import Darwin.C @@ -61,7 +62,7 @@ public final class DaemonAdapter { var addressCopy = address - self.internalPointer = withUnsafeMutablePointer(&addressCopy) { adapter_find(COpaquePointer($0)) } + self.internalPointer = withUnsafeMutablePointer(&addressCopy) { adapter_find($0) } guard internalPointer != nil else { return nil } } @@ -162,11 +163,9 @@ public final class DaemonAdapter { public var address: Address { - let addressOpaquePointer = btd_adapter_get_address(internalPointer) + let addressPointer = btd_adapter_get_address(internalPointer) - assert(addressOpaquePointer != nil, "Nil address pointer") - - let addressPointer = UnsafePointer
(addressOpaquePointer) + assert(addressPointer != nil, "Nil address pointer") return addressPointer.memory } @@ -180,7 +179,7 @@ public final class DaemonAdapter { func btd_adapter_get_default(_: Void) -> COpaquePointer { stub() } - func adapter_find(address: COpaquePointer) -> COpaquePointer { stub() } + func adapter_find(address: UnsafePointer) -> COpaquePointer { stub() } func adapter_find_by_id(id: CInt) -> COpaquePointer { stub() } @@ -208,7 +207,7 @@ public final class DaemonAdapter { func adapter_get_path(adapter: COpaquePointer) -> UnsafePointer { stub() } - func btd_adapter_get_address(adapter: COpaquePointer) -> COpaquePointer { stub() } + func btd_adapter_get_address(adapter: COpaquePointer) -> UnsafePointer { stub() } func adapter_set_name(adapter: COpaquePointer, _ name: UnsafePointer) -> CInt { stub() } diff --git a/Sources/BlueZ/DaemonDevice.swift b/Sources/BlueZ/DaemonDevice.swift index bb365a9..74e714c 100644 --- a/Sources/BlueZ/DaemonDevice.swift +++ b/Sources/BlueZ/DaemonDevice.swift @@ -8,6 +8,7 @@ #if os(Linux) import CBlueZ + import CBlueZInternal import Glibc #elseif os(OSX) || os(iOS) import Darwin.C diff --git a/Sources/BlueZ/GATTDatabase.swift b/Sources/BlueZ/GATTDatabase.swift index 47e6cf1..149df9a 100644 --- a/Sources/BlueZ/GATTDatabase.swift +++ b/Sources/BlueZ/GATTDatabase.swift @@ -8,6 +8,7 @@ #if os(Linux) import CBlueZ + import CBlueZInternal import Glibc #elseif os(OSX) || os(iOS) import Darwin.C diff --git a/Sources/BlueZ/GATTDatabaseAttribute.swift b/Sources/BlueZ/GATTDatabaseAttribute.swift index dbf8664..790f4c6 100644 --- a/Sources/BlueZ/GATTDatabaseAttribute.swift +++ b/Sources/BlueZ/GATTDatabaseAttribute.swift @@ -8,6 +8,7 @@ #if os(Linux) import CBlueZ + import CBlueZInternal import Glibc #elseif os(OSX) || os(iOS) import Darwin.C diff --git a/Sources/BlueZ/GATTServer.swift b/Sources/BlueZ/GATTServer.swift index 92f391a..3b9555c 100644 --- a/Sources/BlueZ/GATTServer.swift +++ b/Sources/BlueZ/GATTServer.swift @@ -8,6 +8,7 @@ #if os(Linux) import CBlueZ + import CBlueZInternal import Glibc #elseif os(OSX) || os(iOS) import Darwin.C diff --git a/Sources/BlueZ/UUID.swift b/Sources/BlueZ/UUID.swift index 5c83ac1..947bb8e 100644 --- a/Sources/BlueZ/UUID.swift +++ b/Sources/BlueZ/UUID.swift @@ -17,24 +17,40 @@ import SwiftFoundation public typealias BluezUUID = bt_uuid_t +/* public extension BluezUUID { public init(_ value: UInt16) { + var uuid = bt_uuid_t() + bt_uuid16_create(&uuid, value) + + self = uuid } public init(_ value: UInt32) { + var uuid = bt_uuid_t() + + bt_uuid32_create(&uuid, value) + self = uuid } + // https://bugs.swift.org/browse/SR-847 /* - public init(_ value: _uint128_t) { - + public init(_ value: UInt128) { + var uuid = bt_uuid_t() + + bt_uuid128_create(&uuid, value) + + self = uuid + }*/ } +*/ /// Type of Bluetooth UUID. public enum UUIDType: Int { @@ -48,9 +64,20 @@ public enum UUIDType: Int { #if os(OSX) || os(iOS) + let MAX_LEN_UUID_STR: CInt = 37 + public struct bt_uuid_t { public init() { stub() } } + + func bt_uuid16_create(btuuid: UnsafeMutablePointer, _ value: UInt16) -> CInt { stub() } + + func bt_uuid32_create(btuuid: UnsafeMutablePointer, _ value: UInt32) -> CInt { stub() } + + //func bt_uuid128_create(btuuid: UnsafeMutablePointer, _ value: UInt128) -> CInt { stub() } + + + +#endif -#endif \ No newline at end of file diff --git a/Sources/ScanTest/main.swift b/Sources/ScanTest/main.swift index 6557fec..e87873b 100644 --- a/Sources/ScanTest/main.swift +++ b/Sources/ScanTest/main.swift @@ -21,7 +21,7 @@ import SwiftFoundation guard let adapter = Adapter() else { Error("No Bluetooth adapters found") } -print("Found Bluetooth adapter with device ID: \(adapter.deviceIdentifier)") +print("Found Bluetooth adapter with device ID: \(adapter.identifier)") print("Address: \(adapter.address!)") diff --git a/Sources/iBeaconTest/main.swift b/Sources/iBeaconTest/main.swift index 777bf1c..da557b4 100644 --- a/Sources/iBeaconTest/main.swift +++ b/Sources/iBeaconTest/main.swift @@ -21,7 +21,7 @@ import SwiftFoundation guard let adapter = Adapter() else { Error("No Bluetooth adapters found") } -print("Found Bluetooth adapter with device ID: \(adapter.deviceIdentifier)") +print("Found Bluetooth adapter with device ID: \(adapter.identifier)") print("Address: \(adapter.address!)") diff --git a/Xcode/BlueZ.xcodeproj/project.pbxproj b/Xcode/BlueZ.xcodeproj/project.pbxproj index ba267b6..8f4b357 100644 --- a/Xcode/BlueZ.xcodeproj/project.pbxproj +++ b/Xcode/BlueZ.xcodeproj/project.pbxproj @@ -34,6 +34,7 @@ 6E881DA21C39812F00E509A9 /* DeviceRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E881D831C39783F00E509A9 /* DeviceRequest.swift */; }; 6E881DAA1C39934200E509A9 /* HCICommandParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E881DA91C39934200E509A9 /* HCICommandParameter.swift */; }; 6E881DAC1C3996A200E509A9 /* OpcodeGroupField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E881DAB1C3996A200E509A9 /* OpcodeGroupField.swift */; }; + 6E894BF41C83B51B00109F45 /* AddressType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E894BF31C83B51B00109F45 /* AddressType.swift */; }; 6E92A4281C15309B007BC4E9 /* BlueZ.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E92A4271C15309B007BC4E9 /* BlueZ.h */; settings = {ATTRIBUTES = (Public, ); }; }; 6E92A4371C1530EF007BC4E9 /* Adapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E92A4321C1530EF007BC4E9 /* Adapter.swift */; }; 6E92A4381C1530EF007BC4E9 /* Address.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E92A4331C1530EF007BC4E9 /* Address.swift */; }; @@ -74,6 +75,7 @@ 6E881DA51C398D0C00E509A9 /* Headers */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Headers; path = ../Headers; sourceTree = ""; }; 6E881DA91C39934200E509A9 /* HCICommandParameter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HCICommandParameter.swift; sourceTree = ""; }; 6E881DAB1C3996A200E509A9 /* OpcodeGroupField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpcodeGroupField.swift; sourceTree = ""; }; + 6E894BF31C83B51B00109F45 /* AddressType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddressType.swift; sourceTree = ""; }; 6E92A4241C15309B007BC4E9 /* BlueZ.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BlueZ.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 6E92A4271C15309B007BC4E9 /* BlueZ.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BlueZ.h; sourceTree = ""; }; 6E92A4291C15309B007BC4E9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -192,6 +194,7 @@ 6E0C5BC71C83805200AF63E5 /* Daemon */, 6E0C5BB81C8373DB00AF63E5 /* Darwin.swift */, 6E92A4331C1530EF007BC4E9 /* Address.swift */, + 6E894BF31C83B51B00109F45 /* AddressType.swift */, 6E0C5BD91C83AAC000AF63E5 /* UUID.swift */, 6E92A4321C1530EF007BC4E9 /* Adapter.swift */, 6E15524F1C3A42FE002CC322 /* Error.swift */, @@ -332,6 +335,7 @@ 6E1552461C39A045002CC322 /* HCIEvent.swift in Sources */, 6E0C5BCD1C83865B00AF63E5 /* GATTServer.swift in Sources */, 6E0C5BDA1C83AAC000AF63E5 /* UUID.swift in Sources */, + 6E894BF41C83B51B00109F45 /* AddressType.swift in Sources */, 6E92A4371C1530EF007BC4E9 /* Adapter.swift in Sources */, 6E0C5BB91C8373DB00AF63E5 /* Darwin.swift in Sources */, 6E881D7C1C38832400E509A9 /* DeviceCommand.swift in Sources */, From 63c093df138c77ea530b1fa8e078470e01cabd13 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Sun, 28 Feb 2016 18:55:08 -0500 Subject: [PATCH 08/18] working on test tools to compile on Linux --- Sources/ScanTest/ScanTest.swift | 3 ++- Sources/ScanTest/main.swift | 3 ++- Sources/iBeaconTest/iBeaconTest.swift | 3 ++- Sources/iBeaconTest/main.swift | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Sources/ScanTest/ScanTest.swift b/Sources/ScanTest/ScanTest.swift index 9c2d96e..6427e9f 100644 --- a/Sources/ScanTest/ScanTest.swift +++ b/Sources/ScanTest/ScanTest.swift @@ -7,9 +7,10 @@ // #if os(Linux) + import BlueZ import CBlueZ + import CBlueZInternal import Glibc - import BlueZ #elseif os(OSX) || os(iOS) import Darwin.C #endif diff --git a/Sources/ScanTest/main.swift b/Sources/ScanTest/main.swift index e87873b..2e2ce29 100644 --- a/Sources/ScanTest/main.swift +++ b/Sources/ScanTest/main.swift @@ -7,9 +7,10 @@ // #if os(Linux) + import BlueZ import CBlueZ + import CBlueZInternal import Glibc - import BlueZ #elseif os(OSX) || os(iOS) import Darwin.C #endif diff --git a/Sources/iBeaconTest/iBeaconTest.swift b/Sources/iBeaconTest/iBeaconTest.swift index d95c0d3..a59bfd9 100644 --- a/Sources/iBeaconTest/iBeaconTest.swift +++ b/Sources/iBeaconTest/iBeaconTest.swift @@ -7,9 +7,10 @@ // #if os(Linux) + import BlueZ import CBlueZ + import CBlueZInternal import Glibc - import BlueZ #elseif os(OSX) || os(iOS) import Darwin.C #endif diff --git a/Sources/iBeaconTest/main.swift b/Sources/iBeaconTest/main.swift index da557b4..2d7d75a 100644 --- a/Sources/iBeaconTest/main.swift +++ b/Sources/iBeaconTest/main.swift @@ -7,9 +7,10 @@ // #if os(Linux) + import BlueZ import CBlueZ + import CBlueZInternal import Glibc - import BlueZ #elseif os(OSX) || os(iOS) import Darwin.C #endif From feeeb581dde08eec8430516a6d768bbbd429cf4b Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Sun, 28 Feb 2016 20:35:29 -0500 Subject: [PATCH 09/18] removed BlueZ Internal stuff --- Package.swift | 1 - Sources/BlueZ/ATT.swift | 84 -------- Sources/BlueZ/Adapter.swift | 1 - Sources/BlueZ/DaemonAdapter.swift | 222 ---------------------- Sources/BlueZ/DaemonDevice.swift | 21 -- Sources/BlueZ/GATT.swift | 22 --- Sources/BlueZ/GATTDatabase.swift | 63 ------ Sources/BlueZ/GATTDatabaseAttribute.swift | 47 ----- Sources/BlueZ/GATTServer.swift | 39 ---- Sources/BlueZ/UUID.swift | 17 +- Sources/ScanTest/ScanTest.swift | 1 - Sources/ScanTest/main.swift | 1 - Sources/iBeaconTest/iBeaconTest.swift | 1 - Sources/iBeaconTest/main.swift | 1 - Xcode/BlueZ.xcodeproj/project.pbxproj | 42 ---- 15 files changed, 10 insertions(+), 553 deletions(-) delete mode 100644 Sources/BlueZ/ATT.swift delete mode 100644 Sources/BlueZ/DaemonAdapter.swift delete mode 100644 Sources/BlueZ/DaemonDevice.swift delete mode 100644 Sources/BlueZ/GATT.swift delete mode 100644 Sources/BlueZ/GATTDatabase.swift delete mode 100644 Sources/BlueZ/GATTDatabaseAttribute.swift delete mode 100644 Sources/BlueZ/GATTServer.swift diff --git a/Package.swift b/Package.swift index a6a8d53..83970da 100644 --- a/Package.swift +++ b/Package.swift @@ -4,7 +4,6 @@ let package = Package( name: "BlueZ", dependencies: [ .Package(url: "https://github.com/PureSwift/CBlueZ.git", majorVersion: 1), - .Package(url: "https://github.com/PureSwift/CBlueZInternal.git", majorVersion: 1), .Package(url: "https://github.com/PureSwift/SwiftFoundation.git", majorVersion: 1), ], targets: [ diff --git a/Sources/BlueZ/ATT.swift b/Sources/BlueZ/ATT.swift deleted file mode 100644 index 9d76ad6..0000000 --- a/Sources/BlueZ/ATT.swift +++ /dev/null @@ -1,84 +0,0 @@ -// -// ATT.swift -// BlueZ -// -// Created by Alsey Coleman Miller on 2/28/16. -// Copyright © 2016 PureSwift. All rights reserved. -// - -#if os(Linux) - import CBlueZ - import CBlueZInternal - import Glibc -#elseif os(OSX) || os(iOS) - import Darwin.C -#endif - -/// Handles the transport and encoding/decoding for the ATT protocol. -public final class ATT { - - /// Whether the file descriptor will be closed on deallocation. - public var closeFileDescriptor: Bool = false { - - willSet { bt_att_set_close_on_unref(internalPointer, newValue) } - } - - // MARK: - Internal Properties - - internal let internalPointer: COpaquePointer - - // MARK: - Initialization - - deinit { - - bt_att_unref(internalPointer) - } - - internal init(_ internalPointer: COpaquePointer) { - - assert(internalPointer != nil) - - self.internalPointer = internalPointer - } - - public init?(fileDescriptor: CInt, externalCrypto: Bool = false) { - - self.internalPointer = bt_att_new(fileDescriptor, externalCrypto) - - guard internalPointer != nil else { return nil } - } - - // MARK: - Methods - - - - // MARK: - Dynamic Properties - - public var fileDescriptor: CInt { - - return bt_att_get_fd(internalPointer) - } - - public var hasCrypto: Bool { - - return bt_att_has_crypto(internalPointer) - } -} - -// MARK: - Darwin Stubs - -#if os(OSX) || os(iOS) - - func bt_att_new(fd: CInt, _ externalCrypto: CBool) -> COpaquePointer { stub() } - - func bt_att_unref(att: COpaquePointer) { stub() } - - func bt_att_set_close_on_unref(att: COpaquePointer, _ doClose: CBool) { stub() } - - func bt_att_get_fd(att: COpaquePointer) -> CInt { stub() } - - func bt_att_has_crypto(att: COpaquePointer) -> CBool { stub() } - - - -#endif diff --git a/Sources/BlueZ/Adapter.swift b/Sources/BlueZ/Adapter.swift index 8f8d6e1..de1e378 100644 --- a/Sources/BlueZ/Adapter.swift +++ b/Sources/BlueZ/Adapter.swift @@ -8,7 +8,6 @@ #if os(Linux) import CBlueZ - import CBlueZInternal import Glibc #elseif os(OSX) || os(iOS) import Darwin.C diff --git a/Sources/BlueZ/DaemonAdapter.swift b/Sources/BlueZ/DaemonAdapter.swift deleted file mode 100644 index d6bb839..0000000 --- a/Sources/BlueZ/DaemonAdapter.swift +++ /dev/null @@ -1,222 +0,0 @@ -// -// DaemonAdapter.swift -// BlueZ -// -// Created by Alsey Coleman Miller on 2/28/16. -// Copyright © 2016 PureSwift. All rights reserved. -// - -#if os(Linux) - import CBlueZ - import CBlueZInternal - import Glibc -#elseif os(OSX) || os(iOS) - import Darwin.C -#endif - -import SwiftFoundation - -/// Adapter interface used in `bluetoothd`. -public final class DaemonAdapter { - - // MARK: - Class Properties - - public var defaultAdapter: DaemonAdapter? { - - let internalPointer = btd_adapter_get_default() - - guard internalPointer != nil else { return nil } - - let adapter = DaemonAdapter(internalPointer) - - return adapter - } - - /// Check if workaround for broken ATT server socket behavior is needed - /// where we need to connect an ATT client socket before pairing to get - /// early access to the ATT channel. - public var lowEnergyConnectBeforePairing: Bool { - - return btd_le_connect_before_pairing() - } - - // MARK: - Internal Properties - - internal let internalPointer: COpaquePointer - - // MARK: - Initialization - - deinit { - - btd_adapter_unref(internalPointer) - } - - internal init(_ internalPointer: COpaquePointer) { - - assert(internalPointer != nil) - - self.internalPointer = internalPointer - } - - public init?(address: Address) { - - var addressCopy = address - - self.internalPointer = withUnsafeMutablePointer(&addressCopy) { adapter_find($0) } - - guard internalPointer != nil else { return nil } - } - - public init?(identifier: CInt) { - - self.internalPointer = adapter_find_by_id(identifier) - - guard internalPointer != nil else { return nil } - } - - // MARK: - Class Methods - - public static func initialize() throws { - - let errorCode = adapter_init() - - guard errorCode == 0 else { throw POSIXError(rawValue: errorCode)! } - } - - public static func cleanup() { adapter_cleanup() } - - public static func shutdown() { adapter_shutdown() } - - // MARK: - Methods - - public func setDeviceClass(mayor mayor: UInt8, minor: UInt8) { - - btd_adapter_set_class(internalPointer, mayor, minor) - } - - public func setDeviceName(name: String) throws { - - let errorCode = adapter_set_name(internalPointer, name) - - guard errorCode == 0 else { throw POSIXError(rawValue: errorCode)! } - } - - public func GATTServerStart() throws { - - let errorCode = btd_adapter_gatt_server_start(internalPointer) - - guard errorCode == 0 else { throw POSIXError(rawValue: errorCode)! } - } - - public func GATTServerStop() { - - btd_adapter_gatt_server_stop(internalPointer) - } - - // MARK: - Dynamic Properties - - public var index: UInt16 { - - return btd_adapter_get_index(internalPointer) - } - - public var isDefault: Bool { - - return btd_adapter_is_default(internalPointer) - } - - public var pairable: Bool { - - return btd_adapter_get_pairable(internalPointer) - } - - public var powered: Bool { - - return btd_adapter_get_powered(internalPointer) - } - - public var connectable: Bool { - - return btd_adapter_get_connectable(internalPointer) - } - - public var deviceClass: UInt32 { - - return btd_adapter_get_class(internalPointer) - } - - public var database: GATTDatabase? { - - let databaseInternalPointer = btd_adapter_get_database(internalPointer) - - guard databaseInternalPointer != nil else { return nil } - - let database = GATTDatabase(databaseInternalPointer) - - return database - } - - public var deviceName: String { - - return String.fromCString(UnsafePointer(btd_adapter_get_name(internalPointer))) ?? "" - } - - public var address: Address { - - let addressPointer = btd_adapter_get_address(internalPointer) - - assert(addressPointer != nil, "Nil address pointer") - - return addressPointer.memory - } -} - -// MARK: - Darwin Stubs - -#if os(OSX) || os(iOS) - - func btd_adapter_unref(adapter: COpaquePointer) { stub() } - - func btd_adapter_get_default(_: Void) -> COpaquePointer { stub() } - - func adapter_find(address: UnsafePointer) -> COpaquePointer { stub() } - - func adapter_find_by_id(id: CInt) -> COpaquePointer { stub() } - - func adapter_init(_: Void) -> CInt { stub() } - - func adapter_cleanup(_: Void) { stub() } - - func adapter_shutdown(_: Void) { stub() } - - func btd_adapter_is_default(adapter: COpaquePointer) -> CBool { stub() } - - func btd_adapter_get_index(adapter: COpaquePointer) -> UInt16 { stub() } - - func btd_adapter_get_pairable(adapter: COpaquePointer) -> CBool { stub() } - - func btd_adapter_get_powered(adapter: COpaquePointer) -> CBool { stub() } - - func btd_adapter_get_connectable(adapter: COpaquePointer) -> CBool { stub() } - - func btd_adapter_get_database(adapter: COpaquePointer) -> COpaquePointer { stub() } - - func btd_adapter_get_class(adapter: COpaquePointer) -> UInt32 { stub() } - - func btd_adapter_get_name(adapter: COpaquePointer) -> UnsafePointer { stub() } - - func adapter_get_path(adapter: COpaquePointer) -> UnsafePointer { stub() } - - func btd_adapter_get_address(adapter: COpaquePointer) -> UnsafePointer { stub() } - - func adapter_set_name(adapter: COpaquePointer, _ name: UnsafePointer) -> CInt { stub() } - - func btd_adapter_set_class(adapter: COpaquePointer, _ major: UInt8, _ minor: UInt8) { stub() } - - func btd_le_connect_before_pairing(_: Void) -> CBool { stub() } - - func btd_adapter_gatt_server_start(adapter: COpaquePointer) -> CInt { stub() } - - func btd_adapter_gatt_server_stop(adapter: COpaquePointer) { stub() } - -#endif \ No newline at end of file diff --git a/Sources/BlueZ/DaemonDevice.swift b/Sources/BlueZ/DaemonDevice.swift deleted file mode 100644 index 74e714c..0000000 --- a/Sources/BlueZ/DaemonDevice.swift +++ /dev/null @@ -1,21 +0,0 @@ -// -// DaemonDevice.swift -// BlueZ -// -// Created by Alsey Coleman Miller on 2/28/16. -// Copyright © 2016 PureSwift. All rights reserved. -// - -#if os(Linux) - import CBlueZ - import CBlueZInternal - import Glibc -#elseif os(OSX) || os(iOS) - import Darwin.C -#endif - -/// Device interface used in `bluetoothd`. -public final class DaemonDevice { - - -} \ No newline at end of file diff --git a/Sources/BlueZ/GATT.swift b/Sources/BlueZ/GATT.swift deleted file mode 100644 index f255773..0000000 --- a/Sources/BlueZ/GATT.swift +++ /dev/null @@ -1,22 +0,0 @@ -// -// GATT.swift -// BlueZ -// -// Created by Alsey Coleman Miller on 2/28/16. -// Copyright © 2016 PureSwift. All rights reserved. -// - -// Provides namespace for GATT related types. - -/// BlueZ GATT -public struct GATT { - - typealias Server = GATTServer - - typealias Database = GATTDatabase -} - -public extension GATTDatabase { - - typealias Attribute = GATTDatabaseAttribute -} \ No newline at end of file diff --git a/Sources/BlueZ/GATTDatabase.swift b/Sources/BlueZ/GATTDatabase.swift deleted file mode 100644 index 149df9a..0000000 --- a/Sources/BlueZ/GATTDatabase.swift +++ /dev/null @@ -1,63 +0,0 @@ -// -// GattDatabase.swift -// BlueZ -// -// Created by Alsey Coleman Miller on 2/28/16. -// Copyright © 2016 PureSwift. All rights reserved. -// - -#if os(Linux) - import CBlueZ - import CBlueZInternal - import Glibc -#elseif os(OSX) || os(iOS) - import Darwin.C -#endif - -public final class GATTDatabase { - - // MARK: - Internal Properties - - internal let internalPointer: COpaquePointer - - // MARK: - Initialization - - internal init(_ internalPointer: COpaquePointer) { - - assert(internalPointer != nil) - - self.internalPointer = internalPointer - } - - public init?() { - - self.internalPointer = gatt_db_new() - - guard internalPointer != nil else { return } - } - - // MARK: - Methods - - - - // MARK: - Dynamic Properties - - public var isEmpty: Bool { - - return gatt_db_isempty(internalPointer) - } -} - -// MARK: - Darwin Stubs - -#if os(OSX) || os(iOS) - - func gatt_db_new(_: Void) -> COpaquePointer { stub() } - - func gatt_db_unref(db: COpaquePointer) { stub() } - - func gatt_db_isempty(db: COpaquePointer) -> CBool { stub() } - - func gatt_db_add_service() { stub() } - -#endif diff --git a/Sources/BlueZ/GATTDatabaseAttribute.swift b/Sources/BlueZ/GATTDatabaseAttribute.swift deleted file mode 100644 index 790f4c6..0000000 --- a/Sources/BlueZ/GATTDatabaseAttribute.swift +++ /dev/null @@ -1,47 +0,0 @@ -// -// GattDatabaseAttribute.swift -// BlueZ -// -// Created by Alsey Coleman Miller on 2/28/16. -// Copyright © 2016 PureSwift. All rights reserved. -// - -#if os(Linux) - import CBlueZ - import CBlueZInternal - import Glibc -#elseif os(OSX) || os(iOS) - import Darwin.C -#endif - -public final class GATTDatabaseAttribute { - - // MARK: - Internal Properties - - internal let internalPointer: COpaquePointer - - // MARK: - Initialization - - internal init(_ internalPointer: COpaquePointer) { - - assert(internalPointer != nil) - - self.internalPointer = internalPointer - } - - // MARK: - Methods - - - - // MARK: - Dynamic Properties - - -} - -// MARK: - Darwin Stubs - -#if os(OSX) || os(iOS) - - //func btd_adapter_unref(adapter: COpaquePointer) { stub() } - -#endif diff --git a/Sources/BlueZ/GATTServer.swift b/Sources/BlueZ/GATTServer.swift deleted file mode 100644 index 3b9555c..0000000 --- a/Sources/BlueZ/GATTServer.swift +++ /dev/null @@ -1,39 +0,0 @@ -// -// GattServer.swift -// BlueZ -// -// Created by Alsey Coleman Miller on 2/28/16. -// Copyright © 2016 PureSwift. All rights reserved. -// - -#if os(Linux) - import CBlueZ - import CBlueZInternal - import Glibc -#elseif os(OSX) || os(iOS) - import Darwin.C -#endif - -public final class GATTServer { - - // MARK: - Internal Properties - - internal let internalPointer: COpaquePointer - - // MARK: - Initialization - - internal init(_ internalPointer: COpaquePointer) { - - assert(internalPointer != nil) - - self.internalPointer = internalPointer - } - - // MARK: - Methods - - - - // MARK: - Dynamic Properties - - -} diff --git a/Sources/BlueZ/UUID.swift b/Sources/BlueZ/UUID.swift index 947bb8e..b171df0 100644 --- a/Sources/BlueZ/UUID.swift +++ b/Sources/BlueZ/UUID.swift @@ -15,10 +15,10 @@ import SwiftFoundation -public typealias BluezUUID = bt_uuid_t +public typealias BluetoothUUID = bt_uuid_t /* -public extension BluezUUID { +public extension BluetoothUUID { public init(_ value: UInt16) { @@ -52,12 +52,15 @@ public extension BluezUUID { } */ -/// Type of Bluetooth UUID. -public enum UUIDType: Int { +public extension BluetoothUUID { - case Bit16 = 16 - case Bit32 = 32 - case Bit128 = 128 + /// Type of Bluetooth UUID. + public enum UUIDType: Int { + + case Bit16 = 16 + case Bit32 = 32 + case Bit128 = 128 + } } // MARK: - Darwin Stubs diff --git a/Sources/ScanTest/ScanTest.swift b/Sources/ScanTest/ScanTest.swift index 6427e9f..3494b77 100644 --- a/Sources/ScanTest/ScanTest.swift +++ b/Sources/ScanTest/ScanTest.swift @@ -9,7 +9,6 @@ #if os(Linux) import BlueZ import CBlueZ - import CBlueZInternal import Glibc #elseif os(OSX) || os(iOS) import Darwin.C diff --git a/Sources/ScanTest/main.swift b/Sources/ScanTest/main.swift index 2e2ce29..6f066e0 100644 --- a/Sources/ScanTest/main.swift +++ b/Sources/ScanTest/main.swift @@ -9,7 +9,6 @@ #if os(Linux) import BlueZ import CBlueZ - import CBlueZInternal import Glibc #elseif os(OSX) || os(iOS) import Darwin.C diff --git a/Sources/iBeaconTest/iBeaconTest.swift b/Sources/iBeaconTest/iBeaconTest.swift index a59bfd9..0679d06 100644 --- a/Sources/iBeaconTest/iBeaconTest.swift +++ b/Sources/iBeaconTest/iBeaconTest.swift @@ -9,7 +9,6 @@ #if os(Linux) import BlueZ import CBlueZ - import CBlueZInternal import Glibc #elseif os(OSX) || os(iOS) import Darwin.C diff --git a/Sources/iBeaconTest/main.swift b/Sources/iBeaconTest/main.swift index 2d7d75a..c2f205e 100644 --- a/Sources/iBeaconTest/main.swift +++ b/Sources/iBeaconTest/main.swift @@ -9,7 +9,6 @@ #if os(Linux) import BlueZ import CBlueZ - import CBlueZInternal import Glibc #elseif os(OSX) || os(iOS) import Darwin.C diff --git a/Xcode/BlueZ.xcodeproj/project.pbxproj b/Xcode/BlueZ.xcodeproj/project.pbxproj index 8f4b357..3f0cabe 100644 --- a/Xcode/BlueZ.xcodeproj/project.pbxproj +++ b/Xcode/BlueZ.xcodeproj/project.pbxproj @@ -11,12 +11,6 @@ 6E0C5BC21C837AA700AF63E5 /* ScanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BBE1C8379D100AF63E5 /* ScanTest.swift */; }; 6E0C5BC31C837AAA00AF63E5 /* iBeaconTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BC01C837A9F00AF63E5 /* iBeaconTest.swift */; }; 6E0C5BC51C837B7700AF63E5 /* TestError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BC41C837B7700AF63E5 /* TestError.swift */; }; - 6E0C5BC91C83807700AF63E5 /* DaemonAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BC81C83807700AF63E5 /* DaemonAdapter.swift */; }; - 6E0C5BCB1C83865000AF63E5 /* GATTDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BCA1C83865000AF63E5 /* GATTDatabase.swift */; }; - 6E0C5BCD1C83865B00AF63E5 /* GATTServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BCC1C83865B00AF63E5 /* GATTServer.swift */; }; - 6E0C5BCF1C83889900AF63E5 /* DaemonDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BCE1C83889900AF63E5 /* DaemonDevice.swift */; }; - 6E0C5BD11C839C5D00AF63E5 /* GATTDatabaseAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BD01C839C5D00AF63E5 /* GATTDatabaseAttribute.swift */; }; - 6E0C5BD41C839E1C00AF63E5 /* ATT.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BD31C839E1C00AF63E5 /* ATT.swift */; }; 6E0C5BD81C83A45100AF63E5 /* SecurityType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BD71C83A45100AF63E5 /* SecurityType.swift */; }; 6E0C5BDA1C83AAC000AF63E5 /* UUID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BD91C83AAC000AF63E5 /* UUID.swift */; }; 6E1552461C39A045002CC322 /* HCIEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E1552451C39A045002CC322 /* HCIEvent.swift */; }; @@ -50,13 +44,6 @@ 6E0C5BC01C837A9F00AF63E5 /* iBeaconTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iBeaconTest.swift; sourceTree = ""; }; 6E0C5BC11C837A9F00AF63E5 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; 6E0C5BC41C837B7700AF63E5 /* TestError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestError.swift; sourceTree = ""; }; - 6E0C5BC81C83807700AF63E5 /* DaemonAdapter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DaemonAdapter.swift; sourceTree = ""; }; - 6E0C5BCA1C83865000AF63E5 /* GATTDatabase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GATTDatabase.swift; sourceTree = ""; }; - 6E0C5BCC1C83865B00AF63E5 /* GATTServer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GATTServer.swift; sourceTree = ""; }; - 6E0C5BCE1C83889900AF63E5 /* DaemonDevice.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DaemonDevice.swift; sourceTree = ""; }; - 6E0C5BD01C839C5D00AF63E5 /* GATTDatabaseAttribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GATTDatabaseAttribute.swift; sourceTree = ""; }; - 6E0C5BD31C839E1C00AF63E5 /* ATT.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ATT.swift; sourceTree = ""; }; - 6E0C5BD51C839E9400AF63E5 /* GATT.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GATT.swift; sourceTree = ""; }; 6E0C5BD71C83A45100AF63E5 /* SecurityType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecurityType.swift; sourceTree = ""; }; 6E0C5BD91C83AAC000AF63E5 /* UUID.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UUID.swift; sourceTree = ""; }; 6E1552451C39A045002CC322 /* HCIEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HCIEvent.swift; sourceTree = ""; }; @@ -128,26 +115,6 @@ path = ../Sources/iBeaconTest; sourceTree = ""; }; - 6E0C5BC71C83805200AF63E5 /* Daemon */ = { - isa = PBXGroup; - children = ( - 6E0C5BC81C83807700AF63E5 /* DaemonAdapter.swift */, - 6E0C5BCE1C83889900AF63E5 /* DaemonDevice.swift */, - ); - name = Daemon; - sourceTree = ""; - }; - 6E0C5BD21C839C9A00AF63E5 /* GATT */ = { - isa = PBXGroup; - children = ( - 6E0C5BD51C839E9400AF63E5 /* GATT.swift */, - 6E0C5BCA1C83865000AF63E5 /* GATTDatabase.swift */, - 6E0C5BD01C839C5D00AF63E5 /* GATTDatabaseAttribute.swift */, - 6E0C5BCC1C83865B00AF63E5 /* GATTServer.swift */, - ); - name = GATT; - sourceTree = ""; - }; 6E795E951C48B815002377FE /* HCI Event */ = { isa = PBXGroup; children = ( @@ -189,9 +156,6 @@ 6E92A4311C1530EF007BC4E9 /* Source */ = { isa = PBXGroup; children = ( - 6E0C5BD31C839E1C00AF63E5 /* ATT.swift */, - 6E0C5BD21C839C9A00AF63E5 /* GATT */, - 6E0C5BC71C83805200AF63E5 /* Daemon */, 6E0C5BB81C8373DB00AF63E5 /* Darwin.swift */, 6E92A4331C1530EF007BC4E9 /* Address.swift */, 6E894BF31C83B51B00109F45 /* AddressType.swift */, @@ -306,24 +270,19 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 6E0C5BD11C839C5D00AF63E5 /* GATTDatabaseAttribute.swift in Sources */, 6E795E891C47EC90002377FE /* LowEnergyCommand.swift in Sources */, 6E15524C1C39C08A002CC322 /* OpcodeCommandField.swift in Sources */, - 6E0C5BD41C839E1C00AF63E5 /* ATT.swift in Sources */, 6E881DAC1C3996A200E509A9 /* OpcodeGroupField.swift in Sources */, 6E15524A1C39A284002CC322 /* LowEnergyAddressType.swift in Sources */, 6E0C5BC31C837AAA00AF63E5 /* iBeaconTest.swift in Sources */, 6E0C5BD81C83A45100AF63E5 /* SecurityType.swift in Sources */, 6E92A43B1C1530EF007BC4E9 /* Scan.swift in Sources */, - 6E0C5BCB1C83865000AF63E5 /* GATTDatabase.swift in Sources */, 6E795E941C48B80F002377FE /* LowEnergyEvent.swift in Sources */, 6E881D821C389F4B00E509A9 /* iBeacon.swift in Sources */, - 6E0C5BCF1C83889900AF63E5 /* DaemonDevice.swift in Sources */, 6E92A4381C1530EF007BC4E9 /* Address.swift in Sources */, 6E881DAA1C39934200E509A9 /* HCICommandParameter.swift in Sources */, 6E881DA21C39812F00E509A9 /* DeviceRequest.swift in Sources */, 6E1552501C3A42FE002CC322 /* Error.swift in Sources */, - 6E0C5BC91C83807700AF63E5 /* DaemonAdapter.swift in Sources */, 6E0C5BC51C837B7700AF63E5 /* TestError.swift in Sources */, 6E1552481C39A18A002CC322 /* HCIError.swift in Sources */, 6E795E901C489FE7002377FE /* LowEnergyCommandParameter.swift in Sources */, @@ -333,7 +292,6 @@ 6ECB305D1C47613F004CCA68 /* LinkControlCommand.swift in Sources */, 6ECB30601C47618E004CCA68 /* HCICommand.swift in Sources */, 6E1552461C39A045002CC322 /* HCIEvent.swift in Sources */, - 6E0C5BCD1C83865B00AF63E5 /* GATTServer.swift in Sources */, 6E0C5BDA1C83AAC000AF63E5 /* UUID.swift in Sources */, 6E894BF41C83B51B00109F45 /* AddressType.swift in Sources */, 6E92A4371C1530EF007BC4E9 /* Adapter.swift in Sources */, From de6603b3cbbb25188adbb8169e80580365415348 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Sun, 28 Feb 2016 20:53:58 -0500 Subject: [PATCH 10/18] disabled BluetoothUUID Swift compiler crashes --- Sources/BlueZ/UUID.swift | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/Sources/BlueZ/UUID.swift b/Sources/BlueZ/UUID.swift index b171df0..3ec1fe3 100644 --- a/Sources/BlueZ/UUID.swift +++ b/Sources/BlueZ/UUID.swift @@ -15,28 +15,42 @@ import SwiftFoundation -public typealias BluetoothUUID = bt_uuid_t +/// Bluetooth UUID used with BlueZ. +public struct BluetoothUUID: ByteValueType { + + public typealias ByteValue = UUID.ByteValue + + public var byteValue: UUID.ByteValue + + public init(byteValue: UUID.ByteValue) { + + self.byteValue = byteValue + } +} /* public extension BluetoothUUID { - public init(_ value: UInt16) { + public init?(_ value: UInt16) { - var uuid = bt_uuid_t() + let pointer = UnsafeMutablePointer.alloc(1) - bt_uuid16_create(&uuid, value) + defer { pointer.dealloc(1) } - self = uuid + bt_uuid16_create(pointer, value) + + self.byteValue = } + /* public init(_ value: UInt32) { var uuid = bt_uuid_t() bt_uuid32_create(&uuid, value) - self = uuid - } + self.byteValue = uuid + }*/ // https://bugs.swift.org/browse/SR-847 /* @@ -49,8 +63,7 @@ public extension BluetoothUUID { self = uuid }*/ -} -*/ +}*/ public extension BluetoothUUID { @@ -72,6 +85,10 @@ public extension BluetoothUUID { public struct bt_uuid_t { public init() { stub() } + + //public var type: CInt + + //public var value: UInt128 } func bt_uuid16_create(btuuid: UnsafeMutablePointer, _ value: UInt16) -> CInt { stub() } From 85492d922a7ab114e1d6a055f47c10c5830e312e Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Sun, 28 Feb 2016 21:55:34 -0500 Subject: [PATCH 11/18] refactored TestError and added PeripheralTest --- Package.swift | 3 ++ Sources/PeripheralTest/PeripheralTest.swift | 22 +++++++++++++ Sources/PeripheralTest/main.swift | 35 +++++++++++++++++++++ Sources/ScanTest/TestError.swift | 19 ----------- Sources/ScanTest/main.swift | 6 ++++ Sources/iBeaconTest/TestError.swift | 23 +------------- Sources/iBeaconTest/main.swift | 6 ++++ Xcode/BlueZ.xcodeproj/project.pbxproj | 23 +++++++++++--- 8 files changed, 91 insertions(+), 46 deletions(-) create mode 100644 Sources/PeripheralTest/PeripheralTest.swift create mode 100644 Sources/PeripheralTest/main.swift delete mode 100644 Sources/ScanTest/TestError.swift mode change 100644 => 120000 Sources/iBeaconTest/TestError.swift diff --git a/Package.swift b/Package.swift index 83970da..f931bc7 100644 --- a/Package.swift +++ b/Package.swift @@ -13,6 +13,9 @@ let package = Package( Target( name: "iBeaconTest", dependencies: [.Target(name: "BlueZ")]), + Target( + name: "PeripheralTest", + dependencies: [.Target(name: "BlueZ")]), Target( name: "BlueZ") ] diff --git a/Sources/PeripheralTest/PeripheralTest.swift b/Sources/PeripheralTest/PeripheralTest.swift new file mode 100644 index 0000000..24be0ea --- /dev/null +++ b/Sources/PeripheralTest/PeripheralTest.swift @@ -0,0 +1,22 @@ +// +// PeripheralTest.swift +// BlueZ +// +// Created by Alsey Coleman Miller on 2/28/16. +// Copyright © 2016 PureSwift. All rights reserved. +// + +#if os(Linux) + import BlueZ + import CBlueZ + import Glibc +#elseif os(OSX) || os(iOS) + import Darwin.C +#endif + +import SwiftFoundation + +func PeripheralTest(adapter: Adapter) { + + +} \ No newline at end of file diff --git a/Sources/PeripheralTest/main.swift b/Sources/PeripheralTest/main.swift new file mode 100644 index 0000000..4986fa5 --- /dev/null +++ b/Sources/PeripheralTest/main.swift @@ -0,0 +1,35 @@ +// +// main.swift +// BlueZ +// +// Created by Alsey Coleman Miller on 12/6/15. +// Copyright © 2015 PureSwift. All rights reserved. +// + +#if os(Linux) + import BlueZ + import CBlueZ + import Glibc +#elseif os(OSX) || os(iOS) + import Darwin.C +#endif + +import SwiftFoundation + +@noreturn func Error(text: String) { + print(text) + exit(1) +} + +// get Bluetooth device + +guard let adapter = Adapter() + else { Error("No Bluetooth adapters found") } + +print("Found Bluetooth adapter with device ID: \(adapter.identifier)") + +print("Address: \(adapter.address!)") + +/// Perform Test +PeripheralTest(adapter) + diff --git a/Sources/ScanTest/TestError.swift b/Sources/ScanTest/TestError.swift deleted file mode 100644 index f21a384..0000000 --- a/Sources/ScanTest/TestError.swift +++ /dev/null @@ -1,19 +0,0 @@ -// -// Error.swift -// BlueZ -// -// Created by Alsey Coleman Miller on 1/12/16. -// Copyright © 2016 PureSwift. All rights reserved. -// - -#if os(Linux) - import Glibc -#elseif os(OSX) || os(iOS) - import Darwin.C -#endif - -@noreturn func Error(text: String) { - - print(text) - exit(1) -} \ No newline at end of file diff --git a/Sources/ScanTest/main.swift b/Sources/ScanTest/main.swift index 6f066e0..6da1223 100644 --- a/Sources/ScanTest/main.swift +++ b/Sources/ScanTest/main.swift @@ -16,6 +16,12 @@ import SwiftFoundation +@noreturn func Error(text: String) { + + print(text) + exit(1) +} + // get Bluetooth device guard let adapter = Adapter() diff --git a/Sources/iBeaconTest/TestError.swift b/Sources/iBeaconTest/TestError.swift deleted file mode 100644 index 249f925..0000000 --- a/Sources/iBeaconTest/TestError.swift +++ /dev/null @@ -1,22 +0,0 @@ -// -// Error.swift -// BlueZ -// -// Created by Alsey Coleman Miller on 1/12/16. -// Copyright © 2016 PureSwift. All rights reserved. -// - -#if os(Linux) - import CBlueZ - import Glibc - import BlueZ -#elseif os(OSX) || os(iOS) - import Darwin.C -#endif - -@noreturn func Error(text: String) { - - print(text) - - exit(1) -} \ No newline at end of file diff --git a/Sources/iBeaconTest/TestError.swift b/Sources/iBeaconTest/TestError.swift new file mode 120000 index 0000000..da49677 --- /dev/null +++ b/Sources/iBeaconTest/TestError.swift @@ -0,0 +1 @@ +/home/coleman/Desktop/Parallels Shared Folders/Developer/BlueZ/Sources/ScanTest/TestError.swift \ No newline at end of file diff --git a/Sources/iBeaconTest/main.swift b/Sources/iBeaconTest/main.swift index c2f205e..71e8b9c 100644 --- a/Sources/iBeaconTest/main.swift +++ b/Sources/iBeaconTest/main.swift @@ -16,6 +16,12 @@ import SwiftFoundation +@noreturn func Error(text: String) { + + print(text) + exit(1) +} + // get Bluetooth device guard let adapter = Adapter() diff --git a/Xcode/BlueZ.xcodeproj/project.pbxproj b/Xcode/BlueZ.xcodeproj/project.pbxproj index 3f0cabe..b394dff 100644 --- a/Xcode/BlueZ.xcodeproj/project.pbxproj +++ b/Xcode/BlueZ.xcodeproj/project.pbxproj @@ -10,7 +10,6 @@ 6E0C5BB91C8373DB00AF63E5 /* Darwin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BB81C8373DB00AF63E5 /* Darwin.swift */; }; 6E0C5BC21C837AA700AF63E5 /* ScanTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BBE1C8379D100AF63E5 /* ScanTest.swift */; }; 6E0C5BC31C837AAA00AF63E5 /* iBeaconTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BC01C837A9F00AF63E5 /* iBeaconTest.swift */; }; - 6E0C5BC51C837B7700AF63E5 /* TestError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BC41C837B7700AF63E5 /* TestError.swift */; }; 6E0C5BD81C83A45100AF63E5 /* SecurityType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BD71C83A45100AF63E5 /* SecurityType.swift */; }; 6E0C5BDA1C83AAC000AF63E5 /* UUID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BD91C83AAC000AF63E5 /* UUID.swift */; }; 6E1552461C39A045002CC322 /* HCIEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E1552451C39A045002CC322 /* HCIEvent.swift */; }; @@ -29,6 +28,8 @@ 6E881DAA1C39934200E509A9 /* HCICommandParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E881DA91C39934200E509A9 /* HCICommandParameter.swift */; }; 6E881DAC1C3996A200E509A9 /* OpcodeGroupField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E881DAB1C3996A200E509A9 /* OpcodeGroupField.swift */; }; 6E894BF41C83B51B00109F45 /* AddressType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E894BF31C83B51B00109F45 /* AddressType.swift */; }; + 6E894BF71C83DE7200109F45 /* PeripheralTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E894BF61C83DE7200109F45 /* PeripheralTest.swift */; }; + 6E894C001C83EA2000109F45 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BBD1C8379D100AF63E5 /* main.swift */; }; 6E92A4281C15309B007BC4E9 /* BlueZ.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E92A4271C15309B007BC4E9 /* BlueZ.h */; settings = {ATTRIBUTES = (Public, ); }; }; 6E92A4371C1530EF007BC4E9 /* Adapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E92A4321C1530EF007BC4E9 /* Adapter.swift */; }; 6E92A4381C1530EF007BC4E9 /* Address.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E92A4331C1530EF007BC4E9 /* Address.swift */; }; @@ -43,7 +44,6 @@ 6E0C5BBE1C8379D100AF63E5 /* ScanTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanTest.swift; sourceTree = ""; }; 6E0C5BC01C837A9F00AF63E5 /* iBeaconTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iBeaconTest.swift; sourceTree = ""; }; 6E0C5BC11C837A9F00AF63E5 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; - 6E0C5BC41C837B7700AF63E5 /* TestError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestError.swift; sourceTree = ""; }; 6E0C5BD71C83A45100AF63E5 /* SecurityType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecurityType.swift; sourceTree = ""; }; 6E0C5BD91C83AAC000AF63E5 /* UUID.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UUID.swift; sourceTree = ""; }; 6E1552451C39A045002CC322 /* HCIEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HCIEvent.swift; sourceTree = ""; }; @@ -63,6 +63,8 @@ 6E881DA91C39934200E509A9 /* HCICommandParameter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HCICommandParameter.swift; sourceTree = ""; }; 6E881DAB1C3996A200E509A9 /* OpcodeGroupField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpcodeGroupField.swift; sourceTree = ""; }; 6E894BF31C83B51B00109F45 /* AddressType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddressType.swift; sourceTree = ""; }; + 6E894BF61C83DE7200109F45 /* PeripheralTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PeripheralTest.swift; sourceTree = ""; }; + 6E894BF81C83DE8E00109F45 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; 6E92A4241C15309B007BC4E9 /* BlueZ.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BlueZ.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 6E92A4271C15309B007BC4E9 /* BlueZ.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BlueZ.h; sourceTree = ""; }; 6E92A4291C15309B007BC4E9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -88,6 +90,7 @@ 6E0C5BBA1C83794700AF63E5 /* Tests */ = { isa = PBXGroup; children = ( + 6E894BF51C83DE5800109F45 /* PeripheralTest */, 6E0C5BBF1C837A9F00AF63E5 /* iBeaconTest */, 6E0C5BBC1C8379D100AF63E5 /* ScanTest */, ); @@ -99,7 +102,6 @@ children = ( 6E0C5BBD1C8379D100AF63E5 /* main.swift */, 6E0C5BBE1C8379D100AF63E5 /* ScanTest.swift */, - 6E0C5BC41C837B7700AF63E5 /* TestError.swift */, ); name = ScanTest; path = ../Sources/ScanTest; @@ -108,8 +110,8 @@ 6E0C5BBF1C837A9F00AF63E5 /* iBeaconTest */ = { isa = PBXGroup; children = ( - 6E0C5BC01C837A9F00AF63E5 /* iBeaconTest.swift */, 6E0C5BC11C837A9F00AF63E5 /* main.swift */, + 6E0C5BC01C837A9F00AF63E5 /* iBeaconTest.swift */, ); name = iBeaconTest; path = ../Sources/iBeaconTest; @@ -124,6 +126,16 @@ name = "HCI Event"; sourceTree = ""; }; + 6E894BF51C83DE5800109F45 /* PeripheralTest */ = { + isa = PBXGroup; + children = ( + 6E894BF81C83DE8E00109F45 /* main.swift */, + 6E894BF61C83DE7200109F45 /* PeripheralTest.swift */, + ); + name = PeripheralTest; + path = ../Sources/PeripheralTest; + sourceTree = ""; + }; 6E92A41A1C15309B007BC4E9 = { isa = PBXGroup; children = ( @@ -283,8 +295,8 @@ 6E881DAA1C39934200E509A9 /* HCICommandParameter.swift in Sources */, 6E881DA21C39812F00E509A9 /* DeviceRequest.swift in Sources */, 6E1552501C3A42FE002CC322 /* Error.swift in Sources */, - 6E0C5BC51C837B7700AF63E5 /* TestError.swift in Sources */, 6E1552481C39A18A002CC322 /* HCIError.swift in Sources */, + 6E894BF71C83DE7200109F45 /* PeripheralTest.swift in Sources */, 6E795E901C489FE7002377FE /* LowEnergyCommandParameter.swift in Sources */, 6E795E9B1C49821B002377FE /* LinkMode.swift in Sources */, 6E795E921C48A186002377FE /* LinkControlCommandParameter.swift in Sources */, @@ -292,6 +304,7 @@ 6ECB305D1C47613F004CCA68 /* LinkControlCommand.swift in Sources */, 6ECB30601C47618E004CCA68 /* HCICommand.swift in Sources */, 6E1552461C39A045002CC322 /* HCIEvent.swift in Sources */, + 6E894C001C83EA2000109F45 /* main.swift in Sources */, 6E0C5BDA1C83AAC000AF63E5 /* UUID.swift in Sources */, 6E894BF41C83B51B00109F45 /* AddressType.swift in Sources */, 6E92A4371C1530EF007BC4E9 /* Adapter.swift in Sources */, From 3a1f49efbc041d1fdcf0202107d1f4c962adf34b Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Sun, 28 Feb 2016 23:09:29 -0500 Subject: [PATCH 12/18] working on L2CAP server --- Sources/BlueZ/Adapter.swift | 12 ++-- Sources/BlueZ/AddressType.swift | 9 +-- Sources/BlueZ/DeviceCommand.swift | 2 +- Sources/BlueZ/DeviceRequest.swift | 2 +- Sources/BlueZ/L2CAP.swift | 81 +++++++++++++++++++++++++++ Sources/BlueZ/Scan.swift | 2 +- Xcode/BlueZ.xcodeproj/project.pbxproj | 4 ++ 7 files changed, 99 insertions(+), 13 deletions(-) create mode 100644 Sources/BlueZ/L2CAP.swift diff --git a/Sources/BlueZ/Adapter.swift b/Sources/BlueZ/Adapter.swift index de1e378..916c1ca 100644 --- a/Sources/BlueZ/Adapter.swift +++ b/Sources/BlueZ/Adapter.swift @@ -21,15 +21,15 @@ public final class Adapter { /// The device identifier of the Bluetooth adapter. public let identifier: CInt - // MARK: - Private Properties + // MARK: - Internal Properties - internal let socket: CInt + internal let internalSocket: CInt // MARK: - Initizalization deinit { - close(socket) + close(internalSocket) } /// Initializes the Bluetooth Adapter with the specified address. @@ -49,11 +49,11 @@ public final class Adapter { self.identifier = hci_get_route(addressPointer) guard self.identifier != -1 - else { self.socket = -1; return nil } // cant be -1 + else { self.internalSocket = -1; return nil } // cant be -1 - self.socket = hci_open_dev(identifier) + self.internalSocket = hci_open_dev(identifier) - guard socket != -1 else { return nil } // cant be -1 + guard internalSocket != -1 else { return nil } // cant be -1 } } diff --git a/Sources/BlueZ/AddressType.swift b/Sources/BlueZ/AddressType.swift index b85efc9..a317ad7 100644 --- a/Sources/BlueZ/AddressType.swift +++ b/Sources/BlueZ/AddressType.swift @@ -6,11 +6,12 @@ // Copyright © 2016 PureSwift. All rights reserved. // -public enum AddressType { +/// BlueZ Address type +public enum AddressType: CInt { - case BDR - case LowEnergyRandom - case LowEnergyPublic + case BREDR = 0x00 + case LowEnergyRandom = 0x01 + case LowEnergyPublic = 0x02 /// Whether the Bluetooth address type is LE. public var isLowEnergy: Bool { diff --git a/Sources/BlueZ/DeviceCommand.swift b/Sources/BlueZ/DeviceCommand.swift index aa73163..e2b465a 100644 --- a/Sources/BlueZ/DeviceCommand.swift +++ b/Sources/BlueZ/DeviceCommand.swift @@ -28,7 +28,7 @@ public extension Adapter { let voidPointer = UnsafeMutablePointer(pointer) - return hci_send_cmd(socket, UInt16(Command.opcodeGroupField.rawValue), command.rawValue, UInt8(CommandParameter.dataLength), voidPointer) == 0 + return hci_send_cmd(internalSocket, UInt16(Command.opcodeGroupField.rawValue), command.rawValue, UInt8(CommandParameter.dataLength), voidPointer) == 0 } } } diff --git a/Sources/BlueZ/DeviceRequest.swift b/Sources/BlueZ/DeviceRequest.swift index 9b296ae..ffdcbbb 100644 --- a/Sources/BlueZ/DeviceRequest.swift +++ b/Sources/BlueZ/DeviceRequest.swift @@ -51,7 +51,7 @@ public extension Adapter { try withUnsafeMutablePointer(&request) { (pointer) throws in - guard hci_send_req(socket, pointer, CInt(timeout)) == 0 + guard hci_send_req(internalSocket, pointer, CInt(timeout)) == 0 else { throw POSIXError.fromErrorNumber! } } diff --git a/Sources/BlueZ/L2CAP.swift b/Sources/BlueZ/L2CAP.swift new file mode 100644 index 0000000..c11fb7e --- /dev/null +++ b/Sources/BlueZ/L2CAP.swift @@ -0,0 +1,81 @@ +// +// L2CAP.swift +// BlueZ +// +// Created by Alsey Coleman Miller on 2/28/16. +// Copyright © 2016 PureSwift. All rights reserved. +// + +#if os(Linux) + import CBlueZ + import Glibc +#elseif os(OSX) || os(iOS) + import Darwin.C +#endif + +import SwiftFoundation + +/// L2CAP Bluetooth Server socket +public final class L2CAPServer { + + // MARK: - Properties + + // MARK: - Internal Properties + + internal let internalSocket: CInt + + // MARK: - Initialization + + deinit { + + close(internalSocket) + } + + /// Create a new L2CAP server on the adapter with the specified address. + public init(address: Address? = nil, port: CUnsignedShort = 0x1001) throws { + + // allocate socket + self.internalSocket = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP) + + // error creating socket + guard internalSocket == 0 else { throw POSIXError.fromErrorNumber! } + + + var localAddress = sockaddr_l2() + localAddress.l2_family = sa_family_t(AF_BLUETOOTH) + localAddress.l2_psm = port + localAddress.l2_bdaddr = address ?? Address(byteValue: (0, 0, 0, 0, 0, 0)) // BDADDR_ANY + + let socketLength = socklen_t(sizeof(sockaddr_l2)) + + // bind socket to port and address + guard withUnsafePointer(&localAddress, { bind(internalSocket, UnsafePointer($0), socketLength) }) == 0 + else { close(internalSocket); throw POSIXError.fromErrorNumber! } + + + + } +} + + +// MARK: - Darwin Stubs + +#if os(OSX) || os(iOS) + + let AF_BLUETOOTH: CInt = 31 + + let BTPROTO_L2CAP: CInt = 0 + + /// L2CAP socket address + struct sockaddr_l2 { + var l2_family: sa_family_t + var l2_psm: CUnsignedShort + var l2_bdaddr: bdaddr_t + var l2_cid: CUnsignedShort + var l2_bdaddr_type: UInt8 + init() { stub() } + } + + + +#endif diff --git a/Sources/BlueZ/Scan.swift b/Sources/BlueZ/Scan.swift index f38f371..884792a 100644 --- a/Sources/BlueZ/Scan.swift +++ b/Sources/BlueZ/Scan.swift @@ -79,7 +79,7 @@ public extension Adapter { let nameBuffer = UnsafeMutablePointer.alloc(maxNameLength) defer { nameBuffer.dealloc(maxNameLength) } - guard hci_read_remote_name(socket, &address, CInt(maxNameLength), nameBuffer, CInt(timeout)) == CInt(0) + guard hci_read_remote_name(internalSocket, &address, CInt(maxNameLength), nameBuffer, CInt(timeout)) == CInt(0) else { throw POSIXError.fromErrorNumber! } let name = String.fromCString(nameBuffer) diff --git a/Xcode/BlueZ.xcodeproj/project.pbxproj b/Xcode/BlueZ.xcodeproj/project.pbxproj index b394dff..a391059 100644 --- a/Xcode/BlueZ.xcodeproj/project.pbxproj +++ b/Xcode/BlueZ.xcodeproj/project.pbxproj @@ -30,6 +30,7 @@ 6E894BF41C83B51B00109F45 /* AddressType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E894BF31C83B51B00109F45 /* AddressType.swift */; }; 6E894BF71C83DE7200109F45 /* PeripheralTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E894BF61C83DE7200109F45 /* PeripheralTest.swift */; }; 6E894C001C83EA2000109F45 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BBD1C8379D100AF63E5 /* main.swift */; }; + 6E894C021C83F1C500109F45 /* L2CAP.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E894C011C83F1C500109F45 /* L2CAP.swift */; }; 6E92A4281C15309B007BC4E9 /* BlueZ.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E92A4271C15309B007BC4E9 /* BlueZ.h */; settings = {ATTRIBUTES = (Public, ); }; }; 6E92A4371C1530EF007BC4E9 /* Adapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E92A4321C1530EF007BC4E9 /* Adapter.swift */; }; 6E92A4381C1530EF007BC4E9 /* Address.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E92A4331C1530EF007BC4E9 /* Address.swift */; }; @@ -65,6 +66,7 @@ 6E894BF31C83B51B00109F45 /* AddressType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddressType.swift; sourceTree = ""; }; 6E894BF61C83DE7200109F45 /* PeripheralTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PeripheralTest.swift; sourceTree = ""; }; 6E894BF81C83DE8E00109F45 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; + 6E894C011C83F1C500109F45 /* L2CAP.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = L2CAP.swift; sourceTree = ""; }; 6E92A4241C15309B007BC4E9 /* BlueZ.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BlueZ.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 6E92A4271C15309B007BC4E9 /* BlueZ.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BlueZ.h; sourceTree = ""; }; 6E92A4291C15309B007BC4E9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -173,6 +175,7 @@ 6E894BF31C83B51B00109F45 /* AddressType.swift */, 6E0C5BD91C83AAC000AF63E5 /* UUID.swift */, 6E92A4321C1530EF007BC4E9 /* Adapter.swift */, + 6E894C011C83F1C500109F45 /* L2CAP.swift */, 6E15524F1C3A42FE002CC322 /* Error.swift */, 6E92A4361C1530EF007BC4E9 /* Scan.swift */, 6E881D7B1C38832400E509A9 /* DeviceCommand.swift */, @@ -307,6 +310,7 @@ 6E894C001C83EA2000109F45 /* main.swift in Sources */, 6E0C5BDA1C83AAC000AF63E5 /* UUID.swift in Sources */, 6E894BF41C83B51B00109F45 /* AddressType.swift in Sources */, + 6E894C021C83F1C500109F45 /* L2CAP.swift in Sources */, 6E92A4371C1530EF007BC4E9 /* Adapter.swift in Sources */, 6E0C5BB91C8373DB00AF63E5 /* Darwin.swift in Sources */, 6E881D7C1C38832400E509A9 /* DeviceCommand.swift in Sources */, From 2f79e341e6572b9329db91f3d8758b59ffe704d8 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Mon, 29 Feb 2016 01:13:46 -0500 Subject: [PATCH 13/18] working on L2CAP --- Sources/BlueZ/Address.swift | 7 ++- Sources/BlueZ/AddressType.swift | 5 +- Sources/BlueZ/Endianness.swift | 41 ++++++++++++ Sources/BlueZ/L2CAP.swift | 91 +++++++++++++++++++++++---- Xcode/BlueZ.xcodeproj/project.pbxproj | 4 ++ 5 files changed, 131 insertions(+), 17 deletions(-) create mode 100644 Sources/BlueZ/Endianness.swift diff --git a/Sources/BlueZ/Address.swift b/Sources/BlueZ/Address.swift index 3664e2a..3a64355 100644 --- a/Sources/BlueZ/Address.swift +++ b/Sources/BlueZ/Address.swift @@ -98,11 +98,12 @@ extension Address: CustomStringConvertible { public extension Address { /// Extracts the Bluetooth address from the device ID. - public init?(deviceIdentifier: CInt) { + public init(deviceIdentifier: CInt) throws { var address = bdaddr_t() - guard hci_devba(deviceIdentifier, &address) == 0 else { return nil } + guard hci_devba(deviceIdentifier, &address) == 0 + else { throw POSIXError.fromErrorNumber! } self = address } @@ -115,7 +116,7 @@ public extension Adapter { /// Fails if the Bluetooth adapter was disconnected or hardware failure. public var address: Address? { - return Address(deviceIdentifier: identifier) + return try? Address(deviceIdentifier: identifier) } } diff --git a/Sources/BlueZ/AddressType.swift b/Sources/BlueZ/AddressType.swift index a317ad7..412e0b9 100644 --- a/Sources/BlueZ/AddressType.swift +++ b/Sources/BlueZ/AddressType.swift @@ -7,8 +7,11 @@ // /// BlueZ Address type -public enum AddressType: CInt { +/// +/// - SeeAlso: [Ten Important Differences between Bluetooth BR/EDR and Bluetooth Smart](http://blog.bluetooth.com/ten-important-differences-between-bluetooth-bredr-and-bluetooth-smart/) +public enum AddressType: UInt8 { + /// Bluetooth Basic Rate/Enhanced Data Rate case BREDR = 0x00 case LowEnergyRandom = 0x01 case LowEnergyPublic = 0x02 diff --git a/Sources/BlueZ/Endianness.swift b/Sources/BlueZ/Endianness.swift new file mode 100644 index 0000000..bbf217e --- /dev/null +++ b/Sources/BlueZ/Endianness.swift @@ -0,0 +1,41 @@ +// +// Endianness.swift +// BlueZ +// +// Created by Alsey Coleman Miller on 2/29/16. +// Copyright © 2016 PureSwift. All rights reserved. +// + +/// Number can be converted to little / big endian. +public protocol EndianConvertible: Equatable { + + var littleEndian: Self { get } + + var bigEndian: Self { get } +} + +extension Int: EndianConvertible { } +extension UInt16: EndianConvertible { } +extension Int16: EndianConvertible { } +extension UInt32: EndianConvertible { } +extension Int32: EndianConvertible { } +extension UInt64: EndianConvertible { } +extension Int64: EndianConvertible { } + +public extension EndianConvertible { + + /// Converts the number to the current endianness. + var currentEndian: Self { + + if isBigEndian { + + return bigEndian + + } else { + + return littleEndian + } + } +} + +public let isBigEndian = 10.bigEndian == 10 \ No newline at end of file diff --git a/Sources/BlueZ/L2CAP.swift b/Sources/BlueZ/L2CAP.swift index c11fb7e..12f6113 100644 --- a/Sources/BlueZ/L2CAP.swift +++ b/Sources/BlueZ/L2CAP.swift @@ -15,15 +15,25 @@ import SwiftFoundation -/// L2CAP Bluetooth Server socket -public final class L2CAPServer { +/// L2CAP Bluetooth socket +public final class L2CAPSocket { // MARK: - Properties + public lazy var address: Address = self.internalAddress.l2_bdaddr + + public lazy var port: UInt16 = self.internalAddress.l2_psm.currentEndian + + public lazy var channelIdentifier: UInt16 = self.internalAddress.l2_cid.currentEndian + + public lazy var addressType: AddressType = AddressType(rawValue: self.internalAddress.l2_bdaddr_type)! + // MARK: - Internal Properties internal let internalSocket: CInt + internal let internalAddress: sockaddr_l2 + // MARK: - Initialization deinit { @@ -31,20 +41,47 @@ public final class L2CAPServer { close(internalSocket) } - /// Create a new L2CAP server on the adapter with the specified address. - public init(address: Address? = nil, port: CUnsignedShort = 0x1001) throws { + /// Create a new L2CAP server on the adapter with the specified identifier. + public init(deviceIdentifier: CInt? = nil, port: UInt16, CID: UInt16? = nil) throws { - // allocate socket - self.internalSocket = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP) + // get address - // error creating socket - guard internalSocket == 0 else { throw POSIXError.fromErrorNumber! } + let address: Address + if let identifier = deviceIdentifier { + + do { address = try Address(deviceIdentifier: identifier) } + + catch { + + // must set values to satisfy compiler + address = Address() + self.internalSocket = 0 + self.internalAddress = sockaddr_l2() + + throw error + } + + } else { + + address = Address(byteValue: (0, 0, 0, 0, 0, 0)) // BDADDR_ANY + } + + // set address var localAddress = sockaddr_l2() localAddress.l2_family = sa_family_t(AF_BLUETOOTH) - localAddress.l2_psm = port - localAddress.l2_bdaddr = address ?? Address(byteValue: (0, 0, 0, 0, 0, 0)) // BDADDR_ANY + localAddress.l2_bdaddr = address + localAddress.l2_psm = port.littleEndian + localAddress.l2_cid = CID?.littleEndian ?? 0 + + self.internalAddress = localAddress + + // allocate socket + self.internalSocket = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP) + + // error creating socket + guard internalSocket == 0 else { throw POSIXError.fromErrorNumber! } let socketLength = socklen_t(sizeof(sockaddr_l2)) @@ -52,12 +89,38 @@ public final class L2CAPServer { guard withUnsafePointer(&localAddress, { bind(internalSocket, UnsafePointer($0), socketLength) }) == 0 else { close(internalSocket); throw POSIXError.fromErrorNumber! } + // put socket into listening mode + guard listen(internalSocket, 1) == 0 + else { close(internalSocket); throw POSIXError.fromErrorNumber! } + } + + /// For already opened client socket. + internal init(clientSocket: CInt, remoteAddress: sockaddr_l2) { + + self.internalSocket = clientSocket + self.internalAddress = remoteAddress + } + + // MARK: - Methods + + /// Blocks the caller until a new connection is recieved. + public func waitForConnection() throws -> L2CAPSocket { + + var remoteAddress = sockaddr_l2() + var socketLength = socklen_t(sizeof(sockaddr_l2)) + let client = withUnsafeMutablePointer(&remoteAddress, { accept(internalSocket, UnsafeMutablePointer($0), &socketLength) }) + + // error accepting new connection + guard client == 0 else { throw POSIXError.fromErrorNumber! } + + return L2CAPSocket(clientSocket: client, remoteAddress: remoteAddress) } + + //public func } - // MARK: - Darwin Stubs #if os(OSX) || os(iOS) @@ -66,6 +129,10 @@ public final class L2CAPServer { let BTPROTO_L2CAP: CInt = 0 + let ATT_CID: CInt = 4 + + let ATT_PSM: CInt = 31 + /// L2CAP socket address struct sockaddr_l2 { var l2_family: sa_family_t @@ -75,7 +142,5 @@ public final class L2CAPServer { var l2_bdaddr_type: UInt8 init() { stub() } } - - #endif diff --git a/Xcode/BlueZ.xcodeproj/project.pbxproj b/Xcode/BlueZ.xcodeproj/project.pbxproj index a391059..6ed05d5 100644 --- a/Xcode/BlueZ.xcodeproj/project.pbxproj +++ b/Xcode/BlueZ.xcodeproj/project.pbxproj @@ -31,6 +31,7 @@ 6E894BF71C83DE7200109F45 /* PeripheralTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E894BF61C83DE7200109F45 /* PeripheralTest.swift */; }; 6E894C001C83EA2000109F45 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BBD1C8379D100AF63E5 /* main.swift */; }; 6E894C021C83F1C500109F45 /* L2CAP.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E894C011C83F1C500109F45 /* L2CAP.swift */; }; + 6E894C041C84092100109F45 /* Endianness.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E894C031C84092100109F45 /* Endianness.swift */; }; 6E92A4281C15309B007BC4E9 /* BlueZ.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E92A4271C15309B007BC4E9 /* BlueZ.h */; settings = {ATTRIBUTES = (Public, ); }; }; 6E92A4371C1530EF007BC4E9 /* Adapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E92A4321C1530EF007BC4E9 /* Adapter.swift */; }; 6E92A4381C1530EF007BC4E9 /* Address.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E92A4331C1530EF007BC4E9 /* Address.swift */; }; @@ -67,6 +68,7 @@ 6E894BF61C83DE7200109F45 /* PeripheralTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PeripheralTest.swift; sourceTree = ""; }; 6E894BF81C83DE8E00109F45 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; 6E894C011C83F1C500109F45 /* L2CAP.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = L2CAP.swift; sourceTree = ""; }; + 6E894C031C84092100109F45 /* Endianness.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Endianness.swift; sourceTree = ""; }; 6E92A4241C15309B007BC4E9 /* BlueZ.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BlueZ.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 6E92A4271C15309B007BC4E9 /* BlueZ.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BlueZ.h; sourceTree = ""; }; 6E92A4291C15309B007BC4E9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -171,6 +173,7 @@ isa = PBXGroup; children = ( 6E0C5BB81C8373DB00AF63E5 /* Darwin.swift */, + 6E894C031C84092100109F45 /* Endianness.swift */, 6E92A4331C1530EF007BC4E9 /* Address.swift */, 6E894BF31C83B51B00109F45 /* AddressType.swift */, 6E0C5BD91C83AAC000AF63E5 /* UUID.swift */, @@ -286,6 +289,7 @@ buildActionMask = 2147483647; files = ( 6E795E891C47EC90002377FE /* LowEnergyCommand.swift in Sources */, + 6E894C041C84092100109F45 /* Endianness.swift in Sources */, 6E15524C1C39C08A002CC322 /* OpcodeCommandField.swift in Sources */, 6E881DAC1C3996A200E509A9 /* OpcodeGroupField.swift in Sources */, 6E15524A1C39A284002CC322 /* LowEnergyAddressType.swift in Sources */, From de179a715b3cc76a585f27ef651196a74eb9a95d Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Mon, 29 Feb 2016 01:40:07 -0500 Subject: [PATCH 14/18] working on L2CAP --- Sources/BlueZ/L2CAP.swift | 36 ++++++++++++++++++--- Sources/PeripheralTest/PeripheralTest.swift | 22 +++++++++++++ 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/Sources/BlueZ/L2CAP.swift b/Sources/BlueZ/L2CAP.swift index 12f6113..1eeb689 100644 --- a/Sources/BlueZ/L2CAP.swift +++ b/Sources/BlueZ/L2CAP.swift @@ -22,12 +22,12 @@ public final class L2CAPSocket { public lazy var address: Address = self.internalAddress.l2_bdaddr + public lazy var addressType: AddressType = AddressType(rawValue: self.internalAddress.l2_bdaddr_type)! + public lazy var port: UInt16 = self.internalAddress.l2_psm.currentEndian public lazy var channelIdentifier: UInt16 = self.internalAddress.l2_cid.currentEndian - public lazy var addressType: AddressType = AddressType(rawValue: self.internalAddress.l2_bdaddr_type)! - // MARK: - Internal Properties internal let internalSocket: CInt @@ -42,7 +42,7 @@ public final class L2CAPSocket { } /// Create a new L2CAP server on the adapter with the specified identifier. - public init(deviceIdentifier: CInt? = nil, port: UInt16, CID: UInt16? = nil) throws { + public init(deviceIdentifier: CInt? = nil, port: UInt16, channelIdentifier: UInt16? = nil) throws { // get address @@ -73,7 +73,7 @@ public final class L2CAPSocket { localAddress.l2_family = sa_family_t(AF_BLUETOOTH) localAddress.l2_bdaddr = address localAddress.l2_psm = port.littleEndian - localAddress.l2_cid = CID?.littleEndian ?? 0 + localAddress.l2_cid = channelIdentifier?.littleEndian ?? 0 self.internalAddress = localAddress @@ -118,9 +118,35 @@ public final class L2CAPSocket { return L2CAPSocket(clientSocket: client, remoteAddress: remoteAddress) } - //public func + /// Reads from the socket. + public func recieve(bufferSize: Int = 1024) throws -> Data { + + var buffer = [UInt8](count: bufferSize, repeatedValue: 0) + + let actualByteCount = read(internalSocket, &buffer, bufferSize) + + guard actualByteCount >= 0 else { throw POSIXError.fromErrorNumber! } + + let actualBytes = Array(buffer.prefix(actualByteCount)) + + return Data(byteValue: actualBytes) + } + + /// Write to the socket. + public func send(data: Data) throws { + + fatalError("Not implemented") + } } +// MARK: - Linux Support + +#if os(Linux) + + public let SOCK_SEQPACKET: CInt = 5 + +#endif + // MARK: - Darwin Stubs #if os(OSX) || os(iOS) diff --git a/Sources/PeripheralTest/PeripheralTest.swift b/Sources/PeripheralTest/PeripheralTest.swift index 24be0ea..66f6887 100644 --- a/Sources/PeripheralTest/PeripheralTest.swift +++ b/Sources/PeripheralTest/PeripheralTest.swift @@ -18,5 +18,27 @@ import SwiftFoundation func PeripheralTest(adapter: Adapter) { + do { + + let ATT_CID: UInt16 = 4 + + let ATT_PSM: UInt16 = 31 + + let server = try L2CAPSocket(deviceIdentifier: adapter.identifier, port: ATT_PSM, channelIdentifier: ATT_CID) + + print("Created L2CAP server") + + while true { + + let newConnection = try server.waitForConnection() + + print("New \(newConnection.addressType) connection from \(newConnection.address)") + + let readData = try newConnection.recieve() + + print("Recieved data: \(String(UTF8Data: readData) ?? "<\(readData.byteValue.count) bytes>"))") + } + } + catch { Error("Error: \(error)") } } \ No newline at end of file From c44bac719db57c919cae65fcae4225fb3f5cda56 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Mon, 29 Feb 2016 02:03:12 -0500 Subject: [PATCH 15/18] working on L2CAP --- Sources/BlueZ/L2CAP.swift | 110 ++++++++++---------- Sources/PeripheralTest/PeripheralTest.swift | 28 ++--- Sources/PeripheralTest/main.swift | 1 - 3 files changed, 69 insertions(+), 70 deletions(-) diff --git a/Sources/BlueZ/L2CAP.swift b/Sources/BlueZ/L2CAP.swift index 1eeb689..5cf02b9 100644 --- a/Sources/BlueZ/L2CAP.swift +++ b/Sources/BlueZ/L2CAP.swift @@ -17,124 +17,124 @@ import SwiftFoundation /// L2CAP Bluetooth socket public final class L2CAPSocket { - + // MARK: - Properties - + public lazy var address: Address = self.internalAddress.l2_bdaddr - + public lazy var addressType: AddressType = AddressType(rawValue: self.internalAddress.l2_bdaddr_type)! - + public lazy var port: UInt16 = self.internalAddress.l2_psm.currentEndian - + public lazy var channelIdentifier: UInt16 = self.internalAddress.l2_cid.currentEndian - + // MARK: - Internal Properties - + internal let internalSocket: CInt - + internal let internalAddress: sockaddr_l2 - + // MARK: - Initialization - + deinit { - + close(internalSocket) } - + /// Create a new L2CAP server on the adapter with the specified identifier. - public init(deviceIdentifier: CInt? = nil, port: UInt16, channelIdentifier: UInt16? = nil) throws { - + public init(deviceIdentifier: CInt? = nil, port: UInt16? = nil, channelIdentifier: UInt16? = nil) throws { + // get address - + let address: Address - + if let identifier = deviceIdentifier { - + do { address = try Address(deviceIdentifier: identifier) } - + catch { - + // must set values to satisfy compiler address = Address() self.internalSocket = 0 self.internalAddress = sockaddr_l2() - + throw error } - + } else { - + address = Address(byteValue: (0, 0, 0, 0, 0, 0)) // BDADDR_ANY } - + // set address - + var localAddress = sockaddr_l2() localAddress.l2_family = sa_family_t(AF_BLUETOOTH) localAddress.l2_bdaddr = address - localAddress.l2_psm = port.littleEndian + localAddress.l2_psm = port?.littleEndian ?? 0 localAddress.l2_cid = channelIdentifier?.littleEndian ?? 0 - + self.internalAddress = localAddress - + // allocate socket self.internalSocket = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP) - + // error creating socket - guard internalSocket == 0 else { throw POSIXError.fromErrorNumber! } - + guard internalSocket >= 0 else { throw POSIXError.fromErrorNumber! } + let socketLength = socklen_t(sizeof(sockaddr_l2)) - + // bind socket to port and address guard withUnsafePointer(&localAddress, { bind(internalSocket, UnsafePointer($0), socketLength) }) == 0 else { close(internalSocket); throw POSIXError.fromErrorNumber! } - + // put socket into listening mode guard listen(internalSocket, 1) == 0 else { close(internalSocket); throw POSIXError.fromErrorNumber! } } - + /// For already opened client socket. internal init(clientSocket: CInt, remoteAddress: sockaddr_l2) { - + self.internalSocket = clientSocket self.internalAddress = remoteAddress } - + // MARK: - Methods - + /// Blocks the caller until a new connection is recieved. public func waitForConnection() throws -> L2CAPSocket { - + var remoteAddress = sockaddr_l2() - + var socketLength = socklen_t(sizeof(sockaddr_l2)) - + let client = withUnsafeMutablePointer(&remoteAddress, { accept(internalSocket, UnsafeMutablePointer($0), &socketLength) }) - + // error accepting new connection guard client == 0 else { throw POSIXError.fromErrorNumber! } - + return L2CAPSocket(clientSocket: client, remoteAddress: remoteAddress) } - + /// Reads from the socket. public func recieve(bufferSize: Int = 1024) throws -> Data { - + var buffer = [UInt8](count: bufferSize, repeatedValue: 0) - + let actualByteCount = read(internalSocket, &buffer, bufferSize) - + guard actualByteCount >= 0 else { throw POSIXError.fromErrorNumber! } - + let actualBytes = Array(buffer.prefix(actualByteCount)) - + return Data(byteValue: actualBytes) } - + /// Write to the socket. public func send(data: Data) throws { - + fatalError("Not implemented") } } @@ -144,21 +144,21 @@ public final class L2CAPSocket { #if os(Linux) public let SOCK_SEQPACKET: CInt = 5 - + #endif // MARK: - Darwin Stubs #if os(OSX) || os(iOS) - + let AF_BLUETOOTH: CInt = 31 - + let BTPROTO_L2CAP: CInt = 0 - + let ATT_CID: CInt = 4 - + let ATT_PSM: CInt = 31 - + /// L2CAP socket address struct sockaddr_l2 { var l2_family: sa_family_t diff --git a/Sources/PeripheralTest/PeripheralTest.swift b/Sources/PeripheralTest/PeripheralTest.swift index 66f6887..a236b72 100644 --- a/Sources/PeripheralTest/PeripheralTest.swift +++ b/Sources/PeripheralTest/PeripheralTest.swift @@ -17,28 +17,28 @@ import SwiftFoundation func PeripheralTest(adapter: Adapter) { - + do { - + let ATT_CID: UInt16 = 4 - - let ATT_PSM: UInt16 = 31 - - let server = try L2CAPSocket(deviceIdentifier: adapter.identifier, port: ATT_PSM, channelIdentifier: ATT_CID) - + + //let ATT_PSM: UInt16 = 31 + + let server = try L2CAPSocket(deviceIdentifier: adapter.identifier, channelIdentifier: ATT_CID) + print("Created L2CAP server") - + while true { - + let newConnection = try server.waitForConnection() - + print("New \(newConnection.addressType) connection from \(newConnection.address)") - + let readData = try newConnection.recieve() - + print("Recieved data: \(String(UTF8Data: readData) ?? "<\(readData.byteValue.count) bytes>"))") } } - + catch { Error("Error: \(error)") } -} \ No newline at end of file +} diff --git a/Sources/PeripheralTest/main.swift b/Sources/PeripheralTest/main.swift index 4986fa5..d79e009 100644 --- a/Sources/PeripheralTest/main.swift +++ b/Sources/PeripheralTest/main.swift @@ -32,4 +32,3 @@ print("Address: \(adapter.address!)") /// Perform Test PeripheralTest(adapter) - From f42958e15fd928a867f68ed95a7be838de246c09 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Mon, 29 Feb 2016 02:50:04 -0500 Subject: [PATCH 16/18] working on L2CAP --- Sources/BlueZ/L2CAP.swift | 3 ++- Sources/PeripheralTest/PeripheralTest.swift | 23 +++++++++------------ 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/Sources/BlueZ/L2CAP.swift b/Sources/BlueZ/L2CAP.swift index 5cf02b9..e8e07ea 100644 --- a/Sources/BlueZ/L2CAP.swift +++ b/Sources/BlueZ/L2CAP.swift @@ -109,7 +109,8 @@ public final class L2CAPSocket { var remoteAddress = sockaddr_l2() var socketLength = socklen_t(sizeof(sockaddr_l2)) - + + // accept new client let client = withUnsafeMutablePointer(&remoteAddress, { accept(internalSocket, UnsafeMutablePointer($0), &socketLength) }) // error accepting new connection diff --git a/Sources/PeripheralTest/PeripheralTest.swift b/Sources/PeripheralTest/PeripheralTest.swift index a236b72..d1abd60 100644 --- a/Sources/PeripheralTest/PeripheralTest.swift +++ b/Sources/PeripheralTest/PeripheralTest.swift @@ -20,24 +20,21 @@ func PeripheralTest(adapter: Adapter) { do { - let ATT_CID: UInt16 = 4 + //let ATT_CID: UInt16 = 4 //let ATT_PSM: UInt16 = 31 - let server = try L2CAPSocket(deviceIdentifier: adapter.identifier, channelIdentifier: ATT_CID) + let server = try L2CAPSocket(deviceIdentifier: adapter.identifier, port: 0x1001) print("Created L2CAP server") - - while true { - - let newConnection = try server.waitForConnection() - - print("New \(newConnection.addressType) connection from \(newConnection.address)") - - let readData = try newConnection.recieve() - - print("Recieved data: \(String(UTF8Data: readData) ?? "<\(readData.byteValue.count) bytes>"))") - } + + let newConnection = try server.waitForConnection() + + print("New \(newConnection.addressType) connection from \(newConnection.address)") + + let readData = try newConnection.recieve() + + print("Recieved data: \(String(UTF8Data: readData) ?? "<\(readData.byteValue.count) bytes>"))") } catch { Error("Error: \(error)") } From 42366673516bb3c25416b79349eca52556a07884 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Mon, 29 Feb 2016 11:19:18 -0500 Subject: [PATCH 17/18] working on L2CAP --- Sources/BlueZ/AddressType.swift | 2 + Sources/BlueZ/L2CAP.swift | 48 +++++++++---- Sources/BlueZ/SecurityType.swift | 14 ++-- Sources/PeripheralTest/PeripheralTest.swift | 80 +++++++++++++++++++-- 4 files changed, 122 insertions(+), 22 deletions(-) diff --git a/Sources/BlueZ/AddressType.swift b/Sources/BlueZ/AddressType.swift index 412e0b9..5808216 100644 --- a/Sources/BlueZ/AddressType.swift +++ b/Sources/BlueZ/AddressType.swift @@ -16,6 +16,8 @@ public enum AddressType: UInt8 { case LowEnergyRandom = 0x01 case LowEnergyPublic = 0x02 + public init() { self = BREDR } + /// Whether the Bluetooth address type is LE. public var isLowEnergy: Bool { diff --git a/Sources/BlueZ/L2CAP.swift b/Sources/BlueZ/L2CAP.swift index e8e07ea..81d35f9 100644 --- a/Sources/BlueZ/L2CAP.swift +++ b/Sources/BlueZ/L2CAP.swift @@ -42,7 +42,7 @@ public final class L2CAPSocket { } /// Create a new L2CAP server on the adapter with the specified identifier. - public init(deviceIdentifier: CInt? = nil, port: UInt16? = nil, channelIdentifier: UInt16? = nil) throws { + public init(deviceIdentifier: CInt? = nil, port: UInt16 = 0, channelIdentifier: UInt16 = 0, addressType: AddressType = AddressType(), securityLevel: SecurityLevel = SecurityLevel()) throws { // get address @@ -53,7 +53,7 @@ public final class L2CAPSocket { do { address = try Address(deviceIdentifier: identifier) } catch { - + // must set values to satisfy compiler address = Address() self.internalSocket = 0 @@ -61,7 +61,7 @@ public final class L2CAPSocket { throw error } - + } else { address = Address(byteValue: (0, 0, 0, 0, 0, 0)) // BDADDR_ANY @@ -70,10 +70,14 @@ public final class L2CAPSocket { // set address var localAddress = sockaddr_l2() + + memset(&localAddress, 0, sizeof(sockaddr_l2)) + localAddress.l2_family = sa_family_t(AF_BLUETOOTH) localAddress.l2_bdaddr = address - localAddress.l2_psm = port?.littleEndian ?? 0 - localAddress.l2_cid = channelIdentifier?.littleEndian ?? 0 + localAddress.l2_psm = port.littleEndian + localAddress.l2_cid = channelIdentifier.littleEndian + localAddress.l2_bdaddr_type = addressType.rawValue self.internalAddress = localAddress @@ -88,9 +92,16 @@ public final class L2CAPSocket { // bind socket to port and address guard withUnsafePointer(&localAddress, { bind(internalSocket, UnsafePointer($0), socketLength) }) == 0 else { close(internalSocket); throw POSIXError.fromErrorNumber! } - + + // set security level + var security = bt_security() + security.level = securityLevel.rawValue + + guard setsockopt(internalSocket, SOL_BLUETOOTH, BT_SECURITY, &security, socklen_t(sizeof(bt_security))) == 0 + else { close(internalSocket); throw POSIXError.fromErrorNumber! } + // put socket into listening mode - guard listen(internalSocket, 1) == 0 + guard listen(internalSocket, 10) == 0 else { close(internalSocket); throw POSIXError.fromErrorNumber! } } @@ -140,6 +151,12 @@ public final class L2CAPSocket { } } +// MARK: - Additional Constants + +public let ATT_CID: CInt = 4 + +public let ATT_PSM: CInt = 31 + // MARK: - Linux Support #if os(Linux) @@ -155,11 +172,11 @@ public final class L2CAPSocket { let AF_BLUETOOTH: CInt = 31 let BTPROTO_L2CAP: CInt = 0 - - let ATT_CID: CInt = 4 - - let ATT_PSM: CInt = 31 - + + let SOL_BLUETOOTH: CInt = 274 + + let BT_SECURITY: CInt = 4 + /// L2CAP socket address struct sockaddr_l2 { var l2_family: sa_family_t @@ -169,5 +186,12 @@ public final class L2CAPSocket { var l2_bdaddr_type: UInt8 init() { stub() } } + + /// Bluetooth security level + struct bt_security { + var level: UInt8 + var key_size: UInt8 + init() { stub() } + } #endif diff --git a/Sources/BlueZ/SecurityType.swift b/Sources/BlueZ/SecurityType.swift index 3d91126..a78c1a2 100644 --- a/Sources/BlueZ/SecurityType.swift +++ b/Sources/BlueZ/SecurityType.swift @@ -6,11 +6,13 @@ // Copyright © 2016 PureSwift. All rights reserved. // -/// Bluetooth security type. -public enum SecurityType: UInt8 { +/// Bluetooth security level. +public enum SecurityLevel: UInt8 { - case SDP - case Low - case Medium - case High + case SDP = 0 + case Low = 1 + case Medium = 2 + case High = 3 + + public init() { self = .SDP } } \ No newline at end of file diff --git a/Sources/PeripheralTest/PeripheralTest.swift b/Sources/PeripheralTest/PeripheralTest.swift index d1abd60..ff9084b 100644 --- a/Sources/PeripheralTest/PeripheralTest.swift +++ b/Sources/PeripheralTest/PeripheralTest.swift @@ -20,11 +20,11 @@ func PeripheralTest(adapter: Adapter) { do { - //let ATT_CID: UInt16 = 4 + let ATT_CID: UInt16 = 4 - //let ATT_PSM: UInt16 = 31 - - let server = try L2CAPSocket(deviceIdentifier: adapter.identifier, port: 0x1001) + let ATT_PSM: UInt16 = 31 + + let server = try L2CAPSocket(deviceIdentifier: adapter.identifier, channelIdentifier: ATT_CID, addressType: .LowEnergyPublic, securityLevel: .Low) print("Created L2CAP server") @@ -39,3 +39,75 @@ func PeripheralTest(adapter: Adapter) { catch { Error("Error: \(error)") } } + +/* +func PeripheralTest(adapter: Adapter) { + + do { + + let port: UInt16 = 0x1001 + + let address = try Address(deviceIdentifier: adapter.identifier) + + var localAddress = sockaddr_l2() + localAddress.l2_family = sa_family_t(AF_BLUETOOTH) + localAddress.l2_bdaddr = address + localAddress.l2_psm = port.littleEndian + + // allocate socket + let internalSocket = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP) + + // error creating socket + guard internalSocket >= 0 else { throw POSIXError.fromErrorNumber! } + + var socketLength = socklen_t(sizeof(sockaddr_l2)) + + // bind socket to port and address + guard withUnsafePointer(&localAddress, { bind(internalSocket, UnsafePointer($0), socketLength) }) == 0 + else { close(internalSocket); throw POSIXError.fromErrorNumber! } + + // put socket into listening mode + guard listen(internalSocket, 10) == 0 + else { close(internalSocket); throw POSIXError.fromErrorNumber! } + + print("Created L2CAP server") + + /// + + var remoteAddressPointer = UnsafeMutablePointer.alloc(1) + + defer { remoteAddressPointer.dealloc(1) } + + // accept new client + let client = accept(internalSocket, UnsafeMutablePointer(remoteAddressPointer), &socketLength) + + // error accepting new connection + guard client == 0 else { throw POSIXError.fromErrorNumber! } + + print("New connection from \(remoteAddressPointer.memory.l2_bdaddr)") + + /// + + let bufferSize = 1024 + + var buffer = [UInt8](count: bufferSize, repeatedValue: 0) + + let actualByteCount = read(internalSocket, &buffer, bufferSize) + + guard actualByteCount >= 0 else { throw POSIXError.fromErrorNumber! } + + let actualBytes = Array(buffer.prefix(actualByteCount)) + + let readData = Data(byteValue: actualBytes) + + print("Recieved data: \(String(UTF8Data: readData) ?? "<\(readData.byteValue.count) bytes>"))") + + close(internalSocket) + + close(client) + } + + catch { Error("Error: \(error)") } +} +*/ + From 99bc331bc40209736359ba44d1f385e18862bfc8 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Mon, 29 Feb 2016 12:04:21 -0500 Subject: [PATCH 18/18] fixed L2CAP server now working --- Sources/BlueZ/L2CAP.swift | 6 +- Sources/PeripheralTest/PeripheralTest.swift | 77 +-------------------- 2 files changed, 4 insertions(+), 79 deletions(-) diff --git a/Sources/BlueZ/L2CAP.swift b/Sources/BlueZ/L2CAP.swift index 81d35f9..f30f516 100644 --- a/Sources/BlueZ/L2CAP.swift +++ b/Sources/BlueZ/L2CAP.swift @@ -125,7 +125,7 @@ public final class L2CAPSocket { let client = withUnsafeMutablePointer(&remoteAddress, { accept(internalSocket, UnsafeMutablePointer($0), &socketLength) }) // error accepting new connection - guard client == 0 else { throw POSIXError.fromErrorNumber! } + guard client >= 0 else { throw POSIXError.fromErrorNumber! } return L2CAPSocket(clientSocket: client, remoteAddress: remoteAddress) } @@ -153,9 +153,9 @@ public final class L2CAPSocket { // MARK: - Additional Constants -public let ATT_CID: CInt = 4 +public let ATT_CID: UInt16 = 4 -public let ATT_PSM: CInt = 31 +public let ATT_PSM: UInt16 = 31 // MARK: - Linux Support diff --git a/Sources/PeripheralTest/PeripheralTest.swift b/Sources/PeripheralTest/PeripheralTest.swift index ff9084b..dd233b6 100644 --- a/Sources/PeripheralTest/PeripheralTest.swift +++ b/Sources/PeripheralTest/PeripheralTest.swift @@ -19,10 +19,6 @@ import SwiftFoundation func PeripheralTest(adapter: Adapter) { do { - - let ATT_CID: UInt16 = 4 - - let ATT_PSM: UInt16 = 31 let server = try L2CAPSocket(deviceIdentifier: adapter.identifier, channelIdentifier: ATT_CID, addressType: .LowEnergyPublic, securityLevel: .Low) @@ -34,80 +30,9 @@ func PeripheralTest(adapter: Adapter) { let readData = try newConnection.recieve() - print("Recieved data: \(String(UTF8Data: readData) ?? "<\(readData.byteValue.count) bytes>"))") + print("Recieved data: \(String(UTF8Data: readData) ?? "\(readData.byteValue.map({ String($0, radix: 16, uppercase: false) }))" )") } catch { Error("Error: \(error)") } } -/* -func PeripheralTest(adapter: Adapter) { - - do { - - let port: UInt16 = 0x1001 - - let address = try Address(deviceIdentifier: adapter.identifier) - - var localAddress = sockaddr_l2() - localAddress.l2_family = sa_family_t(AF_BLUETOOTH) - localAddress.l2_bdaddr = address - localAddress.l2_psm = port.littleEndian - - // allocate socket - let internalSocket = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP) - - // error creating socket - guard internalSocket >= 0 else { throw POSIXError.fromErrorNumber! } - - var socketLength = socklen_t(sizeof(sockaddr_l2)) - - // bind socket to port and address - guard withUnsafePointer(&localAddress, { bind(internalSocket, UnsafePointer($0), socketLength) }) == 0 - else { close(internalSocket); throw POSIXError.fromErrorNumber! } - - // put socket into listening mode - guard listen(internalSocket, 10) == 0 - else { close(internalSocket); throw POSIXError.fromErrorNumber! } - - print("Created L2CAP server") - - /// - - var remoteAddressPointer = UnsafeMutablePointer.alloc(1) - - defer { remoteAddressPointer.dealloc(1) } - - // accept new client - let client = accept(internalSocket, UnsafeMutablePointer(remoteAddressPointer), &socketLength) - - // error accepting new connection - guard client == 0 else { throw POSIXError.fromErrorNumber! } - - print("New connection from \(remoteAddressPointer.memory.l2_bdaddr)") - - /// - - let bufferSize = 1024 - - var buffer = [UInt8](count: bufferSize, repeatedValue: 0) - - let actualByteCount = read(internalSocket, &buffer, bufferSize) - - guard actualByteCount >= 0 else { throw POSIXError.fromErrorNumber! } - - let actualBytes = Array(buffer.prefix(actualByteCount)) - - let readData = Data(byteValue: actualBytes) - - print("Recieved data: \(String(UTF8Data: readData) ?? "<\(readData.byteValue.count) bytes>"))") - - close(internalSocket) - - close(client) - } - - catch { Error("Error: \(error)") } -} -*/ -