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.cpp361
1 files changed, 330 insertions, 31 deletions
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp
index ef2a69b1..e0209693 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp
@@ -47,9 +47,12 @@
#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>
+#include <robuffer.h>
#include <wrl.h>
#include <windows.devices.enumeration.h>
#include <windows.devices.bluetooth.h>
@@ -66,6 +69,7 @@ using namespace ABI::Windows::Devices;
using namespace ABI::Windows::Devices::Bluetooth;
using namespace ABI::Windows::Devices::Bluetooth::Advertisement;
using namespace ABI::Windows::Devices::Enumeration;
+using namespace ABI::Windows::Storage::Streams;
QT_BEGIN_NAMESPACE
@@ -77,6 +81,54 @@ Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINRT)
ret; \
}
+#define WARN_AND_CONTINUE_IF_FAILED(msg) \
+ if (FAILED(hr)) { \
+ qCWarning(QT_BT_WINRT) << msg; \
+ continue; \
+ }
+
+static QByteArray byteArrayFromBuffer(const ComPtr<IBuffer> &buffer)
+{
+ ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteAccess;
+ HRESULT hr = buffer.As(&byteAccess);
+ Q_ASSERT_SUCCEEDED(hr);
+ char *data;
+ hr = byteAccess->Buffer(reinterpret_cast<byte **>(&data));
+ Q_ASSERT_SUCCEEDED(hr);
+ UINT32 size;
+ hr = buffer->get_Length(&size);
+ Q_ASSERT_SUCCEEDED(hr);
+ return QByteArray(data, int(size));
+}
+
+
+static ManufacturerData extractManufacturerData(ComPtr<IBluetoothLEAdvertisement> ad)
+{
+ ManufacturerData ret;
+ ComPtr<IVector<BluetoothLEManufacturerData*>> data;
+ HRESULT hr = ad->get_ManufacturerData(&data);
+ WARN_AND_RETURN_IF_FAILED("Could not obtain list of manufacturer data.", return ret);
+ quint32 size;
+ hr = data->get_Size(&size);
+ WARN_AND_RETURN_IF_FAILED("Could not obtain manufacturer data's list size.", return ret);
+ for (quint32 i = 0; i < size; ++i) {
+ ComPtr<IBluetoothLEManufacturerData> d;
+ hr = data->GetAt(i, &d);
+ WARN_AND_CONTINUE_IF_FAILED("Could not obtain manufacturer data.");
+ quint16 id;
+ hr = d->get_CompanyId(&id);
+ WARN_AND_CONTINUE_IF_FAILED("Could not obtain manufacturer data company id.");
+ ComPtr<IBuffer> buffer;
+ hr = d->get_Data(&buffer);
+ WARN_AND_CONTINUE_IF_FAILED("Could not obtain manufacturer data set.");
+ const QByteArray bufferData = byteArrayFromBuffer(buffer);
+ if (ret.contains(id))
+ qCWarning(QT_BT_WINRT) << "Company ID already present in manufacturer data.";
+ ret.insert(id, bufferData);
+ }
+ return ret;
+}
+
class QWinRTBluetoothDeviceDiscoveryWorker : public QObject
{
Q_OBJECT
@@ -84,7 +136,7 @@ public:
explicit QWinRTBluetoothDeviceDiscoveryWorker(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods);
~QWinRTBluetoothDeviceDiscoveryWorker();
void start();
- void stop();
+ void stopLEWatcher();
private:
void startDeviceDiscovery(QBluetoothDeviceDiscoveryAgent::DiscoveryMethod mode);
@@ -105,13 +157,18 @@ 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();
Q_SIGNALS:
void deviceFound(const QBluetoothDeviceInfo &info);
+ void deviceDataChanged(const QBluetoothAddress &address, QBluetoothDeviceInfo::Fields,
+ qint16 rssi, ManufacturerData manufacturerData);
void scanFinished();
public:
@@ -120,7 +177,17 @@ public:
private:
ComPtr<IBluetoothLEAdvertisementWatcher> m_leWatcher;
EventRegistrationToken m_leDeviceAddedToken;
- QVector<quint64> m_foundLEDevices;
+#if QT_CONFIG(winrt_btle_no_pairing)
+ QMutex m_foundDevicesMutex;
+ struct LEAdvertisingInfo {
+ QVector<QBluetoothUuid> services;
+ qint16 rssi = 0;
+ };
+
+ QMap<quint64, LEAdvertisingInfo> m_foundLEDevicesMap;
+#endif
+ QMap<quint64, qint16> m_foundLEDevices;
+ QMap<quint64, ManufacturerData> m_foundLEManufacturerData;
int m_pendingPairedDevices;
ComPtr<IBluetoothDeviceStatics> m_deviceStatics;
@@ -132,6 +199,8 @@ QWinRTBluetoothDeviceDiscoveryWorker::QWinRTBluetoothDeviceDiscoveryWorker(QBlue
, m_pendingPairedDevices(0)
{
qRegisterMetaType<QBluetoothDeviceInfo>();
+ qRegisterMetaType<QBluetoothDeviceInfo::Fields>();
+ qRegisterMetaType<ManufacturerData>();
#ifdef CLASSIC_APP_BUILD
CoInitialize(NULL);
@@ -144,7 +213,7 @@ QWinRTBluetoothDeviceDiscoveryWorker::QWinRTBluetoothDeviceDiscoveryWorker(QBlue
QWinRTBluetoothDeviceDiscoveryWorker::~QWinRTBluetoothDeviceDiscoveryWorker()
{
- stop();
+ stopLEWatcher();
#ifdef CLASSIC_APP_BUILD
CoUninitialize();
#endif
@@ -166,7 +235,7 @@ void QWinRTBluetoothDeviceDiscoveryWorker::start()
qCDebug(QT_BT_WINRT) << "Worker started";
}
-void QWinRTBluetoothDeviceDiscoveryWorker::stop()
+void QWinRTBluetoothDeviceDiscoveryWorker::stopLEWatcher()
{
if (m_leWatcher) {
HRESULT hr = m_leWatcher->Stop();
@@ -191,9 +260,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);
@@ -239,7 +310,8 @@ void QWinRTBluetoothDeviceDiscoveryWorker::gatherMultipleDeviceInformation(quint
{
for (quint32 i = 0; i < deviceCount; ++i) {
ComPtr<IDeviceInformation> device;
- HRESULT hr = devices->GetAt(i, &device);
+ HRESULT hr;
+ hr = devices->GetAt(i, &device);
Q_ASSERT_SUCCEEDED(hr);
gatherDeviceInformation(device.Get(), mode);
}
@@ -249,15 +321,104 @@ 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;
-
- m_foundLEDevices.append(address);
+ qint16 rssi;
+ hr = args->get_RawSignalStrengthInDBm(&rssi);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<IBluetoothLEAdvertisement> ad;
+ hr = args->get_Advertisement(&ad);
+ Q_ASSERT_SUCCEEDED(hr);
+ const ManufacturerData manufacturerData = extractManufacturerData(ad);
+ QBluetoothDeviceInfo::Fields changedFields = QBluetoothDeviceInfo::Field::None;
+ if (!m_foundLEManufacturerData.contains(address)) {
+ m_foundLEManufacturerData.insert(address, manufacturerData);
+ changedFields.setFlag(QBluetoothDeviceInfo::Field::ManufacturerData);
+ } else if (m_foundLEManufacturerData.value(address) != manufacturerData) {
+ m_foundLEManufacturerData[address] = manufacturerData;
+ changedFields.setFlag(QBluetoothDeviceInfo::Field::ManufacturerData);
+ }
+#if QT_CONFIG(winrt_btle_no_pairing)
+ if (supportsNewLEApi()) {
+ 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;
+ const LEAdvertisingInfo adInfo = m_foundLEDevicesMap.value(address);
+ QVector<QBluetoothUuid> foundServices = adInfo.services;
+ if (adInfo.rssi != rssi) {
+ m_foundLEDevicesMap[address].rssi = rssi;
+ changedFields.setFlag(QBluetoothDeviceInfo::Field::RSSI);
+ }
+ bool newServiceAdded = false;
+ for (const QBluetoothUuid &uuid : qAsConst(serviceUuids)) {
+ if (!foundServices.contains(uuid)) {
+ foundServices.append(uuid);
+ newServiceAdded = true;
+ }
+ }
+ if (!newServiceAdded) {
+ if (!changedFields.testFlag(QBluetoothDeviceInfo::Field::None)) {
+ QMetaObject::invokeMethod(this, "deviceDataChanged", Qt::AutoConnection,
+ Q_ARG(QBluetoothAddress, QBluetoothAddress(address)),
+ Q_ARG(QBluetoothDeviceInfo::Fields, changedFields),
+ Q_ARG(qint16, rssi),
+ Q_ARG(ManufacturerData, manufacturerData));
+ }
+ return S_OK;
+ }
+ m_foundLEDevicesMap[address].services = foundServices;
+ } else {
+ LEAdvertisingInfo info;
+ info.services = std::move(serviceUuids);
+ info.rssi = rssi;
+ m_foundLEDevicesMap.insert(address, info);
+ }
+
+ locker.unlock();
+ } else
+#endif
+ {
+ if (m_foundLEDevices.contains(address)) {
+ if (m_foundLEDevices.value(address) != rssi) {
+ m_foundLEDevices[address] = rssi;
+ changedFields.setFlag(QBluetoothDeviceInfo::Field::RSSI);
+ }
+ if (!changedFields.testFlag(QBluetoothDeviceInfo::Field::None)) {
+ QMetaObject::invokeMethod(this, "deviceDataChanged", Qt::AutoConnection,
+ Q_ARG(QBluetoothAddress, QBluetoothAddress(address)),
+ Q_ARG(QBluetoothDeviceInfo::Fields, changedFields),
+ Q_ARG(qint16, rssi),
+ Q_ARG(ManufacturerData, manufacturerData));
+ }
+ return S_OK;
+ }
+ m_foundLEDevices.insert(address, rssi);
+ }
leBluetoothInfoFromAddressAsync(address);
return S_OK;
}).Get(), &m_leDeviceAddedToken);
@@ -269,6 +430,7 @@ void QWinRTBluetoothDeviceDiscoveryWorker::setupLEDeviceWatcher()
void QWinRTBluetoothDeviceDiscoveryWorker::finishDiscovery()
{
emit scanFinished();
+ stopLEWatcher();
deleteLater();
}
@@ -288,9 +450,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 +484,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 +515,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 +568,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 +587,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 +608,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 +625,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 +666,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 +707,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);
@@ -531,19 +718,104 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEDeviceFound(ComPtr<IB
Q_ASSERT_SUCCEEDED(hr);
uuids.append(QBluetoothUuid(uuid));
}
+ const qint16 rssi = m_foundLEDevices.value(address);
+ const ManufacturerData manufacturerData = m_foundLEManufacturerData.value(address);
qCDebug(QT_BT_WINRT) << "Discovered BTLE device: " << QString::number(address) << btName
- << "Num UUIDs" << uuids.count();
+ << "Num UUIDs" << uuids.count() << "RSSI:" << rssi
+ << "Num manufacturer data" << manufacturerData.count();
+
+ QBluetoothDeviceInfo info(QBluetoothAddress(address), btName, 0);
+ info.setCoreConfigurations(QBluetoothDeviceInfo::LowEnergyCoreConfiguration);
+ info.setServiceUuids(uuids);
+ info.setRssi(rssi);
+ for (const quint16 key : manufacturerData.keys())
+ info.setManufacturerData(key, manufacturerData.value(key));
+ 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;
+
+ const LEAdvertisingInfo adInfo = m_foundLEDevicesMap.value(address);
+ const qint16 rssi = adInfo.rssi;
+ // Use the services obtained from the advertisement data if the device is not paired
+ if (!isPaired) {
+ uuids = adInfo.services.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));
+ }
+ }
+ const ManufacturerData manufacturerData = m_foundLEManufacturerData.value(address);
+
+ qCDebug(QT_BT_WINRT) << "Discovered BTLE device: " << QString::number(address) << btName
+ << "Num UUIDs" << uuids.count() << "RSSI:" << rssi
+ << "Num manufacturer data" << manufacturerData.count();
QBluetoothDeviceInfo info(QBluetoothAddress(address), btName, 0);
info.setCoreConfigurations(QBluetoothDeviceInfo::LowEnergyCoreConfiguration);
info.setServiceUuids(uuids, QBluetoothDeviceInfo::DataIncomplete);
+ info.setRssi(rssi);
+ for (quint16 key : manufacturerData.keys())
+ info.setManufacturerData(key, manufacturerData.value(key));
info.setCached(true);
QMetaObject::invokeMethod(this, "deviceFound", Qt::AutoConnection,
Q_ARG(QBluetoothDeviceInfo, info));
return S_OK;
}
+#endif // QT_CONFIG(winrt_btle_no_pairing)
QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate(
const QBluetoothAddress &deviceAdapter,
@@ -582,6 +854,8 @@ void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent
discoveredDevices.clear();
connect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::deviceFound,
this, &QBluetoothDeviceDiscoveryAgentPrivate::registerDevice);
+ connect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::deviceDataChanged,
+ this, &QBluetoothDeviceDiscoveryAgentPrivate::updateDeviceData);
connect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::scanFinished,
this, &QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished);
worker->start();
@@ -602,7 +876,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::stop()
{
Q_Q(QBluetoothDeviceDiscoveryAgent);
if (worker) {
- worker->stop();
+ worker->stopLEWatcher();
disconnectAndClearWorker();
emit q->canceled();
}
@@ -625,7 +899,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;
@@ -636,6 +910,30 @@ void QBluetoothDeviceDiscoveryAgentPrivate::registerDevice(const QBluetoothDevic
emit q->deviceDiscovered(info);
}
+void QBluetoothDeviceDiscoveryAgentPrivate::updateDeviceData(const QBluetoothAddress &address,
+ QBluetoothDeviceInfo::Fields fields,
+ qint16 rssi,
+ ManufacturerData manufacturerData)
+{
+ if (fields.testFlag(QBluetoothDeviceInfo::Field::None))
+ return;
+
+ Q_Q(QBluetoothDeviceDiscoveryAgent);
+ for (QList<QBluetoothDeviceInfo>::iterator iter = discoveredDevices.begin();
+ iter != discoveredDevices.end(); ++iter) {
+ if (iter->address() == address) {
+ qCDebug(QT_BT_WINRT) << "Updating data for device" << iter->name() << iter->address();
+ if (fields.testFlag(QBluetoothDeviceInfo::Field::RSSI))
+ iter->setRssi(rssi);
+ if (fields.testFlag(QBluetoothDeviceInfo::Field::ManufacturerData))
+ for (quint16 key : manufacturerData.keys())
+ iter->setManufacturerData(key, manufacturerData.value(key));
+ emit q->deviceUpdated(*iter, fields);
+ return;
+ }
+ }
+}
+
void QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished()
{
Q_Q(QBluetoothDeviceDiscoveryAgent);
@@ -645,17 +943,18 @@ void QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished()
void QBluetoothDeviceDiscoveryAgentPrivate::disconnectAndClearWorker()
{
- Q_Q(QBluetoothDeviceDiscoveryAgent);
if (!worker)
return;
disconnect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::scanFinished,
- this, &QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished);
+ this, &QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished);
disconnect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::deviceFound,
- q, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered);
+ this, &QBluetoothDeviceDiscoveryAgentPrivate::registerDevice);
+ disconnect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::deviceDataChanged,
+ this, &QBluetoothDeviceDiscoveryAgentPrivate::updateDeviceData);
if (leScanTimer) {
disconnect(leScanTimer, &QTimer::timeout,
- worker, &QWinRTBluetoothDeviceDiscoveryWorker::finishDiscovery);
+ worker, &QWinRTBluetoothDeviceDiscoveryWorker::finishDiscovery);
}
worker.clear();
}