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