summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIvan Solovev <ivan.solovev@qt.io>2022-08-22 17:59:06 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2022-08-26 11:33:31 +0000
commit7fa049217eddb20b59272f85627bb12f4533afcb (patch)
treeffbed7f1903b9c6f2edc4f9593061e6c7ee773d6
parentd369d77c8ec3cae31a7b08541958507132dd6036 (diff)
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 Change-Id: I1164bbc677d3549ef930243fd645eed344e27b7c Reviewed-by: Juha Vuolle <juha.vuolle@insta.fi> Reviewed-by: Oliver Wolff <oliver.wolff@qt.io> (cherry picked from commit 5fee999b242fadc9efca5423aa1296486aa5a880) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/bluetooth/qlowenergycontroller_winrt.cpp286
-rw-r--r--src/bluetooth/qlowenergycontroller_winrt_p.h24
-rw-r--r--tests/manual/qlowenergycontroller/tst_qlowenergycontroller_device.cpp8
3 files changed, 213 insertions, 105 deletions
diff --git a/src/bluetooth/qlowenergycontroller_winrt.cpp b/src/bluetooth/qlowenergycontroller_winrt.cpp
index 32900618..14eddfbb 100644
--- a/src/bluetooth/qlowenergycontroller_winrt.cpp
+++ b/src/bluetooth/qlowenergycontroller_winrt.cpp
@@ -802,41 +802,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,
@@ -852,23 +870,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()
@@ -1326,22 +1348,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) {
@@ -1352,11 +1385,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);
@@ -1390,21 +1423,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",
@@ -1420,12 +1469,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) {
@@ -1440,7 +1489,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;
}
@@ -1450,7 +1499,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(
@@ -1470,7 +1519,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)
@@ -1530,7 +1580,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 *>>(
@@ -1567,18 +1617,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;
@@ -1604,9 +1665,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";
@@ -1618,12 +1681,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);
@@ -1633,9 +1696,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(
@@ -1668,27 +1732,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));
@@ -1700,12 +1781,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);
@@ -1720,8 +1802,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);
@@ -1750,7 +1832,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;
@@ -1817,8 +1900,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);
@@ -1837,7 +1920,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 91feace9..ef75c6fb 100644
--- a/src/bluetooth/qlowenergycontroller_winrt_p.h
+++ b/src/bluetooth/qlowenergycontroller_winrt_p.h
@@ -162,7 +162,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();
@@ -182,6 +187,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);
};
diff --git a/tests/manual/qlowenergycontroller/tst_qlowenergycontroller_device.cpp b/tests/manual/qlowenergycontroller/tst_qlowenergycontroller_device.cpp
index 55c4cbfc..e71eff4d 100644
--- a/tests/manual/qlowenergycontroller/tst_qlowenergycontroller_device.cpp
+++ b/tests/manual/qlowenergycontroller/tst_qlowenergycontroller_device.cpp
@@ -638,7 +638,9 @@ void tst_qlowenergycontroller_device::testNotificationAndIndication()
service->writeDescriptor(cccd, newValue);
QTRY_VERIFY(cccdWritten);
- // check that there are no updates:
+ // wait for a moment in case there is a value change just happening,
+ // then check that there are no more notifications:
+ QTest::qWait(200);
oldvalue = characteristic.value();
for (int i = 0; i < 3; ++i) {
QTest::qWait(100);
@@ -666,7 +668,9 @@ void tst_qlowenergycontroller_device::testNotificationAndIndication()
service->writeDescriptor(cccd, newValue);
QTRY_VERIFY(cccdWritten);
- // check that there are no indications:
+ // wait for a moment in case there is a value change just happening,
+ // then check that there are no more indications:
+ QTest::qWait(200);
oldvalue = characteristic.value();
for (int i = 0; i < 3; ++i) {
QTest::qWait(100);