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

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