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 | |
4 | #include "qbluetoothserviceinfo.h" |
5 | #include "qbluetoothserviceinfo_p.h" |
6 | |
7 | #include <QUrl> |
8 | |
9 | QT_BEGIN_NAMESPACE |
10 | |
11 | QT_IMPL_METATYPE_EXTERN(QBluetoothServiceInfo) |
12 | QT_IMPL_METATYPE_EXTERN_TAGGED(QBluetoothServiceInfo::Sequence, QBluetoothServiceInfo__Sequence) |
13 | QT_IMPL_METATYPE_EXTERN_TAGGED(QBluetoothServiceInfo::Alternative, |
14 | QBluetoothServiceInfo__Alternative) |
15 | |
16 | /*! |
17 | \class QBluetoothServiceInfo::Sequence |
18 | \inmodule QtBluetooth |
19 | \brief The Sequence class stores attributes of a Bluetooth Data Element |
20 | Sequence. |
21 | |
22 | \since 5.2 |
23 | |
24 | */ |
25 | |
26 | /*! |
27 | \fn QBluetoothServiceInfo::Sequence::Sequence() |
28 | |
29 | Constructs a new empty sequence. |
30 | */ |
31 | |
32 | /*! |
33 | \fn QBluetoothServiceInfo::Sequence::Sequence(const QList<QVariant> &list) |
34 | |
35 | Constructs a new sequence that is a copy of \a list. |
36 | */ |
37 | |
38 | /*! |
39 | \class QBluetoothServiceInfo::Alternative |
40 | \inmodule QtBluetooth |
41 | \brief The Alternative class stores attributes of a Bluetooth Data Element |
42 | Alternative. |
43 | |
44 | \since 5.2 |
45 | */ |
46 | |
47 | /*! |
48 | \fn QBluetoothServiceInfo::Alternative::Alternative() |
49 | |
50 | Constructs a new empty alternative. |
51 | */ |
52 | |
53 | /*! |
54 | \fn QBluetoothServiceInfo::Alternative::Alternative(const QList<QVariant> &list) |
55 | |
56 | Constructs a new alternative that is a copy of \a list. |
57 | */ |
58 | |
59 | /*! |
60 | \class QBluetoothServiceInfo |
61 | \inmodule QtBluetooth |
62 | \brief The QBluetoothServiceInfo class enables access to the attributes of a |
63 | Bluetooth service. |
64 | |
65 | \since 5.2 |
66 | |
67 | QBluetoothServiceInfo provides information about a service offered by a Bluetooth device. |
68 | In addition it can be used to register new services on the local device. Note that such |
69 | a registration only affects the Bluetooth SDP entries. Any server listening |
70 | for incoming connections (e.g an RFCOMM server) must be started before registerService() |
71 | is called. Deregistration must happen in the reverse order. |
72 | |
73 | QBluetoothServiceInfo is not a value type in the traditional sense. All copies of the same |
74 | service info object share the same data as they do not detach upon changing them. This |
75 | ensures that two copies can (de)register the same Bluetooth service. |
76 | |
77 | On iOS, this class cannot be used because the platform does not expose |
78 | an API which may permit access to QBluetoothServiceInfo related features. |
79 | */ |
80 | |
81 | /*! |
82 | \enum QBluetoothServiceInfo::AttributeId |
83 | |
84 | Bluetooth service attributes. Please check the Bluetooth Core Specification for a more detailed description of these attributes. |
85 | |
86 | \value ServiceRecordHandle Specifies a service record from which attributes can be retrieved. |
87 | \value ServiceClassIds UUIDs of service classes that the service conforms to. The |
88 | most common service classes are defined in (\l QBluetoothUuid::ServiceClassUuid) |
89 | \value ServiceRecordState Attibute changes when any other service attribute is added, deleted or modified. |
90 | \value ServiceId UUID that uniquely identifies the service. |
91 | \value ProtocolDescriptorList List of protocols used by the service. The most common protocol Uuids are defined |
92 | in \l QBluetoothUuid::ProtocolUuid |
93 | \value BrowseGroupList List of browse groups the service is in. |
94 | \value LanguageBaseAttributeIdList List of language base attribute IDs to support human-readable attributes. |
95 | \value ServiceInfoTimeToLive Number of seconds for which the service record is expected to remain valid and unchanged. |
96 | \value ServiceAvailability Value indicating the availability of the service. |
97 | \value BluetoothProfileDescriptorList List of profiles to which the service conforms. |
98 | \value DocumentationUrl URL that points to the documentation on the service.. |
99 | \value ClientExecutableUrl URL that refers to the location of an application that can be used to utilize the service. |
100 | \value IconUrl URL to the location of the icon representing the service. |
101 | \value AdditionalProtocolDescriptorList Additional protocols used by the service. This attribute extends \c ProtocolDescriptorList. |
102 | \value PrimaryLanguageBase Base index for primary language text descriptors. |
103 | \value ServiceName Name of the Bluetooth service in the primary language. |
104 | \value ServiceDescription Description of the Bluetooth service in the primary language. |
105 | \value ServiceProvider Name of the company / entity that provides the Bluetooth service primary language. |
106 | |
107 | \note On Windows ServiceClassIds and ProtocolDescriptorList are automatically set to default |
108 | values when a service is created. Manually setting values for these attributes will not work and |
109 | might lead to unexpected results on this platform. |
110 | */ |
111 | |
112 | /*! |
113 | \enum QBluetoothServiceInfo::Protocol |
114 | |
115 | This enum describes the socket protocol used by the service. |
116 | |
117 | \value UnknownProtocol The service uses an unknown socket protocol. |
118 | \value L2capProtocol The service uses the L2CAP socket protocol. This protocol is not supported |
119 | for direct socket connections on Android. |
120 | \value RfcommProtocol The service uses the RFCOMM socket protocol. |
121 | */ |
122 | |
123 | /*! |
124 | \fn bool QBluetoothServiceInfo::isRegistered() const |
125 | |
126 | Returns true if the service information is registered with the platform's Service Discovery Protocol |
127 | (SDP) implementation, otherwise returns false. |
128 | */ |
129 | |
130 | bool QBluetoothServiceInfo::isRegistered() const |
131 | { |
132 | return d_ptr->isRegistered(); |
133 | } |
134 | |
135 | /*! |
136 | \fn bool QBluetoothServiceInfo::registerService(const QBluetoothAddress &localAdapter) |
137 | |
138 | Registers this service with the platform's Service Discovery Protocol (SDP) implementation, |
139 | making it findable by other devices when they perform service discovery. Returns true if the |
140 | service is successfully registered, otherwise returns false. Once registered changes to the record |
141 | cannot be made. The service must be unregistered and registered again with the changes. |
142 | |
143 | The \a localAdapter parameter determines the local Bluetooth adapter under which |
144 | the service should be registered. If \a localAdapter is \c null the default Bluetooth adapter |
145 | will be used. If this service info object is already registered via a local adapter |
146 | and this is function is called using a different local adapter, the previous registration |
147 | is removed and the service reregistered using the new adapter. |
148 | */ |
149 | |
150 | bool QBluetoothServiceInfo::registerService(const QBluetoothAddress &localAdapter) |
151 | { |
152 | #ifdef QT_OSX_BLUETOOTH |
153 | Q_UNUSED(localAdapter); |
154 | return d_ptr->registerService(*this); |
155 | #else |
156 | return d_ptr->registerService(localAdapter); |
157 | #endif |
158 | } |
159 | |
160 | /*! |
161 | \fn bool QBluetoothServiceInfo::unregisterService() |
162 | |
163 | Unregisters this service with the platform's Service Discovery Protocol (SDP) implementation. |
164 | After this, the service will no longer be findable by other devices through service discovery. |
165 | |
166 | Returns true if the service is successfully unregistered, otherwise returns false. |
167 | */ |
168 | |
169 | bool QBluetoothServiceInfo::unregisterService() |
170 | { |
171 | return d_ptr->unregisterService(); |
172 | } |
173 | |
174 | |
175 | /*! |
176 | \fn void QBluetoothServiceInfo::setAttribute(quint16 attributeId, const QBluetoothUuid &value) |
177 | |
178 | This is a convenience function. |
179 | |
180 | Sets the attribute identified by \a attributeId to \a value. |
181 | |
182 | If the service information is already registered with the platform's SDP database, |
183 | the database entry will not be updated until \l registerService() was called again. |
184 | */ |
185 | |
186 | /*! |
187 | \fn void QBluetoothServiceInfo::setAttribute(quint16 attributeId, const QBluetoothServiceInfo::Sequence &value) |
188 | |
189 | This is a convenience function. |
190 | |
191 | Sets the attribute identified by \a attributeId to \a value. |
192 | |
193 | If the service information is already registered with the platform's SDP database, |
194 | the database entry will not be updated until \l registerService() was called again. |
195 | */ |
196 | |
197 | /*! |
198 | \fn void QBluetoothServiceInfo::setAttribute(quint16 attributeId, const QBluetoothServiceInfo::Alternative &value) |
199 | |
200 | This is a convenience function. |
201 | |
202 | Sets the attribute identified by \a attributeId to \a value. |
203 | |
204 | If the service information is already registered with the platform's SDP database, |
205 | the database entry will not be updated until \l registerService() was called again. |
206 | */ |
207 | |
208 | /*! |
209 | \fn void QBluetoothServiceInfo::setServiceName(const QString &name) |
210 | |
211 | This is a convenience function. It is equivalent to calling |
212 | setAttribute(QBluetoothServiceInfo::ServiceName, name). |
213 | |
214 | Sets the service name in the primary language to \a name. |
215 | |
216 | \sa serviceName(), setAttribute() |
217 | */ |
218 | |
219 | /*! |
220 | \fn QString QBluetoothServiceInfo::serviceName() const |
221 | |
222 | This is a convenience function. It is equivalent to calling |
223 | attribute(QBluetoothServiceInfo::ServiceName).toString(). |
224 | |
225 | Returns the service name in the primary language. |
226 | |
227 | \sa setServiceName(), attribute() |
228 | */ |
229 | |
230 | /*! |
231 | \fn void QBluetoothServiceInfo::setServiceDescription(const QString &description) |
232 | |
233 | This is a convenience function. It is equivalent to calling |
234 | setAttribute(QBluetoothServiceInfo::ServiceDescription, description). |
235 | |
236 | Sets the service description in the primary language to \a description. |
237 | |
238 | \sa serviceDescription(), setAttribute() |
239 | */ |
240 | |
241 | /*! |
242 | \fn QString QBluetoothServiceInfo::serviceDescription() const |
243 | |
244 | This is a convenience function. It is equivalent to calling |
245 | attribute(QBluetoothServiceInfo::ServiceDescription).toString(). |
246 | |
247 | Returns the service description in the primary language. |
248 | |
249 | \sa setServiceDescription(), attribute() |
250 | */ |
251 | |
252 | /*! |
253 | \fn void QBluetoothServiceInfo::setServiceProvider(const QString &provider) |
254 | |
255 | This is a convenience function. It is equivalent to calling |
256 | setAttribute(QBluetoothServiceInfo::ServiceProvider, provider). |
257 | |
258 | Sets the service provider in the primary language to \a provider. |
259 | |
260 | \sa serviceProvider(), setAttribute() |
261 | */ |
262 | |
263 | /*! |
264 | \fn QString QBluetoothServiceInfo::serviceProvider() const |
265 | |
266 | This is a convenience function. It is equivalent to calling |
267 | attribute(QBluetoothServiceInfo::ServiceProvider).toString(). |
268 | |
269 | Returns the service provider in the primary language. |
270 | |
271 | \sa setServiceProvider(), attribute() |
272 | */ |
273 | |
274 | /*! |
275 | \fn void QBluetoothServiceInfo::setServiceAvailability(quint8 availability) |
276 | |
277 | This is a convenience function. It is equivalent to calling |
278 | setAttribute(QBluetoothServiceInfo::ServiceAvailability, availability). |
279 | |
280 | Sets the availabiltiy of the service to \a availability. |
281 | |
282 | \sa serviceAvailability(), setAttribute() |
283 | */ |
284 | |
285 | /*! |
286 | \fn quint8 QBluetoothServiceInfo::serviceAvailability() const |
287 | |
288 | This is a convenience function. It is equivalent to calling |
289 | attribute(QBluetoothServiceInfo::ServiceAvailability).toUInt(). |
290 | |
291 | Returns the availability of the service. |
292 | |
293 | \sa setServiceAvailability(), attribute() |
294 | */ |
295 | |
296 | /*! |
297 | \fn void QBluetoothServiceInfo::setServiceUuid(const QBluetoothUuid &uuid) |
298 | |
299 | This is a convenience function. It is equivalent to calling |
300 | setAttribute(QBluetoothServiceInfo::ServiceId, uuid). |
301 | |
302 | Sets the custom service UUID to \a uuid. This function should not be used |
303 | to set a standardized service UUID. |
304 | |
305 | \sa serviceUuid(), setAttribute() |
306 | */ |
307 | |
308 | /*! |
309 | \fn QBluetoothUuid QBluetoothServiceInfo::serviceUuid() const |
310 | |
311 | This is a convenience function. It is equivalent to calling |
312 | attribute(QBluetoothServiceInfo::ServiceId).value<QBluetoothUuid>(). |
313 | |
314 | Returns the custom UUID of the service. This UUID may be null. |
315 | UUIDs based on \l{https://bluetooth.org}{Bluetooth SIG standards} |
316 | should be retrieved via \l serviceClassUuids(). |
317 | |
318 | \sa setServiceUuid(), attribute() |
319 | */ |
320 | |
321 | /*! |
322 | Construct a new invalid QBluetoothServiceInfo; |
323 | */ |
324 | QBluetoothServiceInfo::QBluetoothServiceInfo() |
325 | : d_ptr(QSharedPointer<QBluetoothServiceInfoPrivate>::create()) |
326 | { |
327 | qRegisterMetaType<QBluetoothServiceInfo>(); |
328 | } |
329 | |
330 | /*! |
331 | Construct a new QBluetoothServiceInfo that is a copy of \a other. |
332 | |
333 | The two copies continue to share the same underlying data which does not detach |
334 | upon write. |
335 | */ |
336 | QBluetoothServiceInfo::QBluetoothServiceInfo(const QBluetoothServiceInfo &other) |
337 | : d_ptr(other.d_ptr) |
338 | { |
339 | } |
340 | |
341 | /*! |
342 | Destroys the QBluetoothServiceInfo object. |
343 | */ |
344 | QBluetoothServiceInfo::~QBluetoothServiceInfo() |
345 | { |
346 | } |
347 | |
348 | /*! |
349 | Returns true if the QBluetoothServiceInfo object is valid, otherwise returns false. |
350 | |
351 | An invalid QBluetoothServiceInfo object will have no attributes. |
352 | */ |
353 | bool QBluetoothServiceInfo::isValid() const |
354 | { |
355 | return !d_ptr->attributes.isEmpty(); |
356 | } |
357 | |
358 | /*! |
359 | Returns true if the QBluetoothServiceInfo object is considered complete, otherwise returns false. |
360 | |
361 | A complete QBluetoothServiceInfo object contains a ProtocolDescriptorList attribute. |
362 | */ |
363 | bool QBluetoothServiceInfo::isComplete() const |
364 | { |
365 | return d_ptr->attributes.contains(key: ProtocolDescriptorList); |
366 | } |
367 | |
368 | /*! |
369 | Returns the address of the Bluetooth device that provides this service. |
370 | */ |
371 | QBluetoothDeviceInfo QBluetoothServiceInfo::device() const |
372 | { |
373 | return d_ptr->deviceInfo; |
374 | } |
375 | |
376 | /*! |
377 | Sets the Bluetooth device that provides this service to \a device. |
378 | */ |
379 | void QBluetoothServiceInfo::setDevice(const QBluetoothDeviceInfo &device) |
380 | { |
381 | d_ptr->deviceInfo = device; |
382 | } |
383 | |
384 | /*! |
385 | Sets the attribute identified by \a attributeId to \a value. |
386 | |
387 | If the service information is already registered with the platform's SDP database, |
388 | the database entry will not be updated until \l registerService() was called again. |
389 | |
390 | \note If an attribute expectes a byte-encoded value (e.g. Bluetooth HID services), |
391 | it should be set as QByteArray. |
392 | |
393 | \sa isRegistered(), registerService() |
394 | */ |
395 | void QBluetoothServiceInfo::setAttribute(quint16 attributeId, const QVariant &value) |
396 | { |
397 | d_ptr->attributes[attributeId] = value; |
398 | } |
399 | |
400 | /*! |
401 | Returns the value of the attribute \a attributeId. |
402 | */ |
403 | QVariant QBluetoothServiceInfo::attribute(quint16 attributeId) const |
404 | { |
405 | return d_ptr->attributes.value(key: attributeId); |
406 | } |
407 | |
408 | /*! |
409 | Returns a list of all attribute ids that the QBluetoothServiceInfo object has. |
410 | */ |
411 | QList<quint16> QBluetoothServiceInfo::attributes() const |
412 | { |
413 | return d_ptr->attributes.keys(); |
414 | } |
415 | |
416 | /*! |
417 | Returns true if the QBluetoothServiceInfo object contains the attribute \a attributeId, otherwise returns |
418 | false. |
419 | */ |
420 | bool QBluetoothServiceInfo::contains(quint16 attributeId) const |
421 | { |
422 | return d_ptr->attributes.contains(key: attributeId); |
423 | } |
424 | |
425 | /*! |
426 | Removes the attribute \a attributeId from the QBluetoothServiceInfo object. |
427 | |
428 | If the service information is already registered with the platforms SDP database, |
429 | the database entry will not be updated until \l registerService() was called again. |
430 | */ |
431 | void QBluetoothServiceInfo::removeAttribute(quint16 attributeId) |
432 | { |
433 | d_ptr->attributes.remove(key: attributeId); |
434 | } |
435 | |
436 | /*! |
437 | Returns the protocol that the QBluetoothServiceInfo object uses. |
438 | */ |
439 | QBluetoothServiceInfo::Protocol QBluetoothServiceInfo::socketProtocol() const |
440 | { |
441 | QBluetoothServiceInfo::Sequence parameters = protocolDescriptor(protocol: QBluetoothUuid::ProtocolUuid::Rfcomm); |
442 | if (!parameters.isEmpty()) |
443 | return RfcommProtocol; |
444 | |
445 | parameters = protocolDescriptor(protocol: QBluetoothUuid::ProtocolUuid::L2cap); |
446 | if (!parameters.isEmpty()) |
447 | return L2capProtocol; |
448 | |
449 | return UnknownProtocol; |
450 | } |
451 | |
452 | /*! |
453 | This is a convenience function. Returns the protocol/service multiplexer for services which |
454 | support the L2CAP protocol, otherwise returns -1. |
455 | |
456 | This function is equivalent to extracting the information from |
457 | QBluetoothServiceInfo::Sequence returned by |
458 | QBluetoothServiceInfo::attribute(QBluetoothServiceInfo::ProtocolDescriptorList). |
459 | */ |
460 | int QBluetoothServiceInfo::protocolServiceMultiplexer() const |
461 | { |
462 | QBluetoothServiceInfo::Sequence parameters = protocolDescriptor(protocol: QBluetoothUuid::ProtocolUuid::L2cap); |
463 | |
464 | if (parameters.isEmpty()) |
465 | return -1; |
466 | else if (parameters.size() == 1) |
467 | return 0; |
468 | else |
469 | return parameters.at(i: 1).toUInt(); |
470 | } |
471 | |
472 | /*! |
473 | This is a convenience function. Returns the server channel for services which support the |
474 | RFCOMM protocol, otherwise returns -1. |
475 | |
476 | This function is equivalent to extracting the information from |
477 | QBluetoothServiceInfo::Sequence returned by |
478 | QBluetoothServiceInfo::attribute(QBluetootherServiceInfo::ProtocolDescriptorList). |
479 | */ |
480 | int QBluetoothServiceInfo::serverChannel() const |
481 | { |
482 | return d_ptr->serverChannel(); |
483 | } |
484 | |
485 | /*! |
486 | Returns the protocol parameters as a QBluetoothServiceInfo::Sequence for protocol \a protocol. |
487 | |
488 | An empty QBluetoothServiceInfo::Sequence is returned if \a protocol is not supported. |
489 | */ |
490 | QBluetoothServiceInfo::Sequence QBluetoothServiceInfo::protocolDescriptor(QBluetoothUuid::ProtocolUuid protocol) const |
491 | { |
492 | return d_ptr->protocolDescriptor(protocol); |
493 | } |
494 | |
495 | /*! |
496 | Returns a list of UUIDs describing the service classes that this service conforms to. |
497 | |
498 | This is a convenience function. It is equivalent to calling |
499 | attribute(QBluetoothServiceInfo::ServiceClassIds).value<QBluetoothServiceInfo::Sequence>() |
500 | and subsequently iterating over its QBluetoothUuid entries. |
501 | |
502 | \sa attribute() |
503 | */ |
504 | QList<QBluetoothUuid> QBluetoothServiceInfo::serviceClassUuids() const |
505 | { |
506 | QList<QBluetoothUuid> results; |
507 | |
508 | const QVariant var = attribute(attributeId: QBluetoothServiceInfo::ServiceClassIds); |
509 | if (!var.isValid()) |
510 | return results; |
511 | |
512 | const QBluetoothServiceInfo::Sequence seq = var.value<QBluetoothServiceInfo::Sequence>(); |
513 | for (qsizetype i = 0; i < seq.size(); ++i) |
514 | results.append(t: seq.at(i).value<QBluetoothUuid>()); |
515 | |
516 | return results; |
517 | } |
518 | |
519 | /*! |
520 | Makes a copy of the \a other and assigns it to this QBluetoothServiceInfo object. |
521 | The two copies continue to share the same service and registration details. |
522 | */ |
523 | QBluetoothServiceInfo &QBluetoothServiceInfo::operator=(const QBluetoothServiceInfo &other) |
524 | { |
525 | d_ptr = other.d_ptr; |
526 | |
527 | return *this; |
528 | } |
529 | |
530 | static void dumpAttributeVariant(QDebug dbg, const QVariant &var, const QString& indent) |
531 | { |
532 | switch (var.typeId()) { |
533 | case QMetaType::Void: |
534 | dbg << QString::asprintf(format: "%sEmpty\n" , indent.toUtf8().constData()); |
535 | break; |
536 | case QMetaType::UChar: |
537 | dbg << QString::asprintf(format: "%suchar %u\n" , indent.toUtf8().constData(), var.toUInt()); |
538 | break; |
539 | case QMetaType::UShort: |
540 | dbg << QString::asprintf(format: "%sushort %u\n" , indent.toUtf8().constData(), var.toUInt()); |
541 | break; |
542 | case QMetaType::UInt: |
543 | dbg << QString::asprintf(format: "%suint %u\n" , indent.toUtf8().constData(), var.toUInt()); |
544 | break; |
545 | case QMetaType::Char: |
546 | dbg << QString::asprintf(format: "%schar %d\n" , indent.toUtf8().constData(), var.toInt()); |
547 | break; |
548 | case QMetaType::Short: |
549 | dbg << QString::asprintf(format: "%sshort %d\n" , indent.toUtf8().constData(), var.toInt()); |
550 | break; |
551 | case QMetaType::Int: |
552 | dbg << QString::asprintf(format: "%sint %d\n" , indent.toUtf8().constData(), var.toInt()); |
553 | break; |
554 | case QMetaType::QString: |
555 | dbg << QString::asprintf(format: "%sstring %s\n" , indent.toUtf8().constData(), |
556 | var.toString().toUtf8().constData()); |
557 | break; |
558 | case QMetaType::QByteArray: |
559 | dbg << QString::asprintf(format: "%sbytearray %s\n" , indent.toUtf8().constData(), |
560 | var.toByteArray().toHex().constData()); |
561 | break; |
562 | case QMetaType::Bool: |
563 | dbg << QString::asprintf(format: "%sbool %d\n" , indent.toUtf8().constData(), var.toBool()); |
564 | break; |
565 | case QMetaType::QUrl: |
566 | dbg << QString::asprintf(format: "%surl %s\n" , indent.toUtf8().constData(), |
567 | var.toUrl().toString().toUtf8().constData()); |
568 | break; |
569 | default: |
570 | if (var.typeId() == qMetaTypeId<QBluetoothUuid>()) { |
571 | QBluetoothUuid uuid = var.value<QBluetoothUuid>(); |
572 | switch (uuid.minimumSize()) { |
573 | case 0: |
574 | dbg << QString::asprintf(format: "%suuid NULL\n" , indent.toUtf8().constData()); |
575 | break; |
576 | case 2: |
577 | dbg << QString::asprintf(format: "%suuid2 %04x\n" , indent.toUtf8().constData(), |
578 | uuid.toUInt16()); |
579 | break; |
580 | case 4: |
581 | dbg << QString::asprintf(format: "%suuid %08x\n" , indent.toUtf8().constData(), |
582 | uuid.toUInt32()); |
583 | break; |
584 | case 16: |
585 | dbg << QString::asprintf(format: "%suuid %s\n" , |
586 | indent.toUtf8().constData(), |
587 | uuid.toByteArray(mode: QUuid::Id128).constData()); |
588 | break; |
589 | default: |
590 | dbg << QString::asprintf(format: "%suuid ???\n" , indent.toUtf8().constData()); |
591 | } |
592 | } else if (var.typeId() == qMetaTypeId<QBluetoothServiceInfo::Sequence>()) { |
593 | dbg << QString::asprintf(format: "%sSequence\n" , indent.toUtf8().constData()); |
594 | const QBluetoothServiceInfo::Sequence *sequence = static_cast<const QBluetoothServiceInfo::Sequence *>(var.data()); |
595 | for (const QVariant &v : *sequence) |
596 | dumpAttributeVariant(dbg, var: v, indent: indent + QLatin1Char('\t')); |
597 | } else if (var.typeId() == qMetaTypeId<QBluetoothServiceInfo::Alternative>()) { |
598 | dbg << QString::asprintf(format: "%sAlternative\n" , indent.toUtf8().constData()); |
599 | const QBluetoothServiceInfo::Alternative *alternative = static_cast<const QBluetoothServiceInfo::Alternative *>(var.data()); |
600 | for (const QVariant &v : *alternative) |
601 | dumpAttributeVariant(dbg, var: v, indent: indent + QLatin1Char('\t')); |
602 | } else { |
603 | dbg << QString::asprintf(format: "%sunknown variant type %d\n" , indent.toUtf8().constData(), var.typeId()); |
604 | } |
605 | } |
606 | } |
607 | |
608 | #ifndef QT_NO_DEBUG_STREAM |
609 | QDebug QBluetoothServiceInfo::streamingOperator(QDebug dbg, const QBluetoothServiceInfo &info) |
610 | { |
611 | QDebugStateSaver saver(dbg); |
612 | dbg.noquote() << "\n" ; |
613 | const QList<quint16> attributes = info.attributes(); |
614 | for (quint16 id : attributes) { |
615 | dumpAttributeVariant(dbg, var: info.attribute(attributeId: id), QStringLiteral("(%1)\t" ).arg(a: id)); |
616 | } |
617 | return dbg; |
618 | } |
619 | #endif |
620 | |
621 | QBluetoothServiceInfo::Sequence QBluetoothServiceInfoPrivate::protocolDescriptor(QBluetoothUuid::ProtocolUuid protocol) const |
622 | { |
623 | if (!attributes.contains(key: QBluetoothServiceInfo::ProtocolDescriptorList)) |
624 | return QBluetoothServiceInfo::Sequence(); |
625 | |
626 | const QBluetoothServiceInfo::Sequence sequence |
627 | = attributes.value(key: QBluetoothServiceInfo::ProtocolDescriptorList).value<QBluetoothServiceInfo::Sequence>(); |
628 | for (const QVariant &v : sequence) { |
629 | QBluetoothServiceInfo::Sequence parameters = v.value<QBluetoothServiceInfo::Sequence>(); |
630 | if (parameters.empty()) |
631 | continue; |
632 | if (parameters.at(i: 0).userType() == qMetaTypeId<QBluetoothUuid>()) { |
633 | if (parameters.at(i: 0).value<QBluetoothUuid>() == protocol) |
634 | return parameters; |
635 | } |
636 | } |
637 | |
638 | return QBluetoothServiceInfo::Sequence(); |
639 | } |
640 | |
641 | int QBluetoothServiceInfoPrivate::serverChannel() const |
642 | { |
643 | QBluetoothServiceInfo::Sequence parameters = protocolDescriptor(protocol: QBluetoothUuid::ProtocolUuid::Rfcomm); |
644 | |
645 | if (parameters.isEmpty()) |
646 | return -1; |
647 | else if (parameters.size() == 1) |
648 | return 0; |
649 | else |
650 | return parameters.at(i: 1).toUInt(); |
651 | } |
652 | |
653 | QT_END_NAMESPACE |
654 | |