summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/bluetooth/bluez/bluez_data_p.h4
-rw-r--r--src/bluetooth/bluez/hcimanager.cpp44
-rw-r--r--src/bluetooth/bluez/hcimanager_p.h4
-rw-r--r--src/bluetooth/qlowenergycontroller_bluez.cpp11
4 files changed, 63 insertions, 0 deletions
diff --git a/src/bluetooth/bluez/bluez_data_p.h b/src/bluetooth/bluez/bluez_data_p.h
index 8c2dc43e..25edc661 100644
--- a/src/bluetooth/bluez/bluez_data_p.h
+++ b/src/bluetooth/bluez/bluez_data_p.h
@@ -99,6 +99,10 @@ struct bt_security {
#define BDADDR_LE_PUBLIC 0x01
#define BDADDR_LE_RANDOM 0x02
+#define SCO_LINK 0x00
+#define ACL_LINK 0x01
+#define ESCO_LINK 0x02
+#define LE_LINK 0x80 // based on hcitool.c -> no fixed constant available
/* Byte order conversions */
#if __BYTE_ORDER == __LITTLE_ENDIAN
diff --git a/src/bluetooth/bluez/hcimanager.cpp b/src/bluetooth/bluez/hcimanager.cpp
index 93bf941b..c524117c 100644
--- a/src/bluetooth/bluez/hcimanager.cpp
+++ b/src/bluetooth/bluez/hcimanager.cpp
@@ -288,6 +288,50 @@ QBluetoothAddress HciManager::addressForConnectionHandle(quint16 handle) const
return QBluetoothAddress();
}
+QVector<quint16> HciManager::activeLowEnergyConnections() const
+{
+ if (!isValid())
+ return QVector<quint16>();
+
+ hci_conn_info *info;
+ hci_conn_list_req *infoList;
+
+ const int maxNoOfConnections = 20;
+ infoList = (hci_conn_list_req *)
+ malloc(sizeof(hci_conn_list_req) + maxNoOfConnections * sizeof(hci_conn_info));
+
+ if (!infoList)
+ return QVector<quint16>();
+
+ QScopedPointer<hci_conn_list_req, QScopedPointerPodDeleter> p(infoList);
+ p->conn_num = maxNoOfConnections;
+ p->dev_id = hciDev;
+ info = p->conn_info;
+
+ if (ioctl(hciSocket, HCIGETCONNLIST, (void *) infoList) < 0) {
+ qCWarning(QT_BT_BLUEZ) << "Cannot retrieve connection list";
+ return QVector<quint16>();
+ }
+
+ QVector<quint16> activeLowEnergyHandles;
+ for (int i = 0; i < infoList->conn_num; i++) {
+ switch (info[i].type) {
+ case SCO_LINK:
+ case ACL_LINK:
+ case ESCO_LINK:
+ continue;
+ case LE_LINK:
+ activeLowEnergyHandles.append(info[i].handle);
+ break;
+ default:
+ qCWarning(QT_BT_BLUEZ) << "Unknown active connection type:" << hex << info[i].type;
+ break;
+ }
+ }
+
+ return activeLowEnergyHandles;
+}
+
quint16 forceIntervalIntoRange(double connectionInterval)
{
return qMin<double>(qMax<double>(7.5, connectionInterval), 4000) / 1.25;
diff --git a/src/bluetooth/bluez/hcimanager_p.h b/src/bluetooth/bluez/hcimanager_p.h
index 3bae92e5..3127a747 100644
--- a/src/bluetooth/bluez/hcimanager_p.h
+++ b/src/bluetooth/bluez/hcimanager_p.h
@@ -55,6 +55,7 @@
#include <QtCore/QSet>
#include <QtCore/QSocketNotifier>
#include <QtBluetooth/QBluetoothAddress>
+#include <QVector>
#include "bluez/bluez_data_p.h"
QT_BEGIN_NAMESPACE
@@ -82,6 +83,9 @@ public:
void stopEvents();
QBluetoothAddress addressForConnectionHandle(quint16 handle) const;
+ // active connections
+ QVector<quint16> activeLowEnergyConnections() const;
+
bool sendConnectionUpdateCommand(quint16 handle, const QLowEnergyConnectionParameters &params);
bool sendConnectionParameterUpdateRequest(quint16 handle,
const QLowEnergyConnectionParameters &params);
diff --git a/src/bluetooth/qlowenergycontroller_bluez.cpp b/src/bluetooth/qlowenergycontroller_bluez.cpp
index 3873664a..40744670 100644
--- a/src/bluetooth/qlowenergycontroller_bluez.cpp
+++ b/src/bluetooth/qlowenergycontroller_bluez.cpp
@@ -527,6 +527,17 @@ void QLowEnergyControllerPrivate::connectToDevice()
if (l2cpSocket)
delete l2cpSocket;
+ // check for active running connections
+ // BlueZ 5.37+ (maybe even earlier versions) can have pending BTLE connections
+ // Only one active L2CP socket to CID 0x4 possible at a time
+ QVector<quint16> activeHandles = hciManager->activeLowEnergyConnections();
+ if (!activeHandles.isEmpty()) {
+ qCWarning(QT_BT_BLUEZ) << "Cannot connect due to pending active LE connections";
+ setError(QLowEnergyController::ConnectionError);
+ setState(QLowEnergyController::UnconnectedState);
+ return;
+ }
+
l2cpSocket = new QBluetoothSocket(QBluetoothServiceInfo::L2capProtocol, this);
connect(l2cpSocket, SIGNAL(connected()), this, SLOT(l2cpConnected()));
connect(l2cpSocket, SIGNAL(disconnected()), this, SLOT(l2cpDisconnected()));