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_macos.mm
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
5#include "darwin/btservicerecord_p.h"
9#include "darwin/btutility_p.h"
10
11#include <QtCore/qloggingcategory.h>
12#include <QtCore/qvariant.h>
13#include <QtCore/qglobal.h>
14#include <QtCore/qmutex.h>
15#include <QtCore/qmap.h>
16#include <QtCore/qurl.h>
17
18#include <Foundation/Foundation.h>
19
20#include <IOBluetooth/IOBluetooth.h>
21
23
24namespace {
25
26using DarwinBluetooth::RetainPolicy;
27using ServiceInfo = QBluetoothServiceInfo;
28
29// Alas, since there is no d_ptr<->q_ptr link (which is not that bad in itself),
30// I need these getters duplicated here:
32{
33 ServiceInfo::Sequence parameters = privateInfo.protocolDescriptor(QBluetoothUuid::ProtocolUuid::Rfcomm);
34 if (!parameters.isEmpty())
35 return ServiceInfo::RfcommProtocol;
36
37 parameters = privateInfo.protocolDescriptor(QBluetoothUuid::ProtocolUuid::L2cap);
38 if (!parameters.isEmpty())
39 return ServiceInfo::L2capProtocol;
40
41 return ServiceInfo::UnknownProtocol;
42}
43
44int channel_or_psm(const QBluetoothServiceInfoPrivate &privateInfo, QBluetoothUuid::ProtocolUuid uuid)
45{
46 const auto parameters = privateInfo.protocolDescriptor(uuid);
47 if (parameters.isEmpty())
48 return -1;
49 else if (parameters.size() == 1)
50 return 0;
51
52 return parameters.at(1).toInt();
53}
54
55} // unnamed namespace
56
57QBluetoothServiceInfoPrivate::QBluetoothServiceInfoPrivate()
58{
59}
60
62{
63}
64
65bool QBluetoothServiceInfoPrivate::registerService(const QBluetoothAddress &localAddress)
66{
67 Q_UNUSED(localAddress);
68 return false;
69}
70
71bool QBluetoothServiceInfoPrivate::registerService(const QBluetoothServiceInfo &info)
72{
73 using namespace DarwinBluetooth;
74
76 return false;
77
78 using namespace DarwinBluetooth;
79
80 ObjCStrongReference<NSMutableDictionary> serviceDict(iobluetooth_service_dictionary(info));
81 if (!serviceDict) {
82 qCWarning(QT_BT_DARWIN) << "failed to create a service dictionary";
83 return false;
84 }
85
86 Q_ASSERT(!registered);
87 Q_ASSERT_X(!serviceRecord, Q_FUNC_INFO, "not registered, but serviceRecord is not nil");
88
89 SDPRecord newRecord;
90 newRecord.reset([IOBluetoothSDPServiceRecord
91 publishedServiceRecordWithDictionary:serviceDict], RetainPolicy::doInitialRetain);
92 if (!newRecord) {
93 qCWarning(QT_BT_DARWIN) << "failed to register a service record";
94 return false;
95 }
96
97 BluetoothSDPServiceRecordHandle newRecordHandle = 0;
98 auto *ioSDPRecord = newRecord.getAs<IOBluetoothSDPServiceRecord>();
99 if ([ioSDPRecord getServiceRecordHandle:&newRecordHandle] != kIOReturnSuccess) {
100 qCWarning(QT_BT_DARWIN) << "failed to register a service record";
101 [ioSDPRecord removeServiceRecord];
102 return false;
103 }
104
105 const ServiceInfo::Protocol type = info.socketProtocol();
106 quint16 realPort = 0;
107 QBluetoothServerPrivate *server = nullptr;
108 bool configured = false;
109
110 if (type == QBluetoothServiceInfo::L2capProtocol) {
111 BluetoothL2CAPPSM psm = 0;
112 server = QBluetoothServerPrivate::registeredServer(info.protocolServiceMultiplexer(), type);
113 if ([ioSDPRecord getL2CAPPSM:&psm] == kIOReturnSuccess) {
114 configured = true;
115 realPort = psm;
116 }
117 } else if (type == QBluetoothServiceInfo::RfcommProtocol) {
118 BluetoothRFCOMMChannelID channelID = 0;
119 server = QBluetoothServerPrivate::registeredServer(info.serverChannel(), type);
120 if ([ioSDPRecord getRFCOMMChannelID:&channelID] == kIOReturnSuccess) {
121 configured = true;
122 realPort = channelID;
123 }
124 }
125
126 if (!configured) {
127 [ioSDPRecord removeServiceRecord];
128 qCWarning(QT_BT_DARWIN) << "failed to register a service record";
129 return false;
130 }
131
132 registered = true;
133 serviceRecord.swap(newRecord);
134 serviceRecordHandle = newRecordHandle;
135
136 if (server)
137 server->startListener(realPort);
138
139 return true;
140}
141
142bool QBluetoothServiceInfoPrivate::isRegistered() const
143{
144 return registered;
145}
146
147bool QBluetoothServiceInfoPrivate::unregisterService()
148{
149 if (!registered)
150 return false;
151
152 Q_ASSERT_X(serviceRecord, Q_FUNC_INFO, "service registered, but serviceRecord is nil");
153
154 auto *nativeRecord = serviceRecord.getAs<IOBluetoothSDPServiceRecord>();
155 [nativeRecord removeServiceRecord];
156 serviceRecord.reset();
157
158 const ServiceInfo::Protocol type = socket_protocol(*this);
159 QBluetoothServerPrivate *server = nullptr;
160
161 const QMutexLocker lock(&QBluetoothServerPrivate::channelMapMutex());
162 if (type == ServiceInfo::RfcommProtocol)
163 server = QBluetoothServerPrivate::registeredServer(channel_or_psm(*this, QBluetoothUuid::ProtocolUuid::Rfcomm), type);
164 else if (type == ServiceInfo::L2capProtocol)
165 server = QBluetoothServerPrivate::registeredServer(channel_or_psm(*this, QBluetoothUuid::ProtocolUuid::L2cap), type);
166
167 if (server)
168 server->stopListener();
169
170 registered = false;
171 serviceRecordHandle = 0;
172
173 return true;
174}
175
176QT_END_NAMESPACE
bool registerService(const QBluetoothAddress &localAdapter=QBluetoothAddress())
Combined button and popup list for selecting options.
ServiceInfo::Protocol socket_protocol(const QBluetoothServiceInfoPrivate &privateInfo)
int channel_or_psm(const QBluetoothServiceInfoPrivate &privateInfo, QBluetoothUuid::ProtocolUuid uuid)