diff options
author | Timur Pocheptsov <Timur.Pocheptsov@digia.com> | 2014-11-07 15:29:59 +0100 |
---|---|---|
committer | Timur Pocheptsov <Timur.Pocheptsov@digia.com> | 2014-11-13 14:12:18 +0100 |
commit | 53dad9ebc8e1caa8c13a8b964ecdede381067340 (patch) | |
tree | 18b27fb9a3898a9c37a92763be5163ee7bd3f6a8 /src/bluetooth/osx | |
parent | 720137353b3d6ecb6a07d1f5486ab20306be8134 (diff) |
QLowEnergyController - service discovery (OS X, iOS)
Implement discoverServices and delegate's methods to work with a service
discovery on a peripheral.
- CBUUID (it's internal data) can be only 2 bytes long (16-bit shortened UUID)
despite of the docs saying 'CBUUID is a 16-bit UUID'.
- property 'isPrimary' did not exist prior to 10.9 SDK (OS X).
Change-Id: If692d147c0479ed69a331514617e3ef2a986cdf4
Reviewed-by: Alex Blasche <alexander.blasche@theqtcompany.com>
Diffstat (limited to 'src/bluetooth/osx')
-rw-r--r-- | src/bluetooth/osx/osxbtcentralmanager.mm | 35 | ||||
-rw-r--r-- | src/bluetooth/osx/osxbtcentralmanagerdelegate_p.h | 2 | ||||
-rw-r--r-- | src/bluetooth/osx/osxbtutility.mm | 29 |
3 files changed, 60 insertions, 6 deletions
diff --git a/src/bluetooth/osx/osxbtcentralmanager.mm b/src/bluetooth/osx/osxbtcentralmanager.mm index d2e45832..32fad1db 100644 --- a/src/bluetooth/osx/osxbtcentralmanager.mm +++ b/src/bluetooth/osx/osxbtcentralmanager.mm @@ -252,6 +252,20 @@ using namespace QT_NAMESPACE; - (void)discoverServices { + Q_ASSERT_X(peripheral, "-discoverServices", "invalid peripheral (nil)"); + Q_ASSERT_X(managerState == OSXBluetooth::CentralManagerIdle, + "-discoverServices", "invalid state"); + + // From Apple's docs: + // + //"If the servicesUUIDs parameter is nil, all the available + //services of the peripheral are returned; setting the + //parameter to nil is considerably slower and is not recommended." + // + // ... but we'd like to have them all: + [peripheral setDelegate:self]; + managerState = OSXBluetooth::CentralManagerDiscovering; + [peripheral discoverServices:nil]; } - (bool)discoverServiceDetails:(const QBluetoothUuid &)serviceUuid @@ -425,7 +439,26 @@ using namespace QT_NAMESPACE; - (void)peripheral:(CBPeripheral *)aPeripheral didDiscoverServices:(NSError *)error { Q_UNUSED(aPeripheral) - Q_UNUSED(error) + + + if (managerState != OSXBluetooth::CentralManagerDiscovering) { + // Canceled by -disconnectFromDevice. + return; + } + + managerState = OSXBluetooth::CentralManagerIdle; + + if (error) { + // NSLog, not qCDebug/Warning - to print the error. + NSLog(@"-peripheral:didDiscoverServices:, failed with error %@", error); + // TODO: better error mapping required. + delegate->error(QLowEnergyController::UnknownError); + } else { + QT_BT_MAC_AUTORELEASEPOOL; + + OSXBluetooth::ObjCStrongReference<NSArray> services(peripheral.services, true); + delegate->serviceDiscoveryFinished(services); + } } diff --git a/src/bluetooth/osx/osxbtcentralmanagerdelegate_p.h b/src/bluetooth/osx/osxbtcentralmanagerdelegate_p.h index 65b5e61f..196e14d0 100644 --- a/src/bluetooth/osx/osxbtcentralmanagerdelegate_p.h +++ b/src/bluetooth/osx/osxbtcentralmanagerdelegate_p.h @@ -54,6 +54,8 @@ // and later in the delegate's -centralManagerDidUpdateState: we are trying to finally release // a manager. Otherwise, this thing dies even with ARC. +// TODO: can not reproduce this crash anymore ... probably, this class will be removed soon. + @interface QT_MANGLE_NAMESPACE(OSXBTCentralManagerTransientDelegate) : NSObject<CBCentralManagerDelegate> { CBCentralManager *manager; diff --git a/src/bluetooth/osx/osxbtutility.mm b/src/bluetooth/osx/osxbtutility.mm index 74ee84e6..69e94434 100644 --- a/src/bluetooth/osx/osxbtutility.mm +++ b/src/bluetooth/osx/osxbtutility.mm @@ -165,19 +165,38 @@ QString qt_error_string(IOReturn errorCode) QBluetoothUuid qt_uuid(CBUUID *uuid) { + // Apples' docs say "128 bit" and "16-bit UUIDs are implicitly + // pre-filled with the Bluetooth Base UUID." + // But Core Bluetooth can return CBUUID objects of length 2 + // (16-bit, so they are not pre-filled?). + if (!uuid) return QBluetoothUuid(); QT_BT_MAC_AUTORELEASEPOOL; - if (uuid.data.length != 16) // TODO: warning? + if (uuid.data.length == 2) { + // TODO: this is .. UGLY :) + quint16 qtUuidData = 0; + const quint8 *const source = static_cast<const quint8 *>(uuid.data.bytes); + std::copy(source, source + 2, &qtUuidData); + + return QBluetoothUuid(qtUuidData); + } else if (uuid.data.length == 16) { + quint128 qtUuidData = {}; + const quint8 *const source = static_cast<const quint8 *>(uuid.data.bytes); + std::copy(source, source + 16, qtUuidData.data); + + return QBluetoothUuid(qtUuidData); + } else { + qCDebug(QT_BT_OSX) << "qt_uuid, invalid CBUUID, 2 or 16 bytes expected, but got " + << uuid.data.length << " bytes length"; return QBluetoothUuid(); + } - quint128 qtUuidData = {}; - const quint8 *const source = static_cast<const quint8 *>(uuid.data.bytes); - std::copy(source, source + 16, qtUuidData.data); + if (uuid.data.length != 16) // TODO: warning? + return QBluetoothUuid(); - return QBluetoothUuid(qtUuidData); } CFStrongReference<CFUUIDRef> cf_uuid(const QBluetoothUuid &qtUuid) |