diff options
author | Ivan Solovev <ivan.solovev@qt.io> | 2022-08-22 17:59:06 +0200 |
---|---|---|
committer | Ivan Solovev <ivan.solovev@qt.io> | 2022-08-26 12:49:54 +0200 |
commit | 5fee999b242fadc9efca5423aa1296486aa5a880 (patch) | |
tree | af7293183050bf696937b99f77bda5ef7f934c6f /src | |
parent | 5bca1dec859068aac047b17c2fe49b2eb0d3368e (diff) | |
download | qtconnectivity-5fee999b242fadc9efca5423aa1296486aa5a880.tar.gz |
Bluetooth Windows: refactor getNativeCharacteristic
... to get rid of await() call. The function now requests the
characteristics asynchronously and executes a custom callback, passing
the selected characteristic as a parameter.
After that the refactoring is quite simple: we put all the code
after the getNativeCharacteristic() call into a lambda, and pass this
lambda as a last parameter of the updated method.
As a drive-by: improve
tst_qlowenergycontroller_device::testNotificationAndIndication()
stability by adding QTest::qWait() calls after disabling notification
and indication, like it is done in other places.
Task-number: QTBUG-105556
Pick-to: 6.4 6.3 6.2
Change-Id: I1164bbc677d3549ef930243fd645eed344e27b7c
Reviewed-by: Juha Vuolle <juha.vuolle@insta.fi>
Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/bluetooth/qlowenergycontroller_winrt.cpp | 286 | ||||
-rw-r--r-- | src/bluetooth/qlowenergycontroller_winrt_p.h | 24 |
2 files changed, 207 insertions, 103 deletions
diff --git a/src/bluetooth/qlowenergycontroller_winrt.cpp b/src/bluetooth/qlowenergycontroller_winrt.cpp index e5c938ca..c9def5ab 100644 --- a/src/bluetooth/qlowenergycontroller_winrt.cpp +++ b/src/bluetooth/qlowenergycontroller_winrt.cpp @@ -766,41 +766,59 @@ ComPtr<IGattDeviceService> QLowEnergyControllerPrivateWinRT::getNativeService( return nullptr; } -ComPtr<IGattCharacteristic> QLowEnergyControllerPrivateWinRT::getNativeCharacteristic( - const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid) +HRESULT QLowEnergyControllerPrivateWinRT::getNativeCharacteristic( + const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid, + NativeCharacteristicCallback callback) { ComPtr<IGattDeviceService> service = getNativeService(serviceUuid); if (!service) - return nullptr; + return -1; ComPtr<IGattDeviceService3> service3; HRESULT hr = service.As(&service3); - RETURN_IF_FAILED("Could not cast service to service3", return nullptr); + RETURN_IF_FAILED("Could not cast service to service3", return hr); - ComPtr<IAsyncOperation<GattCharacteristicsResult *>> op; - ComPtr<IGattCharacteristicsResult> result; - hr = service3->GetCharacteristicsForUuidAsync(charUuid, &op); - RETURN_IF_FAILED("Could not obtain native characteristics for service", return nullptr); - hr = QWinRTFunctions::await(op, result.GetAddressOf(), QWinRTFunctions::ProcessMainThreadEvents, 5000); - RETURN_IF_FAILED("Could not await completion of characteristic operation", return nullptr); - GattCommunicationStatus status; - hr = result->get_Status(&status); - if (FAILED(hr) || status != GattCommunicationStatus_Success) { - qErrnoWarning(hr, "Native characteristic operation failed."); - return nullptr; - } - ComPtr<IVectorView<GattCharacteristic *>> characteristics; - hr = result->get_Characteristics(&characteristics); - RETURN_IF_FAILED("Could not obtain characteristic list.", return nullptr); - uint size; - hr = characteristics->get_Size(&size); - RETURN_IF_FAILED("Could not obtain characteristic list's size.", return nullptr); - if (size != 1) - qErrnoWarning("More than 1 characteristic found."); - ComPtr<IGattCharacteristic> characteristic; - hr = characteristics->GetAt(0, &characteristic); - RETURN_IF_FAILED("Could not obtain first characteristic for service", return nullptr); - return characteristic; + ComPtr<IAsyncOperation<GattCharacteristicsResult *>> characteristicRequestOp; + hr = service3->GetCharacteristicsForUuidAsync(charUuid, &characteristicRequestOp); + + QPointer<QLowEnergyControllerPrivateWinRT> thisPtr(this); + hr = characteristicRequestOp->put_Completed( + Callback<IAsyncOperationCompletedHandler<GattCharacteristicsResult *>>( + [thisPtr, callback]( + IAsyncOperation<GattCharacteristicsResult *> *op, AsyncStatus status) + { + if (thisPtr) { + if (status != AsyncStatus::Completed) { + qCDebug(QT_BT_WINDOWS) << "Failed to get result of async characteristic operation"; + return S_OK; + } + ComPtr<IGattCharacteristicsResult> result; + HRESULT hr = op->GetResults(&result); + RETURN_IF_FAILED("Failed to get result of async characteristic operation", return hr); + GattCommunicationStatus status; + hr = result->get_Status(&status); + if (FAILED(hr) || status != GattCommunicationStatus_Success) { + qErrnoWarning(hr, "Native characteristic operation failed."); + return hr; + } + ComPtr<IVectorView<GattCharacteristic *>> characteristics; + hr = result->get_Characteristics(&characteristics); + RETURN_IF_FAILED("Could not obtain characteristic list.", return hr); + uint size; + hr = characteristics->get_Size(&size); + RETURN_IF_FAILED("Could not obtain characteristic list's size.", return hr); + if (size != 1) + qErrnoWarning("More than 1 characteristic found."); + ComPtr<IGattCharacteristic> characteristic; + hr = characteristics->GetAt(0, &characteristic); + RETURN_IF_FAILED("Could not obtain first characteristic for service", return hr); + if (characteristic) + callback(characteristic); // use the characteristic in a custom callback + } + return S_OK; + }).Get()); + + return hr; } void QLowEnergyControllerPrivateWinRT::registerForValueChanges(const QBluetoothUuid &serviceUuid, @@ -816,23 +834,27 @@ void QLowEnergyControllerPrivateWinRT::registerForValueChanges(const QBluetoothU if (QBluetoothUuid(guuid) == charUuid) return; } - ComPtr<IGattCharacteristic> characteristic = getNativeCharacteristic(serviceUuid, charUuid); - if (!characteristic) { - qCDebug(QT_BT_WINDOWS).nospace() << "Could not obtain native characteristic " << charUuid - << " from service " << serviceUuid << ". Qt will not be able to signal" - << " changes for this characteristic."; - return; - } - EventRegistrationToken token; - HRESULT hr; - hr = characteristic->add_ValueChanged( - Callback<ValueChangedHandler>(this, &QLowEnergyControllerPrivateWinRT::onValueChange).Get(), - &token); - RETURN_IF_FAILED("Could not register characteristic for value changes", return) - mValueChangedTokens.append(ValueChangedEntry(characteristic, token)); - qCDebug(QT_BT_WINDOWS) << "Characteristic" << charUuid << "in service" - << serviceUuid << "registered for value changes"; + auto callback = [this, charUuid, serviceUuid](ComPtr<IGattCharacteristic> characteristic) { + EventRegistrationToken token; + HRESULT hr; + hr = characteristic->add_ValueChanged( + Callback<ValueChangedHandler>( + this, &QLowEnergyControllerPrivateWinRT::onValueChange).Get(), + &token); + RETURN_IF_FAILED("Could not register characteristic for value changes", return) + mValueChangedTokens.append(ValueChangedEntry(characteristic, token)); + qCDebug(QT_BT_WINDOWS) << "Characteristic" << charUuid << "in service" + << serviceUuid << "registered for value changes"; + }; + + HRESULT hr = getNativeCharacteristic(serviceUuid, charUuid, callback); + if (FAILED(hr)) { + qCDebug(QT_BT_WINDOWS).nospace() << "Could not obtain native characteristic " + << charUuid << " from service " << serviceUuid + << ". Qt will not be able to signal" + << " changes for this characteristic."; + } } void QLowEnergyControllerPrivateWinRT::unregisterFromValueChanges() @@ -1290,22 +1312,33 @@ void QLowEnergyControllerPrivateWinRT::readCharacteristic( return; } - const QLowEnergyServicePrivate::CharData charData = service->characteristicList.value(charHandle); + const auto charData = service->characteristicList.value(charHandle); if (!(charData.properties & QLowEnergyCharacteristic::Read)) qCDebug(QT_BT_WINDOWS) << "Read flag is not set for characteristic" << charData.uuid; - ComPtr<IGattCharacteristic> characteristic = getNativeCharacteristic(service->uuid, charData.uuid); - if (!characteristic) { + auto characteristicCallback = [charHandle, service, this]( + ComPtr<IGattCharacteristic> characteristic) { + readCharacteristicHelper(service, charHandle, characteristic); + }; + + HRESULT hr = getNativeCharacteristic(service->uuid, charData.uuid, characteristicCallback); + if (FAILED(hr)) { qCDebug(QT_BT_WINDOWS) << "Could not obtain native characteristic" << charData.uuid - << "from service" << service->uuid; + << "from service" << service->uuid; service->setError(QLowEnergyService::CharacteristicReadError); - return; } - ComPtr<IAsyncOperation<GattReadResult*>> readOp; +} + +void QLowEnergyControllerPrivateWinRT::readCharacteristicHelper( + const QSharedPointer<QLowEnergyServicePrivate> service, + const QLowEnergyHandle charHandle, + GattCharacteristicComPtr characteristic) +{ + ComPtr<IAsyncOperation<GattReadResult *>> readOp; HRESULT hr = characteristic->ReadValueWithCacheModeAsync(BluetoothCacheMode_Uncached, &readOp); CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not read characteristic", service, QLowEnergyService::CharacteristicReadError, return) - auto readCompletedLambda = [charData, charHandle, service] + auto readCompletedLambda = [charHandle, service] (IAsyncOperation<GattReadResult*> *op, AsyncStatus status) { if (status == AsyncStatus::Canceled || status == AsyncStatus::Error) { @@ -1316,11 +1349,11 @@ void QLowEnergyControllerPrivateWinRT::readCharacteristic( ComPtr<IGattReadResult> characteristicValue; HRESULT hr; hr = op->GetResults(&characteristicValue); - CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain result for characteristic", - service, QLowEnergyService::CharacteristicReadError, return S_OK) + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain result for characteristic", service, + QLowEnergyService::CharacteristicReadError, return S_OK) const QByteArray value = byteArrayFromGattResult(characteristicValue); - QLowEnergyServicePrivate::CharData charData = service->characteristicList.value(charHandle); + auto charData = service->characteristicList.value(charHandle); charData.value = value; service->characteristicList.insert(charHandle, charData); emit service->characteristicRead(QLowEnergyCharacteristic(service, charHandle), value); @@ -1354,21 +1387,37 @@ void QLowEnergyControllerPrivateWinRT::readDescriptor( return; } - const QLowEnergyServicePrivate::CharData charData = service->characteristicList.value(charHandle); - ComPtr<IGattCharacteristic> characteristic = getNativeCharacteristic(service->uuid, charData.uuid); - if (!characteristic) { + const auto charData = service->characteristicList.value(charHandle); + + auto characteristicCallback = [charHandle, descHandle, service, this]( + ComPtr<IGattCharacteristic> characteristic) { + readDescriptorHelper(service, charHandle, descHandle, characteristic); + }; + + HRESULT hr = getNativeCharacteristic(service->uuid, charData.uuid, characteristicCallback); + if (FAILED(hr)) { qCDebug(QT_BT_WINDOWS) << "Could not obtain native characteristic" << charData.uuid - << "from service" << service->uuid; + << "from service" << service->uuid; service->setError(QLowEnergyService::DescriptorReadError); - return; } +} +void QLowEnergyControllerPrivateWinRT::readDescriptorHelper( + const QSharedPointer<QLowEnergyServicePrivate> service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descHandle, + GattCharacteristicComPtr characteristic) +{ // Get native descriptor - if (!charData.descriptorList.contains(descHandle)) - qCDebug(QT_BT_WINDOWS) << "Descriptor" << descHandle << "cannot be found in characteristic" << charHandle; - const QLowEnergyServicePrivate::DescData descData = charData.descriptorList.value(descHandle); + const auto charData = service->characteristicList.value(charHandle); + if (!charData.descriptorList.contains(descHandle)) { + qCDebug(QT_BT_WINDOWS) << "Descriptor" << descHandle << "cannot be found in characteristic" + << charHandle; + } + const auto descData = charData.descriptorList.value(descHandle); const QBluetoothUuid descUuid = descData.uuid; - if (descUuid == QBluetoothUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration)) { + if (descUuid == + QBluetoothUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration)) { ComPtr<IAsyncOperation<ClientCharConfigDescriptorResult *>> readOp; HRESULT hr = characteristic->ReadClientCharacteristicConfigurationDescriptorAsync(&readOp); CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not read client characteristic configuration", @@ -1384,12 +1433,12 @@ void QLowEnergyControllerPrivateWinRT::readDescriptor( ComPtr<IClientCharConfigDescriptorResult> iValue; HRESULT hr; hr = op->GetResults(&iValue); - CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain result for descriptor", - service, QLowEnergyService::DescriptorReadError, return S_OK) + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain result for descriptor", service, + QLowEnergyService::DescriptorReadError, return S_OK) GattClientCharacteristicConfigurationDescriptorValue value; hr = iValue->get_ClientCharacteristicConfigurationDescriptor(&value); - CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain value for descriptor", - service, QLowEnergyService::DescriptorReadError, return S_OK) + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain value for descriptor", service, + QLowEnergyService::DescriptorReadError, return S_OK) quint16 result = 0; bool correct = false; if (value & GattClientCharacteristicConfigurationDescriptorValue_Indicate) { @@ -1404,7 +1453,7 @@ void QLowEnergyControllerPrivateWinRT::readDescriptor( correct = true; if (!correct) { qCDebug(QT_BT_WINDOWS) << "Descriptor" << descHandle - << "read operation failed. Obtained unexpected value."; + << "read operation failed. Obtained unexpected value."; service->setError(QLowEnergyService::DescriptorReadError); return S_OK; } @@ -1414,7 +1463,7 @@ void QLowEnergyControllerPrivateWinRT::readDescriptor( qToLittleEndian(result, descData.value.data()); service->characteristicList[charHandle].descriptorList[descHandle] = descData; emit service->descriptorRead(QLowEnergyDescriptor(service, charHandle, descHandle), - descData.value); + descData.value); return S_OK; }; hr = readOp->put_Completed( @@ -1434,7 +1483,8 @@ void QLowEnergyControllerPrivateWinRT::readDescriptor( CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain descriptor for uuid", service, QLowEnergyService::DescriptorReadError, return) ComPtr<IGattDescriptorsResult> result; - hr = QWinRTFunctions::await(op, result.GetAddressOf(), QWinRTFunctions::ProcessMainThreadEvents, 5000); + hr = QWinRTFunctions::await(op, result.GetAddressOf(), + QWinRTFunctions::ProcessMainThreadEvents, 5000); CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not await descritpor read result", service, QLowEnergyService::DescriptorReadError, return) @@ -1494,7 +1544,7 @@ void QLowEnergyControllerPrivateWinRT::readDescriptor( descData.value = byteArrayFromGattResult(descriptorValue); service->characteristicList[charHandle].descriptorList[descHandle] = descData; emit service->descriptorRead(QLowEnergyDescriptor(service, charHandle, descHandle), - descData.value); + descData.value); return S_OK; }; hr = readOp->put_Completed(Callback<IAsyncOperationCompletedHandler<GattReadResult *>>( @@ -1531,18 +1581,29 @@ void QLowEnergyControllerPrivateWinRT::writeCharacteristic( : QLowEnergyCharacteristic::WriteNoResponse))) qCDebug(QT_BT_WINDOWS) << "Write flag is not set for characteristic" << charHandle; - ComPtr<IGattCharacteristic> characteristic = getNativeCharacteristic(service->uuid, - charData.uuid); - if (!characteristic) { + auto characteristicCallback = [charHandle, service, newValue, writeWithResponse, this]( + ComPtr<IGattCharacteristic> characteristic) { + writeCharacteristicHelper(service, charHandle, newValue, writeWithResponse, + characteristic); + }; + + HRESULT hr = getNativeCharacteristic(service->uuid, charData.uuid, characteristicCallback); + if (FAILED(hr)) { qCDebug(QT_BT_WINDOWS) << "Could not obtain native characteristic" << charData.uuid - << "from service" << service->uuid; + << "from service" << service->uuid; service->setError(QLowEnergyService::CharacteristicWriteError); - return; } +} + +void QLowEnergyControllerPrivateWinRT::writeCharacteristicHelper( + const QSharedPointer<QLowEnergyServicePrivate> service, + const QLowEnergyHandle charHandle, const QByteArray &newValue, + bool writeWithResponse, GattCharacteristicComPtr characteristic) +{ ComPtr<ABI::Windows::Storage::Streams::IBufferFactory> bufferFactory; HRESULT hr = GetActivationFactory( - HStringReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(), - &bufferFactory); + HStringReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(), + &bufferFactory); CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain buffer factory", service, QLowEnergyService::CharacteristicWriteError, return) ComPtr<ABI::Windows::Storage::Streams::IBuffer> buffer; @@ -1568,9 +1629,11 @@ void QLowEnergyControllerPrivateWinRT::writeCharacteristic( hr = characteristic->WriteValueWithOptionAsync(buffer.Get(), option, &writeOp); CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could write characteristic", service, QLowEnergyService::CharacteristicWriteError, return) + const auto charData = service->characteristicList.value(charHandle); QPointer<QLowEnergyControllerPrivateWinRT> thisPtr(this); - auto writeCompletedLambda = [charData, charHandle, newValue, service, writeWithResponse, thisPtr] - (IAsyncOperation<GattCommunicationStatus> *op, AsyncStatus status) + auto writeCompletedLambda = + [charData, charHandle, newValue, service, writeWithResponse, thisPtr] + (IAsyncOperation<GattCommunicationStatus> *op, AsyncStatus status) { if (status == AsyncStatus::Canceled || status == AsyncStatus::Error) { qCDebug(QT_BT_WINDOWS) << "Characteristic" << charHandle << "write operation failed"; @@ -1582,12 +1645,12 @@ void QLowEnergyControllerPrivateWinRT::writeCharacteristic( hr = op->GetResults(&result); if (hr == E_BLUETOOTH_ATT_INVALID_ATTRIBUTE_VALUE_LENGTH) { qCDebug(QT_BT_WINDOWS) << "Characteristic" << charHandle - << "write operation was tried with invalid value length"; + << "write operation was tried with invalid value length"; service->setError(QLowEnergyService::CharacteristicWriteError); return S_OK; } - CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain characteristic write result", - service, QLowEnergyService::CharacteristicWriteError, return S_OK) + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain characteristic write result", service, + QLowEnergyService::CharacteristicWriteError, return S_OK) if (result != GattCommunicationStatus_Success) { qCDebug(QT_BT_WINDOWS) << "Characteristic" << charHandle << "write operation failed"; service->setError(QLowEnergyService::CharacteristicWriteError); @@ -1597,9 +1660,10 @@ void QLowEnergyControllerPrivateWinRT::writeCharacteristic( // empty. if (thisPtr && charData.properties & QLowEnergyCharacteristic::Read) thisPtr->updateValueOfCharacteristic(charHandle, newValue, false); - if (writeWithResponse) + if (writeWithResponse) { emit service->characteristicWritten(QLowEnergyCharacteristic(service, charHandle), newValue); + } return S_OK; }; hr = writeOp->put_Completed( @@ -1632,27 +1696,44 @@ void QLowEnergyControllerPrivateWinRT::writeDescriptor( return; } - const QLowEnergyServicePrivate::CharData charData = service->characteristicList.value(charHandle); - ComPtr<IGattCharacteristic> characteristic = getNativeCharacteristic(service->uuid, charData.uuid); - if (!characteristic) { + const auto charData = service->characteristicList.value(charHandle); + + auto characteristicCallback = [descHandle, charHandle, service, newValue, this]( + ComPtr<IGattCharacteristic> characteristic) { + writeDescriptorHelper(service, charHandle, descHandle, newValue, characteristic); + }; + + HRESULT hr = getNativeCharacteristic(service->uuid, charData.uuid, characteristicCallback); + if (FAILED(hr)) { qCDebug(QT_BT_WINDOWS) << "Could not obtain native characteristic" << charData.uuid - << "from service" << service->uuid; + << "from service" << service->uuid; service->setError(QLowEnergyService::DescriptorWriteError); - return; } +} +void QLowEnergyControllerPrivateWinRT::writeDescriptorHelper( + const QSharedPointer<QLowEnergyServicePrivate> service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descHandle, + const QByteArray &newValue, + GattCharacteristicComPtr characteristic) +{ // Get native descriptor - if (!charData.descriptorList.contains(descHandle)) - qCDebug(QT_BT_WINDOWS) << "Descriptor" << descHandle << "could not be found in Characteristic" - << charHandle; + const auto charData = service->characteristicList.value(charHandle); + if (!charData.descriptorList.contains(descHandle)) { + qCDebug(QT_BT_WINDOWS) << "Descriptor" << descHandle + << "could not be found in Characteristic" << charHandle; + } QLowEnergyServicePrivate::DescData descData = charData.descriptorList.value(descHandle); - if (descData.uuid == QBluetoothUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration)) { + if (descData.uuid == + QBluetoothUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration)) { GattClientCharacteristicConfigurationDescriptorValue value; quint16 intValue = qFromLittleEndian<quint16>(newValue); if (intValue & GattClientCharacteristicConfigurationDescriptorValue_Indicate && intValue & GattClientCharacteristicConfigurationDescriptorValue_Notify) { - qCWarning(QT_BT_WINDOWS) << "Setting both Indicate and Notify is not supported on WinRT"; + qCWarning(QT_BT_WINDOWS) << "Setting both Indicate and Notify " + "is not supported on WinRT"; value = GattClientCharacteristicConfigurationDescriptorValue( (GattClientCharacteristicConfigurationDescriptorValue_Indicate | GattClientCharacteristicConfigurationDescriptorValue_Notify)); @@ -1664,12 +1745,13 @@ void QLowEnergyControllerPrivateWinRT::writeDescriptor( value = GattClientCharacteristicConfigurationDescriptorValue_None; } else { qCDebug(QT_BT_WINDOWS) << "Descriptor" << descHandle - << "write operation failed: Invalid value"; + << "write operation failed: Invalid value"; service->setError(QLowEnergyService::DescriptorWriteError); return; } ComPtr<IAsyncOperation<enum GattCommunicationStatus>> writeOp; - HRESULT hr = characteristic->WriteClientCharacteristicConfigurationDescriptorAsync(value, &writeOp); + HRESULT hr = + characteristic->WriteClientCharacteristicConfigurationDescriptorAsync(value, &writeOp); CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not write client characteristic configuration", service, QLowEnergyService::DescriptorWriteError, return) QPointer<QLowEnergyControllerPrivateWinRT> thisPtr(this); @@ -1684,8 +1766,8 @@ void QLowEnergyControllerPrivateWinRT::writeDescriptor( GattCommunicationStatus result; HRESULT hr; hr = op->GetResults(&result); - CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain result for descriptor", - service, QLowEnergyService::DescriptorWriteError, return S_OK) + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain result for descriptor", service, + QLowEnergyService::DescriptorWriteError, return S_OK) if (result != GattCommunicationStatus_Success) { qCWarning(QT_BT_WINDOWS) << "Descriptor" << descHandle << "write operation failed"; service->setError(QLowEnergyService::DescriptorWriteError); @@ -1714,7 +1796,8 @@ void QLowEnergyControllerPrivateWinRT::writeDescriptor( CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain descriptor from Uuid", service, QLowEnergyService::DescriptorWriteError, return) ComPtr<IGattDescriptorsResult> result; - hr = QWinRTFunctions::await(op, result.GetAddressOf(), QWinRTFunctions::ProcessMainThreadEvents, 5000); + hr = QWinRTFunctions::await(op, result.GetAddressOf(), + QWinRTFunctions::ProcessMainThreadEvents, 5000); CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not await descriptor operation", service, QLowEnergyService::DescriptorWriteError, return) GattCommunicationStatus commStatus; @@ -1781,8 +1864,8 @@ void QLowEnergyControllerPrivateWinRT::writeDescriptor( GattCommunicationStatus result; HRESULT hr; hr = op->GetResults(&result); - CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain result for descriptor", - service, QLowEnergyService::DescriptorWriteError, return S_OK) + CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not obtain result for descriptor", service, + QLowEnergyService::DescriptorWriteError, return S_OK) if (result != GattCommunicationStatus_Success) { qCDebug(QT_BT_WINDOWS) << "Descriptor" << descHandle << "write operation failed"; service->setError(QLowEnergyService::DescriptorWriteError); @@ -1801,7 +1884,6 @@ void QLowEnergyControllerPrivateWinRT::writeDescriptor( service, QLowEnergyService::DescriptorWriteError, return) } - void QLowEnergyControllerPrivateWinRT::addToGenericAttributeList(const QLowEnergyServiceData &, QLowEnergyHandle) { diff --git a/src/bluetooth/qlowenergycontroller_winrt_p.h b/src/bluetooth/qlowenergycontroller_winrt_p.h index 784589c5..1f59c087 100644 --- a/src/bluetooth/qlowenergycontroller_winrt_p.h +++ b/src/bluetooth/qlowenergycontroller_winrt_p.h @@ -126,7 +126,12 @@ private: QMap<QBluetoothUuid, Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattDeviceService>> m_openedServices; Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattDeviceService> getNativeService(const QBluetoothUuid &serviceUuid); - Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattCharacteristic> getNativeCharacteristic(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid); + + using GattCharacteristicComPtr = Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattCharacteristic>; + using NativeCharacteristicCallback = std::function<void(GattCharacteristicComPtr)>; + HRESULT getNativeCharacteristic(const QBluetoothUuid &serviceUuid, + const QBluetoothUuid &charUuid, + NativeCharacteristicCallback callback); void registerForValueChanges(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid); void unregisterFromValueChanges(); @@ -146,6 +151,23 @@ private: HRESULT onServiceDiscoveryFinished(ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::GattDeviceServicesResult *> *op, ABI::Windows::Foundation::AsyncStatus status); + void readCharacteristicHelper(const QSharedPointer<QLowEnergyServicePrivate> service, + const QLowEnergyHandle charHandle, + GattCharacteristicComPtr characteristic); + void readDescriptorHelper(const QSharedPointer<QLowEnergyServicePrivate> service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle, + GattCharacteristicComPtr characteristic); + void writeCharacteristicHelper(const QSharedPointer<QLowEnergyServicePrivate> service, + const QLowEnergyHandle charHandle, const QByteArray &newValue, + bool writeWithResponse, + GattCharacteristicComPtr characteristic); + void writeDescriptorHelper(const QSharedPointer<QLowEnergyServicePrivate> service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle, + const QByteArray &newValue, + GattCharacteristicComPtr characteristic); + void clearAllServices(); void closeAndRemoveService(const QBluetoothUuid &uuid); }; |