1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // Copyright (C) 2016 BlackBerry Limited. All rights reserved. |
3 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
4 | |
5 | #include <QtBluetooth/QLowEnergyService> |
6 | #include "qlowenergyserviceprivate_p.h" |
7 | #include "qlowenergydescriptor.h" |
8 | |
9 | QT_BEGIN_NAMESPACE |
10 | |
11 | QT_IMPL_METATYPE_EXTERN(QLowEnergyDescriptor) |
12 | |
13 | /*! |
14 | \class QLowEnergyDescriptor |
15 | \inmodule QtBluetooth |
16 | \brief The QLowEnergyDescriptor class stores information about the Bluetooth |
17 | Low Energy descriptor. |
18 | \since 5.4 |
19 | |
20 | QLowEnergyDescriptor provides information about a Bluetooth Low Energy |
21 | descriptor's name(), uuid(), and value(). Descriptors are |
22 | encapsulated by Bluetooth Low Energy characteristics and provide additional |
23 | contextual information about the characteristic (data format, notification activation |
24 | and so on). |
25 | |
26 | The descriptor value may be written via the QLowEnergyService instance |
27 | that manages the service to which this descriptor belongs. The |
28 | \l {QLowEnergyService::writeDescriptor()} function writes the new value. |
29 | The \l {QLowEnergyService::descriptorWritten()} signal |
30 | is emitted upon success. The cached value() of this object is updated accordingly. |
31 | |
32 | \sa QLowEnergyService, QLowEnergyCharacteristic |
33 | */ |
34 | |
35 | struct QLowEnergyDescriptorPrivate |
36 | { |
37 | QLowEnergyHandle charHandle; |
38 | QLowEnergyHandle descHandle; |
39 | }; |
40 | |
41 | /*! |
42 | Construct a new QLowEnergyDescriptor. A default-constructed instance |
43 | of this class is always invalid. |
44 | */ |
45 | QLowEnergyDescriptor::QLowEnergyDescriptor(): |
46 | d_ptr(nullptr) |
47 | { |
48 | } |
49 | |
50 | /*! |
51 | Construct a new QLowEnergyDescriptor that is a copy of \a other. |
52 | |
53 | The two copies continue to share the same underlying data which does not detach |
54 | upon write. |
55 | */ |
56 | QLowEnergyDescriptor::QLowEnergyDescriptor(const QLowEnergyDescriptor &other): |
57 | d_ptr(other.d_ptr) |
58 | { |
59 | if (other.data) { |
60 | data = new QLowEnergyDescriptorPrivate(); |
61 | data->charHandle = other.data->charHandle; |
62 | data->descHandle = other.data->descHandle; |
63 | } |
64 | } |
65 | |
66 | /*! |
67 | \internal |
68 | |
69 | */ |
70 | QLowEnergyDescriptor::QLowEnergyDescriptor(QSharedPointer<QLowEnergyServicePrivate> p, |
71 | QLowEnergyHandle charHandle, |
72 | QLowEnergyHandle descHandle): |
73 | d_ptr(p) |
74 | { |
75 | data = new QLowEnergyDescriptorPrivate(); |
76 | data->charHandle = charHandle; |
77 | data->descHandle = descHandle; |
78 | |
79 | } |
80 | |
81 | /*! |
82 | Destroys the QLowEnergyDescriptor object. |
83 | */ |
84 | QLowEnergyDescriptor::~QLowEnergyDescriptor() |
85 | { |
86 | delete data; |
87 | } |
88 | |
89 | /*! |
90 | Makes a copy of \a other and assigns it to this QLowEnergyDescriptor object. |
91 | The two copies continue to share the same service and controller details. |
92 | */ |
93 | QLowEnergyDescriptor &QLowEnergyDescriptor::operator=(const QLowEnergyDescriptor &other) |
94 | { |
95 | d_ptr = other.d_ptr; |
96 | |
97 | if (!other.data) { |
98 | if (data) { |
99 | delete data; |
100 | data = nullptr; |
101 | } |
102 | } else { |
103 | if (!data) |
104 | data = new QLowEnergyDescriptorPrivate(); |
105 | |
106 | data->charHandle = other.data->charHandle; |
107 | data->descHandle = other.data->descHandle; |
108 | } |
109 | |
110 | return *this; |
111 | } |
112 | |
113 | /*! |
114 | \fn bool QLowEnergyDescriptor::operator==(const QLowEnergyDescriptor &a, |
115 | const QLowEnergyDescriptor &b) |
116 | \brief Returns \c true if \a a is equal to \a b; otherwise \c false. |
117 | |
118 | Two QLowEnergyDescriptor instances are considered to be equal if they refer to |
119 | the same descriptor on the same remote Bluetooth Low Energy device or both |
120 | instances have been default-constructed. |
121 | */ |
122 | |
123 | /*! |
124 | \fn bool QLowEnergyDescriptor::operator!=(const QLowEnergyDescriptor &a, |
125 | const QLowEnergyDescriptor &b) |
126 | \brief Returns \c true if \a a is not equal to \a b; otherwise \c false. |
127 | |
128 | Two QLowEnergyDescriptor instances are considered to be equal if they refer to |
129 | the same descriptor on the same remote Bluetooth Low Energy device or both |
130 | instances have been default-constructed. |
131 | */ |
132 | |
133 | /*! |
134 | \brief Returns \c true if \a other is equal to this QLowEnergyCharacteristic, |
135 | otherwise \c false. |
136 | \internal |
137 | |
138 | Two QLowEnergyDescriptor instances are considered to be equal if they refer to |
139 | the same descriptor on the same remote Bluetooth Low Energy device or both |
140 | instances have been default-constructed. |
141 | */ |
142 | bool QLowEnergyDescriptor::equals(const QLowEnergyDescriptor &a, const QLowEnergyDescriptor &b) |
143 | { |
144 | if (a.d_ptr != b.d_ptr) |
145 | return false; |
146 | |
147 | if ((a.data && !b.data) || (!a.data && b.data)) |
148 | return false; |
149 | |
150 | if (!a.data) |
151 | return true; |
152 | |
153 | if (a.data->charHandle != b.data->charHandle || a.data->descHandle != b.data->descHandle) { |
154 | return false; |
155 | } |
156 | |
157 | return true; |
158 | } |
159 | |
160 | /*! |
161 | Returns \c true if the QLowEnergyDescriptor object is valid, otherwise returns \c false. |
162 | |
163 | An invalid descriptor instance is not associated with any service (default-constructed) |
164 | or the associated service is no longer valid due to a disconnect from |
165 | the underlying Bluetooth Low Energy device, for example. Once the object is invalid |
166 | it cannot become valid anymore. |
167 | |
168 | \note If a QLowEnergyDescriptor instance turns invalid due to a disconnect |
169 | from the underlying device, the information encapsulated by the current |
170 | instance remains as it was at the time of the disconnect. Therefore it can be |
171 | retrieved after the disconnect event. |
172 | */ |
173 | bool QLowEnergyDescriptor::isValid() const |
174 | { |
175 | if (d_ptr.isNull() || !data) |
176 | return false; |
177 | |
178 | if (d_ptr->state == QLowEnergyService::InvalidService) |
179 | return false; |
180 | |
181 | return true; |
182 | } |
183 | |
184 | /*! |
185 | Returns the UUID of this descriptor if \l isValid() returns \c true; otherwise a |
186 | \l {QUuid::isNull()}{null} UUID. |
187 | */ |
188 | QBluetoothUuid QLowEnergyDescriptor::uuid() const |
189 | { |
190 | if (d_ptr.isNull() || !data |
191 | || !d_ptr->characteristicList.contains(key: data->charHandle) |
192 | || !d_ptr->characteristicList[data->charHandle]. |
193 | descriptorList.contains(key: data->descHandle)) { |
194 | return QBluetoothUuid(); |
195 | } |
196 | |
197 | return d_ptr->characteristicList[data->charHandle].descriptorList[data->descHandle].uuid; |
198 | } |
199 | |
200 | /*! |
201 | \internal |
202 | |
203 | Returns the handle of the descriptor or \c 0 if the handle |
204 | cannot be accessed on the platform or the descriptor is invalid. |
205 | |
206 | \note On \macos and iOS handles can differ from 0, but these |
207 | values have no special meaning outside of internal/private API. |
208 | */ |
209 | QLowEnergyHandle QLowEnergyDescriptor::handle() const |
210 | { |
211 | if (!data) |
212 | return 0; |
213 | |
214 | return data->descHandle; |
215 | } |
216 | |
217 | /*! |
218 | Returns the cached value of the descriptor. |
219 | |
220 | The cached descriptor value may be updated using |
221 | \l QLowEnergyService::writeDescriptor() or \l QLowEnergyService::readDescriptor(). |
222 | */ |
223 | QByteArray QLowEnergyDescriptor::value() const |
224 | { |
225 | if (d_ptr.isNull() || !data |
226 | || !d_ptr->characteristicList.contains(key: data->charHandle) |
227 | || !d_ptr->characteristicList[data->charHandle]. |
228 | descriptorList.contains(key: data->descHandle)) { |
229 | return QByteArray(); |
230 | } |
231 | |
232 | return d_ptr->characteristicList[data->charHandle].descriptorList[data->descHandle].value; |
233 | } |
234 | |
235 | /*! |
236 | Returns the human-readable name of the descriptor. |
237 | |
238 | The name is based on the descriptor's \l type(). The complete list |
239 | of descriptor types can be found under |
240 | \l {https://developer.bluetooth.org/gatt/descriptors/Pages/DescriptorsHomePage.aspx}{Bluetooth.org Descriptors}. |
241 | |
242 | The returned string is empty if the \l type() is unknown. |
243 | |
244 | \sa type(), QBluetoothUuid::descriptorToString() |
245 | */ |
246 | |
247 | QString QLowEnergyDescriptor::name() const |
248 | { |
249 | return QBluetoothUuid::descriptorToString(uuid: type()); |
250 | } |
251 | |
252 | /*! |
253 | Returns the type of the descriptor. |
254 | |
255 | \sa name() |
256 | */ |
257 | QBluetoothUuid::DescriptorType QLowEnergyDescriptor::type() const |
258 | { |
259 | const QBluetoothUuid u = uuid(); |
260 | bool ok = false; |
261 | QBluetoothUuid::DescriptorType shortUuid = static_cast<QBluetoothUuid::DescriptorType>(u.toUInt16(ok: &ok)); |
262 | |
263 | if (!ok) |
264 | return QBluetoothUuid::DescriptorType::UnknownDescriptorType; |
265 | |
266 | switch (shortUuid) { |
267 | case QBluetoothUuid::DescriptorType::CharacteristicExtendedProperties: |
268 | case QBluetoothUuid::DescriptorType::CharacteristicUserDescription: |
269 | case QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration: |
270 | case QBluetoothUuid::DescriptorType::ServerCharacteristicConfiguration: |
271 | case QBluetoothUuid::DescriptorType::CharacteristicPresentationFormat: |
272 | case QBluetoothUuid::DescriptorType::CharacteristicAggregateFormat: |
273 | case QBluetoothUuid::DescriptorType::ValidRange: |
274 | case QBluetoothUuid::DescriptorType::ExternalReportReference: |
275 | case QBluetoothUuid::DescriptorType::ReportReference: |
276 | return (QBluetoothUuid::DescriptorType) shortUuid; |
277 | default: |
278 | break; |
279 | } |
280 | |
281 | return QBluetoothUuid::DescriptorType::UnknownDescriptorType; |
282 | } |
283 | |
284 | /*! |
285 | \internal |
286 | |
287 | Returns the handle of the characteristic to which this descriptor belongs |
288 | */ |
289 | QLowEnergyHandle QLowEnergyDescriptor::characteristicHandle() const |
290 | { |
291 | if (d_ptr.isNull() || !data) |
292 | return 0; |
293 | |
294 | return data->charHandle; |
295 | } |
296 | |
297 | QT_END_NAMESPACE |
298 | |