Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qbluetoothlocaldevice_bluez.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <QtCore/QLoggingCategory>
5#include <QtCore/QRandomGenerator>
6#include <QtDBus/QDBusContext>
7
11
12#include "bluez/bluez5_helper_p.h"
13#include "bluez/objectmanager_p.h"
14#include "bluez/properties_p.h"
15#include "bluez/adapter1_bluez5_p.h"
16#include "bluez/device1_bluez5_p.h"
17
18QT_BEGIN_NAMESPACE
19
20Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ)
21
22using namespace QtBluetoothPrivate; // for D-Bus wrappers
23
24QBluetoothLocalDevice::QBluetoothLocalDevice(QObject *parent) :
25 QObject(parent),
26 d_ptr(new QBluetoothLocalDevicePrivate(this))
27{
28 d_ptr->currentMode = hostMode();
29}
30
31QBluetoothLocalDevice::QBluetoothLocalDevice(const QBluetoothAddress &address, QObject *parent) :
32 QObject(parent),
33 d_ptr(new QBluetoothLocalDevicePrivate(this, address))
34{
35 d_ptr->currentMode = hostMode();
36}
37
38QString QBluetoothLocalDevice::name() const
39{
40 if (d_ptr->adapter)
41 return d_ptr->adapter->alias();
42
43 return QString();
44}
45
46QBluetoothAddress QBluetoothLocalDevice::address() const
47{
48 if (d_ptr->adapter)
49 return QBluetoothAddress(d_ptr->adapter->address());
50
51 return QBluetoothAddress();
52}
53
54void QBluetoothLocalDevice::powerOn()
55{
56 if (d_ptr->adapter)
57 d_ptr->adapter->setPowered(true);
58}
59
60void QBluetoothLocalDevice::setHostMode(QBluetoothLocalDevice::HostMode mode)
61{
62 if (!isValid())
63 return;
64
65 Q_D(QBluetoothLocalDevice);
66
67 if (d->pendingHostModeChange != -1) {
68 qCWarning(QT_BT_BLUEZ) << "setHostMode() ignored due to already pending mode change";
69 return;
70 }
71
72 switch (mode) {
73 case HostDiscoverableLimitedInquiry:
74 case HostDiscoverable:
75 if (hostMode() == HostPoweredOff) {
76 // We first have to wait for BT to be powered on,
77 // then we can set the host mode correctly
78 d->pendingHostModeChange = static_cast<int>(HostDiscoverable);
79 d->adapter->setPowered(true);
80 } else {
81 d->adapter->setDiscoverable(true);
82 }
83 break;
84 case HostConnectable:
85 if (hostMode() == HostPoweredOff) {
86 d->pendingHostModeChange = static_cast<int>(HostConnectable);
87 d->adapter->setPowered(true);
88 } else {
89 d->adapter->setDiscoverable(false);
90 }
91 break;
92 case HostPoweredOff:
93 d->adapter->setPowered(false);
94 break;
95 }
96}
97
98QBluetoothLocalDevice::HostMode QBluetoothLocalDevice::hostMode() const
99{
100 if (d_ptr->adapter) {
101 if (!d_ptr->adapter->powered())
102 return HostPoweredOff;
103 else if (d_ptr->adapter->discoverable())
104 return HostDiscoverable;
105 else if (d_ptr->adapter->powered())
106 return HostConnectable;
107 }
108
109 return HostPoweredOff;
110}
111
112QList<QBluetoothAddress> QBluetoothLocalDevice::connectedDevices() const
113{
114 return d_ptr->connectedDevices();
115}
116
117QList<QBluetoothHostInfo> QBluetoothLocalDevice::allDevices()
118{
119 QList<QBluetoothHostInfo> localDevices;
120
121 initializeBluez5();
122 OrgFreedesktopDBusObjectManagerInterface manager(
123 QStringLiteral("org.bluez"), QStringLiteral("/"), QDBusConnection::systemBus());
124 QDBusPendingReply<ManagedObjectList> reply = manager.GetManagedObjects();
125 reply.waitForFinished();
126 if (reply.isError())
127 return localDevices;
128
129 ManagedObjectList managedObjectList = reply.value();
130 for (ManagedObjectList::const_iterator it = managedObjectList.constBegin();
131 it != managedObjectList.constEnd(); ++it) {
132 const InterfaceList &ifaceList = it.value();
133
134 for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd();
135 ++jt) {
136 const QString &iface = jt.key();
137 const QVariantMap &ifaceValues = jt.value();
138
139 if (iface == QStringLiteral("org.bluez.Adapter1")) {
140 QBluetoothHostInfo hostInfo;
141 const QString temp = ifaceValues.value(QStringLiteral("Address")).toString();
142
143 hostInfo.setAddress(QBluetoothAddress(temp));
144 if (hostInfo.address().isNull())
145 continue;
146 hostInfo.setName(ifaceValues.value(QStringLiteral("Name")).toString());
147 localDevices.append(hostInfo);
148 }
149 }
150 }
151 return localDevices;
152}
153
154void QBluetoothLocalDevice::requestPairing(const QBluetoothAddress &address, Pairing pairing)
155{
156 if (!isValid() || address.isNull()) {
157 QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection,
158 Q_ARG(QBluetoothLocalDevice::Error,
159 QBluetoothLocalDevice::PairingError));
160 return;
161 }
162
163 const Pairing current_pairing = pairingStatus(address);
164 if (current_pairing == pairing) {
165 if (d_ptr->adapter) {
166 // A possibly running discovery or pending pairing request should be canceled
167 if (d_ptr->pairingDiscoveryTimer && d_ptr->pairingDiscoveryTimer->isActive()) {
168 d_ptr->pairingDiscoveryTimer->stop();
169 }
170
171 if (d_ptr->pairingTarget) {
172 qCDebug(QT_BT_BLUEZ) << "Cancelling pending pairing request to" << d_ptr->pairingTarget->address();
173 QDBusPendingReply<> cancelReply = d_ptr->pairingTarget->CancelPairing();
174 d_ptr->pairingRequestCanceled = true;
175 cancelReply.waitForFinished();
176 delete d_ptr->pairingTarget;
177 d_ptr->pairingTarget = nullptr;
178 }
179 }
180 QMetaObject::invokeMethod(this, "pairingFinished", Qt::QueuedConnection,
181 Q_ARG(QBluetoothAddress, address),
182 Q_ARG(QBluetoothLocalDevice::Pairing, pairing));
183 return;
184 }
185
186 d_ptr->requestPairing(address, pairing);
187}
188
189void QBluetoothLocalDevicePrivate::requestPairing(const QBluetoothAddress &targetAddress,
190 QBluetoothLocalDevice::Pairing targetPairing)
191{
192 if (!isValid())
193 return;
194
195 //are we already discovering something? -> abort those attempts
196 if (pairingDiscoveryTimer && pairingDiscoveryTimer->isActive()) {
197 pairingDiscoveryTimer->stop();
198 QtBluezDiscoveryManager::instance()->unregisterDiscoveryInterest(adapter->path());
199 }
200
201 if (pairingTarget) {
202 delete pairingTarget;
203 pairingTarget = nullptr;
204 }
205
206 // pairing implies that the device was found
207 // if we cannot find it we may have to turn on Discovery mode for a limited amount of time
208
209 // check device doesn't already exist
210 QDBusPendingReply<ManagedObjectList> reply = manager->GetManagedObjects();
211 reply.waitForFinished();
212 if (reply.isError()) {
213 emit q_ptr->errorOccurred(QBluetoothLocalDevice::PairingError);
214 return;
215 }
216
217 ManagedObjectList managedObjectList = reply.value();
218 for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) {
219 const QDBusObjectPath &path = it.key();
220 const InterfaceList &ifaceList = it.value();
221
222 for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) {
223 const QString &iface = jt.key();
224
225 if (iface == QStringLiteral("org.bluez.Device1")) {
226
227 OrgBluezDevice1Interface device(QStringLiteral("org.bluez"),
228 path.path(),
229 QDBusConnection::systemBus());
230 if (targetAddress == QBluetoothAddress(device.address())) {
231 qCDebug(QT_BT_BLUEZ) << "Initiating direct pair to" << targetAddress.toString();
232 //device exist -> directly work with it
233 processPairing(path.path(), targetPairing);
234 return;
235 }
236 }
237 }
238 }
239
240 //no device matching -> turn on discovery
241 QtBluezDiscoveryManager::instance()->registerDiscoveryInterest(adapter->path());
242
243 address = targetAddress;
244 pairing = targetPairing;
245 if (!pairingDiscoveryTimer) {
246 pairingDiscoveryTimer = new QTimer(this);
247 pairingDiscoveryTimer->setSingleShot(true);
248 pairingDiscoveryTimer->setInterval(20000); //20s
249 connect(pairingDiscoveryTimer, &QTimer::timeout,
250 this, &QBluetoothLocalDevicePrivate::pairingDiscoveryTimedOut);
251 }
252
253 qCDebug(QT_BT_BLUEZ) << "Initiating discovery for pairing on" << targetAddress.toString();
254 pairingDiscoveryTimer->start();
255}
256
257/*!
258 * \internal
259 *
260 * Found a matching device. Now we must ensure its pairing/trusted state is as desired.
261 * If it has to be paired then we need another roundtrip through the event loop
262 * while we wait for the user to accept the pairing dialogs.
263 */
264void QBluetoothLocalDevicePrivate::processPairing(const QString &objectPath,
265 QBluetoothLocalDevice::Pairing target)
266{
267 if (pairingTarget)
268 delete pairingTarget;
269
270 //stop possibly running discovery
271 if (pairingDiscoveryTimer && pairingDiscoveryTimer->isActive()) {
272 pairingDiscoveryTimer->stop();
273
274 QtBluezDiscoveryManager::instance()->unregisterDiscoveryInterest(adapter->path());
275 }
276
277 pairingTarget = new OrgBluezDevice1Interface(QStringLiteral("org.bluez"), objectPath,
278 QDBusConnection::systemBus(), this);
279 const QBluetoothAddress targetAddress(pairingTarget->address());
280
281 Q_Q(QBluetoothLocalDevice);
282
283 switch (target) {
284 case QBluetoothLocalDevice::Unpaired: {
285 delete pairingTarget;
286 pairingTarget = nullptr;
287
288 QDBusPendingReply<> removeReply = adapter->RemoveDevice(QDBusObjectPath(objectPath));
289 auto watcher = new QDBusPendingCallWatcher(removeReply, this);
290 connect(watcher, &QDBusPendingCallWatcher::finished,
291 this, [q, targetAddress](QDBusPendingCallWatcher* watcher){
292 QDBusPendingReply<> reply = *watcher;
293 if (reply.isError())
294 emit q->errorOccurred(QBluetoothLocalDevice::PairingError);
295 else
296 emit q->pairingFinished(targetAddress, QBluetoothLocalDevice::Unpaired);
297
298 watcher->deleteLater();
299 });
300 break;
301 }
302 case QBluetoothLocalDevice::Paired:
303 case QBluetoothLocalDevice::AuthorizedPaired:
304 pairing = target;
305
306 if (!pairingTarget->paired()) {
307 qCDebug(QT_BT_BLUEZ) << "Sending pairing request to" << pairingTarget->address();
308 //initiate the pairing
309 QDBusPendingReply<> pairReply = pairingTarget->Pair();
310 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pairReply, this);
311 connect(watcher, &QDBusPendingCallWatcher::finished,
312 this, &QBluetoothLocalDevicePrivate::pairingCompleted);
313 return;
314 }
315
316 //already paired but Trust level must be adjusted
317 if (target == QBluetoothLocalDevice::AuthorizedPaired && !pairingTarget->trusted())
318 pairingTarget->setTrusted(true);
319 else if (target == QBluetoothLocalDevice::Paired && pairingTarget->trusted())
320 pairingTarget->setTrusted(false);
321
322 delete pairingTarget;
323 pairingTarget = nullptr;
324
325 emit q->pairingFinished(targetAddress, target);
326
327 break;
328 default:
329 break;
330 }
331}
332
333void QBluetoothLocalDevicePrivate::pairingDiscoveryTimedOut()
334{
335 qCWarning(QT_BT_BLUEZ) << "Discovery for pairing purposes failed. Cannot find parable device.";
336
337 QtBluezDiscoveryManager::instance()->unregisterDiscoveryInterest(adapter->path());
338
339 emit q_ptr->errorOccurred(QBluetoothLocalDevice::PairingError);
340}
341
342QBluetoothLocalDevice::Pairing QBluetoothLocalDevice::pairingStatus(
343 const QBluetoothAddress &address) const
344{
345 if (address.isNull())
346 return Unpaired;
347
348 if (isValid())
349 {
350 QDBusPendingReply<ManagedObjectList> reply = d_ptr->manager->GetManagedObjects();
351 reply.waitForFinished();
352 if (reply.isError())
353 return Unpaired;
354
355 ManagedObjectList managedObjectList = reply.value();
356 for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) {
357 const QDBusObjectPath &path = it.key();
358 const InterfaceList &ifaceList = it.value();
359
360 for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) {
361 const QString &iface = jt.key();
362
363 if (iface == QStringLiteral("org.bluez.Device1")) {
364
365 OrgBluezDevice1Interface device(QStringLiteral("org.bluez"),
366 path.path(),
367 QDBusConnection::systemBus());
368
369 if (address == QBluetoothAddress(device.address())) {
370 if (device.trusted() && device.paired())
371 return AuthorizedPaired;
372 else if (device.paired())
373 return Paired;
374 else
375 return Unpaired;
376 }
377 }
378 }
379 }
380 }
381
382 return Unpaired;
383}
384
386 QBluetoothAddress address) :
389 q_ptr(q)
390{
391 registerQBluetoothLocalDeviceMetaType();
392 initializeBluez5();
393 initializeAdapter();
394
395 connectDeviceChanges();
396}
397
398bool objectPathIsForThisDevice(const QString &adapterPath, const QString &objectPath)
399{
400 return (!adapterPath.isEmpty() && objectPath.startsWith(adapterPath));
401}
402
403void QBluetoothLocalDevicePrivate::connectDeviceChanges()
404{
405 if (isValid()) {
406 //setup property change notifications for all existing devices
407 QDBusPendingReply<ManagedObjectList> reply = manager->GetManagedObjects();
408 reply.waitForFinished();
409 if (reply.isError())
410 return;
411
412 OrgFreedesktopDBusPropertiesInterface *monitor = nullptr;
413
414 ManagedObjectList managedObjectList = reply.value();
415 for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) {
416 const QDBusObjectPath &path = it.key();
417 const InterfaceList &ifaceList = it.value();
418
419 // don't track connected devices from other adapters but the current
420 if (!objectPathIsForThisDevice(deviceAdapterPath, path.path()))
421 continue;
422
423 for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) {
424 const QString &iface = jt.key();
425 const QVariantMap &ifaceValues = jt.value();
426
427 if (iface == QStringLiteral("org.bluez.Device1")) {
428 monitor = new OrgFreedesktopDBusPropertiesInterface(QStringLiteral("org.bluez"),
429 path.path(),
430 QDBusConnection::systemBus(), this);
431 connect(monitor, &OrgFreedesktopDBusPropertiesInterface::PropertiesChanged,
432 this, &QBluetoothLocalDevicePrivate::PropertiesChanged);
433 deviceChangeMonitors.insert(path.path(), monitor);
434
435 if (ifaceValues.value(QStringLiteral("Connected"), false).toBool()) {
436 QBluetoothAddress address(ifaceValues.value(QStringLiteral("Address")).toString());
437 connectedDevicesSet.insert(address);
438 }
439 }
440 }
441 }
442 }
443}
444
445QBluetoothLocalDevicePrivate::~QBluetoothLocalDevicePrivate()
446{
447 delete adapter;
448 delete adapterProperties;
449 delete manager;
450 delete pairingTarget;
451
452 qDeleteAll(deviceChangeMonitors);
453}
454
455void QBluetoothLocalDevicePrivate::initializeAdapter()
456{
457 if (adapter)
458 return;
459
460 //get all local adapters
461 if (!manager)
462 manager = new OrgFreedesktopDBusObjectManagerInterface(
463 QStringLiteral("org.bluez"),
464 QStringLiteral("/"),
465 QDBusConnection::systemBus(), this);
466
467 connect(manager, &OrgFreedesktopDBusObjectManagerInterface::InterfacesAdded,
468 this, &QBluetoothLocalDevicePrivate::InterfacesAdded);
469 connect(manager, &OrgFreedesktopDBusObjectManagerInterface::InterfacesRemoved,
470 this, &QBluetoothLocalDevicePrivate::InterfacesRemoved);
471
472 bool ok = true;
473 const QString adapterPath = findAdapterForAddress(localAddress, &ok);
474 if (!ok || adapterPath.isEmpty())
475 return;
476
477 deviceAdapterPath = adapterPath;
478 adapter = new OrgBluezAdapter1Interface(QStringLiteral("org.bluez"), adapterPath,
479 QDBusConnection::systemBus(), this);
480
481 if (adapter) {
482 //hook up propertiesChanged for current adapter
483 adapterProperties = new OrgFreedesktopDBusPropertiesInterface(
484 QStringLiteral("org.bluez"), adapter->path(),
485 QDBusConnection::systemBus(), this);
486 connect(adapterProperties, &OrgFreedesktopDBusPropertiesInterface::PropertiesChanged,
487 this, &QBluetoothLocalDevicePrivate::PropertiesChanged);
488 }
489}
490
491void QBluetoothLocalDevicePrivate::PropertiesChanged(const QString &interface,
492 const QVariantMap &changed_properties,
493 const QStringList &/*invalidated_properties*/,
494 const QDBusMessage &)
495{
496 //qDebug() << "Change" << interface << changed_properties;
497 if (interface == QStringLiteral("org.bluez.Adapter1")) {
498 //update host mode
499 if (changed_properties.contains(QStringLiteral("Discoverable"))
500 || changed_properties.contains(QStringLiteral("Powered"))) {
501
502 QBluetoothLocalDevice::HostMode mode;
503
504 if (!adapter->powered()) {
505 mode = QBluetoothLocalDevice::HostPoweredOff;
506 } else {
507 if (adapter->discoverable())
508 mode = QBluetoothLocalDevice::HostDiscoverable;
509 else
510 mode = QBluetoothLocalDevice::HostConnectable;
511
512 if (pendingHostModeChange != -1) {
513
514 if (static_cast<int>(mode) != pendingHostModeChange) {
515 adapter->setDiscoverable(
516 pendingHostModeChange
517 == static_cast<int>(QBluetoothLocalDevice::HostDiscoverable));
518 pendingHostModeChange = -1;
519 return;
520 }
521 pendingHostModeChange = -1;
522 }
523 }
524
525 if (mode != currentMode)
526 emit q_ptr->hostModeStateChanged(mode);
527
528 currentMode = mode;
529 }
530 } else if (interface == QStringLiteral("org.bluez.Device1")
531 && changed_properties.contains(QStringLiteral("Connected"))) {
532 // update list of connected devices
533 OrgFreedesktopDBusPropertiesInterface *senderIface =
534 qobject_cast<OrgFreedesktopDBusPropertiesInterface*>(sender());
535 if (!senderIface)
536 return;
537
538 const QString currentPath = senderIface->path();
539 bool isConnected = changed_properties.value(QStringLiteral("Connected"), false).toBool();
540 OrgBluezDevice1Interface device(QStringLiteral("org.bluez"), currentPath,
541 QDBusConnection::systemBus());
542 const QBluetoothAddress changedAddress(device.address());
543 bool isInSet = connectedDevicesSet.contains(changedAddress);
544 if (isConnected && !isInSet) {
545 connectedDevicesSet.insert(changedAddress);
546 emit q_ptr->deviceConnected(changedAddress);
547 } else if (!isConnected && isInSet) {
548 connectedDevicesSet.remove(changedAddress);
549 emit q_ptr->deviceDisconnected(changedAddress);
550 }
551 }
552}
553
554void QBluetoothLocalDevicePrivate::InterfacesAdded(const QDBusObjectPath &object_path, InterfaceList interfaces_and_properties)
555{
556 if (interfaces_and_properties.contains(QStringLiteral("org.bluez.Device1"))
557 && !deviceChangeMonitors.contains(object_path.path())) {
558 // a new device was added which we need to add to list of known devices
559
560 if (objectPathIsForThisDevice(deviceAdapterPath, object_path.path())) {
561 OrgFreedesktopDBusPropertiesInterface *monitor = new OrgFreedesktopDBusPropertiesInterface(
562 QStringLiteral("org.bluez"),
563 object_path.path(),
564 QDBusConnection::systemBus());
565 connect(monitor, &OrgFreedesktopDBusPropertiesInterface::PropertiesChanged,
566 this, &QBluetoothLocalDevicePrivate::PropertiesChanged);
567 deviceChangeMonitors.insert(object_path.path(), monitor);
568
569 const QVariantMap ifaceValues = interfaces_and_properties.value(QStringLiteral("org.bluez.Device1"));
570 if (ifaceValues.value(QStringLiteral("Connected"), false).toBool()) {
571 QBluetoothAddress address(ifaceValues.value(QStringLiteral("Address")).toString());
572 connectedDevicesSet.insert(address);
573 emit q_ptr->deviceConnected(address);
574 }
575 }
576 }
577
578 if (pairingDiscoveryTimer && pairingDiscoveryTimer->isActive()
579 && interfaces_and_properties.contains(QStringLiteral("org.bluez.Device1"))) {
580 //device discovery for pairing found new remote device
581 OrgBluezDevice1Interface device(QStringLiteral("org.bluez"),
582 object_path.path(), QDBusConnection::systemBus());
583 if (!address.isNull() && address == QBluetoothAddress(device.address()))
584 processPairing(object_path.path(), pairing);
585 }
586}
587
588void QBluetoothLocalDevicePrivate::InterfacesRemoved(const QDBusObjectPath &object_path,
589 const QStringList &interfaces)
590{
591 if (deviceChangeMonitors.contains(object_path.path())
592 && interfaces.contains(QLatin1String("org.bluez.Device1"))) {
593
594 if (objectPathIsForThisDevice(deviceAdapterPath, object_path.path())) {
595 //a device was removed
596 delete deviceChangeMonitors.take(object_path.path());
597
598 //the path contains the address (e.g.: /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX)
599 //-> use it to update current list of connected devices
600 QString addressString = object_path.path().right(17);
601 addressString.replace(QStringLiteral("_"), QStringLiteral(":"));
602 const QBluetoothAddress address(addressString);
603 bool found = connectedDevicesSet.remove(address);
604 if (found)
605 emit q_ptr->deviceDisconnected(address);
606 }
607 }
608
609 if (adapter && object_path.path() == adapter->path()
610 && interfaces.contains(QLatin1String("org.bluez.Adapter1"))) {
611 qCDebug(QT_BT_BLUEZ) << "Adapter" << adapter->path() << "was removed";
612 // current adapter was removed -> invalidate the instance
613 delete adapter;
614 adapter = nullptr;
615 manager->deleteLater();
616 manager = nullptr;
617 delete adapterProperties;
618 adapterProperties = nullptr;
619
620 delete pairingTarget;
621 pairingTarget = nullptr;
622
623 // turn off connectivity monitoring
624 qDeleteAll(deviceChangeMonitors);
625 deviceChangeMonitors.clear();
626 connectedDevicesSet.clear();
627 }
628}
629
631{
632 return adapter && manager;
633}
634
635QList<QBluetoothAddress> QBluetoothLocalDevicePrivate::connectedDevices() const
636{
637 return connectedDevicesSet.values();
638}
639
640void QBluetoothLocalDevicePrivate::pairingCompleted(QDBusPendingCallWatcher *watcher)
641{
642 Q_Q(QBluetoothLocalDevice);
643 QDBusPendingReply<> reply = *watcher;
644
645 if (reply.isError()) {
646 qCWarning(QT_BT_BLUEZ) << "Failed to create pairing" << reply.error().name();
647 const bool canceledByUs =
648 (reply.error().name() == QStringLiteral("org.bluez.Error.AuthenticationCanceled"))
649 && pairingRequestCanceled;
650 if (!canceledByUs)
651 emit q->errorOccurred(QBluetoothLocalDevice::PairingError);
652
653 pairingRequestCanceled = false;
654 watcher->deleteLater();
655 return;
656 }
657
658 pairingRequestCanceled = false;
659
660 if (adapter) {
661 if (!pairingTarget) {
662 qCWarning(QT_BT_BLUEZ) << "Pairing target expected but found null pointer.";
663 emit q->errorOccurred(QBluetoothLocalDevice::PairingError);
664 watcher->deleteLater();
665 return;
666 }
667
668 if (!pairingTarget->paired()) {
669 qCWarning(QT_BT_BLUEZ) << "Device was not paired as requested";
670 emit q->errorOccurred(QBluetoothLocalDevice::PairingError);
671 watcher->deleteLater();
672 return;
673 }
674
675 const QBluetoothAddress targetAddress(pairingTarget->address());
676
677 if (pairing == QBluetoothLocalDevice::AuthorizedPaired && !pairingTarget->trusted())
678 pairingTarget->setTrusted(true);
679 else if (pairing == QBluetoothLocalDevice::Paired && pairingTarget->trusted())
680 pairingTarget->setTrusted(false);
681
682 delete pairingTarget;
683 pairingTarget = nullptr;
684
685 emit q->pairingFinished(targetAddress, pairing);
686 }
687
688 watcher->deleteLater();
689}
690
691QT_END_NAMESPACE
692
693#include "moc_qbluetoothlocaldevice_p.cpp"
QMap< QDBusObjectPath, InterfaceList > ManagedObjectList
QBluetoothLocalDevicePrivate(QBluetoothLocalDevice *=nullptr, QBluetoothAddress=QBluetoothAddress())
bool objectPathIsForThisDevice(const QString &adapterPath, const QString &objectPath)