diff options
author | Alex Blasche <alexander.blasche@theqtcompany.com> | 2016-05-13 08:26:38 +0200 |
---|---|---|
committer | Alex Blasche <alexander.blasche@theqtcompany.com> | 2016-05-13 08:27:40 +0200 |
commit | 61a7dd3f79525f82345f2e0606b05fce74cb9ec5 (patch) | |
tree | 5a669a730ea765487e0895bc254eb802c8b29429 /src/bluetooth/osx | |
parent | 03e956dc8f80d7131f89f8e6088c5dfc68eaf94d (diff) | |
parent | 2d98ac01e74dc53d9fd42668e3757ca806af9556 (diff) |
Merge branch 'dev' into btle
Change-Id: I073f6c45696fe28b83335fb65cca6270c458851d
Diffstat (limited to 'src/bluetooth/osx')
34 files changed, 2291 insertions, 843 deletions
diff --git a/src/bluetooth/osx/corebluetoothwrapper_p.h b/src/bluetooth/osx/corebluetoothwrapper_p.h index d0b6f23c..1d67c6ba 100644 --- a/src/bluetooth/osx/corebluetoothwrapper_p.h +++ b/src/bluetooth/osx/corebluetoothwrapper_p.h @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** @@ -34,6 +40,17 @@ #ifndef COREBLUETOOTHWRAPPER_P_H #define COREBLUETOOTHWRAPPER_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #ifndef QT_OSX_BLUETOOTH #import <CoreBluetooth/CoreBluetooth.h> diff --git a/src/bluetooth/osx/osxbt.pri b/src/bluetooth/osx/osxbt.pri index 06389fcc..fc0a5a65 100644 --- a/src/bluetooth/osx/osxbt.pri +++ b/src/bluetooth/osx/osxbt.pri @@ -1,5 +1,6 @@ -SOURCES += osx/uistrings.cpp +SOURCES += osx/uistrings.cpp osx/osxbtnotifier.cpp PRIVATE_HEADERS += osx/uistrings_p.h +//QMAKE_CXXFLAGS_WARN_ON += -Wno-nullability-completeness CONFIG(osx) { PRIVATE_HEADERS += osx/osxbtutility_p.h \ @@ -15,7 +16,9 @@ CONFIG(osx) { osx/osxbtobexsession_p.h \ osx/osxbtledeviceinquiry_p.h \ osx/corebluetoothwrapper_p.h \ - osx/osxbtcentralmanager_p.h + osx/osxbtcentralmanager_p.h \ + osx/osxbtnotifier_p.h \ + osx/osxbtperipheralmanager_p.h OBJECTIVE_SOURCES += osx/osxbtutility.mm \ osx/osxbtdevicepair.mm \ @@ -29,14 +32,18 @@ CONFIG(osx) { osx/osxbtsocketlistener.mm \ osx/osxbtobexsession.mm \ osx/osxbtledeviceinquiry.mm \ - osx/osxbtcentralmanager.mm + osx/osxbtcentralmanager.mm \ + osx/osxbtperipheralmanager.mm } else { PRIVATE_HEADERS += osx/osxbtutility_p.h \ osx/osxbtledeviceinquiry_p.h \ osx/corebluetoothwrapper_p.h \ - osx/osxbtcentralmanager_p.h + osx/osxbtcentralmanager_p.h \ + osx/osxbtnotifier_p.h \ + osx/osxbtperipheralmanager_p.h OBJECTIVE_SOURCES += osx/osxbtutility.mm \ osx/osxbtledeviceinquiry.mm \ - osx/osxbtcentralmanager.mm + osx/osxbtcentralmanager.mm \ + osx/osxbtperipheralmanager.mm } diff --git a/src/bluetooth/osx/osxbtcentralmanager.mm b/src/bluetooth/osx/osxbtcentralmanager.mm index 08905da8..3b0e098d 100644 --- a/src/bluetooth/osx/osxbtcentralmanager.mm +++ b/src/bluetooth/osx/osxbtcentralmanager.mm @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** @@ -34,7 +40,7 @@ #include "qlowenergyserviceprivate_p.h" #include "qlowenergycharacteristic.h" #include "osxbtcentralmanager_p.h" - +#include "osxbtnotifier_p.h" #include <QtCore/qloggingcategory.h> #include <QtCore/qsysinfo.h> @@ -43,14 +49,14 @@ #include <algorithm> #include <limits> +Q_DECLARE_METATYPE(QLowEnergyCharacteristic) +Q_DECLARE_METATYPE(QLowEnergyDescriptor) +Q_DECLARE_METATYPE(QLowEnergyHandle) + QT_BEGIN_NAMESPACE namespace OSXBluetooth { -CentralManagerDelegate::~CentralManagerDelegate() -{ -} - NSUInteger qt_countGATTEntries(CBService *service) { // Identify, how many characteristics/descriptors we have on a given service, @@ -81,14 +87,10 @@ NSUInteger qt_countGATTEntries(CBService *service) QT_END_NAMESPACE -#ifdef QT_NAMESPACE -using namespace QT_NAMESPACE; -#endif - @interface QT_MANGLE_NAMESPACE(OSXBTCentralManager) (PrivateAPI) -- (QLowEnergyController::Error)connectToDevice; // "Device" is in Qt's world ... -- (void)connectToPeripheral; // "Peripheral" is in Core Bluetooth. +- (void)retrievePeripheralAndConnect; +- (void)connectToPeripheral; - (void)discoverIncludedServices; - (void)readCharacteristics:(CBService *)service; - (void)serviceDetailsDiscoveryFinished:(CBService *)service; @@ -114,16 +116,14 @@ using namespace QT_NAMESPACE; @implementation QT_MANGLE_NAMESPACE(OSXBTCentralManager) -- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(OSXBluetooth)::CentralManagerDelegate *)aDelegate +- (id)initWith:(OSXBluetooth::LECBManagerNotifier *)aNotifier { - Q_ASSERT_X(aDelegate, Q_FUNC_INFO, "invalid delegate (null)"); - if (self = [super init]) { manager = nil; managerState = OSXBluetooth::CentralManagerIdle; disconnectPending = false; peripheral = nil; - delegate = aDelegate; + notifier = aNotifier; currentService = 0; lastValidHandle = 0; requestPending = false; @@ -150,32 +150,37 @@ using namespace QT_NAMESPACE; [peripheral setDelegate:nil]; [peripheral release]; + if (notifier) + notifier->deleteLater(); + [super dealloc]; } -- (QLowEnergyController::Error)connectToDevice:(const QBluetoothUuid &)aDeviceUuid +- (void)connectToDevice:(const QBluetoothUuid &)aDeviceUuid { - Q_ASSERT_X(managerState == OSXBluetooth::CentralManagerIdle, - Q_FUNC_INFO, "invalid state"); - + disconnectPending = false; // Cancel the previous disconnect if any. deviceUuid = aDeviceUuid; if (!manager) { - managerState = OSXBluetooth::CentralManagerUpdating; // We'll have to wait for updated state. - manager = [[CBCentralManager alloc] initWithDelegate:self queue:nil]; + // The first time we try to connect, no manager created yet, + // no status update received. + if (const dispatch_queue_t leQueue = OSXBluetooth::qt_LE_queue()) { + managerState = OSXBluetooth::CentralManagerUpdating; + manager = [[CBCentralManager alloc] initWithDelegate:self queue:leQueue]; + } + if (!manager) { managerState = OSXBluetooth::CentralManagerIdle; - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed to allocate a " - "central manager"; - return QLowEnergyController::ConnectionError; + qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed to allocate a central manager"; + if (notifier) + emit notifier->CBManagerError(QLowEnergyController::ConnectionError); } - return QLowEnergyController::NoError; - } else { - return [self connectToDevice]; + } else if (managerState != OSXBluetooth::CentralManagerUpdating) { + [self retrievePeripheralAndConnect]; } } -- (QLowEnergyController::Error)connectToDevice +- (void)retrievePeripheralAndConnect { Q_ASSERT_X(manager, Q_FUNC_INFO, "invalid central manager (nil)"); Q_ASSERT_X(managerState == OSXBluetooth::CentralManagerIdle, @@ -183,13 +188,14 @@ using namespace QT_NAMESPACE; if ([self isConnected]) { qCDebug(QT_BT_OSX) << Q_FUNC_INFO << "already connected"; - delegate->connectSuccess(); - return QLowEnergyController::NoError; + if (notifier) + emit notifier->connected(); + return; } else if (peripheral) { // Was retrieved already, but not connected // or disconnected. [self connectToPeripheral]; - return QLowEnergyController::NoError; + return; } using namespace OSXBluetooth; @@ -198,11 +204,13 @@ using namespace QT_NAMESPACE; ObjCScopedPointer<NSMutableArray> uuids([[NSMutableArray alloc] init]); if (!uuids) { qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed to allocate identifiers"; - return QLowEnergyController::ConnectionError; + if (notifier) + emit notifier->CBManagerError(QLowEnergyController::ConnectionError); + return; } -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9, __IPHONE_6_0) - if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_9, QSysInfo::MV_IOS_6_0)) { +#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 = {}; @@ -210,37 +218,47 @@ using namespace QT_NAMESPACE; const ObjCScopedPointer<NSUUID> nsUuid([[NSUUID alloc] initWithUUIDBytes:uuidData]); if (!nsUuid) { qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed to allocate NSUUID identifier"; - return QLowEnergyController::ConnectionError; + if (notifier) + emit notifier->CBManagerError(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"; - return QLowEnergyController::UnknownRemoteDeviceError; + if (notifier) + emit notifier->CBManagerError(QLowEnergyController::UnknownRemoteDeviceError); + return; } peripheral = [static_cast<CBPeripheral *>([peripherals objectAtIndex:0]) retain]; [self connectToPeripheral]; - - return QLowEnergyController::NoError; + 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"; + if (notifier) + emit notifier->CBManagerError(QLowEnergyController::UnknownRemoteDeviceError); + return; + } + OSXBluetooth::CFStrongReference<CFUUIDRef> cfUuid(OSXBluetooth::cf_uuid(deviceUuid)); if (!cfUuid) { qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed to create CFUUID object"; - return QLowEnergyController::ConnectionError; + if (notifier) + emit notifier->CBManagerError(QLowEnergyController::ConnectionError); + return; } - // TODO: With ARC this cast will be illegal: + // 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 retrievePeripherals:uuids]; - - return QLowEnergyController::NoError; + [manager performSelector:@selector(retrievePeripherals:) withObject:uuids.data()]; } - (void)connectToPeripheral @@ -253,7 +271,8 @@ using namespace QT_NAMESPACE; // The state is still the same - connecting. if ([self isConnected]) { qCDebug(QT_BT_OSX) << Q_FUNC_INFO << "already connected"; - delegate->connectSuccess(); + if (notifier) + emit notifier->connected(); } else { qCDebug(QT_BT_OSX) << Q_FUNC_INFO << "trying to connect"; managerState = OSXBluetooth::CentralManagerConnecting; @@ -272,7 +291,12 @@ using namespace QT_NAMESPACE; if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_9, QSysInfo::MV_IOS_7_0)) return peripheral.state == CBPeripheralStateConnected; #endif - return peripheral.isConnected; + // 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)]); } - (void)disconnectFromDevice @@ -280,10 +304,17 @@ using namespace QT_NAMESPACE; [self reset]; if (managerState == OSXBluetooth::CentralManagerUpdating) { - disconnectPending = true; + disconnectPending = true; // this is for 'didUpdate' method. + if (notifier) { + // We were waiting for the first update + // with 'PoweredOn' status, when suddenly got disconnected called. + // Since we have not attempted to connect yet, emit now. + // Note: we do not change the state, since we still maybe interested + // in the status update before the next connect attempt. + emit notifier->disconnected(); + } } else { disconnectPending = false; - if ([self isConnected]) managerState = OSXBluetooth::CentralManagerDisconnecting; else @@ -292,8 +323,9 @@ using namespace QT_NAMESPACE; // We have to call -cancelPeripheralConnection: even // if not connected (to cancel a pending connect attempt). // Unfortunately, didDisconnect callback is not always called - // (despite of Apple's docs saying it _must_). - [manager cancelPeripheralConnection:peripheral]; + // (despite of Apple's docs saying it _must_ be). + if (peripheral) + [manager cancelPeripheralConnection:peripheral]; } } @@ -310,7 +342,6 @@ using namespace QT_NAMESPACE; //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]; @@ -320,19 +351,17 @@ using namespace QT_NAMESPACE; { using namespace OSXBluetooth; - Q_ASSERT_X(managerState == CentralManagerIdle, Q_FUNC_INFO, - "invalid state"); + Q_ASSERT_X(managerState == CentralManagerIdle, Q_FUNC_INFO, "invalid state"); Q_ASSERT_X(manager, Q_FUNC_INFO, "invalid manager (nil)"); Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)"); QT_BT_MAC_AUTORELEASEPOOL; NSArray *const services = peripheral.services; - if (!services || !services.count) { // Actually, !services.count works in both cases, but ... + if (!services || !services.count) { // A peripheral without any services at all. - Q_ASSERT_X(delegate, Q_FUNC_INFO, - "invalid delegate (null)"); - delegate->serviceDiscoveryFinished(ObjCStrongReference<NSArray>()); + if (notifier) + emit notifier->serviceDiscoveryFinished(); } else { // 'reset' also calls retain on a parameter. servicesToVisitNext.reset(nil); @@ -347,7 +376,7 @@ using namespace QT_NAMESPACE; } } -- (bool)discoverServiceDetails:(const QBluetoothUuid &)serviceUuid +- (void)discoverServiceDetails:(const QBluetoothUuid &)serviceUuid { // This function does not change 'managerState', since it // can be called concurrently (not waiting for the previous @@ -362,7 +391,7 @@ using namespace QT_NAMESPACE; if (servicesToDiscoverDetails.contains(serviceUuid)) { qCWarning(QT_BT_OSX) << Q_FUNC_INFO <<"already discovering for " << serviceUuid; - return true; + return; } QT_BT_MAC_AUTORELEASEPOOL; @@ -370,13 +399,16 @@ using namespace QT_NAMESPACE; if (CBService *const service = [self serviceForUUID:serviceUuid]) { servicesToDiscoverDetails.append(serviceUuid); [peripheral discoverCharacteristics:nil forService:service]; - return true; + return; } qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "unknown service uuid " << serviceUuid; - return false; + if (notifier) { + emit notifier->CBManagerError(serviceUuid, + QLowEnergyService::UnknownError); + } } - (void)readCharacteristics:(CBService *)service @@ -389,11 +421,9 @@ using namespace QT_NAMESPACE; QT_BT_MAC_AUTORELEASEPOOL; - Q_ASSERT_X(managerState != CentralManagerUpdating, Q_FUNC_INFO, - "invalid state"); + Q_ASSERT_X(managerState != CentralManagerUpdating, Q_FUNC_INFO, "invalid state"); Q_ASSERT_X(manager, Q_FUNC_INFO, "invalid manager (nil)"); Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)"); - Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); if (!service.characteristics || !service.characteristics.count) return [self serviceDetailsDiscoveryFinished:service]; @@ -433,20 +463,16 @@ using namespace QT_NAMESPACE; - (void)readDescriptors:(CBService *)service { - Q_ASSERT_X(service, "-readDescriptors:", - "invalid service (nil)"); + Q_ASSERT_X(service, Q_FUNC_INFO, "invalid service (nil)"); Q_ASSERT_X(managerState != OSXBluetooth::CentralManagerUpdating, - "-readDescriptors:", - "invalid state"); - Q_ASSERT_X(peripheral, "-readDescriptors:", - "invalid peripheral (nil)"); + Q_FUNC_INFO, "invalid state"); + Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)"); QT_BT_MAC_AUTORELEASEPOOL; NSArray *const cs = service.characteristics; // We can never be here if we have no characteristics. - Q_ASSERT_X(cs && cs.count, "-readDescriptors:", - "invalid service"); + Q_ASSERT_X(cs && cs.count, Q_FUNC_INFO, "invalid service"); for (CBCharacteristic *c in cs) { if (c.descriptors && c.descriptors.count) return [peripheral readValueForDescriptor:[c.descriptors objectAtIndex:0]]; @@ -458,9 +484,7 @@ using namespace QT_NAMESPACE; - (void)serviceDetailsDiscoveryFinished:(CBService *)service { - // Q_ASSERT_X(service, Q_FUNC_INFO, "invalid service (nil)"); - Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); using namespace OSXBluetooth; @@ -476,7 +500,8 @@ using namespace QT_NAMESPACE; 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"; - delegate->error(serviceUuid, QLowEnergyService::OperationError); + if (notifier) + notifier->CBManagerError(serviceUuid, QLowEnergyService::OperationError); return; } @@ -539,8 +564,8 @@ using namespace QT_NAMESPACE; qtService->endHandle = lastValidHandle; - ObjCStrongReference<CBService> leService(service, true); - delegate->serviceDetailsDiscoveryFinished(qtService); + if (notifier) + emit notifier->serviceDetailsDiscoveryFinished(qtService); } - (void)performNextRequest @@ -683,28 +708,37 @@ using namespace QT_NAMESPACE; } } -- (bool)setNotifyValue:(const QByteArray &)value - forCharacteristic:(QT_PREPEND_NAMESPACE(QLowEnergyHandle))charHandle +- (void)setNotifyValue:(const QByteArray &)value + forCharacteristic:(QLowEnergyHandle)charHandle + onService:(const QBluetoothUuid &)serviceUuid { using namespace OSXBluetooth; Q_ASSERT_X(charHandle, Q_FUNC_INFO, "invalid characteristic handle (0)"); - Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); if (!charMap.contains(charHandle)) { qCWarning(QT_BT_OSX) << Q_FUNC_INFO - << "unknown characteristic handle " << charHandle; - return false; + << "unknown characteristic handle " + << charHandle; + if (notifier) { + emit notifier->CBManagerError(serviceUuid, + QLowEnergyService::DescriptorWriteError); + } + return; } // At the moment we call setNotifyValue _only_ from 'writeDescriptor'; - // from Qt's API POV it's a descriptor write oprtation and we must report + // from Qt's API POV it's a descriptor write operation and we must report // 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"; - return false; + if (notifier) { + emit notifier->CBManagerError(serviceUuid, + QLowEnergyService::DescriptorWriteError); + } + return; } LERequest request; @@ -714,11 +748,10 @@ using namespace QT_NAMESPACE; requests.enqueue(request); [self performNextRequest]; - - return true; } -- (bool)readCharacteristic:(QT_PREPEND_NAMESPACE(QLowEnergyHandle))charHandle +- (void)readCharacteristic:(QLowEnergyHandle)charHandle + onService:(const QBluetoothUuid &)serviceUuid { using namespace OSXBluetooth; @@ -728,7 +761,12 @@ using namespace QT_NAMESPACE; if (!charMap.contains(charHandle)) { qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "characteristic: " << charHandle << " not found"; - return false; + if (notifier) { + emit notifier->CBManagerError(serviceUuid, + QLowEnergyService::CharacteristicReadError); + + } + return; } LERequest request; @@ -737,12 +775,11 @@ using namespace QT_NAMESPACE; requests.enqueue(request); [self performNextRequest]; - - return true; } -- (bool)write:(const QT_PREPEND_NAMESPACE(QByteArray) &)value - charHandle:(QT_PREPEND_NAMESPACE(QLowEnergyHandle))charHandle +- (void)write:(const QByteArray &)value + charHandle:(QLowEnergyHandle)charHandle + onService:(const QBluetoothUuid &)serviceUuid withResponse:(bool)withResponse { using namespace OSXBluetooth; @@ -752,8 +789,13 @@ using namespace QT_NAMESPACE; QT_BT_MAC_AUTORELEASEPOOL; if (!charMap.contains(charHandle)) { - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "characteristic: " << charHandle << " not found"; - return false; + qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "characteristic: " + << charHandle << " not found"; + if (notifier) { + emit notifier->CBManagerError(serviceUuid, + QLowEnergyService::CharacteristicWriteError); + } + return; } LERequest request; @@ -764,11 +806,10 @@ using namespace QT_NAMESPACE; requests.enqueue(request); [self performNextRequest]; - - return true; } -- (bool)readDescriptor:(QT_PREPEND_NAMESPACE(QLowEnergyHandle))descHandle +- (void)readDescriptor:(QLowEnergyHandle)descHandle + onService:(const QBluetoothUuid &)serviceUuid { using namespace OSXBluetooth; @@ -777,7 +818,11 @@ using namespace QT_NAMESPACE; if (!descMap.contains(descHandle)) { qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "handle:" << descHandle << "not found"; - return false; + if (notifier) { + emit notifier->CBManagerError(serviceUuid, + QLowEnergyService::DescriptorReadError); + } + return; } LERequest request; @@ -786,11 +831,11 @@ using namespace QT_NAMESPACE; requests.enqueue(request); [self performNextRequest]; - - return true; } -- (bool)write:(const QByteArray &)value descHandle:(QLowEnergyHandle)descHandle +- (void)write:(const QByteArray &)value + descHandle:(QLowEnergyHandle)descHandle + onService:(const QBluetoothUuid &)serviceUuid { using namespace OSXBluetooth; @@ -799,7 +844,11 @@ using namespace QT_NAMESPACE; if (!descMap.contains(descHandle)) { qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "handle: " << descHandle << " not found"; - return false; + if (notifier) { + emit notifier->CBManagerError(serviceUuid, + QLowEnergyService::DescriptorWriteError); + } + return; } LERequest request; @@ -809,8 +858,6 @@ using namespace QT_NAMESPACE; requests.enqueue(request); [self performNextRequest]; - - return true; } // Aux. methods: @@ -831,7 +878,7 @@ using namespace QT_NAMESPACE; CBService *const s = [toVisit objectAtIndex:i]; if (equal_uuids(s.UUID, qtUuid)) return s; - if ([visitedNodes containsObject:s] && s.includedServices && s.includedServices.count) { + if (![visitedNodes containsObject:s] && s.includedServices && s.includedServices.count) { [visitedNodes addObject:s]; [toVisitNext addObjectsFromArray:s.includedServices]; } @@ -1028,8 +1075,6 @@ using namespace QT_NAMESPACE; - (void)centralManagerDidUpdateState:(CBCentralManager *)central { - Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); - using namespace OSXBluetooth; const CBCentralManagerState state = central.state; @@ -1044,47 +1089,42 @@ using namespace QT_NAMESPACE; return; } - if (disconnectPending) { - disconnectPending = false; - managerState = OSXBluetooth::CentralManagerIdle; - return [self disconnectFromDevice]; - } - // Let's check some states we do not like first: if (state == CBCentralManagerStateUnsupported || state == CBCentralManagerStateUnauthorized) { if (managerState == CentralManagerUpdating) { // We tried to connect just to realize, LE is not supported. Report this. managerState = CentralManagerIdle; - delegate->LEnotSupported(); + if (notifier) + emit notifier->LEnotSupported(); } else { // TODO: if we are here, LE _was_ supported and we first managed to update // and reset managerState from CentralManagerUpdating. managerState = CentralManagerIdle; - delegate->error(QLowEnergyController::InvalidBluetoothAdapterError); + if (notifier) + emit notifier->CBManagerError(QLowEnergyController::InvalidBluetoothAdapterError); } return; } if (state == CBCentralManagerStatePoweredOff) { + managerState = CentralManagerIdle; if (managerState == CentralManagerUpdating) { - // I've seen this instead of Unsopported on OS X. - managerState = CentralManagerIdle; - delegate->LEnotSupported(); + // I've seen this instead of Unsupported on OS X. + if (notifier) + emit notifier->LEnotSupported(); } else { - managerState = CentralManagerIdle; // TODO: we need a better error + // what will happen if later the state changes to PoweredOn??? - delegate->error(QLowEnergyController::InvalidBluetoothAdapterError); + if (notifier) + emit notifier->CBManagerError(QLowEnergyController::InvalidBluetoothAdapterError); } return; } if (state == CBCentralManagerStatePoweredOn) { - if (managerState == CentralManagerUpdating) { + if (managerState == CentralManagerUpdating && !disconnectPending) { managerState = CentralManagerIdle; - const QLowEnergyController::Error status = [self connectToDevice]; - if (status != QLowEnergyController::NoError)// An allocation problem? - delegate->error(status); + [self retrievePeripheralAndConnect]; } } else { // We actually handled all known states, but .. Core Bluetooth can change? @@ -1107,12 +1147,9 @@ using namespace QT_NAMESPACE; managerState = OSXBluetooth::CentralManagerIdle; if (!peripherals || peripherals.count != 1) { - Q_ASSERT_X(delegate, Q_FUNC_INFO, - "invalid delegate (null)"); - qCDebug(QT_BT_OSX) << Q_FUNC_INFO <<"unexpected number of peripherals (!= 1)"; - - delegate->error(QLowEnergyController::UnknownRemoteDeviceError); + if (notifier) + emit notifier->CBManagerError(QLowEnergyController::UnknownRemoteDeviceError); } else { peripheral = [static_cast<CBPeripheral *>([peripherals objectAtIndex:0]) retain]; [self connectToPeripheral]; @@ -1124,15 +1161,14 @@ using namespace QT_NAMESPACE; Q_UNUSED(central) Q_UNUSED(aPeripheral) - Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); - if (managerState != OSXBluetooth::CentralManagerConnecting) { // We called cancel but before disconnected, managed to connect? return; } managerState = OSXBluetooth::CentralManagerIdle; - delegate->connectSuccess(); + if (notifier) + emit notifier->connected(); } - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)aPeripheral @@ -1142,8 +1178,6 @@ using namespace QT_NAMESPACE; Q_UNUSED(aPeripheral) Q_UNUSED(error) - Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); - if (managerState != OSXBluetooth::CentralManagerConnecting) { // Canceled already. return; @@ -1151,7 +1185,8 @@ using namespace QT_NAMESPACE; managerState = OSXBluetooth::CentralManagerIdle; // TODO: better error mapping is required. - delegate->error(QLowEnergyController::UnknownRemoteDeviceError); + if (notifier) + notifier->CBManagerError(QLowEnergyController::UnknownRemoteDeviceError); } - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)aPeripheral @@ -1160,19 +1195,18 @@ using namespace QT_NAMESPACE; Q_UNUSED(central) Q_UNUSED(aPeripheral) - Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); - // Clear internal caches/data. [self reset]; if (error && managerState == OSXBluetooth::CentralManagerDisconnecting) { managerState = OSXBluetooth::CentralManagerIdle; qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed to disconnect"; - // TODO: instead of 'unknown' - .. ? - delegate->error(QLowEnergyController::UnknownRemoteDeviceError); + if (notifier) + emit notifier->CBManagerError(QLowEnergyController::UnknownRemoteDeviceError); } else { managerState = OSXBluetooth::CentralManagerIdle; - delegate->disconnected(); + if (notifier) + emit notifier->disconnected(); } } @@ -1190,10 +1224,10 @@ using namespace QT_NAMESPACE; managerState = OSXBluetooth::CentralManagerIdle; if (error) { - // NSLog, not qCDebug/Warning - to print the error. NSLog(@"%s failed with error %@", Q_FUNC_INFO, error); // TODO: better error mapping required. - delegate->error(QLowEnergyController::UnknownError); + if (notifier) + emit notifier->CBManagerError(QLowEnergyController::UnknownError); } else { [self discoverIncludedServices]; } @@ -1214,14 +1248,11 @@ using namespace QT_NAMESPACE; QT_BT_MAC_AUTORELEASEPOOL; - Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)"); - // TODO: asserts on other "pointers" ... managerState = CentralManagerIdle; if (error) { - // NSLog, not qCWarning/Critical - to log the actual NSError and service UUID. NSLog(@"%s: finished with error %@ for service %@", Q_FUNC_INFO, error, service.UUID); } else if (service.includedServices && service.includedServices.count) { @@ -1268,8 +1299,8 @@ using namespace QT_NAMESPACE; servicesToVisit.reset(nil); servicesToVisitNext.reset(nil); - const ObjCStrongReference<NSArray> services(peripheral.services, true); // true == retain. - delegate->serviceDiscoveryFinished(services); + if (notifier) + emit notifier->serviceDiscoveryFinished(); } - (void)peripheral:(CBPeripheral *)aPeripheral didDiscoverCharacteristicsForService:(CBService *)service @@ -1279,21 +1310,20 @@ using namespace QT_NAMESPACE; // discoveries active. Q_UNUSED(aPeripheral) - // TODO: check that this can never be called after cancelPeripheralConnection was executed. + if (!notifier) { + // Detached. + return; + } using namespace OSXBluetooth; - Q_ASSERT_X(managerState != CentralManagerUpdating, - Q_FUNC_INFO, "invalid state"); - Q_ASSERT_X(delegate, Q_FUNC_INFO, - "invalid delegate (null)"); + Q_ASSERT_X(managerState != CentralManagerUpdating, Q_FUNC_INFO, "invalid state"); if (error) { - // NSLog to show the actual NSError (can contain something interesting). 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). - delegate->error(qt_uuid(service.UUID), QLowEnergyController::UnknownError); + emit notifier->CBManagerError(qt_uuid(service.UUID), QLowEnergyController::UnknownError); } else { [self readCharacteristics:service]; } @@ -1305,11 +1335,15 @@ using namespace QT_NAMESPACE; { Q_UNUSED(aPeripheral) + if (!notifier) { + // Detached. + return; + } + using namespace OSXBluetooth; Q_ASSERT_X(managerState != CentralManagerUpdating, Q_FUNC_INFO, "invalid state"); Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)"); - Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); QT_BT_MAC_AUTORELEASEPOOL; // First, let's check if we're discovering a service details now. @@ -1319,13 +1353,12 @@ using namespace QT_NAMESPACE; const QLowEnergyHandle chHandle = charMap.key(characteristic); if (error) { - // Use NSLog, not qCDebug/qCWarning to log the actual error. NSLog(@"%s failed with error %@", Q_FUNC_INFO, error); if (!isDetailsDiscovery) { if (chHandle && chHandle == currentReadHandle) { currentReadHandle = 0; requestPending = false; - delegate->error(qtUuid, QLowEnergyService::CharacteristicReadError); + emit notifier->CBManagerError(qtUuid, QLowEnergyService::CharacteristicReadError); [self performNextRequest]; } return; @@ -1359,10 +1392,10 @@ using namespace QT_NAMESPACE; requestPending = false; currentReadHandle = 0; // - delegate->characteristicReadNotification(chHandle, qt_bytearray(characteristic.value)); + emit notifier->characteristicRead(chHandle, qt_bytearray(characteristic.value)); [self performNextRequest]; } else { - delegate->characteristicUpdateNotification(chHandle, qt_bytearray(characteristic.value)); + emit notifier->characteristicUpdated(chHandle, qt_bytearray(characteristic.value)); } } } @@ -1375,12 +1408,16 @@ using namespace QT_NAMESPACE; // have several discoveries active at the same time. Q_UNUSED(aPeripheral) + if (!notifier) { + // Detached, no need to continue ... + return; + } + QT_BT_MAC_AUTORELEASEPOOL; using namespace OSXBluetooth; if (error) { - // Log the error using NSLog: NSLog(@"%s failed with error %@", Q_FUNC_INFO, error); // We can continue though ... } @@ -1402,6 +1439,11 @@ using namespace QT_NAMESPACE; Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)"); + if (!notifier) { + // Detached ... + return; + } + QT_BT_MAC_AUTORELEASEPOOL; using namespace OSXBluetooth; @@ -1412,14 +1454,13 @@ using namespace QT_NAMESPACE; const QLowEnergyHandle dHandle = descMap.key(descriptor); if (error) { - // NSLog to log the actual error ... NSLog(@"%s failed with error %@", Q_FUNC_INFO, error); if (!isDetailsDiscovery) { if (dHandle && dHandle == currentReadHandle) { currentReadHandle = 0; requestPending = false; - delegate->error(qtUuid, QLowEnergyService::DescriptorReadError); + emit notifier->CBManagerError(qtUuid, QLowEnergyService::DescriptorReadError); [self performNextRequest]; } return; @@ -1459,7 +1500,7 @@ using namespace QT_NAMESPACE; if (dHandle == currentReadHandle) { currentReadHandle = 0; requestPending = false; - delegate->descriptorReadNotification(dHandle, qt_bytearray(static_cast<NSObject *>(descriptor.value))); + emit notifier->descriptorRead(dHandle, qt_bytearray(static_cast<NSObject *>(descriptor.value))); [self performNextRequest]; } } @@ -1472,6 +1513,11 @@ using namespace QT_NAMESPACE; Q_UNUSED(aPeripheral) Q_UNUSED(characteristic) + if (!notifier) { + // Detached. + return; + } + // From docs: // // "This method is invoked only when your app calls the writeValue:forCharacteristic:type: @@ -1485,8 +1531,6 @@ using namespace QT_NAMESPACE; requestPending = false; - Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); - // Error or not, but the cached value has to be deleted ... const QByteArray valueToReport(valuesToWrite.value(characteristic, QByteArray())); @@ -1496,15 +1540,12 @@ using namespace QT_NAMESPACE; } if (error) { - // Use NSLog to log the actual error: NSLog(@"%s failed with error %@", Q_FUNC_INFO, error); - delegate->error(qt_uuid(characteristic.service.UUID), - QLowEnergyService::CharacteristicWriteError); + emit notifier->CBManagerError(qt_uuid(characteristic.service.UUID), + QLowEnergyService::CharacteristicWriteError); } else { - // Keys are unique. const QLowEnergyHandle cHandle = charMap.key(characteristic); - Q_ASSERT_X(cHandle, Q_FUNC_INFO, "invalid handle, not found in the characteristics map"); - delegate->characteristicWriteNotification(cHandle, valueToReport); + emit notifier->characteristicWritten(cHandle, valueToReport); } [self performNextRequest]; @@ -1516,7 +1557,10 @@ using namespace QT_NAMESPACE; { Q_UNUSED(aPeripheral) - Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); + if (!notifier) { + // Detached already. + return; + } using namespace OSXBluetooth; @@ -1524,23 +1568,20 @@ using namespace QT_NAMESPACE; requestPending = false; - using namespace OSXBluetooth; - // 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"; if (error) { - // NSLog to log the actual NSError: NSLog(@"%s failed with error %@", Q_FUNC_INFO, error); - delegate->error(qt_uuid(descriptor.characteristic.service.UUID), - QLowEnergyService::DescriptorWriteError); + 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"); - delegate->descriptorWriteNotification(dHandle, valueToReport); + emit notifier->descriptorWritten(dHandle, valueToReport); } [self performNextRequest]; @@ -1552,40 +1593,42 @@ using namespace QT_NAMESPACE; { Q_UNUSED(aPeripheral) + if (!notifier) + return; + using namespace OSXBluetooth; QT_BT_MAC_AUTORELEASEPOOL; requestPending = false; - Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (nil)"); - const QBluetoothUuid qtUuid(QBluetoothUuid::ClientCharacteristicConfiguration); CBDescriptor *const descriptor = [self descriptor:qtUuid forCharacteristic:characteristic]; const QByteArray valueToReport(valuesToWrite.value(descriptor, QByteArray())); const int nRemoved = valuesToWrite.remove(descriptor); if (error) { - // NSLog to log the actual NSError: NSLog(@"%s failed with error %@", Q_FUNC_INFO, error); - delegate->error(qt_uuid(characteristic.service.UUID), - // In Qt's API it's a descriptor write actually. - QLowEnergyService::DescriptorWriteError); - } else { - if (nRemoved) { - const QLowEnergyHandle dHandle = descMap.key(descriptor); - delegate->descriptorWriteNotification(dHandle, valueToReport); - } else { - /* - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << ": notification value set to " - << int(characteristic.isNotifying) - << " but no client characteristic configuration descriptor found" - " or no previous writeDescriptor request found"; - */ - } + // In Qt's API it's a descriptor write actually. + emit notifier->CBManagerError(qt_uuid(characteristic.service.UUID), + QLowEnergyService::DescriptorWriteError); + } else if (nRemoved) { + const QLowEnergyHandle dHandle = descMap.key(descriptor); + emit notifier->descriptorWritten(dHandle, valueToReport); } [self performNextRequest]; } +- (void)detach +{ + if (notifier) { + notifier->disconnect(); + notifier->deleteLater(); + notifier = 0; + } + + [self disconnectFromDevice]; +} + @end diff --git a/src/bluetooth/osx/osxbtcentralmanager_p.h b/src/bluetooth/osx/osxbtcentralmanager_p.h index e8d7d234..5453822f 100644 --- a/src/bluetooth/osx/osxbtcentralmanager_p.h +++ b/src/bluetooth/osx/osxbtcentralmanager_p.h @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** @@ -34,6 +40,17 @@ #ifndef OSXBTCENTRALMANAGER_P_H #define OSXBTCENTRALMANAGER_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qlowenergycontroller.h" #include "qlowenergyservice.h" #include "qbluetoothuuid.h" @@ -58,41 +75,7 @@ class QLowEnergyServicePrivate; namespace OSXBluetooth { -class CentralManagerDelegate -{ -public: - typedef QT_MANGLE_NAMESPACE(OSXBTCentralManager) ObjCCentralManager; - typedef ObjCStrongReference<NSArray> LEServices; - typedef QSharedPointer<QLowEnergyServicePrivate> LEService; - typedef ObjCStrongReference<CBCharacteristic> LECharacteristic; - - virtual ~CentralManagerDelegate(); - - virtual void LEnotSupported() = 0; - virtual void connectSuccess() = 0; - virtual void serviceDiscoveryFinished(LEServices services) = 0; - virtual void serviceDetailsDiscoveryFinished(LEService service) = 0; - virtual void characteristicReadNotification(QLowEnergyHandle charHandle, - const QByteArray &value) = 0; - virtual void characteristicWriteNotification(QLowEnergyHandle charHandle, - const QByteArray &value) = 0; - virtual void characteristicUpdateNotification(QLowEnergyHandle charHandle, - const QByteArray &value) = 0; - virtual void descriptorReadNotification(QLowEnergyHandle descHandle, - const QByteArray &value) = 0; - virtual void descriptorWriteNotification(QLowEnergyHandle descHandle, - const QByteArray &value) = 0; - virtual void disconnected() = 0; - - // General errors. - virtual void error(QLowEnergyController::Error error) = 0; - // Service related errors. - virtual void error(const QBluetoothUuid &serviceUuid, - QLowEnergyController::Error error) = 0; - // Characteristics/descriptors related errors. - virtual void error(const QBluetoothUuid &serviceUuid, - QLowEnergyService::ServiceError error) = 0; -}; +class LECBManagerNotifier; enum CentralManagerState { @@ -115,8 +98,8 @@ typedef QHash<QLowEnergyHandle, CBService *> ServiceHash; typedef QHash<QLowEnergyHandle, CBCharacteristic *> CharHash; typedef QHash<QLowEnergyHandle, CBDescriptor *> DescHash; -// Descriptor/charactesirsti read/write requests -// - we have to serialize 'concurrent' write requests. +// Descriptor/charactesirstic read/write requests +// - we have to serialize 'concurrent' requests. struct LERequest { enum RequestType { CharRead, @@ -154,14 +137,14 @@ QT_END_NAMESPACE @interface QT_MANGLE_NAMESPACE(OSXBTCentralManager) : NSObject<CBCentralManagerDelegate, CBPeripheralDelegate> { +@private CBCentralManager *manager; QT_PREPEND_NAMESPACE(OSXBluetooth)::CentralManagerState managerState; bool disconnectPending; QT_PREPEND_NAMESPACE(QBluetoothUuid) deviceUuid; - CBPeripheral *peripheral; - QT_PREPEND_NAMESPACE(OSXBluetooth)::CentralManagerDelegate *delegate; + QT_PREPEND_NAMESPACE(OSXBluetooth)::LECBManagerNotifier *notifier; // Quite a verbose service discovery machinery // (a "graph traversal"). @@ -186,32 +169,43 @@ QT_END_NAMESPACE QT_PREPEND_NAMESPACE(QLowEnergyHandle) currentReadHandle; QT_PREPEND_NAMESPACE(OSXBluetooth)::ValueHash valuesToWrite; +@public + CBPeripheral *peripheral; } -- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(OSXBluetooth)::CentralManagerDelegate *)aDelegate; +- (id)initWith:(QT_PREPEND_NAMESPACE(OSXBluetooth)::LECBManagerNotifier *)notifier; - (void)dealloc; -- (QT_PREPEND_NAMESPACE(QLowEnergyController)::Error) - connectToDevice:(const QT_PREPEND_NAMESPACE(QBluetoothUuid) &)aDeviceUuid; +// IMPORTANT: _all_ these methods are to be executed on qt_LE_queue, +// when passing parameters - C++ objects _must_ be copied (see the controller's code). +- (void)connectToDevice:(const QT_PREPEND_NAMESPACE(QBluetoothUuid) &)aDeviceUuid; - (void)disconnectFromDevice; - (void)discoverServices; -- (bool)discoverServiceDetails:(const QT_PREPEND_NAMESPACE(QBluetoothUuid) &)serviceUuid; +- (void)discoverServiceDetails:(const QT_PREPEND_NAMESPACE(QBluetoothUuid) &)serviceUuid; -- (bool)setNotifyValue:(const QT_PREPEND_NAMESPACE(QByteArray) &)value - forCharacteristic:(QT_PREPEND_NAMESPACE(QLowEnergyHandle))charHandle; +- (void)setNotifyValue:(const QT_PREPEND_NAMESPACE(QByteArray) &)value + forCharacteristic:(QT_PREPEND_NAMESPACE(QLowEnergyHandle))charHandle + onService:(const QT_PREPEND_NAMESPACE(QBluetoothUuid) &)serviceUuid; -- (bool)readCharacteristic:(QT_PREPEND_NAMESPACE(QLowEnergyHandle))charHandle; +- (void)readCharacteristic:(QT_PREPEND_NAMESPACE(QLowEnergyHandle))charHandle + onService:(const QT_PREPEND_NAMESPACE(QBluetoothUuid) &)serviceUuid; -- (bool)write:(const QT_PREPEND_NAMESPACE(QByteArray) &)value +- (void)write:(const QT_PREPEND_NAMESPACE(QByteArray) &)value charHandle:(QT_PREPEND_NAMESPACE(QLowEnergyHandle))charHandle + onService:(const QT_PREPEND_NAMESPACE(QBluetoothUuid) &)serviceUuid withResponse:(bool)writeWithResponse; -- (bool)readDescriptor:(QT_PREPEND_NAMESPACE(QLowEnergyHandle))descHandle; +- (void)readDescriptor:(QT_PREPEND_NAMESPACE(QLowEnergyHandle))descHandle + onService:(const QT_PREPEND_NAMESPACE(QBluetoothUuid) &)serviceUuid; + +- (void)write:(const QT_PREPEND_NAMESPACE(QByteArray) &)value + descHandle:(QT_PREPEND_NAMESPACE(QLowEnergyHandle))descHandle + onService:(const QT_PREPEND_NAMESPACE(QBluetoothUuid) &)serviceUuid; + +- (void)detach; -- (bool)write:(const QT_PREPEND_NAMESPACE(QByteArray) &)value - descHandle:(QT_PREPEND_NAMESPACE(QLowEnergyHandle))descHandle; @end #endif diff --git a/src/bluetooth/osx/osxbtchanneldelegate.mm b/src/bluetooth/osx/osxbtchanneldelegate.mm index 2214168b..822e9d4e 100644 --- a/src/bluetooth/osx/osxbtchanneldelegate.mm +++ b/src/bluetooth/osx/osxbtchanneldelegate.mm @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/bluetooth/osx/osxbtchanneldelegate_p.h b/src/bluetooth/osx/osxbtchanneldelegate_p.h index edcf6950..1102e935 100644 --- a/src/bluetooth/osx/osxbtchanneldelegate_p.h +++ b/src/bluetooth/osx/osxbtchanneldelegate_p.h @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** @@ -34,6 +40,17 @@ #ifndef OSXBTCHANNELDELEGATE_P_H #define OSXBTCHANNELDELEGATE_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtCore/qglobal.h> #include <IOKit/IOReturn.h> diff --git a/src/bluetooth/osx/osxbtconnectionmonitor.mm b/src/bluetooth/osx/osxbtconnectionmonitor.mm index 8228d135..6cbe9b01 100644 --- a/src/bluetooth/osx/osxbtconnectionmonitor.mm +++ b/src/bluetooth/osx/osxbtconnectionmonitor.mm @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/bluetooth/osx/osxbtconnectionmonitor_p.h b/src/bluetooth/osx/osxbtconnectionmonitor_p.h index 4ad28885..7f95db87 100644 --- a/src/bluetooth/osx/osxbtconnectionmonitor_p.h +++ b/src/bluetooth/osx/osxbtconnectionmonitor_p.h @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** @@ -34,6 +40,17 @@ #ifndef OSXBTCONNECTIONMONITOR_P_H #define OSXBTCONNECTIONMONITOR_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qbluetoothaddress.h" #include <QtCore/qglobal.h> diff --git a/src/bluetooth/osx/osxbtdeviceinquiry.mm b/src/bluetooth/osx/osxbtdeviceinquiry.mm index 949b035a..d38110c7 100644 --- a/src/bluetooth/osx/osxbtdeviceinquiry.mm +++ b/src/bluetooth/osx/osxbtdeviceinquiry.mm @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/bluetooth/osx/osxbtdeviceinquiry_p.h b/src/bluetooth/osx/osxbtdeviceinquiry_p.h index 4397b45d..13227839 100644 --- a/src/bluetooth/osx/osxbtdeviceinquiry_p.h +++ b/src/bluetooth/osx/osxbtdeviceinquiry_p.h @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** @@ -34,6 +40,17 @@ #ifndef OSXBTDEVICEINQUIRY_P_H #define OSXBTDEVICEINQUIRY_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtCore/qglobal.h> // We have to import objc code (it does not have inclusion guards). diff --git a/src/bluetooth/osx/osxbtdevicepair.mm b/src/bluetooth/osx/osxbtdevicepair.mm index 41c20b8b..737a312f 100644 --- a/src/bluetooth/osx/osxbtdevicepair.mm +++ b/src/bluetooth/osx/osxbtdevicepair.mm @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/bluetooth/osx/osxbtdevicepair_p.h b/src/bluetooth/osx/osxbtdevicepair_p.h index a2aa2de0..35709734 100644 --- a/src/bluetooth/osx/osxbtdevicepair_p.h +++ b/src/bluetooth/osx/osxbtdevicepair_p.h @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** @@ -34,6 +40,17 @@ #ifndef OSXBTDEVICEPAIR_P_H #define OSXBTDEVICEPAIR_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qbluetoothaddress.h" #include "osxbtutility_p.h" diff --git a/src/bluetooth/osx/osxbtl2capchannel.mm b/src/bluetooth/osx/osxbtl2capchannel.mm index 93e15012..2d596654 100644 --- a/src/bluetooth/osx/osxbtl2capchannel.mm +++ b/src/bluetooth/osx/osxbtl2capchannel.mm @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/bluetooth/osx/osxbtl2capchannel_p.h b/src/bluetooth/osx/osxbtl2capchannel_p.h index 9736bd1d..7bc88102 100644 --- a/src/bluetooth/osx/osxbtl2capchannel_p.h +++ b/src/bluetooth/osx/osxbtl2capchannel_p.h @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** @@ -34,6 +40,17 @@ #ifndef OSXBTL2CAPCHANNEL_P_H #define OSXBTL2CAPCHANNEL_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtCore/qglobal.h> #include <Foundation/Foundation.h> diff --git a/src/bluetooth/osx/osxbtledeviceinquiry.mm b/src/bluetooth/osx/osxbtledeviceinquiry.mm index af304d8d..88370fa6 100644 --- a/src/bluetooth/osx/osxbtledeviceinquiry.mm +++ b/src/bluetooth/osx/osxbtledeviceinquiry.mm @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** @@ -46,10 +52,6 @@ QT_BEGIN_NAMESPACE namespace OSXBluetooth { -LEDeviceInquiryDelegate::~LEDeviceInquiryDelegate() -{ -} - #if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9, __IPHONE_6_0) QBluetoothUuid qt_uuid(NSUUID *nsUuid) @@ -107,32 +109,19 @@ using namespace QT_NAMESPACE; #endif -@interface QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry) (PrivateAPI) <CBCentralManagerDelegate, CBPeripheralDelegate> -// "Timeout" callback to stop a scan. +@interface QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry) (PrivateAPI) <CBCentralManagerDelegate> - (void)stopScan; +- (void)handlePoweredOff; @end @implementation QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry) -+ (int)inquiryLength -{ - // There is no default timeout, - // scan does not stop if not asked. - // Return in milliseconds - return 10 * 1000; -} - -- (id)initWithDelegate:(OSXBluetooth::LEDeviceInquiryDelegate *)aDelegate +- (id)init { - Q_ASSERT_X(aDelegate, Q_FUNC_INFO, "invalid delegate (null)"); - if (self = [super init]) { - delegate = aDelegate; - peripherals = [[NSMutableDictionary alloc] init]; - manager = nil; - pendingStart = false; - cancelled = false; - isActive = false; + uuids.reset([[NSMutableSet alloc] init]); + internalState = InquiryStarting; + state.store(int(internalState)); } return self; @@ -140,115 +129,137 @@ using namespace QT_NAMESPACE; - (void)dealloc { - [NSObject cancelPreviousPerformRequestsWithTarget:self]; - if (manager) { [manager setDelegate:nil]; - if (isActive) + if (internalState == InquiryActive) [manager stopScan]; - [manager release]; } - [peripherals release]; [super dealloc]; } - (void)stopScan { - // Scan's timeout. - Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); - Q_ASSERT_X(manager, Q_FUNC_INFO, "invalid central (nil)"); - Q_ASSERT_X(!pendingStart, Q_FUNC_INFO, "invalid state"); - Q_ASSERT_X(!cancelled, Q_FUNC_INFO, "invalid state"); - Q_ASSERT_X(isActive, Q_FUNC_INFO, "invalid state"); - - [manager setDelegate:nil]; - [manager stopScan]; - isActive = false; + // Scan's "timeout" - we consider LE device + // discovery finished. + using namespace OSXBluetooth; - delegate->LEdeviceInquiryFinished(); + if (internalState == InquiryActive) { + if (scanTimer.elapsed() >= qt_LE_deviceInquiryLength() * 1000) { + // We indeed stop now: + [manager stopScan]; + [manager setDelegate:nil]; + internalState = InquiryFinished; + state.store(int(internalState)); + } else { + dispatch_queue_t leQueue(qt_LE_queue()); + Q_ASSERT(leQueue); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, + int64_t(qt_LE_deviceInquiryLength() / 100. * NSEC_PER_SEC)), + leQueue, + ^{ + [self stopScan]; + }); + } + } } -- (bool)start +- (void)handlePoweredOff { - Q_ASSERT_X(![self isActive], Q_FUNC_INFO, "LE device scan is already active"); - Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); - - if (!peripherals) { - qCCritical(QT_BT_OSX) << Q_FUNC_INFO << "internal error"; - return false; - } + // This is interesting on iOS only, where + // the system shows an alert asking to enable + // Bluetooth in the 'Settings' app. If not done yet (after 30 + // seconds) - we consider it an error. + if (internalState == InquiryStarting) { + if (errorTimer.elapsed() >= 30000) { + [manager setDelegate:nil]; + internalState = ErrorPoweredOff; + state.store(int(internalState)); + } else { + dispatch_queue_t leQueue(OSXBluetooth::qt_LE_queue()); + Q_ASSERT(leQueue); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, + (int64_t)(30 / 100. * NSEC_PER_SEC)), + leQueue, + ^{ + [self handlePoweredOff]; + }); - cancelled = false; - [peripherals removeAllObjects]; - - if (manager) { - // We can never be here, if status was not updated yet. - [manager setDelegate:nil]; - [manager release]; + } } +} - startTime = QTime(); - pendingStart = true; - manager = [CBCentralManager alloc]; - manager = [manager initWithDelegate:self queue:nil]; - if (!manager) { - qCCritical(QT_BT_OSX) << Q_FUNC_INFO << "failed to create a central manager"; - return false; - } +- (void)start +{ + dispatch_queue_t leQueue(OSXBluetooth::qt_LE_queue()); - return true; + Q_ASSERT(leQueue); + manager.reset([[CBCentralManager alloc] initWithDelegate:self queue:leQueue]); } - (void)centralManagerDidUpdateState:(CBCentralManager *)central { - Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); + if (central != manager) + return; - if (cancelled) { - Q_ASSERT_X(!isActive, Q_FUNC_INFO, "isActive is true"); - pendingStart = false; - delegate->LEdeviceInquiryFinished(); + if (internalState != InquiryActive && internalState != InquiryStarting) return; - } - const CBCentralManagerState state = central.state; - if (state == CBCentralManagerStatePoweredOn) { - if (pendingStart) { - pendingStart = false; - isActive = true; -#ifndef Q_OS_OSX - const NSTimeInterval timeout([QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry) inquiryLength] / 1000); - Q_ASSERT_X(timeout > 0., Q_FUNC_INFO, "invalid scan timeout"); - [self performSelector:@selector(stopScan) withObject:nil afterDelay:timeout]; -#endif - startTime = QTime::currentTime(); + using namespace OSXBluetooth; + + dispatch_queue_t leQueue(qt_LE_queue()); + Q_ASSERT(leQueue); + + const CBCentralManagerState cbState(central.state); + if (cbState == CBCentralManagerStatePoweredOn) { + if (internalState == InquiryStarting) { + internalState = InquiryActive; + // Scan time is actually 10 seconds. Having a block with such delay can prevent + // 'self' from being deleted in time, which is not good. So we split this + // 10 s. timeout into smaller 'chunks'. + scanTimer.start(); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, + int64_t(qt_LE_deviceInquiryLength() / 100. * NSEC_PER_SEC)), + leQueue, + ^{ + [self stopScan]; + }); [manager scanForPeripheralsWithServices:nil options:nil]; } // Else we ignore. } else if (state == CBCentralManagerStateUnsupported || state == CBCentralManagerStateUnauthorized) { - if (pendingStart) { - pendingStart = false; - delegate->LEnotSupported(); - } else if (isActive) { - // It's not clear if this thing can happen at all. - // We had LE supported and now .. not anymore? - // Report as an error. - [NSObject cancelPreviousPerformRequestsWithTarget:self]; - isActive = false; + if (internalState == InquiryActive) { [manager stopScan]; - delegate->LEdeviceInquiryError(QBluetoothDeviceDiscoveryAgent::PoweredOffError); + // Not sure how this is possible at all, probably, can never happen. + internalState = ErrorPoweredOff; + } else { + internalState = ErrorLENotSupported; } - } else if (state == CBCentralManagerStatePoweredOff) { - if (pendingStart) { - pendingStart = false; - delegate->LEnotSupported(); - } else if (isActive) { - // We were able to start (isActive == true), so we had - // powered ON and now the adapter is OFF. - [NSObject cancelPreviousPerformRequestsWithTarget:self]; - isActive = false; + + [manager setDelegate:nil]; + } else if (cbState == CBCentralManagerStatePoweredOff) { + if (internalState == InquiryStarting) { +#ifndef Q_OS_OSX + // On iOS a user can see at this point an alert asking to enable + // Bluetooth in the "Settings" app. If a user does, + // we'll receive 'PoweredOn' state update later. + // No change in state. Wait for 30 seconds (we split it into 'chunks' not + // to retain 'self' for too long ) ... + errorTimer.start(); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, + (int64_t)(30 / 100. * NSEC_PER_SEC)), + leQueue, + ^{ + [self handlePoweredOff]; + }); + return; +#endif + internalState = ErrorPoweredOff; + } else { + internalState = ErrorPoweredOff; [manager stopScan]; - delegate->LEdeviceInquiryError(QBluetoothDeviceDiscoveryAgent::PoweredOffError); - } // Else we ignore. + } + + [manager setDelegate:nil]; } else { // The following two states we ignore (from Apple's docs): //" @@ -259,78 +270,102 @@ using namespace QT_NAMESPACE; // -CBCentralManagerStateResetting // The connection with the system service was momentarily // lost; an update is imminent. " - // - // TODO: check if "is imminent" means UpdateState will - // be called again with something more reasonable. + // Wait for this imminent update. } + + state.store(int(internalState)); } - (void)stop { - [NSObject cancelPreviousPerformRequestsWithTarget:self]; - - if (pendingStart || cancelled) { - // We have to wait for a status update. - cancelled = true; - return; - } - - if (isActive) { + if (internalState == InquiryActive) [manager stopScan]; - isActive = false; - delegate->LEdeviceInquiryFinished(); - } + + [manager setDelegate:nil]; + internalState = InquiryCancelled; + state.store(int(internalState)); } - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI { - Q_UNUSED(central) - Q_UNUSED(advertisementData) + Q_UNUSED(advertisementData); using namespace OSXBluetooth; - if (!isActive) + if (central != manager) + return; + + if (internalState != InquiryActive) return; - Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)"); + QBluetoothUuid deviceUuid; -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9, __IPHONE_6_0) - if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_9, QSysInfo::MV_IOS_6_0)) { +#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)) { if (!peripheral.identifier) { qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "peripheral without NSUUID"; return; } - if (![peripherals objectForKey:peripheral.identifier]) { - [peripherals setObject:peripheral forKey:peripheral.identifier]; - const QBluetoothUuid deviceUuid(OSXBluetooth::qt_uuid(peripheral.identifier)); - delegate->LEdeviceFound(peripheral, deviceUuid, advertisementData, RSSI); + if ([uuids containsObject:peripheral.identifier]) { + // We already know this peripheral ... + return; } - return; + + [uuids addObject:peripheral.identifier]; + deviceUuid = OSXBluetooth::qt_uuid(peripheral.identifier); } #endif - if (!peripheral.UUID) { - qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "peripheral without UUID"; - return; + // Either SDK or the target is below 10.9/7.0: + // The property UUID was finally removed in iOS 9, we have + // to avoid compilation errors ... + if (deviceUuid.isNull()) { + CFUUIDRef cfUUID = Q_NULLPTR; + + if ([peripheral respondsToSelector:@selector(UUID)]) { + // This will require a bridged cast if we switch to ARC ... + cfUUID = reinterpret_cast<CFUUIDRef>([peripheral performSelector:@selector(UUID)]); + } + + if (!cfUUID) { + qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "peripheral without CFUUID"; + return; + } + + StringStrongReference key(uuid_as_nsstring(cfUUID)); + if ([uuids containsObject:key.data()]) + return; // We've seen this peripheral before ... + [uuids addObject:key.data()]; + deviceUuid = OSXBluetooth::qt_uuid(cfUUID); } - StringStrongReference key(uuid_as_nsstring(peripheral.UUID)); - if (![peripherals objectForKey:key.data()]) { - [peripherals setObject:peripheral forKey:key.data()]; - const QBluetoothUuid deviceUuid(OSXBluetooth::qt_uuid(peripheral.UUID)); - delegate->LEdeviceFound(peripheral, deviceUuid, advertisementData, RSSI); + if (deviceUuid.isNull()) { + qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "no way to address peripheral, QBluetoothUuid is null"; + return; } + + QString name; + if (peripheral.name) + name = QString::fromNSString(peripheral.name); + + // TODO: fix 'classOfDevice' (0 for now). + QBluetoothDeviceInfo newDeviceInfo(deviceUuid, name, 0); + if (RSSI) + newDeviceInfo.setRssi([RSSI shortValue]); + // CoreBluetooth scans only for LE devices. + newDeviceInfo.setCoreConfigurations(QBluetoothDeviceInfo::LowEnergyCoreConfiguration); + devices.append(newDeviceInfo); } -- (bool)isActive +- (LEInquiryState) inquiryState { - return pendingStart || isActive; + return LEInquiryState(state.load()); } -- (const QTime&)startTime +- (const QList<QBluetoothDeviceInfo> &)discoveredDevices { - return startTime; + return devices; } @end diff --git a/src/bluetooth/osx/osxbtledeviceinquiry_p.h b/src/bluetooth/osx/osxbtledeviceinquiry_p.h index 7e6d0c8f..24bf181e 100644 --- a/src/bluetooth/osx/osxbtledeviceinquiry_p.h +++ b/src/bluetooth/osx/osxbtledeviceinquiry_p.h @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** @@ -34,77 +40,71 @@ #ifndef OSXBTLEDEVICEINQUIRY_P_H #define OSXBTLEDEVICEINQUIRY_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qbluetoothdevicediscoveryagent.h" +#include "qbluetoothdeviceinfo.h" +#include "osxbtutility_p.h" -#include <QtCore/qdatetime.h> +#include <QtCore/qelapsedtimer.h> #include <QtCore/qglobal.h> +#include <QtCore/qatomic.h> #include <QtCore/qlist.h> #include <Foundation/Foundation.h> -@class QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry); - @class CBCentralManager; @class CBPeripheral; QT_BEGIN_NAMESPACE -class QBluetoothDeviceInfo; class QBluetoothUuid; -namespace OSXBluetooth { +QT_END_NAMESPACE -class LEDeviceInquiryDelegate +enum LEInquiryState { -public: - typedef QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry) LEDeviceInquiryObjC; - - virtual ~LEDeviceInquiryDelegate(); - - // At the moment the only error we're reporting is PoweredOffError! - virtual void LEdeviceInquiryError(QBluetoothDeviceDiscoveryAgent::Error error) = 0; - - virtual void LEnotSupported() = 0; - virtual void LEdeviceFound(CBPeripheral *peripheral, const QBluetoothUuid &uuid, - NSDictionary *advertisementData, NSNumber *RSSI) = 0; - virtual void LEdeviceInquiryFinished() = 0; + InquiryStarting, + InquiryActive, + InquiryFinished, + InquiryCancelled, + ErrorPoweredOff, + ErrorLENotSupported }; -} +@interface QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry) : NSObject +{ + QT_PREPEND_NAMESPACE(OSXBluetooth)::ObjCScopedPointer<NSMutableSet> uuids; + QT_PREPEND_NAMESPACE(OSXBluetooth)::ObjCScopedPointer<CBCentralManager> manager; -QT_END_NAMESPACE + QList<QBluetoothDeviceInfo> devices; -// Bluetooth Low Energy scan for iOS and OS X. + LEInquiryState internalState; + QT_PREPEND_NAMESPACE(QAtomicInt) state; -@interface QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry) : NSObject -{// Protocols are adopted in the mm file. - QT_PREPEND_NAMESPACE(OSXBluetooth)::LEDeviceInquiryDelegate *delegate; - - // TODO: scoped pointers/shared pointers? - NSMutableDictionary *peripherals; // Found devices. - CBCentralManager *manager; - - // pending - waiting for a status update first. - bool pendingStart; - bool cancelled; - // scan actually started. - bool isActive; - QTime startTime; + // Timers to check if we can execute delayed callbacks: + QT_PREPEND_NAMESPACE(QElapsedTimer) errorTimer; + QT_PREPEND_NAMESPACE(QElapsedTimer) scanTimer; } -// Inquiry length in milliseconds. -+ (int)inquiryLength; - -- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(OSXBluetooth)::LEDeviceInquiryDelegate *)aDelegate; +- (id)init; - (void)dealloc; -// Actual scan can be delayed - we have to wait for a status update first. -- (bool)start; -// Stop can be delayed - if we're waiting for a status update. +// IMPORTANT: both 'start' and 'stop' are to be executed on the "Qt's LE queue". +- (void)start; - (void)stop; -- (bool)isActive; -- (const QTime &)startTime; +- (LEInquiryState)inquiryState; +- (const QList<QBluetoothDeviceInfo> &)discoveredDevices; @end diff --git a/src/bluetooth/osx/osxbtnotifier.cpp b/src/bluetooth/osx/osxbtnotifier.cpp new file mode 100644 index 00000000..0e0343cf --- /dev/null +++ b/src/bluetooth/osx/osxbtnotifier.cpp @@ -0,0 +1 @@ +#include "osxbtnotifier_p.h" diff --git a/src/bluetooth/osx/osxbtnotifier_p.h b/src/bluetooth/osx/osxbtnotifier_p.h new file mode 100644 index 00000000..3059e2d3 --- /dev/null +++ b/src/bluetooth/osx/osxbtnotifier_p.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtBluetooth module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef OSXBTNOTIFIER_P_H +#define OSXBTNOTIFIER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + + +#include "qlowenergycontroller.h" +#include "qbluetoothuuid.h" +#include "qbluetooth.h" + +#include <QtCore/qsharedpointer.h> +#include <QtCore/qbytearray.h> +#include <QtCore/qglobal.h> +#include <QtCore/qobject.h> + +QT_BEGIN_NAMESPACE + +class QLowEnergyServicePrivate; + +namespace OSXBluetooth +{ + +class LECBManagerNotifier : public QObject +{ + Q_OBJECT + +Q_SIGNALS: + void connected(); + void disconnected(); + + void serviceDiscoveryFinished(); + void serviceDetailsDiscoveryFinished(QSharedPointer<QLowEnergyServicePrivate> service); + void characteristicRead(QLowEnergyHandle charHandle, const QByteArray &value); + void characteristicWritten(QLowEnergyHandle charHandle, const QByteArray &value); + void characteristicUpdated(QLowEnergyHandle charHandle, const QByteArray &value); + void descriptorRead(QLowEnergyHandle descHandle, const QByteArray &value); + void descriptorWritten(QLowEnergyHandle descHandle, const QByteArray &value); + + void LEnotSupported(); + void CBManagerError(QLowEnergyController::Error error); + void CBManagerError(const QBluetoothUuid &serviceUuid, QLowEnergyController::Error error); + void CBManagerError(const QBluetoothUuid &serviceUuid, QLowEnergyService::ServiceError error); + +}; + +} + +QT_END_NAMESPACE + +#endif diff --git a/src/bluetooth/osx/osxbtobexsession.mm b/src/bluetooth/osx/osxbtobexsession.mm index f48da22d..4e4013f3 100644 --- a/src/bluetooth/osx/osxbtobexsession.mm +++ b/src/bluetooth/osx/osxbtobexsession.mm @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/bluetooth/osx/osxbtobexsession_p.h b/src/bluetooth/osx/osxbtobexsession_p.h index ac2699cf..dfb3d48a 100644 --- a/src/bluetooth/osx/osxbtobexsession_p.h +++ b/src/bluetooth/osx/osxbtobexsession_p.h @@ -1,36 +1,53 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtCore/qvariant.h> #include <QtCore/qglobal.h> diff --git a/src/bluetooth/osx/osxbtperipheralmanager.mm b/src/bluetooth/osx/osxbtperipheralmanager.mm new file mode 100644 index 00000000..4731fdd2 --- /dev/null +++ b/src/bluetooth/osx/osxbtperipheralmanager.mm @@ -0,0 +1,754 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtBluetooth module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + + +#include "qlowenergycharacteristicdata.h" +#include "qlowenergydescriptordata.h" +#include "osxbtperipheralmanager_p.h" +#include "qlowenergyservicedata.h" +#include "osxbtnotifier_p.h" +#include "qbluetooth.h" + +#include <QtCore/qdebug.h> +#include <QtCore/qlist.h> + +#include <algorithm> +#include <limits> +#include <set> + +namespace +{ + +CBCharacteristicProperties cb_properties(const QLowEnergyCharacteristicData &data) +{ + // Direct 'mapping' is ok. + return CBCharacteristicProperties(int(data.properties())); +} + +CBAttributePermissions cb_permissions(const QLowEnergyCharacteristicData &data) +{ + using QLEC = QLowEnergyCharacteristic; + + const auto props = data.properties(); + CBAttributePermissions cbFlags = {}; + + if ((props & QLEC::Write) || (props & QLEC::WriteNoResponse) + || (props & QLEC::WriteSigned)) { + cbFlags = CBAttributePermissions(cbFlags | CBAttributePermissionsWriteable); + } + + if (props & QLEC::Read) + cbFlags = CBAttributePermissions(cbFlags | CBAttributePermissionsReadable); + + if (data.writeConstraints() & QBluetooth::AttEncryptionRequired) + cbFlags = CBAttributePermissions(cbFlags | CBAttributePermissionsWriteEncryptionRequired); + + if (data.readConstraints() & QBluetooth::AttEncryptionRequired) + cbFlags = CBAttributePermissions(cbFlags | CBAttributePermissionsReadEncryptionRequired); + + return cbFlags; +} + +ObjCStrongReference<CBMutableCharacteristic> create_characteristic(const QLowEnergyCharacteristicData &data) +{ + const ObjCStrongReference<CBMutableCharacteristic> ch([[CBMutableCharacteristic alloc] initWithType:cb_uuid(data.uuid()) + properties:cb_properties(data) + value:nil + permissions:cb_permissions(data)], + false /*do not retain*/); + return ch; +} + +ObjCStrongReference<CBMutableDescriptor> create_descriptor(const QLowEnergyDescriptorData &data) +{ + // CoreBluetooth supports only: + /* + "That said, only two of these are currently supported when creating local, + mutable descriptors: the characteristic user description descriptor and + the characteristic format descriptor, represented by the CBUUID constants + CBUUIDCharacteristicUserDescriptionString and CBUUIDCharacteristicFormatString" + */ + + if (data.uuid() != QBluetoothUuid::CharacteristicUserDescription && + data.uuid() != QBluetoothUuid::CharacteristicPresentationFormat) { + qCWarning(QT_BT_OSX) << "unsupported descriptor" << data.uuid(); + return {}; + } + + QT_BT_MAC_AUTORELEASEPOOL + + // Descriptors are immutable with CoreBluetooth, that's why we + // have to provide a value here and not able to change it later. + ObjCStrongReference<NSObject> value; + if (data.uuid() == QBluetoothUuid::CharacteristicUserDescription) { + const QString asQString(QString::fromUtf8(data.value())); + value.reset(asQString.toNSString()); + } else { + const auto nsData = data_from_bytearray(data.value()); + value.reset(nsData.data()); + } + + const ObjCStrongReference<CBMutableDescriptor> d([[CBMutableDescriptor alloc] + initWithType:cb_uuid(data.uuid()) + value:value], false /*do not retain*/); + return d; +} + +quint32 qt_countGATTEntries(const QLowEnergyServiceData &data) +{ + const auto maxu32 = std::numeric_limits<quint32>::max(); + // + 1 for a service itself. + quint32 nEntries = 1 + quint32(data.includedServices().count()); + for (const auto &ch : data.characteristics()) { + if (maxu32 - 2 < nEntries) + return {}; + nEntries += 2; + if (maxu32 - ch.descriptors().count() < nEntries) + return {}; + nEntries += ch.descriptors().count(); + } + + return nEntries; +} + +} + +@interface QT_MANGLE_NAMESPACE(OSXBTPeripheralManager) (PrivateAPI) + +- (void)addConnectedCentral:(CBCentral *)central; +- (void)removeConnectedCentral:(CBCentral *)central; +- (CBService *)findIncludedService:(const QBluetoothUuid &)qtUUID; + +- (void)addIncludedServices:(const QLowEnergyServiceData &)data + to:(CBMutableService *)cbService + qtService:(QLowEnergyServicePrivate *)qtService; + +- (void)addCharacteristicsAndDescriptors:(const QLowEnergyServiceData &)data + to:(CBMutableService *)cbService + qtService:(QLowEnergyServicePrivate *)qtService; + +- (CBATTError)validateWriteRequest:(CBATTRequest *)request; + +@end + +@implementation QT_MANGLE_NAMESPACE(OSXBTPeripheralManager) + +- (id)initWith:(LECBManagerNotifier *)aNotifier +{ + if (self = [super init]) { + Q_ASSERT(aNotifier); + notifier = aNotifier; + state = PeripheralState::idle; + nextServiceToAdd = {}; + connectedCentrals.reset([[NSMutableSet alloc] init]); + } + + return self; +} + +- (void)dealloc +{ + [self detach]; + [super dealloc]; +} + +- (QSharedPointer<QLowEnergyServicePrivate>)addService:(const QLowEnergyServiceData &)data +{ + using QLES = QLowEnergyService; + + const auto nEntries = qt_countGATTEntries(data); + if (!nEntries || nEntries > std::numeric_limits<QLowEnergyHandle>::max() - lastHandle) { + qCCritical(QT_BT_OSX) << "addService: not enough handles"; + return {}; + } + + QT_BT_MAC_AUTORELEASEPOOL + + const BOOL primary = data.type() == QLowEnergyServiceData::ServiceTypePrimary; + const auto cbUUID = cb_uuid(data.uuid()); + + const ObjCStrongReference<CBMutableService> + newCBService([[CBMutableService alloc] initWithType:cbUUID primary:primary], + false /*do not retain*/); + + if (!newCBService) { + qCCritical(QT_BT_OSX) << "addService: failed to create CBMutableService"; + return {}; + } + + auto newQtService = QSharedPointer<QLowEnergyServicePrivate>::create(); + newQtService->state = QLowEnergyService::LocalService; + newQtService->uuid = data.uuid(); + newQtService->type = primary ? QLES::PrimaryService : QLES::IncludedService; + newQtService->startHandle = ++lastHandle; + // Controller will be set by ... controller :) + + [self addIncludedServices:data to:newCBService qtService:newQtService.data()]; + [self addCharacteristicsAndDescriptors:data to:newCBService qtService:newQtService.data()]; + + services.push_back(newCBService); + serviceIndex[data.uuid()] = newCBService; + + return newQtService; +} + +- (void) setParameters:(const QLowEnergyAdvertisingParameters &)parameters + data:(const QLowEnergyAdvertisingData &)data + scanResponse:(const QLowEnergyAdvertisingData &)scanResponse +{ + Q_UNUSED(parameters) + + // This is the last method we call on the controller's thread + // before starting advertising on the Qt's LE queue. + // From Apple's docs: + /* + - (void)startAdvertising:(NSDictionary *)advertisementData + + Advertises peripheral manager data. + + * advertisementData + + - An optional dictionary containing the data you want to advertise. + The possible keys of an advertisementData dictionary are detailed in CBCentralManagerDelegate + Protocol Reference. That said, only two of the keys are supported for peripheral manager objects: + CBAdvertisementDataLocalNameKey and CBAdvertisementDataServiceUUIDsKey. + */ + + QT_BT_MAC_AUTORELEASEPOOL + + advertisementData.reset([[NSMutableDictionary alloc] init]); + if (!advertisementData) { + qCWarning(QT_BT_OSX) << "setParameters: failed to allocate " + "NSMutableDictonary (advertisementData)"; + return; + } + + auto localName = scanResponse.localName(); + if (!localName.size()) + localName = data.localName(); + + if (localName.size()) { + [advertisementData setObject:localName.toNSString() + forKey:CBAdvertisementDataLocalNameKey]; + } + + if (!data.services().count() && !scanResponse.services().count()) + return; + + const ObjCScopedPointer<NSMutableArray> uuids([[NSMutableArray alloc] init]); + if (!uuids) { + qCWarning(QT_BT_OSX) << "setParameters: failed to allocate " + "NSMutableArray (services uuids)"; + return; + } + + + for (const auto &qtUUID : data.services()) { + const auto cbUUID = cb_uuid(qtUUID); + if (cbUUID) + [uuids addObject:cbUUID]; + } + + for (const auto &qtUUID : scanResponse.services()) { + const auto cbUUID = cb_uuid(qtUUID); + if (cbUUID) + [uuids addObject:cbUUID]; + } + + if ([uuids count]) { + [advertisementData setObject:uuids + forKey:CBAdvertisementDataServiceUUIDsKey]; + } +} + +- (void)startAdvertising +{ + state = PeripheralState::waitingForPowerOn; + if (manager) + [manager setDelegate:nil]; + manager.reset([[CBPeripheralManager alloc] initWithDelegate:self + queue:OSXBluetooth::qt_LE_queue()]); +} + +- (void)stopAdvertising +{ + [manager stopAdvertising]; + state = PeripheralState::idle; +} + +- (void)detach +{ + if (notifier) { + notifier->disconnect(); + notifier->deleteLater(); + notifier = nullptr; + } + + if (state == PeripheralState::advertising) { + [manager stopAdvertising]; + [manager setDelegate:nil]; + state = PeripheralState::idle; + } +} + +- (void)write:(const QByteArray &)value + charHandle:(QLowEnergyHandle)charHandle +{ + if (!notifier) + return; + + QT_BT_MAC_AUTORELEASEPOOL + + if (!charMap.contains(charHandle)) { + emit notifier->CBManagerError(QLowEnergyController::UnknownError); + return; + } + + const auto nsData = data_from_bytearray(value); + charValues[charHandle] = nsData; + updateQueue.push_back(UpdateRequest{charHandle, nsData}); + [self sendUpdateRequests]; +} + +- (void) addServicesToPeripheral +{ + Q_ASSERT(manager); + + if (nextServiceToAdd < services.size()) + [manager addService:services[nextServiceToAdd++]]; +} + +// CBPeripheralManagerDelegate: + +- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral +{ + if (peripheral != manager || !notifier) + return; + + if (peripheral.state == CBPeripheralManagerStatePoweredOn) { + // "Bluetooth is currently powered on and is available to use." + if (state == PeripheralState::waitingForPowerOn) { + [manager removeAllServices]; + nextServiceToAdd = {}; + state = PeripheralState::advertising; + [self addServicesToPeripheral]; + } + return; + } + + /* + "A state with a value lower than CBPeripheralManagerStatePoweredOn implies that + advertising has stopped and that any connected centrals have been disconnected." + */ + + [connectedCentrals removeAllObjects]; + + if (state == PeripheralState::advertising) { + state = PeripheralState::waitingForPowerOn; + } else if (state == PeripheralState::connected) { + state = PeripheralState::idle; + emit notifier->disconnected(); + } + + // The next four states are _below_ "powered off"; according to the docs: + /* + "In addition, the local database is cleared and all services must be + explicitly added again." + */ + + if (peripheral.state == CBPeripheralManagerStateUnauthorized || + peripheral.state == CBPeripheralManagerStateUnsupported) { + emit notifier->LEnotSupported(); + state = PeripheralState::idle; + } +} + +- (void)peripheralManager:(CBPeripheralManager *)peripheral + willRestoreState:(NSDictionary *)dict +{ + Q_UNUSED(peripheral) + Q_UNUSED(dict) + // NOOP atm. +} + +- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral + error:(NSError *)error +{ + if (peripheral != manager || !notifier) + return; + + if (error) { + NSLog(@"failed to start advertising, error: %@", error); + state = PeripheralState::idle; + emit notifier->CBManagerError(QLowEnergyController::AdvertisingError); + } +} + +- (void)peripheralManager:(CBPeripheralManager *)peripheral + didAddService:(CBService *)service error:(NSError *)error +{ + Q_UNUSED(service) + + if (peripheral != manager || !notifier) + return; + + if (error) { + NSLog(@"failed to add a service, error: %@", error); + emit notifier->CBManagerError(QLowEnergyController::AdvertisingError); + state = PeripheralState::idle; + return; + } + + if (nextServiceToAdd == services.size()) + [manager startAdvertising:[advertisementData count] ? advertisementData.data() : nil]; + else + [self addServicesToPeripheral]; +} + +- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central + didSubscribeToCharacteristic:(CBCharacteristic *)characteristic +{ + Q_UNUSED(characteristic) + + if (peripheral != manager || !notifier) + return; + + [self addConnectedCentral:central]; +} + +- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central + didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic +{ + Q_UNUSED(characteristic) + + if (peripheral != manager || !notifier) + return; + + [self removeConnectedCentral:central]; +} + +- (void)peripheralManager:(CBPeripheralManager *)peripheral + didReceiveReadRequest:(CBATTRequest *)request +{ + if (peripheral != manager || !notifier) + return; + + QT_BT_MAC_AUTORELEASEPOOL + + const auto handle = charMap.key(request.characteristic); + if (!handle || !charValues.contains(handle)) { + qCWarning(QT_BT_OSX) << "invalid read request, unknown characteristic"; + [manager respondToRequest:request withResult:CBATTErrorInvalidHandle]; + return; + } + + const auto &value = charValues[handle]; + if (request.offset > [value length]) { + qCWarning(QT_BT_OSX) << "invalid offset in a read request"; + [manager respondToRequest:request withResult:CBATTErrorInvalidOffset]; + return; + } + + [self addConnectedCentral:request.central]; + + NSData *dataToSend = nil; + if (!request.offset) { + dataToSend = value; + } else { + dataToSend = [value subdataWithRange: + NSMakeRange(request.offset, [value length] - request.offset)]; + } + + request.value = dataToSend; + [manager respondToRequest:request withResult:CBATTErrorSuccess]; +} + +- (void)peripheralManager:(CBPeripheralManager *)peripheral + didReceiveWriteRequests:(NSArray *)requests +{ + QT_BT_MAC_AUTORELEASEPOOL + + if (peripheral != manager || !notifier) { + // Detached already. + return; + } + + // We first test if all requests are valid + // since CoreBluetooth requires "all or none" + // and respond only _once_ to the first one. + for (CBATTRequest *request in requests) { + const auto status = [self validateWriteRequest:request]; + if (status != CBATTErrorSuccess) { + [manager respondToRequest:[requests objectAtIndex:0] + withResult:status]; + return; + } + } + + std::set<QLowEnergyHandle> updated; + + for (CBATTRequest *request in requests) { + // Transition to 'connected' if needed. + [self addConnectedCentral:request.central]; + + const auto charHandle = charMap.key(request.characteristic); + updated.insert(charHandle); + NSMutableData *const data = static_cast<NSMutableData *>(charValues[charHandle]); + [data replaceBytesInRange:NSMakeRange(request.offset, request.value.length) + withBytes:data.bytes]; + } + + for (const auto handle : updated) + emit notifier->characteristicUpdated(handle, qt_bytearray(charValues[handle])); + + if (requests.count) { + [manager respondToRequest:[requests objectAtIndex:0] + withResult:CBATTErrorSuccess]; + } +} + +- (void)peripheralManagerIsReadyToUpdateSubscribers:(CBPeripheralManager *)peripheral +{ + if (peripheral != manager || !notifier) { + // Detached. + return; + } + + [self sendUpdateRequests]; +} + +- (void)sendUpdateRequests +{ + QT_BT_MAC_AUTORELEASEPOOL + + while (updateQueue.size()) { + const auto &request = updateQueue.front(); + Q_ASSERT(charMap.contains(request.charHandle)); + const BOOL res = [manager updateValue:request.value + forCharacteristic:static_cast<CBMutableCharacteristic *>(charMap[request.charHandle]) + onSubscribedCentrals:nil]; + if (!res) { + // Have to wait for the 'ManagerIsReadyToUpdate'. + break; + } + + updateQueue.pop_front(); + } +} + +// Private API: + +- (void)addConnectedCentral:(CBCentral *)central +{ + if (!central) + return; + + if (!notifier) { + // We were detached. + return; + } + + QT_BT_MAC_AUTORELEASEPOOL + + if (state == PeripheralState::advertising) { + state = PeripheralState::connected; + [manager stopAdvertising]; + emit notifier->connected(); + } + + if (![connectedCentrals containsObject:central.identifier]) + [connectedCentrals addObject:central.identifier]; +} + +- (void)removeConnectedCentral:(CBCentral *)central +{ + if (!notifier) { + // Detached. + return; + } + + QT_BT_MAC_AUTORELEASEPOOL + + if ([connectedCentrals containsObject:central.identifier]) + [connectedCentrals removeObject:central.identifier]; + + if (state == PeripheralState::connected && ![connectedCentrals count]) { + state = PeripheralState::idle; + emit notifier->disconnected(); + } +} + +- (CBService *)findIncludedService:(const QBluetoothUuid &)qtUUID +{ + const auto it = serviceIndex.find(qtUUID); + if (it == serviceIndex.end()) + return nil; + + return it->second; +} + +- (void)addIncludedServices:(const QLowEnergyServiceData &)data + to:(CBMutableService *)cbService + qtService:(QLowEnergyServicePrivate *)qtService +{ + Q_ASSERT(cbService); + Q_ASSERT(qtService); + + QT_BT_MAC_AUTORELEASEPOOL + + ObjCScopedPointer<NSMutableArray> included([[NSMutableArray alloc] init]); + if (!included) { + qCWarning(QT_BT_OSX) << "addIncludedSerivces: failed " + "to allocate NSMutableArray"; + return; + } + + for (auto includedService : data.includedServices()) { + if (CBService *cbs = [self findIncludedService:includedService->serviceUuid()]) { + [included addObject:cbs]; + qtService->includedServices << includedService->serviceUuid(); + ++lastHandle; + } else { + qCWarning(QT_BT_OSX) << "can not use" << includedService->serviceUuid() + << "as included, it has to be added first"; + } + } + + if ([included count]) + cbService.includedServices = included; +} + +- (void)addCharacteristicsAndDescriptors:(const QLowEnergyServiceData &)data + to:(CBMutableService *)cbService + qtService:(QLowEnergyServicePrivate *)qtService +{ + Q_ASSERT(cbService); + Q_ASSERT(qtService); + + QT_BT_MAC_AUTORELEASEPOOL + + ObjCScopedPointer<NSMutableArray> newCBChars([[NSMutableArray alloc] init]); + if (!newCBChars) { + qCWarning(QT_BT_OSX) << "addCharacteristicsAndDescritptors: " + "failed to allocate NSMutableArray " + "(characteristics)"; + return; + } + + for (const auto &ch : data.characteristics()) { + const auto cbChar(create_characteristic(ch)); + if (!cbChar) { + qCWarning(QT_BT_OSX) << "addCharacteristicsAndDescritptors: " + "failed to allocate a characteristic"; + continue; + } + + const auto nsData(data_from_bytearray(ch.value())); + if (!nsData) { + qCWarning(QT_BT_OSX) << "addCharacteristicsAndDescritptors: " + "addService: failed to allocate NSData (char value)"; + continue; + } + + [newCBChars addObject:cbChar]; + + const auto declHandle = ++lastHandle; + // CB part: + charMap[declHandle] = cbChar; + charValues[declHandle] = data_from_bytearray(ch.value()); + // QT part: + QLowEnergyServicePrivate::CharData charData; + charData.valueHandle = ++lastHandle; + charData.uuid = ch.uuid(); + charData.properties = ch.properties(); + charData.value = ch.value(); + + const ObjCScopedPointer<NSMutableArray> newCBDescs([[NSMutableArray alloc] init]); + if (!newCBDescs) { + qCWarning(QT_BT_OSX) << "addCharacteristicsAndDescritptors: " + "failed to allocate NSMutableArray " + "(descriptors)"; + continue; + } + + for (const auto &desc : ch.descriptors()) { + // CB part: + const auto cbDesc(create_descriptor(desc)); + const auto descHandle = ++lastHandle; + if (cbDesc) { + // See comments in create_descriptor on + // why cbDesc can be nil. + [newCBDescs addObject:cbDesc]; + } + // QT part: + QLowEnergyServicePrivate::DescData descData; + descData.uuid = desc.uuid(); + descData.value = desc.value(); + charData.descriptorList.insert(descHandle, descData); + } + + if ([newCBDescs count]) + cbChar.data().descriptors = newCBDescs.data(); // retains + + qtService->characteristicList.insert(declHandle, charData); + } + + if ([newCBChars count]) + cbService.characteristics = newCBChars.data(); +} + +- (CBATTError)validateWriteRequest:(CBATTRequest *)request +{ + Q_ASSERT(request); + + QT_BT_MAC_AUTORELEASEPOOL + + const auto handle = charMap.key(request.characteristic); + if (!handle || !charValues.contains(handle)) + return CBATTErrorInvalidHandle; + + NSMutableData *data = static_cast<NSMutableData *>(charValues[handle]); + if (request.offset > data.length || request.value.length > data.length - request.offset) + return CBATTErrorInvalidOffset; + + return CBATTErrorSuccess; +} + +@end diff --git a/src/bluetooth/osx/osxbtperipheralmanager_p.h b/src/bluetooth/osx/osxbtperipheralmanager_p.h new file mode 100644 index 00000000..481a9fab --- /dev/null +++ b/src/bluetooth/osx/osxbtperipheralmanager_p.h @@ -0,0 +1,176 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtBluetooth module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef OSXBTPERIPHERALMANAGER_P_H +#define OSXBTPERIPHERALMANAGER_P_H + + +#include "osxbtutility_p.h" + +#include "qlowenergyadvertisingparameters.h" +#include "qlowenergyserviceprivate_p.h" +#include "qbluetoothuuid.h" +#include "qbluetooth.h" + +#include <QtCore/qsharedpointer.h> +#include <QtCore/qbytearray.h> +#include <QtCore/qsysinfo.h> +#include <QtCore/qglobal.h> +#include <QtCore/qmap.h> + +#include <vector> +#include <deque> +#include <map> + +// Foundation.h must be included before corebluetoothwrapper_p.h - +// a workaround for a broken 10.9 SDK. +#include <Foundation/Foundation.h> + +#include "corebluetoothwrapper_p.h" + +QT_BEGIN_NAMESPACE + +class QLowEnergyServiceData; + +namespace OSXBluetooth +{ + +class LECBManagerNotifier; + +} + +QT_END_NAMESPACE + + +// Exposing names in a header is ugly, but constant QT_PREPEND_NAMESPACE is even worse ... +// After all, this header is to be included only in its own and controller's *.mm files. + +QT_USE_NAMESPACE + +using namespace OSXBluetooth; + + +template<class Type> +using GenericLEMap = QMap<QLowEnergyHandle, Type>; + +enum class PeripheralState +{ + idle, + waitingForPowerOn, + advertising, + connected +}; + +struct UpdateRequest +{ + UpdateRequest() = default; + UpdateRequest(QLowEnergyHandle handle, const ObjCStrongReference<NSData> &val) + : charHandle(handle), + value(val) + { + } + + QLowEnergyHandle charHandle = {}; + ObjCStrongReference<NSData> value; +}; + +@interface QT_MANGLE_NAMESPACE(OSXBTPeripheralManager) : NSObject<CBPeripheralManagerDelegate> +{ + ObjCScopedPointer<CBPeripheralManager> manager; + LECBManagerNotifier *notifier; + + QLowEnergyHandle lastHandle; + // Services in this vector are placed in such order: + // the one that has included services, must + // follow its included services to avoid exceptions from CBPeripheralManager. + std::vector<ObjCStrongReference<CBMutableService>> services; + decltype(services.size()) nextServiceToAdd; + + // Lookup map for included services: + std::map<QBluetoothUuid, CBService *> serviceIndex; + ObjCScopedPointer<NSMutableDictionary> advertisementData; + + GenericLEMap<CBCharacteristic *> charMap; + GenericLEMap<ObjCStrongReference<NSData>> charValues; + + std::deque<UpdateRequest> updateQueue; + + ObjCScopedPointer<NSMutableSet> connectedCentrals; + + PeripheralState state; +} + +- (id)initWith:(LECBManagerNotifier *)notifier; +- (void)dealloc; + +- (QSharedPointer<QLowEnergyServicePrivate>)addService:(const QLowEnergyServiceData &)data; +- (void) setParameters:(const QLowEnergyAdvertisingParameters &)parameters + data:(const QLowEnergyAdvertisingData &)data + scanResponse:(const QLowEnergyAdvertisingData &)scanResponse; + +// To be executed on the Qt's special BTLE dispatch queue. +- (void)startAdvertising; +- (void)stopAdvertising; +- (void)detach; + +- (void)write:(const QByteArray &)value + charHandle:(QLowEnergyHandle)charHandle; + + +// CBPeripheralManagerDelegate's callbacks (BTLE queue). +- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral; +- (void)peripheralManager:(CBPeripheralManager *)peripheral + willRestoreState:(NSDictionary *)dict; +- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral + error:(NSError *)error; +- (void)peripheralManager:(CBPeripheralManager *)peripheral + didAddService:(CBService *)service error:(NSError *)error; +- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central + didSubscribeToCharacteristic:(CBCharacteristic *)characteristic; +- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central + didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic; +- (void)peripheralManager:(CBPeripheralManager *)peripheral + didReceiveReadRequest:(CBATTRequest *)request; +- (void)peripheralManager:(CBPeripheralManager *)peripheral + didReceiveWriteRequests:(NSArray *)requests; +- (void)peripheralManagerIsReadyToUpdateSubscribers:(CBPeripheralManager *)peripheral; + +@end + +#endif diff --git a/src/bluetooth/osx/osxbtrfcommchannel.mm b/src/bluetooth/osx/osxbtrfcommchannel.mm index a91f62dc..b2ee8b64 100644 --- a/src/bluetooth/osx/osxbtrfcommchannel.mm +++ b/src/bluetooth/osx/osxbtrfcommchannel.mm @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/bluetooth/osx/osxbtrfcommchannel_p.h b/src/bluetooth/osx/osxbtrfcommchannel_p.h index 80758ab0..89d765d8 100644 --- a/src/bluetooth/osx/osxbtrfcommchannel_p.h +++ b/src/bluetooth/osx/osxbtrfcommchannel_p.h @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** @@ -34,6 +40,17 @@ #ifndef OSXBTRFCOMMCHANNEL_P_H #define OSXBTRFCOMMCHANNEL_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtCore/qglobal.h> #include <Foundation/Foundation.h> diff --git a/src/bluetooth/osx/osxbtsdpinquiry.mm b/src/bluetooth/osx/osxbtsdpinquiry.mm index 004d9e61..28dc2342 100644 --- a/src/bluetooth/osx/osxbtsdpinquiry.mm +++ b/src/bluetooth/osx/osxbtsdpinquiry.mm @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/bluetooth/osx/osxbtsdpinquiry_p.h b/src/bluetooth/osx/osxbtsdpinquiry_p.h index 20b6c66c..ea75e649 100644 --- a/src/bluetooth/osx/osxbtsdpinquiry_p.h +++ b/src/bluetooth/osx/osxbtsdpinquiry_p.h @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** @@ -34,6 +40,17 @@ #ifndef OSXBTSDPINQUIRY_H #define OSXBTSDPINQUIRY_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "qbluetoothaddress.h" #include "qbluetoothuuid.h" diff --git a/src/bluetooth/osx/osxbtservicerecord.mm b/src/bluetooth/osx/osxbtservicerecord.mm index cd80ee63..11dcac88 100644 --- a/src/bluetooth/osx/osxbtservicerecord.mm +++ b/src/bluetooth/osx/osxbtservicerecord.mm @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/bluetooth/osx/osxbtservicerecord_p.h b/src/bluetooth/osx/osxbtservicerecord_p.h index fa84147b..6b2db8a8 100644 --- a/src/bluetooth/osx/osxbtservicerecord_p.h +++ b/src/bluetooth/osx/osxbtservicerecord_p.h @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** @@ -34,6 +40,17 @@ #ifndef OSXBTSERVICERECORD_P_H #define OSXBTSERVICERECORD_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include "osxbtutility_p.h" #include <QtCore/qglobal.h> diff --git a/src/bluetooth/osx/osxbtsocketlistener.mm b/src/bluetooth/osx/osxbtsocketlistener.mm index e3124dd1..5b004f94 100644 --- a/src/bluetooth/osx/osxbtsocketlistener.mm +++ b/src/bluetooth/osx/osxbtsocketlistener.mm @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/bluetooth/osx/osxbtsocketlistener_p.h b/src/bluetooth/osx/osxbtsocketlistener_p.h index e4fd8882..4a362763 100644 --- a/src/bluetooth/osx/osxbtsocketlistener_p.h +++ b/src/bluetooth/osx/osxbtsocketlistener_p.h @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** @@ -34,6 +40,17 @@ #ifndef OSXBTSOCKETLISTENER_P_H #define OSXBTSOCKETLISTENER_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtCore/qglobal.h> #include <Foundation/Foundation.h> diff --git a/src/bluetooth/osx/osxbtutility.mm b/src/bluetooth/osx/osxbtutility.mm index a5d3d936..f579b2a4 100644 --- a/src/bluetooth/osx/osxbtutility.mm +++ b/src/bluetooth/osx/osxbtutility.mm @@ -1,36 +1,43 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include "qlowenergycharacteristicdata.h" #include "qbluetoothaddress.h" #include "osxbtutility_p.h" #include "qbluetoothuuid.h" @@ -305,6 +312,47 @@ ObjCStrongReference<NSData> data_from_bytearray(const QByteArray & qtData) return result; } +// A small RAII class for a dispatch queue. +class SerialDispatchQueue +{ +public: + explicit SerialDispatchQueue(const char *label) + { + Q_ASSERT(label); + + queue = dispatch_queue_create(label, DISPATCH_QUEUE_SERIAL); + if (!queue) { + qCCritical(QT_BT_OSX) << "failed to create dispatch queue with label" + << label; + } + } + ~SerialDispatchQueue() + { + if (queue) + dispatch_release(queue); + } + + dispatch_queue_t data() const + { + return queue; + } +private: + dispatch_queue_t queue; + + Q_DISABLE_COPY(SerialDispatchQueue) +}; + +dispatch_queue_t qt_LE_queue() +{ + static const SerialDispatchQueue leQueue("qt-bluetooth-LE-queue"); + return leQueue.data(); +} + +unsigned qt_LE_deviceInquiryLength() +{ + return 10; +} + } QT_END_NAMESPACE diff --git a/src/bluetooth/osx/osxbtutility_p.h b/src/bluetooth/osx/osxbtutility_p.h index 18d8732a..5e616b74 100644 --- a/src/bluetooth/osx/osxbtutility_p.h +++ b/src/bluetooth/osx/osxbtutility_p.h @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** @@ -34,6 +40,17 @@ #ifndef OSXBTUTILITY_P_H #define OSXBTUTILITY_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtCore/qloggingcategory.h> #include <QtCore/qscopedpointer.h> #include <QtCore/qsysinfo.h> @@ -47,6 +64,8 @@ QT_BEGIN_NAMESPACE +class QLowEnergyCharacteristicData; +class QBluetoothAddress; class QBluetoothUuid; namespace OSXBluetooth { @@ -83,8 +102,7 @@ public: } }; -typedef ObjCScopedPointer<NSAutoreleasePool> AutoreleasePool; -#define QT_BT_MAC_AUTORELEASEPOOL const OSXBluetooth::AutoreleasePool pool([[NSAutoreleasePool alloc] init]) +#define QT_BT_MAC_AUTORELEASEPOOL const QMacAutoReleasePool pool; template<class T> class ObjCStrongReference { @@ -266,7 +284,7 @@ QString qt_address(NSString *address); #ifndef QT_IOS_BLUETOOTH -class QBluetoothAddress qt_address(const BluetoothDeviceAddress *address); +QBluetoothAddress qt_address(const BluetoothDeviceAddress *address); BluetoothDeviceAddress iobluetooth_address(const QBluetoothAddress &address); ObjCStrongReference<IOBluetoothSDPUUID> iobluetooth_uuid(const QBluetoothUuid &uuid); @@ -295,6 +313,10 @@ inline QSysInfo::MacVersion qt_OS_limit(QSysInfo::MacVersion osxVersion, QSysInf #endif } +dispatch_queue_t qt_LE_queue(); +// LE scan, in seconds. +unsigned qt_LE_deviceInquiryLength(); + } // namespace OSXBluetooth // Logging category for both OS X and iOS. diff --git a/src/bluetooth/osx/uistrings.cpp b/src/bluetooth/osx/uistrings.cpp index 5684533e..7260417f 100644 --- a/src/bluetooth/osx/uistrings.cpp +++ b/src/bluetooth/osx/uistrings.cpp @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/bluetooth/osx/uistrings_p.h b/src/bluetooth/osx/uistrings_p.h index 303bad89..999a8c6d 100644 --- a/src/bluetooth/osx/uistrings_p.h +++ b/src/bluetooth/osx/uistrings_p.h @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** @@ -34,6 +40,17 @@ #ifndef TRANSLATIONS_H #define TRANSLATIONS_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QtCore/QCoreApplication> #include <QtCore/QString> |