1 | // Copyright (C) 2018 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 "qbluetoothsocket.h" |
5 | #include "qbluetoothsocket_bluezdbus_p.h" |
6 | |
7 | #include "bluez/bluez_data_p.h" |
8 | #include "bluez/bluez5_helper_p.h" |
9 | #include "bluez/adapter1_bluez5_p.h" |
10 | #include "bluez/device1_bluez5_p.h" |
11 | #include "bluez/objectmanager_p.h" |
12 | #include "bluez/profile1_p.h" |
13 | #include "bluez/profile1context_p.h" |
14 | #include "bluez/profilemanager1_p.h" |
15 | |
16 | #include <QtBluetooth/qbluetoothdeviceinfo.h> |
17 | #include <QtBluetooth/qbluetoothserviceinfo.h> |
18 | |
19 | #include <QtCore/qloggingcategory.h> |
20 | #include <QtCore/qrandom.h> |
21 | |
22 | #include <QtNetwork/qlocalsocket.h> |
23 | |
24 | #include <unistd.h> |
25 | |
26 | QT_BEGIN_NAMESPACE |
27 | |
28 | using namespace Qt::StringLiterals; |
29 | |
30 | Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ) |
31 | |
32 | QBluetoothSocketPrivateBluezDBus::QBluetoothSocketPrivateBluezDBus() |
33 | { |
34 | secFlags = QBluetooth::Security::NoSecurity; |
35 | |
36 | profileManager = new OrgBluezProfileManager1Interface( |
37 | QStringLiteral("org.bluez" ), |
38 | QStringLiteral("/org/bluez" ), |
39 | QDBusConnection::systemBus(), |
40 | this); |
41 | } |
42 | |
43 | QBluetoothSocketPrivateBluezDBus::~QBluetoothSocketPrivateBluezDBus() |
44 | { |
45 | } |
46 | |
47 | bool QBluetoothSocketPrivateBluezDBus::ensureNativeSocket(QBluetoothServiceInfo::Protocol type) |
48 | { |
49 | switch (type) { |
50 | case QBluetoothServiceInfo::UnknownProtocol: |
51 | break; |
52 | case QBluetoothServiceInfo::RfcommProtocol: |
53 | case QBluetoothServiceInfo::L2capProtocol: |
54 | socketType = type; |
55 | return true; |
56 | } |
57 | |
58 | return false; |
59 | } |
60 | |
61 | void QBluetoothSocketPrivateBluezDBus::connectToServiceHelper( |
62 | const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode) |
63 | { |
64 | // TODO Remove when Bluez4 support dropped |
65 | // Only used by QBluetoothSocketPrivateBluez |
66 | Q_UNUSED(openMode); |
67 | Q_UNUSED(address); |
68 | Q_UNUSED(port); |
69 | } |
70 | |
71 | static QString findRemoteDevicePath(const QBluetoothAddress &address) |
72 | { |
73 | OrgFreedesktopDBusObjectManagerInterface manager(QStringLiteral("org.bluez" ), |
74 | QStringLiteral("/" ), |
75 | QDBusConnection::systemBus()); |
76 | |
77 | bool ok = false; |
78 | const QString adapterPath = findAdapterForAddress(wantedAddress: QBluetoothAddress(), ok: &ok); |
79 | if (!ok) |
80 | return QString(); |
81 | |
82 | auto reply = manager.GetManagedObjects(); |
83 | reply.waitForFinished(); |
84 | if (reply.isError()) |
85 | return QString(); |
86 | |
87 | ManagedObjectList objectList = reply.value(); |
88 | for (ManagedObjectList::const_iterator it = objectList.constBegin(); |
89 | it != objectList.constEnd(); ++it) { |
90 | const QDBusObjectPath &path = it.key(); |
91 | const InterfaceList &ifaceList = it.value(); |
92 | |
93 | for (InterfaceList::const_iterator ifaceIter = ifaceList.constBegin(); |
94 | ifaceIter != ifaceList.constEnd(); ++ifaceIter) { |
95 | if (ifaceIter.key() == QStringLiteral("org.bluez.Device1" )) { |
96 | if (path.path().indexOf(s: adapterPath) != 0) |
97 | continue; // devices whose path does not start with same path we skip |
98 | |
99 | OrgBluezDevice1Interface device(QStringLiteral("org.bluez" ), |
100 | path.path(), QDBusConnection::systemBus()); |
101 | if (device.adapter().path() != adapterPath) |
102 | continue; |
103 | |
104 | const QBluetoothAddress btAddress(device.address()); |
105 | if (btAddress.isNull() || btAddress != address) |
106 | continue; |
107 | |
108 | return path.path(); |
109 | } |
110 | } |
111 | } |
112 | |
113 | return QString(); |
114 | } |
115 | |
116 | void QBluetoothSocketPrivateBluezDBus::connectToServiceHelper( |
117 | const QBluetoothAddress &address, const QBluetoothUuid &uuid, |
118 | QIODevice::OpenMode openMode) |
119 | { |
120 | Q_Q(QBluetoothSocket); |
121 | |
122 | int i = 0; |
123 | bool success = false; |
124 | profileUuid = uuid.toString(mode: QUuid::WithoutBraces); |
125 | |
126 | if (profileContext) { |
127 | qCDebug(QT_BT_BLUEZ) << "Profile context still active. close socket first." ; |
128 | q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError); |
129 | return; |
130 | } |
131 | |
132 | |
133 | profileContext = new OrgBluezProfile1ContextInterface(this); |
134 | connect(sender: profileContext, signal: &OrgBluezProfile1ContextInterface::newConnection, |
135 | context: this, slot: &QBluetoothSocketPrivateBluezDBus::remoteConnected); |
136 | |
137 | for (i = 0; i < 10 && !success; i++) { |
138 | // profile registration might fail in case other service uses same path |
139 | // try 10 times and otherwise abort |
140 | |
141 | profilePath = u"/qt/btsocket/%1%2/%3"_s . |
142 | arg(a: sanitizeNameForDBus(text: QCoreApplication::applicationName())). |
143 | arg(a: QCoreApplication::applicationPid()). |
144 | arg(a: QRandomGenerator::global()->generate()); |
145 | |
146 | success = QDBusConnection::systemBus().registerObject( |
147 | path: profilePath, object: profileContext, options: QDBusConnection::ExportAllSlots); |
148 | } |
149 | |
150 | if (!success) { |
151 | // we could not register the profile |
152 | qCWarning(QT_BT_BLUEZ) << "Cannot export serial client profile on DBus" ; |
153 | |
154 | delete profileContext; |
155 | profileContext = nullptr; |
156 | |
157 | errorString = QBluetoothSocket::tr(s: "Cannot export profile on DBus" ); |
158 | q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError); |
159 | |
160 | return; |
161 | } |
162 | |
163 | QVariantMap profileOptions; |
164 | profileOptions.insert(QStringLiteral("Role" ), QStringLiteral("client" )); |
165 | profileOptions.insert(QStringLiteral("Service" ), value: profileUuid); |
166 | profileOptions.insert(QStringLiteral("Name" ), |
167 | QStringLiteral("QBluetoothSocket-%1" ).arg(a: QCoreApplication::applicationPid())); |
168 | |
169 | // TODO support more profile parameter |
170 | // profileOptions.insert(QStringLiteral("Channel"), 0); |
171 | |
172 | qCDebug(QT_BT_BLUEZ) << "Registering client profile on" << profilePath << "with options:" ; |
173 | qCDebug(QT_BT_BLUEZ) << profileOptions; |
174 | QDBusPendingReply<> reply = profileManager->RegisterProfile( |
175 | profile: QDBusObjectPath(profilePath), |
176 | UUID: profileUuid, |
177 | options: profileOptions); |
178 | reply.waitForFinished(); |
179 | if (reply.isError()) { |
180 | qCWarning(QT_BT_BLUEZ) << "Client profile registration failed:" |
181 | << reply.error().message(); |
182 | |
183 | QDBusConnection::systemBus().unregisterObject(path: profilePath); |
184 | errorString = QBluetoothSocket::tr(s: "Cannot register profile on DBus" ); |
185 | q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError); |
186 | return; |
187 | } |
188 | |
189 | remoteDevicePath = findRemoteDevicePath(address); |
190 | if (remoteDevicePath.isEmpty()) { |
191 | qCWarning(QT_BT_BLUEZ) << "Unknown remote device:" << address |
192 | << "Try device discovery first" ; |
193 | clearSocket(); |
194 | |
195 | errorString = QBluetoothSocket::tr(s: "Cannot find remote device" ); |
196 | q->setSocketError(QBluetoothSocket::SocketError::HostNotFoundError); |
197 | return; |
198 | } |
199 | |
200 | OrgBluezDevice1Interface device(QStringLiteral("org.bluez" ), remoteDevicePath, |
201 | QDBusConnection::systemBus()); |
202 | reply = device.ConnectProfile(UUID: profileUuid); |
203 | QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); |
204 | connect(sender: watcher, signal: &QDBusPendingCallWatcher::finished, |
205 | context: this, slot: &QBluetoothSocketPrivateBluezDBus::connectToServiceReplyHandler); |
206 | |
207 | q->setOpenMode(openMode); |
208 | q->setSocketState(QBluetoothSocket::SocketState::ConnectingState); |
209 | } |
210 | |
211 | void QBluetoothSocketPrivateBluezDBus::connectToServiceReplyHandler( |
212 | QDBusPendingCallWatcher *watcher) |
213 | { |
214 | Q_Q(QBluetoothSocket); |
215 | |
216 | QDBusPendingReply<> reply = *watcher; |
217 | if (reply.isError()) { |
218 | qCWarning(QT_BT_BLUEZ) << "Cannot connect to profile/service." ; |
219 | |
220 | clearSocket(); |
221 | |
222 | errorString = QBluetoothSocket::tr(s: "Cannot connect to remote profile" ); |
223 | q->setSocketError(QBluetoothSocket::SocketError::HostNotFoundError); |
224 | } |
225 | watcher->deleteLater(); |
226 | } |
227 | |
228 | void QBluetoothSocketPrivateBluezDBus::connectToService( |
229 | const QBluetoothServiceInfo &service, QIODevice::OpenMode openMode) |
230 | { |
231 | Q_Q(QBluetoothSocket); |
232 | QBluetoothUuid targetService; |
233 | |
234 | targetService = service.serviceUuid(); |
235 | if (targetService.isNull()) { |
236 | // Do we have serialport service class? |
237 | if (service.serviceClassUuids().contains(t: QBluetoothUuid::ServiceClassUuid::SerialPort)) |
238 | targetService = QBluetoothUuid::ServiceClassUuid::SerialPort; |
239 | } |
240 | |
241 | if (targetService.isNull()) { |
242 | qCWarning(QT_BT_BLUEZ) << "Cannot find appropriate serviceUuid" |
243 | << "or SerialPort service class uuid" ; |
244 | errorString = QBluetoothSocket::tr(s: "Missing serviceUuid or Serial Port service class uuid" ); |
245 | q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError); |
246 | return; |
247 | } |
248 | |
249 | if (service.socketProtocol() != QBluetoothServiceInfo::Protocol::UnknownProtocol) |
250 | socketType = service.socketProtocol(); |
251 | qCDebug(QT_BT_BLUEZ) << "Socket protocol used:" << socketType; |
252 | |
253 | connectToService(address: service.device().address(), uuid: targetService, openMode); |
254 | } |
255 | |
256 | void QBluetoothSocketPrivateBluezDBus::connectToService( |
257 | const QBluetoothAddress &address, const QBluetoothUuid &uuid, QIODevice::OpenMode openMode) |
258 | { |
259 | Q_Q(QBluetoothSocket); |
260 | |
261 | if (address.isNull()) { |
262 | qCWarning(QT_BT_BLUEZ) << "Invalid address to remote address passed." ; |
263 | errorString = QBluetoothSocket::tr(s: "Invalid Bluetooth address passed to connectToService()" ); |
264 | q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError); |
265 | return; |
266 | } |
267 | |
268 | if (uuid.isNull()) { |
269 | qCWarning(QT_BT_BLUEZ) << "Cannot find appropriate serviceUuid" |
270 | << "or SerialPort service class uuid" ; |
271 | errorString = QBluetoothSocket::tr(s: "Missing serviceUuid or Serial Port service class uuid" ); |
272 | q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError); |
273 | return; |
274 | } |
275 | |
276 | if (q->state() != QBluetoothSocket::SocketState::UnconnectedState) { |
277 | qCWarning(QT_BT_BLUEZ) << "QBluetoothSocketPrivateBluezDBus::connectToService called on busy socket" ; |
278 | errorString = QBluetoothSocket::tr(s: "Trying to connect while connection is in progress" ); |
279 | q->setSocketError(QBluetoothSocket::SocketError::OperationError); |
280 | return; |
281 | } |
282 | |
283 | if (q->socketType() == QBluetoothServiceInfo::UnknownProtocol) { |
284 | qCWarning(QT_BT_BLUEZ) << "QBluetoothSocketPrivateBluezDBus::connectToService cannot " |
285 | "connect with 'UnknownProtocol' (type provided by given service)" ; |
286 | errorString = QBluetoothSocket::tr(s: "Socket type not supported" ); |
287 | q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError); |
288 | return; |
289 | } |
290 | |
291 | if (!ensureNativeSocket(type: q->socketType())) { |
292 | errorString = QBluetoothSocket::tr(s: "Socket type not supported" ); |
293 | q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError); |
294 | return; |
295 | } |
296 | connectToServiceHelper(address, uuid, openMode); |
297 | } |
298 | |
299 | void QBluetoothSocketPrivateBluezDBus::connectToService( |
300 | const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode) |
301 | { |
302 | |
303 | Q_UNUSED(port); |
304 | Q_UNUSED(address); |
305 | Q_UNUSED(openMode); |
306 | Q_Q(QBluetoothSocket); |
307 | |
308 | errorString = tr(s: "Connecting to port is not supported via Bluez DBus" ); |
309 | q->setSocketError(QBluetoothSocket::SocketError::ServiceNotFoundError); |
310 | qCWarning(QT_BT_BLUEZ) << "Connecting to port is not supported (Uuid required)" ; |
311 | } |
312 | |
313 | void QBluetoothSocketPrivateBluezDBus::abort() |
314 | { |
315 | if (localSocket) { |
316 | localSocket->close(); |
317 | // delayed disconnected signal emission when localSocket closes |
318 | } else { |
319 | Q_Q(QBluetoothSocket); |
320 | |
321 | clearSocket(); |
322 | q->setOpenMode(QIODevice::NotOpen); |
323 | q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); |
324 | emit q->readChannelFinished(); |
325 | } |
326 | } |
327 | |
328 | QString QBluetoothSocketPrivateBluezDBus::localName() const |
329 | { |
330 | bool ok = false; |
331 | const QString adapterPath = findAdapterForAddress(wantedAddress: QBluetoothAddress(), ok: &ok); |
332 | if (!ok) |
333 | return QString(); |
334 | |
335 | OrgBluezAdapter1Interface adapter(QStringLiteral("org.bluez" ), adapterPath, |
336 | QDBusConnection::systemBus()); |
337 | return QString(adapter.alias()); |
338 | } |
339 | |
340 | QBluetoothAddress QBluetoothSocketPrivateBluezDBus::localAddress() const |
341 | { |
342 | bool ok = false; |
343 | const QString adapterPath = findAdapterForAddress(wantedAddress: QBluetoothAddress(), ok: &ok); |
344 | if (!ok) |
345 | return QBluetoothAddress(); |
346 | |
347 | OrgBluezAdapter1Interface adapter(QStringLiteral("org.bluez" ), adapterPath, |
348 | QDBusConnection::systemBus()); |
349 | return QBluetoothAddress(adapter.address()); |
350 | } |
351 | |
352 | quint16 QBluetoothSocketPrivateBluezDBus::localPort() const |
353 | { |
354 | int descriptor = -1; |
355 | |
356 | if (localSocket) |
357 | descriptor = int(localSocket->socketDescriptor()); |
358 | if (descriptor == -1) |
359 | return 0; |
360 | |
361 | if (socketType == QBluetoothServiceInfo::RfcommProtocol) { |
362 | sockaddr_rc addr; |
363 | socklen_t addrLength = sizeof(addr); |
364 | |
365 | if (::getsockname(fd: descriptor, addr: reinterpret_cast<sockaddr *>(&addr), len: &addrLength) == 0) |
366 | return (addr.rc_channel); |
367 | } else if (socketType == QBluetoothServiceInfo::L2capProtocol) { |
368 | sockaddr_l2 addr; |
369 | socklen_t addrLength = sizeof(addr); |
370 | |
371 | if (::getsockname(fd: descriptor, addr: reinterpret_cast<sockaddr *>(&addr), len: &addrLength) == 0) |
372 | return addr.l2_psm; |
373 | } |
374 | |
375 | return 0; |
376 | } |
377 | |
378 | QString QBluetoothSocketPrivateBluezDBus::peerName() const |
379 | { |
380 | if (remoteDevicePath.isEmpty()) |
381 | return QString(); |
382 | |
383 | OrgBluezDevice1Interface device(QStringLiteral("org.bluez" ), remoteDevicePath, |
384 | QDBusConnection::systemBus()); |
385 | return device.alias(); |
386 | } |
387 | |
388 | QBluetoothAddress QBluetoothSocketPrivateBluezDBus::peerAddress() const |
389 | { |
390 | if (remoteDevicePath.isEmpty()) |
391 | return QBluetoothAddress(); |
392 | |
393 | OrgBluezDevice1Interface device(QStringLiteral("org.bluez" ), remoteDevicePath, |
394 | QDBusConnection::systemBus()); |
395 | return QBluetoothAddress(device.address()); |
396 | } |
397 | |
398 | quint16 QBluetoothSocketPrivateBluezDBus::peerPort() const |
399 | { |
400 | int descriptor = -1; |
401 | |
402 | if (localSocket) |
403 | descriptor = int(localSocket->socketDescriptor()); |
404 | if (descriptor == -1) |
405 | return 0; |
406 | |
407 | if (socketType == QBluetoothServiceInfo::RfcommProtocol) { |
408 | sockaddr_rc addr; |
409 | socklen_t addrLength = sizeof(addr); |
410 | |
411 | if (::getpeername(fd: descriptor, addr: reinterpret_cast<sockaddr *>(&addr), len: &addrLength) == 0) |
412 | return addr.rc_channel; |
413 | } else if (socketType == QBluetoothServiceInfo::L2capProtocol) { |
414 | sockaddr_l2 addr; |
415 | socklen_t addrLength = sizeof(addr); |
416 | |
417 | if (::getpeername(fd: descriptor, addr: reinterpret_cast<sockaddr *>(&addr), len: &addrLength) == 0) |
418 | return addr.l2_psm; |
419 | } |
420 | |
421 | return 0; |
422 | } |
423 | |
424 | qint64 QBluetoothSocketPrivateBluezDBus::writeData(const char *data, qint64 maxSize) |
425 | { |
426 | Q_UNUSED(data); |
427 | Q_UNUSED(maxSize); |
428 | |
429 | Q_Q(QBluetoothSocket); |
430 | |
431 | if (state != QBluetoothSocket::SocketState::ConnectedState) { |
432 | errorString = QBluetoothSocket::tr(s: "Cannot write while not connected" ); |
433 | q->setSocketError(QBluetoothSocket::SocketError::OperationError); |
434 | return -1; |
435 | } |
436 | |
437 | if (localSocket) |
438 | return localSocket->write(data, len: maxSize); |
439 | |
440 | return -1; |
441 | } |
442 | |
443 | qint64 QBluetoothSocketPrivateBluezDBus::readData(char *data, qint64 maxSize) |
444 | { |
445 | Q_UNUSED(data); |
446 | Q_UNUSED(maxSize); |
447 | |
448 | Q_Q(QBluetoothSocket); |
449 | |
450 | if (state != QBluetoothSocket::SocketState::ConnectedState) { |
451 | errorString = QBluetoothSocket::tr(s: "Cannot read while not connected" ); |
452 | q->setSocketError(QBluetoothSocket::SocketError::OperationError); |
453 | return -1; |
454 | } |
455 | |
456 | if (localSocket) |
457 | return localSocket->read(data, maxlen: maxSize); |
458 | |
459 | return -1; |
460 | } |
461 | |
462 | void QBluetoothSocketPrivateBluezDBus::close() |
463 | { |
464 | abort(); |
465 | } |
466 | |
467 | bool QBluetoothSocketPrivateBluezDBus::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType, |
468 | QBluetoothSocket::SocketState socketState, QBluetoothSocket::OpenMode openMode) |
469 | { |
470 | Q_UNUSED(socketDescriptor); |
471 | Q_UNUSED(socketType); |
472 | Q_UNUSED(socketState); |
473 | Q_UNUSED(openMode); |
474 | return false; |
475 | } |
476 | |
477 | qint64 QBluetoothSocketPrivateBluezDBus::bytesAvailable() const |
478 | { |
479 | if (localSocket) |
480 | return localSocket->bytesAvailable(); |
481 | |
482 | return 0; |
483 | } |
484 | |
485 | bool QBluetoothSocketPrivateBluezDBus::canReadLine() const |
486 | { |
487 | if (localSocket) |
488 | return localSocket->canReadLine(); |
489 | |
490 | return false; |
491 | } |
492 | |
493 | qint64 QBluetoothSocketPrivateBluezDBus::bytesToWrite() const |
494 | { |
495 | if (localSocket) |
496 | return localSocket->bytesToWrite(); |
497 | |
498 | return 0; |
499 | } |
500 | |
501 | void QBluetoothSocketPrivateBluezDBus::remoteConnected(const QDBusUnixFileDescriptor &fd) |
502 | { |
503 | Q_Q(QBluetoothSocket); |
504 | |
505 | int descriptor = ::dup(fd: fd.fileDescriptor()); |
506 | localSocket = new QLocalSocket(this); |
507 | bool success = localSocket->setSocketDescriptor( |
508 | socketDescriptor: descriptor, socketState: QLocalSocket::ConnectedState, openMode: q->openMode()); |
509 | if (!success || !localSocket->isValid()) { |
510 | q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); |
511 | delete localSocket; |
512 | localSocket = nullptr; |
513 | } else { |
514 | connect(sender: localSocket, signal: &QLocalSocket::readyRead, |
515 | context: q, slot: &QBluetoothSocket::readyRead); |
516 | connect(sender: localSocket, signal: &QLocalSocket::stateChanged, |
517 | context: this, slot: &QBluetoothSocketPrivateBluezDBus::socketStateChanged); |
518 | connect(sender: localSocket, signal: &QLocalSocket::bytesWritten, |
519 | context: q, slot: &QBluetoothSocket::bytesWritten); |
520 | |
521 | socket = descriptor; |
522 | q->setSocketState(QBluetoothSocket::SocketState::ConnectedState); |
523 | } |
524 | } |
525 | |
526 | void QBluetoothSocketPrivateBluezDBus::socketStateChanged(QLocalSocket::LocalSocketState newState) |
527 | { |
528 | Q_Q(QBluetoothSocket); |
529 | |
530 | switch (newState) { |
531 | case QLocalSocket::ClosingState: |
532 | q->setSocketState(QBluetoothSocket::SocketState::ClosingState); |
533 | break; |
534 | case QLocalSocket::UnconnectedState: |
535 | clearSocket(); |
536 | q->setOpenMode(QIODevice::NotOpen); |
537 | q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState); |
538 | emit q->readChannelFinished(); |
539 | break; |
540 | default: |
541 | // ConnectingState and ConnectedState not mapped |
542 | // (already set at the time when the socket is created) |
543 | break; |
544 | } |
545 | } |
546 | |
547 | void QBluetoothSocketPrivateBluezDBus::clearSocket() |
548 | { |
549 | Q_Q(QBluetoothSocket); |
550 | |
551 | if (profilePath.isEmpty()) |
552 | return; |
553 | |
554 | qCDebug(QT_BT_BLUEZ) << "Clearing profile called for" << profilePath; |
555 | |
556 | if (localSocket) { |
557 | localSocket->close(); |
558 | localSocket->deleteLater(); |
559 | localSocket = nullptr; |
560 | } |
561 | |
562 | socket = -1; |
563 | |
564 | if (q->state() == QBluetoothSocket::SocketState::ConnectedState) { |
565 | OrgBluezDevice1Interface device(QStringLiteral("org.bluez" ), remoteDevicePath, |
566 | QDBusConnection::systemBus()); |
567 | auto reply = device.DisconnectProfile(UUID: profileUuid); |
568 | reply.waitForFinished(); |
569 | if (reply.isError()) { |
570 | qCWarning(QT_BT_BLUEZ) << "Disconnect profile failed:" |
571 | << reply.error().message(); |
572 | } |
573 | } |
574 | |
575 | QDBusPendingReply<> reply = profileManager->UnregisterProfile(profile: QDBusObjectPath(profilePath)); |
576 | reply.waitForFinished(); |
577 | if (reply.isError()) |
578 | qCWarning(QT_BT_BLUEZ) << "Unregister profile:" << reply.error().message(); |
579 | |
580 | QDBusConnection::systemBus().unregisterObject(path: profilePath); |
581 | |
582 | if (profileContext) { |
583 | delete profileContext; |
584 | profileContext = nullptr; |
585 | } |
586 | |
587 | remoteDevicePath.clear(); |
588 | profileUuid.clear(); |
589 | profilePath.clear(); |
590 | } |
591 | QT_END_NAMESPACE |
592 | |
593 | #include "moc_qbluetoothsocket_bluezdbus_p.cpp" |
594 | |