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