diff options
Diffstat (limited to 'src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp')
-rw-r--r-- | src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp | 195 |
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; |