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_winrt.cpp
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
8
9#include <QtCore/QLoggingCategory>
10#include <QtCore/private/qfunctions_winrt_p.h>
11
12#include <wrl.h>
13#include <windows.devices.bluetooth.h>
14#include <windows.devices.bluetooth.rfcomm.h>
15#include <windows.foundation.h>
16#include <windows.networking.sockets.h>
17#include <windows.storage.streams.h>
18
19using namespace Microsoft::WRL;
20using namespace Microsoft::WRL::Wrappers;
22using namespace ABI::Windows::Devices::Bluetooth::Rfcomm;
23using namespace ABI::Windows::Foundation;
24using namespace ABI::Windows::Foundation::Collections;
25using namespace ABI::Windows::Networking::Sockets;
26using namespace ABI::Windows::Storage::Streams;
27
29
30Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINDOWS)
31
32#define TYPE_VOID 0
33#define TYPE_UINT8 8
34#define TYPE_UINT16 9
35#define TYPE_UINT32 10
36#define TYPE_UINT64 11
37//#define TYPE_UINT128 12
38#define TYPE_INT8 16
39#define TYPE_INT16 17
40#define TYPE_INT32 18
41#define TYPE_INT64 19
42//#define TYPE_INT128 20
43#define TYPE_UUID16 25
44#define TYPE_UUID32 26
45#define TYPE_UUID128 28
46#define TYPE_STRING_BASE 32
47#define TYPE_BOOLEAN 40
48#define TYPE_SEQUENCE_BASE 48
49#define TYPE_ALTERNATIVE_BASE 56
50#define TYPE_URL_BASE 64
51
52extern QHash<QBluetoothServerPrivate *, int> __fakeServerPorts;
53
54inline bool typeIsOfBase(unsigned char type, unsigned char baseType)
55{
56 return ((type & baseType) == baseType);
57}
58
59qint64 getLengthForBaseType(unsigned char type, ComPtr<IDataReader> &reader)
60{
61 const bool isOfBase = (typeIsOfBase(type, TYPE_STRING_BASE)
65 if (!isOfBase)
66 return -1;
67
68 HRESULT hr;
69 // For these types, the first 5 bits are the base type followed by 3 bits
70 // describing the size index. This index decides how many additional bits
71 // have to be read to get the type's length.
72 const unsigned char sizeIndex = (type & 0x7);
73 switch (sizeIndex) {
74 case 5: {
76 hr = reader->ReadByte(&length);
77 RETURN_IF_FAILED("Could not read length from buffer", return -1);
78 return length;
79 } case 6: {
81 hr = reader->ReadUInt16(&length);
82 RETURN_IF_FAILED("Could not read length from buffer", return -1);
83 return length;
84 } case 7: {
86 hr = reader->ReadUInt32(&length);
87 RETURN_IF_FAILED("Could not read length from buffer", return -1);
88 return length;
89 }
90 }
91 return -1;
92}
93
94bool writeStringHelper(const QString &string, ComPtr<IDataWriter> writer)
95{
96 HRESULT hr;
97 const qsizetype stringLength = string.size();
98 unsigned char type = TYPE_STRING_BASE;
99 if (stringLength < 0) {
100 qCWarning(QT_BT_WINDOWS) << "Can not write invalid string value to buffer";
101 return false;
102 } if (stringLength <= 0xff) {
103 type += 5;
104 hr = writer->WriteByte(type);
105 RETURN_FALSE_IF_FAILED("Could not write string type data.");
106 hr = writer->WriteByte(stringLength);
107 RETURN_FALSE_IF_FAILED("Could not write string length.");
108 } else if (stringLength <= 0xffff) {
109 type += 6;
110 hr = writer->WriteByte(type);
111 RETURN_FALSE_IF_FAILED("Could not write string type data.");
112 hr = writer->WriteUInt16(stringLength);
113 RETURN_FALSE_IF_FAILED("Could not write string length.");
114 } else {
115 type += 7;
116 hr = writer->WriteByte(type);
117 RETURN_FALSE_IF_FAILED("Could not write string type data.");
118 hr = writer->WriteUInt32(stringLength);
119 RETURN_FALSE_IF_FAILED("Could not write string length.");
120 }
121 HStringReference stringRef(reinterpret_cast<LPCWSTR>(string.utf16()));
123 hr = writer->WriteString(stringRef.Get(), &bytesWritten);
124 RETURN_FALSE_IF_FAILED("Could not write string to buffer.");
125 if (bytesWritten != size_t(string.size())) {
126 qCWarning(QT_BT_WINDOWS) << "Did not write full value to buffer";
127 return false;
128 }
129 return true;
130}
131
133{
134 ComPtr<IDataReaderStatics> dataReaderStatics;
135 HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_DataReader).Get(),
136 &dataReaderStatics);
137 Q_ASSERT_SUCCEEDED(hr);
138
139 ComPtr<IDataReader> reader;
140 hr = dataReaderStatics->FromBuffer(buffer.Get(), reader.GetAddressOf());
141 Q_ASSERT_SUCCEEDED(hr);
142
143 BYTE type;
144 hr = reader->ReadByte(&type);
145 Q_ASSERT_SUCCEEDED(hr);
147 qCWarning(QT_BT_WINDOWS) << Q_FUNC_INFO << "Malformed profile descriptor list read";
148 return false;
149 }
150
152 hr = reader->ReadByte(&type);
153 Q_ASSERT_SUCCEEDED(hr);
154 // We have to "repair" the structure if the outer sequence contains a uuid directly
155 if (type == TYPE_UUID16 && length == 4) {
156 qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Repairing profile descriptor list";
157 quint16 uuid;
158 hr = reader->ReadUInt16(&uuid);
159 Q_ASSERT_SUCCEEDED(hr);
160
161 ComPtr<IDataWriter> writer;
162 hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_DataWriter).Get(),
163 &writer);
164 Q_ASSERT_SUCCEEDED(hr);
165
166 hr = writer->WriteByte(TYPE_SEQUENCE_BASE + 5);
167 Q_ASSERT_SUCCEEDED(hr);
168 // 8 == length of nested sequence (outer sequence -> inner sequence -> uuid and version)
169 hr = writer->WriteByte(8);
170 Q_ASSERT_SUCCEEDED(hr);
171 hr = writer->WriteByte(TYPE_SEQUENCE_BASE + 5);
172 Q_ASSERT_SUCCEEDED(hr);
173 hr = writer->WriteByte(7);
174 Q_ASSERT_SUCCEEDED(hr);
175 hr = writer->WriteByte(TYPE_UUID16);
176 Q_ASSERT_SUCCEEDED(hr);
177 hr = writer->WriteUInt16(uuid);
178 Q_ASSERT_SUCCEEDED(hr);
179 // Write default version to make WinRT happy
180 hr = writer->WriteByte(TYPE_UINT16);
181 Q_ASSERT_SUCCEEDED(hr);
182 hr = writer->WriteUInt16(0x100);
183 Q_ASSERT_SUCCEEDED(hr);
184
185 hr = writer->DetachBuffer(&buffer);
186 Q_ASSERT_SUCCEEDED(hr);
187 }
188
189 return true;
190}
191
192static ComPtr<IBuffer> bufferFromAttribute(const QVariant &attribute)
193{
194 ComPtr<IDataWriter> writer;
195 HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_DataWriter).Get(),
196 &writer);
197 Q_ASSERT_SUCCEEDED(hr);
198
199 switch (attribute.typeId()) {
200 case QMetaType::Void:
201 qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering attribute of type QMetaType::Void:";
202 hr = writer->WriteByte(TYPE_VOID);
203 Q_ASSERT_SUCCEEDED(hr);
204 break;
205 case QMetaType::UChar:
206 qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering attribute of type QMetaType::UChar:" << attribute.value<quint8>();
207 hr = writer->WriteByte(TYPE_UINT8);
208 Q_ASSERT_SUCCEEDED(hr);
209 hr = writer->WriteByte(attribute.value<quint8>());
210 Q_ASSERT_SUCCEEDED(hr);
211 break;
212 case QMetaType::UShort:
213 qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering attribute of type QMetaType::UShort:" << attribute.value<quint16>();
214 hr = writer->WriteByte(TYPE_UINT16);
215 Q_ASSERT_SUCCEEDED(hr);
216 hr = writer->WriteUInt16(attribute.value<quint16>());
217 Q_ASSERT_SUCCEEDED(hr);
218 break;
219 case QMetaType::UInt:
220 qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering attribute of type QMetaType::UInt:" << attribute.value<quint32>();
221 hr = writer->WriteByte(TYPE_UINT32);
222 Q_ASSERT_SUCCEEDED(hr);
223 hr = writer->WriteUInt32(attribute.value<quint32>());
224 Q_ASSERT_SUCCEEDED(hr);
225 break;
226 case QMetaType::ULongLong:
227 qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering attribute of type QMetaType::ULongLong:" << attribute.value<quint64>();
228 hr = writer->WriteByte(TYPE_UINT64);
229 Q_ASSERT_SUCCEEDED(hr);
230 hr = writer->WriteUInt64(attribute.value<quint64>());
231 Q_ASSERT_SUCCEEDED(hr);
232 break;
233 case QMetaType::Char:
234 qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering attribute of type QMetaType::Char:" << attribute.value<qint8>();
235 hr = writer->WriteByte(TYPE_INT8);
236 Q_ASSERT_SUCCEEDED(hr);
237 hr = writer->WriteByte(attribute.value<qint8>());
238 Q_ASSERT_SUCCEEDED(hr);
239 break;
240 case QMetaType::Short:
241 qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering attribute of type QMetaType::Short:" << attribute.value<qint16>();
242 hr = writer->WriteByte(TYPE_INT16);
243 Q_ASSERT_SUCCEEDED(hr);
244 hr = writer->WriteInt16(attribute.value<qint16>());
245 Q_ASSERT_SUCCEEDED(hr);
246 break;
247 case QMetaType::Int:
248 qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering attribute of type QMetaType::Int:" << attribute.value<qint32>();
249 hr = writer->WriteByte(TYPE_INT32);
250 Q_ASSERT_SUCCEEDED(hr);
251 hr = writer->WriteInt32(attribute.value<qint32>());
252 Q_ASSERT_SUCCEEDED(hr);
253 break;
254 case QMetaType::LongLong:
255 qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering attribute of type QMetaType::LongLong:" << attribute.value<qint64>();
256 hr = writer->WriteByte(TYPE_INT64);
257 Q_ASSERT_SUCCEEDED(hr);
258 hr = writer->WriteInt64(attribute.value<qint64>());
259 Q_ASSERT_SUCCEEDED(hr);
260 break;
261 case QMetaType::QByteArray: {
262 qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering attribute of type QMetaType::QByteArray:" << attribute.value<QString>();
263 const QString stringValue = QString::fromLatin1(attribute.value<QByteArray>().toHex());
264 const bool writeSuccess = writeStringHelper(stringValue, writer);
265 if (!writeSuccess)
266 return nullptr;
267 break;
268 }
269 case QMetaType::QString: {
270 qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering attribute of type QMetaType::QString:" << attribute.value<QString>();
271 const QString stringValue = attribute.value<QString>();
272 const bool writeSucces = writeStringHelper(stringValue, writer);
273 if (!writeSucces)
274 return nullptr;
275 break;
276 }
277 case QMetaType::Bool:
278 qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering attribute of type QMetaType::Bool:" << attribute.value<bool>();
279 hr = writer->WriteByte(TYPE_BOOLEAN);
280 Q_ASSERT_SUCCEEDED(hr);
281 hr = writer->WriteByte(attribute.value<bool>());
282 Q_ASSERT_SUCCEEDED(hr);
283 break;
284 case QMetaType::QUrl:
285 qCWarning(QT_BT_WINDOWS) << "Don't know how to register QMetaType::QUrl";
286 return nullptr;
287 break;
288 default:
289 if (attribute.userType() == qMetaTypeId<QBluetoothUuid>()) {
291 switch (uuid.minimumSize()) {
292 case 0:
293 qCWarning(QT_BT_WINDOWS) << "Don't know how to register Uuid of length 0";
294 return nullptr;
295 case 2:
296 qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering Uuid attribute with length 2:" << uuid;
297 hr = writer->WriteByte(TYPE_UUID16);
298 Q_ASSERT_SUCCEEDED(hr);
299 hr = writer->WriteUInt16(uuid.toUInt16());
300 Q_ASSERT_SUCCEEDED(hr);
301 break;
302 case 4:
303 qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering Uuid attribute with length 4:" << uuid;
304 hr = writer->WriteByte(TYPE_UUID32);
305 Q_ASSERT_SUCCEEDED(hr);
306 hr = writer->WriteUInt32(uuid.toUInt32());
307 Q_ASSERT_SUCCEEDED(hr);
308 break;
309 case 16:
310 default:
311 qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registering Uuid attribute:" << uuid;
312 hr = writer->WriteByte(TYPE_UUID128);
313 Q_ASSERT_SUCCEEDED(hr);
314 hr = writer->WriteGuid(uuid);
315 Q_ASSERT_SUCCEEDED(hr);
316 break;
317 }
318 } else if (attribute.userType() == qMetaTypeId<QBluetoothServiceInfo::Sequence>()) {
319 qCDebug(QT_BT_WINDOWS) << "Registering sequence attribute";
320 const QBluetoothServiceInfo::Sequence *sequence =
321 static_cast<const QBluetoothServiceInfo::Sequence *>(attribute.data());
322 ComPtr<IDataWriter> tmpWriter;
323 HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_DataWriter).Get(),
324 &tmpWriter);
325 Q_ASSERT_SUCCEEDED(hr);
326 for (const QVariant &v : *sequence) {
327 ComPtr<IBuffer> tmpBuffer = bufferFromAttribute(v);
328 if (!tmpBuffer) {
329 qCWarning(QT_BT_WINDOWS) << "Could not create buffer from attribute in sequence";
330 return nullptr;
331 }
332 quint32 l;
333 hr = tmpBuffer->get_Length(&l);
334 Q_ASSERT_SUCCEEDED(hr);
335 hr = tmpWriter->WriteBuffer(tmpBuffer.Get());
336 Q_ASSERT_SUCCEEDED(hr);
337 }
338 ComPtr<IBuffer> tmpBuffer;
339 hr = tmpWriter->DetachBuffer(&tmpBuffer);
340 Q_ASSERT_SUCCEEDED(hr);
341 // write sequence length
343 tmpBuffer->get_Length(&length);
344 Q_ASSERT_SUCCEEDED(hr);
345 unsigned char type = TYPE_SEQUENCE_BASE;
346 length += 1;
347 if (length <= 0xff) {
348 type += 5;
349 hr = writer->WriteByte(type);
350 Q_ASSERT_SUCCEEDED(hr);
351 hr = writer->WriteByte(length);
352 Q_ASSERT_SUCCEEDED(hr);
353 } else if (length <= 0xffff) {
354 type += 6;
355 hr = writer->WriteByte(type);
356 Q_ASSERT_SUCCEEDED(hr);
357 hr = writer->WriteUInt16(length);
358 Q_ASSERT_SUCCEEDED(hr);
359 } else {
360 type += 7;
361 hr = writer->WriteByte(type);
362 Q_ASSERT_SUCCEEDED(hr);
363 hr = writer->WriteUInt32(length);
364 Q_ASSERT_SUCCEEDED(hr);
365 }
366 // write sequence data
367 hr = writer->WriteBuffer(tmpBuffer.Get());
368 Q_ASSERT_SUCCEEDED(hr);
369 qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registered sequence attribute with length" << length;
370 } else if (attribute.userType() == qMetaTypeId<QBluetoothServiceInfo::Alternative>()) {
371 qCWarning(QT_BT_WINDOWS) << "Don't know how to register user type Alternative";
372 return nullptr;
373 } else {
374 qCWarning(QT_BT_WINDOWS) << "Unknown variant type" << attribute.userType();
375 return nullptr;
376 }
377 }
378 ComPtr<IBuffer> buffer;
379 hr = writer->DetachBuffer(&buffer);
380 Q_ASSERT_SUCCEEDED(hr);
381 return buffer;
382}
383
385 : registered(false)
386{
387 mainThreadCoInit(this);
388}
389
391{
392 mainThreadCoUninit(this);
393}
394
396{
397 return registered;
398}
399
401{
402 Q_UNUSED(localAdapter);
403 if (registered)
404 return false;
405
407 qCWarning(QT_BT_WINDOWS) << Q_FUNC_INFO << "Only RFCOMM services can be registered on WinRT";
408 return false;
409 }
410
412 if (!sPriv)
413 return false;
414
415 HRESULT hr;
417 ComPtr<IRfcommServiceIdStatics> serviceIdStatics;
418 hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Devices_Bluetooth_Rfcomm_RfcommServiceId).Get(),
419 IID_PPV_ARGS(&serviceIdStatics));
420 Q_ASSERT_SUCCEEDED(hr);
421 ComPtr<IRfcommServiceId> serviceId;
422 hr = serviceIdStatics->FromUuid(uuid, &serviceId);
423 Q_ASSERT_SUCCEEDED(hr);
424 ComPtr<IRfcommServiceProviderStatics> providerStatics;
425 hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Devices_Bluetooth_Rfcomm_RfcommServiceProvider).Get(),
426 IID_PPV_ARGS(&providerStatics));
427 Q_ASSERT_SUCCEEDED(hr);
428 ComPtr<IAsyncOperation<RfcommServiceProvider *>> op;
429 hr = providerStatics->CreateAsync(serviceId.Get(), &op);
430 Q_ASSERT_SUCCEEDED(hr);
431 hr = QWinRTFunctions::await(op, serviceProvider.GetAddressOf());
432 if (hr == HRESULT_FROM_WIN32(ERROR_DEVICE_NOT_AVAILABLE)) {
433 qCWarning(QT_BT_WINDOWS) << Q_FUNC_INFO << "No bluetooth adapter available.";
434 return false;
435 } else {
436 Q_ASSERT_SUCCEEDED(hr);
437 }
438
439 ComPtr<IStreamSocketListener> listener = sPriv->listener();
440 if (!listener) {
441 qCWarning(QT_BT_WINDOWS) << Q_FUNC_INFO << "Could not obtain listener from server.";
442 return false;
443 }
444
445
446 HString serviceIdHString;
447 serviceId->AsString(serviceIdHString.GetAddressOf());
448 Q_ASSERT_SUCCEEDED(hr);
449 const QString serviceIdString = QString::fromWCharArray(WindowsGetStringRawBuffer(serviceIdHString.Get(), nullptr));
450
451 //tell the server what service name our listener should have
452 //and start the real listener
453 bool result = sPriv->initiateActiveListening(serviceIdString);
454 if (!result) {
455 return false;
456 }
457
458 result = writeSdpAttributes();
459 if (!result) {
460 qCWarning(QT_BT_WINDOWS) << "Could not write SDP attributes.";
461 return false;
462 }
463 qCDebug(QT_BT_WINDOWS) << "SDP attributes written.";
464
465 ComPtr<IRfcommServiceProvider2> serviceProvider2;
466 hr = serviceProvider.As(&serviceProvider2);
467 Q_ASSERT_SUCCEEDED(hr);
468 hr = serviceProvider2->StartAdvertisingWithRadioDiscoverability(listener.Get(), true);
469 if (FAILED(hr)) {
470 qCWarning(QT_BT_WINDOWS) << Q_FUNC_INFO << "Could not start advertising. Check your SDP data.";
471 return false;
472 }
473
474 registered = true;
475 return true;
476}
477
479{
480 if (!registered)
481 return false;
482
484 if (!sPriv) {
485 //QBluetoothServer::close() was called without prior call to unregisterService().
486 //Now it is unregistered anyway.
487 registered = false;
488 return true;
489 }
490
491 bool result = sPriv->deactivateActiveListening();
492 if (!result)
493 return false;
494
495 HRESULT hr;
496 hr = serviceProvider->StopAdvertising();
497 Q_ASSERT_SUCCEEDED(hr);
498
499 registered = false;
500 return true;
501}
502
503bool QBluetoothServiceInfoPrivate::writeSdpAttributes()
504{
505 if (!serviceProvider)
506 return false;
507
508 ComPtr<IDataWriter> writer;
509 HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_DataWriter).Get(),
510 &writer);
511 Q_ASSERT_SUCCEEDED(hr);
512 ComPtr<IMap<UINT32, IBuffer *>> rawAttributes;
513 hr = serviceProvider->get_SdpRawAttributes(&rawAttributes);
514 Q_ASSERT_SUCCEEDED(hr);
515 const QList<quint16> keys = attributes.keys();
516 for (quint16 key : keys) {
517 // The SDP Class Id List and RFCOMM and L2CAP protocol descriptors are automatically
518 // generated by the RfcommServiceProvider. Do not specify it in the SDP raw attribute map.
521 continue;
523 HRESULT hr;
524 ComPtr<IBuffer> buffer = bufferFromAttribute(attribute);
525 if (!buffer) {
526 qCWarning(QT_BT_WINDOWS) << "Could not create buffer from attribute with id:" << key;
527 return false;
528 }
529
530 // Other backends support a wrong structure in profile descriptor list. In order to make
531 // WinRT accept the list without breaking existing apps we have to repair this structure.
534 qCWarning(QT_BT_WINDOWS) << Q_FUNC_INFO << "Error while checking/repairing structure of profile descriptor list";
535 return false;
536 }
537 }
538
539 hr = writer->WriteBuffer(buffer.Get());
540 Q_ASSERT_SUCCEEDED(hr);
541
542 hr = writer->DetachBuffer(&buffer);
543 Q_ASSERT_SUCCEEDED(hr);
544
545 boolean replaced;
546 hr = rawAttributes->Insert(key, buffer.Get(), &replaced);
547 Q_ASSERT_SUCCEEDED(hr);
548 Q_ASSERT(!replaced);
549 qCDebug(QT_BT_WINDOWS) << Q_FUNC_INFO << "Registered attribute" << QString::number(key, 16).rightJustified(4, QLatin1Char('0')) << "with value" << attribute;
550 }
551 return true;
552}
553
\inmodule QtBluetooth
QBluetoothServiceInfo::Sequence protocolDescriptor(QBluetoothUuid::ProtocolUuid protocol) const
QMap< quint16, QVariant > attributes
bool registerService(const QBluetoothAddress &localAdapter=QBluetoothAddress())
\inmodule QtBluetooth
int minimumSize() const
Returns the minimum size in bytes that this UUID can be represented in.
\inmodule QtCore
Definition qbytearray.h:57
QByteArray toHex(char separator='\0') const
Returns a hex encoded copy of the byte array.
T value(const Key &key, const T &defaultValue=T()) const
Definition qmap.h:357
QList< Key > keys() const
Definition qmap.h:383
\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
static QString fromWCharArray(const wchar_t *string, qsizetype size=-1)
Definition qstring.h:1309
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 qvariant.h:65
T value() const &
Definition qvariant.h:516
Combined button and popup list for selecting options.
QT_BEGIN_NAMESPACE QHash< QBluetoothServerPrivate *, int > __fakeServerPorts
#define TYPE_UINT64
#define TYPE_UUID128
#define TYPE_URL_BASE
#define TYPE_UUID16
static ComPtr< IBuffer > bufferFromAttribute(const QVariant &attribute)
#define TYPE_STRING_BASE
#define TYPE_ALTERNATIVE_BASE
qint64 getLengthForBaseType(unsigned char type, ComPtr< IDataReader > &reader)
bool repairProfileDescriptorListIfNeeded(ComPtr< IBuffer > &buffer)
#define TYPE_UUID32
bool typeIsOfBase(unsigned char type, unsigned char baseType)
#define TYPE_BOOLEAN
QHash< QBluetoothServerPrivate *, int > __fakeServerPorts
#define TYPE_UINT16
#define TYPE_UINT32
#define TYPE_SEQUENCE_BASE
bool writeStringHelper(const QString &string, ComPtr< IDataWriter > writer)
void mainThreadCoInit(void *caller)
void mainThreadCoUninit(void *caller)
#define Q_FUNC_INFO
EGLOutputLayerEXT EGLint attribute
#define qCWarning(category,...)
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
GLenum GLsizei GLuint GLint * bytesWritten
GLsizei const GLfloat * v
[13]
GLuint64 key
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLenum GLsizei length
GLenum GLuint buffer
GLenum type
GLuint64EXT * result
[6]
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_UNUSED(x)
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
unsigned long long quint64
Definition qtypes.h:61
ptrdiff_t qsizetype
Definition qtypes.h:165
long long qint64
Definition qtypes.h:60
QT_BEGIN_NAMESPACE typedef signed char qint8
Definition qtypes.h:45
unsigned char quint8
Definition qtypes.h:46
long HRESULT
QStringList keys
\inmodule QtCore \reentrant
Definition qchar.h:18