summaryrefslogtreecommitdiffstats
path: root/src/bluetooth/qlowenergycontroller_bluezdbus.cpp
diff options
context:
space:
mode:
authorTarja Sundqvist <tarja.sundqvist@qt.io>2023-04-24 10:13:37 +0300
committerTarja Sundqvist <tarja.sundqvist@qt.io>2023-04-24 10:13:37 +0300
commitda6113cb52beb5731d8c95ecbfc375936f59def2 (patch)
tree81a617b98e6e04d660fb2e75aae942a49ed7c2a1 /src/bluetooth/qlowenergycontroller_bluezdbus.cpp
parent3dcb548bd6fe4aa488ca0bac95e65a7a366c3eca (diff)
parentca96a42035255b4355e4d8ddba7f5da7b9006577 (diff)
Merge remote-tracking branch 'origin/tqtc/lts-5.15.10' into tqtc/lts-5.15-opensource
Diffstat (limited to 'src/bluetooth/qlowenergycontroller_bluezdbus.cpp')
-rw-r--r--src/bluetooth/qlowenergycontroller_bluezdbus.cpp64
1 files changed, 53 insertions, 11 deletions
diff --git a/src/bluetooth/qlowenergycontroller_bluezdbus.cpp b/src/bluetooth/qlowenergycontroller_bluezdbus.cpp
index c159e97e..2dbb28ae 100644
--- a/src/bluetooth/qlowenergycontroller_bluezdbus.cpp
+++ b/src/bluetooth/qlowenergycontroller_bluezdbus.cpp
@@ -415,7 +415,8 @@ void QLowEnergyControllerPrivateBluezDBus::discoverServices()
Q_Q(QLowEnergyController);
auto setupServicePrivate = [&, q](
- QLowEnergyService::ServiceType type, const QBluetoothUuid &uuid, const QString &path){
+ QLowEnergyService::ServiceType type, const QBluetoothUuid &uuid,
+ const QString &path, const bool battery1Interface = false){
QSharedPointer<QLowEnergyServicePrivate> priv = QSharedPointer<QLowEnergyServicePrivate>::create();
priv->uuid = uuid;
priv->type = type; // we make a guess we cannot validate
@@ -423,8 +424,11 @@ void QLowEnergyControllerPrivateBluezDBus::discoverServices()
GattService serviceContainer;
serviceContainer.servicePath = path;
- if (uuid == QBluetoothUuid::BatteryService)
+
+ if (battery1Interface) {
+ qCDebug(QT_BT_BLUEZ) << "Using Battery1 interface to emulate generic interface";
serviceContainer.hasBatteryService = true;
+ }
serviceList.insert(priv->uuid, priv);
dbusServices.insert(priv->uuid, serviceContainer);
@@ -434,25 +438,50 @@ void QLowEnergyControllerPrivateBluezDBus::discoverServices()
const ManagedObjectList managedObjectList = reply.value();
const QString servicePathPrefix = device->path().append(QStringLiteral("/service"));
+
+ // The Bluez battery service (0x180f) support has evolved over time and needs additional logic:
+ //
+ // * Until 5.47 Bluez exposes battery services via generic interface (GattService1) only
+ // * Between 5.48..5.54 Bluez exposes battery service as a dedicated 'Battery1' interface only
+ // * From 5.55 Bluez exposes both the generic service as well as the dedicated 'Battery1'
+ //
+ // To hide the difference from users the 'Battery1' interface will be used to emulate the
+ // generic interface. Importantly also the GattService1 interface, if available, is available
+ // early whereas the Battery1 interface may be available only later (generated too late for
+ // this service discovery's purposes)
+ //
+ // The precedence for battery service here is as follows:
+ // * If available via GattService1, use that and ignore possible Battery1 interface
+ // * If Battery1 interface is available or the 'org.bluez.Device1' lists battery service
+ // amongst list of available services, mark the service such that the code will later
+ // look up the Battery1 service details
+ bool gattBatteryService{false};
+ QString batteryServicePath;
+
for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) {
const InterfaceList &ifaceList = it.value();
if (!it.key().path().startsWith(device->path()))
continue;
- // Since Bluez 5.48 battery services (0x180f) are no longer exposed
- // as generic services under servicePathPrefix.
- // A dedicated org.bluez.Battery1 interface is exposed. Here we are going to revert
- // Bettery1 to the generic pattern.
if (it.key().path() == device->path()) {
- // find Battery1 service
+ // See if the battery service is available or is assumed to be available later
for (InterfaceList::const_iterator battIter = ifaceList.constBegin(); battIter != ifaceList.constEnd(); ++battIter) {
const QString &iface = battIter.key();
if (iface == QStringLiteral("org.bluez.Battery1")) {
- qCDebug(QT_BT_BLUEZ) << "Found dedicated Battery service -> emulating generic btle access";
- setupServicePrivate(QLowEnergyService::PrimaryService,
- QBluetoothUuid::BatteryService,
- it.key().path());
+ qCDebug(QT_BT_BLUEZ) << "Dedicated Battery1 service available";
+ batteryServicePath = it.key().path();
+ break;
+ } else if (iface == QStringLiteral("org.bluez.Device1")) {
+ for (auto const& uuid :
+ battIter.value()[QStringLiteral("UUIDs")].toStringList()) {
+ if (QBluetoothUuid(uuid) ==
+ QBluetoothUuid::ServiceClassUuid::BatteryService) {
+ qCDebug(QT_BT_BLUEZ) << "Battery service listed as available service";
+ batteryServicePath = it.key().path();
+ break;
+ }
+ }
}
}
continue;
@@ -468,6 +497,11 @@ void QLowEnergyControllerPrivateBluezDBus::discoverServices()
QScopedPointer<OrgBluezGattService1Interface> service(new OrgBluezGattService1Interface(
QStringLiteral("org.bluez"),it.key().path(),
QDBusConnection::systemBus(), this));
+ if (QBluetoothUuid(service->uUID()) ==
+ QBluetoothUuid::ServiceClassUuid::BatteryService) {
+ qCDebug(QT_BT_BLUEZ) << "Using battery service via GattService1 interface";
+ gattBatteryService = true;
+ }
setupServicePrivate(service->primary()
? QLowEnergyService::PrimaryService
: QLowEnergyService::IncludedService,
@@ -476,6 +510,12 @@ void QLowEnergyControllerPrivateBluezDBus::discoverServices()
}
}
+ if (!gattBatteryService && !batteryServicePath.isEmpty()) {
+ setupServicePrivate(QLowEnergyService::PrimaryService,
+ QBluetoothUuid::ServiceClassUuid::BatteryService,
+ batteryServicePath, true);
+ }
+
setState(QLowEnergyController::DiscoveredState);
emit q->discoveryFinished();
}
@@ -1305,3 +1345,5 @@ QLowEnergyService *QLowEnergyControllerPrivateBluezDBus::addServiceHelper(
}
QT_END_NAMESPACE
+
+#include "moc_qlowenergycontroller_bluezdbus_p.cpp"