summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuha Vuolle <juha.vuolle@insta.fi>2022-10-27 13:28:53 +0300
committerJuha Vuolle <juha.vuolle@insta.fi>2022-12-07 11:47:19 +0200
commitb8a3a97ea9324b8501ef341b51d776c3ac8dbbd3 (patch)
treee2775c2dade092887e61cfc5763158a60a9af1e9
parent6d1b1d56217fa7e901847a600ad858faa151af96 (diff)
downloadqtconnectivity-b8a3a97ea9324b8501ef341b51d776c3ac8dbbd3.tar.gz
Add Bluez DBus peripheral role selection support
A preparatory commit for adding Bluez DBus peripheral role support. Fixes: QTBUG-107508 Change-Id: Ifa2b12df9856011048a9bc311e5da96275700f5e Reviewed-by: Ivan Solovev <ivan.solovev@qt.io> Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
-rw-r--r--src/bluetooth/bluez/bluez5_helper.cpp35
-rw-r--r--src/bluetooth/bluez/bluez5_helper_p.h2
-rw-r--r--src/bluetooth/qlowenergycontroller.cpp33
3 files changed, 64 insertions, 6 deletions
diff --git a/src/bluetooth/bluez/bluez5_helper.cpp b/src/bluetooth/bluez/bluez5_helper.cpp
index 5f252026..e2e34669 100644
--- a/src/bluetooth/bluez/bluez5_helper.cpp
+++ b/src/bluetooth/bluez/bluez5_helper.cpp
@@ -512,6 +512,41 @@ QString findAdapterForAddress(const QBluetoothAddress &wantedAddress, bool *ok =
}
/*
+
+ Checks the presence of peripheral interface
+
+*/
+
+bool peripheralInterfaceAvailable(const QBluetoothAddress &localAddress)
+{
+ // First find the object path to the desired adapter
+ bool ok = false;
+ const QString hostAdapterPath = findAdapterForAddress(localAddress, &ok);
+ if (!ok || hostAdapterPath.isEmpty())
+ return false;
+
+ // Then check if that adapter provides peripheral dbus interface
+ OrgFreedesktopDBusObjectManagerInterface manager(QStringLiteral("org.bluez"),
+ QStringLiteral("/"),
+ QDBusConnection::systemBus());
+ QDBusPendingReply<ManagedObjectList> reply = manager.GetManagedObjects();
+ reply.waitForFinished();
+ if (reply.isError())
+ return false;
+
+ using namespace Qt::StringLiterals;
+ // For example /org/bluez/hci0 contains org.bluezLEAdvertisingManager1
+ const bool peripheralSupported = reply.value()
+ .value(QDBusObjectPath(hostAdapterPath))
+ .contains("org.bluez.LEAdvertisingManager1"_L1);
+
+ qCDebug(QT_BT_BLUEZ) << "Peripheral role"
+ << (peripheralSupported ? "" : "not")
+ << "supported on" << hostAdapterPath;
+ return peripheralSupported;
+}
+
+/*
Removes every character that cannot be used in QDbusObjectPath
See QDbusUtil::isValidObjectPath(QString) for more details.
diff --git a/src/bluetooth/bluez/bluez5_helper_p.h b/src/bluetooth/bluez/bluez5_helper_p.h
index 1904da90..2d23ba92 100644
--- a/src/bluetooth/bluez/bluez5_helper_p.h
+++ b/src/bluetooth/bluez/bluez5_helper_p.h
@@ -43,6 +43,8 @@ QString sanitizeNameForDBus(const QString& text);
QString findAdapterForAddress(const QBluetoothAddress &wantedAddress, bool *ok);
+bool peripheralInterfaceAvailable(const QBluetoothAddress &localAddress);
+
class QtBluezDiscoveryManagerPrivate;
class QtBluezDiscoveryManager : public QObject
{
diff --git a/src/bluetooth/qlowenergycontroller.cpp b/src/bluetooth/qlowenergycontroller.cpp
index 4e7c8e95..92e93f6d 100644
--- a/src/bluetooth/qlowenergycontroller.cpp
+++ b/src/bluetooth/qlowenergycontroller.cpp
@@ -301,30 +301,51 @@ void registerQLowEnergyControllerMetaType()
}
}
-static QLowEnergyControllerPrivate *privateController(QLowEnergyController::Role role)
+static QLowEnergyControllerPrivate *privateController(
+ QLowEnergyController::Role role,
+ const QBluetoothAddress& localDevice = QBluetoothAddress{})
{
#if QT_CONFIG(bluez) && !defined(QT_BLUEZ_NO_BTLE)
- // The new DBUS implementation only supports Central role for now
- // For Peripheral role support see QTBUG-66909
+ // Central role
+ // The minimum Bluez DBus version for central role is 5.42, otherwise we
+ // fall back to kernel ATT backend. Application can also force the choice
+ // with an environment variable (see bluetoothdVersion())
+ //
+ // Peripheral role
+ // For the dbus peripheral backend we check the presence of the required DBus APIs, and in
+ // addition the application needs to opt-in to the DBus peripheral role by setting the
+ // environment variable. Otherwise we fall back to the kernel ATT backend
+ //
+ // ### Qt 7 consider removing the non-dbus bluez (kernel ATT) support
if (role == QLowEnergyController::CentralRole
&& bluetoothdVersion() >= QVersionNumber(5, 42)) {
- qCWarning(QT_BT) << "Using BlueZ LE DBus API";
+ qCDebug(QT_BT) << "Using BlueZ LE DBus API for central";
+ return new QLowEnergyControllerPrivateBluezDBus();
+ } else if (role == QLowEnergyController::PeripheralRole
+ && qEnvironmentVariableIsSet("BLUETOOTH_USE_DBUS_PERIPHERAL")
+ && peripheralInterfaceAvailable(localDevice)) {
+ qCDebug(QT_BT) << "Using BlueZ LE DBus API for peripheral";
return new QLowEnergyControllerPrivateBluezDBus();
} else {
- qCWarning(QT_BT) << "Using BlueZ kernel ATT interface";
+ qCDebug(QT_BT) << "Using BlueZ kernel ATT interface for"
+ << (role == QLowEnergyController::CentralRole ? "central" : "peripheral");
return new QLowEnergyControllerPrivateBluez();
}
#elif defined(QT_ANDROID_BLUETOOTH)
Q_UNUSED(role);
+ Q_UNUSED(localDevice);
return new QLowEnergyControllerPrivateAndroid();
#elif defined(QT_WINRT_BLUETOOTH)
Q_UNUSED(role);
+ Q_UNUSED(localDevice);
return new QLowEnergyControllerPrivateWinRT();
#elif defined(Q_OS_DARWIN)
Q_UNUSED(role);
+ Q_UNUSED(localDevice);
return new QLowEnergyControllerPrivateDarwin();
#else
Q_UNUSED(role);
+ Q_UNUSED(localDevice);
return new QLowEnergyControllerPrivateCommon();
#endif
}
@@ -450,7 +471,7 @@ QLowEnergyController *QLowEnergyController::createPeripheral(const QBluetoothAdd
QLowEnergyController::QLowEnergyController(const QBluetoothAddress &localDevice, QObject *parent)
: QObject(parent)
{
- d_ptr = privateController(PeripheralRole);
+ d_ptr = privateController(PeripheralRole, localDevice);
Q_D(QLowEnergyController);
d->q_ptr = this;