diff options
Diffstat (limited to 'src/bluetooth/osx/osxbtcentralmanager.mm')
-rw-r--r-- | src/bluetooth/osx/osxbtcentralmanager.mm | 218 |
1 files changed, 74 insertions, 144 deletions
diff --git a/src/bluetooth/osx/osxbtcentralmanager.mm b/src/bluetooth/osx/osxbtcentralmanager.mm index 06425753..f7218ca6 100644 --- a/src/bluetooth/osx/osxbtcentralmanager.mm +++ b/src/bluetooth/osx/osxbtcentralmanager.mm @@ -43,7 +43,6 @@ #include "osxbtnotifier_p.h" #include <QtCore/qloggingcategory.h> -#include <QtCore/qsysinfo.h> #include <QtCore/qdebug.h> #include <algorithm> @@ -116,7 +115,7 @@ QT_END_NAMESPACE @implementation QT_MANGLE_NAMESPACE(OSXBTCentralManager) -- (id)initWith:(OSXBluetooth::LECentralNotifier *)aNotifier +- (id)initWith:(OSXBluetooth::LECBManagerNotifier *)aNotifier { if (self = [super init]) { manager = nil; @@ -171,9 +170,9 @@ QT_END_NAMESPACE if (!manager) { managerState = OSXBluetooth::CentralManagerIdle; - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed to allocate a central manager"; + qCWarning(QT_BT_OSX) << "failed to allocate a central manager"; if (notifier) - emit notifier->CBCentralManagerError(QLowEnergyController::ConnectionError); + emit notifier->CBManagerError(QLowEnergyController::ConnectionError); } } else if (managerState != OSXBluetooth::CentralManagerUpdating) { [self retrievePeripheralAndConnect]; @@ -187,7 +186,7 @@ QT_END_NAMESPACE Q_FUNC_INFO, "invalid state"); if ([self isConnected]) { - qCDebug(QT_BT_OSX) << Q_FUNC_INFO << "already connected"; + qCDebug(QT_BT_OSX) << "already connected"; if (notifier) emit notifier->connected(); return; @@ -203,62 +202,37 @@ QT_END_NAMESPACE // Retrieve a peripheral first ... ObjCScopedPointer<NSMutableArray> uuids([[NSMutableArray alloc] init]); if (!uuids) { - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed to allocate identifiers"; + qCWarning(QT_BT_OSX) << "failed to allocate identifiers"; if (notifier) - emit notifier->CBCentralManagerError(QLowEnergyController::ConnectionError); + emit notifier->CBManagerError(QLowEnergyController::ConnectionError); return; } -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9, __IPHONE_7_0) - if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_9, QSysInfo::MV_IOS_7_0)) { - const quint128 qtUuidData(deviceUuid.toUInt128()); - // STATIC_ASSERT on sizes would be handy! - uuid_t uuidData = {}; - std::copy(qtUuidData.data, qtUuidData.data + 16, uuidData); - const ObjCScopedPointer<NSUUID> nsUuid([[NSUUID alloc] initWithUUIDBytes:uuidData]); - if (!nsUuid) { - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed to allocate NSUUID identifier"; - if (notifier) - emit notifier->CBCentralManagerError(QLowEnergyController::ConnectionError); - return; - } - - [uuids addObject:nsUuid]; - // With the latest CoreBluetooth, we can synchronously retrive peripherals: - QT_BT_MAC_AUTORELEASEPOOL; - NSArray *const peripherals = [manager retrievePeripheralsWithIdentifiers:uuids]; - if (!peripherals || peripherals.count != 1) { - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed to retrive a peripheral"; - if (notifier) - emit notifier->CBCentralManagerError(QLowEnergyController::UnknownRemoteDeviceError); - return; - } - peripheral = [static_cast<CBPeripheral *>([peripherals objectAtIndex:0]) retain]; - [self connectToPeripheral]; - return; - } -#endif - // Either SDK or the target is below 10.9/7.0 - if (![manager respondsToSelector:@selector(retrievePeripherals:)]) { - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed to retrive a peripheral"; + const quint128 qtUuidData(deviceUuid.toUInt128()); + uuid_t uuidData = {}; + std::copy(qtUuidData.data, qtUuidData.data + 16, uuidData); + const ObjCScopedPointer<NSUUID> nsUuid([[NSUUID alloc] initWithUUIDBytes:uuidData]); + if (!nsUuid) { + qCWarning(QT_BT_OSX) << "failed to allocate NSUUID identifier"; if (notifier) - emit notifier->CBCentralManagerError(QLowEnergyController::UnknownRemoteDeviceError); + emit notifier->CBManagerError(QLowEnergyController::ConnectionError); return; } - OSXBluetooth::CFStrongReference<CFUUIDRef> cfUuid(OSXBluetooth::cf_uuid(deviceUuid)); - if (!cfUuid) { - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed to create CFUUID object"; + [uuids addObject:nsUuid]; + // With the latest CoreBluetooth, we can synchronously retrive peripherals: + QT_BT_MAC_AUTORELEASEPOOL; + NSArray *const peripherals = [manager retrievePeripheralsWithIdentifiers:uuids]; + if (!peripherals || peripherals.count != 1) { + qCWarning(QT_BT_OSX) << "failed to retrive a peripheral"; if (notifier) - emit notifier->CBCentralManagerError(QLowEnergyController::ConnectionError); + emit notifier->CBManagerError(QLowEnergyController::UnknownRemoteDeviceError); return; } - // With ARC this cast will be illegal: - [uuids addObject:(id)cfUuid.data()]; - // Unfortunately, with old Core Bluetooth this call is asynchronous ... - managerState = OSXBluetooth::CentralManagerConnecting; - [manager performSelector:@selector(retrievePeripherals:) withObject:uuids.data()]; + + peripheral = [static_cast<CBPeripheral *>([peripherals objectAtIndex:0]) retain]; + [self connectToPeripheral]; } - (void)connectToPeripheral @@ -270,11 +244,11 @@ QT_END_NAMESPACE // The state is still the same - connecting. if ([self isConnected]) { - qCDebug(QT_BT_OSX) << Q_FUNC_INFO << "already connected"; + qCDebug(QT_BT_OSX) << "already connected"; if (notifier) emit notifier->connected(); } else { - qCDebug(QT_BT_OSX) << Q_FUNC_INFO << "trying to connect"; + qCDebug(QT_BT_OSX) << "trying to connect"; managerState = OSXBluetooth::CentralManagerConnecting; [manager connectPeripheral:peripheral options:nil]; } @@ -285,18 +259,7 @@ QT_END_NAMESPACE if (!peripheral) return false; -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9, __IPHONE_7_0) - using OSXBluetooth::qt_OS_limit; - - if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_9, QSysInfo::MV_IOS_7_0)) - return peripheral.state == CBPeripheralStateConnected; -#endif - // Either SDK or the target is below 10.9/7.0 ... - if (![peripheral respondsToSelector:@selector(isConnected)]) - return false; - - // Ugly cast to deal with id being a pointer ... - return reinterpret_cast<quintptr>([peripheral performSelector:@selector(isConnected)]); + return peripheral.state == CBPeripheralStateConnected; } - (void)disconnectFromDevice @@ -389,7 +352,7 @@ QT_END_NAMESPACE Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)"); if (servicesToDiscoverDetails.contains(serviceUuid)) { - qCWarning(QT_BT_OSX) << Q_FUNC_INFO <<"already discovering for " + qCWarning(QT_BT_OSX) << "already discovering for" << serviceUuid; return; } @@ -402,11 +365,11 @@ QT_END_NAMESPACE return; } - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "unknown service uuid " + qCWarning(QT_BT_OSX) << "unknown service uuid" << serviceUuid; if (notifier) { - emit notifier->CBCentralManagerError(serviceUuid, + emit notifier->CBManagerError(serviceUuid, QLowEnergyService::UnknownError); } } @@ -499,9 +462,9 @@ QT_END_NAMESPACE const QLowEnergyHandle maxHandle = std::numeric_limits<QLowEnergyHandle>::max(); if (nHandles >= maxHandle || lastValidHandle > maxHandle - nHandles) { // Well, that's unlikely :) But we must be sure. - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "can not allocate more handles"; + qCWarning(QT_BT_OSX) << "can not allocate more handles"; if (notifier) - notifier->CBCentralManagerError(serviceUuid, QLowEnergyService::OperationError); + notifier->CBManagerError(serviceUuid, QLowEnergyService::OperationError); return; } @@ -603,7 +566,7 @@ QT_END_NAMESPACE const LERequest request(requests.dequeue()); if (request.type == LERequest::CharRead) { if (!charMap.contains(request.handle)) { - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "characteristic with handle" + qCWarning(QT_BT_OSX) << "characteristic with handle" << request.handle << "not found"; return [self performNextRequest]; } @@ -613,7 +576,7 @@ QT_END_NAMESPACE [peripheral readValueForCharacteristic:charMap[request.handle]]; } else { if (!descMap.contains(request.handle)) { - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "descriptor with handle" + qCWarning(QT_BT_OSX) << "descriptor with handle" << request.handle << "not found"; return [self performNextRequest]; } @@ -640,8 +603,8 @@ QT_END_NAMESPACE if (request.type == LERequest::DescWrite) { if (!descMap.contains(request.handle)) { - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "handle: " - << request.handle << " not found"; + qCWarning(QT_BT_OSX) << "handle:" << request.handle + << "not found"; return [self performNextRequest]; } @@ -649,8 +612,7 @@ QT_END_NAMESPACE ObjCStrongReference<NSData> data(data_from_bytearray(request.value)); if (!data) { // Even if qtData.size() == 0, we still need NSData object. - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed " - "to allocate an NSData object"; + qCWarning(QT_BT_OSX) << "failed to allocate an NSData object"; return [self performNextRequest]; } @@ -661,8 +623,8 @@ QT_END_NAMESPACE return [peripheral writeValue:data.data() forDescriptor:descriptor]; } else { if (!charMap.contains(request.handle)) { - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "characteristic with " - "handle: " << request.handle << " not found"; + qCWarning(QT_BT_OSX) << "characteristic with handle:" + << request.handle << "not found"; return [self performNextRequest]; } @@ -687,7 +649,7 @@ QT_END_NAMESPACE ObjCStrongReference<NSData> data(data_from_bytearray(request.value)); if (!data) { // Even if qtData.size() == 0, we still need NSData object. - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed to allocate NSData object"; + qCWarning(QT_BT_OSX) << "failed to allocate NSData object"; return [self performNextRequest]; } @@ -717,11 +679,10 @@ QT_END_NAMESPACE Q_ASSERT_X(charHandle, Q_FUNC_INFO, "invalid characteristic handle (0)"); if (!charMap.contains(charHandle)) { - qCWarning(QT_BT_OSX) << Q_FUNC_INFO - << "unknown characteristic handle " + qCWarning(QT_BT_OSX) << "unknown characteristic handle" << charHandle; if (notifier) { - emit notifier->CBCentralManagerError(serviceUuid, + emit notifier->CBManagerError(serviceUuid, QLowEnergyService::DescriptorWriteError); } return; @@ -732,10 +693,9 @@ QT_END_NAMESPACE // it back, so check _now_ that we really have this descriptor. const QBluetoothUuid qtUuid(QBluetoothUuid::ClientCharacteristicConfiguration); if (![self descriptor:qtUuid forCharacteristic:charMap[charHandle]]) { - qCWarning(QT_BT_OSX) << Q_FUNC_INFO - << "no client characteristic configuration found"; + qCWarning(QT_BT_OSX) << "no client characteristic configuration found"; if (notifier) { - emit notifier->CBCentralManagerError(serviceUuid, + emit notifier->CBManagerError(serviceUuid, QLowEnergyService::DescriptorWriteError); } return; @@ -760,9 +720,9 @@ QT_END_NAMESPACE QT_BT_MAC_AUTORELEASEPOOL; if (!charMap.contains(charHandle)) { - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "characteristic: " << charHandle << " not found"; + qCWarning(QT_BT_OSX) << "characteristic:" << charHandle << "not found"; if (notifier) { - emit notifier->CBCentralManagerError(serviceUuid, + emit notifier->CBManagerError(serviceUuid, QLowEnergyService::CharacteristicReadError); } @@ -789,10 +749,9 @@ QT_END_NAMESPACE QT_BT_MAC_AUTORELEASEPOOL; if (!charMap.contains(charHandle)) { - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "characteristic: " - << charHandle << " not found"; + qCWarning(QT_BT_OSX) << "characteristic:" << charHandle << "not found"; if (notifier) { - emit notifier->CBCentralManagerError(serviceUuid, + emit notifier->CBManagerError(serviceUuid, QLowEnergyService::CharacteristicWriteError); } return; @@ -816,10 +775,9 @@ QT_END_NAMESPACE Q_ASSERT_X(descHandle, Q_FUNC_INFO, "invalid descriptor handle (0)"); if (!descMap.contains(descHandle)) { - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "handle:" - << descHandle << "not found"; + qCWarning(QT_BT_OSX) << "handle:" << descHandle << "not found"; if (notifier) { - emit notifier->CBCentralManagerError(serviceUuid, + emit notifier->CBManagerError(serviceUuid, QLowEnergyService::DescriptorReadError); } return; @@ -842,10 +800,9 @@ QT_END_NAMESPACE Q_ASSERT_X(descHandle, Q_FUNC_INFO, "invalid descriptor handle (0)"); if (!descMap.contains(descHandle)) { - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "handle: " - << descHandle << " not found"; + qCWarning(QT_BT_OSX) << "handle:" << descHandle << "not found"; if (notifier) { - emit notifier->CBCentralManagerError(serviceUuid, + emit notifier->CBManagerError(serviceUuid, QLowEnergyService::DescriptorWriteError); } return; @@ -1029,27 +986,25 @@ QT_END_NAMESPACE if ([obj isKindOfClass:[CBCharacteristic class]]) { CBCharacteristic *const ch = static_cast<CBCharacteristic *>(obj); if (!charMap.key(ch)) { - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "unexpected " - "characteristic, no handle found"; + qCWarning(QT_BT_OSX) << "unexpected characteristic, no handle found"; return false; } } else if ([obj isKindOfClass:[CBDescriptor class]]) { CBDescriptor *const d = static_cast<CBDescriptor *>(obj); if (!descMap.key(d)) { - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "unexpected " - "descriptor, no handle found"; + qCWarning(QT_BT_OSX) << "unexpected descriptor, no handle found"; return false; } } else { - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "invalid object, " - "characteristic or descriptor required"; + qCWarning(QT_BT_OSX) << "invalid object, characteristic " + "or descriptor required"; return false; } if (valuesToWrite.contains(obj)) { // It can be a result of some previous errors - for example, // we never got a callback from a previous write. - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "already has a cached value for this " + qCWarning(QT_BT_OSX) << "already has a cached value for this " "object, the value will be replaced"; } @@ -1114,7 +1069,7 @@ QT_END_NAMESPACE // and reset managerState from CentralManagerUpdating. managerState = CentralManagerIdle; if (notifier) - emit notifier->CBCentralManagerError(QLowEnergyController::InvalidBluetoothAdapterError); + emit notifier->CBManagerError(QLowEnergyController::InvalidBluetoothAdapterError); } return; } @@ -1133,7 +1088,7 @@ QT_END_NAMESPACE // TODO: we need a better error + // what will happen if later the state changes to PoweredOn??? if (notifier) - emit notifier->CBCentralManagerError(QLowEnergyController::InvalidBluetoothAdapterError); + emit notifier->CBManagerError(QLowEnergyController::InvalidBluetoothAdapterError); } return; } @@ -1153,30 +1108,6 @@ QT_END_NAMESPACE } } -- (void)centralManager:(CBCentralManager *)central didRetrievePeripherals:(NSArray *)peripherals -{ - Q_UNUSED(central) - - // This method is required for iOS before 7.0 and OS X below 10.9. - Q_ASSERT_X(manager, Q_FUNC_INFO, "invalid central manager (nil)"); - - if (managerState != OSXBluetooth::CentralManagerConnecting) { - // Canceled by calling -disconnectFromDevice method. - return; - } - - managerState = OSXBluetooth::CentralManagerIdle; - - if (!peripherals || peripherals.count != 1) { - qCDebug(QT_BT_OSX) << Q_FUNC_INFO <<"unexpected number of peripherals (!= 1)"; - if (notifier) - emit notifier->CBCentralManagerError(QLowEnergyController::UnknownRemoteDeviceError); - } else { - peripheral = [static_cast<CBPeripheral *>([peripherals objectAtIndex:0]) retain]; - [self connectToPeripheral]; - } -} - - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)aPeripheral { Q_UNUSED(central) @@ -1207,7 +1138,7 @@ QT_END_NAMESPACE managerState = OSXBluetooth::CentralManagerIdle; // TODO: better error mapping is required. if (notifier) - notifier->CBCentralManagerError(QLowEnergyController::UnknownRemoteDeviceError); + notifier->CBManagerError(QLowEnergyController::UnknownRemoteDeviceError); } - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)aPeripheral @@ -1221,9 +1152,9 @@ QT_END_NAMESPACE if (error && managerState == OSXBluetooth::CentralManagerDisconnecting) { managerState = OSXBluetooth::CentralManagerIdle; - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed to disconnect"; + qCWarning(QT_BT_OSX) << "failed to disconnect"; if (notifier) - emit notifier->CBCentralManagerError(QLowEnergyController::UnknownRemoteDeviceError); + emit notifier->CBManagerError(QLowEnergyController::UnknownRemoteDeviceError); } else { managerState = OSXBluetooth::CentralManagerIdle; if (notifier) @@ -1248,7 +1179,7 @@ QT_END_NAMESPACE NSLog(@"%s failed with error %@", Q_FUNC_INFO, error); // TODO: better error mapping required. if (notifier) - emit notifier->CBCentralManagerError(QLowEnergyController::UnknownError); + emit notifier->CBManagerError(QLowEnergyController::UnknownError); } else { [self discoverIncludedServices]; } @@ -1344,7 +1275,7 @@ QT_END_NAMESPACE NSLog(@"%s failed with error: %@", Q_FUNC_INFO, error); // We did not discover any characteristics and can not discover descriptors, // inform our delegate (it will set a service state also). - emit notifier->CBCentralManagerError(qt_uuid(service.UUID), QLowEnergyController::UnknownError); + emit notifier->CBManagerError(qt_uuid(service.UUID), QLowEnergyController::UnknownError); } else { [self readCharacteristics:service]; } @@ -1379,7 +1310,7 @@ QT_END_NAMESPACE if (chHandle && chHandle == currentReadHandle) { currentReadHandle = 0; requestPending = false; - emit notifier->CBCentralManagerError(qtUuid, QLowEnergyService::CharacteristicReadError); + emit notifier->CBManagerError(qtUuid, QLowEnergyService::CharacteristicReadError); [self performNextRequest]; } return; @@ -1402,7 +1333,7 @@ QT_END_NAMESPACE // updated values ... // TODO: this must be properly tested. if (!chHandle) { - qCCritical(QT_BT_OSX) << Q_FUNC_INFO << "unexpected update notification, " + qCCritical(QT_BT_OSX) << "unexpected update notification, " "no characteristic handle found"; return; } @@ -1481,7 +1412,7 @@ QT_END_NAMESPACE if (dHandle && dHandle == currentReadHandle) { currentReadHandle = 0; requestPending = false; - emit notifier->CBCentralManagerError(qtUuid, QLowEnergyService::DescriptorReadError); + emit notifier->CBManagerError(qtUuid, QLowEnergyService::DescriptorReadError); [self performNextRequest]; } return; @@ -1513,7 +1444,7 @@ QT_END_NAMESPACE } } else { if (!dHandle) { - qCCritical(QT_BT_OSX) << Q_FUNC_INFO << "unexpected value update notification, " + qCCritical(QT_BT_OSX) << "unexpected value update notification, " "no descriptor handle found"; return; } @@ -1556,13 +1487,13 @@ QT_END_NAMESPACE // Error or not, but the cached value has to be deleted ... const QByteArray valueToReport(valuesToWrite.value(characteristic, QByteArray())); if (!valuesToWrite.remove(characteristic)) { - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "no updated value found" - " for characteristic"; + qCWarning(QT_BT_OSX) << "no updated value found " + "for characteristic"; } if (error) { NSLog(@"%s failed with error %@", Q_FUNC_INFO, error); - emit notifier->CBCentralManagerError(qt_uuid(characteristic.service.UUID), + emit notifier->CBManagerError(qt_uuid(characteristic.service.UUID), QLowEnergyService::CharacteristicWriteError); } else { const QLowEnergyHandle cHandle = charMap.key(characteristic); @@ -1592,16 +1523,15 @@ QT_END_NAMESPACE // Error or not, a value (if any) must be removed. const QByteArray valueToReport(valuesToWrite.value(descriptor, QByteArray())); if (!valuesToWrite.remove(descriptor)) - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "no updated value found"; + qCWarning(QT_BT_OSX) << "no updated value found"; if (error) { NSLog(@"%s failed with error %@", Q_FUNC_INFO, error); - emit notifier->CBCentralManagerError(qt_uuid(descriptor.characteristic.service.UUID), + emit notifier->CBManagerError(qt_uuid(descriptor.characteristic.service.UUID), QLowEnergyService::DescriptorWriteError); } else { const QLowEnergyHandle dHandle = descMap.key(descriptor); - Q_ASSERT_X(dHandle, Q_FUNC_INFO, - "descriptor not found in the descriptors map"); + Q_ASSERT_X(dHandle, Q_FUNC_INFO, "descriptor not found in the descriptors map"); emit notifier->descriptorWritten(dHandle, valueToReport); } @@ -1631,7 +1561,7 @@ QT_END_NAMESPACE if (error) { NSLog(@"%s failed with error %@", Q_FUNC_INFO, error); // In Qt's API it's a descriptor write actually. - emit notifier->CBCentralManagerError(qt_uuid(characteristic.service.UUID), + emit notifier->CBManagerError(qt_uuid(characteristic.service.UUID), QLowEnergyService::DescriptorWriteError); } else if (nRemoved) { const QLowEnergyHandle dHandle = descMap.key(descriptor); |