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
45QT_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
161bool 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
181bool 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
200bool 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*/
355QBluetoothServiceInfo::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*/
367QBluetoothServiceInfo::QBluetoothServiceInfo(const QBluetoothServiceInfo &other)
368 : d_ptr(other.d_ptr)
369{
370}
371
372/*!
373 Destroys the QBluetoothServiceInfo object.
374*/
375QBluetoothServiceInfo::~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*/
384bool 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*/
394bool QBluetoothServiceInfo::isComplete() const
395{
396 return d_ptr->attributes.contains(ProtocolDescriptorList);
397}
398
399/*!
400 Returns the address of the Bluetooth device that provides this service.
401*/
402QBluetoothDeviceInfo 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*/
410void 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*/
426void 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*/
434QVariant QBluetoothServiceInfo::attribute(quint16 attributeId) const
435{
436 return d_ptr->attributes.value(attributeId);
437}
438
439/*!
440 Returns a list of all attribute ids that the QBluetoothServiceInfo object has.
441*/
442QList<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*/
451bool QBluetoothServiceInfo::contains(quint16 attributeId) const
452{
453 return d_ptr->attributes.contains(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*/
462void QBluetoothServiceInfo::removeAttribute(quint16 attributeId)
463{
464 d_ptr->attributes.remove(attributeId);
465}
466
467/*!
468 Returns the protocol that the QBluetoothServiceInfo object uses.
469*/
470QBluetoothServiceInfo::Protocol QBluetoothServiceInfo::socketProtocol() const
471{
472 QBluetoothServiceInfo::Sequence parameters = protocolDescriptor(QBluetoothUuid::Rfcomm);
473 if (!parameters.isEmpty())
474 return RfcommProtocol;
475
476 parameters = protocolDescriptor(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*/
491int QBluetoothServiceInfo::protocolServiceMultiplexer() const
492{
493 QBluetoothServiceInfo::Sequence parameters = protocolDescriptor(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(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*/
511int 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*/
521QBluetoothServiceInfo::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*/
535QList<QBluetoothUuid> QBluetoothServiceInfo::serviceClassUuids() const
536{
537 QList<QBluetoothUuid> results;
538
539 const QVariant var = attribute(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(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*/
554QBluetoothServiceInfo &QBluetoothServiceInfo::operator=(const QBluetoothServiceInfo &other)
555{
556 d_ptr = other.d_ptr;
557
558 return *this;
559}
560
561static void dumpAttributeVariant(QDebug dbg, const QVariant &var, const QString& indent)
562{
563 switch (int(var.type())) {
564 case QMetaType::Void:
565 dbg << QString::asprintf("%sEmpty\n", indent.toUtf8().constData());
566 break;
567 case QMetaType::UChar:
568 dbg << QString::asprintf("%suchar %u\n", indent.toUtf8().constData(), var.toUInt());
569 break;
570 case QMetaType::UShort:
571 dbg << QString::asprintf("%sushort %u\n", indent.toUtf8().constData(), var.toUInt());
572 break;
573 case QMetaType::UInt:
574 dbg << QString::asprintf("%suint %u\n", indent.toUtf8().constData(), var.toUInt());
575 break;
576 case QMetaType::Char:
577 dbg << QString::asprintf("%schar %d\n", indent.toUtf8().constData(), var.toInt());
578 break;
579 case QMetaType::Short:
580 dbg << QString::asprintf("%sshort %d\n", indent.toUtf8().constData(), var.toInt());
581 break;
582 case QMetaType::Int:
583 dbg << QString::asprintf("%sint %d\n", indent.toUtf8().constData(), var.toInt());
584 break;
585 case QMetaType::QString:
586 dbg << QString::asprintf("%sstring %s\n", indent.toUtf8().constData(),
587 var.toString().toUtf8().constData());
588 break;
589 case QMetaType::QByteArray:
590 dbg << QString::asprintf("%sbytearray %s\n", indent.toUtf8().constData(),
591 var.toByteArray().toHex().constData());
592 break;
593 case QMetaType::Bool:
594 dbg << QString::asprintf("%sbool %d\n", indent.toUtf8().constData(), var.toBool());
595 break;
596 case QMetaType::QUrl:
597 dbg << QString::asprintf("%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("%suuid NULL\n", indent.toUtf8().constData());
606 break;
607 case 2:
608 dbg << QString::asprintf("%suuid2 %04x\n", indent.toUtf8().constData(),
609 uuid.toUInt16());
610 break;
611 case 4:
612 dbg << QString::asprintf("%suuid %08x\n", indent.toUtf8().constData(),
613 uuid.toUInt32());
614 break;
615 case 16:
616 dbg << QString::asprintf("%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("%suuid ???\n", indent.toUtf8().constData());
622 }
623 } else if (var.userType() == qMetaTypeId<QBluetoothServiceInfo::Sequence>()) {
624 dbg << QString::asprintf("%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, v, indent + QLatin1Char('\t'));
628 } else if (var.userType() == qMetaTypeId<QBluetoothServiceInfo::Alternative>()) {
629 dbg << QString::asprintf("%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, v, indent + QLatin1Char('\t'));
633 }
634 break;
635 default:
636 dbg << QString::asprintf("%sunknown variant type %d\n", indent.toUtf8().constData(),
637 var.userType());
638 }
639}
640
641
642QDebug 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, info.attribute(id), QStringLiteral("(%1)\t").arg(id));
649 }
650 return dbg;
651}
652
653QBluetoothServiceInfo::Sequence QBluetoothServiceInfoPrivate::protocolDescriptor(QBluetoothUuid::ProtocolUuid protocol) const
654{
655 if (!attributes.contains(QBluetoothServiceInfo::ProtocolDescriptorList))
656 return QBluetoothServiceInfo::Sequence();
657
658 const QBluetoothServiceInfo::Sequence sequence
659 = attributes.value(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(0).userType() == qMetaTypeId<QBluetoothUuid>()) {
665 if (parameters.at(0).value<QBluetoothUuid>() == protocol)
666 return parameters;
667 }
668 }
669
670 return QBluetoothServiceInfo::Sequence();
671}
672
673int QBluetoothServiceInfoPrivate::serverChannel() const
674{
675 QBluetoothServiceInfo::Sequence parameters = protocolDescriptor(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(1).toUInt();
683}
684
685QT_END_NAMESPACE
686