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_bluez_p.h"
6#include "qbluetoothdeviceinfo.h"
7
8#include "bluez/objectmanager_p.h"
9#include <QtBluetooth/QBluetoothLocalDevice>
10#include "bluez/bluez_data_p.h"
11
12#include <qplatformdefs.h>
13#include <QtCore/private/qcore_unix_p.h>
14
15#include <QtCore/QLoggingCategory>
16
17#include <errno.h>
18#include <unistd.h>
19#include <string.h>
20
21#include <QtCore/QSocketNotifier>
22
23QT_BEGIN_NAMESPACE
24
25Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ)
26
27QBluetoothSocketPrivateBluez::QBluetoothSocketPrivateBluez()
28 : QBluetoothSocketBasePrivate()
29{
30 secFlags = QBluetooth::Security::Authorization;
31}
32
33QBluetoothSocketPrivateBluez::~QBluetoothSocketPrivateBluez()
34{
35 delete readNotifier;
36 readNotifier = nullptr;
37 delete connectWriteNotifier;
38 connectWriteNotifier = nullptr;
39
40 // If the socket wasn't closed/aborted make sure we free the socket file descriptor
41 if (socket != -1)
42 QT_CLOSE(fd: socket);
43}
44
45bool QBluetoothSocketPrivateBluez::ensureNativeSocket(QBluetoothServiceInfo::Protocol type)
46{
47 if (socket != -1) {
48 if (socketType == type)
49 return true;
50
51 delete readNotifier;
52 readNotifier = nullptr;
53 delete connectWriteNotifier;
54 connectWriteNotifier = nullptr;
55 QT_CLOSE(fd: socket);
56 }
57
58 socketType = type;
59
60 switch (type) {
61 case QBluetoothServiceInfo::L2capProtocol:
62 socket = ::socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
63 break;
64 case QBluetoothServiceInfo::RfcommProtocol:
65 socket = ::socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
66 break;
67 default:
68 socket = -1;
69 }
70
71 if (socket == -1)
72 return false;
73
74 int flags = fcntl(fd: socket, F_GETFL, 0);
75 fcntl(fd: socket, F_SETFL, flags | O_NONBLOCK);
76
77 Q_Q(QBluetoothSocket);
78 readNotifier = new QSocketNotifier(socket, QSocketNotifier::Read);
79 QObject::connect(sender: readNotifier, SIGNAL(activated(QSocketDescriptor)), receiver: this, SLOT(_q_readNotify()));
80 connectWriteNotifier = new QSocketNotifier(socket, QSocketNotifier::Write, q);
81 QObject::connect(sender: connectWriteNotifier, SIGNAL(activated(QSocketDescriptor)), receiver: this, SLOT(_q_writeNotify()));
82
83 connectWriteNotifier->setEnabled(false);
84 readNotifier->setEnabled(false);
85
86
87 return true;
88}
89
90void QBluetoothSocketPrivateBluez::connectToServiceHelper(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode)
91{
92 Q_Q(QBluetoothSocket);
93 int result = -1;
94
95 if (socket == -1 && !ensureNativeSocket(type: socketType)) {
96 errorString = QBluetoothSocket::tr(s: "Unknown socket error");
97 q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError);
98 return;
99 }
100
101 // apply preferred security level
102 // ignore QBluetooth::Security::Authentication -> not used anymore by kernel
103 struct bt_security security;
104 memset(s: &security, c: 0, n: sizeof(security));
105
106 if (secFlags & QBluetooth::Security::Authorization)
107 security.level = BT_SECURITY_LOW;
108 if (secFlags & QBluetooth::Security::Encryption)
109 security.level = BT_SECURITY_MEDIUM;
110 if (secFlags & QBluetooth::Security::Secure)
111 security.level = BT_SECURITY_HIGH;
112
113 if (setsockopt(fd: socket, SOL_BLUETOOTH, BT_SECURITY,
114 optval: &security, optlen: sizeof(security)) != 0) {
115 qCWarning(QT_BT_BLUEZ) << "Failed to set socket option, closing socket for safety" << errno;
116 qCWarning(QT_BT_BLUEZ) << "Error: " << qt_error_string(errno);
117 errorString = QBluetoothSocket::tr(s: "Cannot set connection security level");
118 q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError);
119 return;
120 }
121
122 if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
123 sockaddr_rc addr;
124
125 memset(s: &addr, c: 0, n: sizeof(addr));
126 addr.rc_family = AF_BLUETOOTH;
127 addr.rc_channel = port;
128
129 convertAddress(from: address.toUInt64(), to&: addr.rc_bdaddr.b);
130
131 connectWriteNotifier->setEnabled(true);
132 readNotifier->setEnabled(true);
133
134 result = ::connect(fd: socket, addr: (sockaddr *)&addr, len: sizeof(addr));
135 } else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
136 sockaddr_l2 addr;
137
138 memset(s: &addr, c: 0, n: sizeof(addr));
139 addr.l2_family = AF_BLUETOOTH;
140 // This is an ugly hack but the socket class does what's needed already.
141 // For L2CP GATT we need a channel rather than a socket and the LE address type
142 // We don't want to make this public API offering for now especially since
143 // only Linux (of all platforms supported by this library) supports this type
144 // of socket.
145
146#if QT_CONFIG(bluez) && !defined(QT_BLUEZ_NO_BTLE)
147 if (lowEnergySocketType) {
148 addr.l2_cid = htobs(port);
149 addr.l2_bdaddr_type = lowEnergySocketType;
150 } else {
151 addr.l2_psm = htobs(port);
152 }
153#else
154 addr.l2_psm = htobs(port);
155#endif
156
157 convertAddress(from: address.toUInt64(), to&: addr.l2_bdaddr.b);
158
159 connectWriteNotifier->setEnabled(true);
160 readNotifier->setEnabled(true);
161
162 result = ::connect(fd: socket, addr: (sockaddr *)&addr, len: sizeof(addr));
163 }
164
165 if (result >= 0 || (result == -1 && errno == EINPROGRESS)) {
166 connecting = true;
167 q->setSocketState(QBluetoothSocket::SocketState::ConnectingState);
168 q->setOpenMode(openMode);
169 } else {
170 errorString = qt_error_string(errno);
171 q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError);
172 }
173}
174
175void QBluetoothSocketPrivateBluez::connectToService(
176 const QBluetoothServiceInfo &service, QIODevice::OpenMode openMode)
177{
178 Q_Q(QBluetoothSocket);
179
180 if (q->state() != QBluetoothSocket::SocketState::UnconnectedState
181 && q->state() != QBluetoothSocket::SocketState::ServiceLookupState) {
182 qCWarning(QT_BT_BLUEZ) << "QBluetoothSocketPrivateBluez::connectToService called on busy socket";
183 errorString = QBluetoothSocket::tr(s: "Trying to connect while connection is in progress");
184 q->setSocketError(QBluetoothSocket::SocketError::OperationError);
185 return;
186 }
187
188 // we are checking the service protocol and not socketType()
189 // socketType will change in ensureNativeSocket()
190 if (service.socketProtocol() == QBluetoothServiceInfo::UnknownProtocol) {
191 qCWarning(QT_BT_BLUEZ) << "QBluetoothSocket::connectToService cannot "
192 "connect with 'UnknownProtocol' (type provided by given service)";
193 errorString = QBluetoothSocket::tr(s: "Socket type not supported");
194 q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError);
195 return;
196 }
197
198 if (service.protocolServiceMultiplexer() > 0) {
199 Q_ASSERT(service.socketProtocol() == QBluetoothServiceInfo::L2capProtocol);
200
201 if (!ensureNativeSocket(type: QBluetoothServiceInfo::L2capProtocol)) {
202 errorString = QBluetoothSocket::tr(s: "Unknown socket error");
203 q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError);
204 return;
205 }
206 connectToServiceHelper(address: service.device().address(), port: service.protocolServiceMultiplexer(),
207 openMode);
208 } else if (service.serverChannel() > 0) {
209 Q_ASSERT(service.socketProtocol() == QBluetoothServiceInfo::RfcommProtocol);
210
211 if (!ensureNativeSocket(type: QBluetoothServiceInfo::RfcommProtocol)) {
212 errorString = QBluetoothSocket::tr(s: "Unknown socket error");
213 q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError);
214 return;
215 }
216 connectToServiceHelper(address: service.device().address(), port: service.serverChannel(), openMode);
217 } else {
218 // try doing service discovery to see if we can find the socket
219 if (service.serviceUuid().isNull()
220 && !service.serviceClassUuids().contains(t: QBluetoothUuid::ServiceClassUuid::SerialPort)) {
221 qCWarning(QT_BT_BLUEZ) << "No port, no PSM, and no UUID provided. Unable to connect";
222 return;
223 }
224 qCDebug(QT_BT_BLUEZ) << "Need a port/psm, doing discovery";
225 q->doDeviceDiscovery(service, openMode);
226 }
227}
228
229void QBluetoothSocketPrivateBluez::connectToService(
230 const QBluetoothAddress &address, const QBluetoothUuid &uuid,
231 QIODevice::OpenMode openMode)
232{
233 Q_Q(QBluetoothSocket);
234
235 if (q->state() != QBluetoothSocket::SocketState::UnconnectedState) {
236 qCWarning(QT_BT_BLUEZ) << "QBluetoothSocketPrivateBluez::connectToService called on busy socket";
237 errorString = QBluetoothSocket::tr(s: "Trying to connect while connection is in progress");
238 q->setSocketError(QBluetoothSocket::SocketError::OperationError);
239 return;
240 }
241
242 if (q->socketType() == QBluetoothServiceInfo::UnknownProtocol) {
243 qCWarning(QT_BT_BLUEZ) << "QBluetoothSocketPrivateBluez::connectToService cannot "
244 "connect with 'UnknownProtocol' (type provided by given service)";
245 errorString = QBluetoothSocket::tr(s: "Socket type not supported");
246 q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError);
247 return;
248 }
249
250 QBluetoothServiceInfo service;
251 QBluetoothDeviceInfo device(address, QString(), QBluetoothDeviceInfo::MiscellaneousDevice);
252 service.setDevice(device);
253 service.setServiceUuid(uuid);
254 q->doDeviceDiscovery(service, openMode);
255}
256
257void QBluetoothSocketPrivateBluez::connectToService(
258 const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode)
259{
260 Q_Q(QBluetoothSocket);
261
262 if (q->socketType() == QBluetoothServiceInfo::UnknownProtocol) {
263 qCWarning(QT_BT_BLUEZ) << "QBluetoothSocketPrivateBluez::connectToService cannot "
264 "connect with 'UnknownProtocol' (type provided by given service)";
265 errorString = QBluetoothSocket::tr(s: "Socket type not supported");
266 q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError);
267 return;
268 }
269
270 if (q->state() != QBluetoothSocket::SocketState::UnconnectedState) {
271 qCWarning(QT_BT_BLUEZ) << "QBluetoothSocketPrivateBluez::connectToService called on busy socket";
272 errorString = QBluetoothSocket::tr(s: "Trying to connect while connection is in progress");
273 q->setSocketError(QBluetoothSocket::SocketError::OperationError);
274 return;
275 }
276 connectToServiceHelper(address, port, openMode);
277}
278
279void QBluetoothSocketPrivateBluez::_q_writeNotify()
280{
281 Q_Q(QBluetoothSocket);
282 if (connecting && state == QBluetoothSocket::SocketState::ConnectingState){
283 int errorno, len;
284 len = sizeof(errorno);
285 ::getsockopt(fd: socket, SOL_SOCKET, SO_ERROR, optval: &errorno, optlen: (socklen_t*)&len);
286 if(errorno) {
287 errorString = qt_error_string(errorCode: errorno);
288 q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError);
289 return;
290 }
291
292 q->setSocketState(QBluetoothSocket::SocketState::ConnectedState);
293
294 connectWriteNotifier->setEnabled(false);
295 connecting = false;
296 }
297 else {
298 if (txBuffer.size() == 0) {
299 connectWriteNotifier->setEnabled(false);
300 return;
301 }
302
303 char buf[1024];
304
305 const auto size = txBuffer.read(target: buf, size: 1024);
306 const auto writtenBytes = qt_safe_write(fd: socket, data: buf, len: size);
307 if (writtenBytes < 0) {
308 switch (errno) {
309 case EAGAIN:
310 txBuffer.ungetBlock(block: buf, size);
311 break;
312 default:
313 // every other case returns error
314 errorString = QBluetoothSocket::tr(s: "Network Error: %1").arg(a: qt_error_string(errno)) ;
315 q->setSocketError(QBluetoothSocket::SocketError::NetworkError);
316 break;
317 }
318 } else {
319 if (writtenBytes < size) {
320 // add remainder back to buffer
321 char* remainder = buf + writtenBytes;
322 txBuffer.ungetBlock(block: remainder, size: size - writtenBytes);
323 }
324 if (writtenBytes > 0)
325 emit q->bytesWritten(bytes: writtenBytes);
326 }
327
328 if (txBuffer.size()) {
329 connectWriteNotifier->setEnabled(true);
330 }
331 else if (state == QBluetoothSocket::SocketState::ClosingState) {
332 connectWriteNotifier->setEnabled(false);
333 this->close();
334 }
335 }
336}
337
338void QBluetoothSocketPrivateBluez::_q_readNotify()
339{
340 Q_Q(QBluetoothSocket);
341 char *writePointer = rxBuffer.reserve(QPRIVATELINEARBUFFER_BUFFERSIZE);
342// qint64 readFromDevice = q->readData(writePointer, QPRIVATELINEARBUFFER_BUFFERSIZE);
343 const auto readFromDevice = ::read(fd: socket, buf: writePointer, QPRIVATELINEARBUFFER_BUFFERSIZE);
344 rxBuffer.chop(QPRIVATELINEARBUFFER_BUFFERSIZE - (readFromDevice < 0 ? 0 : readFromDevice));
345 if(readFromDevice <= 0){
346 int errsv = errno;
347 readNotifier->setEnabled(false);
348 connectWriteNotifier->setEnabled(false);
349 errorString = qt_error_string(errorCode: errsv);
350 qCWarning(QT_BT_BLUEZ) << Q_FUNC_INFO << socket << "error:" << readFromDevice << errorString;
351 if (errsv == EHOSTDOWN)
352 q->setSocketError(QBluetoothSocket::SocketError::HostNotFoundError);
353 else if (errsv == ECONNRESET)
354 q->setSocketError(QBluetoothSocket::SocketError::RemoteHostClosedError);
355 else
356 q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError);
357
358 q->disconnectFromService();
359 }
360 else {
361 emit q->readyRead();
362 }
363}
364
365void QBluetoothSocketPrivateBluez::abort()
366{
367 delete readNotifier;
368 readNotifier = nullptr;
369 delete connectWriteNotifier;
370 connectWriteNotifier = nullptr;
371
372 // We don't transition through Closing for abort, so
373 // we don't call disconnectFromService or
374 // QBluetoothSocket::close
375 QT_CLOSE(fd: socket);
376 socket = -1;
377
378 Q_Q(QBluetoothSocket);
379
380 q->setOpenMode(QIODevice::NotOpen);
381 q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState);
382 emit q->readChannelFinished();
383}
384
385QString QBluetoothSocketPrivateBluez::localName() const
386{
387 const QBluetoothAddress address = localAddress();
388 if (address.isNull())
389 return QString();
390
391 QBluetoothLocalDevice device(address);
392 return device.name();
393}
394
395QBluetoothAddress QBluetoothSocketPrivateBluez::localAddress() const
396{
397 if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
398 sockaddr_rc addr;
399 socklen_t addrLength = sizeof(addr);
400
401 if (::getsockname(fd: socket, addr: reinterpret_cast<sockaddr *>(&addr), len: &addrLength) == 0)
402 return QBluetoothAddress(convertAddress(from: addr.rc_bdaddr.b));
403 } else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
404 sockaddr_l2 addr;
405 socklen_t addrLength = sizeof(addr);
406
407 if (::getsockname(fd: socket, addr: reinterpret_cast<sockaddr *>(&addr), len: &addrLength) == 0)
408 return QBluetoothAddress(convertAddress(from: addr.l2_bdaddr.b));
409 }
410
411 return QBluetoothAddress();
412}
413
414quint16 QBluetoothSocketPrivateBluez::localPort() const
415{
416 if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
417 sockaddr_rc addr;
418 socklen_t addrLength = sizeof(addr);
419
420 if (::getsockname(fd: socket, addr: reinterpret_cast<sockaddr *>(&addr), len: &addrLength) == 0)
421 return addr.rc_channel;
422 } else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
423 sockaddr_l2 addr;
424 socklen_t addrLength = sizeof(addr);
425
426 if (::getsockname(fd: socket, addr: reinterpret_cast<sockaddr *>(&addr), len: &addrLength) == 0)
427 return addr.l2_psm;
428 }
429
430 return 0;
431}
432
433QString QBluetoothSocketPrivateBluez::peerName() const
434{
435 quint64 bdaddr;
436
437 if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
438 sockaddr_rc addr;
439 socklen_t addrLength = sizeof(addr);
440
441 if (::getpeername(fd: socket, addr: reinterpret_cast<sockaddr *>(&addr), len: &addrLength) < 0)
442 return QString();
443
444 convertAddress(from: addr.rc_bdaddr.b, to: &bdaddr);
445 } else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
446 sockaddr_l2 addr;
447 socklen_t addrLength = sizeof(addr);
448
449 if (::getpeername(fd: socket, addr: reinterpret_cast<sockaddr *>(&addr), len: &addrLength) < 0)
450 return QString();
451
452 convertAddress(from: addr.l2_bdaddr.b, to: &bdaddr);
453 } else {
454 qCWarning(QT_BT_BLUEZ) << "peerName() called on socket of unknown type";
455 return QString();
456 }
457
458 const QString peerAddress = QBluetoothAddress(bdaddr).toString();
459
460 initializeBluez5();
461 OrgFreedesktopDBusObjectManagerInterface manager(
462 QStringLiteral("org.bluez"), QStringLiteral("/"), QDBusConnection::systemBus());
463 QDBusPendingReply<ManagedObjectList> reply = manager.GetManagedObjects();
464 reply.waitForFinished();
465 if (reply.isError())
466 return QString();
467
468 ManagedObjectList managedObjectList = reply.value();
469 for (ManagedObjectList::const_iterator it = managedObjectList.constBegin();
470 it != managedObjectList.constEnd(); ++it) {
471 const InterfaceList &ifaceList = it.value();
472
473 for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd();
474 ++jt) {
475 const QString &iface = jt.key();
476 const QVariantMap &ifaceValues = jt.value();
477
478 if (iface == QStringLiteral("org.bluez.Device1")) {
479 if (ifaceValues.value(QStringLiteral("Address")).toString() == peerAddress)
480 return ifaceValues.value(QStringLiteral("Alias")).toString();
481 }
482 }
483 }
484 return QString();
485}
486
487QBluetoothAddress QBluetoothSocketPrivateBluez::peerAddress() const
488{
489 if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
490 sockaddr_rc addr;
491 socklen_t addrLength = sizeof(addr);
492
493 if (::getpeername(fd: socket, addr: reinterpret_cast<sockaddr *>(&addr), len: &addrLength) == 0)
494 return QBluetoothAddress(convertAddress(from: addr.rc_bdaddr.b));
495 } else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
496 sockaddr_l2 addr;
497 socklen_t addrLength = sizeof(addr);
498
499 if (::getpeername(fd: socket, addr: reinterpret_cast<sockaddr *>(&addr), len: &addrLength) == 0)
500 return QBluetoothAddress(convertAddress(from: addr.l2_bdaddr.b));
501 }
502
503 return QBluetoothAddress();
504}
505
506quint16 QBluetoothSocketPrivateBluez::peerPort() const
507{
508 if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
509 sockaddr_rc addr;
510 socklen_t addrLength = sizeof(addr);
511
512 if (::getpeername(fd: socket, addr: reinterpret_cast<sockaddr *>(&addr), len: &addrLength) == 0)
513 return addr.rc_channel;
514 } else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
515 sockaddr_l2 addr;
516 socklen_t addrLength = sizeof(addr);
517
518 if (::getpeername(fd: socket, addr: reinterpret_cast<sockaddr *>(&addr), len: &addrLength) == 0)
519 return addr.l2_psm;
520 }
521
522 return 0;
523}
524
525qint64 QBluetoothSocketPrivateBluez::writeData(const char *data, qint64 maxSize)
526{
527 Q_Q(QBluetoothSocket);
528
529 if (state != QBluetoothSocket::SocketState::ConnectedState) {
530 errorString = QBluetoothSocket::tr(s: "Cannot write while not connected");
531 q->setSocketError(QBluetoothSocket::SocketError::OperationError);
532 return -1;
533 }
534
535 if (q->openMode() & QIODevice::Unbuffered) {
536 auto sz = ::qt_safe_write(fd: socket, data, len: maxSize);
537 if (sz < 0) {
538 switch (errno) {
539 case EAGAIN:
540 sz = 0;
541 break;
542 default:
543 errorString = QBluetoothSocket::tr(s: "Network Error: %1").arg(a: qt_error_string(errno));
544 q->setSocketError(QBluetoothSocket::SocketError::NetworkError);
545 }
546 }
547
548 if (sz > 0)
549 emit q->bytesWritten(bytes: sz);
550
551 return sz;
552 }
553 else {
554
555 if(!connectWriteNotifier)
556 return -1;
557
558 if(txBuffer.size() == 0) {
559 connectWriteNotifier->setEnabled(true);
560 QMetaObject::invokeMethod(obj: this, member: "_q_writeNotify", c: Qt::QueuedConnection);
561 }
562
563 char *txbuf = txBuffer.reserve(size: maxSize);
564 memcpy(dest: txbuf, src: data, n: maxSize);
565
566 return maxSize;
567 }
568}
569
570qint64 QBluetoothSocketPrivateBluez::readData(char *data, qint64 maxSize)
571{
572 Q_Q(QBluetoothSocket);
573
574 if (state != QBluetoothSocket::SocketState::ConnectedState) {
575 errorString = QBluetoothSocket::tr(s: "Cannot read while not connected");
576 q->setSocketError(QBluetoothSocket::SocketError::OperationError);
577 return -1;
578 }
579
580 if (!rxBuffer.isEmpty())
581 return rxBuffer.read(target: data, size: maxSize);
582
583 return 0;
584}
585
586void QBluetoothSocketPrivateBluez::close()
587{
588 // If we have pending data on the write buffer, wait until it has been written,
589 // after which this close() will be called again
590 if (txBuffer.size() > 0)
591 connectWriteNotifier->setEnabled(true);
592 else
593 abort();
594}
595
596bool QBluetoothSocketPrivateBluez::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType_,
597 QBluetoothSocket::SocketState socketState, QBluetoothSocket::OpenMode openMode)
598{
599 Q_Q(QBluetoothSocket);
600 delete readNotifier;
601 readNotifier = nullptr;
602 delete connectWriteNotifier;
603 connectWriteNotifier = nullptr;
604
605 socketType = socketType_;
606 if (socket != -1)
607 QT_CLOSE(fd: socket);
608
609 socket = socketDescriptor;
610
611 // ensure that O_NONBLOCK is set on new connections.
612 int flags = fcntl(fd: socket, F_GETFL, 0);
613 if (!(flags & O_NONBLOCK))
614 fcntl(fd: socket, F_SETFL, flags | O_NONBLOCK);
615
616 readNotifier = new QSocketNotifier(socket, QSocketNotifier::Read);
617 QObject::connect(sender: readNotifier, SIGNAL(activated(QSocketDescriptor)), receiver: this, SLOT(_q_readNotify()));
618 connectWriteNotifier = new QSocketNotifier(socket, QSocketNotifier::Write, q);
619 QObject::connect(sender: connectWriteNotifier, SIGNAL(activated(QSocketDescriptor)), receiver: this, SLOT(_q_writeNotify()));
620
621 q->setOpenMode(openMode);
622 q->setSocketState(socketState);
623
624 return true;
625}
626
627qint64 QBluetoothSocketPrivateBluez::bytesAvailable() const
628{
629 return rxBuffer.size();
630}
631
632qint64 QBluetoothSocketPrivateBluez::bytesToWrite() const
633{
634 return txBuffer.size();
635}
636
637bool QBluetoothSocketPrivateBluez::canReadLine() const
638{
639 return rxBuffer.canReadLine();
640}
641
642QT_END_NAMESPACE
643
644#include "moc_qbluetoothsocket_bluez_p.cpp"
645

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