Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qlowenergycontroller_bluez_p.h
Go to the documentation of this file.
1// Copyright (C) 2017 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#ifndef QLOWENERGYCONTROLLERBLUEZ_P_H
5#define QLOWENERGYCONTROLLERBLUEZ_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <qglobal.h>
19#include <QtCore/QList>
20#include <QtCore/QQueue>
21#include <QtBluetooth/qbluetooth.h>
22#include <QtBluetooth/qlowenergycharacteristic.h>
25#include "bluez/bluez_data_p.h"
26
27#include <QtBluetooth/QBluetoothSocket>
28#include <functional>
29
31
33class QTimer;
34
35class HciManager;
37class QSocketNotifier;
39
41
42class QLeAdvertiser;
43
45{
47public:
50
51 void init() override;
52
53 void connectToDevice() override;
54 void disconnectFromDevice() override;
55
56 void discoverServices() override;
57 void discoverServiceDetails(const QBluetoothUuid &service,
59
61 const QLowEnergyAdvertisingData &advertisingData,
62 const QLowEnergyAdvertisingData &scanResponseData) override;
63 void stopAdvertising() override;
64
66
67 // read data
68 void readCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service,
69 const QLowEnergyHandle charHandle) override;
70 void readDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service,
71 const QLowEnergyHandle charHandle,
72 const QLowEnergyHandle descriptorHandle) override;
73
74 // write data
75 void writeCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service,
76 const QLowEnergyHandle charHandle,
77 const QByteArray &newValue, QLowEnergyService::WriteMode mode) override;
78 void writeDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service,
79 const QLowEnergyHandle charHandle,
80 const QLowEnergyHandle descriptorHandle,
81 const QByteArray &newValue) override;
82
84 QLowEnergyHandle startHandle) override;
85
86 int mtu() const override;
87
88 struct Attribute {
89 Attribute() : handle(0) {}
90
93 QLowEnergyCharacteristic::PropertyTypes properties;
94 QBluetooth::AttAccessConstraints readConstraints;
95 QBluetooth::AttAccessConstraints writeConstraints;
100 };
101 QList<Attribute> localAttributes;
102
103private:
104 quint16 connectionHandle = 0;
105 QBluetoothSocket *l2cpSocket = nullptr;
106 struct Request {
108 QByteArray payload;
109 // TODO reference below is ugly but until we know all commands and their
110 // requirements this is WIP
112 QVariant reference2;
113 };
114 QQueue<Request> openRequests;
115
116 struct WriteRequest {
117 WriteRequest() {}
118 WriteRequest(quint16 h, quint16 o, const QByteArray &v)
119 : handle(h), valueOffset(o), value(v) {}
121 quint16 valueOffset;
123 };
124 QList<WriteRequest> openPrepareWriteRequests;
125
126 // Invariant: !scheduledIndications.isEmpty => indicationInFlight == true
127 QList<QLowEnergyHandle> scheduledIndications;
128 bool indicationInFlight = false;
129
130 struct TempClientConfigurationData {
131 TempClientConfigurationData(QLowEnergyServicePrivate::DescData *dd = nullptr,
132 QLowEnergyHandle chHndl = 0, QLowEnergyHandle coHndl = 0)
133 : descData(dd), charValueHandle(chHndl), configHandle(coHndl) {}
134
136 QLowEnergyHandle charValueHandle;
137 QLowEnergyHandle configHandle;
138 };
139
140 struct ClientConfigurationData {
141 ClientConfigurationData(QLowEnergyHandle chHndl = 0, QLowEnergyHandle coHndl = 0,
142 quint16 val = 0)
143 : charValueHandle(chHndl), configHandle(coHndl), configValue(val) {}
144
145 QLowEnergyHandle charValueHandle;
146 QLowEnergyHandle configHandle;
147 quint16 configValue;
148 bool charValueWasUpdated = false;
149 };
150 QHash<quint64, QList<ClientConfigurationData>> clientConfigData;
151
152 struct SigningData {
153 SigningData() = default;
154 SigningData(BluezUint128 csrk, quint32 signCounter = quint32(-1))
155 : key(csrk), counter(signCounter) {}
156
158 quint32 counter = quint32(-1);
159 };
160 QHash<quint64, SigningData> signingData;
161 LeCmacCalculator *cmacCalculator = nullptr;
162
163 bool requestPending;
164 quint16 mtuSize;
165 int securityLevelValue;
166 bool encryptionChangePending;
167 bool receivedMtuExchangeRequest = false;
168
169 std::shared_ptr<HciManager> hciManager;
170 QLeAdvertiser *advertiser = nullptr;
171 QSocketNotifier *serverSocketNotifier = nullptr;
172 QTimer *requestTimer = nullptr;
173 RemoteDeviceManager* device1Manager = nullptr;
174
175 /*
176 Defines the maximum number of milliseconds the implementation will
177 wait for requests that require a response.
178
179 This addresses the problem that some non-conformant BTLE devices
180 do not implement the request/response system properly. In such cases
181 the queue system would hang forever.
182
183 Once timeout has been triggered we gracefully continue with the next request.
184 Depending on the type of the timed out ATT command we either ignore it
185 or artifically trigger an error response to ensure the API gives the
186 appropriate response. Potentially this can cause problems when the
187 response for the dropped requests arrives very late. That's why a big warning
188 is printed about the compromised state when a timeout is triggered.
189 */
190 int gattRequestTimeout = 20000;
191
192 void handleConnectionRequest();
193 void closeServerSocket();
194
195 bool isBonded() const;
196 QList<TempClientConfigurationData> gatherClientConfigData();
197 void storeClientConfigurations();
198 void restoreClientConfigurations();
199
200 enum SigningKeyType { LocalSigningKey, RemoteSigningKey };
201 void loadSigningDataIfNecessary(SigningKeyType keyType);
202 void storeSignCounter(SigningKeyType keyType) const;
203 QString signingKeySettingsGroup(SigningKeyType keyType) const;
204 QString keySettingsFilePath() const;
205
206 void sendPacket(const QByteArray &packet);
207 void sendNextPendingRequest();
208 void processReply(const Request &request, const QByteArray &reply);
209
210 void sendReadByGroupRequest(QLowEnergyHandle start, QLowEnergyHandle end,
211 quint16 type);
212 void sendReadByTypeRequest(QSharedPointer<QLowEnergyServicePrivate> serviceData,
213 QLowEnergyHandle nextHandle, quint16 attributeType);
214 void sendReadValueRequest(QLowEnergyHandle attributeHandle, bool isDescriptor);
215 void readServiceValues(const QBluetoothUuid &service,
216 bool readCharacteristics);
217 void readServiceValuesByOffset(uint handleData, quint16 offset,
218 bool isLastValue);
219
220 void discoverServiceDescriptors(const QBluetoothUuid &serviceUuid);
221 void discoverNextDescriptor(QSharedPointer<QLowEnergyServicePrivate> serviceData,
222 const QList<QLowEnergyHandle> pendingCharHandles,
223 QLowEnergyHandle startingHandle);
224 void processUnsolicitedReply(const QByteArray &msg);
225 void exchangeMTU();
226 bool setSecurityLevel(int level);
227 int securityLevel() const;
228 void sendExecuteWriteRequest(const QLowEnergyHandle attrHandle,
229 const QByteArray &newValue,
230 bool isCancelation);
231 void sendNextPrepareWriteRequest(const QLowEnergyHandle handle,
232 const QByteArray &newValue, quint16 offset);
233 bool increaseEncryptLevelfRequired(QBluezConst::AttError errorCode);
234
235 void resetController();
236
237 void handleAdvertisingError();
238
239 bool checkPacketSize(const QByteArray &packet, int minSize, int maxSize = -1);
240 bool checkHandle(const QByteArray &packet, QLowEnergyHandle handle);
241 bool checkHandlePair(QBluezConst::AttCommand request, QLowEnergyHandle startingHandle,
242 QLowEnergyHandle endingHandle);
243
244 void handleExchangeMtuRequest(const QByteArray &packet);
245 void handleFindInformationRequest(const QByteArray &packet);
246 void handleFindByTypeValueRequest(const QByteArray &packet);
247 void handleReadByTypeRequest(const QByteArray &packet);
248 void handleReadRequest(const QByteArray &packet);
249 void handleReadBlobRequest(const QByteArray &packet);
250 void handleReadMultipleRequest(const QByteArray &packet);
251 void handleReadByGroupTypeRequest(const QByteArray &packet);
252 void handleWriteRequestOrCommand(const QByteArray &packet);
253 void handlePrepareWriteRequest(const QByteArray &packet);
254 void handleExecuteWriteRequest(const QByteArray &packet);
255
256 void sendErrorResponse(QBluezConst::AttCommand request, quint16 handle,
258
259 using ElemWriter = std::function<void(const Attribute &, char *&)>;
260 void sendListResponse(const QByteArray &packetStart, qsizetype elemSize,
261 const QList<Attribute> &attributes, const ElemWriter &elemWriter);
262
263 void sendNotification(QLowEnergyHandle handle);
264 void sendIndication(QLowEnergyHandle handle);
265 void sendNotificationOrIndication(QBluezConst::AttCommand opCode, QLowEnergyHandle handle);
266 void sendNextIndication();
267
268 void ensureUniformAttributes(QList<Attribute> &attributes,
269 const std::function<int(const Attribute &)> &getSize);
270 void ensureUniformUuidSizes(QList<Attribute> &attributes);
271 void ensureUniformValueSizes(QList<Attribute> &attributes);
272
273 using AttributePredicate = std::function<bool(const Attribute &)>;
274 QList<Attribute> getAttributes(
275 QLowEnergyHandle startHandle, QLowEnergyHandle endHandle,
276 const AttributePredicate &attributePredicate = [](const Attribute &) { return true; });
277
278 QBluezConst::AttError checkPermissions(const Attribute &attr,
280 QBluezConst::AttError checkReadPermissions(const Attribute &attr);
281 QBluezConst::AttError checkReadPermissions(QList<Attribute> &attributes);
282
283 bool verifyMac(const QByteArray &message, BluezUint128 csrk, quint32 signCounter,
284 quint64 expectedMac);
285
286 void updateLocalAttributeValue(
288 const QByteArray &value,
289 QLowEnergyCharacteristic &characteristic,
290 QLowEnergyDescriptor &descriptor);
291
292 void writeCharacteristicForPeripheral(
294 const QByteArray &newValue);
295 void writeCharacteristicForCentral(const QSharedPointer<QLowEnergyServicePrivate> &service,
296 QLowEnergyHandle charHandle,
297 QLowEnergyHandle valueHandle,
298 const QByteArray &newValue,
300
301 void writeDescriptorForPeripheral(
302 const QSharedPointer<QLowEnergyServicePrivate> &service,
303 const QLowEnergyHandle charHandle,
304 const QLowEnergyHandle descriptorHandle,
305 const QByteArray &newValue);
306 void writeDescriptorForCentral(
307 const QLowEnergyHandle charHandle,
308 const QLowEnergyHandle descriptorHandle,
309 const QByteArray &newValue);
310
311 void restartRequestTimer();
312 void establishL2cpClientSocket();
313 void createServicesForCentralIfRequired();
314
315private slots:
316 void l2cpConnected();
317 void l2cpDisconnected();
318 void l2cpErrorChanged(QBluetoothSocket::SocketError);
319 void l2cpReadyRead();
320 void encryptionChangedEvent(const QBluetoothAddress&, bool);
321 void handleGattRequestTimeout();
322 void activeConnectionTerminationDone();
323};
324
326
328
329#endif //QLOWENERGYCONTROLLERBLUEZ_P_H
\inmodule QtBluetooth
\inmodule QtBluetooth
SocketError
This enum describes Bluetooth socket error types.
\inmodule QtBluetooth
\inmodule QtCore
Definition qbytearray.h:57
The QLowEnergyAdvertisingData class represents the data to be broadcast during Bluetooth Low Energy a...
The QLowEnergyAdvertisingParameters class represents the parameters used for Bluetooth Low Energy adv...
PropertyType
This enum describes the properties of a characteristic.
The QLowEnergyConnectionParameters class is used when requesting or reporting an update of the parame...
void discoverServiceDetails(const QBluetoothUuid &service, QLowEnergyService::DiscoveryMode mode) override
void readCharacteristic(const QSharedPointer< QLowEnergyServicePrivate > service, const QLowEnergyHandle charHandle) override
void writeCharacteristic(const QSharedPointer< QLowEnergyServicePrivate > service, const QLowEnergyHandle charHandle, const QByteArray &newValue, QLowEnergyService::WriteMode mode) override
Writes long (prepare write request), short (write request) and writeWithoutResponse characteristic va...
void writeDescriptor(const QSharedPointer< QLowEnergyServicePrivate > service, const QLowEnergyHandle charHandle, const QLowEnergyHandle descriptorHandle, const QByteArray &newValue) override
void startAdvertising(const QLowEnergyAdvertisingParameters &params, const QLowEnergyAdvertisingData &advertisingData, const QLowEnergyAdvertisingData &scanResponseData) override
void readDescriptor(const QSharedPointer< QLowEnergyServicePrivate > service, const QLowEnergyHandle charHandle, const QLowEnergyHandle descriptorHandle) override
void addToGenericAttributeList(const QLowEnergyServiceData &service, QLowEnergyHandle startHandle) override
void requestConnectionUpdate(const QLowEnergyConnectionParameters &params) override
\inmodule QtBluetooth
The QLowEnergyServiceData class is used to set up GATT service data. \inmodule QtBluetooth.
DiscoveryMode
This enum lists service discovery modes.
WriteMode
This enum describes the mode to be used when writing a characteristic value.
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
\inmodule QtCore
Definition qtimer.h:20
\inmodule QtCore
Definition qvariant.h:65
Combined button and popup list for selecting options.
quint16 QLowEnergyHandle
Definition qbluetooth.h:42
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
void registerQLowEnergyControllerMetaType()
GLsizei const GLfloat * v
[13]
GLuint64 GLenum void * handle
GLenum mode
GLenum GLuint GLint level
GLuint64 key
GLuint GLuint end
GLint reference
GLenum type
GLuint GLsizei const GLchar * message
GLuint start
GLenum GLuint GLintptr offset
GLfloat GLfloat GLfloat GLfloat h
GLuint counter
void ** params
GLuint GLfloat * val
static QSize getSize(QTextDocument *doc, const QTextImageFormat &format)
#define Q_OBJECT
#define slots
@ Q_RELOCATABLE_TYPE
Definition qtypeinfo.h:158
#define Q_DECLARE_TYPEINFO(TYPE, FLAGS)
Definition qtypeinfo.h:180
unsigned int quint32
Definition qtypes.h:50
unsigned short quint16
Definition qtypes.h:48
unsigned long long quint64
Definition qtypes.h:61
ptrdiff_t qsizetype
Definition qtypes.h:165
unsigned int uint
Definition qtypes.h:34
QNetworkRequest request(url)
QNetworkReply * reply
void checkHandle()
QLowEnergyCharacteristic::PropertyTypes properties
\inmodule QtCore
Definition quuid.h:58