summaryrefslogtreecommitdiffstats
path: root/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp')
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp195
1 files changed, 176 insertions, 19 deletions
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp
index ef2a69b1..a353f5e3 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp
@@ -47,6 +47,8 @@
#endif
#include "qfunctions_winrt.h"
+#include <QtBluetooth/private/qtbluetoothglobal_p.h>
+#include <QtBluetooth/private/qbluetoothutils_winrt_p.h>
#include <QtCore/QLoggingCategory>
#include <QtCore/private/qeventdispatcher_winrt_p.h>
@@ -105,7 +107,10 @@ private:
CheckForPairing,
OmitPairingCheck
};
- HRESULT onBluetoothLEDeviceFound(ComPtr<IBluetoothLEDevice> device, PairingCheck pairingCheck = CheckForPairing);
+ HRESULT onBluetoothLEDeviceFound(ComPtr<IBluetoothLEDevice> device, PairingCheck pairingCheck);
+#if QT_CONFIG(winrt_btle_no_pairing)
+ HRESULT onBluetoothLEDeviceFound(ComPtr<IBluetoothLEDevice> device);
+#endif
public slots:
void finishDiscovery();
@@ -120,6 +125,10 @@ public:
private:
ComPtr<IBluetoothLEAdvertisementWatcher> m_leWatcher;
EventRegistrationToken m_leDeviceAddedToken;
+#if QT_CONFIG(winrt_btle_no_pairing)
+ QMutex m_foundDevicesMutex;
+ QMap<quint64, QVector<QBluetoothUuid>> m_foundLEDevicesMap;
+#endif
QVector<quint64> m_foundLEDevices;
int m_pendingPairedDevices;
@@ -191,9 +200,11 @@ void QWinRTBluetoothDeviceDiscoveryWorker::startDeviceDiscovery(QBluetoothDevice
ComPtr<IAsyncOperation<DeviceInformationCollection *>> op;
hr = deviceInformationStatics->FindAllAsyncAqsFilter(deviceSelector.Get(), &op);
WARN_AND_RETURN_IF_FAILED("Could not start bluetooth device discovery operation", return);
+ QPointer<QWinRTBluetoothDeviceDiscoveryWorker> thisPointer(this);
hr = op->put_Completed(
- Callback<IAsyncOperationCompletedHandler<DeviceInformationCollection *>>([this, mode](IAsyncOperation<DeviceInformationCollection *> *op, AsyncStatus) {
- onDeviceDiscoveryFinished(op, mode);
+ Callback<IAsyncOperationCompletedHandler<DeviceInformationCollection *>>([thisPointer, mode](IAsyncOperation<DeviceInformationCollection *> *op, AsyncStatus status) {
+ if (status == Completed && thisPointer)
+ thisPointer->onDeviceDiscoveryFinished(op, mode);
return S_OK;
}).Get());
WARN_AND_RETURN_IF_FAILED("Could not add callback to bluetooth device discovery operation", return);
@@ -249,15 +260,64 @@ void QWinRTBluetoothDeviceDiscoveryWorker::setupLEDeviceWatcher()
{
HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Devices_Bluetooth_Advertisement_BluetoothLEAdvertisementWatcher).Get(), &m_leWatcher);
Q_ASSERT_SUCCEEDED(hr);
+#if QT_CONFIG(winrt_btle_no_pairing)
+ if (supportsNewLEApi()) {
+ hr = m_leWatcher->put_ScanningMode(BluetoothLEScanningMode_Active);
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+#endif // winrt_btle_no_pairing
hr = m_leWatcher->add_Received(Callback<ITypedEventHandler<BluetoothLEAdvertisementWatcher *, BluetoothLEAdvertisementReceivedEventArgs *>>([this](IBluetoothLEAdvertisementWatcher *, IBluetoothLEAdvertisementReceivedEventArgs *args) {
quint64 address;
HRESULT hr;
hr = args->get_BluetoothAddress(&address);
Q_ASSERT_SUCCEEDED(hr);
- if (m_foundLEDevices.contains(address))
- return S_OK;
+#if QT_CONFIG(winrt_btle_no_pairing)
+ if (supportsNewLEApi()) {
+ ComPtr<IBluetoothLEAdvertisement> ad;
+ hr = args->get_Advertisement(&ad);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<IVector<GUID>> guids;
+ hr = ad->get_ServiceUuids(&guids);
+ Q_ASSERT_SUCCEEDED(hr);
+ quint32 size;
+ hr = guids->get_Size(&size);
+ Q_ASSERT_SUCCEEDED(hr);
+ QVector<QBluetoothUuid> serviceUuids;
+ for (quint32 i = 0; i < size; ++i) {
+ GUID guid;
+ hr = guids->GetAt(i, &guid);
+ Q_ASSERT_SUCCEEDED(hr);
+ QBluetoothUuid uuid(guid);
+ serviceUuids.append(uuid);
+ }
+ QMutexLocker locker(&m_foundDevicesMutex);
+ // Merge newly found services with list of currently found ones
+ if (m_foundLEDevicesMap.contains(address)) {
+ if (size == 0)
+ return S_OK;
+ QVector<QBluetoothUuid> foundServices = m_foundLEDevicesMap.value(address);
+ bool newServiceAdded = false;
+ for (const QBluetoothUuid &uuid : qAsConst(serviceUuids)) {
+ if (!foundServices.contains(uuid)) {
+ foundServices.append(uuid);
+ newServiceAdded = true;
+ }
+ }
+ if (!newServiceAdded)
+ return S_OK;
+ m_foundLEDevicesMap[address] = foundServices;
+ } else {
+ m_foundLEDevicesMap.insert(address, serviceUuids);
+ }
- m_foundLEDevices.append(address);
+ locker.unlock();
+ } else
+#endif
+ {
+ if (m_foundLEDevices.contains(address))
+ return S_OK;
+ m_foundLEDevices.append(address);
+ }
leBluetoothInfoFromAddressAsync(address);
return S_OK;
}).Get(), &m_leDeviceAddedToken);
@@ -288,9 +348,14 @@ void QWinRTBluetoothDeviceDiscoveryWorker::classicBluetoothInfoFromDeviceIdAsync
qCWarning(QT_BT_WINRT) << "Could not obtain bluetooth device from id";
return S_OK;
}
-
+ QPointer<QWinRTBluetoothDeviceDiscoveryWorker> thisPointer(this);
hr = deviceFromIdOperation->put_Completed(Callback<IAsyncOperationCompletedHandler<BluetoothDevice *>>
- (this, &QWinRTBluetoothDeviceDiscoveryWorker::onPairedClassicBluetoothDeviceFoundAsync).Get());
+ ([thisPointer](IAsyncOperation<BluetoothDevice *> *op, AsyncStatus status)
+ {
+ if (status == Completed && thisPointer)
+ thisPointer->onPairedClassicBluetoothDeviceFoundAsync(op, status);
+ return S_OK;
+ }).Get());
if (FAILED(hr)) {
--m_pendingPairedDevices;
if (!m_pendingPairedDevices
@@ -317,9 +382,14 @@ void QWinRTBluetoothDeviceDiscoveryWorker::leBluetoothInfoFromDeviceIdAsync(HSTR
qCWarning(QT_BT_WINRT) << "Could not obtain bluetooth device from id";
return S_OK;
}
-
+ QPointer<QWinRTBluetoothDeviceDiscoveryWorker> thisPointer(this);
hr = deviceFromIdOperation->put_Completed(Callback<IAsyncOperationCompletedHandler<BluetoothLEDevice *>>
- (this, &QWinRTBluetoothDeviceDiscoveryWorker::onPairedBluetoothLEDeviceFoundAsync).Get());
+ ([thisPointer] (IAsyncOperation<BluetoothLEDevice *> *op, AsyncStatus status)
+ {
+ if (status == Completed && thisPointer)
+ thisPointer->onPairedBluetoothLEDeviceFoundAsync(op, status);
+ return S_OK;
+ }).Get());
if (FAILED(hr)) {
--m_pendingPairedDevices;
qCWarning(QT_BT_WINRT) << "Could not register device found callback";
@@ -343,9 +413,14 @@ void QWinRTBluetoothDeviceDiscoveryWorker::leBluetoothInfoFromAddressAsync(quint
qCWarning(QT_BT_WINRT) << "Could not obtain bluetooth device from address";
return S_OK;
}
-
+ QPointer<QWinRTBluetoothDeviceDiscoveryWorker> thisPointer(this);
hr = deviceFromAddressOperation->put_Completed(Callback<IAsyncOperationCompletedHandler<BluetoothLEDevice *>>
- (this, &QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEDeviceFoundAsync).Get());
+ ([thisPointer](IAsyncOperation<BluetoothLEDevice *> *op, AsyncStatus status)
+ {
+ if (status == Completed && thisPointer)
+ thisPointer->onBluetoothLEDeviceFoundAsync(op, status);
+ return S_OK;
+ }).Get());
if (FAILED(hr)) {
qCWarning(QT_BT_WINRT) << "Could not register device found callback";
return S_OK;
@@ -391,7 +466,7 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onPairedClassicBluetoothDeviceFoun
uint serviceCount;
hr = deviceServices->get_Size(&serviceCount);
Q_ASSERT_SUCCEEDED(hr);
- QList<QBluetoothUuid> uuids;
+ QVector<QBluetoothUuid> uuids;
for (uint i = 0; i < serviceCount; ++i) {
ComPtr<Rfcomm::IRfcommDeviceService> service;
hr = deviceServices->GetAt(i, &service);
@@ -410,7 +485,7 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onPairedClassicBluetoothDeviceFoun
QBluetoothDeviceInfo info(QBluetoothAddress(address), btName, classOfDeviceInt);
info.setCoreConfigurations(QBluetoothDeviceInfo::BaseRateCoreConfiguration);
- info.setServiceUuids(uuids, QBluetoothDeviceInfo::DataIncomplete);
+ info.setServiceUuids(uuids);
info.setCached(true);
QMetaObject::invokeMethod(this, "deviceFound", Qt::AutoConnection,
@@ -431,7 +506,12 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onPairedBluetoothLEDeviceFoundAsyn
HRESULT hr;
hr = op->GetResults(&device);
Q_ASSERT_SUCCEEDED(hr);
- return onBluetoothLEDeviceFound(device, OmitPairingCheck);
+#if QT_CONFIG(winrt_btle_no_pairing)
+ if (supportsNewLEApi())
+ return onBluetoothLEDeviceFound(device);
+ else
+#endif
+ return onBluetoothLEDeviceFound(device, OmitPairingCheck);
}
HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEDeviceFoundAsync(IAsyncOperation<BluetoothLEDevice *> *op, AsyncStatus status)
@@ -443,7 +523,12 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEDeviceFoundAsync(IAsy
HRESULT hr;
hr = op->GetResults(&device);
Q_ASSERT_SUCCEEDED(hr);
- return onBluetoothLEDeviceFound(device, PairingCheck::CheckForPairing);
+#if QT_CONFIG(winrt_btle_no_pairing)
+ if (supportsNewLEApi())
+ return onBluetoothLEDeviceFound(device);
+ else
+#endif
+ return onBluetoothLEDeviceFound(device, PairingCheck::CheckForPairing);
}
HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEDeviceFound(ComPtr<IBluetoothLEDevice> device, PairingCheck pairingCheck)
@@ -479,7 +564,7 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEDeviceFound(ComPtr<IB
QPointer<QWinRTBluetoothDeviceDiscoveryWorker> tPointer(this);
hr = pairing.Get()->PairAsync(&pairingOp);
Q_ASSERT_SUCCEEDED(hr);
- pairingOp.Get()->put_Completed(
+ pairingOp->put_Completed(
Callback<IAsyncOperationCompletedHandler<DevicePairingResult *>>([device, tPointer](IAsyncOperation<DevicePairingResult *> *op, AsyncStatus status) {
if (!tPointer)
return S_OK;
@@ -520,7 +605,7 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEDeviceFound(ComPtr<IB
uint serviceCount;
hr = deviceServices->get_Size(&serviceCount);
Q_ASSERT_SUCCEEDED(hr);
- QList<QBluetoothUuid> uuids;
+ QVector<QBluetoothUuid> uuids;
for (uint i = 0; i < serviceCount; ++i) {
ComPtr<GenericAttributeProfile::IGattDeviceService> service;
hr = deviceServices->GetAt(i, &service);
@@ -537,6 +622,77 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEDeviceFound(ComPtr<IB
QBluetoothDeviceInfo info(QBluetoothAddress(address), btName, 0);
info.setCoreConfigurations(QBluetoothDeviceInfo::LowEnergyCoreConfiguration);
+ info.setServiceUuids(uuids);
+ info.setCached(true);
+
+ QMetaObject::invokeMethod(this, "deviceFound", Qt::AutoConnection,
+ Q_ARG(QBluetoothDeviceInfo, info));
+ return S_OK;
+}
+
+#if QT_CONFIG(winrt_btle_no_pairing)
+HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEDeviceFound(ComPtr<IBluetoothLEDevice> device)
+{
+ if (!device) {
+ qCDebug(QT_BT_WINRT) << "onBluetoothLEDeviceFound: No device given";
+ return S_OK;
+ }
+
+ UINT64 address;
+ HString name;
+ HRESULT hr = device->get_BluetoothAddress(&address);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = device->get_Name(name.GetAddressOf());
+ Q_ASSERT_SUCCEEDED(hr);
+ const QString btName = QString::fromWCharArray(WindowsGetStringRawBuffer(name.Get(), nullptr));
+
+ ComPtr<IBluetoothLEDevice2> device2;
+ hr = device.As(&device2);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<IDeviceInformation> deviceInfo;
+ hr = device2->get_DeviceInformation(&deviceInfo);
+ Q_ASSERT_SUCCEEDED(hr);
+ if (!deviceInfo) {
+ qCDebug(QT_BT_WINRT) << "onBluetoothLEDeviceFound: Could not obtain device information";
+ return S_OK;
+ }
+ ComPtr<IDeviceInformation2> deviceInfo2;
+ hr = deviceInfo.As(&deviceInfo2);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<IDeviceInformationPairing> pairing;
+ hr = deviceInfo2->get_Pairing(&pairing);
+ Q_ASSERT_SUCCEEDED(hr);
+ boolean isPaired;
+ hr = pairing->get_IsPaired(&isPaired);
+ Q_ASSERT_SUCCEEDED(hr);
+ QList<QBluetoothUuid> uuids;
+
+ // Use the services obtained from the advertisement data if the device is not paired
+ if (!isPaired) {
+ uuids = m_foundLEDevicesMap.value(address).toList();
+ } else {
+ IVectorView <GenericAttributeProfile::GattDeviceService *> *deviceServices;
+ hr = device->get_GattServices(&deviceServices);
+ Q_ASSERT_SUCCEEDED(hr);
+ uint serviceCount;
+ hr = deviceServices->get_Size(&serviceCount);
+ Q_ASSERT_SUCCEEDED(hr);
+ for (uint i = 0; i < serviceCount; ++i) {
+ ComPtr<GenericAttributeProfile::IGattDeviceService> service;
+ hr = deviceServices->GetAt(i, &service);
+ Q_ASSERT_SUCCEEDED(hr);
+ GUID uuid;
+ hr = service->get_Uuid(&uuid);
+ Q_ASSERT_SUCCEEDED(hr);
+ uuids.append(QBluetoothUuid(uuid));
+ }
+ }
+
+ qCDebug(QT_BT_WINRT) << "Discovered BTLE device: " << QString::number(address) << btName
+ << "Num UUIDs" << uuids.count();
+
+ QBluetoothDeviceInfo info(QBluetoothAddress(address), btName, 0);
+ info.setCoreConfigurations(QBluetoothDeviceInfo::LowEnergyCoreConfiguration);
info.setServiceUuids(uuids, QBluetoothDeviceInfo::DataIncomplete);
info.setCached(true);
@@ -544,6 +700,7 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEDeviceFound(ComPtr<IB
Q_ARG(QBluetoothDeviceInfo, info));
return S_OK;
}
+#endif // QT_CONFIG(winrt_btle_no_pairing)
QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate(
const QBluetoothAddress &deviceAdapter,
@@ -625,7 +782,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::registerDevice(const QBluetoothDevic
uuids.append(info.serviceUuids());
const QSet<QBluetoothUuid> uuidSet = uuids.toSet();
if (iter->serviceUuids().count() != uuidSet.count())
- iter->setServiceUuids(uuidSet.toList(), QBluetoothDeviceInfo::DataIncomplete);
+ iter->setServiceUuids(uuidSet.toList().toVector());
if (iter->coreConfigurations() != info.coreConfigurations())
iter->setCoreConfigurations(QBluetoothDeviceInfo::BaseRateAndLowEnergyCoreConfiguration);
return;