8#include "bluez/objectmanager_p.h"
9#include <QtBluetooth/QBluetoothLocalDevice>
10#include "bluez/bluez_data_p.h"
12#include <qplatformdefs.h>
13#include <QtCore/private/qcore_unix_p.h>
15#include <QtCore/QLoggingCategory>
21#include <QtCore/QSocketNotifier>
25Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ)
27using namespace QtBluetoothPrivate;
30 : QBluetoothSocketBasePrivate()
32 secFlags = QBluetooth::Security::Authorization;
38 readNotifier =
nullptr;
39 delete connectWriteNotifier;
40 connectWriteNotifier =
nullptr;
50 if (socketType == type)
54 readNotifier =
nullptr;
55 delete connectWriteNotifier;
56 connectWriteNotifier =
nullptr;
63 case QBluetoothServiceInfo::L2capProtocol:
64 socket = ::socket(AF_BLUETOOTH, SOCK_SEQPACKET,
BTPROTO_L2CAP);
66 case QBluetoothServiceInfo::RfcommProtocol:
76 int flags = fcntl(socket, F_GETFL, 0);
77 fcntl(socket, F_SETFL, flags | O_NONBLOCK);
79 Q_Q(QBluetoothSocket);
80 readNotifier =
new QSocketNotifier(socket, QSocketNotifier::Read);
81 QObject::connect(readNotifier, SIGNAL(activated(QSocketDescriptor)),
this, SLOT(_q_readNotify()));
82 connectWriteNotifier =
new QSocketNotifier(socket, QSocketNotifier::Write, q);
83 QObject::connect(connectWriteNotifier, SIGNAL(activated(QSocketDescriptor)),
this, SLOT(_q_writeNotify()));
85 connectWriteNotifier->setEnabled(
false);
86 readNotifier->setEnabled(
false);
94 Q_Q(QBluetoothSocket);
97 if (socket == -1 && !ensureNativeSocket(socketType)) {
98 errorString = QBluetoothSocket::tr(
"Unknown socket error");
99 q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError);
105 struct bt_security security;
106 memset(&security, 0,
sizeof(security));
108 if (secFlags & QBluetooth::Security::Authorization)
110 if (secFlags & QBluetooth::Security::Encryption)
112 if (secFlags & QBluetooth::Security::Secure)
116 &security,
sizeof(security)) != 0) {
117 qCWarning(QT_BT_BLUEZ) <<
"Failed to set socket option, closing socket for safety" << errno;
118 qCWarning(QT_BT_BLUEZ) <<
"Error: " << qt_error_string(errno);
119 errorString = QBluetoothSocket::tr(
"Cannot set connection security level");
120 q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError);
124 if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
127 memset(&addr, 0,
sizeof(addr));
129 addr.rc_channel = port;
131 convertAddress(address.toUInt64(), addr.rc_bdaddr.b);
133 connectWriteNotifier->setEnabled(
true);
134 readNotifier->setEnabled(
true);
136 result = ::connect(socket, (sockaddr *)&addr,
sizeof(addr));
137 }
else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
140 memset(&addr, 0,
sizeof(addr));
148#if QT_CONFIG(bluez) && !defined(QT_BLUEZ_NO_BTLE)
149 if (lowEnergySocketType) {
150 addr.l2_cid = htobs(port);
151 addr.l2_bdaddr_type = lowEnergySocketType;
153 addr.l2_psm = htobs(port);
159 convertAddress(address.toUInt64(), addr.l2_bdaddr.b);
161 connectWriteNotifier->setEnabled(
true);
162 readNotifier->setEnabled(
true);
164 result = ::connect(socket, (sockaddr *)&addr,
sizeof(addr));
167 if (result >= 0 || (result == -1 && errno == EINPROGRESS)) {
169 q->setSocketState(QBluetoothSocket::SocketState::ConnectingState);
170 q->setOpenMode(openMode);
172 errorString = qt_error_string(errno);
173 q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError);
178 const QBluetoothServiceInfo &service, QIODevice::OpenMode openMode)
180 Q_Q(QBluetoothSocket);
182 if (q->state() != QBluetoothSocket::SocketState::UnconnectedState
183 && q->state() != QBluetoothSocket::SocketState::ServiceLookupState) {
184 qCWarning(QT_BT_BLUEZ) <<
"QBluetoothSocketPrivateBluez::connectToService called on busy socket";
185 errorString = QBluetoothSocket::tr(
"Trying to connect while connection is in progress");
186 q->setSocketError(QBluetoothSocket::SocketError::OperationError);
192 if (service.socketProtocol() == QBluetoothServiceInfo::UnknownProtocol) {
193 qCWarning(QT_BT_BLUEZ) <<
"QBluetoothSocket::connectToService cannot "
194 "connect with 'UnknownProtocol' (type provided by given service)";
195 errorString = QBluetoothSocket::tr(
"Socket type not supported");
196 q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError);
200 if (service.protocolServiceMultiplexer() > 0) {
201 Q_ASSERT(service.socketProtocol() == QBluetoothServiceInfo::L2capProtocol);
203 if (!ensureNativeSocket(QBluetoothServiceInfo::L2capProtocol)) {
204 errorString = QBluetoothSocket::tr(
"Unknown socket error");
205 q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError);
208 connectToServiceHelper(service.device().address(), service.protocolServiceMultiplexer(),
210 }
else if (service.serverChannel() > 0) {
211 Q_ASSERT(service.socketProtocol() == QBluetoothServiceInfo::RfcommProtocol);
213 if (!ensureNativeSocket(QBluetoothServiceInfo::RfcommProtocol)) {
214 errorString = QBluetoothSocket::tr(
"Unknown socket error");
215 q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError);
218 connectToServiceHelper(service.device().address(), service.serverChannel(), openMode);
221 if (service.serviceUuid().isNull()
222 && !service.serviceClassUuids().contains(QBluetoothUuid::ServiceClassUuid::SerialPort)) {
223 qCWarning(QT_BT_BLUEZ) <<
"No port, no PSM, and no UUID provided. Unable to connect";
226 qCDebug(QT_BT_BLUEZ) <<
"Need a port/psm, doing discovery";
227 q->doDeviceDiscovery(service, openMode);
232 const QBluetoothAddress &address,
const QBluetoothUuid &uuid,
233 QIODevice::OpenMode openMode)
235 Q_Q(QBluetoothSocket);
237 if (q->state() != QBluetoothSocket::SocketState::UnconnectedState) {
238 qCWarning(QT_BT_BLUEZ) <<
"QBluetoothSocketPrivateBluez::connectToService called on busy socket";
239 errorString = QBluetoothSocket::tr(
"Trying to connect while connection is in progress");
240 q->setSocketError(QBluetoothSocket::SocketError::OperationError);
244 if (q->socketType() == QBluetoothServiceInfo::UnknownProtocol) {
245 qCWarning(QT_BT_BLUEZ) <<
"QBluetoothSocketPrivateBluez::connectToService cannot "
246 "connect with 'UnknownProtocol' (type provided by given service)";
247 errorString = QBluetoothSocket::tr(
"Socket type not supported");
248 q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError);
252 QBluetoothServiceInfo service;
254 service.setDevice(device);
255 service.setServiceUuid(uuid);
256 q->doDeviceDiscovery(service, openMode);
260 const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode)
262 Q_Q(QBluetoothSocket);
264 if (q->socketType() == QBluetoothServiceInfo::UnknownProtocol) {
265 qCWarning(QT_BT_BLUEZ) <<
"QBluetoothSocketPrivateBluez::connectToService cannot "
266 "connect with 'UnknownProtocol' (type provided by given service)";
267 errorString = QBluetoothSocket::tr(
"Socket type not supported");
268 q->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError);
272 if (q->state() != QBluetoothSocket::SocketState::UnconnectedState) {
273 qCWarning(QT_BT_BLUEZ) <<
"QBluetoothSocketPrivateBluez::connectToService called on busy socket";
274 errorString = QBluetoothSocket::tr(
"Trying to connect while connection is in progress");
275 q->setSocketError(QBluetoothSocket::SocketError::OperationError);
278 connectToServiceHelper(address, port, openMode);
283 Q_Q(QBluetoothSocket);
284 if (connecting && state == QBluetoothSocket::SocketState::ConnectingState){
286 len =
sizeof(errorno);
287 ::getsockopt(socket, SOL_SOCKET, SO_ERROR, &errorno, (socklen_t*)&len);
289 errorString = qt_error_string(errorno);
290 q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError);
294 q->setSocketState(QBluetoothSocket::SocketState::ConnectedState);
296 connectWriteNotifier->setEnabled(
false);
300 if (txBuffer.size() == 0) {
301 connectWriteNotifier->setEnabled(
false);
307 const auto size = txBuffer.read(buf, 1024);
308 const auto writtenBytes = qt_safe_write(socket, buf, size);
309 if (writtenBytes < 0) {
312 txBuffer.ungetBlock(buf, size);
316 errorString = QBluetoothSocket::tr(
"Network Error: %1").arg(qt_error_string(errno)) ;
317 q->setSocketError(QBluetoothSocket::SocketError::NetworkError);
321 if (writtenBytes < size) {
323 char* remainder = buf + writtenBytes;
324 txBuffer.ungetBlock(remainder, size - writtenBytes);
326 if (writtenBytes > 0)
327 emit q->bytesWritten(writtenBytes);
330 if (txBuffer.size()) {
331 connectWriteNotifier->setEnabled(
true);
333 else if (state == QBluetoothSocket::SocketState::ClosingState) {
334 connectWriteNotifier->setEnabled(
false);
342 Q_Q(QBluetoothSocket);
347 if(readFromDevice <= 0){
349 readNotifier->setEnabled(
false);
350 connectWriteNotifier->setEnabled(
false);
351 errorString = qt_error_string(errsv);
352 qCWarning(QT_BT_BLUEZ) << Q_FUNC_INFO << socket <<
"error:" << readFromDevice << errorString;
353 if (errsv == EHOSTDOWN)
354 q->setSocketError(QBluetoothSocket::SocketError::HostNotFoundError);
355 else if (errsv == ECONNRESET)
356 q->setSocketError(QBluetoothSocket::SocketError::RemoteHostClosedError);
358 q->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError);
360 q->disconnectFromService();
370 readNotifier =
nullptr;
371 delete connectWriteNotifier;
372 connectWriteNotifier =
nullptr;
380 Q_Q(QBluetoothSocket);
382 q->setOpenMode(QIODevice::NotOpen);
383 q->setSocketState(QBluetoothSocket::SocketState::UnconnectedState);
384 emit q->readChannelFinished();
389 const QBluetoothAddress address = localAddress();
390 if (address.isNull())
393 QBluetoothLocalDevice device(address);
394 return device.name();
399 if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
401 socklen_t addrLength =
sizeof(addr);
403 if (::getsockname(socket,
reinterpret_cast<sockaddr *>(&addr), &addrLength) == 0)
404 return QBluetoothAddress(convertAddress(addr.rc_bdaddr.b));
405 }
else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
407 socklen_t addrLength =
sizeof(addr);
409 if (::getsockname(socket,
reinterpret_cast<sockaddr *>(&addr), &addrLength) == 0)
410 return QBluetoothAddress(convertAddress(addr.l2_bdaddr.b));
413 return QBluetoothAddress();
418 if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
420 socklen_t addrLength =
sizeof(addr);
422 if (::getsockname(socket,
reinterpret_cast<sockaddr *>(&addr), &addrLength) == 0)
423 return addr.rc_channel;
424 }
else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
426 socklen_t addrLength =
sizeof(addr);
428 if (::getsockname(socket,
reinterpret_cast<sockaddr *>(&addr), &addrLength) == 0)
439 if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
441 socklen_t addrLength =
sizeof(addr);
443 if (::getpeername(socket,
reinterpret_cast<sockaddr *>(&addr), &addrLength) < 0)
446 convertAddress(addr.rc_bdaddr.b, &bdaddr);
447 }
else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
449 socklen_t addrLength =
sizeof(addr);
451 if (::getpeername(socket,
reinterpret_cast<sockaddr *>(&addr), &addrLength) < 0)
454 convertAddress(addr.l2_bdaddr.b, &bdaddr);
456 qCWarning(QT_BT_BLUEZ) <<
"peerName() called on socket of unknown type";
460 const QString peerAddress = QBluetoothAddress(bdaddr).toString();
463 OrgFreedesktopDBusObjectManagerInterface manager(
464 QStringLiteral(
"org.bluez"), QStringLiteral(
"/"), QDBusConnection::systemBus());
465 QDBusPendingReply<ManagedObjectList> reply = manager.GetManagedObjects();
466 reply.waitForFinished();
471 for (ManagedObjectList::const_iterator it = managedObjectList.constBegin();
472 it != managedObjectList.constEnd(); ++it) {
473 const InterfaceList &ifaceList = it.value();
475 for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd();
477 const QString &iface = jt.key();
478 const QVariantMap &ifaceValues = jt.value();
480 if (iface == QStringLiteral(
"org.bluez.Device1")) {
481 if (ifaceValues.value(QStringLiteral(
"Address")).toString() == peerAddress)
482 return ifaceValues.value(QStringLiteral(
"Alias")).toString();
491 if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
493 socklen_t addrLength =
sizeof(addr);
495 if (::getpeername(socket,
reinterpret_cast<sockaddr *>(&addr), &addrLength) == 0)
496 return QBluetoothAddress(convertAddress(addr.rc_bdaddr.b));
497 }
else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
499 socklen_t addrLength =
sizeof(addr);
501 if (::getpeername(socket,
reinterpret_cast<sockaddr *>(&addr), &addrLength) == 0)
502 return QBluetoothAddress(convertAddress(addr.l2_bdaddr.b));
505 return QBluetoothAddress();
510 if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
512 socklen_t addrLength =
sizeof(addr);
514 if (::getpeername(socket,
reinterpret_cast<sockaddr *>(&addr), &addrLength) == 0)
515 return addr.rc_channel;
516 }
else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
518 socklen_t addrLength =
sizeof(addr);
520 if (::getpeername(socket,
reinterpret_cast<sockaddr *>(&addr), &addrLength) == 0)
529 Q_Q(QBluetoothSocket);
531 if (state != QBluetoothSocket::SocketState::ConnectedState) {
532 errorString = QBluetoothSocket::tr(
"Cannot write while not connected");
533 q->setSocketError(QBluetoothSocket::SocketError::OperationError);
537 if (q->openMode() & QIODevice::Unbuffered) {
538 auto sz = ::qt_safe_write(socket, data, maxSize);
545 errorString = QBluetoothSocket::tr(
"Network Error: %1").arg(qt_error_string(errno));
546 q->setSocketError(QBluetoothSocket::SocketError::NetworkError);
551 emit q->bytesWritten(sz);
557 if(!connectWriteNotifier)
560 if(txBuffer.size() == 0) {
561 connectWriteNotifier->setEnabled(
true);
562 QMetaObject::invokeMethod(
this,
"_q_writeNotify", Qt::QueuedConnection);
565 char *txbuf = txBuffer.reserve(maxSize);
566 memcpy(txbuf, data, maxSize);
574 Q_Q(QBluetoothSocket);
576 if (state != QBluetoothSocket::SocketState::ConnectedState) {
577 errorString = QBluetoothSocket::tr(
"Cannot read while not connected");
578 q->setSocketError(QBluetoothSocket::SocketError::OperationError);
582 if (!rxBuffer.isEmpty())
583 return rxBuffer.read(data, maxSize);
592 if (txBuffer.size() > 0)
593 connectWriteNotifier->setEnabled(
true);
599 QBluetoothSocket::SocketState socketState, QBluetoothSocket::OpenMode openMode)
601 Q_Q(QBluetoothSocket);
603 readNotifier =
nullptr;
604 delete connectWriteNotifier;
605 connectWriteNotifier =
nullptr;
607 socketType = socketType_;
611 socket = socketDescriptor;
614 int flags = fcntl(socket, F_GETFL, 0);
615 if (!(flags & O_NONBLOCK))
616 fcntl(socket, F_SETFL, flags | O_NONBLOCK);
618 readNotifier =
new QSocketNotifier(socket, QSocketNotifier::Read);
619 QObject::connect(readNotifier, SIGNAL(activated(QSocketDescriptor)),
this, SLOT(_q_readNotify()));
620 connectWriteNotifier =
new QSocketNotifier(socket, QSocketNotifier::Write, q);
621 QObject::connect(connectWriteNotifier, SIGNAL(activated(QSocketDescriptor)),
this, SLOT(_q_writeNotify()));
623 q->setOpenMode(openMode);
624 q->setSocketState(socketState);
631 return rxBuffer.size();
636 return txBuffer.size();
641 return rxBuffer.canReadLine();
646#include "moc_qbluetoothsocket_bluez_p.cpp"
#define QPRIVATELINEARBUFFER_BUFFERSIZE
QMap< QDBusObjectPath, InterfaceList > ManagedObjectList
#define BT_SECURITY_MEDIUM
QString localName() const override
qint64 writeData(const char *data, qint64 maxSize) override
quint16 localPort() const override
qint64 bytesAvailable() const override
QBluetoothAddress peerAddress() const override
qint64 readData(char *data, qint64 maxSize) override
QString peerName() const override
void connectToService(const QBluetoothServiceInfo &service, QIODevice::OpenMode openMode) override
bool canReadLine() const override
~QBluetoothSocketPrivateBluez() override
QBluetoothAddress localAddress() const override
void connectToService(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode) override
qint64 bytesToWrite() const override
bool setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType, QBluetoothSocket::SocketState socketState=QBluetoothSocket::SocketState::ConnectedState, QBluetoothSocket::OpenMode openMode=QBluetoothSocket::ReadWrite) override
QBluetoothSocketPrivateBluez()
void connectToServiceHelper(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode) override
quint16 peerPort() const override