Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qbluetoothserviceinfo.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
7#include <QUrl>
8
10
11QT_IMPL_METATYPE_EXTERN(QBluetoothServiceInfo)
12QT_IMPL_METATYPE_EXTERN_TAGGED(QBluetoothServiceInfo::Sequence, QBluetoothServiceInfo__Sequence)
13QT_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, and the HarmonyOS
120 backend implements RFCOMM only.
121 \value RfcommProtocol The service uses the RFCOMM socket protocol.
122*/
123
124/*!
125 \fn bool QBluetoothServiceInfo::isRegistered() const
126
127 Returns true if the service information is registered with the platform's Service Discovery Protocol
128 (SDP) implementation, otherwise returns false.
129*/
130
131bool QBluetoothServiceInfo::isRegistered() const
132{
133 return d_ptr->isRegistered();
134}
135
136/*!
137 \fn bool QBluetoothServiceInfo::registerService(const QBluetoothAddress &localAdapter)
138
139 Registers this service with the platform's Service Discovery Protocol (SDP) implementation,
140 making it findable by other devices when they perform service discovery. Returns true if the
141 service is successfully registered, otherwise returns false. Once registered changes to the record
142 cannot be made. The service must be unregistered and registered again with the changes.
143
144 The \a localAdapter parameter determines the local Bluetooth adapter under which
145 the service should be registered. If \a localAdapter is \c null the default Bluetooth adapter
146 will be used. If this service info object is already registered via a local adapter
147 and this is function is called using a different local adapter, the previous registration
148 is removed and the service reregistered using the new adapter.
149*/
150
151bool QBluetoothServiceInfo::registerService(const QBluetoothAddress &localAdapter)
152{
153#ifdef QT_OSX_BLUETOOTH
154 Q_UNUSED(localAdapter);
155 return d_ptr->registerService(*this);
156#else
157 return d_ptr->registerService(localAdapter);
158#endif
159}
160
161/*!
162 \fn bool QBluetoothServiceInfo::unregisterService()
163
164 Unregisters this service with the platform's Service Discovery Protocol (SDP) implementation.
165 After this, the service will no longer be findable by other devices through service discovery.
166
167 Returns true if the service is successfully unregistered, otherwise returns false.
168*/
169
170bool QBluetoothServiceInfo::unregisterService()
171{
172 return d_ptr->unregisterService();
173}
174
175
176/*!
177 \fn void QBluetoothServiceInfo::setAttribute(quint16 attributeId, const QBluetoothUuid &value)
178
179 This is a convenience function.
180
181 Sets the attribute identified by \a attributeId to \a value.
182
183 If the service information is already registered with the platform's SDP database,
184 the database entry will not be updated until \l registerService() was called again.
185*/
186
187/*!
188 \fn void QBluetoothServiceInfo::setAttribute(quint16 attributeId, const QBluetoothServiceInfo::Sequence &value)
189
190 This is a convenience function.
191
192 Sets the attribute identified by \a attributeId to \a value.
193
194 If the service information is already registered with the platform's SDP database,
195 the database entry will not be updated until \l registerService() was called again.
196*/
197
198/*!
199 \fn void QBluetoothServiceInfo::setAttribute(quint16 attributeId, const QBluetoothServiceInfo::Alternative &value)
200
201 This is a convenience function.
202
203 Sets the attribute identified by \a attributeId to \a value.
204
205 If the service information is already registered with the platform's SDP database,
206 the database entry will not be updated until \l registerService() was called again.
207*/
208
209/*!
210 \fn void QBluetoothServiceInfo::setServiceName(const QString &name)
211
212 This is a convenience function. It is equivalent to calling
213 setAttribute(QBluetoothServiceInfo::ServiceName, name).
214
215 Sets the service name in the primary language to \a name.
216
217 \sa serviceName(), setAttribute()
218*/
219
220/*!
221 \fn QString QBluetoothServiceInfo::serviceName() const
222
223 This is a convenience function. It is equivalent to calling
224 attribute(QBluetoothServiceInfo::ServiceName).toString().
225
226 Returns the service name in the primary language.
227
228 \sa setServiceName(), attribute()
229*/
230
231/*!
232 \fn void QBluetoothServiceInfo::setServiceDescription(const QString &description)
233
234 This is a convenience function. It is equivalent to calling
235 setAttribute(QBluetoothServiceInfo::ServiceDescription, description).
236
237 Sets the service description in the primary language to \a description.
238
239 \sa serviceDescription(), setAttribute()
240*/
241
242/*!
243 \fn QString QBluetoothServiceInfo::serviceDescription() const
244
245 This is a convenience function. It is equivalent to calling
246 attribute(QBluetoothServiceInfo::ServiceDescription).toString().
247
248 Returns the service description in the primary language.
249
250 \sa setServiceDescription(), attribute()
251*/
252
253/*!
254 \fn void QBluetoothServiceInfo::setServiceProvider(const QString &provider)
255
256 This is a convenience function. It is equivalent to calling
257 setAttribute(QBluetoothServiceInfo::ServiceProvider, provider).
258
259 Sets the service provider in the primary language to \a provider.
260
261 \sa serviceProvider(), setAttribute()
262*/
263
264/*!
265 \fn QString QBluetoothServiceInfo::serviceProvider() const
266
267 This is a convenience function. It is equivalent to calling
268 attribute(QBluetoothServiceInfo::ServiceProvider).toString().
269
270 Returns the service provider in the primary language.
271
272 \sa setServiceProvider(), attribute()
273*/
274
275/*!
276 \fn void QBluetoothServiceInfo::setServiceAvailability(quint8 availability)
277
278 This is a convenience function. It is equivalent to calling
279 setAttribute(QBluetoothServiceInfo::ServiceAvailability, availability).
280
281 Sets the availabiltiy of the service to \a availability.
282
283 \sa serviceAvailability(), setAttribute()
284*/
285
286/*!
287 \fn quint8 QBluetoothServiceInfo::serviceAvailability() const
288
289 This is a convenience function. It is equivalent to calling
290 attribute(QBluetoothServiceInfo::ServiceAvailability).toUInt().
291
292 Returns the availability of the service.
293
294 \sa setServiceAvailability(), attribute()
295*/
296
297/*!
298 \fn void QBluetoothServiceInfo::setServiceUuid(const QBluetoothUuid &uuid)
299
300 This is a convenience function. It is equivalent to calling
301 setAttribute(QBluetoothServiceInfo::ServiceId, uuid).
302
303 Sets the custom service UUID to \a uuid. This function should not be used
304 to set a standardized service UUID.
305
306 \sa serviceUuid(), setAttribute()
307*/
308
309/*!
310 \fn QBluetoothUuid QBluetoothServiceInfo::serviceUuid() const
311
312 This is a convenience function. It is equivalent to calling
313 attribute(QBluetoothServiceInfo::ServiceId).value<QBluetoothUuid>().
314
315 Returns the custom UUID of the service. This UUID may be null.
316 UUIDs based on \l{https://bluetooth.org}{Bluetooth SIG standards}
317 should be retrieved via \l serviceClassUuids().
318
319 \sa setServiceUuid(), attribute()
320*/
321
322/*!
323 Construct a new invalid QBluetoothServiceInfo;
324*/
325QBluetoothServiceInfo::QBluetoothServiceInfo()
326 : d_ptr(QSharedPointer<QBluetoothServiceInfoPrivate>::create())
327{
328 qRegisterMetaType<QBluetoothServiceInfo>();
329}
330
331/*!
332 Construct a new QBluetoothServiceInfo that is a copy of \a other.
333
334 The two copies continue to share the same underlying data which does not detach
335 upon write.
336*/
337QBluetoothServiceInfo::QBluetoothServiceInfo(const QBluetoothServiceInfo &other)
338 : d_ptr(other.d_ptr)
339{
340}
341
342/*!
343 Destroys the QBluetoothServiceInfo object.
344*/
345QBluetoothServiceInfo::~QBluetoothServiceInfo()
346{
347}
348
349/*!
350 Returns true if the QBluetoothServiceInfo object is valid, otherwise returns false.
351
352 An invalid QBluetoothServiceInfo object will have no attributes.
353*/
354bool QBluetoothServiceInfo::isValid() const
355{
356 return !d_ptr->attributes.isEmpty();
357}
358
359/*!
360 Returns true if the QBluetoothServiceInfo object is considered complete, otherwise returns false.
361
362 A complete QBluetoothServiceInfo object contains a ProtocolDescriptorList attribute.
363*/
364bool QBluetoothServiceInfo::isComplete() const
365{
366 return d_ptr->attributes.contains(ProtocolDescriptorList);
367}
368
369/*!
370 Returns the address of the Bluetooth device that provides this service.
371*/
372QBluetoothDeviceInfo QBluetoothServiceInfo::device() const
373{
374 return d_ptr->deviceInfo;
375}
376
377/*!
378 Sets the Bluetooth device that provides this service to \a device.
379*/
380void QBluetoothServiceInfo::setDevice(const QBluetoothDeviceInfo &device)
381{
382 d_ptr->deviceInfo = device;
383}
384
385/*!
386 Sets the attribute identified by \a attributeId to \a value.
387
388 If the service information is already registered with the platform's SDP database,
389 the database entry will not be updated until \l registerService() was called again.
390
391 \note If an attribute expectes a byte-encoded value (e.g. Bluetooth HID services),
392 it should be set as QByteArray.
393
394 \sa isRegistered(), registerService()
395*/
396void QBluetoothServiceInfo::setAttribute(quint16 attributeId, const QVariant &value)
397{
398 d_ptr->attributes[attributeId] = value;
399}
400
401/*!
402 Returns the value of the attribute \a attributeId.
403*/
404QVariant QBluetoothServiceInfo::attribute(quint16 attributeId) const
405{
406 return d_ptr->attributes.value(attributeId);
407}
408
409/*!
410 Returns a list of all attribute ids that the QBluetoothServiceInfo object has.
411*/
412QList<quint16> QBluetoothServiceInfo::attributes() const
413{
414 return d_ptr->attributes.keys();
415}
416
417/*!
418 Returns true if the QBluetoothServiceInfo object contains the attribute \a attributeId, otherwise returns
419 false.
420*/
421bool QBluetoothServiceInfo::contains(quint16 attributeId) const
422{
423 return d_ptr->attributes.contains(attributeId);
424}
425
426/*!
427 Removes the attribute \a attributeId from the QBluetoothServiceInfo object.
428
429 If the service information is already registered with the platforms SDP database,
430 the database entry will not be updated until \l registerService() was called again.
431*/
432void QBluetoothServiceInfo::removeAttribute(quint16 attributeId)
433{
434 d_ptr->attributes.remove(attributeId);
435}
436
437/*!
438 Returns the protocol that the QBluetoothServiceInfo object uses.
439*/
440QBluetoothServiceInfo::Protocol QBluetoothServiceInfo::socketProtocol() const
441{
442 QBluetoothServiceInfo::Sequence parameters = protocolDescriptor(QBluetoothUuid::ProtocolUuid::Rfcomm);
443 if (!parameters.isEmpty())
444 return RfcommProtocol;
445
446 parameters = protocolDescriptor(QBluetoothUuid::ProtocolUuid::L2cap);
447 if (!parameters.isEmpty())
448 return L2capProtocol;
449
450 return UnknownProtocol;
451}
452
453/*!
454 This is a convenience function. Returns the protocol/service multiplexer for services which
455 support the L2CAP protocol, otherwise returns -1.
456
457 This function is equivalent to extracting the information from
458 QBluetoothServiceInfo::Sequence returned by
459 QBluetoothServiceInfo::attribute(QBluetoothServiceInfo::ProtocolDescriptorList).
460*/
461int QBluetoothServiceInfo::protocolServiceMultiplexer() const
462{
463 QBluetoothServiceInfo::Sequence parameters = protocolDescriptor(QBluetoothUuid::ProtocolUuid::L2cap);
464
465 if (parameters.isEmpty())
466 return -1;
467 else if (parameters.size() == 1)
468 return 0;
469 else
470 return parameters.at(1).toUInt();
471}
472
473/*!
474 This is a convenience function. Returns the server channel for services which support the
475 RFCOMM protocol, otherwise returns -1.
476
477 This function is equivalent to extracting the information from
478 QBluetoothServiceInfo::Sequence returned by
479 QBluetoothServiceInfo::attribute(QBluetootherServiceInfo::ProtocolDescriptorList).
480*/
481int QBluetoothServiceInfo::serverChannel() const
482{
483 return d_ptr->serverChannel();
484}
485
486/*!
487 Returns the protocol parameters as a QBluetoothServiceInfo::Sequence for protocol \a protocol.
488
489 An empty QBluetoothServiceInfo::Sequence is returned if \a protocol is not supported.
490*/
491QBluetoothServiceInfo::Sequence QBluetoothServiceInfo::protocolDescriptor(QBluetoothUuid::ProtocolUuid protocol) const
492{
493 return d_ptr->protocolDescriptor(protocol);
494}
495
496/*!
497 Returns a list of UUIDs describing the service classes that this service conforms to.
498
499 This is a convenience function. It is equivalent to calling
500 attribute(QBluetoothServiceInfo::ServiceClassIds).value<QBluetoothServiceInfo::Sequence>()
501 and subsequently iterating over its QBluetoothUuid entries.
502
503 \sa attribute()
504*/
505QList<QBluetoothUuid> QBluetoothServiceInfo::serviceClassUuids() const
506{
507 QList<QBluetoothUuid> results;
508
509 const QVariant var = attribute(QBluetoothServiceInfo::ServiceClassIds);
510 if (!var.isValid())
511 return results;
512
513 const QBluetoothServiceInfo::Sequence seq = var.value<QBluetoothServiceInfo::Sequence>();
514 for (qsizetype i = 0; i < seq.size(); ++i)
515 results.append(seq.at(i).value<QBluetoothUuid>());
516
517 return results;
518}
519
520/*!
521 Makes a copy of the \a other and assigns it to this QBluetoothServiceInfo object.
522 The two copies continue to share the same service and registration details.
523*/
524QBluetoothServiceInfo &QBluetoothServiceInfo::operator=(const QBluetoothServiceInfo &other)
525{
526 d_ptr = other.d_ptr;
527
528 return *this;
529}
530
531#ifndef QT_NO_DEBUG_STREAM
532static void dumpAttributeVariant(QDebug dbg, const QVariant &var, const QString& indent)
533{
534 switch (var.typeId()) {
535 case QMetaType::Void:
536 dbg << QString::asprintf("%sEmpty\n", indent.toUtf8().constData());
537 break;
538 case QMetaType::UChar:
539 dbg << QString::asprintf("%suchar %u\n", indent.toUtf8().constData(), var.toUInt());
540 break;
541 case QMetaType::UShort:
542 dbg << QString::asprintf("%sushort %u\n", indent.toUtf8().constData(), var.toUInt());
543 break;
544 case QMetaType::UInt:
545 dbg << QString::asprintf("%suint %u\n", indent.toUtf8().constData(), var.toUInt());
546 break;
547 case QMetaType::Char:
548 dbg << QString::asprintf("%schar %d\n", indent.toUtf8().constData(), var.toInt());
549 break;
550 case QMetaType::Short:
551 dbg << QString::asprintf("%sshort %d\n", indent.toUtf8().constData(), var.toInt());
552 break;
553 case QMetaType::Int:
554 dbg << QString::asprintf("%sint %d\n", indent.toUtf8().constData(), var.toInt());
555 break;
556 case QMetaType::QString:
557 dbg << QString::asprintf("%sstring %s\n", indent.toUtf8().constData(),
558 var.toString().toUtf8().constData());
559 break;
560 case QMetaType::QByteArray:
561 dbg << QString::asprintf("%sbytearray %s\n", indent.toUtf8().constData(),
562 var.toByteArray().toHex().constData());
563 break;
564 case QMetaType::Bool:
565 dbg << QString::asprintf("%sbool %d\n", indent.toUtf8().constData(), var.toBool());
566 break;
567 case QMetaType::QUrl:
568 dbg << QString::asprintf("%surl %s\n", indent.toUtf8().constData(),
569 var.toUrl().toString().toUtf8().constData());
570 break;
571 default:
572 if (var.typeId() == qMetaTypeId<QBluetoothUuid>()) {
573 QBluetoothUuid uuid = var.value<QBluetoothUuid>();
574 switch (uuid.minimumSize()) {
575 case 0:
576 dbg << QString::asprintf("%suuid NULL\n", indent.toUtf8().constData());
577 break;
578 case 2:
579 dbg << QString::asprintf("%suuid2 %04x\n", indent.toUtf8().constData(),
580 uuid.toUInt16());
581 break;
582 case 4:
583 dbg << QString::asprintf("%suuid %08x\n", indent.toUtf8().constData(),
584 uuid.toUInt32());
585 break;
586 case 16:
587 dbg << QString::asprintf("%suuid %s\n",
588 indent.toUtf8().constData(),
589 uuid.toByteArray(QUuid::Id128).constData());
590 break;
591 default:
592 dbg << QString::asprintf("%suuid ???\n", indent.toUtf8().constData());
593 }
594 } else if (var.typeId() == qMetaTypeId<QBluetoothServiceInfo::Sequence>()) {
595 dbg << QString::asprintf("%sSequence\n", indent.toUtf8().constData());
596 const QBluetoothServiceInfo::Sequence *sequence = static_cast<const QBluetoothServiceInfo::Sequence *>(var.data());
597 for (const QVariant &v : *sequence)
598 dumpAttributeVariant(dbg, v, indent + QLatin1Char('\t'));
599 } else if (var.typeId() == qMetaTypeId<QBluetoothServiceInfo::Alternative>()) {
600 dbg << QString::asprintf("%sAlternative\n", indent.toUtf8().constData());
601 const QBluetoothServiceInfo::Alternative *alternative = static_cast<const QBluetoothServiceInfo::Alternative *>(var.data());
602 for (const QVariant &v : *alternative)
603 dumpAttributeVariant(dbg, v, indent + QLatin1Char('\t'));
604 } else {
605 dbg << QString::asprintf("%sunknown variant type %d\n", indent.toUtf8().constData(), var.typeId());
606 }
607 }
608}
609
610QDebug QBluetoothServiceInfo::streamingOperator(QDebug dbg, const QBluetoothServiceInfo &info)
611{
612 QDebugStateSaver saver(dbg);
613 dbg.noquote() << "\n";
614 const QList<quint16> attributes = info.attributes();
615 for (quint16 id : attributes) {
616 dumpAttributeVariant(dbg, info.attribute(id), QStringLiteral("(%1)\t").arg(id));
617 }
618 return dbg;
619}
620#endif // QT_NO_DEBUG_STREAM
621
623{
624 if (!attributes.contains(QBluetoothServiceInfo::ProtocolDescriptorList))
625 return QBluetoothServiceInfo::Sequence();
626
627 const QBluetoothServiceInfo::Sequence sequence
628 = attributes.value(QBluetoothServiceInfo::ProtocolDescriptorList).value<QBluetoothServiceInfo::Sequence>();
629 for (const QVariant &v : sequence) {
630 QBluetoothServiceInfo::Sequence parameters = v.value<QBluetoothServiceInfo::Sequence>();
631 if (parameters.empty())
632 continue;
633 if (parameters.at(0).userType() == qMetaTypeId<QBluetoothUuid>()) {
634 if (parameters.at(0).value<QBluetoothUuid>() == protocol)
635 return parameters;
636 }
637 }
638
639 return QBluetoothServiceInfo::Sequence();
640}
641
643{
644 QBluetoothServiceInfo::Sequence parameters = protocolDescriptor(QBluetoothUuid::ProtocolUuid::Rfcomm);
645
646 if (parameters.isEmpty())
647 return -1;
648 else if (parameters.size() == 1)
649 return 0;
650 else
651 return parameters.at(1).toUInt();
652}
653
654QT_END_NAMESPACE
QBluetoothServiceInfo::Sequence protocolDescriptor(QBluetoothUuid::ProtocolUuid protocol) const
Combined button and popup list for selecting options.
static void dumpAttributeVariant(QDebug dbg, const QVariant &var, const QString &indent)