diff options
author | Alex Blasche <alexander.blasche@qt.io> | 2017-05-18 09:08:29 +0200 |
---|---|---|
committer | Alex Blasche <alexander.blasche@qt.io> | 2017-05-29 10:24:32 +0000 |
commit | 8692ff9d1c32bcc56e4c8c0c9f07ee2eb1a2681d (patch) | |
tree | 37d3cbf7c137522865c6d76d29250e81d44de181 /src/bluetooth/qlowenergycontroller_bluez.cpp | |
parent | ca248e3667f52f951bdd60d923b25a6b8fb4296d (diff) |
Avoid bluetoothd and QtBluetooth collision when connecting to BTLE dev
BlueZ's improving support for BTLE creates a new collision when
attenpting to connect to remote BTLE devices. There can only ever be
one connection.
This patch ensures that when QtBluetooth attempts to connect we do
not have a pending BTLE connection. This could have been caused via
other QtBLuetooth based processes or applications
such as bluetoothctl or bluetoothd in general. If a connection
is pending we close the connection external to the current QtBLuetooth
instance.
This is not an ideal situation as several processes can potentially
fight over btle access. The long term solution is a port of QtBluetooth
to BlueZ's new DBus API.
Task-number: QTBUG-55150
Change-Id: I96b30ae180d1348027e8f9f09c997f44409dfc48
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
Diffstat (limited to 'src/bluetooth/qlowenergycontroller_bluez.cpp')
-rw-r--r-- | src/bluetooth/qlowenergycontroller_bluez.cpp | 55 |
1 files changed, 54 insertions, 1 deletions
diff --git a/src/bluetooth/qlowenergycontroller_bluez.cpp b/src/bluetooth/qlowenergycontroller_bluez.cpp index 40744670..1649fe8c 100644 --- a/src/bluetooth/qlowenergycontroller_bluez.cpp +++ b/src/bluetooth/qlowenergycontroller_bluez.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Copyright (C) 2016 Javier S. Pedro <maemo@javispedro.com> ** Contact: https://www.qt.io/licensing/ ** @@ -44,6 +44,8 @@ #include "qleadvertiser_p.h" #include "bluez/bluez_data_p.h" #include "bluez/hcimanager_p.h" +#include "bluez/remotedevicemanager_p.h" +#include "bluez/bluez5_helper_p.h" #include <QtCore/QFileInfo> #include <QtCore/QLoggingCategory> @@ -530,13 +532,64 @@ void QLowEnergyControllerPrivate::connectToDevice() // 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 + // this check is not performed for BlueZ 4 based platforms as bluetoothd + // does not support BTLE management + + if (!isBluez5()) { + establishL2cpClientSocket(); + return; + } + QVector<quint16> activeHandles = hciManager->activeLowEnergyConnections(); if (!activeHandles.isEmpty()) { qCWarning(QT_BT_BLUEZ) << "Cannot connect due to pending active LE connections"; + + if (!device1Manager) { + device1Manager = new RemoteDeviceManager(localAdapter, this); + connect(device1Manager, &RemoteDeviceManager::finished, + this, &QLowEnergyControllerPrivate::activeConnectionTerminationDone); + } + + QVector<QBluetoothAddress> connectedAddresses; + for (const auto handle: activeHandles) { + const QBluetoothAddress addr = hciManager->addressForConnectionHandle(handle); + if (!addr.isNull()) + connectedAddresses.push_back(addr); + } + device1Manager->scheduleJob(RemoteDeviceManager::JobType::JobDisconnectDevice, connectedAddresses); + } else { + establishL2cpClientSocket(); + } +} + +/*! + * Handles outcome of attempts to close external connections. + */ +void QLowEnergyControllerPrivate::activeConnectionTerminationDone() +{ + if (!device1Manager) + return; + + qCDebug(QT_BT_BLUEZ) << "RemoteDeviceManager finished attempting" + << "to close external connections"; + + QVector<quint16> activeHandles = hciManager->activeLowEnergyConnections(); + if (!activeHandles.isEmpty()) { + qCWarning(QT_BT_BLUEZ) << "Cannot close pending external BTLE connections. Aborting connect attempt"; setError(QLowEnergyController::ConnectionError); setState(QLowEnergyController::UnconnectedState); return; + } else { + establishL2cpClientSocket(); } +} + +/*! + * Establishes the L2CP client socket. + */ +void QLowEnergyControllerPrivate::establishL2cpClientSocket() +{ + //we are already in Connecting state l2cpSocket = new QBluetoothSocket(QBluetoothServiceInfo::L2capProtocol, this); connect(l2cpSocket, SIGNAL(connected()), this, SLOT(l2cpConnected())); |