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 | |