| 1 | // Copyright (C) 2022 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 "bluezperipheralconnectionmanager_p.h" | 
| 5 | #include "device1_bluez5_p.h" | 
| 6 |  | 
| 7 | #include <QtBluetooth/QBluetoothLocalDevice> | 
| 8 | #include <QtDBus/QDBusConnection> | 
| 9 | #include <QtCore/QLoggingCategory> | 
| 10 |  | 
| 11 | QT_BEGIN_NAMESPACE | 
| 12 |  | 
| 13 | Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ) | 
| 14 |  | 
| 15 | using namespace Qt::StringLiterals; | 
| 16 |  | 
| 17 | QtBluezPeripheralConnectionManager::QtBluezPeripheralConnectionManager( | 
| 18 |         const QBluetoothAddress& localAddress, QObject* parent) | 
| 19 |     : QObject(parent), | 
| 20 |       m_localDevice(new QBluetoothLocalDevice(localAddress, this)) | 
| 21 | { | 
| 22 |     QObject::connect(sender: m_localDevice, signal: &QBluetoothLocalDevice::deviceDisconnected, | 
| 23 |                      context: this, slot: &QtBluezPeripheralConnectionManager::remoteDeviceDisconnected); | 
| 24 | } | 
| 25 |  | 
| 26 | void QtBluezPeripheralConnectionManager::remoteDeviceAccessEvent( | 
| 27 |         const QString& remoteDeviceObjectPath, quint16 mtu) | 
| 28 | { | 
| 29 |     if (m_clients.contains(key: remoteDeviceObjectPath)) | 
| 30 |         return; // Already aware of the client | 
| 31 |  | 
| 32 |     std::unique_ptr<OrgBluezDevice1Interface> device{new OrgBluezDevice1Interface( | 
| 33 |                                                      "org.bluez"_L1 , remoteDeviceObjectPath, | 
| 34 |                                                      QDBusConnection::systemBus(), this)}; | 
| 35 |  | 
| 36 |     qCDebug(QT_BT_BLUEZ) << "New LE Gatt client connected: "  << remoteDeviceObjectPath | 
| 37 |                          << device->address() << device->name() << "mtu:"  << mtu; | 
| 38 |  | 
| 39 |     RemoteDeviceDetails details{.address: QBluetoothAddress{device->address()}, .name: device->name(), .mtu: mtu}; | 
| 40 |  | 
| 41 |     m_clients.insert(key: remoteDeviceObjectPath, value: details); | 
| 42 |     if (!m_connected) { | 
| 43 |         m_connected = true; | 
| 44 |         emit connectivityStateChanged(connected: true); | 
| 45 |     } | 
| 46 |     emit remoteDeviceChanged(address: details.address, name: details.name, mtu: details.mtu); | 
| 47 | } | 
| 48 |  | 
| 49 | void QtBluezPeripheralConnectionManager::remoteDeviceDisconnected(const QBluetoothAddress& address) | 
| 50 | { | 
| 51 |     // Find if the disconnected device was gatt client | 
| 52 |     bool remoteDetailsChanged{false}; | 
| 53 |     for (auto it = m_clients.begin(); it != m_clients.end(); it++) { | 
| 54 |         if (it.value().address == address) { | 
| 55 |             qCDebug(QT_BT_BLUEZ) << "LE Gatt client disconnected:"  << address; | 
| 56 |             remoteDetailsChanged = true; | 
| 57 |             m_clients.remove(key: it.key()); | 
| 58 |             break; | 
| 59 |         } | 
| 60 |     } | 
| 61 |  | 
| 62 |     if (!remoteDetailsChanged) | 
| 63 |         return; | 
| 64 |  | 
| 65 |     if (m_clients.isEmpty() && m_connected) { | 
| 66 |         m_connected = false; | 
| 67 |         emit connectivityStateChanged(connected: false); | 
| 68 |     } | 
| 69 |  | 
| 70 |     // If a client disconnected but there are others, pick any other. | 
| 71 |     // Qt API doesn't distinguish between clients | 
| 72 |     if (!m_clients.isEmpty()) { | 
| 73 |         emit remoteDeviceChanged(address: m_clients.last().address, | 
| 74 |                                  name: m_clients.last().name, mtu: m_clients.last().mtu); | 
| 75 |     } | 
| 76 | } | 
| 77 |  | 
| 78 | void QtBluezPeripheralConnectionManager::disconnectDevices() | 
| 79 | { | 
| 80 |     for (auto it = m_clients.begin(); it != m_clients.end(); it++) { | 
| 81 |         std::unique_ptr<OrgBluezDevice1Interface> device{new OrgBluezDevice1Interface( | 
| 82 |                         "org.bluez"_L1 , it.key(), QDBusConnection::systemBus())}; | 
| 83 |         device->Disconnect(); | 
| 84 |     } | 
| 85 |     reset(); | 
| 86 | } | 
| 87 |  | 
| 88 | void QtBluezPeripheralConnectionManager::reset() | 
| 89 | { | 
| 90 |     m_connected = false; | 
| 91 |     m_clients.clear(); | 
| 92 | } | 
| 93 |  | 
| 94 | QT_END_NAMESPACE | 
| 95 |  | 
| 96 | #include "moc_bluezperipheralconnectionmanager_p.cpp" | 
| 97 |  |