summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIvan Solovev <ivan.solovev@qt.io>2022-08-22 17:35:50 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2022-08-26 11:33:37 +0000
commit0a1b965df26101b1e62b09e9df6061734a311132 (patch)
treebf92f3032ff35e841e2a9b00e0361bde17554c66
parent7fa049217eddb20b59272f85627bb12f4533afcb (diff)
Bluetooth Windows: refactor getNativeService
... to get rid of await() call. The function now requests the services asynchronously and executes a custom callback, passing the selected service as a parameter. After that the refactoring is quite simple: we put all the code after the getNativeService() call into a lambda, and pass this lambda as a last parameter of the updated method. Task-number: QTBUG-105556 Change-Id: If474a7446ee70059e06d46bab48771c31ba37a89 Reviewed-by: Juha Vuolle <juha.vuolle@insta.fi> Reviewed-by: Oliver Wolff <oliver.wolff@qt.io> (cherry picked from commit 595ce0449b16133d6708c7d0a17ce618f4d01724) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/bluetooth/qlowenergycontroller_winrt.cpp215
-rw-r--r--src/bluetooth/qlowenergycontroller_winrt_p.h10
2 files changed, 132 insertions, 93 deletions
diff --git a/src/bluetooth/qlowenergycontroller_winrt.cpp b/src/bluetooth/qlowenergycontroller_winrt.cpp
index 14eddfbb..88c93f4f 100644
--- a/src/bluetooth/qlowenergycontroller_winrt.cpp
+++ b/src/bluetooth/qlowenergycontroller_winrt.cpp
@@ -751,108 +751,129 @@ void QLowEnergyControllerPrivateWinRT::disconnectFromDevice()
emit q->disconnected();
}
-ComPtr<IGattDeviceService> QLowEnergyControllerPrivateWinRT::getNativeService(
- const QBluetoothUuid &serviceUuid)
+HRESULT QLowEnergyControllerPrivateWinRT::getNativeService(const QBluetoothUuid &serviceUuid,
+ NativeServiceCallback callback)
{
- if (m_openedServices.contains(serviceUuid))
- return m_openedServices.value(serviceUuid);
+ if (m_openedServices.contains(serviceUuid)) {
+ callback(m_openedServices.value(serviceUuid));
+ return S_OK;
+ }
ComPtr<IBluetoothLEDevice3> device3;
HRESULT hr = mDevice.As(&device3);
- RETURN_IF_FAILED("Could not convert to IBluetoothDevice3", return nullptr);
+ RETURN_IF_FAILED("Could not convert to IBluetoothDevice3", return hr);
ComPtr<IAsyncOperation<GattDeviceServicesResult *>> servicesResultOperation;
hr = device3->GetGattServicesForUuidAsync(serviceUuid, &servicesResultOperation);
- RETURN_IF_FAILED("Could not start async services request", return nullptr);
+ RETURN_IF_FAILED("Could not start async services request", return hr);
- ComPtr<IGattDeviceServicesResult> result;
QPointer<QLowEnergyControllerPrivateWinRT> thisPtr(this);
- hr = QWinRTFunctions::await(servicesResultOperation, result.GetAddressOf(),
- QWinRTFunctions::ProcessMainThreadEvents, 5000);
- // Guard against the object being deleted while we are awaiting.
- if (!thisPtr) {
- qCWarning(QT_BT_WINDOWS) << "LE controller was removed while awaiting";
- return nullptr;
- }
- RETURN_IF_FAILED("Failed to get result of async services request", return nullptr);
+ hr = servicesResultOperation->put_Completed(
+ Callback<IAsyncOperationCompletedHandler<
+ GenericAttributeProfile::GattDeviceServicesResult *>>(
+ [thisPtr, callback, &serviceUuid](
+ IAsyncOperation<GattDeviceServicesResult *> *op, AsyncStatus status)
+ {
+ if (thisPtr) {
+ if (status != AsyncStatus::Completed) {
+ qCDebug(QT_BT_WINDOWS) << "Failed to get result of async service request";
+ return S_OK;
+ }
+ ComPtr<IGattDeviceServicesResult> result;
+ ComPtr<IVectorView<GattDeviceService *>> deviceServices;
+ HRESULT hr = op->GetResults(&result);
+ RETURN_IF_FAILED("Failed to get result of async service request", return hr);
- ComPtr<IVectorView<GattDeviceService *>> services;
- hr = result->get_Services(&services);
- RETURN_IF_FAILED("Failed to extract services from the result", return nullptr);
+ ComPtr<IVectorView<GattDeviceService *>> services;
+ hr = result->get_Services(&services);
+ RETURN_IF_FAILED("Failed to extract services from the result", return hr);
- uint servicesCount = 0;
- hr = services->get_Size(&servicesCount);
- RETURN_IF_FAILED("Failed to extract services count", return nullptr);
+ uint servicesCount = 0;
+ hr = services->get_Size(&servicesCount);
+ RETURN_IF_FAILED("Failed to extract services count", return hr);
- if (servicesCount > 0) {
- if (servicesCount > 1) {
- qWarning() << "getNativeService: more than one service detected for UUID" << serviceUuid
- << "The first service will be used.";
+ if (servicesCount > 0) {
+ if (servicesCount > 1) {
+ qWarning() << "getNativeService: more than one service detected for UUID"
+ << serviceUuid << "The first service will be used.";
+ }
+ ComPtr<IGattDeviceService> service;
+ hr = services->GetAt(0, &service);
+ if (FAILED(hr)) {
+ qCDebug(QT_BT_WINDOWS) << "Could not obtain native service for Uuid"
+ << serviceUuid;
+ }
+ if (service) {
+ thisPtr->m_openedServices[serviceUuid] = service;
+ callback(service); // Use the service in a custom callback
+ }
+ } else {
+ qCWarning(QT_BT_WINDOWS) << "No services found for Uuid" << serviceUuid;
+ }
+ } else {
+ qCWarning(QT_BT_WINDOWS) << "LE controller was removed while getting native service";
}
- ComPtr<IGattDeviceService> service;
- hr = services->GetAt(0, &service);
- if (FAILED(hr))
- qCDebug(QT_BT_WINDOWS) << "Could not obtain native service for Uuid" << serviceUuid;
- if (service)
- m_openedServices[serviceUuid] = service;
- return service;
- } else {
- qCWarning(QT_BT_WINDOWS) << "No services found for Uuid" << serviceUuid;
- }
- return nullptr;
+ return S_OK;
+ }).Get());
+
+ return hr;
}
HRESULT QLowEnergyControllerPrivateWinRT::getNativeCharacteristic(
const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid,
NativeCharacteristicCallback callback)
{
- ComPtr<IGattDeviceService> service = getNativeService(serviceUuid);
- if (!service)
- return -1;
-
- ComPtr<IGattDeviceService3> service3;
- HRESULT hr = service.As(&service3);
- RETURN_IF_FAILED("Could not cast service to service3", return hr);
-
- 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;
+ auto serviceCallback = [thisPtr, callback, charUuid](ComPtr<IGattDeviceService> service) {
+ ComPtr<IGattDeviceService3> service3;
+ HRESULT hr = service.As(&service3);
+ RETURN_IF_FAILED("Could not cast service to service3", return);
+
+ ComPtr<IAsyncOperation<GattCharacteristicsResult *>> characteristicRequestOp;
+ hr = service3->GetCharacteristicsForUuidAsync(charUuid, &characteristicRequestOp);
+
+ 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 S_OK;
+ }
+ ComPtr<IVectorView<GattCharacteristic *>> characteristics;
+ hr = result->get_Characteristics(&characteristics);
+ RETURN_IF_FAILED("Could not obtain characteristic list.", return S_OK);
+ uint size;
+ hr = characteristics->get_Size(&size);
+ RETURN_IF_FAILED("Could not obtain characteristic list's size.", return S_OK);
+ 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 S_OK);
+ if (characteristic)
+ callback(characteristic); // use the characteristic in a custom callback
}
- 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 S_OK;
+ }).Get());
+ };
+
+ HRESULT hr = getNativeService(serviceUuid, serviceCallback);
+ if (FAILED(hr))
+ qCDebug(QT_BT_WINDOWS) << "Failed to get native service for" << serviceUuid;
return hr;
}
@@ -1198,12 +1219,19 @@ void QLowEnergyControllerPrivateWinRT::discoverServiceDetails(
// clear the cache to rediscover service details
closeAndRemoveService(service);
- ComPtr<IGattDeviceService> deviceService = getNativeService(service);
- if (!deviceService) {
+ auto serviceCallback = [service, mode, this](ComPtr<IGattDeviceService> deviceService) {
+ discoverServiceDetailsHelper(service, mode, deviceService);
+ };
+
+ HRESULT hr = getNativeService(service, serviceCallback);
+ if (FAILED(hr))
qCDebug(QT_BT_WINDOWS) << "Could not obtain native service for uuid " << service;
- return;
- }
+}
+void QLowEnergyControllerPrivateWinRT::discoverServiceDetailsHelper(
+ const QBluetoothUuid &service, QLowEnergyService::DiscoveryMode mode,
+ GattDeviceServiceComPtr deviceService)
+{
auto reactOnDiscoveryError = [](QSharedPointer<QLowEnergyServicePrivate> service,
const QString &msg)
{
@@ -1214,7 +1242,7 @@ void QLowEnergyControllerPrivateWinRT::discoverServiceDetails(
//update service data
QSharedPointer<QLowEnergyServicePrivate> pointer = serviceList.value(service);
qCDebug(QT_BT_WINDOWS_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread"
- << QThread::currentThread();
+ << QThread::currentThread();
pointer->setState(QLowEnergyService::RemoteServiceDiscovering);
ComPtr<IGattDeviceService3> deviceService3;
HRESULT hr = deviceService.As(&deviceService3);
@@ -1225,34 +1253,39 @@ void QLowEnergyControllerPrivateWinRT::discoverServiceDetails(
ComPtr<IAsyncOperation<GattDeviceServicesResult *>> op;
hr = deviceService3->GetIncludedServicesAsync(&op);
if (FAILED(hr)) {
- reactOnDiscoveryError(pointer, QStringLiteral("Could not obtain included service list: %1").arg(hr));
+ reactOnDiscoveryError(pointer,
+ QStringLiteral("Could not obtain included service list: %1").arg(hr));
return;
}
ComPtr<IGattDeviceServicesResult> result;
hr = QWinRTFunctions::await(op, result.GetAddressOf());
if (FAILED(hr)) {
- reactOnDiscoveryError(pointer, QStringLiteral("Could not await service operation: %1").arg(hr));
+ reactOnDiscoveryError(pointer,
+ QStringLiteral("Could not await service operation: %1").arg(hr));
return;
}
GattCommunicationStatus status;
hr = result->get_Status(&status);
if (FAILED(hr) || status != GattCommunicationStatus_Success) {
reactOnDiscoveryError(pointer,
- QStringLiteral("Obtaining list of included services failed: %1").arg(hr));
+ QStringLiteral("Obtaining list of included services failed: %1").
+ arg(hr));
return;
}
ComPtr<IVectorView<GattDeviceService *>> deviceServices;
hr = result->get_Services(&deviceServices);
if (FAILED(hr)) {
reactOnDiscoveryError(pointer,
- QStringLiteral("Could not obtain service list from result: %1").arg(hr));
+ QStringLiteral("Could not obtain service list from result: %1").
+ arg(hr));
return;
}
uint serviceCount;
hr = deviceServices->get_Size(&serviceCount);
if (FAILED(hr)) {
reactOnDiscoveryError(pointer,
- QStringLiteral("Could not obtain included service list's size: %1").arg(hr));
+ QStringLiteral("Could not obtain included service list's size: %1").
+ arg(hr));
return;
}
for (uint i = 0; i < serviceCount; ++i) {
diff --git a/src/bluetooth/qlowenergycontroller_winrt_p.h b/src/bluetooth/qlowenergycontroller_winrt_p.h
index ef75c6fb..984e2e77 100644
--- a/src/bluetooth/qlowenergycontroller_winrt_p.h
+++ b/src/bluetooth/qlowenergycontroller_winrt_p.h
@@ -159,9 +159,12 @@ private:
EventRegistrationToken token;
};
QList<ValueChangedEntry> mValueChangedTokens;
- 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);
+ using GattDeviceServiceComPtr = Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattDeviceService>;
+ QMap<QBluetoothUuid, GattDeviceServiceComPtr> m_openedServices;
+
+ using NativeServiceCallback = std::function<void(GattDeviceServiceComPtr)>;
+ HRESULT getNativeService(const QBluetoothUuid &serviceUuid, NativeServiceCallback callback);
using GattCharacteristicComPtr = Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattCharacteristic>;
using NativeCharacteristicCallback = std::function<void(GattCharacteristicComPtr)>;
@@ -203,6 +206,9 @@ private:
const QLowEnergyHandle descriptorHandle,
const QByteArray &newValue,
GattCharacteristicComPtr characteristic);
+ void discoverServiceDetailsHelper(const QBluetoothUuid &service,
+ QLowEnergyService::DiscoveryMode mode,
+ GattDeviceServiceComPtr deviceService);
void clearAllServices();
void closeAndRemoveService(const QBluetoothUuid &uuid);