summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlex Blasche <alexander.blasche@qt.io>2019-04-09 09:56:54 +0200
committerAlex Blasche <alexander.blasche@qt.io>2019-04-10 06:29:40 +0000
commit17e2ac555af234d03144cad72d70a29c62357a38 (patch)
tree9f1c0922727e39e8734413a4fe3076b8d4193a98 /src
parent6257ca589f435ea9b4f73067098ab54bbc873faf (diff)
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>
Diffstat (limited to 'src')
-rw-r--r--src/bluetooth/qbluetoothsocket.cpp7
-rw-r--r--src/bluetooth/qbluetoothsocket_android.cpp28
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;