diff options
author | Kari Oikarinen <kari.oikarinen@qt.io> | 2019-01-08 08:18:01 +0200 |
---|---|---|
committer | Kari Oikarinen <kari.oikarinen@qt.io> | 2019-01-08 08:18:01 +0200 |
commit | 1b4bf7b4e82f5f320da9f78ef4c23a3330c41737 (patch) | |
tree | 46649777e4cf63fd5ef4c30bd08c3c62fa1db94c | |
parent | 04084404ba35a6add235e110944b93c31eda9010 (diff) | |
parent | 99b308ab5488e5cfa77f5078eebc2fa9387217b8 (diff) |
Merge 5.12 into 5.12.1
Change-Id: Ia4746e04af7784d9a33a6c1aa7e0f08fd7dafe1a
29 files changed, 314 insertions, 232 deletions
diff --git a/.qmake.conf b/.qmake.conf index 097d8b94..1c14aab6 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -1,3 +1,3 @@ load(qt_build_config) -MODULE_VERSION = 5.12.0 +MODULE_VERSION = 5.12.1 diff --git a/src/bluetooth/bluez/bluez5_helper.cpp b/src/bluetooth/bluez/bluez5_helper.cpp index bacdfe3c..7ce67690 100644 --- a/src/bluetooth/bluez/bluez5_helper.cpp +++ b/src/bluetooth/bluez/bluez5_helper.cpp @@ -195,6 +195,13 @@ bool mandatoryHciIoctlsAvailable() QVersionNumber bluetoothdVersion() { if (bluezDaemonVersion()->isNull()) { + // Register DBus specific meta types (copied from isBluez5()) + // Not all code paths run through isBluez5() but still need the + // registration. + qDBusRegisterMetaType<InterfaceList>(); + qDBusRegisterMetaType<ManagedObjectList>(); + qDBusRegisterMetaType<ManufacturerDataList>(); + qCDebug(QT_BT_BLUEZ) << "Detecting bluetoothd version"; //Order of matching // 1. Pick whatever the user decides via BLUETOOTH_FORCE_DBUS_LE_VERSION diff --git a/src/bluetooth/osx/osxbtcentralmanager.mm b/src/bluetooth/osx/osxbtcentralmanager.mm index 9254bd98..cadabbaf 100644 --- a/src/bluetooth/osx/osxbtcentralmanager.mm +++ b/src/bluetooth/osx/osxbtcentralmanager.mm @@ -46,6 +46,7 @@ #include <QtCore/qdebug.h> #include <algorithm> +#include <vector> #include <limits> Q_DECLARE_METATYPE(QLowEnergyHandle) @@ -92,13 +93,24 @@ ObjCStrongReference<NSError> qt_timeoutNSError(OperationTimeout type) return ObjCStrongReference<NSError>(nsError, false /*do not retain, done already*/); } +auto qt_find_watchdog(const std::vector<GCDTimer> &watchdogs, id object, OperationTimeout type) +{ + return std::find_if(watchdogs.begin(), watchdogs.end(), [object, type](const GCDTimer &other){ + return [other objectUnderWatch] == object && [other timeoutType] == type;}); +} + } // namespace OSXBluetooth QT_END_NAMESPACE +QT_USE_NAMESPACE @interface QT_MANGLE_NAMESPACE(OSXBTCentralManager) (PrivateAPI) +- (void)watchAfter:(id)object timeout:(OSXBluetooth::OperationTimeout)type; +- (bool)objectIsUnderWatch:(id)object operation:(OSXBluetooth::OperationTimeout)type; +- (void)stopWatchingAfter:(id)object operation:(OSXBluetooth::OperationTimeout)type; +- (void)stopWatchers; - (void)retrievePeripheralAndConnect; - (void)connectToPeripheral; - (void)discoverIncludedServices; @@ -125,6 +137,45 @@ QT_END_NAMESPACE @end @implementation QT_MANGLE_NAMESPACE(OSXBTCentralManager) +{ +@private + CBCentralManager *manager; + OSXBluetooth::CentralManagerState managerState; + bool disconnectPending; + + QBluetoothUuid deviceUuid; + + OSXBluetooth::LECBManagerNotifier *notifier; + + // Quite a verbose service discovery machinery + // (a "graph traversal"). + OSXBluetooth::ObjCStrongReference<NSMutableArray> servicesToVisit; + // The service we're discovering now (included services discovery): + NSUInteger currentService; + // Included services, we'll iterate through at the end of 'servicesToVisit': + OSXBluetooth::ObjCStrongReference<NSMutableArray> servicesToVisitNext; + // We'd like to avoid loops in a services' topology: + OSXBluetooth::ObjCStrongReference<NSMutableSet> visitedServices; + + QList<QBluetoothUuid> servicesToDiscoverDetails; + + OSXBluetooth::ServiceHash serviceMap; + OSXBluetooth::CharHash charMap; + OSXBluetooth::DescHash descMap; + + QLowEnergyHandle lastValidHandle; + + bool requestPending; + OSXBluetooth::RequestQueue requests; + QLowEnergyHandle currentReadHandle; + + OSXBluetooth::ValueHash valuesToWrite; + + qint64 timeoutMS; + std::vector<OSXBluetooth::GCDTimer> timeoutWatchdogs; + + CBPeripheral *peripheral; +} - (id)initWith:(OSXBluetooth::LECBManagerNotifier *)aNotifier { @@ -140,7 +191,6 @@ QT_END_NAMESPACE lastValidHandle = 0; requestPending = false; currentReadHandle = 0; - timeoutType = OperationTimeout::none; if (Q_UNLIKELY(!qEnvironmentVariableIsEmpty("BLUETOOTH_GATT_TIMEOUT"))) { bool ok = false; @@ -176,62 +226,91 @@ QT_END_NAMESPACE if (notifier) notifier->deleteLater(); + [self stopWatchers]; [super dealloc]; } +- (CBPeripheral *)peripheral +{ + return peripheral; +} + - (void)watchAfter:(id)object timeout:(OSXBluetooth::OperationTimeout)type { using namespace OSXBluetooth; - objectUnderWatch = object; - timeoutType = type; - [timeoutWatchdog cancelTimer]; - timeoutWatchdog.reset([[GCDTimerObjC alloc] initWithDelegate:self]); - [timeoutWatchdog startWithTimeout:timeoutMS step:200]; + GCDTimer newWatcher([[GCDTimerObjC alloc] initWithDelegate:self], false /*do not retain*/); + [newWatcher watchAfter:object withTimeoutType:type]; + timeoutWatchdogs.push_back(newWatcher); + [newWatcher startWithTimeout:timeoutMS step:200]; +} + +- (bool)objectIsUnderWatch:(id)object operation:(OSXBluetooth::OperationTimeout)type +{ + return OSXBluetooth::qt_find_watchdog(timeoutWatchdogs, object, type) != timeoutWatchdogs.end(); } -- (void)stopWatchdog +- (void)stopWatchingAfter:(id)object operation:(OSXBluetooth::OperationTimeout)type { - [timeoutWatchdog cancelTimer]; - objectUnderWatch = nil; - timeoutType = OSXBluetooth::OperationTimeout::none; + auto pos = OSXBluetooth::qt_find_watchdog(timeoutWatchdogs, object, type); + if (pos != timeoutWatchdogs.end()) { + [*pos cancelTimer]; + timeoutWatchdogs.erase(pos); + } } -- (void)timeout +- (void)stopWatchers { + for (auto &watchdog : timeoutWatchdogs) + [watchdog cancelTimer]; + timeoutWatchdogs.clear(); +} + +- (void)timeout:(id)sender +{ + Q_UNUSED(sender) + using namespace OSXBluetooth; - Q_ASSERT(objectUnderWatch); - NSLog(@"Timeout caused by: %@", objectUnderWatch); - const ObjCStrongReference<NSError> nsError(qt_timeoutNSError(timeoutType)); - switch (timeoutType) { + GCDTimerObjC *watcher = static_cast<GCDTimerObjC *>(sender); + id cbObject = [watcher objectUnderWatch]; + const OperationTimeout type = [watcher timeoutType]; + + Q_ASSERT([self objectIsUnderWatch:cbObject operation:type]); + + NSLog(@"Timeout caused by: %@", cbObject); + + // Note that after this switch the 'watcher' is released (we don't + // own it anymore), though GCD is probably still holding a reference. + const ObjCStrongReference<NSError> nsError(qt_timeoutNSError(type)); + switch (type) { case OperationTimeout::serviceDiscovery: qCWarning(QT_BT_OSX, "Timeout in services discovery"); [self peripheral:peripheral didDiscoverServices:nsError]; break; case OperationTimeout::includedServicesDiscovery: qCWarning(QT_BT_OSX, "Timeout in included services discovery"); - [self peripheral:peripheral didDiscoverIncludedServicesForService:objectUnderWatch error:nsError]; + [self peripheral:peripheral didDiscoverIncludedServicesForService:cbObject error:nsError]; break; case OperationTimeout::characteristicsDiscovery: qCWarning(QT_BT_OSX, "Timeout in characteristics discovery"); - [self peripheral:peripheral didDiscoverCharacteristicsForService:objectUnderWatch error:nsError]; + [self peripheral:peripheral didDiscoverCharacteristicsForService:cbObject error:nsError]; break; case OperationTimeout::characteristicRead: qCWarning(QT_BT_OSX, "Timeout while reading a characteristic"); - [self peripheral:peripheral didUpdateValueForCharacteristic:objectUnderWatch error:nsError]; + [self peripheral:peripheral didUpdateValueForCharacteristic:cbObject error:nsError]; break; case OperationTimeout::descriptorsDiscovery: qCWarning(QT_BT_OSX, "Timeout in descriptors discovery"); - [self peripheral:peripheral didDiscoverDescriptorsForCharacteristic:objectUnderWatch error:nsError]; + [self peripheral:peripheral didDiscoverDescriptorsForCharacteristic:cbObject error:nsError]; break; case OperationTimeout::descriptorRead: qCWarning(QT_BT_OSX, "Timeout while reading a descriptor"); - [self peripheral:peripheral didUpdateValueForDescriptor:objectUnderWatch error:nsError]; + [self peripheral:peripheral didUpdateValueForDescriptor:cbObject error:nsError]; break; case OperationTimeout::characteristicWrite: qCWarning(QT_BT_OSX, "Timeout while writing a characteristic with response"); - [self peripheral:peripheral didWriteValueForCharacteristic:objectUnderWatch error:nsError]; + [self peripheral:peripheral didWriteValueForCharacteristic:cbObject error:nsError]; default:; } } @@ -1119,7 +1198,7 @@ QT_END_NAMESPACE charMap.clear(); descMap.clear(); currentReadHandle = 0; - [self stopWatchdog]; + [self stopWatchers]; // TODO: also serviceToVisit/VisitNext and visitedServices ? } @@ -1272,12 +1351,14 @@ QT_END_NAMESPACE return; } - if (objectUnderWatch != aPeripheral) { - // Timed out. + using namespace OSXBluetooth; + if (![self objectIsUnderWatch:aPeripheral operation:OperationTimeout::serviceDiscovery]) // Timed out already return; - } - [self stopWatchdog]; + QT_BT_MAC_AUTORELEASEPOOL; + + [self stopWatchingAfter:aPeripheral operation:OperationTimeout::serviceDiscovery]; + managerState = OSXBluetooth::CentralManagerIdle; if (error) { @@ -1303,16 +1384,14 @@ QT_END_NAMESPACE return; } - if (service != objectUnderWatch) { - // Timed out. + if (![self objectIsUnderWatch:service operation:OperationTimeout::includedServicesDiscovery]) return; - } QT_BT_MAC_AUTORELEASEPOOL; Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)"); - [self stopWatchdog]; + [self stopWatchingAfter:service operation:OperationTimeout::includedServicesDiscovery]; managerState = CentralManagerIdle; if (error) { @@ -1380,14 +1459,14 @@ QT_END_NAMESPACE return; } - if (service != objectUnderWatch) { - // Timed out already? + using namespace OSXBluetooth; + + if (![self objectIsUnderWatch:service operation:OperationTimeout::characteristicsDiscovery]) return; - } - [self stopWatchdog]; + QT_BT_MAC_AUTORELEASEPOOL; - using namespace OSXBluetooth; + [self stopWatchingAfter:service operation:OperationTimeout::characteristicsDiscovery]; Q_ASSERT_X(managerState != CentralManagerUpdating, Q_FUNC_INFO, "invalid state"); @@ -1407,21 +1486,21 @@ QT_END_NAMESPACE { Q_UNUSED(aPeripheral) - if (!notifier) { - // Detached. + if (!notifier) // Detached. return; - } - - const bool readMatch = characteristic == objectUnderWatch; - if (readMatch) - [self stopWatchdog]; using namespace OSXBluetooth; + QT_BT_MAC_AUTORELEASEPOOL; + + const bool readMatch = [self objectIsUnderWatch:characteristic operation:OperationTimeout::characteristicRead]; + if (readMatch) + [self stopWatchingAfter:characteristic operation:OperationTimeout::characteristicRead]; + Q_ASSERT_X(managerState != CentralManagerUpdating, Q_FUNC_INFO, "invalid state"); Q_ASSERT_X(peripheral, Q_FUNC_INFO, "invalid peripheral (nil)"); - QT_BT_MAC_AUTORELEASEPOOL; + // First, let's check if we're discovering a service details now. CBService *const service = characteristic.service; const QBluetoothUuid qtUuid(qt_uuid(service.UUID)); @@ -1495,12 +1574,12 @@ QT_END_NAMESPACE QT_BT_MAC_AUTORELEASEPOOL; - if (characteristic != objectUnderWatch) - return; + using namespace OSXBluetooth; - [self stopWatchdog]; + if (![self objectIsUnderWatch:characteristic operation:OperationTimeout::descriptorsDiscovery]) + return; - using namespace OSXBluetooth; + [self stopWatchingAfter:characteristic operation:OperationTimeout::descriptorsDiscovery]; if (error) { NSLog(@"%s failed with error %@", Q_FUNC_INFO, error); @@ -1533,12 +1612,12 @@ QT_END_NAMESPACE QT_BT_MAC_AUTORELEASEPOOL; - if (descriptor != objectUnderWatch) - return; + using namespace OSXBluetooth; - [self stopWatchdog]; + if (![self objectIsUnderWatch:descriptor operation:OperationTimeout::descriptorRead]) + return; - using namespace OSXBluetooth; + [self stopWatchingAfter:descriptor operation:OperationTimeout::descriptorRead]; CBService *const service = descriptor.characteristic.service; const QBluetoothUuid qtUuid(qt_uuid(service.UUID)); @@ -1625,13 +1704,12 @@ QT_END_NAMESPACE QT_BT_MAC_AUTORELEASEPOOL; - if (characteristic != objectUnderWatch) + if (![self objectIsUnderWatch:characteristic operation:OperationTimeout::characteristicWrite]) return; - [self stopWatchdog]; + [self stopWatchingAfter:characteristic operation:OperationTimeout::characteristicWrite]; requestPending = false; - // Error or not, but the cached value has to be deleted ... const QByteArray valueToReport(valuesToWrite.value(characteristic, QByteArray())); if (!valuesToWrite.remove(characteristic)) { @@ -1727,7 +1805,7 @@ QT_END_NAMESPACE notifier = nullptr; } - [self stopWatchdog]; + [self stopWatchers]; [self disconnectFromDevice]; } diff --git a/src/bluetooth/osx/osxbtcentralmanager_p.h b/src/bluetooth/osx/osxbtcentralmanager_p.h index e172d874..ce348dc6 100644 --- a/src/bluetooth/osx/osxbtcentralmanager_p.h +++ b/src/bluetooth/osx/osxbtcentralmanager_p.h @@ -87,18 +87,6 @@ enum CentralManagerState CentralManagerDisconnecting }; -enum class OperationTimeout -{ - none, - serviceDiscovery, - includedServicesDiscovery, - characteristicsDiscovery, - characteristicRead, - descriptorsDiscovery, - descriptorRead, - characteristicWrite -}; - // In Qt we work with handles and UUIDs. Core Bluetooth // has NSArrays (and nested NSArrays inside servces/characteristics). // To simplify a navigation, I need a simple way to map from a handle @@ -148,52 +136,11 @@ QT_END_NAMESPACE @interface QT_MANGLE_NAMESPACE(OSXBTCentralManager) : NSObject<CBCentralManagerDelegate, CBPeripheralDelegate, QT_MANGLE_NAMESPACE(GCDTimerDelegate)> -{ -@private - CBCentralManager *manager; - QT_PREPEND_NAMESPACE(OSXBluetooth)::CentralManagerState managerState; - bool disconnectPending; - - QT_PREPEND_NAMESPACE(QBluetoothUuid) deviceUuid; - - QT_PREPEND_NAMESPACE(OSXBluetooth)::LECBManagerNotifier *notifier; - - // Quite a verbose service discovery machinery - // (a "graph traversal"). - QT_PREPEND_NAMESPACE(OSXBluetooth)::ObjCStrongReference<NSMutableArray> servicesToVisit; - // The service we're discovering now (included services discovery): - NSUInteger currentService; - // Included services, we'll iterate through at the end of 'servicesToVisit': - QT_PREPEND_NAMESPACE(OSXBluetooth)::ObjCStrongReference<NSMutableArray> servicesToVisitNext; - // We'd like to avoid loops in a services' topology: - QT_PREPEND_NAMESPACE(OSXBluetooth)::ObjCStrongReference<NSMutableSet> visitedServices; - - QT_PREPEND_NAMESPACE(QList)<QT_PREPEND_NAMESPACE(QBluetoothUuid)> servicesToDiscoverDetails; - - QT_PREPEND_NAMESPACE(OSXBluetooth)::ServiceHash serviceMap; - QT_PREPEND_NAMESPACE(OSXBluetooth)::CharHash charMap; - QT_PREPEND_NAMESPACE(OSXBluetooth)::DescHash descMap; - - QT_PREPEND_NAMESPACE(QLowEnergyHandle) lastValidHandle; - - bool requestPending; - QT_PREPEND_NAMESPACE(OSXBluetooth)::RequestQueue requests; - QT_PREPEND_NAMESPACE(QLowEnergyHandle) currentReadHandle; - - QT_PREPEND_NAMESPACE(OSXBluetooth)::ValueHash valuesToWrite; - - qint64 timeoutMS; - id objectUnderWatch; - QT_PREPEND_NAMESPACE(OSXBluetooth)::OperationTimeout timeoutType; - QT_PREPEND_NAMESPACE(OSXBluetooth)::GCDTimer timeoutWatchdog; - -@public - CBPeripheral *peripheral; -} - - (id)initWith:(QT_PREPEND_NAMESPACE(OSXBluetooth)::LECBManagerNotifier *)notifier; - (void)dealloc; +- (CBPeripheral *)peripheral; + // 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; diff --git a/src/bluetooth/osx/osxbtconnectionmonitor.mm b/src/bluetooth/osx/osxbtconnectionmonitor.mm index dcd38726..b777af8e 100644 --- a/src/bluetooth/osx/osxbtconnectionmonitor.mm +++ b/src/bluetooth/osx/osxbtconnectionmonitor.mm @@ -59,6 +59,11 @@ using namespace QT_NAMESPACE; #endif @implementation QT_MANGLE_NAMESPACE(OSXBTConnectionMonitor) +{ + QT_PREPEND_NAMESPACE(OSXBluetooth::ConnectionMonitor) *monitor; + IOBluetoothUserNotification *discoveryNotification; + NSMutableArray *foundConnections; +} - (id)initWithMonitor:(OSXBluetooth::ConnectionMonitor *)aMonitor { diff --git a/src/bluetooth/osx/osxbtconnectionmonitor_p.h b/src/bluetooth/osx/osxbtconnectionmonitor_p.h index 18ffc86a..679f6124 100644 --- a/src/bluetooth/osx/osxbtconnectionmonitor_p.h +++ b/src/bluetooth/osx/osxbtconnectionmonitor_p.h @@ -79,11 +79,6 @@ public: QT_END_NAMESPACE @interface QT_MANGLE_NAMESPACE(OSXBTConnectionMonitor) : NSObject -{ - QT_PREPEND_NAMESPACE(OSXBluetooth::ConnectionMonitor) *monitor; - IOBluetoothUserNotification *discoveryNotification; - NSMutableArray *foundConnections; -} - (id)initWithMonitor:(QT_PREPEND_NAMESPACE(OSXBluetooth::ConnectionMonitor) *)monitor; - (void)connectionNotification:(id)notification withDevice:(IOBluetoothDevice *)device; diff --git a/src/bluetooth/osx/osxbtdeviceinquiry.mm b/src/bluetooth/osx/osxbtdeviceinquiry.mm index 79a8a92c..57cd73e1 100644 --- a/src/bluetooth/osx/osxbtdeviceinquiry.mm +++ b/src/bluetooth/osx/osxbtdeviceinquiry.mm @@ -60,6 +60,11 @@ QT_USE_NAMESPACE @implementation QT_MANGLE_NAMESPACE(OSXBTDeviceInquiry) +{ + IOBluetoothDeviceInquiry *m_inquiry; + bool m_active; + QT_PREPEND_NAMESPACE(OSXBluetooth::DeviceInquiryDelegate) *m_delegate;//C++ "delegate" +} - (id)initWithDelegate:(OSXBluetooth::DeviceInquiryDelegate *)delegate { diff --git a/src/bluetooth/osx/osxbtdeviceinquiry_p.h b/src/bluetooth/osx/osxbtdeviceinquiry_p.h index 777184f9..0fec2db2 100644 --- a/src/bluetooth/osx/osxbtdeviceinquiry_p.h +++ b/src/bluetooth/osx/osxbtdeviceinquiry_p.h @@ -80,11 +80,6 @@ public: QT_END_NAMESPACE @interface QT_MANGLE_NAMESPACE(OSXBTDeviceInquiry) : NSObject<IOBluetoothDeviceInquiryDelegate> -{ - IOBluetoothDeviceInquiry *m_inquiry; - bool m_active; - QT_PREPEND_NAMESPACE(OSXBluetooth::DeviceInquiryDelegate) *m_delegate;//C++ "delegate" -} - (id)initWithDelegate:(QT_PREPEND_NAMESPACE(OSXBluetooth::DeviceInquiryDelegate) *)delegate; - (void)dealloc; diff --git a/src/bluetooth/osx/osxbtdevicepair.mm b/src/bluetooth/osx/osxbtdevicepair.mm index dcaa3536..75dbbcad 100644 --- a/src/bluetooth/osx/osxbtdevicepair.mm +++ b/src/bluetooth/osx/osxbtdevicepair.mm @@ -69,6 +69,13 @@ QT_END_NAMESPACE QT_USE_NAMESPACE @implementation QT_MANGLE_NAMESPACE(OSXBTPairing) +{ + QT_PREPEND_NAMESPACE(QBluetoothAddress) m_targetAddress; + + bool m_active; + IOBluetoothDevicePair *m_pairing; // The real pairing request + QT_PREPEND_NAMESPACE(OSXBluetooth)::PairingDelegate *m_object; +} - (id)initWithTarget:(const QBluetoothAddress &)address delegate:(OSXBluetooth::PairingDelegate *)object diff --git a/src/bluetooth/osx/osxbtdevicepair_p.h b/src/bluetooth/osx/osxbtdevicepair_p.h index d5db5e35..1a2c7d6b 100644 --- a/src/bluetooth/osx/osxbtdevicepair_p.h +++ b/src/bluetooth/osx/osxbtdevicepair_p.h @@ -90,13 +90,6 @@ ObjCStrongReference<IOBluetoothDevice> device_with_address(const QBluetoothAddre QT_END_NAMESPACE @interface QT_MANGLE_NAMESPACE(OSXBTPairing) : NSObject<IOBluetoothDevicePairDelegate> -{ - QT_PREPEND_NAMESPACE(QBluetoothAddress) m_targetAddress; - - bool m_active; - IOBluetoothDevicePair *m_pairing; // The real pairing request - QT_PREPEND_NAMESPACE(OSXBluetooth)::PairingDelegate *m_object; -} - (id)initWithTarget:(const QBluetoothAddress &)address delegate:(QT_PREPEND_NAMESPACE(OSXBluetooth::PairingDelegate) *)object; diff --git a/src/bluetooth/osx/osxbtgcdtimer.mm b/src/bluetooth/osx/osxbtgcdtimer.mm index 095f8680..9663ca93 100644 --- a/src/bluetooth/osx/osxbtgcdtimer.mm +++ b/src/bluetooth/osx/osxbtgcdtimer.mm @@ -44,7 +44,23 @@ #include <algorithm> -@implementation QT_MANGLE_NAMESPACE(OSXBTGCDTimer) +QT_USE_NAMESPACE +using namespace OSXBluetooth; + +@implementation QT_MANGLE_NAMESPACE(OSXBTGCDTimer) { +@private + qint64 timeoutMS; + qint64 timeoutStepMS; + + // Optional: + id objectUnderWatch; + OperationTimeout timeoutType; + + QElapsedTimer timer; + id<QT_MANGLE_NAMESPACE(GCDTimerDelegate)> timeoutHandler; + + bool cancelled; +} - (instancetype)initWithDelegate:(id<QT_MANGLE_NAMESPACE(GCDTimerDelegate)>)delegate { @@ -52,11 +68,19 @@ timeoutHandler = delegate; timeoutMS = 0; timeoutStepMS = 0; + objectUnderWatch = nil; + timeoutType = OperationTimeout::none; cancelled = false; } return self; } +- (void)watchAfter:(id)object withTimeoutType:(OperationTimeout)type +{ + objectUnderWatch = object; + timeoutType = type; +} + - (void)startWithTimeout:(qint64)ms step:(qint64)stepMS { Q_ASSERT(!timeoutMS && !timeoutStepMS); @@ -86,9 +110,8 @@ const qint64 elapsed = timer.elapsed(); if (elapsed >= timeoutMS) { - [timeoutHandler timeout]; + [timeoutHandler timeout:self]; } else { - using namespace QT_PREPEND_NAMESPACE(OSXBluetooth); // Re-schedule: dispatch_queue_t leQueue(qt_LE_queue()); Q_ASSERT(leQueue); @@ -106,6 +129,18 @@ { cancelled = true; timeoutHandler = nil; + objectUnderWatch = nil; + timeoutType = OperationTimeout::none; +} + +- (id)objectUnderWatch +{ + return objectUnderWatch; +} + +- (OperationTimeout)timeoutType +{ + return timeoutType; } @end diff --git a/src/bluetooth/osx/osxbtgcdtimer_p.h b/src/bluetooth/osx/osxbtgcdtimer_p.h index 007a004b..6bd82c9a 100644 --- a/src/bluetooth/osx/osxbtgcdtimer_p.h +++ b/src/bluetooth/osx/osxbtgcdtimer_p.h @@ -58,25 +58,39 @@ #include <Foundation/Foundation.h> +QT_BEGIN_NAMESPACE + +namespace OSXBluetooth { + +enum class OperationTimeout +{ + none, + serviceDiscovery, + includedServicesDiscovery, + characteristicsDiscovery, + characteristicRead, + descriptorsDiscovery, + descriptorRead, + characteristicWrite +}; + +} // namespace OSXBluetooth + +QT_END_NAMESPACE + @protocol QT_MANGLE_NAMESPACE(GCDTimerDelegate) @required -- (void)timeout; +- (void)timeout:(id)sender; @end -@interface QT_MANGLE_NAMESPACE(OSXBTGCDTimer) : NSObject { -@private - qint64 timeoutMS; - qint64 timeoutStepMS; - QT_PREPEND_NAMESPACE(QElapsedTimer) timer; - id<QT_MANGLE_NAMESPACE(GCDTimerDelegate)> timeoutHandler; - bool cancelled; -} - +@interface QT_MANGLE_NAMESPACE(OSXBTGCDTimer) : NSObject - (instancetype)initWithDelegate:(id<QT_MANGLE_NAMESPACE(GCDTimerDelegate)>)delegate; +- (void)watchAfter:(id)object withTimeoutType:(QT_PREPEND_NAMESPACE(OSXBluetooth)::OperationTimeout)type; - (void)startWithTimeout:(qint64)ms step:(qint64)stepMS; - (void)handleTimeout; - (void)cancelTimer; - +- (id)objectUnderWatch; +- (QT_PREPEND_NAMESPACE(OSXBluetooth)::OperationTimeout)timeoutType; @end QT_BEGIN_NAMESPACE @@ -84,9 +98,9 @@ QT_BEGIN_NAMESPACE namespace OSXBluetooth { using GCDTimerObjC = QT_MANGLE_NAMESPACE(OSXBTGCDTimer); -using GCDTimer = ObjCScopedPointer<GCDTimerObjC>; +using GCDTimer = ObjCStrongReference<GCDTimerObjC>; -} +} // namespace OSXBluetooth QT_END_NAMESPACE diff --git a/src/bluetooth/osx/osxbtl2capchannel.mm b/src/bluetooth/osx/osxbtl2capchannel.mm index 474fe04b..dc8468a0 100644 --- a/src/bluetooth/osx/osxbtl2capchannel.mm +++ b/src/bluetooth/osx/osxbtl2capchannel.mm @@ -48,6 +48,12 @@ QT_USE_NAMESPACE @implementation QT_MANGLE_NAMESPACE(OSXBTL2CAPChannel) +{ + QT_PREPEND_NAMESPACE(OSXBluetooth)::ChannelDelegate *delegate; + IOBluetoothDevice *device; + IOBluetoothL2CAPChannel *channel; + bool connected; +} - (id)initWithDelegate:(OSXBluetooth::ChannelDelegate *)aDelegate { diff --git a/src/bluetooth/osx/osxbtl2capchannel_p.h b/src/bluetooth/osx/osxbtl2capchannel_p.h index a8a08975..512087b4 100644 --- a/src/bluetooth/osx/osxbtl2capchannel_p.h +++ b/src/bluetooth/osx/osxbtl2capchannel_p.h @@ -72,12 +72,6 @@ class ChannelDelegate; QT_END_NAMESPACE @interface QT_MANGLE_NAMESPACE(OSXBTL2CAPChannel) : NSObject<IOBluetoothL2CAPChannelDelegate> -{ - QT_PREPEND_NAMESPACE(OSXBluetooth)::ChannelDelegate *delegate; - IOBluetoothDevice *device; - IOBluetoothL2CAPChannel *channel; - bool connected; -} - (id)initWithDelegate:(QT_PREPEND_NAMESPACE(OSXBluetooth)::ChannelDelegate *)aDelegate; - (id)initWithDelegate:(QT_PREPEND_NAMESPACE(OSXBluetooth)::ChannelDelegate *)aDelegate diff --git a/src/bluetooth/osx/osxbtledeviceinquiry.mm b/src/bluetooth/osx/osxbtledeviceinquiry.mm index e61968ed..ccf1c279 100644 --- a/src/bluetooth/osx/osxbtledeviceinquiry.mm +++ b/src/bluetooth/osx/osxbtledeviceinquiry.mm @@ -122,6 +122,16 @@ QT_END_NAMESPACE QT_USE_NAMESPACE @implementation QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry) +{ + LECBManagerNotifier *notifier; + ObjCScopedPointer<CBCentralManager> manager; + + QList<QBluetoothDeviceInfo> devices; + LEInquiryState internalState; + int inquiryTimeoutMS; + + QT_PREPEND_NAMESPACE(OSXBluetooth)::GCDTimer elapsedTimer; +} -(id)initWithNotifier:(LECBManagerNotifier *)aNotifier { @@ -151,8 +161,10 @@ QT_USE_NAMESPACE [super dealloc]; } -- (void)timeout +- (void)timeout:(id)sender { + Q_UNUSED(sender) + if (internalState == InquiryActive) { [manager stopScan]; [manager setDelegate:nil]; @@ -204,7 +216,7 @@ QT_USE_NAMESPACE if (inquiryTimeoutMS > 0) { [elapsedTimer cancelTimer]; - elapsedTimer.reset([[GCDTimerObjC alloc] initWithDelegate:self]); + elapsedTimer.resetWithoutRetain([[GCDTimerObjC alloc] initWithDelegate:self]); [elapsedTimer startWithTimeout:inquiryTimeoutMS step:timeStepMS]; } @@ -239,7 +251,7 @@ QT_USE_NAMESPACE // we'll receive 'PoweredOn' state update later. // No change in internalState. Wait for 30 seconds. [elapsedTimer cancelTimer]; - elapsedTimer.reset([[GCDTimerObjC alloc] initWithDelegate:self]); + elapsedTimer.resetWithoutRetain([[GCDTimerObjC alloc] initWithDelegate:self]); [elapsedTimer startWithTimeout:powerOffTimeoutMS step:300]; return; #else diff --git a/src/bluetooth/osx/osxbtledeviceinquiry_p.h b/src/bluetooth/osx/osxbtledeviceinquiry_p.h index a19055ab..d99a93bd 100644 --- a/src/bluetooth/osx/osxbtledeviceinquiry_p.h +++ b/src/bluetooth/osx/osxbtledeviceinquiry_p.h @@ -89,17 +89,6 @@ enum LEInquiryState }; @interface QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry) : NSObject<CBCentralManagerDelegate, QT_MANGLE_NAMESPACE(GCDTimerDelegate)> -{ - LECBManagerNotifier *notifier; - ObjCScopedPointer<CBCentralManager> manager; - - QList<QBluetoothDeviceInfo> devices; - LEInquiryState internalState; - int inquiryTimeoutMS; - - QT_PREPEND_NAMESPACE(OSXBluetooth)::GCDTimer elapsedTimer; -} - - (id)initWithNotifier:(LECBManagerNotifier *)aNotifier; - (void)dealloc; diff --git a/src/bluetooth/osx/osxbtobexsession.mm b/src/bluetooth/osx/osxbtobexsession.mm index 9fbc2c12..868b2319 100644 --- a/src/bluetooth/osx/osxbtobexsession.mm +++ b/src/bluetooth/osx/osxbtobexsession.mm @@ -418,6 +418,27 @@ QT_USE_NAMESPACE @end @implementation QT_MANGLE_NAMESPACE(OSXBTOBEXSession) +{ + QT_PREPEND_NAMESPACE(OSXBluetooth)::OBEXSessionDelegate *delegate; + IOBluetoothDevice *device; + quint16 channelID; + IOBluetoothOBEXSession *session; + + QT_PREPEND_NAMESPACE(OSXBluetooth)::OBEXRequest currentRequest; + + bool connected; + bool connectionIDFound; + quint32 connectionID; + + QT_PREPEND_NAMESPACE(QIODevice) *inputStream; + + // TODO: switch to scoped pointers or strong reference objects instead. + NSMutableData *headersData; + NSMutableData *bodyData; + + quint32 bytesSent; + bool pendingAbort; +} + (OBEXMaxPacketLength) maxPacketLength { diff --git a/src/bluetooth/osx/osxbtobexsession_p.h b/src/bluetooth/osx/osxbtobexsession_p.h index 78c93452..49465f24 100644 --- a/src/bluetooth/osx/osxbtobexsession_p.h +++ b/src/bluetooth/osx/osxbtobexsession_p.h @@ -101,27 +101,6 @@ QT_END_NAMESPACE // (it does not have an interface to re-send data or re-use the same transfer reply). // It either succeeds or fails and tries to cleanup in any case. @interface QT_MANGLE_NAMESPACE(OSXBTOBEXSession) : NSObject -{ - QT_PREPEND_NAMESPACE(OSXBluetooth)::OBEXSessionDelegate *delegate; - IOBluetoothDevice *device; - quint16 channelID; - IOBluetoothOBEXSession *session; - - QT_PREPEND_NAMESPACE(OSXBluetooth)::OBEXRequest currentRequest; - - bool connected; - bool connectionIDFound; - quint32 connectionID; - - QT_PREPEND_NAMESPACE(QIODevice) *inputStream; - - // TODO: switch to scoped pointers or strong reference objects instead. - NSMutableData *headersData; - NSMutableData *bodyData; - - quint32 bytesSent; - bool pendingAbort; -} - (id)initWithDelegate:(QT_PREPEND_NAMESPACE(OSXBluetooth::OBEXSessionDelegate) *)aDelegate remoteDevice:(const QBluetoothAddress &)deviceAddress channelID:(quint16)port; diff --git a/src/bluetooth/osx/osxbtperipheralmanager.mm b/src/bluetooth/osx/osxbtperipheralmanager.mm index d3d92f41..1998340a 100644 --- a/src/bluetooth/osx/osxbtperipheralmanager.mm +++ b/src/bluetooth/osx/osxbtperipheralmanager.mm @@ -178,6 +178,33 @@ bool qt_validate_value_range(const QLowEnergyCharacteristicData &data) @end @implementation QT_MANGLE_NAMESPACE(OSXBTPeripheralManager) +{ + 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<NSMutableData>> charValues; + + QMap<QLowEnergyHandle, ValueRange> valueRanges; + + std::deque<UpdateRequest> updateQueue; + + ObjCScopedPointer<NSMutableSet> connectedCentrals; + + PeripheralState state; + NSUInteger maxNotificationValueLength; +} - (id)initWith:(LECBManagerNotifier *)aNotifier { diff --git a/src/bluetooth/osx/osxbtperipheralmanager_p.h b/src/bluetooth/osx/osxbtperipheralmanager_p.h index 19a831d8..fcf55698 100644 --- a/src/bluetooth/osx/osxbtperipheralmanager_p.h +++ b/src/bluetooth/osx/osxbtperipheralmanager_p.h @@ -122,33 +122,6 @@ struct UpdateRequest using ValueRange = QPair<NSUInteger, NSUInteger>; @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<NSMutableData>> charValues; - - QMap<QLowEnergyHandle, ValueRange> valueRanges; - - std::deque<UpdateRequest> updateQueue; - - ObjCScopedPointer<NSMutableSet> connectedCentrals; - - PeripheralState state; - NSUInteger maxNotificationValueLength; -} - (id)initWith:(LECBManagerNotifier *)notifier; - (void)dealloc; diff --git a/src/bluetooth/osx/osxbtrfcommchannel.mm b/src/bluetooth/osx/osxbtrfcommchannel.mm index bd87aae0..00b67ee0 100644 --- a/src/bluetooth/osx/osxbtrfcommchannel.mm +++ b/src/bluetooth/osx/osxbtrfcommchannel.mm @@ -45,6 +45,12 @@ QT_USE_NAMESPACE @implementation QT_MANGLE_NAMESPACE(OSXBTRFCOMMChannel) +{ + QT_PREPEND_NAMESPACE(OSXBluetooth)::ChannelDelegate *delegate; + IOBluetoothDevice *device; + IOBluetoothRFCOMMChannel *channel; + bool connected; +} - (id)initWithDelegate:(OSXBluetooth::ChannelDelegate *)aDelegate { diff --git a/src/bluetooth/osx/osxbtrfcommchannel_p.h b/src/bluetooth/osx/osxbtrfcommchannel_p.h index bb615559..775999ed 100644 --- a/src/bluetooth/osx/osxbtrfcommchannel_p.h +++ b/src/bluetooth/osx/osxbtrfcommchannel_p.h @@ -72,12 +72,6 @@ class ChannelDelegate; QT_END_NAMESPACE @interface QT_MANGLE_NAMESPACE(OSXBTRFCOMMChannel) : NSObject<IOBluetoothRFCOMMChannelDelegate> -{ - QT_PREPEND_NAMESPACE(OSXBluetooth)::ChannelDelegate *delegate; - IOBluetoothDevice *device; - IOBluetoothRFCOMMChannel *channel; - bool connected; -} - (id)initWithDelegate:(QT_PREPEND_NAMESPACE(OSXBluetooth)::ChannelDelegate *)aDelegate; - (id)initWithDelegate:(QT_PREPEND_NAMESPACE(OSXBluetooth)::ChannelDelegate *)aDelegate diff --git a/src/bluetooth/osx/osxbtsdpinquiry.mm b/src/bluetooth/osx/osxbtsdpinquiry.mm index 23d1bd84..591d75a5 100644 --- a/src/bluetooth/osx/osxbtsdpinquiry.mm +++ b/src/bluetooth/osx/osxbtsdpinquiry.mm @@ -212,6 +212,11 @@ QT_USE_NAMESPACE using namespace OSXBluetooth; @implementation QT_MANGLE_NAMESPACE(OSXBTSDPInquiry) +{ + QT_PREPEND_NAMESPACE(OSXBluetooth::SDPInquiryDelegate) *delegate; + IOBluetoothDevice *device; + bool isActive; +} - (id)initWithDelegate:(SDPInquiryDelegate *)aDelegate { diff --git a/src/bluetooth/osx/osxbtsdpinquiry_p.h b/src/bluetooth/osx/osxbtsdpinquiry_p.h index 6b39634e..c63738bb 100644 --- a/src/bluetooth/osx/osxbtsdpinquiry_p.h +++ b/src/bluetooth/osx/osxbtsdpinquiry_p.h @@ -88,11 +88,6 @@ QList<QBluetoothUuid> extract_services_uuids(IOBluetoothDevice *device); QT_END_NAMESPACE @interface QT_MANGLE_NAMESPACE(OSXBTSDPInquiry) : NSObject -{ - QT_PREPEND_NAMESPACE(OSXBluetooth::SDPInquiryDelegate) *delegate; - IOBluetoothDevice *device; - bool isActive; -} - (id)initWithDelegate:(QT_PREPEND_NAMESPACE(OSXBluetooth::SDPInquiryDelegate) *)aDelegate; - (void)dealloc; diff --git a/src/bluetooth/osx/osxbtsocketlistener.mm b/src/bluetooth/osx/osxbtsocketlistener.mm index 52243990..517b7f2d 100644 --- a/src/bluetooth/osx/osxbtsocketlistener.mm +++ b/src/bluetooth/osx/osxbtsocketlistener.mm @@ -57,6 +57,11 @@ QT_END_NAMESPACE QT_USE_NAMESPACE @implementation QT_MANGLE_NAMESPACE(OSXBTSocketListener) +{ + IOBluetoothUserNotification *connectionNotification; + QT_PREPEND_NAMESPACE(OSXBluetooth::SocketListener) *delegate; + quint16 port; +} - (id)initWithListener:(OSXBluetooth::SocketListener *)aDelegate { diff --git a/src/bluetooth/osx/osxbtsocketlistener_p.h b/src/bluetooth/osx/osxbtsocketlistener_p.h index afe3eadc..cac0b7c4 100644 --- a/src/bluetooth/osx/osxbtsocketlistener_p.h +++ b/src/bluetooth/osx/osxbtsocketlistener_p.h @@ -82,11 +82,6 @@ QT_END_NAMESPACE // RFCOMM or L2CAP protocol. It must be deleted to stop listening. @interface QT_MANGLE_NAMESPACE(OSXBTSocketListener) : NSObject -{ - IOBluetoothUserNotification *connectionNotification; - QT_PREPEND_NAMESPACE(OSXBluetooth::SocketListener) *delegate; - quint16 port; -} - (id)initWithListener:(QT_PREPEND_NAMESPACE(OSXBluetooth::SocketListener) *)aDelegate; - (void)dealloc; diff --git a/src/bluetooth/qbluetoothsocket.cpp b/src/bluetooth/qbluetoothsocket.cpp index 16461bd3..eecb1401 100644 --- a/src/bluetooth/qbluetoothsocket.cpp +++ b/src/bluetooth/qbluetoothsocket.cpp @@ -427,8 +427,8 @@ void QBluetoothSocket::connectToService(const QBluetoothAddress &address, const At any point, the socket can emit error() to signal that an error occurred. - On Android, a connection to a service can not be established using a port. Calling this function - will emit a \l {QBluetoothSocket::ServiceNotFoundError}{ServiceNotFoundError}. + On Android and BlueZ (version 5.46 or above), a connection to a service can not be established using a port. + Calling this function will emit a \l {QBluetoothSocket::ServiceNotFoundError}{ServiceNotFoundError}. Note that most platforms require a pairing prior to connecting to the remote device. Otherwise the connection process may fail. diff --git a/src/bluetooth/qlowenergycontroller_osx.mm b/src/bluetooth/qlowenergycontroller_osx.mm index d01686ae..8cef621c 100644 --- a/src/bluetooth/qlowenergycontroller_osx.mm +++ b/src/bluetooth/qlowenergycontroller_osx.mm @@ -234,7 +234,7 @@ void QLowEnergyControllerPrivateOSX::_q_serviceDiscoveryFinished() QT_BT_MAC_AUTORELEASEPOOL; - NSArray *const services = centralManager.data()->peripheral.services; + NSArray *const services = [centralManager.data() peripheral].services; // Now we have to traverse the discovered services tree. // Essentially it's an iterative version of more complicated code from the // OSXBTCentralManager's code. diff --git a/src/imports/nfc/qdeclarativendeffilter.cpp b/src/imports/nfc/qdeclarativendeffilter.cpp index 6cbda747..c382ccd9 100644 --- a/src/imports/nfc/qdeclarativendeffilter.cpp +++ b/src/imports/nfc/qdeclarativendeffilter.cpp @@ -104,7 +104,7 @@ */ QDeclarativeNdefFilter::QDeclarativeNdefFilter(QObject *parent) -: QObject(parent), m_minimum(1), m_maximum(UINT_MAX) +: QObject(parent), m_minimum(1), m_maximum(INT_MAX) { } |