diff options
author | Alex Blasche <alexander.blasche@qt.io> | 2019-04-09 09:56:54 +0200 |
---|---|---|
committer | Alex Blasche <alexander.blasche@qt.io> | 2019-04-10 06:29:40 +0000 |
commit | 17e2ac555af234d03144cad72d70a29c62357a38 (patch) | |
tree | 9f1c0922727e39e8734413a4fe3076b8d4193a98 | |
parent | 6257ca589f435ea9b4f73067098ab54bbc873faf (diff) | |
download | qtconnectivity-17e2ac555af234d03144cad72d70a29c62357a38.tar.gz |
Android: Increase chance of establishing serial connection w/o SPP uuid
SDP discovery on Android only returns a flat list of uuids. It mixes
service class uuid and service uuids. Furthermore it is unable to detect
whether a serial connection uses rfcomm or l2cp as base protocol. The
last limitation is the fact that serial sockets can only be established
using rfcomm (no l2cp).
This poses a serious challenge because there is no way to say whether
a given custom service uuid is indeed an SPP based service or whether
it uses rfcomm. The only way to know for sure is to connect and check
whether it succeeds.
This also means QBluetoothServiceInfo instances returned by
QBluetoothServiceDiscoveryAgent may or may not mark a serial service
with SPP uuid or rfcomm protocol tag. Currently, it guess that that a
custom uuid together with SPP uuid implies an rfcomm setup. If the SPP
uuid was not found, rfcomm is never set (but is a requirement for
QBluetoothSocket). This patch makes QBluetoothSocket on Android a bit
more forgiving by assuming every given QBluetoothServiceInfo instance
requires rfcomm. After all that's the only supported protocol on Android.
Fixes: QTBUG-75035
Change-Id: I498ac5acd2a394b198a113fd23d750bbf17a7f7b
Reviewed-by: BogDan Vatra <bogdan@kdab.com>
-rw-r--r-- | src/bluetooth/qbluetoothsocket.cpp | 7 | ||||
-rw-r--r-- | src/bluetooth/qbluetoothsocket_android.cpp | 28 |
2 files changed, 32 insertions, 3 deletions
diff --git a/src/bluetooth/qbluetoothsocket.cpp b/src/bluetooth/qbluetoothsocket.cpp index eecb1401..daa589bb 100644 --- a/src/bluetooth/qbluetoothsocket.cpp +++ b/src/bluetooth/qbluetoothsocket.cpp @@ -360,8 +360,8 @@ qint64 QBluetoothSocket::bytesToWrite() const /*! Attempts to connect to the service described by \a service. - The socket is opened in the given \a openMode. The \l socketType() may change - depending on the protocol required by \a service. + The socket is opened in the given \a openMode. The \l socketType() is ignored + if \a service specifies a differing \l QBluetoothServiceInfo::socketProtocol(). The socket first enters ConnectingState and attempts to connect to the device providing \a service. If a connection is established, QBluetoothSocket enters ConnectedState and @@ -372,6 +372,9 @@ qint64 QBluetoothSocket::bytesToWrite() const Note that most platforms require a pairing prior to connecting to the remote device. Otherwise the connection process may fail. + On Android, only RFCOMM connections are possible. This function ignores any socket protocol indicator + and assumes RFCOMM. + \sa state(), disconnectFromService() */ void QBluetoothSocket::connectToService(const QBluetoothServiceInfo &service, OpenMode openMode) diff --git a/src/bluetooth/qbluetoothsocket_android.cpp b/src/bluetooth/qbluetoothsocket_android.cpp index 46bd4a23..85da325b 100644 --- a/src/bluetooth/qbluetoothsocket_android.cpp +++ b/src/bluetooth/qbluetoothsocket_android.cpp @@ -494,7 +494,33 @@ void QBluetoothSocketPrivateAndroid::connectToService( return; } - if (!ensureNativeSocket(service.socketProtocol())) { + // Workaround for QTBUG-75035 + /* Not all Android devices publish or discover the SPP uuid for serial services. + * Also, Android does not permit the detection of the protocol used by a serial + * Bluetooth connection. + * + * Therefore, QBluetoothServiceDiscoveryAgentPrivate::populateDiscoveredServices() + * may have to guess what protocol a potential custom uuid uses. The guessing works + * reasonably well as long as the SDP discovery finds the SPP uuid. Otherwise + * the SPP and rfcomm protocol info is missing in \a service. + * + * Android only supports RFCOMM (no L2CP). We assume (in favor of user experience) + * that a non-RFCOMM protocol implies a missing SPP uuid during discovery but the user + * still wanting to connect with the given \a service instance. + */ + + auto protocol = service.socketProtocol(); + switch (protocol) { + case QBluetoothServiceInfo::L2capProtocol: + case QBluetoothServiceInfo::UnknownProtocol: + qCWarning(QT_BT_ANDROID) << "Changing socket protocol to RFCOMM"; + protocol = QBluetoothServiceInfo::RfcommProtocol; + break; + case QBluetoothServiceInfo::RfcommProtocol: + break; + } + + if (!ensureNativeSocket(protocol)) { errorString = QBluetoothSocket::tr("Socket type not supported"); q->setSocketError(QBluetoothSocket::UnsupportedProtocolError); return; |