diff --git a/Sources/BluetoothLinux/Deque.swift b/Sources/BluetoothLinux/Deque.swift index 524c9d3..0ebcf12 100644 --- a/Sources/BluetoothLinux/Deque.swift +++ b/Sources/BluetoothLinux/Deque.swift @@ -798,7 +798,7 @@ final class DequeBuffer: NonObjectiveCBase { //MARK: extension DequeBuffer { - internal func forEach(@noescape body: (Element) throws -> ()) rethrows { + internal func forEach( body: @noescape(Element) throws -> ()) rethrows { if start + count <= capacity { var p = elements + start for _ in 0 ..< count { @@ -822,19 +822,19 @@ extension DequeBuffer { } extension Deque { - public func forEach(@noescape body: (Element) throws -> ()) rethrows { + public func forEach( body: @noescape(Element) throws -> ()) rethrows { try withExtendedLifetime(buffer) { try $0.forEach { try body($0) } } } - public func map(@noescape transform: (Element) throws -> T) rethrows -> [T] { + public func map( transform: @noescape(Element) throws -> T) rethrows -> [T] { var result: [T] = [] result.reserveCapacity(self.count) try self.forEach { result.append(try transform($0)) } return result } - public func flatMap(@noescape transform: (Element) throws -> T?) rethrows -> [T] { + public func flatMap( transform: @noescape(Element) throws -> T?) rethrows -> [T] { var result: [T] = [] try self.forEach { if let r = try transform($0) { @@ -852,7 +852,7 @@ extension Deque { return result } - public func filter(@noescape includeElement: (Element) throws -> Bool) rethrows -> [Element] { + public func filter( includeElement: @noescape(Element) throws -> Bool) rethrows -> [Element] { var result: [Element] = [] try self.forEach { if try includeElement($0) { @@ -862,7 +862,7 @@ extension Deque { return result } - public func reduce(initial: T, @noescape combine: (T, Element) throws -> T) rethrows -> T { + public func reduce(initial: T, combine: @noescape(T, Element) throws -> T) rethrows -> T { var result = initial try self.forEach { result = try combine(result, $0) diff --git a/Sources/BluetoothLinux/GATTServer.swift b/Sources/BluetoothLinux/GATTServer.swift index d6c7693..803d0af 100644 --- a/Sources/BluetoothLinux/GATTServer.swift +++ b/Sources/BluetoothLinux/GATTServer.swift @@ -171,7 +171,7 @@ public final class GATTServer { /// Conditionally respond @inline(__always) - func doResponse(@autoclosure _ block: () -> ()) { + func doResponse( _ block: @autoclosure() -> ()) { if shouldRespond { block() } } diff --git a/Sources/BluetoothLinux/IOVector.swift b/Sources/BluetoothLinux/IOVector.swift deleted file mode 100644 index 5e2dafe..0000000 --- a/Sources/BluetoothLinux/IOVector.swift +++ /dev/null @@ -1,28 +0,0 @@ -// -// IOVector.swift -// BluetoothLinux -// -// Created by Alsey Coleman Miller on 3/14/16. -// Copyright © 2016 PureSwift. All rights reserved. -// - -#if os(Linux) - import Glibc -#elseif os(OSX) || os(iOS) - import Darwin.C -#endif - -public extension iovec { - - public init(byteValue: [UInt8]) { - - let length = byteValue.count - var vector = iovec() - vector.iov_len = length - vector.iov_base = UnsafeMutablePointer.init(allocatingCapacity: length) - - memcpy(vector.iov_base, byteValue, length) - - self = vector - } -} diff --git a/Sources/BluetoothLinux/iBeacon.swift b/Sources/BluetoothLinux/iBeacon.swift index 0fec4b7..a0025c2 100644 --- a/Sources/BluetoothLinux/iBeacon.swift +++ b/Sources/BluetoothLinux/iBeacon.swift @@ -36,7 +36,7 @@ public extension Adapter { // set iBeacon data var advertisingDataCommand = LowEnergyCommand.SetAdvertisingDataParameter() - SetBeaconData(UUID: UUID, mayor: mayor, minor: minor, RSSI: UInt8(bitPattern: RSSI), parameter: &advertisingDataCommand) + SetBeaconData(UUID: UUID, major: mayor, minor: minor, RSSI: UInt8(bitPattern: RSSI), parameter: &advertisingDataCommand) try deviceRequest(advertisingDataCommand, timeout: commandTimeout) } @@ -51,7 +51,7 @@ public extension Adapter { // MARK: - Private -private func SetBeaconData(UUID: SwiftFoundation.UUID, mayor: UInt16, minor: UInt16, RSSI: UInt8, parameter: inout LowEnergyCommand.SetAdvertisingDataParameter) { +internal func SetBeaconData(UUID: SwiftFoundation.UUID, major: UInt16, minor: UInt16, RSSI: UInt8, parameter: inout LowEnergyCommand.SetAdvertisingDataParameter) { parameter.length = 30 @@ -85,10 +85,10 @@ private func SetBeaconData(UUID: SwiftFoundation.UUID, mayor: UInt16, minor: UIn parameter.data.23 = littleUUIDBytes[13] parameter.data.24 = littleUUIDBytes[14] - let mayorBytes = mayor.littleEndian.bytes + let majorBytes = major.littleEndian.bytes - parameter.data.25 = mayorBytes.0 - parameter.data.26 = mayorBytes.1 + parameter.data.25 = majorBytes.0 + parameter.data.26 = majorBytes.1 let minorBytes = minor.littleEndian.bytes diff --git a/Sources/UnitTests/iBeaconTests.swift b/Sources/UnitTests/iBeaconTests.swift new file mode 100644 index 0000000..45c4ce8 --- /dev/null +++ b/Sources/UnitTests/iBeaconTests.swift @@ -0,0 +1,44 @@ +// +// iBeaconTests.swift +// BluetoothLinux +// +// Created by Alsey Coleman Miller on 4/29/16. +// Copyright © 2016 PureSwift. All rights reserved. +// + +#if os(OSX) + + import XCTest + import SwiftFoundation + import Bluetooth + @testable import BluetoothLinux + + final class iBeaconTests: XCTestCase { + + func testAdvertisementData() { + + let identifier = UUID() + + let major: UInt16 = 0 + + let minor: UInt16 = 1 + + let rssi: Int8 = -59 + + var adverstisementDataParameter = beaconAdvertisementData(identifier.toData().byteValue, CInt(major), CInt(minor), CInt(rssi)) + + var parameterBytes = [UInt8].init(repeating: 0, count: Int(adverstisementDataParameter.length)) + + withUnsafePointer(&adverstisementDataParameter.data) { memcpy(¶meterBytes, UnsafePointer($0), parameterBytes.count) } + + var advertisingDataCommand = LowEnergyCommand.SetAdvertisingDataParameter() + + SetBeaconData(UUID: identifier, major: major, minor: minor, RSSI: UInt8(bitPattern: rssi), parameter: &advertisingDataCommand) + + XCTAssert(adverstisementDataParameter.length == advertisingDataCommand.length, "Invalid Length: \(adverstisementDataParameter.length) == \(advertisingDataCommand.length)") + + //XCTAssert(memcmp(<#T##UnsafePointer!#>, <#T##UnsafePointer!#>, <#T##Int#>)) + } + } + +#endif \ No newline at end of file diff --git a/Xcode/BluetoothLinux.xcodeproj/project.pbxproj b/Xcode/BluetoothLinux.xcodeproj/project.pbxproj index 207c955..0fe0fc0 100644 --- a/Xcode/BluetoothLinux.xcodeproj/project.pbxproj +++ b/Xcode/BluetoothLinux.xcodeproj/project.pbxproj @@ -22,14 +22,14 @@ 6E53E1771C8503AC00AC8FCA /* GATTDatabase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E53E1761C8503AC00AC8FCA /* GATTDatabase.swift */; }; 6E53E1791C8503CA00AC8FCA /* ATTConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E53E1781C8503CA00AC8FCA /* ATTConnection.swift */; }; 6E53E17F1C85945E00AC8FCA /* Deque.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E53E17E1C85945E00AC8FCA /* Deque.swift */; }; + 6E66A8E51CD44D70005F922F /* BluetoothLinux.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E92A4271C15309B007BC4E9 /* BluetoothLinux.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6E66A8E71CD44E2F005F922F /* iBeaconTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E66A8E31CD44A61005F922F /* iBeaconTests.swift */; }; 6E795E9B1C49821B002377FE /* LinkMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E795E9A1C49821B002377FE /* LinkMode.swift */; }; 6E881D821C389F4B00E509A9 /* iBeacon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E881D811C389F4B00E509A9 /* iBeacon.swift */; }; 6E881DA21C39812F00E509A9 /* DeviceRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E881D831C39783F00E509A9 /* DeviceRequest.swift */; }; 6E894BF41C83B51B00109F45 /* AddressType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E894BF31C83B51B00109F45 /* AddressType.swift */; }; 6E894C001C83EA2000109F45 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0C5BBD1C8379D100AF63E5 /* main.swift */; }; 6E894C021C83F1C500109F45 /* L2CAP.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E894C011C83F1C500109F45 /* L2CAP.swift */; }; - 6E927EC91C977D7D009AB500 /* IOVector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E927EC81C977D7D009AB500 /* IOVector.swift */; }; - 6E92A4281C15309B007BC4E9 /* BluetoothLinux.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E92A4271C15309B007BC4E9 /* BluetoothLinux.h */; settings = {ATTRIBUTES = (Public, ); }; }; 6E92A4371C1530EF007BC4E9 /* Adapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E92A4321C1530EF007BC4E9 /* Adapter.swift */; }; 6E92A43B1C1530EF007BC4E9 /* Scan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E92A4361C1530EF007BC4E9 /* Scan.swift */; }; 6EA37EF41C84B4EA00A61969 /* L2CAPServerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA37EF21C84B4EA00A61969 /* L2CAPServerTest.swift */; }; @@ -84,13 +84,14 @@ 6E53E1761C8503AC00AC8FCA /* GATTDatabase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GATTDatabase.swift; sourceTree = ""; }; 6E53E1781C8503CA00AC8FCA /* ATTConnection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ATTConnection.swift; sourceTree = ""; }; 6E53E17E1C85945E00AC8FCA /* Deque.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Deque.swift; sourceTree = ""; }; + 6E66A8E31CD44A61005F922F /* iBeaconTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = iBeaconTests.swift; sourceTree = ""; }; + 6E66A8E61CD44DD2005F922F /* iBeaconTestsHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = iBeaconTestsHelper.h; sourceTree = ""; }; 6E739C8D1C88EE4C00D4775B /* ioctl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ioctl.h; sourceTree = ""; }; 6E795E9A1C49821B002377FE /* LinkMode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LinkMode.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 = ""; }; 6E894BF31C83B51B00109F45 /* AddressType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddressType.swift; sourceTree = ""; }; 6E894C011C83F1C500109F45 /* L2CAP.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = L2CAP.swift; sourceTree = ""; }; - 6E927EC81C977D7D009AB500 /* IOVector.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IOVector.swift; sourceTree = ""; }; 6E92A4241C15309B007BC4E9 /* BluetoothLinux.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BluetoothLinux.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 6E92A4271C15309B007BC4E9 /* BluetoothLinux.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BluetoothLinux.h; sourceTree = ""; }; 6E92A4291C15309B007BC4E9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -208,7 +209,6 @@ 6E196CC61C86A5EC009FA9CF /* BluetoothProtocol.swift */, 6E92A4361C1530EF007BC4E9 /* Scan.swift */, 6E881D811C389F4B00E509A9 /* iBeacon.swift */, - 6E927EC81C977D7D009AB500 /* IOVector.swift */, 6E894C011C83F1C500109F45 /* L2CAP.swift */, 6E53E1781C8503CA00AC8FCA /* ATTConnection.swift */, 6E53E1721C84FD8200AC8FCA /* GATTServer.swift */, @@ -247,6 +247,7 @@ children = ( 6EF928FA1C8830D200D9A103 /* Info.plist */, 6EF929051C8832FF00D9A103 /* BluetoothLinuxTests-Bridging-Header.h */, + 6E66A8E61CD44DD2005F922F /* iBeaconTestsHelper.h */, 6EF929041C8831C700D9A103 /* MathTestsHelper.h */, 6EF9290A1C88350600D9A103 /* IOCTLTestsHelper.h */, 6E739C8D1C88EE4C00D4775B /* ioctl.h */, @@ -259,6 +260,7 @@ isa = PBXGroup; children = ( 6EF929021C88316D00D9A103 /* MathTests.swift */, + 6E66A8E31CD44A61005F922F /* iBeaconTests.swift */, ); name = "Unit Tests"; path = ../Sources/UnitTests; @@ -290,7 +292,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 6E92A4281C15309B007BC4E9 /* BluetoothLinux.h in Headers */, + 6E66A8E51CD44D70005F922F /* BluetoothLinux.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -404,7 +406,6 @@ 6E881D821C389F4B00E509A9 /* iBeacon.swift in Sources */, 6EF355211C965EB400730BAB /* GATTServerTest.swift in Sources */, 6E196CCB1C87B47E009FA9CF /* DeviceCommand.swift in Sources */, - 6E927EC91C977D7D009AB500 /* IOVector.swift in Sources */, 6E196CC51C869A2E009FA9CF /* IOCTL.swift in Sources */, 6E881DA21C39812F00E509A9 /* DeviceRequest.swift in Sources */, 6E795E9B1C49821B002377FE /* LinkMode.swift in Sources */, @@ -423,6 +424,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 6E66A8E71CD44E2F005F922F /* iBeaconTests.swift in Sources */, 6EF929071C8832FF00D9A103 /* DarwinTests.m in Sources */, 6EF929031C88316D00D9A103 /* MathTests.swift in Sources */, ); diff --git a/Xcode/BluetoothLinux/BluetoothLinux.h b/Xcode/BluetoothLinux/BluetoothLinux.h index b1bc1ed..e64c32f 100644 --- a/Xcode/BluetoothLinux/BluetoothLinux.h +++ b/Xcode/BluetoothLinux/BluetoothLinux.h @@ -17,4 +17,4 @@ FOUNDATION_EXPORT const unsigned char BluetoothLinuxVersionString[]; static inline void hci_set_bit(int nr, void *addr) { *((uint32_t *) addr + (nr >> 5)) |= (1 << (nr & 31)); -} \ No newline at end of file +} diff --git a/Xcode/BluetoothLinuxTests/BluetoothLinuxTests-Bridging-Header.h b/Xcode/BluetoothLinuxTests/BluetoothLinuxTests-Bridging-Header.h index bc18cce..d20d2aa 100644 --- a/Xcode/BluetoothLinuxTests/BluetoothLinuxTests-Bridging-Header.h +++ b/Xcode/BluetoothLinuxTests/BluetoothLinuxTests-Bridging-Header.h @@ -4,3 +4,4 @@ #import "MathTestsHelper.h" #import "IOCTLTestsHelper.h" +#import "iBeaconTestsHelper.h" \ No newline at end of file diff --git a/Xcode/BluetoothLinuxTests/iBeaconTestsHelper.h b/Xcode/BluetoothLinuxTests/iBeaconTestsHelper.h new file mode 100644 index 0000000..53213a0 --- /dev/null +++ b/Xcode/BluetoothLinuxTests/iBeaconTestsHelper.h @@ -0,0 +1,103 @@ +// +// iBeaconTestsHelper.h +// BluetoothLinux +// +// Created by Alsey Coleman Miller on 4/29/16. +// Copyright © 2016 PureSwift. All rights reserved. +// + +#define EIR_FLAGS 0X01 +#define EIR_NAME_SHORT 0x08 +#define EIR_NAME_COMPLETE 0x09 +#define EIR_MANUFACTURE_SPECIFIC 0xFF + +/* Byte order conversions */ +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define htobs(d) (d) +#define htobl(d) (d) +#define htobll(d) (d) +#define btohs(d) (d) +#define btohl(d) (d) +#define btohll(d) (d) +#elif __BYTE_ORDER == __BIG_ENDIAN +#define htobs(d) bswap_16(d) +#define htobl(d) bswap_32(d) +#define htobll(d) bswap_64(d) +#define btohs(d) bswap_16(d) +#define btohl(d) bswap_32(d) +#define btohll(d) bswap_64(d) +#else +#error "Unknown byte order" +#endif + +typedef struct { + uint8_t length; + uint8_t data[31]; +} __attribute__ ((packed)) le_set_advertising_data_cp; + +static inline unsigned int twoc(int in, int t) +{ + return (in < 0) ? (in + (2 << (t-1))) : in; +} + +static inline unsigned int *uuid_str_to_data(char *uuid) +{ + char conv[] = "0123456789ABCDEF"; + int len = strlen(uuid); + unsigned int *data = (unsigned int*)malloc(sizeof(unsigned int) * len); + unsigned int *dp = data; + char *cu = uuid; + + for(; cu> 8 & 0x00FF); segment_length++; + adv_data_cp.data[adv_data_cp.length + segment_length] = htobs(major_number & 0x00FF); segment_length++; + + // Minor number + adv_data_cp.data[adv_data_cp.length + segment_length] = htobs(minor_number >> 8 & 0x00FF); segment_length++; + adv_data_cp.data[adv_data_cp.length + segment_length] = htobs(minor_number & 0x00FF); segment_length++; + + // RSSI calibration + adv_data_cp.data[adv_data_cp.length + segment_length] = htobs(twoc(rssi_value, 8)); segment_length++; + + adv_data_cp.data[adv_data_cp.length] = htobs(segment_length - 1); + + adv_data_cp.length += segment_length; + + return adv_data_cp; +}