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
qbluetoothserviceinfo_bluez.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 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
6
9
10#include <QtCore/QLoggingCategory>
11#include <QtCore/QXmlStreamWriter>
12#include <QtCore/QAtomicInt>
13
15
16using namespace Qt::StringLiterals;
17
19
21
22static void writeAttribute(QXmlStreamWriter *stream, const QVariant &attribute)
23{
24 const QString unsignedFormat(QStringLiteral("0x%1"));
25
26 switch (attribute.typeId()) {
27 case QMetaType::Void:
28 stream->writeEmptyElement(QStringLiteral("nil"));
29 break;
30 case QMetaType::UChar:
31 stream->writeEmptyElement(QStringLiteral("uint8"));
32 stream->writeAttribute(QStringLiteral("value"),
33 unsignedFormat.arg(attribute.value<quint8>(), 2, 16,
34 QLatin1Char('0')));
35 break;
36 case QMetaType::UShort:
37 stream->writeEmptyElement(QStringLiteral("uint16"));
38 stream->writeAttribute(QStringLiteral("value"),
39 unsignedFormat.arg(attribute.value<quint16>(), 4, 16,
40 QLatin1Char('0')));
41 break;
42 case QMetaType::UInt:
43 stream->writeEmptyElement(QStringLiteral("uint32"));
44 stream->writeAttribute(QStringLiteral("value"),
45 unsignedFormat.arg(attribute.value<quint32>(), 8, 16,
46 QLatin1Char('0')));
47 break;
48 case QMetaType::Char:
49 stream->writeEmptyElement(QStringLiteral("int8"));
50 stream->writeAttribute(QStringLiteral("value"),
52 break;
53 case QMetaType::Short:
54 stream->writeEmptyElement(QStringLiteral("int16"));
55 stream->writeAttribute(QStringLiteral("value"),
57 break;
58 case QMetaType::Int:
59 stream->writeEmptyElement(QStringLiteral("int32"));
60 stream->writeAttribute(QStringLiteral("value"),
62 break;
63 case QMetaType::QByteArray:
64 stream->writeEmptyElement(QStringLiteral("text"));
65 stream->writeAttribute(QStringLiteral("value"),
67 stream->writeAttribute(QStringLiteral("encoding"), QStringLiteral("hex"));
68 break;
69 case QMetaType::QString:
70 stream->writeEmptyElement(QStringLiteral("text"));
71 stream->writeAttribute(QStringLiteral("value"), attribute.value<QString>());
72 stream->writeAttribute(QStringLiteral("encoding"), QStringLiteral("normal"));
73 break;
74 case QMetaType::Bool:
75 stream->writeEmptyElement(QStringLiteral("boolean"));
76 if (attribute.value<bool>())
77 stream->writeAttribute(QStringLiteral("value"), QStringLiteral("true"));
78 else
79 stream->writeAttribute(QStringLiteral("value"), QStringLiteral("false"));
80 break;
81 case QMetaType::QUrl:
82 stream->writeEmptyElement(QStringLiteral("url"));
83 stream->writeAttribute(QStringLiteral("value"), attribute.value<QUrl>().toString());
84 break;
85 default:
86 if (attribute.userType() == qMetaTypeId<QBluetoothUuid>()) {
87 stream->writeEmptyElement(QStringLiteral("uuid"));
88
90 switch (uuid.minimumSize()) {
91 case 0:
92 stream->writeAttribute(QStringLiteral("value"),
93 unsignedFormat.arg(quint16(0), 4, 16, QLatin1Char('0')));
94 break;
95 case 2:
96 stream->writeAttribute(QStringLiteral("value"),
97 unsignedFormat.arg(uuid.toUInt16(), 4, 16,
98 QLatin1Char('0')));
99 break;
100 case 4:
101 stream->writeAttribute(QStringLiteral("value"),
102 unsignedFormat.arg(uuid.toUInt32(), 8, 16,
103 QLatin1Char('0')));
104 break;
105 case 16:
106 stream->writeAttribute(QStringLiteral("value"), uuid.toString().mid(1, 36));
107 break;
108 default:
109 stream->writeAttribute(QStringLiteral("value"), uuid.toString().mid(1, 36));
110 }
111 } else if (attribute.userType() == qMetaTypeId<QBluetoothServiceInfo::Sequence>()) {
112 stream->writeStartElement(QStringLiteral("sequence"));
113 const QBluetoothServiceInfo::Sequence *sequence =
114 static_cast<const QBluetoothServiceInfo::Sequence *>(attribute.data());
115 for (const QVariant &v : *sequence)
117 stream->writeEndElement();
118 } else if (attribute.userType() == qMetaTypeId<QBluetoothServiceInfo::Alternative>()) {
119 const QBluetoothServiceInfo::Alternative *alternative =
120 static_cast<const QBluetoothServiceInfo::Alternative *>(attribute.data());
121 for (const QVariant &v : *alternative)
123 stream->writeEndElement();
124 } else {
125 qCWarning(QT_BT_BLUEZ) << "Unknown variant type" << attribute.userType();
126 }
127 }
128}
129
131: serviceRecord(0), registered(false)
132{
135 QStringLiteral("/org/bluez"),
137}
138
140{
141}
142
144{
145 return registered;
146}
147
149{
150 if (!registered)
151 return false;
152
153 if (profilePath.isEmpty())
154 return false;
155
156 QDBusPendingReply<> reply = service->UnregisterProfile(QDBusObjectPath(profilePath));
157 reply.waitForFinished();
158 if (reply.isError()) {
159 qCWarning(QT_BT_BLUEZ) << "Cannot unregister profile:" << profilePath
160 << reply.error().message();
161 return false;
162 }
163 profilePath.clear();
164
165 registered = false;
166 return true;
167}
168
169// TODO Implement local adapter behavior
171{
172 if (registered)
173 return false;
174
175 QString xmlServiceRecord;
176
177 QXmlStreamWriter stream(&xmlServiceRecord);
178 stream.setAutoFormatting(true);
179
180 stream.writeStartDocument(QStringLiteral("1.0"));
181
182 stream.writeStartElement(QStringLiteral("record"));
183
184 const QString unsignedFormat(QStringLiteral("0x%1"));
185
187 while (i != attributes.constEnd()) {
188 stream.writeStartElement(QStringLiteral("attribute"));
189 stream.writeAttribute(QStringLiteral("id"), unsignedFormat.arg(i.key(), 4, 16, QLatin1Char('0')));
190 writeAttribute(&stream, i.value());
191 stream.writeEndElement();
192
193 ++i;
194 }
195
196 stream.writeEndElement();
197
198 stream.writeEndDocument();
199
200 // create path
201 profilePath = u"/qt/profile"_s;
202 profilePath.append(QString::fromLatin1("/%1%2/%3")
205 .arg(pathCounter.fetchAndAddOrdered(1)));
206
208 mapping.insert(QStringLiteral("ServiceRecord"), xmlServiceRecord);
209 mapping.insert(QStringLiteral("Role"), QStringLiteral("server"));
210
211 // Strategy to pick service uuid
212 // 1.) use serviceUuid()
213 // 2.) use first custom uuid if available
214 // 3.) use first service class uuid
215 QBluetoothUuid profileUuid =
217 QBluetoothUuid firstCustomUuid;
218 if (profileUuid.isNull()) {
220 if (var.isValid()) {
223 for (const auto &e : seq) {
224 auto tempUuid = e.value<QBluetoothUuid>();
225 if (tempUuid.isNull())
226 continue;
227
228 int size = tempUuid.minimumSize();
229 if (size == 2 || size == 4) { // Base UUID derived
230 if (profileUuid.isNull())
231 profileUuid = tempUuid;
232 } else if (firstCustomUuid.isNull()) {
233 firstCustomUuid = tempUuid;
234 }
235 }
236 }
237 }
238
239 if (!firstCustomUuid.isNull())
240 profileUuid = firstCustomUuid;
241
242 QString uuidString = profileUuid.toString(QUuid::WithoutBraces);
243
244 qCDebug(QT_BT_BLUEZ) << "Registering profile under" << profilePath << uuidString;
245
247 service->RegisterProfile(QDBusObjectPath(profilePath), uuidString, mapping);
248 reply.waitForFinished();
249 if (reply.isError()) {
250 qCWarning(QT_BT_BLUEZ) << "Cannot register profile" << reply.error().message();
251 return false;
252 }
253
254 registered = true;
255 return true;
256}
257
QString sanitizeNameForDBus(const QString &text)
QT_BEGIN_NAMESPACE void initializeBluez5()
\inmodule QtCore
Definition qatomic.h:112
\inmodule QtBluetooth
QMap< quint16, QVariant > attributes
bool registerService(const QBluetoothAddress &localAdapter=QBluetoothAddress())
\inmodule QtBluetooth
quint16 toUInt16(bool *ok=nullptr) const
Returns the 16 bit representation of this UUID.
int minimumSize() const
Returns the minimum size in bytes that this UUID can be represented in.
quint32 toUInt32(bool *ok=nullptr) const
Returns the 32 bit representation of this UUID.
\inmodule QtCore
Definition qbytearray.h:57
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:124
QByteArray toHex(char separator='\0') const
Returns a hex encoded copy of the byte array.
static qint64 applicationPid() Q_DECL_CONST_FUNCTION
QString applicationName
the name of this application
static QDBusConnection systemBus()
Returns a QDBusConnection object opened with the system bus.
\inmodule QtDBus
T value(qsizetype i) const
Definition qlist.h:664
iterator insert(const Key &key, const T &value)
Definition qmap.h:688
T value(const Key &key, const T &defaultValue=T()) const
Definition qmap.h:357
const_iterator constBegin() const
Definition qmap.h:600
const_iterator constEnd() const
Definition qmap.h:604
NetworkError error() const
Returns the error that was found during the processing of this request.
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
QString mid(qsizetype position, qsizetype n=-1) const &
Definition qstring.cpp:5300
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:8084
\inmodule QtCore
Definition qurl.h:94
QString toString(FormattingOptions options=FormattingOptions(PrettyDecoded)) const
Returns a string representation of the URL.
Definition qurl.cpp:2831
@ WithoutBraces
Definition quuid.h:54
QString toString(StringFormat mode=WithBraces) const
Definition quuid.cpp:650
bool isNull() const noexcept
Returns true if this is the null UUID {00000000-0000-0000-0000-000000000000}; otherwise returns false...
Definition quuid.cpp:818
\inmodule QtCore
Definition qvariant.h:65
T value() const &
Definition qvariant.h:516
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
Definition qvariant.h:714
Combined button and popup list for selecting options.
Q_CORE_EXPORT QtJniTypes::Service service()
static QAtomicInt pathCounter
static void writeAttribute(QXmlStreamWriter *stream, const QVariant &attribute)
EGLStreamKHR stream
EGLOutputLayerEXT EGLint attribute
#define qCWarning(category,...)
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
GLsizei const GLfloat * v
[13]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLenum GLenum GLenum mapping
SSL_CTX int void * arg
#define QStringLiteral(str)
unsigned int quint32
Definition qtypes.h:50
short qint16
Definition qtypes.h:47
unsigned short quint16
Definition qtypes.h:48
int qint32
Definition qtypes.h:49
QT_BEGIN_NAMESPACE typedef signed char qint8
Definition qtypes.h:45
unsigned char quint8
Definition qtypes.h:46
QNetworkReply * reply
\inmodule QtCore \reentrant
Definition qchar.h:18