summaryrefslogtreecommitdiffstats
path: root/src/bluetooth/osx/osxbtcentralmanager.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/bluetooth/osx/osxbtcentralmanager.mm')
-rw-r--r--src/bluetooth/osx/osxbtcentralmanager.mm609
1 files changed, 296 insertions, 313 deletions
diff --git a/src/bluetooth/osx/osxbtcentralmanager.mm b/src/bluetooth/osx/osxbtcentralmanager.mm
index 614e4ae5..f7218ca6 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,23 +40,22 @@
#include "qlowenergyserviceprivate_p.h"
#include "qlowenergycharacteristic.h"
#include "osxbtcentralmanager_p.h"
-
+#include "osxbtnotifier_p.h"
#include <QtCore/qloggingcategory.h>
-#include <QtCore/qsysinfo.h>
#include <QtCore/qdebug.h>
#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 +86,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 +115,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,46 +149,52 @@ 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) << "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,
Q_FUNC_INFO, "invalid state");
if ([self isConnected]) {
- qCDebug(QT_BT_OSX) << Q_FUNC_INFO << "already connected";
- delegate->connectSuccess();
- return QLowEnergyController::NoError;
+ qCDebug(QT_BT_OSX) << "already connected";
+ 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;
@@ -197,56 +202,37 @@ using namespace QT_NAMESPACE;
// Retrieve a peripheral first ...
ObjCScopedPointer<NSMutableArray> uuids([[NSMutableArray alloc] init]);
if (!uuids) {
- qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed to allocate identifiers";
- return QLowEnergyController::ConnectionError;
- }
-
-#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9, __IPHONE_7_0)
- if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_9, QSysInfo::MV_IOS_7_0)) {
- const quint128 qtUuidData(deviceUuid.toUInt128());
- // STATIC_ASSERT on sizes would be handy!
- uuid_t uuidData = {};
- std::copy(qtUuidData.data, qtUuidData.data + 16, uuidData);
- const ObjCScopedPointer<NSUUID> nsUuid([[NSUUID alloc] initWithUUIDBytes:uuidData]);
- if (!nsUuid) {
- qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed to allocate NSUUID identifier";
- return QLowEnergyController::ConnectionError;
- }
+ qCWarning(QT_BT_OSX) << "failed to allocate identifiers";
+ 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;
- }
-
- peripheral = [static_cast<CBPeripheral *>([peripherals objectAtIndex:0]) retain];
- [self connectToPeripheral];
-
- return QLowEnergyController::NoError;
- }
-#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";
- return QLowEnergyController::UnknownRemoteDeviceError;
+ const quint128 qtUuidData(deviceUuid.toUInt128());
+ uuid_t uuidData = {};
+ std::copy(qtUuidData.data, qtUuidData.data + 16, uuidData);
+ const ObjCScopedPointer<NSUUID> nsUuid([[NSUUID alloc] initWithUUIDBytes:uuidData]);
+ if (!nsUuid) {
+ qCWarning(QT_BT_OSX) << "failed to allocate NSUUID identifier";
+ if (notifier)
+ emit notifier->CBManagerError(QLowEnergyController::ConnectionError);
+ return;
}
- OSXBluetooth::CFStrongReference<CFUUIDRef> cfUuid(OSXBluetooth::cf_uuid(deviceUuid));
- if (!cfUuid) {
- qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed to create CFUUID object";
- return QLowEnergyController::ConnectionError;
+ [uuids addObject:nsUuid];
+ // With the latest CoreBluetooth, we can synchronously retrive peripherals:
+ QT_BT_MAC_AUTORELEASEPOOL;
+ NSArray *const peripherals = [manager retrievePeripheralsWithIdentifiers:uuids];
+ if (!peripherals || peripherals.count != 1) {
+ qCWarning(QT_BT_OSX) << "failed to retrive a peripheral";
+ if (notifier)
+ emit notifier->CBManagerError(QLowEnergyController::UnknownRemoteDeviceError);
+ return;
}
- // TODO: With ARC this cast will be illegal:
- [uuids addObject:(id)cfUuid.data()];
- // Unfortunately, with old Core Bluetooth this call is asynchronous ...
- managerState = OSXBluetooth::CentralManagerConnecting;
- [manager performSelector:@selector(retrievePeripherals:) withObject:uuids.data()];
- return QLowEnergyController::NoError;
+ peripheral = [static_cast<CBPeripheral *>([peripherals objectAtIndex:0]) retain];
+ [self connectToPeripheral];
}
- (void)connectToPeripheral
@@ -258,10 +244,11 @@ 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();
+ qCDebug(QT_BT_OSX) << "already connected";
+ if (notifier)
+ emit notifier->connected();
} else {
- qCDebug(QT_BT_OSX) << Q_FUNC_INFO << "trying to connect";
+ qCDebug(QT_BT_OSX) << "trying to connect";
managerState = OSXBluetooth::CentralManagerConnecting;
[manager connectPeripheral:peripheral options:nil];
}
@@ -272,18 +259,7 @@ using namespace QT_NAMESPACE;
if (!peripheral)
return false;
-#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9, __IPHONE_7_0)
- using OSXBluetooth::qt_OS_limit;
-
- if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_9, QSysInfo::MV_IOS_7_0))
- return peripheral.state == CBPeripheralStateConnected;
-#endif
- // Either SDK or the target is below 10.9/7.0 ...
- if (![peripheral respondsToSelector:@selector(isConnected)])
- return false;
-
- // Ugly cast to deal with id being a pointer ...
- return reinterpret_cast<quintptr>([peripheral performSelector:@selector(isConnected)]);
+ return peripheral.state == CBPeripheralStateConnected;
}
- (void)disconnectFromDevice
@@ -291,10 +267,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
@@ -303,8 +286,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];
}
}
@@ -321,7 +305,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];
@@ -331,19 +314,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);
@@ -358,7 +339,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
@@ -371,9 +352,9 @@ using namespace QT_NAMESPACE;
Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)");
if (servicesToDiscoverDetails.contains(serviceUuid)) {
- qCWarning(QT_BT_OSX) << Q_FUNC_INFO <<"already discovering for "
+ qCWarning(QT_BT_OSX) << "already discovering for"
<< serviceUuid;
- return true;
+ return;
}
QT_BT_MAC_AUTORELEASEPOOL;
@@ -381,13 +362,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 "
+ qCWarning(QT_BT_OSX) << "unknown service uuid"
<< serviceUuid;
- return false;
+ if (notifier) {
+ emit notifier->CBManagerError(serviceUuid,
+ QLowEnergyService::UnknownError);
+ }
}
- (void)readCharacteristics:(CBService *)service
@@ -400,11 +384,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];
@@ -444,20 +426,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]];
@@ -469,9 +447,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;
@@ -486,8 +462,9 @@ using namespace QT_NAMESPACE;
const QLowEnergyHandle maxHandle = std::numeric_limits<QLowEnergyHandle>::max();
if (nHandles >= maxHandle || lastValidHandle > maxHandle - nHandles) {
// Well, that's unlikely :) But we must be sure.
- qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "can not allocate more handles";
- delegate->error(serviceUuid, QLowEnergyService::OperationError);
+ qCWarning(QT_BT_OSX) << "can not allocate more handles";
+ if (notifier)
+ notifier->CBManagerError(serviceUuid, QLowEnergyService::OperationError);
return;
}
@@ -550,8 +527,8 @@ using namespace QT_NAMESPACE;
qtService->endHandle = lastValidHandle;
- ObjCStrongReference<CBService> leService(service, true);
- delegate->serviceDetailsDiscoveryFinished(qtService);
+ if (notifier)
+ emit notifier->serviceDetailsDiscoveryFinished(qtService);
}
- (void)performNextRequest
@@ -589,7 +566,7 @@ using namespace QT_NAMESPACE;
const LERequest request(requests.dequeue());
if (request.type == LERequest::CharRead) {
if (!charMap.contains(request.handle)) {
- qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "characteristic with handle"
+ qCWarning(QT_BT_OSX) << "characteristic with handle"
<< request.handle << "not found";
return [self performNextRequest];
}
@@ -599,7 +576,7 @@ using namespace QT_NAMESPACE;
[peripheral readValueForCharacteristic:charMap[request.handle]];
} else {
if (!descMap.contains(request.handle)) {
- qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "descriptor with handle"
+ qCWarning(QT_BT_OSX) << "descriptor with handle"
<< request.handle << "not found";
return [self performNextRequest];
}
@@ -626,8 +603,8 @@ using namespace QT_NAMESPACE;
if (request.type == LERequest::DescWrite) {
if (!descMap.contains(request.handle)) {
- qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "handle: "
- << request.handle << " not found";
+ qCWarning(QT_BT_OSX) << "handle:" << request.handle
+ << "not found";
return [self performNextRequest];
}
@@ -635,8 +612,7 @@ using namespace QT_NAMESPACE;
ObjCStrongReference<NSData> data(data_from_bytearray(request.value));
if (!data) {
// Even if qtData.size() == 0, we still need NSData object.
- qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed "
- "to allocate an NSData object";
+ qCWarning(QT_BT_OSX) << "failed to allocate an NSData object";
return [self performNextRequest];
}
@@ -647,8 +623,8 @@ using namespace QT_NAMESPACE;
return [peripheral writeValue:data.data() forDescriptor:descriptor];
} else {
if (!charMap.contains(request.handle)) {
- qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "characteristic with "
- "handle: " << request.handle << " not found";
+ qCWarning(QT_BT_OSX) << "characteristic with handle:"
+ << request.handle << "not found";
return [self performNextRequest];
}
@@ -673,7 +649,7 @@ using namespace QT_NAMESPACE;
ObjCStrongReference<NSData> data(data_from_bytearray(request.value));
if (!data) {
// Even if qtData.size() == 0, we still need NSData object.
- qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "failed to allocate NSData object";
+ qCWarning(QT_BT_OSX) << "failed to allocate NSData object";
return [self performNextRequest];
}
@@ -694,28 +670,35 @@ 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;
+ qCWarning(QT_BT_OSX) << "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;
+ qCWarning(QT_BT_OSX) << "no client characteristic configuration found";
+ if (notifier) {
+ emit notifier->CBManagerError(serviceUuid,
+ QLowEnergyService::DescriptorWriteError);
+ }
+ return;
}
LERequest request;
@@ -725,11 +708,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;
@@ -738,8 +720,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) << "characteristic:" << charHandle << "not found";
+ if (notifier) {
+ emit notifier->CBManagerError(serviceUuid,
+ QLowEnergyService::CharacteristicReadError);
+
+ }
+ return;
}
LERequest request;
@@ -748,12 +735,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;
@@ -763,8 +749,12 @@ 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) << "characteristic:" << charHandle << "not found";
+ if (notifier) {
+ emit notifier->CBManagerError(serviceUuid,
+ QLowEnergyService::CharacteristicWriteError);
+ }
+ return;
}
LERequest request;
@@ -775,20 +765,22 @@ 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;
Q_ASSERT_X(descHandle, Q_FUNC_INFO, "invalid descriptor handle (0)");
if (!descMap.contains(descHandle)) {
- qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "handle:"
- << descHandle << "not found";
- return false;
+ qCWarning(QT_BT_OSX) << "handle:" << descHandle << "not found";
+ if (notifier) {
+ emit notifier->CBManagerError(serviceUuid,
+ QLowEnergyService::DescriptorReadError);
+ }
+ return;
}
LERequest request;
@@ -797,20 +789,23 @@ 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;
Q_ASSERT_X(descHandle, Q_FUNC_INFO, "invalid descriptor handle (0)");
if (!descMap.contains(descHandle)) {
- qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "handle: "
- << descHandle << " not found";
- return false;
+ qCWarning(QT_BT_OSX) << "handle:" << descHandle << "not found";
+ if (notifier) {
+ emit notifier->CBManagerError(serviceUuid,
+ QLowEnergyService::DescriptorWriteError);
+ }
+ return;
}
LERequest request;
@@ -820,8 +815,6 @@ using namespace QT_NAMESPACE;
requests.enqueue(request);
[self performNextRequest];
-
- return true;
}
// Aux. methods:
@@ -842,7 +835,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];
}
@@ -993,27 +986,25 @@ using namespace QT_NAMESPACE;
if ([obj isKindOfClass:[CBCharacteristic class]]) {
CBCharacteristic *const ch = static_cast<CBCharacteristic *>(obj);
if (!charMap.key(ch)) {
- qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "unexpected "
- "characteristic, no handle found";
+ qCWarning(QT_BT_OSX) << "unexpected characteristic, no handle found";
return false;
}
} else if ([obj isKindOfClass:[CBDescriptor class]]) {
CBDescriptor *const d = static_cast<CBDescriptor *>(obj);
if (!descMap.key(d)) {
- qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "unexpected "
- "descriptor, no handle found";
+ qCWarning(QT_BT_OSX) << "unexpected descriptor, no handle found";
return false;
}
} else {
- qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "invalid object, "
- "characteristic or descriptor required";
+ qCWarning(QT_BT_OSX) << "invalid object, characteristic "
+ "or descriptor required";
return false;
}
if (valuesToWrite.contains(obj)) {
// It can be a result of some previous errors - for example,
// we never got a callback from a previous write.
- qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "already has a cached value for this "
+ qCWarning(QT_BT_OSX) << "already has a cached value for this "
"object, the value will be replaced";
}
@@ -1039,14 +1030,21 @@ using namespace QT_NAMESPACE;
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
- Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid delegate (null)");
-
using namespace OSXBluetooth;
+#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_10_0)
+ const CBManagerState state = central.state;
+#else
const CBCentralManagerState state = central.state;
+#endif
+#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_10_0)
+ if (state == CBManagerStateUnknown
+ || state == CBManagerStateResetting) {
+#else
if (state == CBCentralManagerStateUnknown
|| state == CBCentralManagerStateResetting) {
+#endif
// We still have to wait, docs say:
// "The current state of the central manager is unknown;
// an update is imminent." or
@@ -1055,47 +1053,54 @@ 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 QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_10_0)
+ if (state == CBManagerStateUnsupported || state == CBManagerStateUnauthorized) {
+#else
if (state == CBCentralManagerStateUnsupported || state == CBCentralManagerStateUnauthorized) {
+#endif
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 QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_10_0)
+ if (state == CBManagerStatePoweredOff) {
+#else
if (state == CBCentralManagerStatePoweredOff) {
+#endif
+ 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 QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_10_0)
+ if (state == CBManagerStatePoweredOn) {
+#else
if (state == CBCentralManagerStatePoweredOn) {
- if (managerState == CentralManagerUpdating) {
+#endif
+ 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?
@@ -1103,47 +1108,19 @@ using namespace QT_NAMESPACE;
}
}
-- (void)centralManager:(CBCentralManager *)central didRetrievePeripherals:(NSArray *)peripherals
-{
- Q_UNUSED(central)
-
- // This method is required for iOS before 7.0 and OS X below 10.9.
- Q_ASSERT_X(manager, Q_FUNC_INFO, "invalid central manager (nil)");
-
- if (managerState != OSXBluetooth::CentralManagerConnecting) {
- // Canceled by calling -disconnectFromDevice method.
- return;
- }
-
- managerState = OSXBluetooth::CentralManagerIdle;
-
- if (!peripherals || peripherals.count != 1) {
- 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);
- } else {
- peripheral = [static_cast<CBPeripheral *>([peripherals objectAtIndex:0]) retain];
- [self connectToPeripheral];
- }
-}
-
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)aPeripheral
{
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
@@ -1153,8 +1130,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;
@@ -1162,7 +1137,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
@@ -1171,19 +1147,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);
+ qCWarning(QT_BT_OSX) << "failed to disconnect";
+ if (notifier)
+ emit notifier->CBManagerError(QLowEnergyController::UnknownRemoteDeviceError);
} else {
managerState = OSXBluetooth::CentralManagerIdle;
- delegate->disconnected();
+ if (notifier)
+ emit notifier->disconnected();
}
}
@@ -1201,10 +1176,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];
}
@@ -1225,14 +1200,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) {
@@ -1279,8 +1251,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
@@ -1290,21 +1262,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];
}
@@ -1316,11 +1287,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.
@@ -1330,13 +1305,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,7 +1333,7 @@ using namespace QT_NAMESPACE;
// updated values ...
// TODO: this must be properly tested.
if (!chHandle) {
- qCCritical(QT_BT_OSX) << Q_FUNC_INFO << "unexpected update notification, "
+ qCCritical(QT_BT_OSX) << "unexpected update notification, "
"no characteristic handle found";
return;
}
@@ -1370,10 +1344,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));
}
}
}
@@ -1386,12 +1360,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 ...
}
@@ -1413,6 +1391,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;
@@ -1423,14 +1406,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;
@@ -1462,7 +1444,7 @@ using namespace QT_NAMESPACE;
}
} else {
if (!dHandle) {
- qCCritical(QT_BT_OSX) << Q_FUNC_INFO << "unexpected value update notification, "
+ qCCritical(QT_BT_OSX) << "unexpected value update notification, "
"no descriptor handle found";
return;
}
@@ -1470,7 +1452,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];
}
}
@@ -1483,6 +1465,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:
@@ -1496,26 +1483,21 @@ 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()));
if (!valuesToWrite.remove(characteristic)) {
- qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "no updated value found"
- " for characteristic";
+ qCWarning(QT_BT_OSX) << "no updated value found "
+ "for characteristic";
}
if (error) {
- // 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];
@@ -1527,7 +1509,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;
@@ -1535,23 +1520,19 @@ 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";
+ qCWarning(QT_BT_OSX) << "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);
+ Q_ASSERT_X(dHandle, Q_FUNC_INFO, "descriptor not found in the descriptors map");
+ emit notifier->descriptorWritten(dHandle, valueToReport);
}
[self performNextRequest];
@@ -1563,40 +1544,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