9#include <QtBluetooth/private/qbluetoothdevicewatcher_winrt_p.h>
10#include <QtBluetooth/private/qbluetoothutils_winrt_p.h>
11#include <QtBluetooth/private/qtbluetoothglobal_p.h>
13#include <QtCore/QLoggingCategory>
14#include <QtCore/QMutex>
15#include <QtCore/qendian.h>
17#include <winrt/Windows.Devices.Bluetooth.h>
18#include <winrt/Windows.Devices.Bluetooth.Advertisement.h>
19#include <winrt/Windows.Devices.Bluetooth.Rfcomm.h>
20#include <winrt/Windows.Devices.Bluetooth.GenericAttributeProfile.h>
21#include <winrt/Windows.Devices.Enumeration.h>
22#include <winrt/Windows.Foundation.h>
23#include <winrt/Windows.Foundation.Collections.h>
24#include <winrt/Windows.Storage.Streams.h>
26using namespace winrt::Windows::Devices::Bluetooth;
27using namespace winrt::Windows::Devices::Bluetooth::Advertisement;
28using namespace winrt::Windows::Devices::Bluetooth::GenericAttributeProfile;
29using namespace winrt::Windows::Devices::Bluetooth::Rfcomm;
30using namespace winrt::Windows::Devices::Enumeration;
31using namespace winrt::Windows::Foundation;
32using namespace winrt::Windows::Storage::Streams;
36QT_IMPL_METATYPE_EXTERN(ManufacturerData)
37QT_IMPL_METATYPE_EXTERN(ServiceData)
39Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINDOWS)
41static QByteArray byteArrayFromBuffer(
const IBuffer &buffer)
43 const uint8_t *data = buffer.data();
44 return QByteArray(
reinterpret_cast<
const char *>(data),
45 static_cast<qsizetype>(buffer.Length()));
48static ManufacturerData extractManufacturerData(
const BluetoothLEAdvertisement &ad)
51 const auto data = ad.ManufacturerData();
52 for (
const auto &item : data) {
53 const uint16_t id = item.CompanyId();
54 const QByteArray bufferData = byteArrayFromBuffer(item.Data());
56 qCWarning(QT_BT_WINDOWS) <<
"Company ID already present in manufacturer data.";
57 ret.insert(id, bufferData);
62static ServiceData extractServiceData(
const BluetoothLEAdvertisement &ad)
64 static constexpr int serviceDataTypes[3] = { 0x16, 0x20, 0x21 };
68 for (
const auto &serviceDataType : serviceDataTypes) {
69 const auto dataSections = ad.GetSectionsByType(serviceDataType);
70 for (
const auto §ion : dataSections) {
71 const unsigned char dataType = section.DataType();
72 const QByteArray bufferData = byteArrayFromBuffer(section.Data());
73 if (dataType == 0x16) {
74 Q_ASSERT(bufferData.size() >= 2);
75 ret.insert(QBluetoothUuid(qFromLittleEndian<quint16>(bufferData.constData())),
76 bufferData.right(bufferData.length() - 2));
77 }
else if (dataType == 0x20) {
78 Q_ASSERT(bufferData.size() >= 4);
79 ret.insert(QBluetoothUuid(qFromLittleEndian<quint32>(bufferData.constData())),
80 bufferData.right(bufferData.length() - 4));
81 }
else if (dataType == 0x21) {
82 Q_ASSERT(bufferData.size() >= 16);
83 ret.insert(QBluetoothUuid(qToBigEndian<QUuid::Id128Bytes>(
84 qFromLittleEndian<QUuid::Id128Bytes>(bufferData.constData()))),
85 bufferData.right(bufferData.length() - 16));
94static GUID fromWinRtGuid(
const winrt::guid &guid)
100 { guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
101 guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7] }
106class AdvertisementWatcherWrapper :
public QObject,
107 public std::enable_shared_from_this<AdvertisementWatcherWrapper>
111 AdvertisementWatcherWrapper() {}
112 ~AdvertisementWatcherWrapper()
118 m_watcher.AllowExtendedAdvertisements(
true);
119 m_watcher.ScanningMode(BluetoothLEScanningMode::Active);
128 unsubscribeFromEvents();
136 void advertisementDataReceived(quint64 address, qint16 rssi,
137 const ManufacturerData &manufacturerData,
138 const ServiceData &serviceData,
139 const QList<QBluetoothUuid> &uuids);
141 void subscribeToEvents()
145 auto thisPtr = shared_from_this();
146 m_receivedToken = m_watcher.Received(
147 [thisPtr](BluetoothLEAdvertisementWatcher,
148 BluetoothLEAdvertisementReceivedEventArgs args) {
149 const uint64_t address = args.BluetoothAddress();
150 const short rssi = args.RawSignalStrengthInDBm();
151 const BluetoothLEAdvertisement ad = args.Advertisement();
153 const ManufacturerData manufacturerData = extractManufacturerData(ad);
154 const ServiceData serviceData = extractServiceData(ad);
156 QList<QBluetoothUuid> serviceUuids;
157 const auto guids = ad.ServiceUuids();
158 for (
const auto &guid : guids) {
159 const GUID uuid = fromWinRtGuid(guid);
160 serviceUuids.append(QBluetoothUuid(uuid));
163 emit thisPtr->advertisementDataReceived(address, rssi, manufacturerData,
164 serviceData, serviceUuids);
167 void unsubscribeFromEvents()
169 m_watcher.Received(m_receivedToken);
173 const auto status = m_watcher.Status();
174 return status == BluetoothLEAdvertisementWatcherStatus::Started
175 || status == BluetoothLEAdvertisementWatcherStatus::Aborted;
178 BluetoothLEAdvertisementWatcher m_watcher;
179 winrt::event_token m_receivedToken;
186 L"System.Devices.Aep.ProtocolId:=\"{e0cbf06c-cd8b-4647-bb8a-263b43f0f974}\"";
203 void startDeviceDiscovery(QBluetoothDeviceDiscoveryAgent::DiscoveryMethod mode);
205 std::shared_ptr<QBluetoothDeviceWatcherWinRT> createDeviceWatcher(winrt::hstring selector,
207 void generateError(QBluetoothDeviceDiscoveryAgent::Error error,
const char *msg =
nullptr);
208 void invokeDeviceFoundWithDebug(
const QBluetoothDeviceInfo &info);
209 void finishDiscovery();
210 bool isFinished()
const;
213 void getClassicDeviceFromId(
const winrt::hstring &id);
214 void handleClassicDevice(
const BluetoothDevice &device);
215 void handleRfcommServices(
const RfcommDeviceServicesResult &servicesResult,
216 uint64_t address,
const QString &name, uint32_t classOfDeviceInt,
220 void getLowEnergyDeviceFromId(
const winrt::hstring &id);
221 void handleLowEnergyDevice(
const BluetoothLEDevice &device);
222 void handleGattServices(
const GattDeviceServicesResult &servicesResult,
223 QBluetoothDeviceInfo &info);
226 std::shared_ptr<AdvertisementWatcherWrapper> createAdvertisementWatcher();
229 Q_INVOKABLE
void decrementPendingDevicesCountAndCheckFinished(
230 std::shared_ptr<QWinRTBluetoothDeviceDiscoveryWorker> worker);
235 qint16 rssi, ManufacturerData manufacturerData, ServiceData serviceData);
241 void onDeviceEnumerationCompleted(
int watcherId);
243 void onAdvertisementDataReceived(quint64 address, qint16 rssi,
244 const ManufacturerData &manufacturerData,
245 const ServiceData &serviceData,
246 const QList<QBluetoothUuid> &uuids);
248 void stopAdvertisementWatcher();
251 struct LEAdvertisingInfo {
252 QList<QBluetoothUuid> services;
253 ManufacturerData manufacturerData;
254 ServiceData serviceData;
258 quint8 requestedModes = 0;
259 QMutex m_leDevicesMutex;
260 QMap<quint64, LEAdvertisingInfo> m_foundLEDevicesMap;
261 int m_pendingDevices = 0;
263 static constexpr int ClassicWatcherId = 1;
264 static constexpr int LowEnergyWatcherId = 2;
266 std::shared_ptr<QBluetoothDeviceWatcherWinRT> m_classicWatcher;
267 std::shared_ptr<QBluetoothDeviceWatcherWinRT> m_lowEnergyWatcher;
268 std::shared_ptr<AdvertisementWatcherWrapper> m_advertisementWatcher;
269 bool m_classicScanStarted =
false;
270 bool m_lowEnergyScanStarted =
false;
271 QTimer *m_leScanTimer =
nullptr;
275 std::shared_ptr<QWinRTBluetoothDeviceDiscoveryWorker> worker)
277 QMetaObject::invokeMethod(worker.get(),
"decrementPendingDevicesCountAndCheckFinished",
278 Qt::QueuedConnection,
279 Q_ARG(std::shared_ptr<QWinRTBluetoothDeviceDiscoveryWorker>,
284 QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods,
int interval)
285 : requestedModes(methods)
287 qRegisterMetaType<QBluetoothDeviceInfo>();
288 qRegisterMetaType<QBluetoothDeviceInfo::Fields>();
289 qRegisterMetaType<ManufacturerData>();
290 qRegisterMetaType<std::shared_ptr<QWinRTBluetoothDeviceDiscoveryWorker>>();
292 m_classicWatcher = createDeviceWatcher(ClassicDeviceSelector, ClassicWatcherId);
295 const auto leSelector = BluetoothLEDevice::GetDeviceSelectorFromPairingState(
true);
296 m_lowEnergyWatcher = createDeviceWatcher(leSelector, LowEnergyWatcherId);
297 m_advertisementWatcher = createAdvertisementWatcher();
304 m_leScanTimer =
new QTimer(
this);
305 m_leScanTimer->setSingleShot(
true);
306 m_leScanTimer->setInterval(interval);
307 connect(m_leScanTimer, &QTimer::timeout,
this,
308 &QWinRTBluetoothDeviceDiscoveryWorker::stopAdvertisementWatcher);
319 if (requestedModes & QBluetoothDeviceDiscoveryAgent::ClassicMethod) {
320 if (m_classicWatcher && m_classicWatcher->init()) {
321 m_classicWatcher->start();
322 m_classicScanStarted =
true;
324 generateError(QBluetoothDeviceDiscoveryAgent::Error::UnknownError,
325 "Could not start classic device watcher");
328 if (requestedModes & QBluetoothDeviceDiscoveryAgent::LowEnergyMethod) {
329 if (m_lowEnergyWatcher && m_lowEnergyWatcher->init()) {
330 m_lowEnergyWatcher->start();
331 m_lowEnergyScanStarted =
true;
333 generateError(QBluetoothDeviceDiscoveryAgent::Error::UnknownError,
334 "Could not start low energy device watcher");
336 if (m_advertisementWatcher) {
337 m_advertisementWatcher->init();
338 m_advertisementWatcher->start();
340 m_leScanTimer->start();
342 generateError(QBluetoothDeviceDiscoveryAgent::Error::UnknownError,
343 "Could not start low energy advertisement watcher");
347 qCDebug(QT_BT_WINDOWS) <<
"Worker started";
352 if (m_leScanTimer && m_leScanTimer->isActive())
353 m_leScanTimer->stop();
354 m_classicWatcher->stop();
355 m_lowEnergyWatcher->stop();
356 m_advertisementWatcher->stop();
369 return (m_pendingDevices == 0) && !m_lowEnergyScanStarted && !m_classicScanStarted
370 && (m_leScanTimer && !m_leScanTimer->isActive());
375 if (watcherId == ClassicWatcherId)
376 getClassicDeviceFromId(deviceId);
377 else if (watcherId == LowEnergyWatcherId)
378 getLowEnergyDeviceFromId(deviceId);
383 qCDebug(QT_BT_WINDOWS) << (watcherId == ClassicWatcherId ?
"BT" :
"BTLE")
384 <<
"enumeration completed";
385 if (watcherId == ClassicWatcherId) {
386 m_classicWatcher->stop();
387 m_classicScanStarted =
false;
388 }
else if (watcherId == LowEnergyWatcherId) {
389 m_lowEnergyWatcher->stop();
390 m_lowEnergyScanStarted =
false;
398 quint64 address, qint16 rssi,
const ManufacturerData &manufacturerData,
399 const ServiceData &serviceData,
const QList<QBluetoothUuid> &uuids)
402 bool needDiscoverServices =
false;
404 QMutexLocker locker(&m_leDevicesMutex);
405 if (m_foundLEDevicesMap.contains(address)) {
406 QBluetoothDeviceInfo::Fields changedFields = QBluetoothDeviceInfo::Field::None;
407 const LEAdvertisingInfo adInfo = m_foundLEDevicesMap.value(address);
408 QList<QBluetoothUuid> foundServices = adInfo.services;
409 if (adInfo.rssi != rssi) {
410 m_foundLEDevicesMap[address].rssi = rssi;
411 changedFields.setFlag(QBluetoothDeviceInfo::Field::RSSI);
413 if (adInfo.manufacturerData != manufacturerData) {
414 m_foundLEDevicesMap[address].manufacturerData.insert(manufacturerData);
415 if (adInfo.manufacturerData != m_foundLEDevicesMap[address].manufacturerData)
416 changedFields.setFlag(QBluetoothDeviceInfo::Field::ManufacturerData);
418 if (adInfo.serviceData != serviceData) {
419 m_foundLEDevicesMap[address].serviceData.insert(serviceData);
420 if (adInfo.serviceData != m_foundLEDevicesMap[address].serviceData)
421 changedFields.setFlag((QBluetoothDeviceInfo::Field::ServiceData));
423 for (
const QBluetoothUuid &uuid : std::as_const(uuids)) {
424 if (!foundServices.contains(uuid)) {
425 foundServices.append(uuid);
426 needDiscoverServices =
true;
429 if (!needDiscoverServices) {
430 if (!changedFields.testFlag(QBluetoothDeviceInfo::Field::None)) {
431 QMetaObject::invokeMethod(
this,
"deviceDataChanged", Qt::AutoConnection,
432 Q_ARG(QBluetoothAddress, QBluetoothAddress(address)),
433 Q_ARG(QBluetoothDeviceInfo::Fields, changedFields),
435 Q_ARG(ManufacturerData, manufacturerData),
436 Q_ARG(ServiceData, serviceData));
439 m_foundLEDevicesMap[address].services = foundServices;
441 needDiscoverServices =
true;
442 LEAdvertisingInfo info;
443 info.services = std::move(uuids);
444 info.manufacturerData = std::move(manufacturerData);
445 info.serviceData = std::move(serviceData);
447 m_foundLEDevicesMap.insert(address, info);
450 if (needDiscoverServices) {
452 auto thisPtr = shared_from_this();
453 auto asyncOp = BluetoothLEDevice::FromBluetoothAddressAsync(address);
454 asyncOp.Completed([thisPtr, address](
auto &&op, AsyncStatus status) {
456 if (status == AsyncStatus::Completed) {
457 BluetoothLEDevice device = op.GetResults();
459 thisPtr->handleLowEnergyDevice(device);
464 qCDebug(QT_BT_WINDOWS) <<
"Failed to get LE device from address"
465 << QBluetoothAddress(address);
474 m_advertisementWatcher->stop();
479std::shared_ptr<QBluetoothDeviceWatcherWinRT>
482 auto watcher = std::make_shared<QBluetoothDeviceWatcherWinRT>(
483 watcherId, selector, DeviceInformationKind::AssociationEndpoint);
485 connect(watcher.get(), &QBluetoothDeviceWatcherWinRT::deviceAdded,
486 this, &QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothDeviceFound,
487 Qt::QueuedConnection);
488 connect(watcher.get(), &QBluetoothDeviceWatcherWinRT::enumerationCompleted,
489 this, &QWinRTBluetoothDeviceDiscoveryWorker::onDeviceEnumerationCompleted,
490 Qt::QueuedConnection);
496 QBluetoothDeviceDiscoveryAgent::Error error,
const char *msg)
498 emit errorOccured(error);
499 qCWarning(QT_BT_WINDOWS) << msg;
504 qCDebug(QT_BT_WINDOWS) <<
"Discovered BTLE device: " << info.address() << info.name()
505 <<
"Num UUIDs" << info.serviceUuids().size() <<
"RSSI:" << info.rssi()
506 <<
"Num manufacturer data" << info.manufacturerData().size()
507 <<
"Num service data" << info.serviceData().size();
509 QMetaObject::invokeMethod(
this,
"deviceFound", Qt::AutoConnection,
510 Q_ARG(QBluetoothDeviceInfo, info));
517 auto thisPtr = shared_from_this();
518 auto asyncOp = BluetoothDevice::FromIdAsync(id);
519 asyncOp.Completed([thisPtr](
auto &&op, AsyncStatus status) {
521 if (status == AsyncStatus::Completed) {
522 BluetoothDevice device = op.GetResults();
524 thisPtr->handleClassicDevice(device);
529 qCDebug(QT_BT_WINDOWS) <<
"Failed to get Classic device from id";
538 const uint64_t address = device.BluetoothAddress();
539 const std::wstring name { device.Name() };
540 const QString btName = QString::fromStdWString(name);
541 const uint32_t deviceClass = device.ClassOfDevice().RawValue();
547 const bool isCached = device.DeviceInformation().Pairing().IsPaired();
549 auto thisPtr = shared_from_this();
550 auto asyncOp = device.GetRfcommServicesAsync();
551 asyncOp.Completed([thisPtr, address, btName, deviceClass, isCached]
552 (
auto &&op, AsyncStatus status) {
554 if (status == AsyncStatus::Completed) {
555 auto servicesResult = op.GetResults();
556 if (servicesResult) {
557 thisPtr->handleRfcommServices(servicesResult, address, btName,
558 deviceClass, isCached);
563 qCDebug(QT_BT_WINDOWS) <<
"Failed to get RFCOMM services for device" << btName;
571 const RfcommDeviceServicesResult &servicesResult, uint64_t address,
572 const QString &name, uint32_t classOfDeviceInt,
bool isCached)
575 auto shared = shared_from_this();
576 auto guard = qScopeGuard([shared]() {
581 const auto error = servicesResult.Error();
582 if (error != BluetoothError::Success) {
583 qCWarning(QT_BT_WINDOWS) <<
"Obtain device services completed with BluetoothError"
584 <<
static_cast<
int>(error);
588 const auto services = servicesResult.Services();
589 QList<QBluetoothUuid> uuids;
590 for (
const auto &service : services) {
591 const auto serviceId = service.ServiceId();
592 const GUID uuid = fromWinRtGuid(serviceId.Uuid());
593 uuids.append(QBluetoothUuid(uuid));
596 const QBluetoothAddress btAddress(address);
598 qCDebug(QT_BT_WINDOWS) <<
"Discovered BT device: " << btAddress << name
599 <<
"Num UUIDs" << uuids.size();
601 QBluetoothDeviceInfo info(btAddress, name, classOfDeviceInt);
602 info.setCoreConfigurations(QBluetoothDeviceInfo::BaseRateCoreConfiguration);
603 info.setServiceUuids(uuids);
604 info.setCached(isCached);
606 QMetaObject::invokeMethod(
this,
"deviceFound", Qt::AutoConnection,
607 Q_ARG(QBluetoothDeviceInfo, info));
611 std::shared_ptr<QWinRTBluetoothDeviceDiscoveryWorker> worker)
625 auto asyncOp = BluetoothLEDevice::FromIdAsync(id);
626 auto thisPtr = shared_from_this();
627 asyncOp.Completed([thisPtr](
auto &&op, AsyncStatus status) {
629 if (status == AsyncStatus::Completed) {
630 BluetoothLEDevice device = op.GetResults();
632 thisPtr->handleLowEnergyDevice(device);
637 qCDebug(QT_BT_WINDOWS) <<
"Failed to get LE device from id";
646 const uint64_t address = device.BluetoothAddress();
647 const std::wstring name { device.Name() };
648 const QString btName = QString::fromStdWString(name);
649 const bool isPaired = device.DeviceInformation().Pairing().IsPaired();
651 m_leDevicesMutex.lock();
652 const LEAdvertisingInfo adInfo = m_foundLEDevicesMap.value(address);
653 m_leDevicesMutex.unlock();
654 const ManufacturerData manufacturerData = adInfo.manufacturerData;
655 const ServiceData serviceData = adInfo.serviceData;
656 const qint16 rssi = adInfo.rssi;
658 QBluetoothDeviceInfo info(QBluetoothAddress(address), btName, 0);
659 info.setCoreConfigurations(QBluetoothDeviceInfo::LowEnergyCoreConfiguration);
661 for (quint16 key : manufacturerData.keys())
662 info.setManufacturerData(key, manufacturerData.value(key));
663 for (QBluetoothUuid key : serviceData.keys())
664 info.setServiceData(key, serviceData.value(key));
675 info.setCached(isPaired);
679 info.setServiceUuids(adInfo.services);
681 invokeDeviceFoundWithDebug(info);
683 auto asyncOp = device.GetGattServicesAsync();
684 auto thisPtr = shared_from_this();
685 asyncOp.Completed([thisPtr, info](
auto &&op, AsyncStatus status)
mutable {
686 if (status == AsyncStatus::Completed) {
687 auto servicesResult = op.GetResults();
688 if (servicesResult) {
689 thisPtr->handleGattServices(servicesResult, info);
694 qCDebug(QT_BT_WINDOWS) <<
"Failed to get GATT services for device" << info.name();
702 const GattDeviceServicesResult &servicesResult, QBluetoothDeviceInfo &info)
705 auto shared = shared_from_this();
706 auto guard = qScopeGuard([shared]() {
711 const auto status = servicesResult.Status();
712 if (status == GattCommunicationStatus::Success) {
713 const auto services = servicesResult.Services();
714 QList<QBluetoothUuid> uuids;
715 for (
const auto &service : services) {
716 const GUID uuid = fromWinRtGuid(service.Uuid());
717 uuids.append(QBluetoothUuid(uuid));
719 info.setServiceUuids(uuids);
721 qCWarning(QT_BT_WINDOWS) <<
"Obtaining LE services finished with status"
722 <<
static_cast<
int>(status);
724 invokeDeviceFoundWithDebug(info);
727std::shared_ptr<AdvertisementWatcherWrapper>
730 auto watcher = std::make_shared<AdvertisementWatcherWrapper>();
732 connect(watcher.get(), &AdvertisementWatcherWrapper::advertisementDataReceived,
733 this, &QWinRTBluetoothDeviceDiscoveryWorker::onAdvertisementDataReceived,
734 Qt::QueuedConnection);
739QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate(
740 const QBluetoothAddress &deviceAdapter, QBluetoothDeviceDiscoveryAgent *parent)
741 : q_ptr(parent), adapterAddress(deviceAdapter)
743 mainThreadCoInit(
this);
746QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate()
748 disconnectAndClearWorker();
749 mainThreadCoUninit(
this);
752bool QBluetoothDeviceDiscoveryAgentPrivate::isActive()
const
754 return worker !=
nullptr;
757QBluetoothDeviceDiscoveryAgent::DiscoveryMethods QBluetoothDeviceDiscoveryAgent::supportedDiscoveryMethods()
759 return (ClassicMethod | LowEnergyMethod);
762void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods)
764 QBluetoothLocalDevice adapter(adapterAddress);
765 if (!adapter.isValid()) {
766 qCWarning(QT_BT_WINDOWS) <<
"Cannot find Bluetooth adapter for device search";
767 lastError = QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError;
768 errorString = QBluetoothDeviceDiscoveryAgent::tr(
"Cannot find valid Bluetooth adapter.");
769 emit q_ptr->errorOccurred(lastError);
771 }
else if (adapter.hostMode() == QBluetoothLocalDevice::HostPoweredOff) {
772 qCWarning(QT_BT_WINDOWS) <<
"Bluetooth adapter powered off";
773 lastError = QBluetoothDeviceDiscoveryAgent::PoweredOffError;
774 errorString = QBluetoothDeviceDiscoveryAgent::tr(
"Bluetooth adapter powered off.");
775 emit q_ptr->errorOccurred(lastError);
782 worker = std::make_shared<QWinRTBluetoothDeviceDiscoveryWorker>(methods,
783 lowEnergySearchTimeout);
784 lastError = QBluetoothDeviceDiscoveryAgent::NoError;
786 discoveredDevices.clear();
787 connect(worker.get(), &QWinRTBluetoothDeviceDiscoveryWorker::deviceFound,
788 this, &QBluetoothDeviceDiscoveryAgentPrivate::registerDevice);
789 connect(worker.get(), &QWinRTBluetoothDeviceDiscoveryWorker::deviceDataChanged,
790 this, &QBluetoothDeviceDiscoveryAgentPrivate::updateDeviceData);
791 connect(worker.get(), &QWinRTBluetoothDeviceDiscoveryWorker::errorOccured,
792 this, &QBluetoothDeviceDiscoveryAgentPrivate::onErrorOccured);
793 connect(worker.get(), &QWinRTBluetoothDeviceDiscoveryWorker::scanFinished,
794 this, &QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished);
798void QBluetoothDeviceDiscoveryAgentPrivate::stop()
800 Q_Q(QBluetoothDeviceDiscoveryAgent);
803 disconnectAndClearWorker();
808void QBluetoothDeviceDiscoveryAgentPrivate::registerDevice(
const QBluetoothDeviceInfo &info)
810 Q_Q(QBluetoothDeviceDiscoveryAgent);
812 for (QList<QBluetoothDeviceInfo>::iterator iter = discoveredDevices.begin();
813 iter != discoveredDevices.end(); ++iter) {
814 if (iter->address() == info.address()) {
815 qCDebug(QT_BT_WINDOWS) <<
"Updating device" << iter->name() << iter->address();
817 QList<QBluetoothUuid> uuids = iter->serviceUuids();
818 uuids.append(info.serviceUuids());
819 const QSet<QBluetoothUuid> uuidSet(uuids.begin(), uuids.end());
820 if (iter->serviceUuids().size() != uuidSet.size())
821 iter->setServiceUuids(uuidSet.values().toVector());
822 if (iter->coreConfigurations() != info.coreConfigurations())
823 iter->setCoreConfigurations(QBluetoothDeviceInfo::BaseRateAndLowEnergyCoreConfiguration);
828 discoveredDevices << info;
829 emit q->deviceDiscovered(info);
832void QBluetoothDeviceDiscoveryAgentPrivate::updateDeviceData(
const QBluetoothAddress &address,
833 QBluetoothDeviceInfo::Fields fields,
835 ManufacturerData manufacturerData,
836 ServiceData serviceData)
838 if (fields.testFlag(QBluetoothDeviceInfo::Field::None))
841 Q_Q(QBluetoothDeviceDiscoveryAgent);
842 for (QList<QBluetoothDeviceInfo>::iterator iter = discoveredDevices.begin();
843 iter != discoveredDevices.end(); ++iter) {
844 if (iter->address() == address) {
845 qCDebug(QT_BT_WINDOWS) <<
"Updating data for device" << iter->name() << iter->address();
846 if (fields.testFlag(QBluetoothDeviceInfo::Field::RSSI))
848 if (fields.testFlag(QBluetoothDeviceInfo::Field::ManufacturerData))
849 for (quint16 key : manufacturerData.keys())
850 iter->setManufacturerData(key, manufacturerData.value(key));
851 if (fields.testFlag(QBluetoothDeviceInfo::Field::ServiceData))
852 for (QBluetoothUuid key : serviceData.keys())
853 iter->setServiceData(key, serviceData.value(key));
856 iter->setCached(
false);
857 emit q->deviceUpdated(*iter, fields);
863void QBluetoothDeviceDiscoveryAgentPrivate::onErrorOccured(QBluetoothDeviceDiscoveryAgent::Error e)
865 Q_Q(QBluetoothDeviceDiscoveryAgent);
867 emit q->errorOccurred(e);
870void QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished()
872 Q_Q(QBluetoothDeviceDiscoveryAgent);
873 disconnectAndClearWorker();
877void QBluetoothDeviceDiscoveryAgentPrivate::disconnectAndClearWorker()
882 disconnect(worker.get(), &QWinRTBluetoothDeviceDiscoveryWorker::scanFinished,
883 this, &QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished);
884 disconnect(worker.get(), &QWinRTBluetoothDeviceDiscoveryWorker::deviceFound,
885 this, &QBluetoothDeviceDiscoveryAgentPrivate::registerDevice);
886 disconnect(worker.get(), &QWinRTBluetoothDeviceDiscoveryWorker::deviceDataChanged,
887 this, &QBluetoothDeviceDiscoveryAgentPrivate::updateDeviceData);
888 disconnect(worker.get(), &QWinRTBluetoothDeviceDiscoveryWorker::errorOccured,
889 this, &QBluetoothDeviceDiscoveryAgentPrivate::onErrorOccured);
896#include <qbluetoothdevicediscoveryagent_winrt.moc>
void deviceDataChanged(const QBluetoothAddress &address, QBluetoothDeviceInfo::Fields, qint16 rssi, ManufacturerData manufacturerData, ServiceData serviceData)
void errorOccured(QBluetoothDeviceDiscoveryAgent::Error error)
~QWinRTBluetoothDeviceDiscoveryWorker()
static void invokeDecrementPendingDevicesCountAndCheckFinished(std::shared_ptr< QWinRTBluetoothDeviceDiscoveryWorker > worker)
static const winrt::hstring ClassicDeviceSelector