diff options
Diffstat (limited to 'src/bluetooth')
-rw-r--r-- | src/bluetooth/osx/osxbtcentralmanager.mm | 24 | ||||
-rw-r--r-- | src/bluetooth/osx/osxbtnotifier_p.h | 1 | ||||
-rw-r--r-- | src/bluetooth/qlowenergycontroller_osx.mm | 17 | ||||
-rw-r--r-- | src/bluetooth/qlowenergycontroller_osx_p.h | 1 | ||||
-rw-r--r-- | src/bluetooth/qlowenergycontroller_winrt.cpp | 20 |
5 files changed, 55 insertions, 8 deletions
diff --git a/src/bluetooth/osx/osxbtcentralmanager.mm b/src/bluetooth/osx/osxbtcentralmanager.mm index 41713909..6b742684 100644 --- a/src/bluetooth/osx/osxbtcentralmanager.mm +++ b/src/bluetooth/osx/osxbtcentralmanager.mm @@ -1373,6 +1373,30 @@ QT_USE_NAMESPACE [self discoverIncludedServices]; } +- (void)peripheral:(CBPeripheral *)aPeripheral + didModifyServices:(NSArray<CBService *> *)invalidatedServices +{ + Q_UNUSED(aPeripheral) + Q_UNUSED(invalidatedServices) + + qCWarning(QT_BT_OSX) << "The peripheral has modified its services."; + // "This method is invoked whenever one or more services of a peripheral have changed. + // A peripheral’s services have changed if: + // * A service is removed from the peripheral’s database + // * A new service is added to the peripheral’s database + // * A service that was previously removed from the peripheral’s + // database is readded to the database at a different location" + + // In case new services were added - we have to discover them. + // In case some were removed - we can end up with dangling pointers + // (see our 'watchdogs', for example). To handle the situation + // we stop all current operations here, report to QLowEnergyController + // so that it can trigger re-discovery. + [self reset]; + managerState = OSXBluetooth::CentralManagerIdle; + if (notifier) + emit notifier->servicesWereModified(); +} - (void)peripheral:(CBPeripheral *)aPeripheral didDiscoverIncludedServicesForService:(CBService *)service error:(NSError *)error diff --git a/src/bluetooth/osx/osxbtnotifier_p.h b/src/bluetooth/osx/osxbtnotifier_p.h index 47ee6ba1..dca6c268 100644 --- a/src/bluetooth/osx/osxbtnotifier_p.h +++ b/src/bluetooth/osx/osxbtnotifier_p.h @@ -89,6 +89,7 @@ Q_SIGNALS: void descriptorRead(QLowEnergyHandle descHandle, const QByteArray &value); void descriptorWritten(QLowEnergyHandle descHandle, const QByteArray &value); void notificationEnabled(QLowEnergyHandle charHandle, bool enabled); + void servicesWereModified(); void LEnotSupported(); void CBManagerError(QBluetoothDeviceDiscoveryAgent::Error error); diff --git a/src/bluetooth/qlowenergycontroller_osx.mm b/src/bluetooth/qlowenergycontroller_osx.mm index 8cef621c..8bcdc22e 100644 --- a/src/bluetooth/qlowenergycontroller_osx.mm +++ b/src/bluetooth/qlowenergycontroller_osx.mm @@ -339,6 +339,21 @@ void QLowEnergyControllerPrivateOSX::_q_serviceDetailsDiscoveryFinished(QSharedP qtService->setState(QLowEnergyService::ServiceDiscovered); } +void QLowEnergyControllerPrivateOSX::_q_servicesWereModified() +{ + if (!(controllerState == QLowEnergyController::DiscoveringState + || controllerState == QLowEnergyController::DiscoveredState)) { + qCWarning(QT_BT_OSX) << "services were modified while controller is not in Discovered/Discovering state"; + return; + } + + if (controllerState == QLowEnergyController::DiscoveredState) + invalidateServices(); + + controllerState = QLowEnergyController::ConnectedState; + q_ptr->discoverServices(); +} + void QLowEnergyControllerPrivateOSX::_q_characteristicRead(QLowEnergyHandle charHandle, const QByteArray &value) { @@ -989,6 +1004,8 @@ bool QLowEnergyControllerPrivateOSX::connectSlots(OSXBluetooth::LECBManagerNotif this, &QLowEnergyControllerPrivateOSX::_q_serviceDiscoveryFinished); ok = ok && connect(notifier, &LECBManagerNotifier::serviceDetailsDiscoveryFinished, this, &QLowEnergyControllerPrivateOSX::_q_serviceDetailsDiscoveryFinished); + ok = ok && connect(notifier, &LECBManagerNotifier::servicesWereModified, + this, &QLowEnergyControllerPrivateOSX::_q_servicesWereModified); ok = ok && connect(notifier, &LECBManagerNotifier::characteristicRead, this, &QLowEnergyControllerPrivateOSX::_q_characteristicRead); ok = ok && connect(notifier, &LECBManagerNotifier::characteristicWritten, diff --git a/src/bluetooth/qlowenergycontroller_osx_p.h b/src/bluetooth/qlowenergycontroller_osx_p.h index 24b7c6e9..da959895 100644 --- a/src/bluetooth/qlowenergycontroller_osx_p.h +++ b/src/bluetooth/qlowenergycontroller_osx_p.h @@ -98,6 +98,7 @@ private Q_SLOTS: void _q_serviceDiscoveryFinished(); void _q_serviceDetailsDiscoveryFinished(QSharedPointer<QLowEnergyServicePrivate> service); + void _q_servicesWereModified(); void _q_characteristicRead(QLowEnergyHandle charHandle, const QByteArray &value); void _q_characteristicWritten(QLowEnergyHandle charHandle, const QByteArray &value); diff --git a/src/bluetooth/qlowenergycontroller_winrt.cpp b/src/bluetooth/qlowenergycontroller_winrt.cpp index f4a5d0cc..e70b046b 100644 --- a/src/bluetooth/qlowenergycontroller_winrt.cpp +++ b/src/bluetooth/qlowenergycontroller_winrt.cpp @@ -750,7 +750,7 @@ void QLowEnergyControllerPrivateWinRT::readDescriptor(const QSharedPointer<QLowE HRESULT hr; hr = QEventDispatcherWinRT::runOnXamlThread([charHandle, descHandle, service, this]() { - QLowEnergyServicePrivate::CharData charData = service->characteristicList.value(charHandle); + const QLowEnergyServicePrivate::CharData charData = service->characteristicList.value(charHandle); ComPtr<IGattCharacteristic> characteristic = getNativeCharacteristic(service->uuid, charData.uuid); if (!characteristic) { qCDebug(QT_BT_WINRT) << "Could not obtain native characteristic" << charData.uuid @@ -762,12 +762,13 @@ void QLowEnergyControllerPrivateWinRT::readDescriptor(const QSharedPointer<QLowE // Get native descriptor if (!charData.descriptorList.contains(descHandle)) qCDebug(QT_BT_WINRT) << "Descriptor" << descHandle << "cannot be found in characteristic" << charHandle; - QLowEnergyServicePrivate::DescData descData = charData.descriptorList.value(descHandle); - if (descData.uuid == QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)) { + const QLowEnergyServicePrivate::DescData descData = charData.descriptorList.value(descHandle); + const QBluetoothUuid descUuid = descData.uuid; + if (descUuid == QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)) { ComPtr<IAsyncOperation<ClientCharConfigDescriptorResult *>> readOp; HRESULT hr = characteristic->ReadClientCharacteristicConfigurationDescriptorAsync(&readOp); Q_ASSERT_SUCCEEDED(hr); - auto readCompletedLambda = [&charData, charHandle, &descData, descHandle, service] + auto readCompletedLambda = [charHandle, descHandle, service] (IAsyncOperation<ClientCharConfigDescriptorResult *> *op, AsyncStatus status) { if (status == AsyncStatus::Canceled || status == AsyncStatus::Error) { @@ -808,9 +809,11 @@ void QLowEnergyControllerPrivateWinRT::readDescriptor(const QSharedPointer<QLowE service->setError(QLowEnergyService::DescriptorReadError); return S_OK; } + QLowEnergyServicePrivate::DescData descData; + descData.uuid = QBluetoothUuid::ClientCharacteristicConfiguration; descData.value = QByteArray(2, Qt::Uninitialized); qToLittleEndian(result, descData.value.data()); - charData.descriptorList.insert(descHandle, descData); + service->characteristicList[charHandle].descriptorList[descHandle] = descData; emit service->descriptorRead(QLowEnergyDescriptor(service, charHandle, descHandle), descData.value); return S_OK; @@ -828,7 +831,7 @@ void QLowEnergyControllerPrivateWinRT::readDescriptor(const QSharedPointer<QLowE ComPtr<IAsyncOperation<GattReadResult*>> readOp; hr = descriptor->ReadValueWithCacheModeAsync(BluetoothCacheMode_Uncached, &readOp); Q_ASSERT_SUCCEEDED(hr); - auto readCompletedLambda = [&charData, charHandle, &descData, descHandle, service] + auto readCompletedLambda = [charHandle, descHandle, descUuid, service] (IAsyncOperation<GattReadResult*> *op, AsyncStatus status) { if (status == AsyncStatus::Canceled || status == AsyncStatus::Error) { @@ -844,11 +847,12 @@ void QLowEnergyControllerPrivateWinRT::readDescriptor(const QSharedPointer<QLowE service->setError(QLowEnergyService::DescriptorReadError); return S_OK; } - if (descData.uuid == QBluetoothUuid::CharacteristicUserDescription) + QLowEnergyServicePrivate::DescData descData; + if (descUuid == QBluetoothUuid::CharacteristicUserDescription) descData.value = byteArrayFromGattResult(descriptorValue, true); else descData.value = byteArrayFromGattResult(descriptorValue); - charData.descriptorList.insert(descHandle, descData); + service->characteristicList[charHandle].descriptorList[descHandle] = descData; emit service->descriptorRead(QLowEnergyDescriptor(service, charHandle, descHandle), descData.value); return S_OK; |