1/****************************************************************************
2**
3** Copyright (C) 2018 The Qt Company Ltd.
4** Copyright (C) 2016 BlackBerry Limited. All rights reserved.
5** Contact: https://www.qt.io/licensing/
6**
7** This file is part of the QtBluetooth module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial License Usage
11** Licensees holding valid commercial Qt licenses may use this file in
12** accordance with the commercial license agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and The Qt Company. For licensing terms
15** and conditions see https://www.qt.io/terms-conditions. For further
16** information use the contact form at https://www.qt.io/contact-us.
17**
18** GNU Lesser General Public License Usage
19** Alternatively, this file may be used under the terms of the GNU Lesser
20** General Public License version 3 as published by the Free Software
21** Foundation and appearing in the file LICENSE.LGPL3 included in the
22** packaging of this file. Please review the following information to
23** ensure the GNU Lesser General Public License version 3 requirements
24** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25**
26** GNU General Public License Usage
27** Alternatively, this file may be used under the terms of the GNU
28** General Public License version 2.0 or (at your option) the GNU General
29** Public license version 3 or any later version approved by the KDE Free
30** Qt Foundation. The licenses are as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32** included in the packaging of this file. Please review the following
33** information to ensure the GNU General Public License requirements will
34** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35** https://www.gnu.org/licenses/gpl-3.0.html.
36**
37** $QT_END_LICENSE$
38**
39****************************************************************************/
40
41#include "qbluetoothsocket.h"
42#if QT_CONFIG(bluez)
43#include "qbluetoothsocket_bluez_p.h"
44#include "qbluetoothsocket_bluezdbus_p.h"
45#include "bluez/bluez5_helper_p.h"
46#elif defined(QT_ANDROID_BLUETOOTH)
47#include "qbluetoothsocket_android_p.h"
48#elif defined(QT_WINRT_BLUETOOTH)
49#include "qbluetoothsocket_winrt_p.h"
50#elif defined(QT_WIN_BLUETOOTH)
51#include "qbluetoothsocket_win_p.h"
52#elif defined(QT_OSX_BLUETOOTH)
53#include "qbluetoothsocket_osx_p.h"
54#else
55#include "qbluetoothsocket_dummy_p.h"
56#endif
57
58#include "qbluetoothservicediscoveryagent.h"
59
60#include <QtCore/QLoggingCategory>
61#include <QSocketNotifier>
62
63QT_BEGIN_NAMESPACE
64
65Q_DECLARE_LOGGING_CATEGORY(QT_BT)
66
67/*!
68 \class QBluetoothSocket
69 \inmodule QtBluetooth
70 \brief The QBluetoothSocket class enables connection to a Bluetooth device
71 running a bluetooth server.
72
73 \since 5.2
74
75 QBluetoothSocket supports two socket types, \l {QBluetoothServiceInfo::L2capProtocol}{L2CAP} and
76 \l {QBluetoothServiceInfo::RfcommProtocol}{RFCOMM}.
77
78 \l {QBluetoothServiceInfo::L2capProtocol}{L2CAP} is a low level datagram-oriented Bluetooth socket.
79 Android does not support \l {QBluetoothServiceInfo::L2capProtocol}{L2CAP} for socket
80 connections.
81
82 \l {QBluetoothServiceInfo::RfcommProtocol}{RFCOMM} is a reliable, stream-oriented socket. RFCOMM
83 sockets emulate an RS-232 serial port.
84
85 To create a connection to a Bluetooth service, create a socket of the appropriate type and call
86 connectToService() passing the Bluetooth address and port number. QBluetoothSocket will emit
87 the connected() signal when the connection is established.
88
89 If the \l {QBluetoothServiceInfo::Protocol}{Protocol} is not supported on a platform, calling
90 \l connectToService() will emit a \l {QBluetoothSocket::UnsupportedProtocolError}{UnsupportedProtocolError} error.
91
92 \note QBluetoothSocket does not support synchronous read and write operations. Functions such
93 as \l waitForReadyRead() and \l waitForBytesWritten() are not implemented. I/O operations should be
94 performed using \l readyRead(), \l read() and \l write().
95
96 On iOS, this class cannot be used because the platform does not expose
97 an API which may permit access to QBluetoothSocket related features.
98
99 \note On macOS Monterey (12) the socket data flow is paused when a
100 modal dialogue is executing, or an event tracking mode is entered (for
101 example by long-pressing a Window close button). This may change in the
102 future releases of macOS.
103*/
104
105/*!
106 \enum QBluetoothSocket::SocketState
107
108 This enum describes the state of the Bluetooth socket.
109
110 \value UnconnectedState Socket is not connected.
111 \value ServiceLookupState Socket is querying connection parameters.
112 \value ConnectingState Socket is attempting to connect to a device.
113 \value ConnectedState Socket is connected to a device.
114 \value BoundState Socket is bound to a local address and port.
115 \value ClosingState Socket is connected and will be closed once all pending data is
116 written to the socket.
117 \value ListeningState Socket is listening for incoming connections.
118*/
119
120/*!
121 \enum QBluetoothSocket::SocketError
122
123 This enum describes Bluetooth socket error types.
124
125 \value UnknownSocketError An unknown error has occurred.
126 \value NoSocketError No error. Used for testing.
127 \value HostNotFoundError Could not find the remote host.
128 \value ServiceNotFoundError Could not find the service UUID on remote host.
129 \value NetworkError Attempt to read or write from socket returned an error
130 \value UnsupportedProtocolError The \l {QBluetoothServiceInfo::Protocol}{Protocol} is not
131 supported on this platform.
132 \value OperationError An operation was attempted while the socket was in a state
133 that did not permit it.
134 \value RemoteHostClosedError The remote host closed the connection. This value was
135 introduced by Qt 5.10.
136*/
137
138/*!
139 \fn void QBluetoothSocket::connected()
140
141 This signal is emitted when a connection is established.
142
143 \sa QBluetoothSocket::ConnectedState, stateChanged()
144*/
145
146/*!
147 \fn void QBluetoothSocket::disconnected()
148
149 This signal is emitted when the socket is disconnected.
150
151 \sa QBluetoothSocket::UnconnectedState, stateChanged()
152*/
153
154/*!
155 \fn void QBluetoothSocket::error(QBluetoothSocket::SocketError error)
156
157 This signal is emitted when an \a error occurs.
158
159 \sa error()
160*/
161
162/*!
163 \fn QBluetoothSocket::stateChanged(QBluetoothSocket::SocketState state)
164
165 This signal is emitted when the socket state changes to \a state.
166
167 \sa connected(), disconnected(), state(), QBluetoothSocket::SocketState
168*/
169
170/*!
171 \fn void QBluetoothSocket::abort()
172
173 Aborts the current connection and resets the socket. Unlike disconnectFromService(), this
174 function immediately closes the socket, discarding any pending data in the write buffer.
175
176 \note On Android, aborting the socket requires asynchronous interaction with Android threads.
177 Therefore the associated \l disconnected() and \l stateChanged() signals are delayed
178 until the threads have finished the closure.
179
180 \sa disconnectFromService(), close()
181*/
182
183/*!
184 \fn void QBluetoothSocket::close()
185
186 Disconnects the socket's connection with the device.
187
188 \note On Android, closing the socket requires asynchronous interaction with Android threads.
189 Therefore the associated \l disconnected() and \l stateChanged() signals are delayed
190 until the threads have finished the closure.
191
192*/
193
194/*!
195 \fn void QBluetoothSocket::disconnectFromService()
196
197 Attempts to close the socket. If there is pending data waiting to be written QBluetoothSocket
198 will enter ClosingState and wait until all data has been written. Eventually, it will enter
199 UnconnectedState and emit the disconnected() signal.
200
201 \sa connectToService()
202*/
203
204/*!
205 \fn QString QBluetoothSocket::localName() const
206
207 Returns the name of the local device.
208
209 Although some platforms may differ the socket must generally be connected to guarantee
210 the return of a valid name. In particular, this is true when dealing with platforms
211 that support multiple local Bluetooth adapters.
212*/
213
214/*!
215 \fn QBluetoothAddress QBluetoothSocket::localAddress() const
216
217 Returns the address of the local device.
218
219 Although some platforms may differ the socket must generally be connected to guarantee
220 the return of a valid address. In particular, this is true when dealing with platforms
221 that support multiple local Bluetooth adapters.
222*/
223
224/*!
225 \fn quint16 QBluetoothSocket::localPort() const
226
227 Returns the port number of the local socket if available, otherwise returns 0.
228 Although some platforms may differ the socket must generally be connected to guarantee
229 the return of a valid port number.
230
231 On Android and \macos, this feature is not supported and returns 0.
232*/
233
234/*!
235 \fn QString QBluetoothSocket::peerName() const
236
237 Returns the name of the peer device.
238*/
239
240/*!
241 \fn QBluetoothAddress QBluetoothSocket::peerAddress() const
242
243 Returns the address of the peer device.
244*/
245
246/*!
247 \fn quint16 QBluetoothSocket::peerPort() const
248
249 Return the port number of the peer socket if available, otherwise returns 0.
250 On Android, this feature is not supported.
251*/
252
253/*!
254 \fn qint64 QBluetoothSocket::readData(char *data, qint64 maxSize)
255
256 \reimp
257*/
258
259/*!
260 \fn qint64 QBluetoothSocket::writeData(const char *data, qint64 maxSize)
261
262 \reimp
263*/
264
265static QBluetoothSocketBasePrivate *createSocketPrivate()
266{
267#if QT_CONFIG(bluez)
268 if (bluetoothdVersion() >= QVersionNumber(5, 46)) {
269 qCDebug(QT_BT) << "Using Bluetooth dbus socket implementation";
270 return new QBluetoothSocketPrivateBluezDBus();
271 } else {
272 qCDebug(QT_BT) << "Using Bluetooth raw socket implementation";
273 return new QBluetoothSocketPrivateBluez();
274 }
275#elif defined(QT_ANDROID_BLUETOOTH)
276 return new QBluetoothSocketPrivateAndroid();
277#elif defined(QT_WINRT_BLUETOOTH)
278 return new QBluetoothSocketPrivateWinRT();
279#elif defined(QT_WIN_BLUETOOTH)
280 return new QBluetoothSocketPrivateWin();
281#elif defined(QT_OSX_BLUETOOTH)
282 return new QBluetoothSocketPrivate();
283#else
284 return new QBluetoothSocketPrivateDummy();
285#endif
286}
287
288/*!
289 Constructs a Bluetooth socket of \a socketType type, with \a parent.
290*/
291QBluetoothSocket::QBluetoothSocket(QBluetoothServiceInfo::Protocol socketType, QObject *parent)
292: QIODevice(parent)
293{
294 d_ptr = createSocketPrivate();
295 d_ptr->q_ptr = this;
296
297 Q_D(QBluetoothSocketBase);
298 d->ensureNativeSocket(type: socketType);
299
300 setOpenMode(QIODevice::NotOpen);
301}
302
303/*!
304 Constructs a Bluetooth socket with \a parent.
305*/
306QBluetoothSocket::QBluetoothSocket(QObject *parent)
307 : QIODevice(parent)
308{
309 d_ptr = createSocketPrivate();
310 d_ptr->q_ptr = this;
311 setOpenMode(QIODevice::NotOpen);
312}
313
314#if QT_CONFIG(bluez)
315
316/*!
317 \internal
318*/
319QBluetoothSocket::QBluetoothSocket(QBluetoothSocketBasePrivate *dPrivate,
320 QBluetoothServiceInfo::Protocol socketType,
321 QObject *parent)
322 : QIODevice(parent)
323{
324 d_ptr = dPrivate;
325 d_ptr->q_ptr = this;
326
327 Q_D(QBluetoothSocketBase);
328 d->ensureNativeSocket(socketType);
329
330 setOpenMode(QIODevice::NotOpen);
331}
332
333#endif
334
335/*!
336 Destroys the Bluetooth socket.
337*/
338QBluetoothSocket::~QBluetoothSocket()
339{
340 delete d_ptr;
341 d_ptr = nullptr;
342}
343
344/*!
345 \reimp
346*/
347bool QBluetoothSocket::isSequential() const
348{
349 return true;
350}
351
352/*!
353 Returns the number of incoming bytes that are waiting to be read.
354
355 \sa bytesToWrite(), read()
356*/
357qint64 QBluetoothSocket::bytesAvailable() const
358{
359 Q_D(const QBluetoothSocketBase);
360 return QIODevice::bytesAvailable() + d->bytesAvailable();
361}
362
363/*!
364 Returns the number of bytes that are waiting to be written. The bytes are written when control
365 goes back to the event loop.
366*/
367qint64 QBluetoothSocket::bytesToWrite() const
368{
369 Q_D(const QBluetoothSocketBase);
370 return d->bytesToWrite();
371}
372
373/*!
374 Attempts to connect to the service described by \a service.
375
376 The socket is opened in the given \a openMode. The \l socketType() is ignored
377 if \a service specifies a differing \l QBluetoothServiceInfo::socketProtocol().
378
379 The socket first enters ConnectingState and attempts to connect to the device providing
380 \a service. If a connection is established, QBluetoothSocket enters ConnectedState and
381 emits connected().
382
383 At any point, the socket can emit error() to signal that an error occurred.
384
385 Note that most platforms require a pairing prior to connecting to the remote device. Otherwise
386 the connection process may fail.
387
388 On Android, only RFCOMM connections are possible. This function ignores any socket protocol indicator
389 and assumes RFCOMM.
390
391 \sa state(), disconnectFromService()
392*/
393void QBluetoothSocket::connectToService(const QBluetoothServiceInfo &service, OpenMode openMode)
394{
395 Q_D(QBluetoothSocketBase);
396 d->connectToService(service, openMode);
397}
398
399/*!
400 \fn void QBluetoothSocket::connectToService(const QBluetoothAddress &address, QBluetoothUuid::ServiceClassUuid uuid, OpenMode mode = ReadWrite)
401
402 \internal
403
404 Exists to avoid QTBUG-65831.
405*/
406
407/*!
408 Attempts to make a connection to the service identified by \a uuid on the device with address
409 \a address.
410
411 The socket is opened in the given \a openMode.
412
413 For BlueZ, the socket first enters the \l ServiceLookupState and queries the connection parameters for
414 \a uuid. If the service parameters are successfully retrieved the socket enters
415 ConnectingState, and attempts to connect to \a address. If a connection is established,
416 QBluetoothSocket enters \l ConnectedState and emits connected().
417
418 On Android, the service connection can directly be established
419 using the UUID of the remote service. Therefore the platform does not require
420 the \l ServiceLookupState and \l socketType() is always set to
421 \l QBluetoothServiceInfo::RfcommProtocol.
422
423 At any point, the socket can emit error() to signal that an error occurred.
424
425 Note that most platforms require a pairing prior to connecting to the remote device. Otherwise
426 the connection process may fail.
427
428 \sa state(), disconnectFromService()
429*/
430void QBluetoothSocket::connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid, OpenMode openMode)
431{
432 Q_D(QBluetoothSocketBase);
433 d->connectToService(address, uuid, openMode);
434}
435
436/*!
437 Attempts to make a connection with \a address on the given \a port.
438
439 The socket is opened in the given \a openMode.
440
441 The socket first enters ConnectingState, and attempts to connect to \a address. If a
442 connection is established, QBluetoothSocket enters ConnectedState and emits connected().
443
444 At any point, the socket can emit error() to signal that an error occurred.
445
446 On Android and BlueZ (version 5.46 or above), a connection to a service can not be established using a port.
447 Calling this function will emit a \l {QBluetoothSocket::ServiceNotFoundError}{ServiceNotFoundError}.
448
449 Note that most platforms require a pairing prior to connecting to the remote device. Otherwise
450 the connection process may fail.
451
452 \sa state(), disconnectFromService()
453*/
454void QBluetoothSocket::connectToService(const QBluetoothAddress &address, quint16 port, OpenMode openMode)
455{
456 Q_D(QBluetoothSocketBase);
457 d->connectToService(address, port, openMode);
458}
459
460/*!
461 Returns the socket type. The socket automatically adjusts to the protocol
462 offered by the remote service.
463
464 Android only support \l{QBluetoothServiceInfo::RfcommProtocol}{RFCOMM}
465 based sockets.
466*/
467QBluetoothServiceInfo::Protocol QBluetoothSocket::socketType() const
468{
469 Q_D(const QBluetoothSocketBase);
470 return d->socketType;
471}
472
473/*!
474 Returns the current state of the socket.
475*/
476QBluetoothSocket::SocketState QBluetoothSocket::state() const
477{
478 Q_D(const QBluetoothSocketBase);
479 return d->state;
480}
481
482/*!
483 Returns the last error.
484*/
485QBluetoothSocket::SocketError QBluetoothSocket::error() const
486{
487 Q_D(const QBluetoothSocketBase);
488 return d->socketError;
489}
490
491/*!
492 Returns a user displayable text string for the error.
493 */
494QString QBluetoothSocket::errorString() const
495{
496 Q_D(const QBluetoothSocketBase);
497 return d->errorString;
498}
499
500/*!
501 Sets the preferred security parameter for the connection attempt to
502 \a flags. This value is incorporated when calling \l connectToService().
503 Therefore it is required to reconnect to change this parameter for an
504 existing connection.
505
506 On Bluez this property is set to QBluetooth::Authorization by default.
507
508 On \macos, this value is ignored as the platform does not permit access
509 to the security parameter of the socket. By default the platform prefers
510 secure/encrypted connections though and therefore this function always
511 returns \l QBluetooth::Secure.
512
513 Android only supports two levels of security (secure and non-secure). If this flag is set to
514 \l QBluetooth::NoSecurity the socket object will not employ any authentication or encryption.
515 Any other security flag combination will trigger a secure Bluetooth connection.
516 This flag is set to \l QBluetooth::Secure by default.
517
518 \note A secure connection requires a pairing between the two devices. On
519 some platforms, the pairing is automatically initiated during the establishment
520 of the connection. Other platforms require the application to manually trigger
521 the pairing before attempting to connect.
522
523 \sa preferredSecurityFlags()
524
525 \since 5.6
526*/
527void QBluetoothSocket::setPreferredSecurityFlags(QBluetooth::SecurityFlags flags)
528{
529#ifdef QT_OSX_BLUETOOTH
530 return; // not supported on macOS.
531#endif
532 Q_D(QBluetoothSocketBase);
533 if (d->secFlags != flags)
534 d->secFlags = flags;
535}
536
537/*!
538 Returns the security parameters used for the initial connection
539 attempt.
540
541 The security parameters may be renegotiated between the two parties
542 during or after the connection has been established. If such a change happens
543 it is not reflected in the value of this flag.
544
545 On \macos, this flag is always set to \l QBluetooth::Secure.
546
547 \sa setPreferredSecurityFlags()
548
549 \since 5.6
550*/
551QBluetooth::SecurityFlags QBluetoothSocket::preferredSecurityFlags() const
552{
553#if QT_OSX_BLUETOOTH
554 // not supported on macOS - platform always uses encryption
555 return QBluetooth::Secure;
556#else
557 Q_D(const QBluetoothSocketBase);
558 return d->secFlags;
559#endif // QT_OSX_BLUETOOTH
560}
561
562/*!
563 Sets the socket state to \a state.
564*/
565void QBluetoothSocket::setSocketState(QBluetoothSocket::SocketState state)
566{
567 Q_D(QBluetoothSocketBase);
568 const SocketState old = d->state;
569 if (state == old)
570 return;
571
572 d->state = state;
573 if(old != d->state)
574 emit stateChanged(state);
575 if (state == QBluetoothSocket::ConnectedState) {
576 emit connected();
577 } else if ((old == QBluetoothSocket::ConnectedState
578 || old == QBluetoothSocket::ClosingState)
579 && state == QBluetoothSocket::UnconnectedState) {
580 emit disconnected();
581 }
582 if(state == ListeningState){
583#ifdef QT_OSX_BLUETOOTH
584 qCWarning(QT_BT) << "listening socket is not supported by IOBluetooth";
585#endif
586 // TODO: look at this, is this really correct?
587 // if we're a listening socket we can't handle connects?
588 if (d->readNotifier) {
589 d->readNotifier->setEnabled(false);
590 }
591 }
592}
593
594/*!
595 Returns true if you can read at least one line from the device
596 */
597
598bool QBluetoothSocket::canReadLine() const
599{
600 Q_D(const QBluetoothSocketBase);
601 return d->canReadLine() || QIODevice::canReadLine();
602}
603
604/*!
605 Sets the type of error that last occurred to \a error_.
606*/
607void QBluetoothSocket::setSocketError(QBluetoothSocket::SocketError error_)
608{
609 Q_D(QBluetoothSocketBase);
610 d->socketError = error_;
611 emit error(error: error_);
612}
613
614/*!
615 Start device discovery for \a service and open the socket with \a openMode. If the socket
616 is created with a service uuid device address, use service discovery to find the
617 port number to connect to.
618*/
619
620void QBluetoothSocket::doDeviceDiscovery(const QBluetoothServiceInfo &service, OpenMode openMode)
621{
622 Q_D(QBluetoothSocketBase);
623
624 setSocketState(QBluetoothSocket::ServiceLookupState);
625 qCDebug(QT_BT) << "Starting Bluetooth service discovery";
626
627 if(d->discoveryAgent) {
628 d->discoveryAgent->stop();
629 delete d->discoveryAgent;
630 }
631
632 d->discoveryAgent = new QBluetoothServiceDiscoveryAgent(this);
633 d->discoveryAgent->setRemoteAddress(service.device().address());
634
635 //qDebug() << "Got agent";
636
637 connect(sender: d->discoveryAgent, signal: &QBluetoothServiceDiscoveryAgent::serviceDiscovered,
638 receiver: this, slot: &QBluetoothSocket::serviceDiscovered);
639 connect(sender: d->discoveryAgent, signal: &QBluetoothServiceDiscoveryAgent::finished,
640 receiver: this, slot: &QBluetoothSocket::discoveryFinished);
641
642 d->openMode = openMode;
643
644 QList<QBluetoothUuid> filterUuids = service.serviceClassUuids();
645 if(!service.serviceUuid().isNull())
646 filterUuids.append(t: service.serviceUuid());
647
648 if (!filterUuids.isEmpty())
649 d->discoveryAgent->setUuidFilter(filterUuids);
650
651 // we have to ID the service somehow
652 Q_ASSERT(!d->discoveryAgent->uuidFilter().isEmpty());
653
654 qCDebug(QT_BT) << "UUID filter" << d->discoveryAgent->uuidFilter();
655
656 d->discoveryAgent->start(mode: QBluetoothServiceDiscoveryAgent::FullDiscovery);
657}
658
659void QBluetoothSocket::serviceDiscovered(const QBluetoothServiceInfo &service)
660{
661 Q_D(QBluetoothSocketBase);
662 qCDebug(QT_BT) << "FOUND SERVICE!" << service;
663 if (service.protocolServiceMultiplexer() > 0 || service.serverChannel() > 0) {
664 connectToService(service, openMode: d->openMode);
665 d->discoveryAgent->deleteLater();
666 d->discoveryAgent = nullptr;
667#ifdef QT_WINRT_BLUETOOTH
668 } else if (!service.attribute(0xBEEF).isNull()
669 && !service.attribute(0xBEF0).isNull()) {
670 connectToService(service, d->openMode);
671 d->discoveryAgent->deleteLater();
672 d->discoveryAgent = nullptr;
673#endif
674 } else {
675 qCDebug(QT_BT) << "Could not find port/psm for potential remote service";
676 }
677}
678
679void QBluetoothSocket::discoveryFinished()
680{
681 qCDebug(QT_BT) << "Socket discovery finished";
682 Q_D(QBluetoothSocketBase);
683 if (d->discoveryAgent){
684 qCDebug(QT_BT) << "Didn't find any";
685 d->errorString = tr(s: "Service cannot be found");
686 setSocketError(ServiceNotFoundError);
687 setSocketState(QBluetoothSocket::UnconnectedState);
688 d->discoveryAgent->deleteLater();
689 d->discoveryAgent = nullptr;
690 }
691}
692
693void QBluetoothSocket::abort()
694{
695 if (state() == UnconnectedState)
696 return;
697
698 Q_D(QBluetoothSocketBase);
699 setOpenMode(QIODevice::NotOpen);
700
701 if (state() == ServiceLookupState && d->discoveryAgent) {
702 d->discoveryAgent->disconnect();
703 d->discoveryAgent->stop();
704 d->discoveryAgent = nullptr;
705 }
706
707 setSocketState(ClosingState);
708 d->abort();
709}
710
711void QBluetoothSocket::disconnectFromService()
712{
713 close();
714}
715
716QString QBluetoothSocket::localName() const
717{
718 Q_D(const QBluetoothSocketBase);
719 return d->localName();
720}
721
722QBluetoothAddress QBluetoothSocket::localAddress() const
723{
724 Q_D(const QBluetoothSocketBase);
725 return d->localAddress();
726}
727
728quint16 QBluetoothSocket::localPort() const
729{
730 Q_D(const QBluetoothSocketBase);
731 return d->localPort();
732}
733
734QString QBluetoothSocket::peerName() const
735{
736 Q_D(const QBluetoothSocketBase);
737 return d->peerName();
738}
739
740QBluetoothAddress QBluetoothSocket::peerAddress() const
741{
742 Q_D(const QBluetoothSocketBase);
743 return d->peerAddress();
744}
745
746quint16 QBluetoothSocket::peerPort() const
747{
748 Q_D(const QBluetoothSocketBase);
749 return d->peerPort();
750}
751
752qint64 QBluetoothSocket::writeData(const char *data, qint64 maxSize)
753{
754 Q_D(QBluetoothSocketBase);
755
756 if (!data || maxSize <= 0) {
757 d_ptr->errorString = tr(s: "Invalid data/data size");
758 setSocketError(QBluetoothSocket::OperationError);
759 return -1;
760 }
761
762 return d->writeData(data, maxSize);
763}
764
765qint64 QBluetoothSocket::readData(char *data, qint64 maxSize)
766{
767 Q_D(QBluetoothSocketBase);
768 return d->readData(data, maxSize);
769}
770
771void QBluetoothSocket::close()
772{
773 if (state() == UnconnectedState)
774 return;
775
776 Q_D(QBluetoothSocketBase);
777 setOpenMode(QIODevice::NotOpen);
778
779 if (state() == ServiceLookupState && d->discoveryAgent) {
780 d->discoveryAgent->disconnect();
781 d->discoveryAgent->stop();
782 d->discoveryAgent = nullptr;
783 }
784
785 setSocketState(ClosingState);
786
787 d->close();
788}
789
790/*!
791 Set the socket to use \a socketDescriptor with a type of \a socketType,
792 which is in state, \a socketState, and mode, \a openMode.
793
794 Returns true on success
795*/
796
797
798bool QBluetoothSocket::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType,
799 SocketState socketState, OpenMode openMode)
800{
801 Q_D(QBluetoothSocketBase);
802 return d->setSocketDescriptor(socketDescriptor, socketType, socketState, openMode);
803}
804
805/*!
806 Returns the platform-specific socket descriptor, if available.
807 This function returns -1 if the descriptor is not available or an error has occurred.
808*/
809
810int QBluetoothSocket::socketDescriptor() const
811{
812 Q_D(const QBluetoothSocketBase);
813 return d->socket;
814}
815
816
817
818#ifndef QT_NO_DEBUG_STREAM
819QDebug operator<<(QDebug debug, QBluetoothSocket::SocketError error)
820{
821 switch (error) {
822 case QBluetoothSocket::UnknownSocketError:
823 debug << "QBluetoothSocket::UnknownSocketError";
824 break;
825 case QBluetoothSocket::HostNotFoundError:
826 debug << "QBluetoothSocket::HostNotFoundError";
827 break;
828 case QBluetoothSocket::RemoteHostClosedError:
829 debug << "QBluetoothSocket::RemoteHostClosedError";
830 break;
831 case QBluetoothSocket::ServiceNotFoundError:
832 debug << "QBluetoothSocket::ServiceNotFoundError";
833 break;
834 case QBluetoothSocket::NetworkError:
835 debug << "QBluetoothSocket::NetworkError";
836 break;
837 case QBluetoothSocket::UnsupportedProtocolError:
838 debug << "QBluetoothSocket::UnsupportedProtocolError";
839 break;
840 default:
841 debug << "QBluetoothSocket::SocketError(" << (int)error << ")";
842 }
843 return debug;
844}
845
846QDebug operator<<(QDebug debug, QBluetoothSocket::SocketState state)
847{
848 switch (state) {
849 case QBluetoothSocket::UnconnectedState:
850 debug << "QBluetoothSocket::UnconnectedState";
851 break;
852 case QBluetoothSocket::ConnectingState:
853 debug << "QBluetoothSocket::ConnectingState";
854 break;
855 case QBluetoothSocket::ConnectedState:
856 debug << "QBluetoothSocket::ConnectedState";
857 break;
858 case QBluetoothSocket::BoundState:
859 debug << "QBluetoothSocket::BoundState";
860 break;
861 case QBluetoothSocket::ClosingState:
862 debug << "QBluetoothSocket::ClosingState";
863 break;
864 case QBluetoothSocket::ListeningState:
865 debug << "QBluetoothSocket::ListeningState";
866 break;
867 case QBluetoothSocket::ServiceLookupState:
868 debug << "QBluetoothSocket::ServiceLookupState";
869 break;
870 default:
871 debug << "QBluetoothSocket::SocketState(" << (int)state << ")";
872 }
873 return debug;
874}
875#endif
876
877QT_END_NAMESPACE
878
879#include "moc_qbluetoothsocket.cpp"
880

source code of qtconnectivity/src/bluetooth/qbluetoothsocket.cpp