1/*
2 * BluezQt - Asynchronous Bluez wrapper library
3 *
4 * SPDX-FileCopyrightText: 2021 Ivan Podkurkov <podkiva2@gmail.com>
5 *
6 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
7 */
8
9#include "gattcharacteristicremote_p.h"
10#include "gattcharacteristicremote.h"
11#include "gattdescriptorremote.h"
12#include "gattdescriptorremote_p.h"
13#include "device_p.h"
14#include "device.h"
15#include "adapter.h"
16#include "input.h"
17#include "input_p.h"
18#include "mediaplayer.h"
19#include "mediaplayer_p.h"
20#include "utils.h"
21#include "macros.h"
22
23namespace BluezQt
24{
25
26GattCharacteristicRemotePrivate::GattCharacteristicRemotePrivate(const QString &path, const QVariantMap &properties, const GattServiceRemotePtr &service)
27 : QObject()
28 , m_dbusProperties(nullptr)
29 , m_writeAcquired(false)
30 , m_notifyAcquired(false)
31 , m_notifying(false)
32 , m_handle()
33 , m_MTU()
34 , m_service(service)
35{
36 m_bluezGattCharacteristic = new BluezGattCharacteristic(Strings::orgBluez(), path, DBusConnection::orgBluez(), this);
37
38 init(properties);
39}
40
41void GattCharacteristicRemotePrivate::init(const QVariantMap &properties)
42{
43 m_dbusProperties = new DBusProperties(Strings::orgBluez(), m_bluezGattCharacteristic->path(),
44 DBusConnection::orgBluez(), this);
45
46 // Init properties
47 m_uuid = properties.value(QStringLiteral("UUID")).toString();
48 m_value = properties.value(QStringLiteral("Value")).toByteArray();
49 m_writeAcquired = properties.value(QStringLiteral("WriteAcquired")).toBool();
50 m_notifyAcquired = properties.value(QStringLiteral("NotifyAcquired")).toBool();
51 m_notifying = properties.value(QStringLiteral("Notifying")).toBool();
52 m_flags = properties.value(QStringLiteral("Flags")).toStringList();
53 m_handle = properties.value(QStringLiteral("Handle")).value<quint16>();
54 m_MTU = properties.value(QStringLiteral("MTU")).value<quint16>();
55}
56
57void GattCharacteristicRemotePrivate::interfacesAdded(const QString &path, const QVariantMapMap &interfaces)
58{
59 bool changed = false;
60 QVariantMapMap::const_iterator it;
61
62 for (it = interfaces.constBegin(); it != interfaces.constEnd(); ++it) {
63 if (it.key() == Strings::orgBluezGattDescriptor1()) {
64 addGattDescriptor(gattDescriptorPath: path,properties: it.value());
65 changed = true;
66 }
67 }
68
69 if (changed) {
70 Q_EMIT q.lock().data()->characteristicChanged(characteristic: q.toStrongRef());
71 }
72}
73
74void GattCharacteristicRemotePrivate::interfacesRemoved(const QString &path, const QStringList &interfaces)
75{
76 Q_UNUSED(path)
77 bool changed = false;
78
79 for (auto& interface : interfaces) {
80 if (interface == Strings::orgBluezGattDescriptor1()) {
81 removeGattDescriptor(gattDescriptorPath: path);
82 changed = true;
83 }
84 }
85
86 if (changed) {
87 Q_EMIT q.lock().data()->characteristicChanged(characteristic: q.toStrongRef());
88 }
89}
90
91void GattCharacteristicRemotePrivate::addGattDescriptor(const QString &gattDescriptorPath, const QVariantMap &properties)
92{
93 // Check if we have the right path
94 if (m_bluezGattCharacteristic->path() != properties.value(QStringLiteral("Characteristic")).value<QDBusObjectPath>().path()) {
95 return;
96 }
97
98 GattCharacteristicRemotePtr characteristic = GattCharacteristicRemotePtr(this->q);
99
100 if (!characteristic) {
101 return;
102 }
103
104 GattDescriptorRemotePtr gattDescriptor = GattDescriptorRemotePtr(new GattDescriptorRemote(gattDescriptorPath, properties, characteristic));
105 gattDescriptor->d->q = gattDescriptor.toWeakRef();
106 m_descriptors.append(t: gattDescriptor);
107
108 Q_EMIT characteristic->gattDescriptorAdded(descriptor: gattDescriptor);
109 Q_EMIT characteristic->descriptorsChanged(descriptors: m_descriptors);
110
111 // Connections
112 connect(sender: gattDescriptor.data(),signal: &GattDescriptorRemote::descriptorChanged,context: q.lock().data(),slot: &GattCharacteristicRemote::gattDescriptorChanged);
113}
114
115void GattCharacteristicRemotePrivate::removeGattDescriptor(const QString &gattDescriptorPath)
116{
117 GattCharacteristicRemotePtr characteristic = GattCharacteristicRemotePtr(this->q);
118
119 if (!characteristic) {
120 return;
121 }
122
123 GattDescriptorRemotePtr gattDescriptor = nullptr;
124 for (int i=0; i < characteristic->descriptors().size(); ++i) {
125 if (characteristic->descriptors().at(i)->ubi() == gattDescriptorPath) {
126 gattDescriptor = characteristic->descriptors().at(i);
127 }
128 }
129
130 if (gattDescriptor == nullptr) {
131 return;
132 }
133
134 m_descriptors.removeOne(t: gattDescriptor);
135
136 Q_EMIT characteristic->gattDescriptorRemoved(descriptor: gattDescriptor);
137 Q_EMIT characteristic->descriptorsChanged(descriptors: m_descriptors);
138
139 // Connections
140 disconnect(sender: gattDescriptor.data(),signal: &GattDescriptorRemote::descriptorChanged,receiver: q.lock().data(),slot: &GattCharacteristicRemote::gattDescriptorChanged);
141}
142
143QDBusPendingReply<> GattCharacteristicRemotePrivate::setDBusProperty(const QString &name, const QVariant &value)
144{
145 return m_dbusProperties->Set(interface_name: Strings::orgBluezGattCharacteristic1(), property_name: name, value: QDBusVariant(value));
146}
147
148void GattCharacteristicRemotePrivate::propertiesChanged(const QString &path, const QString &interface, const QVariantMap &changed, const QStringList &invalidated)
149{
150 Q_UNUSED(path)
151
152 if (interface == Strings::orgBluezGattDescriptor1()) {
153 for (GattDescriptorRemotePtr descriptor : m_descriptors) {
154 if (path.startsWith(s: descriptor->ubi())) {
155 descriptor->d->propertiesChanged(path, interface, changed, invalidated);
156 return;
157 }
158 }
159 } else if (interface != Strings::orgBluezGattCharacteristic1()) {
160 return;
161 }
162
163 QVariantMap::const_iterator i;
164 for (i = changed.constBegin(); i != changed.constEnd(); ++i) {
165 const QVariant &value = i.value();
166 const QString &property = i.key();
167
168 if (property == QLatin1String("UUID")) {
169 PROPERTY_CHANGED(m_uuid, toString, uuidChanged);
170 } else if (property == QLatin1String("Value")) {
171 PROPERTY_CHANGED(m_value, toByteArray, valueChanged);
172 } else if (property == QLatin1String("WriteAcquired")) {
173 PROPERTY_CHANGED(m_writeAcquired, toBool, writeAcquiredChanged);
174 } else if (property == QLatin1String("NotifyAcquired")) {
175 PROPERTY_CHANGED(m_writeAcquired, toBool, writeAcquiredChanged);
176 } else if (property == QLatin1String("Notifying")) {
177 PROPERTY_CHANGED(m_notifying, toBool, notifyingChanged);
178 } else if (property == QLatin1String("Flags")) {
179 PROPERTY_CHANGED2(m_flags, value.toStringList(), flagsChanged);
180 } else if (property == QLatin1String("Handle")) {
181 PROPERTY_CHANGED2(m_handle, value.value<quint16>(), handleChanged);
182 } else if (property == QLatin1String("MTU")) {
183 PROPERTY_CHANGED2(m_MTU, value.value<quint16>(), MTUChanged);
184 }
185 }
186
187 for (auto& property : invalidated) {
188 if (property == QLatin1String("UUID")) {
189 PROPERTY_INVALIDATED(m_uuid, QString(), uuidChanged);
190 } else if (property == QLatin1String("Value")) {
191 PROPERTY_INVALIDATED(m_value, QByteArray(), valueChanged);
192 } else if (property == QLatin1String("WriteAcquired")) {
193 PROPERTY_INVALIDATED(m_writeAcquired, false, writeAcquiredChanged);
194 } else if (property == QLatin1String("NotifyAcquired")) {
195 PROPERTY_INVALIDATED(m_writeAcquired, false, writeAcquiredChanged);
196 } else if (property == QLatin1String("Notifying")) {
197 PROPERTY_INVALIDATED(m_notifying, false, notifyingChanged);
198 } else if (property == QLatin1String("Flags")) {
199 PROPERTY_INVALIDATED(m_flags, QStringList(), flagsChanged);
200 } else if (property == QLatin1String("Handle")) {
201 PROPERTY_INVALIDATED(m_handle, quint16(), handleChanged);
202 } else if (property == QLatin1String("MTU")) {
203 PROPERTY_INVALIDATED(m_MTU, quint16(), MTUChanged);
204 }
205 }
206
207 q.lock().data()->characteristicChanged(characteristic: q.toStrongRef());
208}
209
210} // namespace BluezQt
211
212#include "moc_gattcharacteristicremote_p.cpp"
213

source code of bluez-qt/src/gattcharacteristicremote_p.cpp