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 "gattserviceremote_p.h" |
10 | #include "gattserviceremote.h" |
11 | #include "gattcharacteristicremote_p.h" |
12 | #include "gattcharacteristicremote.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 | |
23 | namespace BluezQt |
24 | { |
25 | |
26 | GattServiceRemotePrivate::GattServiceRemotePrivate(const QString &path, const QVariantMap &properties, const DevicePtr &device) |
27 | : QObject() |
28 | , m_dbusProperties(nullptr) |
29 | , m_primary(false) |
30 | , m_device(device) |
31 | , m_handle(0) |
32 | { |
33 | m_bluezGattService = new BluezGattService(Strings::orgBluez(), path, DBusConnection::orgBluez(), this); |
34 | |
35 | init(properties); |
36 | } |
37 | |
38 | void GattServiceRemotePrivate::init(const QVariantMap &properties) |
39 | { |
40 | m_dbusProperties = new DBusProperties(Strings::orgBluez(), m_bluezGattService->path(), |
41 | DBusConnection::orgBluez(), this); |
42 | |
43 | // Init properties |
44 | m_uuid = properties.value(QStringLiteral("UUID" )).toString(); |
45 | m_primary = properties.value(QStringLiteral("Primary" )).toBool(); |
46 | m_includes = properties.value(QStringLiteral("Includes" )).value<QList<QDBusObjectPath>>(); |
47 | m_handle = static_cast<quint16>(properties.value(QStringLiteral("Handle" )).toUInt()); |
48 | |
49 | } |
50 | |
51 | void GattServiceRemotePrivate::interfacesAdded(const QString &path, const QVariantMapMap &interfaces) |
52 | { |
53 | bool changed = false; |
54 | QVariantMapMap::const_iterator it; |
55 | |
56 | for (it = interfaces.constBegin(); it != interfaces.constEnd(); ++it) { |
57 | if (it.key() == Strings::orgBluezGattCharacteristic1()) { |
58 | addGattCharacteristic(gattCharacteristicPath: path,properties: it.value()); |
59 | changed = true; |
60 | } |
61 | } |
62 | |
63 | for (auto& ch: m_characteristics) { |
64 | if (path.startsWith(s: ch->ubi())) { |
65 | ch->d->interfacesAdded(path, interfaces); |
66 | changed = true; |
67 | } |
68 | } |
69 | |
70 | if (changed) { |
71 | Q_EMIT q.lock().data()->serviceChanged(service: q.toStrongRef()); |
72 | } |
73 | } |
74 | |
75 | void GattServiceRemotePrivate::interfacesRemoved(const QString &path, const QStringList &interfaces) |
76 | { |
77 | Q_UNUSED(path) |
78 | bool changed = false; |
79 | |
80 | for (auto& interface : interfaces) { |
81 | if (interface == Strings::orgBluezGattCharacteristic1()) { |
82 | removeGattCharacteristic(gattCharacteristicPath: path); |
83 | changed = true; |
84 | } |
85 | } |
86 | |
87 | for (auto& ch: m_characteristics) { |
88 | if (path.startsWith(s: ch->ubi())) { |
89 | ch->d->interfacesRemoved(path, interfaces); |
90 | changed = true; |
91 | } |
92 | } |
93 | |
94 | if (changed) { |
95 | Q_EMIT q.lock().data()->serviceChanged(service: q.toStrongRef()); |
96 | } |
97 | } |
98 | |
99 | void GattServiceRemotePrivate::addGattCharacteristic(const QString &gattCharacteristicPath, const QVariantMap &properties) |
100 | { |
101 | // Check if we have the right path |
102 | if (m_bluezGattService->path() != properties.value(QStringLiteral("Service" )).value<QDBusObjectPath>().path()) { |
103 | return; |
104 | } |
105 | |
106 | GattServiceRemotePtr service = GattServiceRemotePtr(this->q); |
107 | |
108 | if (!service) { |
109 | return; |
110 | } |
111 | |
112 | GattCharacteristicRemotePtr gattCharacteristic = GattCharacteristicRemotePtr(new GattCharacteristicRemote(gattCharacteristicPath, properties, service)); |
113 | gattCharacteristic->d->q = gattCharacteristic.toWeakRef(); |
114 | m_characteristics.append(t: gattCharacteristic); |
115 | |
116 | Q_EMIT service->gattCharacteristicAdded(characteristic: gattCharacteristic); |
117 | Q_EMIT service->characteristicsChanged(characteristics: m_characteristics); |
118 | |
119 | // Connections |
120 | connect(sender: gattCharacteristic.data(),signal: &GattCharacteristicRemote::characteristicChanged,context: q.lock().data(),slot: &GattServiceRemote::gattCharacteristicChanged); |
121 | } |
122 | |
123 | void GattServiceRemotePrivate::removeGattCharacteristic(const QString &gattCharacteristicPath) |
124 | { |
125 | GattServiceRemotePtr service = GattServiceRemotePtr(this->q); |
126 | |
127 | if (!service) { |
128 | return; |
129 | } |
130 | |
131 | GattCharacteristicRemotePtr gattCharacteristic = nullptr; |
132 | for (int i=0; i < service->characteristics().size(); ++i) { |
133 | if (service->characteristics().at(i)->ubi() == gattCharacteristicPath) { |
134 | gattCharacteristic = service->characteristics().at(i); |
135 | } |
136 | } |
137 | |
138 | if (gattCharacteristic == nullptr) { |
139 | return; |
140 | } |
141 | |
142 | m_characteristics.removeOne(t: gattCharacteristic); |
143 | |
144 | Q_EMIT service->gattCharacteristicRemoved(characteristic: gattCharacteristic); |
145 | Q_EMIT service->characteristicsChanged(characteristics: m_characteristics); |
146 | |
147 | // Connections |
148 | disconnect(sender: gattCharacteristic.data(),signal: &GattCharacteristicRemote::characteristicChanged,receiver: q.lock().data(),slot: &GattServiceRemote::gattCharacteristicChanged); |
149 | } |
150 | |
151 | QDBusPendingReply<> GattServiceRemotePrivate::setDBusProperty(const QString &name, const QVariant &value) |
152 | { |
153 | return m_dbusProperties->Set(interface_name: Strings::orgBluezGattService1(), property_name: name, value: QDBusVariant(value)); |
154 | } |
155 | |
156 | void GattServiceRemotePrivate::propertiesChanged(const QString &path, const QString &interface, const QVariantMap &changed, const QStringList &invalidated) |
157 | { |
158 | if (interface == Strings::orgBluezGattCharacteristic1() || interface == Strings::orgBluezGattDescriptor1()) { |
159 | for (GattCharacteristicRemotePtr characteristic : m_characteristics) { |
160 | if (path.startsWith(s: characteristic->ubi())) { |
161 | characteristic->d->propertiesChanged(path, interface, changed, invalidated); |
162 | return; |
163 | } |
164 | } |
165 | } else if (interface != Strings::orgBluezGattService1()) { |
166 | return; |
167 | } |
168 | |
169 | QVariantMap::const_iterator i; |
170 | for (i = changed.constBegin(); i != changed.constEnd(); ++i) { |
171 | const QVariant &value = i.value(); |
172 | const QString &property = i.key(); |
173 | |
174 | if (property == QLatin1String("UUID" )) { |
175 | PROPERTY_CHANGED(m_uuid, toString, uuidChanged); |
176 | } else if (property == QLatin1String("Primary" )) { |
177 | PROPERTY_CHANGED(m_primary, toBool, primaryChanged); |
178 | } else if (property == QLatin1String("Includes" )) { |
179 | PROPERTY_CHANGED2(m_includes, value.value<QList<QDBusObjectPath>>(), includesChanged); |
180 | } else if (property == QLatin1String("Handle" )) { |
181 | PROPERTY_CHANGED2(m_handle, value.value<quint16>(), handleChanged); |
182 | } |
183 | } |
184 | |
185 | for (auto& property : invalidated) { |
186 | if (property == QLatin1String("UUID" )) { |
187 | PROPERTY_INVALIDATED(m_uuid, QString(), uuidChanged); |
188 | } else if (property == QLatin1String("Primary" )) { |
189 | PROPERTY_INVALIDATED(m_primary, false, primaryChanged); |
190 | } else if (property == QLatin1String("Includes" )) { |
191 | PROPERTY_INVALIDATED(m_includes, QList<QDBusObjectPath>(), includesChanged); |
192 | } else if (property == QLatin1String("Handle" )) { |
193 | PROPERTY_INVALIDATED(m_handle, quint16(), handleChanged); |
194 | } |
195 | } |
196 | |
197 | q.lock().data()->serviceChanged(service: q.toStrongRef()); |
198 | } |
199 | |
200 | } // namespace BluezQt |
201 | |
202 | #include "moc_gattserviceremote_p.cpp" |
203 | |