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
9QT_BEGIN_NAMESPACE
10
11QT_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
35struct 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*/
45QLowEnergyDescriptor::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*/
56QLowEnergyDescriptor::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*/
70QLowEnergyDescriptor::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*/
84QLowEnergyDescriptor::~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*/
93QLowEnergyDescriptor &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 */
142bool 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*/
173bool 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*/
188QBluetoothUuid 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*/
209QLowEnergyHandle 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*/
223QByteArray 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
247QString 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 */
257QBluetoothUuid::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 */
289QLowEnergyHandle QLowEnergyDescriptor::characteristicHandle() const
290{
291 if (d_ptr.isNull() || !data)
292 return 0;
293
294 return data->charHandle;
295}
296
297QT_END_NAMESPACE
298

source code of qtconnectivity/src/bluetooth/qlowenergydescriptor.cpp