9#include <QtCore/QLoggingCategory>
10#include <QtCore/private/qfunctions_winrt_p.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>
20using namespace Microsoft::WRL::Wrappers;
22using namespace ABI::Windows::Devices::Bluetooth::Rfcomm;
24using namespace ABI::Windows::Foundation::Collections;
25using namespace ABI::Windows::Networking::Sockets;
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
56 return ((
type & baseType) == baseType);
72 const unsigned char sizeIndex = (
type & 0x7);
76 hr = reader->ReadByte(&
length);
77 RETURN_IF_FAILED(
"Could not read length from buffer",
return -1);
81 hr = reader->ReadUInt16(&
length);
82 RETURN_IF_FAILED(
"Could not read length from buffer",
return -1);
86 hr = reader->ReadUInt32(&
length);
87 RETURN_IF_FAILED(
"Could not read length from buffer",
return -1);
97 const qsizetype stringLength =
string.size();
99 if (stringLength < 0) {
100 qCWarning(QT_BT_WINDOWS) <<
"Can not write invalid string value to buffer";
102 }
if (stringLength <= 0xff) {
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) {
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.");
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.");
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.");
126 qCWarning(QT_BT_WINDOWS) <<
"Did not write full value to buffer";
134 ComPtr<IDataReaderStatics> dataReaderStatics;
135 HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_DataReader).Get(),
137 Q_ASSERT_SUCCEEDED(hr);
139 ComPtr<IDataReader> reader;
140 hr = dataReaderStatics->FromBuffer(
buffer.Get(), reader.GetAddressOf());
141 Q_ASSERT_SUCCEEDED(hr);
144 hr = reader->ReadByte(&
type);
145 Q_ASSERT_SUCCEEDED(hr);
152 hr = reader->ReadByte(&
type);
153 Q_ASSERT_SUCCEEDED(hr);
158 hr = reader->ReadUInt16(&uuid);
159 Q_ASSERT_SUCCEEDED(hr);
161 ComPtr<IDataWriter> writer;
162 hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_DataWriter).Get(),
164 Q_ASSERT_SUCCEEDED(hr);
167 Q_ASSERT_SUCCEEDED(hr);
169 hr = writer->WriteByte(8);
170 Q_ASSERT_SUCCEEDED(hr);
172 Q_ASSERT_SUCCEEDED(hr);
173 hr = writer->WriteByte(7);
174 Q_ASSERT_SUCCEEDED(hr);
176 Q_ASSERT_SUCCEEDED(hr);
177 hr = writer->WriteUInt16(uuid);
178 Q_ASSERT_SUCCEEDED(hr);
181 Q_ASSERT_SUCCEEDED(hr);
182 hr = writer->WriteUInt16(0x100);
183 Q_ASSERT_SUCCEEDED(hr);
185 hr = writer->DetachBuffer(&
buffer);
186 Q_ASSERT_SUCCEEDED(hr);
194 ComPtr<IDataWriter> writer;
195 HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_DataWriter).Get(),
197 Q_ASSERT_SUCCEEDED(hr);
200 case QMetaType::Void:
201 qCDebug(QT_BT_WINDOWS) <<
Q_FUNC_INFO <<
"Registering attribute of type QMetaType::Void:";
203 Q_ASSERT_SUCCEEDED(hr);
205 case QMetaType::UChar:
208 Q_ASSERT_SUCCEEDED(hr);
210 Q_ASSERT_SUCCEEDED(hr);
212 case QMetaType::UShort:
215 Q_ASSERT_SUCCEEDED(hr);
217 Q_ASSERT_SUCCEEDED(hr);
219 case QMetaType::UInt:
222 Q_ASSERT_SUCCEEDED(hr);
224 Q_ASSERT_SUCCEEDED(hr);
226 case QMetaType::ULongLong:
229 Q_ASSERT_SUCCEEDED(hr);
231 Q_ASSERT_SUCCEEDED(hr);
233 case QMetaType::Char:
236 Q_ASSERT_SUCCEEDED(hr);
238 Q_ASSERT_SUCCEEDED(hr);
240 case QMetaType::Short:
243 Q_ASSERT_SUCCEEDED(hr);
245 Q_ASSERT_SUCCEEDED(hr);
250 Q_ASSERT_SUCCEEDED(hr);
252 Q_ASSERT_SUCCEEDED(hr);
254 case QMetaType::LongLong:
257 Q_ASSERT_SUCCEEDED(hr);
259 Q_ASSERT_SUCCEEDED(hr);
261 case QMetaType::QByteArray: {
269 case QMetaType::QString: {
277 case QMetaType::Bool:
280 Q_ASSERT_SUCCEEDED(hr);
281 hr = writer->WriteByte(
attribute.value<
bool>());
282 Q_ASSERT_SUCCEEDED(hr);
284 case QMetaType::QUrl:
285 qCWarning(QT_BT_WINDOWS) <<
"Don't know how to register QMetaType::QUrl";
289 if (
attribute.userType() == qMetaTypeId<QBluetoothUuid>()) {
293 qCWarning(QT_BT_WINDOWS) <<
"Don't know how to register Uuid of length 0";
296 qCDebug(QT_BT_WINDOWS) <<
Q_FUNC_INFO <<
"Registering Uuid attribute with length 2:" << uuid;
298 Q_ASSERT_SUCCEEDED(hr);
299 hr = writer->WriteUInt16(uuid.toUInt16());
300 Q_ASSERT_SUCCEEDED(hr);
303 qCDebug(QT_BT_WINDOWS) <<
Q_FUNC_INFO <<
"Registering Uuid attribute with length 4:" << uuid;
305 Q_ASSERT_SUCCEEDED(hr);
306 hr = writer->WriteUInt32(uuid.toUInt32());
307 Q_ASSERT_SUCCEEDED(hr);
313 Q_ASSERT_SUCCEEDED(hr);
314 hr = writer->WriteGuid(uuid);
315 Q_ASSERT_SUCCEEDED(hr);
318 }
else if (
attribute.userType() == qMetaTypeId<QBluetoothServiceInfo::Sequence>()) {
319 qCDebug(QT_BT_WINDOWS) <<
"Registering sequence attribute";
322 ComPtr<IDataWriter> tmpWriter;
323 HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_DataWriter).Get(),
325 Q_ASSERT_SUCCEEDED(hr);
329 qCWarning(QT_BT_WINDOWS) <<
"Could not create buffer from attribute in sequence";
333 hr = tmpBuffer->get_Length(&l);
334 Q_ASSERT_SUCCEEDED(hr);
335 hr = tmpWriter->WriteBuffer(tmpBuffer.Get());
336 Q_ASSERT_SUCCEEDED(hr);
338 ComPtr<IBuffer> tmpBuffer;
339 hr = tmpWriter->DetachBuffer(&tmpBuffer);
340 Q_ASSERT_SUCCEEDED(hr);
343 tmpBuffer->get_Length(&
length);
344 Q_ASSERT_SUCCEEDED(hr);
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) {
355 hr = writer->WriteByte(
type);
356 Q_ASSERT_SUCCEEDED(hr);
357 hr = writer->WriteUInt16(
length);
358 Q_ASSERT_SUCCEEDED(hr);
361 hr = writer->WriteByte(
type);
362 Q_ASSERT_SUCCEEDED(hr);
363 hr = writer->WriteUInt32(
length);
364 Q_ASSERT_SUCCEEDED(hr);
367 hr = writer->WriteBuffer(tmpBuffer.Get());
368 Q_ASSERT_SUCCEEDED(hr);
370 }
else if (
attribute.userType() == qMetaTypeId<QBluetoothServiceInfo::Alternative>()) {
371 qCWarning(QT_BT_WINDOWS) <<
"Don't know how to register user type Alternative";
379 hr = writer->DetachBuffer(&
buffer);
380 Q_ASSERT_SUCCEEDED(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)) {
436 Q_ASSERT_SUCCEEDED(hr);
439 ComPtr<IStreamSocketListener> listener = sPriv->listener();
446 HString serviceIdHString;
447 serviceId->AsString(serviceIdHString.GetAddressOf());
448 Q_ASSERT_SUCCEEDED(hr);
453 bool result = sPriv->initiateActiveListening(serviceIdString);
458 result = writeSdpAttributes();
460 qCWarning(QT_BT_WINDOWS) <<
"Could not write SDP attributes.";
463 qCDebug(QT_BT_WINDOWS) <<
"SDP attributes written.";
465 ComPtr<IRfcommServiceProvider2> serviceProvider2;
466 hr = serviceProvider.As(&serviceProvider2);
467 Q_ASSERT_SUCCEEDED(hr);
468 hr = serviceProvider2->StartAdvertisingWithRadioDiscoverability(listener.Get(),
true);
491 bool result = sPriv->deactivateActiveListening();
496 hr = serviceProvider->StopAdvertising();
497 Q_ASSERT_SUCCEEDED(hr);
503bool QBluetoothServiceInfoPrivate::writeSdpAttributes()
505 if (!serviceProvider)
508 ComPtr<IDataWriter> writer;
509 HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_DataWriter).Get(),
511 Q_ASSERT_SUCCEEDED(hr);
512 ComPtr<IMap<UINT32, IBuffer *>> rawAttributes;
513 hr = serviceProvider->get_SdpRawAttributes(&rawAttributes);
514 Q_ASSERT_SUCCEEDED(hr);
526 qCWarning(QT_BT_WINDOWS) <<
"Could not create buffer from attribute with id:" <<
key;
534 qCWarning(QT_BT_WINDOWS) <<
Q_FUNC_INFO <<
"Error while checking/repairing structure of profile descriptor list";
539 hr = writer->WriteBuffer(
buffer.Get());
540 Q_ASSERT_SUCCEEDED(hr);
542 hr = writer->DetachBuffer(&
buffer);
543 Q_ASSERT_SUCCEEDED(hr);
546 hr = rawAttributes->Insert(
key,
buffer.Get(), &replaced);
547 Q_ASSERT_SUCCEEDED(hr);
QBluetoothServiceInfo::Sequence protocolDescriptor(QBluetoothUuid::ProtocolUuid protocol) const
QMap< quint16, QVariant > attributes
QBluetoothServiceInfoPrivate()
bool registerService(const QBluetoothAddress &localAdapter=QBluetoothAddress())
int serverChannel() const
bool isRegistered() const
~QBluetoothServiceInfoPrivate()
@ BluetoothProfileDescriptorList
int minimumSize() const
Returns the minimum size in bytes that this UUID can be represented in.
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
QList< Key > keys() const
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QString fromWCharArray(const wchar_t *string, qsizetype size=-1)
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Combined button and popup list for selecting options.
QT_BEGIN_NAMESPACE QHash< QBluetoothServerPrivate *, int > __fakeServerPorts
static ComPtr< IBuffer > bufferFromAttribute(const QVariant &attribute)
#define TYPE_ALTERNATIVE_BASE
qint64 getLengthForBaseType(unsigned char type, ComPtr< IDataReader > &reader)
bool repairProfileDescriptorListIfNeeded(ComPtr< IBuffer > &buffer)
bool typeIsOfBase(unsigned char type, unsigned char baseType)
QHash< QBluetoothServerPrivate *, int > __fakeServerPorts
#define TYPE_SEQUENCE_BASE
bool writeStringHelper(const QString &string, ComPtr< IDataWriter > writer)
void mainThreadCoInit(void *caller)
void mainThreadCoUninit(void *caller)
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]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLenum GLsizei length
unsigned long long quint64
QT_BEGIN_NAMESPACE typedef signed char qint8
\inmodule QtCore \reentrant