7#include <QtBluetooth/qbluetoothlocaldevice.h>
8#include <QtBluetooth/QLowEnergyCharacteristicData>
9#include <QtBluetooth/QLowEnergyDescriptorData>
10#include <QtBluetooth/private/qbluetoothutils_winrt_p.h>
11#include <QtBluetooth/QLowEnergyService>
13#include <QtCore/QtEndian>
14#include <QtCore/QLoggingCategory>
15#include <QtCore/private/qfunctions_winrt_p.h>
16#include <QtCore/QDeadlineTimer>
20#include <windows.devices.enumeration.h>
21#include <windows.devices.bluetooth.h>
22#include <windows.devices.bluetooth.genericattributeprofile.h>
23#include <windows.foundation.collections.h>
24#include <windows.foundation.metadata.h>
25#include <windows.storage.streams.h>
28using namespace Microsoft::WRL::Wrappers;
30using namespace ABI::Windows::Foundation::Collections;
31using namespace ABI::Windows::Foundation::Metadata;
34using namespace ABI::Windows::Devices::Bluetooth::GenericAttributeProfile;
35using namespace ABI::Windows::Devices::Enumeration;
40typedef ITypedEventHandler<BluetoothLEDevice *, IInspectable *>
StatusHandler;
41typedef ITypedEventHandler<GattSession *, IInspectable *>
MtuHandler;
46#define EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED(hr) \
48 emitErrorAndQuitThread(hr); \
52#define EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, message) \
54 emitErrorAndQuitThread(message); \
58#define WARN_AND_CONTINUE_IF_FAILED(hr, msg) \
60 qCWarning(QT_BT_WINDOWS) << msg; \
64#define DEC_CHAR_COUNT_AND_CONTINUE_IF_FAILED(hr, msg) \
66 qCWarning(QT_BT_WINDOWS) << msg; \
67 --mCharacteristicsCountToBeDiscovered; \
71#define CHECK_FOR_DEVICE_CONNECTION_ERROR_IMPL(this, hr, msg, ret) \
73 this->handleConnectionError(msg); \
77#define CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, msg, ret) \
78 CHECK_FOR_DEVICE_CONNECTION_ERROR_IMPL(this, hr, msg, ret)
80#define CHECK_HR_AND_SET_SERVICE_ERROR(hr, msg, service, error, ret) \
82 qCDebug(QT_BT_WINDOWS) << msg; \
83 service->setError(error); \
93 bool isWCharString =
false)
97 hr = gattResult->get_Value(&
buffer);
98 if (FAILED(hr) || !
buffer) {
99 qCWarning(QT_BT_WINDOWS) <<
"Could not obtain buffer from GattReadResult";
109 HRESULT hr = service.As(&closableService);
110 RETURN_IF_FAILED(
"Could not cast type to closable",
return);
111 hr = closableService->Close();
112 RETURN_IF_FAILED(
"Close() call failed",
return);
124 qCDebug(QT_BT_WINDOWS) << __FUNCTION__;
131 qCDebug(QT_BT_WINDOWS) << __FUNCTION__;
140 qCDebug(QT_BT_WINDOWS) << __FUNCTION__;
145 hr = QWinRTFunctions::await(characteristicsOp, characteristicsResult.GetAddressOf(),
146 QWinRTFunctions::ProcessMainThreadEvents, 5000,
149 GattCommunicationStatus status;
150 hr = characteristicsResult->get_Status(&status);
152 if (status != GattCommunicationStatus_Success) {
153 emitErrorAndQuitThread(
QLatin1String(
"Could not obtain char list"));
157 hr = characteristicsResult->get_Characteristics(&characteristics);
160 uint characteristicsCount;
161 hr = characteristics->get_Size(&characteristicsCount);
167 hr = characteristics->GetAt(
i, &characteristic);
169 qCWarning(QT_BT_WINDOWS) <<
"Could not obtain characteristic at" <<
i;
175 hr = characteristic.As(&characteristic3);
177 qCWarning(QT_BT_WINDOWS) <<
"Could not cast characteristic";
187 hr = characteristic3->GetDescriptorsAsync(&descAsyncOp);
191 hr = QWinRTFunctions::await(descAsyncOp, descResult.GetAddressOf(),
192 QWinRTFunctions::ProcessMainThreadEvents, 5000,
197 hr = characteristic->get_AttributeHandle(&
handle);
199 hr,
"Could not obtain characteristic's attribute handle")
207 hr = characteristic->get_Uuid(&guuid);
211 hr = characteristic->get_CharacteristicProperties(&
properties);
213 "Could not obtain characteristic's properties")
218 hr = characteristic->ReadValueWithCacheModeAsync(BluetoothCacheMode_Uncached,
222 hr = QWinRTFunctions::await(readOp, readResult.GetAddressOf(),
223 QWinRTFunctions::ProcessMainThreadEvents, 5000,
226 "Could not obtain characteristic read result")
228 qCWarning(QT_BT_WINDOWS) <<
"Characteristic read result is null";
236 GattCommunicationStatus commStatus;
237 hr = descResult->get_Status(&commStatus);
238 if (FAILED(hr) || commStatus != GattCommunicationStatus_Success) {
239 qCWarning(QT_BT_WINDOWS) <<
"Descriptor operation failed";
244 hr = descResult->get_Descriptors(&descriptors);
247 uint descriptorCount;
248 hr = descriptors->get_Size(&descriptorCount);
253 hr = descriptors->GetAt(
j, &descriptor);
256 hr = descriptor->get_AttributeHandle(&descHandle);
259 hr = descriptor->get_Uuid(&descriptorUuid);
266 hr = characteristic->ReadClientCharacteristicConfigurationDescriptorAsync(
270 hr = QWinRTFunctions::await(readOp, readResult.GetAddressOf(),
271 QWinRTFunctions::ProcessMainThreadEvents, 5000,
274 GattClientCharacteristicConfigurationDescriptorValue
value;
275 hr = readResult->get_ClientCharacteristicConfigurationDescriptor(&
value);
277 "Could not get descriptor value from result")
279 bool correct =
false;
280 if (
value & GattClientCharacteristicConfigurationDescriptorValue_Indicate) {
281 result |= GattClientCharacteristicConfigurationDescriptorValue_Indicate;
284 if (
value & GattClientCharacteristicConfigurationDescriptorValue_Notify) {
285 result |= GattClientCharacteristicConfigurationDescriptorValue_Notify;
288 if (
value == GattClientCharacteristicConfigurationDescriptorValue_None)
300 hr = descriptor->ReadValueWithCacheModeAsync(BluetoothCacheMode_Uncached,
304 hr = QWinRTFunctions::await(readOp, readResult.GetAddressOf(),
305 QWinRTFunctions::ProcessMainThreadEvents, 5000,
320 checkAllCharacteristicsDiscovered();
329 void checkAllCharacteristicsDiscovered();
330 void emitErrorAndQuitThread(
HRESULT hr);
352void QWinRTLowEnergyServiceHandler::checkAllCharacteristicsDiscovered()
361void QWinRTLowEnergyServiceHandler::emitErrorAndQuitThread(
HRESULT hr)
366void QWinRTLowEnergyServiceHandler::emitErrorAndQuitThread(
const QString &
error)
379 qCDebug(QT_BT_WINDOWS) << __FUNCTION__;
385 qCDebug(QT_BT_WINDOWS) << __FUNCTION__;
387 mGattSession.Reset();
391 if (mInitialized == S_OK || mInitialized == S_FALSE)
404 void connectToPairedDevice();
405 void connectToUnpairedDevice();
407 void emitErrorAndQuitThread(
const char *
error);
408 void emitConnectedAndQuitThread();
413 bool mAbortConnection =
false;
414 HRESULT mInitialized = E_UNEXPECTED;
419 qCDebug(QT_BT_WINDOWS) << __FUNCTION__;
420 mInitialized = CoInitializeEx(NULL, COINIT_MULTITHREADED);
423 auto earlyExit = [
this]() {
return mAbortConnection; };
425 HRESULT hr = GetActivationFactory(
426 HString::MakeReference(RuntimeClass_Windows_Devices_Bluetooth_BluetoothLEDevice).Get(),
430 hr = deviceStatics->FromBluetoothAddressAsync(mAddress.toUInt64(), &deviceFromIdOperation);
432 hr = QWinRTFunctions::await(deviceFromIdOperation, mDevice.GetAddressOf(),
433 QWinRTFunctions::ProcessMainThreadEvents, 5000, earlyExit);
434 if (FAILED(hr) || !mDevice) {
435 emitErrorAndQuitThread(
"Could not find LE device");
441 hr = mDevice.As(&device4);
445 hr = device4->get_BluetoothDeviceId(&deviceId);
450 hr = GetActivationFactory(
451 HString::MakeReference(
452 RuntimeClass_Windows_Devices_Bluetooth_GenericAttributeProfile_GattSession)
459 hr = sessionStatics->FromDeviceIdAsync(deviceId.Get(), &gattSessionFromIdOperation);
461 hr = QWinRTFunctions::await(gattSessionFromIdOperation, mGattSession.GetAddressOf(),
462 QWinRTFunctions::ProcessMainThreadEvents, 5000, earlyExit);
465 BluetoothConnectionStatus status;
466 hr = mDevice->get_ConnectionStatus(&status);
468 if (status == BluetoothConnectionStatus::BluetoothConnectionStatus_Connected) {
469 emitConnectedAndQuitThread();
476 connectToUnpairedDevice();
478 connectToPairedDevice();
483 mAbortConnection =
true;
492void QWinRTLowEnergyConnectionHandler::connectToPairedDevice()
494 qCDebug(QT_BT_WINDOWS) << __FUNCTION__;
496 HRESULT hr = mDevice.As(&device3);
499 auto earlyExit = [
this]() {
return mAbortConnection; };
502 hr = device3->GetGattServicesAsync(&deviceServicesOp);
505 hr = QWinRTFunctions::await(deviceServicesOp, deviceServicesResult.GetAddressOf(),
506 QWinRTFunctions::ProcessThreadEvents, 5000, earlyExit);
509 GattCommunicationStatus commStatus;
510 hr = deviceServicesResult->get_Status(&commStatus);
511 if (FAILED(hr) || commStatus != GattCommunicationStatus_Success) {
512 emitErrorAndQuitThread(
"Service operation failed");
517 hr = deviceServicesResult->get_Services(&deviceServices);
520 hr = deviceServices->get_Size(&serviceCount);
523 if (serviceCount == 0) {
524 emitErrorAndQuitThread(
"Found devices without services");
530 for (
uint i = 0;
i < serviceCount; ++
i) {
532 hr = deviceServices->GetAt(
i, &service);
538 hr = service3->GetCharacteristicsAsync(&characteristicsOp);
541 hr = QWinRTFunctions::await(characteristicsOp, characteristicsResult.GetAddressOf(),
542 QWinRTFunctions::ProcessThreadEvents, 5000, earlyExit);
544 GattCommunicationStatus commStatus;
545 hr = characteristicsResult->get_Status(&commStatus);
546 if (FAILED(hr) || commStatus != GattCommunicationStatus_Success) {
547 qCWarning(QT_BT_WINDOWS) <<
"Characteristic operation failed";
551 hr = characteristicsResult->get_Characteristics(&characteristics);
552 if (hr == E_ACCESSDENIED) {
555 emitErrorAndQuitThread(
"Could not obtain characteristic list. "
556 "Please check your manifest capabilities");
560 uint characteristicsCount;
561 hr = characteristics->get_Size(&characteristicsCount);
563 "Could not obtain characteristic list's size");
564 for (
uint j = 0;
j < characteristicsCount; ++
j) {
566 hr = characteristics->GetAt(
j, &characteristic);
569 GattCharacteristicProperties
props;
570 hr = characteristic->get_CharacteristicProperties(&
props);
572 hr,
"Could not obtain characteristic's properties");
573 if (!(
props & GattCharacteristicProperties_Read))
575 hr = characteristic->ReadValueWithCacheModeAsync(
576 BluetoothCacheMode::BluetoothCacheMode_Uncached, &op);
581 hr = QWinRTFunctions::await(op,
result.GetAddressOf(),
582 QWinRTFunctions::ProcessThreadEvents, 5000, earlyExit);
585 if (hr == E_ILLEGAL_METHOD_CALL)
592 qCDebug(QT_BT_WINDOWS) <<
"Problem reading value";
596 emitConnectedAndQuitThread();
604 emitErrorAndQuitThread(
"Connect to device failed due to timeout!");
607void QWinRTLowEnergyConnectionHandler::connectToUnpairedDevice()
609 qCDebug(QT_BT_WINDOWS) << __FUNCTION__;
611 HRESULT hr = mDevice.As(&device3);
614 auto earlyExit = [
this]() {
return mAbortConnection; };
618 hr = device3->GetGattServicesAsync(&deviceServicesOp);
620 hr = QWinRTFunctions::await(deviceServicesOp, deviceServicesResult.GetAddressOf(),
621 QWinRTFunctions::ProcessMainThreadEvents, 0, earlyExit);
624 GattCommunicationStatus commStatus;
625 hr = deviceServicesResult->get_Status(&commStatus);
626 if (commStatus == GattCommunicationStatus_Unreachable)
629 if (FAILED(hr) || commStatus != GattCommunicationStatus_Success) {
630 emitErrorAndQuitThread(
"Service operation failed");
634 emitConnectedAndQuitThread();
640 emitErrorAndQuitThread(
"Connect to device failed due to timeout!");
643void QWinRTLowEnergyConnectionHandler::emitErrorAndQuitThread(
const QString &
error)
649void QWinRTLowEnergyConnectionHandler::emitErrorAndQuitThread(
const char *
error)
654void QWinRTLowEnergyConnectionHandler::emitConnectedAndQuitThread()
665 this, &QLowEnergyControllerPrivateWinRT::handleCharacteristicChanged,
671 unregisterFromStatusChanges();
672 unregisterFromValueChanges();
681 qCDebug(QT_BT_WINDOWS) << __FUNCTION__;
683 qCWarning(QT_BT_WINDOWS) <<
"Invalid/null remote device address";
701 if (!
device || !session) {
702 handleConnectionError(
"Failed to get device or gatt service");
706 mGattSession = session;
708 if (!registerForStatusChanges() || !registerForMtuChanges()) {
709 handleConnectionError(
"Failed to register for changes");
722 qCDebug(QT_BT_WINDOWS) << __FUNCTION__;
726 unregisterFromValueChanges();
727 unregisterFromStatusChanges();
728 unregisterFromMtuChanges();
730 mGattSession =
nullptr;
733 emit q->disconnected();
737 NativeServiceCallback callback)
739 if (m_openedServices.contains(serviceUuid)) {
740 callback(m_openedServices.value(serviceUuid));
745 HRESULT hr = mDevice.As(&device3);
746 RETURN_IF_FAILED(
"Could not convert to IBluetoothDevice3",
return hr);
749 hr = device3->GetGattServicesForUuidAsync(serviceUuid, &servicesResultOperation);
750 RETURN_IF_FAILED(
"Could not start async services request",
return hr);
753 hr = servicesResultOperation->put_Completed(
754 Callback<IAsyncOperationCompletedHandler<
755 GenericAttributeProfile::GattDeviceServicesResult *>>(
756 [thisPtr, callback, &serviceUuid](
760 if (status != AsyncStatus::Completed) {
761 qCDebug(QT_BT_WINDOWS) <<
"Failed to get result of async service request";
767 RETURN_IF_FAILED(
"Failed to get result of async service request",
return hr);
771 RETURN_IF_FAILED(
"Failed to extract services from the result",
return hr);
773 uint servicesCount = 0;
774 hr =
services->get_Size(&servicesCount);
775 RETURN_IF_FAILED(
"Failed to extract services count",
return hr);
777 if (servicesCount > 0) {
778 if (servicesCount > 1) {
779 qWarning() <<
"getNativeService: more than one service detected for UUID"
780 << serviceUuid <<
"The first service will be used.";
785 qCDebug(QT_BT_WINDOWS) <<
"Could not obtain native service for Uuid"
789 thisPtr->m_openedServices[serviceUuid] =
service;
793 qCWarning(QT_BT_WINDOWS) <<
"No services found for Uuid" << serviceUuid;
796 qCWarning(QT_BT_WINDOWS) <<
"LE controller was removed while getting native service";
804HRESULT QLowEnergyControllerPrivateWinRT::getNativeCharacteristic(
806 NativeCharacteristicCallback callback)
812 RETURN_IF_FAILED(
"Could not cast service to service3",
return);
815 hr = service3->GetCharacteristicsForUuidAsync(charUuid, &characteristicRequestOp);
817 hr = characteristicRequestOp->put_Completed(
818 Callback<IAsyncOperationCompletedHandler<GattCharacteristicsResult *>>(
823 if (status != AsyncStatus::Completed) {
824 qCDebug(QT_BT_WINDOWS) <<
"Failed to get result of async characteristic "
830 RETURN_IF_FAILED(
"Failed to get result of async characteristic operation",
832 GattCommunicationStatus status;
833 hr =
result->get_Status(&status);
834 if (FAILED(hr) || status != GattCommunicationStatus_Success) {
835 qErrnoWarning(hr,
"Native characteristic operation failed.");
839 hr =
result->get_Characteristics(&characteristics);
840 RETURN_IF_FAILED(
"Could not obtain characteristic list.",
return S_OK);
842 hr = characteristics->get_Size(&
size);
843 RETURN_IF_FAILED(
"Could not obtain characteristic list's size.",
return S_OK);
847 hr = characteristics->GetAt(0, &characteristic);
848 RETURN_IF_FAILED(
"Could not obtain first characteristic for service",
return S_OK);
850 callback(characteristic);
856 HRESULT hr = getNativeService(serviceUuid, serviceCallback);
858 qCDebug(QT_BT_WINDOWS) <<
"Failed to get native service for" << serviceUuid;
863void QLowEnergyControllerPrivateWinRT::registerForValueChanges(
const QBluetoothUuid &serviceUuid,
866 qCDebug(QT_BT_WINDOWS) <<
"Registering characteristic" << charUuid <<
"in service"
867 << serviceUuid <<
"for value changes";
868 for (
const ValueChangedEntry &
entry :
std::as_const(mValueChangedTokens)) {
871 hr =
entry.characteristic->get_Uuid(&guuid);
877 auto callback = [
this, charUuid, serviceUuid](
ComPtr<IGattCharacteristic> characteristic) {
878 EventRegistrationToken
token;
880 hr = characteristic->add_ValueChanged(
881 Callback<ValueChangedHandler>(
882 this, &QLowEnergyControllerPrivateWinRT::onValueChange).Get(),
884 RETURN_IF_FAILED(
"Could not register characteristic for value changes",
return)
885 mValueChangedTokens.
append(ValueChangedEntry(characteristic,
token));
886 qCDebug(QT_BT_WINDOWS) <<
"Characteristic" << charUuid <<
"in service"
887 << serviceUuid <<
"registered for value changes";
890 HRESULT hr = getNativeCharacteristic(serviceUuid, charUuid, callback);
892 qCDebug(QT_BT_WINDOWS).nospace() <<
"Could not obtain native characteristic "
893 << charUuid <<
" from service " << serviceUuid
894 <<
". Qt will not be able to signal"
895 <<
" changes for this characteristic.";
899void QLowEnergyControllerPrivateWinRT::unregisterFromValueChanges()
901 qCDebug(QT_BT_WINDOWS) <<
"Unregistering " << mValueChangedTokens.
size() <<
" value change tokens";
903 for (
const ValueChangedEntry &
entry :
std::as_const(mValueChangedTokens)) {
904 if (!
entry.characteristic) {
905 qCWarning(QT_BT_WINDOWS) <<
"Unregistering from value changes for characteristic failed."
906 <<
"Characteristic has been deleted";
909 hr =
entry.characteristic->remove_ValueChanged(
entry.token);
911 qCWarning(QT_BT_WINDOWS) <<
"Unregistering from value changes for characteristic failed.";
913 mValueChangedTokens.
clear();
916HRESULT QLowEnergyControllerPrivateWinRT::onValueChange(IGattCharacteristic *characteristic, IGattValueChangedEventArgs *
args)
920 hr = characteristic->get_AttributeHandle(&
handle);
921 RETURN_IF_FAILED(
"Could not obtain characteristic's handle",
return S_OK)
924 RETURN_IF_FAILED(
"Could not obtain characteristic's value",
return S_OK)
928HRESULT QLowEnergyControllerPrivateWinRT::onMtuChange(IGattSession *session, IInspectable *
args)
930 qCDebug(QT_BT_WINDOWS) << __FUNCTION__;
931 if (session != mGattSession.Get()) {
932 qCWarning(QT_BT_WINDOWS) <<
"Got MTU changed event for wrong or outdated GattSession.";
941bool QLowEnergyControllerPrivateWinRT::registerForStatusChanges()
946 qCDebug(QT_BT_WINDOWS) << __FUNCTION__;
949 hr = mDevice->add_ConnectionStatusChanged(
950 Callback<StatusHandler>(
this, &QLowEnergyControllerPrivateWinRT::onStatusChange).Get(),
951 &mStatusChangedToken);
952 RETURN_IF_FAILED(
"Could not add status callback",
return false)
956void QLowEnergyControllerPrivateWinRT::unregisterFromStatusChanges()
958 qCDebug(QT_BT_WINDOWS) << __FUNCTION__;
959 if (mDevice && mStatusChangedToken.value) {
960 mDevice->remove_ConnectionStatusChanged(mStatusChangedToken);
961 mStatusChangedToken.value = 0;
965bool QLowEnergyControllerPrivateWinRT::registerForMtuChanges()
967 if (!mDevice || !mGattSession)
970 qCDebug(QT_BT_WINDOWS) << __FUNCTION__;
973 hr = mGattSession->add_MaxPduSizeChanged(
974 Callback<MtuHandler>(
this, &QLowEnergyControllerPrivateWinRT::onMtuChange).Get(),
976 RETURN_IF_FAILED(
"Could not add MTU callback",
return false)
980void QLowEnergyControllerPrivateWinRT::unregisterFromMtuChanges()
982 qCDebug(QT_BT_WINDOWS) << __FUNCTION__;
983 if (mDevice && mGattSession && mMtuChangedToken.value) {
984 mGattSession->remove_MaxPduSizeChanged(mMtuChangedToken);
985 mMtuChangedToken.value = 0;
989HRESULT QLowEnergyControllerPrivateWinRT::onStatusChange(IBluetoothLEDevice *dev, IInspectable *)
992 BluetoothConnectionStatus status;
994 hr = dev->get_ConnectionStatus(&status);
995 RETURN_IF_FAILED(
"Could not obtain connection status",
return S_OK)
997 && status == BluetoothConnectionStatus::BluetoothConnectionStatus_Connected) {
1001 && status == BluetoothConnectionStatus::BluetoothConnectionStatus_Disconnected) {
1003 unregisterFromValueChanges();
1004 unregisterFromStatusChanges();
1005 unregisterFromMtuChanges();
1006 mGattSession =
nullptr;
1010 emit q->disconnected();
1015void QLowEnergyControllerPrivateWinRT::obtainIncludedServices(
1022 RETURN_IF_FAILED(
"Could not cast service",
return);
1024 hr = service3->GetIncludedServicesAsync(&op);
1026 RETURN_IF_FAILED(
"Could not obtain included services",
return);
1028 hr = QWinRTFunctions::await(op,
result.GetAddressOf(), QWinRTFunctions::ProcessMainThreadEvents, 5000);
1029 RETURN_IF_FAILED(
"Could not await service operation",
return);
1033 GattCommunicationStatus status;
1034 hr =
result->get_Status(&status);
1035 if (FAILED(hr) || status != GattCommunicationStatus_Success) {
1036 qErrnoWarning(
"Could not obtain list of included services");
1040 hr =
result->get_Services(&includedServices);
1041 RETURN_IF_FAILED(
"Could not obtain service list",
return);
1044 hr = includedServices->get_Size(&
count);
1045 RETURN_IF_FAILED(
"Could not obtain service list's size",
return);
1048 hr = includedServices->GetAt(
i, &includedService);
1051 hr = includedService->get_Uuid(&guuid);
1055 qCDebug(QT_BT_WINDOWS_SERVICE_THREAD) << __FUNCTION__
1056 <<
"Changing service pointer from thread"
1059 includedPointer =
serviceList.value(includedUuid);
1062 priv->uuid = includedUuid;
1063 priv->setController(
this);
1066 serviceList.insert(includedUuid, includedPointer);
1069 servicePointer->includedServices.append(includedUuid);
1071 obtainIncludedServices(includedPointer, includedService);
1073 emit q->serviceDiscovered(includedUuid);
1089 if (status != AsyncStatus::Completed) {
1090 qCDebug(QT_BT_WINDOWS) <<
"Could not obtain services";
1098 GattCommunicationStatus commStatus;
1099 hr =
result->get_Status(&commStatus);
1102 if (commStatus != GattCommunicationStatus_Success)
1105 hr =
result->get_Services(&deviceServices);
1110 hr = deviceServices->get_Size(&serviceCount);
1113 for (
uint i = 0;
i < serviceCount; ++
i) {
1115 hr = deviceServices->GetAt(
i, &deviceService);
1118 hr = deviceService->get_Uuid(&guuid);
1121 m_openedServices[
service] = deviceService;
1123 qCDebug(QT_BT_WINDOWS_SERVICE_THREAD) << __FUNCTION__
1124 <<
"Changing service pointer from thread"
1132 priv->setController(
this);
1139 obtainIncludedServices(
pointer, deviceService);
1144 emit q->discoveryFinished();
1149 emit q->serviceDiscovered(service);
1153 emit q->discoveryFinished();
1158void QLowEnergyControllerPrivateWinRT::clearAllServices()
1162 for (
auto &uuid : m_requestDetailsServiceUuids)
1163 m_openedServices.
remove(uuid);
1164 m_requestDetailsServiceUuids.
clear();
1166 for (
auto service : m_openedServices) {
1169 m_openedServices.clear();
1172void QLowEnergyControllerPrivateWinRT::closeAndRemoveService(
const QBluetoothUuid &uuid)
1174 auto service = m_openedServices.take(uuid);
1181 qCDebug(QT_BT_WINDOWS) <<
"Service discovery initiated";
1185 HRESULT hr = mDevice.As(&device3);
1188 hr = device3->GetGattServicesAsync(&asyncResult);
1190 hr = asyncResult->put_Completed(
1191 Callback<IAsyncOperationCompletedHandler<GenericAttributeProfile::GattDeviceServicesResult *>>(
1192 this, &QLowEnergyControllerPrivateWinRT::onServiceDiscoveryFinished).Get());
1200 qCDebug(QT_BT_WINDOWS) << __FUNCTION__ << service;
1202 qCWarning(QT_BT_WINDOWS) <<
"Discovery done of unknown service:"
1203 << service.toString();
1208 closeAndRemoveService(service);
1211 discoverServiceDetailsHelper(service,
mode, deviceService);
1214 HRESULT hr = getNativeService(service, serviceCallback);
1216 qCDebug(QT_BT_WINDOWS) <<
"Could not obtain native service for uuid " << service;
1219void QLowEnergyControllerPrivateWinRT::discoverServiceDetailsHelper(
1221 GattDeviceServiceComPtr deviceService)
1226 qCDebug(QT_BT_WINDOWS) << msg;
1232 qCDebug(QT_BT_WINDOWS_SERVICE_THREAD) << __FUNCTION__ <<
"Changing service pointer from thread"
1236 HRESULT hr = deviceService.As(&deviceService3);
1242 hr = deviceService3->GetIncludedServicesAsync(&op);
1244 reactOnDiscoveryError(
pointer,
1249 hr = QWinRTFunctions::await(op,
result.GetAddressOf());
1251 reactOnDiscoveryError(
pointer,
1255 GattCommunicationStatus status;
1256 hr =
result->get_Status(&status);
1257 if (FAILED(hr) || status != GattCommunicationStatus_Success) {
1258 reactOnDiscoveryError(
pointer,
1259 QStringLiteral(
"Obtaining list of included services failed: %1").
1264 hr =
result->get_Services(&deviceServices);
1266 reactOnDiscoveryError(
pointer,
1272 hr = deviceServices->get_Size(&serviceCount);
1274 reactOnDiscoveryError(
pointer,
1275 QStringLiteral(
"Could not obtain included service list's size: %1").
1279 for (
uint i = 0;
i < serviceCount; ++
i) {
1281 hr = deviceServices->GetAt(
i, &includedService);
1284 hr = includedService->get_Uuid(&guuid);
1288 if (service.isNull()) {
1289 qCDebug(QT_BT_WINDOWS) <<
"Could not find service";
1293 pointer->includedServices.append(service);
1297 if (!otherService.
isNull())
1303 m_requestDetailsServiceUuids.
insert(service);
1312 this, &QLowEnergyControllerPrivateWinRT::handleServiceHandlerError);
1318 qCWarning(QT_BT_WINDOWS)
1319 <<
"Discovery complete for unknown service:" << service.toString();
1322 m_requestDetailsServiceUuids.
remove(service);
1325 pointer->startHandle = startHandle;
1326 pointer->endHandle = endHandle;
1327 pointer->characteristicList = charList;
1330 registerForValueChanges(
service, indicateChar);
1360 qCDebug(QT_BT_WINDOWS) << __FUNCTION__ << service << charHandle;
1361 qCDebug(QT_BT_WINDOWS_SERVICE_THREAD) << __FUNCTION__ <<
"Changing service pointer from thread"
1370 if (!service->characteristicList.contains(charHandle)) {
1371 qCDebug(QT_BT_WINDOWS) << charHandle <<
"could not be found in service" << service->uuid;
1376 const auto charData = service->characteristicList.value(charHandle);
1378 qCDebug(QT_BT_WINDOWS) <<
"Read flag is not set for characteristic" << charData.uuid;
1380 auto characteristicCallback = [charHandle, service,
this](
1382 readCharacteristicHelper(service, charHandle, characteristic);
1385 HRESULT hr = getNativeCharacteristic(service->uuid, charData.uuid, characteristicCallback);
1387 qCDebug(QT_BT_WINDOWS) <<
"Could not obtain native characteristic" << charData.uuid
1388 <<
"from service" << service->uuid;
1393void QLowEnergyControllerPrivateWinRT::readCharacteristicHelper(
1396 GattCharacteristicComPtr characteristic)
1399 HRESULT hr = characteristic->ReadValueWithCacheModeAsync(BluetoothCacheMode_Uncached, &readOp);
1402 auto readCompletedLambda = [charHandle, service]
1405 if (status == AsyncStatus::Canceled || status == AsyncStatus::Error) {
1406 qCDebug(QT_BT_WINDOWS) <<
"Characteristic" << charHandle <<
"read operation failed.";
1412 hr = op->GetResults(&characteristicValue);
1417 auto charData =
service->characteristicList.value(charHandle);
1418 charData.value =
value;
1419 service->characteristicList.insert(charHandle, charData);
1423 hr = readOp->put_Completed(Callback<IAsyncOperationCompletedHandler<GattReadResult *>>(
1424 readCompletedLambda).Get());
1434 qCDebug(QT_BT_WINDOWS) << __FUNCTION__ << service << charHandle << descHandle;
1435 qCDebug(QT_BT_WINDOWS_SERVICE_THREAD) << __FUNCTION__ <<
"Changing service pointer from thread"
1444 if (!service->characteristicList.contains(charHandle)) {
1445 qCDebug(QT_BT_WINDOWS) <<
"Descriptor" << descHandle <<
"in characteristic" << charHandle
1446 <<
"cannot be found in service" << service->uuid;
1451 const auto charData = service->characteristicList.value(charHandle);
1453 auto characteristicCallback = [charHandle, descHandle, service,
this](
1455 readDescriptorHelper(service, charHandle, descHandle, characteristic);
1458 HRESULT hr = getNativeCharacteristic(service->uuid, charData.uuid, characteristicCallback);
1460 qCDebug(QT_BT_WINDOWS) <<
"Could not obtain native characteristic" << charData.uuid
1461 <<
"from service" << service->uuid;
1466void QLowEnergyControllerPrivateWinRT::readDescriptorHelper(
1470 GattCharacteristicComPtr characteristic)
1473 const auto charData = service->characteristicList.value(charHandle);
1474 if (!charData.descriptorList.contains(descHandle)) {
1475 qCDebug(QT_BT_WINDOWS) <<
"Descriptor" << descHandle <<
"cannot be found in characteristic"
1478 const auto descData = charData.descriptorList.value(descHandle);
1483 HRESULT hr = characteristic->ReadClientCharacteristicConfigurationDescriptorAsync(&readOp);
1486 auto readCompletedLambda = [charHandle, descHandle,
service]
1489 if (status == AsyncStatus::Canceled || status == AsyncStatus::Error) {
1490 qCDebug(QT_BT_WINDOWS) <<
"Descriptor" << descHandle <<
"read operation failed";
1496 hr = op->GetResults(&iValue);
1499 GattClientCharacteristicConfigurationDescriptorValue
value;
1500 hr = iValue->get_ClientCharacteristicConfigurationDescriptor(&
value);
1504 bool correct =
false;
1505 if (
value & GattClientCharacteristicConfigurationDescriptorValue_Indicate) {
1509 if (
value & GattClientCharacteristicConfigurationDescriptorValue_Notify) {
1513 if (
value == GattClientCharacteristicConfigurationDescriptorValue_None)
1516 qCDebug(QT_BT_WINDOWS) <<
"Descriptor" << descHandle
1517 <<
"read operation failed. Obtained unexpected value.";
1525 service->characteristicList[charHandle].descriptorList[descHandle] = descData;
1530 hr = readOp->put_Completed(
1531 Callback<IAsyncOperationCompletedHandler<ClientCharConfigDescriptorResult *>>(
1532 readCompletedLambda).Get());
1539 HRESULT hr = characteristic.As(&characteristic3);
1543 hr = characteristic3->GetDescriptorsForUuidAsync(descData.
uuid, &op);
1547 hr = QWinRTFunctions::await(op,
result.GetAddressOf(),
1548 QWinRTFunctions::ProcessMainThreadEvents, 5000);
1552 GattCommunicationStatus commStatus;
1553 hr =
result->get_Status(&commStatus);
1554 if (FAILED(hr) || commStatus != GattCommunicationStatus_Success) {
1561 hr =
result->get_Descriptors(&descriptors);
1565 hr = descriptors->get_Size(&
size);
1569 qCWarning(QT_BT_WINDOWS) <<
"No descriptor with uuid" << descData.
uuid <<
"was found.";
1572 }
else if (
size > 1) {
1573 qCWarning(QT_BT_WINDOWS) <<
"There is more than 1 descriptor with uuid" << descData.
uuid;
1577 hr = descriptors->GetAt(0, &descriptor);
1581 hr = descriptor->ReadValueWithCacheModeAsync(BluetoothCacheMode_Uncached, &readOp);
1584 auto readCompletedLambda = [charHandle, descHandle, descUuid,
service]
1587 if (status == AsyncStatus::Canceled || status == AsyncStatus::Error) {
1588 qCDebug(QT_BT_WINDOWS) <<
"Descriptor" << descHandle <<
"read operation failed";
1594 hr = op->GetResults(&descriptorValue);
1596 qCDebug(QT_BT_WINDOWS) <<
"Could not obtain result for descriptor" << descHandle;
1601 descData.
uuid = descUuid;
1606 service->characteristicList[charHandle].descriptorList[descHandle] = descData;
1611 hr = readOp->put_Completed(Callback<IAsyncOperationCompletedHandler<GattReadResult *>>(
1612 readCompletedLambda).Get());
1623 qCDebug(QT_BT_WINDOWS) << __FUNCTION__ << service << charHandle << newValue <<
mode;
1624 qCDebug(QT_BT_WINDOWS_SERVICE_THREAD) << __FUNCTION__ <<
"Changing service pointer from thread"
1632 if (!service->characteristicList.contains(charHandle)) {
1633 qCDebug(QT_BT_WINDOWS) <<
"Characteristic" << charHandle <<
"cannot be found in service"
1643 qCDebug(QT_BT_WINDOWS) <<
"Write flag is not set for characteristic" << charHandle;
1645 auto characteristicCallback = [charHandle, service, newValue, writeWithResponse,
this](
1647 writeCharacteristicHelper(service, charHandle, newValue, writeWithResponse,
1651 HRESULT hr = getNativeCharacteristic(service->uuid, charData.
uuid, characteristicCallback);
1653 qCDebug(QT_BT_WINDOWS) <<
"Could not obtain native characteristic" << charData.
uuid
1654 <<
"from service" << service->uuid;
1659void QLowEnergyControllerPrivateWinRT::writeCharacteristicHelper(
1662 bool writeWithResponse, GattCharacteristicComPtr characteristic)
1665 HRESULT hr = GetActivationFactory(
1666 HStringReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(),
1679 hr =
buffer.As(&byteAccess);
1683 hr = byteAccess->Buffer(&bytes);
1686 memcpy(bytes, newValue,
length);
1688 GattWriteOption
option = writeWithResponse ? GattWriteOption_WriteWithResponse
1689 : GattWriteOption_WriteWithoutResponse;
1690 hr = characteristic->WriteValueWithOptionAsync(
buffer.Get(),
option, &writeOp);
1693 const auto charData = service->characteristicList.value(charHandle);
1695 auto writeCompletedLambda =
1696 [charData, charHandle, newValue, service, writeWithResponse, thisPtr]
1699 if (status == AsyncStatus::Canceled || status == AsyncStatus::Error) {
1700 qCDebug(QT_BT_WINDOWS) <<
"Characteristic" << charHandle <<
"write operation failed";
1704 GattCommunicationStatus
result;
1706 hr = op->GetResults(&
result);
1707 if (hr == E_BLUETOOTH_ATT_INVALID_ATTRIBUTE_VALUE_LENGTH) {
1708 qCDebug(QT_BT_WINDOWS) <<
"Characteristic" << charHandle
1709 <<
"write operation was tried with invalid value length";
1715 if (
result != GattCommunicationStatus_Success) {
1716 qCDebug(QT_BT_WINDOWS) <<
"Characteristic" << charHandle <<
"write operation failed";
1723 thisPtr->updateValueOfCharacteristic(charHandle, newValue,
false);
1724 if (writeWithResponse) {
1730 hr = writeOp->put_Completed(
1731 Callback<IAsyncOperationCompletedHandler<GattCommunicationStatus>>(
1732 writeCompletedLambda).Get());
1743 qCDebug(QT_BT_WINDOWS) << __FUNCTION__ << service << charHandle << descHandle << newValue;
1744 qCDebug(QT_BT_WINDOWS_SERVICE_THREAD) << __FUNCTION__ <<
"Changing service pointer from thread"
1753 if (!service->characteristicList.contains(charHandle)) {
1754 qCDebug(QT_BT_WINDOWS) <<
"Descriptor" << descHandle <<
"in characteristic" << charHandle
1755 <<
"could not be found in service" << service->uuid;
1760 const auto charData = service->characteristicList.value(charHandle);
1762 auto characteristicCallback = [descHandle, charHandle, service, newValue,
this](
1764 writeDescriptorHelper(service, charHandle, descHandle, newValue, characteristic);
1767 HRESULT hr = getNativeCharacteristic(service->uuid, charData.uuid, characteristicCallback);
1769 qCDebug(QT_BT_WINDOWS) <<
"Could not obtain native characteristic" << charData.uuid
1770 <<
"from service" << service->uuid;
1775void QLowEnergyControllerPrivateWinRT::writeDescriptorHelper(
1780 GattCharacteristicComPtr characteristic)
1783 const auto charData = service->characteristicList.value(charHandle);
1784 if (!charData.descriptorList.contains(descHandle)) {
1785 qCDebug(QT_BT_WINDOWS) <<
"Descriptor" << descHandle
1786 <<
"could not be found in Characteristic" << charHandle;
1790 if (descData.
uuid ==
1792 GattClientCharacteristicConfigurationDescriptorValue
value;
1793 quint16 intValue = qFromLittleEndian<quint16>(newValue);
1794 if (intValue & GattClientCharacteristicConfigurationDescriptorValue_Indicate
1795 && intValue & GattClientCharacteristicConfigurationDescriptorValue_Notify) {
1796 qCWarning(QT_BT_WINDOWS) <<
"Setting both Indicate and Notify "
1797 "is not supported on WinRT";
1798 value = GattClientCharacteristicConfigurationDescriptorValue(
1799 (GattClientCharacteristicConfigurationDescriptorValue_Indicate
1800 | GattClientCharacteristicConfigurationDescriptorValue_Notify));
1801 }
else if (intValue & GattClientCharacteristicConfigurationDescriptorValue_Indicate) {
1802 value = GattClientCharacteristicConfigurationDescriptorValue_Indicate;
1803 }
else if (intValue & GattClientCharacteristicConfigurationDescriptorValue_Notify) {
1804 value = GattClientCharacteristicConfigurationDescriptorValue_Notify;
1805 }
else if (intValue == 0) {
1806 value = GattClientCharacteristicConfigurationDescriptorValue_None;
1808 qCDebug(QT_BT_WINDOWS) <<
"Descriptor" << descHandle
1809 <<
"write operation failed: Invalid value";
1815 characteristic->WriteClientCharacteristicConfigurationDescriptorAsync(
value, &writeOp);
1819 auto writeCompletedLambda = [charHandle, descHandle, newValue,
service, thisPtr]
1822 if (status == AsyncStatus::Canceled || status == AsyncStatus::Error) {
1823 qCDebug(QT_BT_WINDOWS) <<
"Descriptor" << descHandle <<
"write operation failed";
1827 GattCommunicationStatus
result;
1829 hr = op->GetResults(&
result);
1832 if (
result != GattCommunicationStatus_Success) {
1833 qCWarning(QT_BT_WINDOWS) <<
"Descriptor" << descHandle <<
"write operation failed";
1838 thisPtr->updateValueOfDescriptor(charHandle, descHandle, newValue,
false);
1843 hr = writeOp->put_Completed(
1844 Callback<IAsyncOperationCompletedHandler<GattCommunicationStatus >>(
1845 writeCompletedLambda).Get());
1852 HRESULT hr = characteristic.As(&characteristic3);
1856 hr = characteristic3->GetDescriptorsForUuidAsync(descData.
uuid, &op);
1860 hr = QWinRTFunctions::await(op,
result.GetAddressOf(),
1861 QWinRTFunctions::ProcessMainThreadEvents, 5000);
1864 GattCommunicationStatus commStatus;
1865 hr =
result->get_Status(&commStatus);
1866 if (FAILED(hr) || commStatus != GattCommunicationStatus_Success) {
1867 qCWarning(QT_BT_WINDOWS) <<
"Descriptor operation failed";
1872 hr =
result->get_Descriptors(&descriptors);
1876 hr = descriptors->get_Size(&
size);
1880 qCWarning(QT_BT_WINDOWS) <<
"No descriptor with uuid" << descData.
uuid <<
"was found.";
1882 }
else if (
size > 1) {
1883 qCWarning(QT_BT_WINDOWS) <<
"There is more than 1 descriptor with uuid" << descData.
uuid;
1886 hr = descriptors->GetAt(0, &descriptor);
1890 hr = GetActivationFactory(
1891 HStringReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(),
1904 hr =
buffer.As(&byteAccess);
1908 hr = byteAccess->Buffer(&bytes);
1911 memcpy(bytes, newValue,
length);
1913 hr = descriptor->WriteValueAsync(
buffer.Get(), &writeOp);
1917 auto writeCompletedLambda = [charHandle, descHandle, newValue,
service, thisPtr]
1920 if (status == AsyncStatus::Canceled || status == AsyncStatus::Error) {
1921 qCDebug(QT_BT_WINDOWS) <<
"Descriptor" << descHandle <<
"write operation failed";
1925 GattCommunicationStatus
result;
1927 hr = op->GetResults(&
result);
1930 if (
result != GattCommunicationStatus_Success) {
1931 qCDebug(QT_BT_WINDOWS) <<
"Descriptor" << descHandle <<
"write operation failed";
1936 thisPtr->updateValueOfDescriptor(charHandle, descHandle, newValue,
false);
1941 hr = writeOp->put_Completed(
1942 Callback<IAsyncOperationCompletedHandler<GattCommunicationStatus>>(
1943 writeCompletedLambda).Get());
1957 if (!mGattSession) {
1958 qCDebug(QT_BT_WINDOWS) <<
"mtu queried before GattSession available. Using default mtu.";
1962 HRESULT hr = mGattSession->get_MaxPduSize(&
mtu);
1963 RETURN_IF_FAILED(
"could not obtain MTU size",
return mtu);
1964 qCDebug(QT_BT_WINDOWS) <<
"mtu determined to be" <<
mtu;
1968void QLowEnergyControllerPrivateWinRT::handleCharacteristicChanged(
1971 qCDebug(QT_BT_WINDOWS) << __FUNCTION__ << charHandle <<
data;
1972 qCDebug(QT_BT_WINDOWS_SERVICE_THREAD) << __FUNCTION__ <<
"Changing service pointer from thread"
1976 if (service.isNull())
1979 qCDebug(QT_BT_WINDOWS) <<
"Characteristic change notification" << service->uuid
1980 << charHandle <<
data.toHex();
1983 if (!characteristic.
isValid()) {
1984 qCWarning(QT_BT_WINDOWS) <<
"characteristicChanged: Cannot find characteristic";
1996void QLowEnergyControllerPrivateWinRT::handleServiceHandlerError(
const QString &
error)
2001 qCWarning(QT_BT_WINDOWS) <<
"Error while discovering services:" <<
error;
2006void QLowEnergyControllerPrivateWinRT::handleConnectionError(
const char *logMessage)
2011 unregisterFromStatusChanges();
2012 unregisterFromMtuChanges();
2017#include "qlowenergycontroller_winrt.moc"
IOBluetoothDevice * device
std::vector< ObjCStrongReference< CBMutableService > > services
Pairing
This enum describes the pairing state between the two Bluetooth devices.
Pairing pairingStatus(const QBluetoothAddress &address) const
Returns the current bluetooth pairing status of address, if it's unpaired, paired,...
@ CharacteristicUserDescription
@ ClientCharacteristicConfiguration
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
qsizetype length() const noexcept
Same as size().
bool hasExpired() const noexcept
Returns true if this QDeadlineTimer object has expired, false if there remains time left.
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
qsizetype size() const noexcept
void append(parameter_type t)
The QLowEnergyAdvertisingData class represents the data to be broadcast during Bluetooth Low Energy a...
The QLowEnergyAdvertisingParameters class represents the parameters used for Bluetooth Low Energy adv...
QLowEnergyCharacteristic::PropertyTypes properties() const
Returns the properties of the characteristic.
bool isValid() const
Returns true if the QLowEnergyCharacteristic object is valid, otherwise returns false.
The QLowEnergyConnectionParameters class is used when requesting or reporting an update of the parame...
void discoverServiceDetails(const QBluetoothUuid &service, QLowEnergyService::DiscoveryMode mode) override
void stopAdvertising() override
~QLowEnergyControllerPrivateWinRT() override
QLowEnergyControllerPrivateWinRT()
void characteristicChanged(quint16 charHandle, const QByteArray &data)
void addToGenericAttributeList(const QLowEnergyServiceData &service, QLowEnergyHandle startHandle) override
void readDescriptor(const QSharedPointer< QLowEnergyServicePrivate > service, const QLowEnergyHandle charHandle, const QLowEnergyHandle descriptorHandle) override
void connectToDevice() override
void disconnectFromDevice() override
void writeDescriptor(const QSharedPointer< QLowEnergyServicePrivate > service, const QLowEnergyHandle charHandle, const QLowEnergyHandle descriptorHandle, const QByteArray &newValue) override
void startAdvertising(const QLowEnergyAdvertisingParameters ¶ms, const QLowEnergyAdvertisingData &advertisingData, const QLowEnergyAdvertisingData &scanResponseData) override
void readCharacteristic(const QSharedPointer< QLowEnergyServicePrivate > service, const QLowEnergyHandle charHandle) override
void writeCharacteristic(const QSharedPointer< QLowEnergyServicePrivate > service, const QLowEnergyHandle charHandle, const QByteArray &newValue, QLowEnergyService::WriteMode mode) override
void requestConnectionUpdate(const QLowEnergyConnectionParameters ¶ms) override
void discoverServices() override
QLowEnergyCharacteristic characteristicForHandle(QLowEnergyHandle handle)
Returns a valid characteristic if the given handle is the handle of the characteristic itself or one ...
QSharedPointer< QLowEnergyServicePrivate > serviceForHandle(QLowEnergyHandle handle)
void invalidateServices()
ServiceDataMap serviceList
QLowEnergyController::Error error
void setError(QLowEnergyController::Error newError)
QLowEnergyController::Role role
quint16 updateValueOfCharacteristic(QLowEnergyHandle charHandle, const QByteArray &value, bool appendValue)
Returns the length of the updated characteristic value.
QLowEnergyController::ControllerState state
QBluetoothAddress remoteDevice
void setState(QLowEnergyController::ControllerState newState)
@ UnknownRemoteDeviceError
The QLowEnergyServiceData class is used to set up GATT service data. \inmodule QtBluetooth.
DiscoveryMode
This enum lists service discovery modes.
@ CharacteristicWriteError
@ CharacteristicReadError
@ RemoteServiceDiscovered
@ RemoteServiceDiscovering
WriteMode
This enum describes the mode to be used when writing a characteristic value.
void moveToThread(QThread *thread)
Changes the thread affinity for this object and its children.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
QThread * thread() const
Returns the thread in which the object lives.
void destroyed(QObject *=nullptr)
This signal is emitted immediately before the object obj is destroyed, after any instances of QPointe...
void deleteLater()
\threadsafe
bool remove(const T &value)
iterator insert(const T &value)
bool isNull() const noexcept
Returns true if this object refers to \nullptr.
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QByteArray toUtf8() const &
void start(Priority=InheritPriority)
static QThread * currentThread()
void finished(QPrivateSignal)
void started(QPrivateSignal)
void deviceConnected(ComPtr< IBluetoothLEDevice > device, ComPtr< IGattSession > session)
QWinRTLowEnergyConnectionHandler(const QBluetoothAddress &address)
~QWinRTLowEnergyConnectionHandler()
void errorOccurred(const QString &error)
void handleDeviceDisconnectRequest()
uint mCharacteristicsCountToBeDiscovered
QList< QBluetoothUuid > mIndicateChars
void errorOccured(const QString &error)
void charListObtained(const QBluetoothUuid &service, QHash< QLowEnergyHandle, QLowEnergyServicePrivate::CharData > charList, QList< QBluetoothUuid > indicateChars, QLowEnergyHandle startHandle, QLowEnergyHandle endHandle)
QLowEnergyService::DiscoveryMode mMode
QWinRTLowEnergyServiceHandler(const QBluetoothUuid &service, const ComPtr< IGattDeviceService3 > &deviceService, QLowEnergyService::DiscoveryMode mode)
ComPtr< IGattDeviceService3 > mDeviceService
~QWinRTLowEnergyServiceHandler()
QHash< QLowEnergyHandle, QLowEnergyServicePrivate::CharData > mCharacteristicList
void qErrnoWarning(const char *msg,...)
Combined button and popup list for selecting options.
Q_CORE_EXPORT QtJniTypes::Service service()
constexpr Initialization Uninitialized
static QByteArray byteArrayFromBuffer(const IBuffer &buffer)
static const QCssKnownValue properties[NumProperties - 1]
DBusConnection const char DBusError * error
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
constexpr T qToLittleEndian(T source)
Q_DECL_COLD_FUNCTION Q_CORE_EXPORT QString qt_error_string(int errorCode=-1)
#define qCWarning(category,...)
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
IGattReadClientCharacteristicConfigurationDescriptorResult IClientCharConfigDescriptorResult
#define EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED_2(hr, message)
QT_BEGIN_NAMESPACE typedef ITypedEventHandler< BluetoothLEDevice *, IInspectable * > StatusHandler
#define CHECK_HR_AND_SET_SERVICE_ERROR(hr, msg, service, error, ret)
static QByteArray byteArrayFromGattResult(const ComPtr< IGattReadResult > &gattResult, bool isWCharString=false)
static void closeDeviceService(ComPtr< T > service)
#define DEC_CHAR_COUNT_AND_CONTINUE_IF_FAILED(hr, msg)
#define CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, msg, ret)
ITypedEventHandler< GattSession *, IInspectable * > MtuHandler
GattReadClientCharacteristicConfigurationDescriptorResult ClientCharConfigDescriptorResult
static constexpr qint64 kMaxConnectTimeout
ITypedEventHandler< GattCharacteristic *, GattValueChangedEventArgs * > ValueChangedHandler
#define WARN_AND_CONTINUE_IF_FAILED(hr, msg)
#define EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED(hr)
void registerQLowEnergyControllerMetaType()
GLuint64 GLenum void * handle
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLenum GLsizei length
GLenum GLenum GLsizei count
GLenum GLuint GLsizei const GLenum * props
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint GLuint64EXT address
GLsizei const void * pointer
GLdouble GLdouble GLdouble GLdouble q
QT_BEGIN_NAMESPACE typedef void(* Callback)(QQmlNotifierEndpoint *, void **)
QLatin1StringView QLatin1String
#define QStringLiteral(str)
#define Q_UNIMPLEMENTED()
if(qFloatDistance(a, b)<(1<< 7))
[0]
settings remove("monkey")
QDeadlineTimer deadline(30s)
myObject disconnect()
[26]
QHash< QLowEnergyHandle, DescData > descriptorList
QLowEnergyHandle valueHandle
QLowEnergyCharacteristic::PropertyTypes properties