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
11QT_BEGIN_NAMESPACE
12
13Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ)
14
15using namespace Qt::StringLiterals;
16
17QtBluezPeripheralConnectionManager::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
26void 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
49void 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
78void 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
88void QtBluezPeripheralConnectionManager::reset()
89{
90 m_connected = false;
91 m_clients.clear();
92}
93
94QT_END_NAMESPACE
95
96#include "moc_bluezperipheralconnectionmanager_p.cpp"
97

source code of qtconnectivity/src/bluetooth/bluez/bluezperipheralconnectionmanager.cpp