5#include "bluez/adapter1_bluez5_p.h"
6#include "bluez/bluez5_helper_p.h"
7#include "bluez/device1_bluez5_p.h"
8#include "bluez/gattservice1_p.h"
9#include "bluez/gattchar1_p.h"
10#include "bluez/gattdesc1_p.h"
11#include "bluez/battery1_p.h"
12#include "bluez/objectmanager_p.h"
13#include "bluez/properties_p.h"
14#include "bluez/bluezperipheralapplication_p.h"
15#include "bluez/bluezperipheralconnectionmanager_p.h"
19Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ)
21using namespace QtBluetoothPrivate;
24 const QString &adapterPathWithPeripheralSupport)
26 adapterPathWithPeripheralSupport(adapterPathWithPeripheralSupport)
32 if (state != QLowEnergyController::UnconnectedState) {
33 qCWarning(QT_BT_BLUEZ) <<
"Low Energy Controller is not Unconnected when deleted."
34 <<
"Deleted in state:" << state;
40 if (role == QLowEnergyController::PeripheralRole) {
41 Q_ASSERT(!adapterPathWithPeripheralSupport.isEmpty());
43 peripheralApplication =
new QtBluezPeripheralApplication(adapterPathWithPeripheralSupport,
46 QObject::connect(peripheralApplication, &QtBluezPeripheralApplication::errorOccurred,
this,
47 &QLowEnergyControllerPrivateBluezDBus::handlePeripheralApplicationError);
49 QObject::connect(peripheralApplication, &QtBluezPeripheralApplication::registered,
this,
50 &QLowEnergyControllerPrivateBluezDBus::handlePeripheralApplicationRegistered);
52 QObject::connect(peripheralApplication,
53 &QtBluezPeripheralApplication::characteristicValueUpdatedByRemote,
this,
54 &QLowEnergyControllerPrivateBluezDBus::handlePeripheralCharacteristicValueUpdate);
56 QObject::connect(peripheralApplication,
57 &QtBluezPeripheralApplication::descriptorValueUpdatedByRemote,
this,
58 &QLowEnergyControllerPrivateBluezDBus::handlePeripheralDescriptorValueUpdate);
60 peripheralConnectionManager =
61 new QtBluezPeripheralConnectionManager(localAdapter,
this);
63 QObject::connect(peripheralApplication,
64 &QtBluezPeripheralApplication::remoteDeviceAccessEvent,
65 peripheralConnectionManager,
66 &QtBluezPeripheralConnectionManager::remoteDeviceAccessEvent);
68 QObject::connect(peripheralConnectionManager,
69 &QtBluezPeripheralConnectionManager::connectivityStateChanged,
this,
70 &QLowEnergyControllerPrivateBluezDBus::handlePeripheralConnectivityChanged);
72 QObject::connect(peripheralConnectionManager,
73 &QtBluezPeripheralConnectionManager::remoteDeviceChanged,
this,
74 &QLowEnergyControllerPrivateBluezDBus::handlePeripheralRemoteDeviceChanged);
79 const QString &interface,
const QVariantMap &changedProperties,
82 if (interface == QStringLiteral(
"org.bluez.Device1")) {
83 qCDebug(QT_BT_BLUEZ) <<
"######" << interface << changedProperties;
84 if (changedProperties.contains(QStringLiteral(
"ServicesResolved"))) {
89 bool isResolved = changedProperties.value(QStringLiteral(
"ServicesResolved")).toBool();
91 setState(QLowEnergyController::ConnectedState);
92 pendingConnect =
false;
93 disconnectSignalRequired =
true;
94 Q_Q(QLowEnergyController);
100 if (changedProperties.contains(QStringLiteral(
"Connected"))) {
101 bool isConnected = changedProperties.value(QStringLiteral(
"Connected")).toBool();
104 case QLowEnergyController::ConnectingState:
105 case QLowEnergyController::ConnectedState:
106 case QLowEnergyController::DiscoveringState:
107 case QLowEnergyController::DiscoveredState:
108 case QLowEnergyController::ClosingState:
110 QLowEnergyController::Error newError = QLowEnergyController::NoError;
112 newError = QLowEnergyController::ConnectionError;
114 executeClose(newError);
117 case QLowEnergyController::AdvertisingState:
118 case QLowEnergyController::UnconnectedState:
125 if (changedProperties.contains(QStringLiteral(
"UUIDs"))) {
126 const QStringList newUuidStringList = changedProperties.value(QStringLiteral(
"UUIDs")).toStringList();
127 QList<QBluetoothUuid> newUuidList;
128 for (
const QString &uuidString : newUuidStringList)
129 newUuidList.append(QBluetoothUuid(uuidString));
131 for (
const QBluetoothUuid &uuid : serviceList.keys()) {
132 if (!newUuidList.contains(uuid)) {
133 qCDebug(QT_BT_BLUEZ) <<
__func__ <<
"Service" << uuid <<
"has been removed";
134 QSharedPointer<QLowEnergyServicePrivate> service = serviceList.take(uuid);
135 service->setController(
nullptr);
136 dbusServices.remove(uuid);
141 }
else if (interface == QStringLiteral(
"org.bluez.Battery1")) {
142 qCDebug(QT_BT_BLUEZ) <<
"######" << interface << changedProperties;
143 if (changedProperties.contains(QStringLiteral(
"Percentage"))) {
146 const QBluetoothUuid uuid(QBluetoothUuid::ServiceClassUuid::BatteryService);
147 if (!serviceList.contains(uuid) || !dbusServices.contains(uuid)
148 || !dbusServices[uuid].hasBatteryService
149 || dbusServices[uuid].batteryInterface.isNull())
152 QSharedPointer<QLowEnergyServicePrivate> serviceData = serviceList.value(uuid);
153 if (serviceData->state != QLowEnergyService::RemoteServiceDiscovered)
156 QHash<QLowEnergyHandle, QLowEnergyServicePrivate::CharData>::iterator iter;
157 iter = serviceData->characteristicList.begin();
158 while (iter != serviceData->characteristicList.end()) {
159 auto &charData = iter.value();
160 if (charData.uuid != QBluetoothUuid::CharacteristicType::BatteryLevel)
164 bool cccActive =
false;
165 for (
const QLowEnergyServicePrivate::DescData &descData : std::as_const(charData.descriptorList)) {
166 if (descData.uuid != QBluetoothUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration))
168 if (descData.value == QByteArray::fromHex(
"0100")
169 || descData.value == QByteArray::fromHex(
"0200")) {
175 const QByteArray newValue(1,
char(dbusServices[uuid].batteryInterface->percentage()));
176 qCDebug(QT_BT_BLUEZ) <<
"Battery1 char update" << cccActive
177 << charData.value.toHex() <<
"->" << newValue.toHex();
178 if (cccActive && newValue != charData.value) {
179 qCDebug(QT_BT_BLUEZ) <<
"Property update for Battery1";
180 charData.value = newValue;
181 QLowEnergyCharacteristic ch(serviceData, iter.key());
182 emit serviceData->characteristicChanged(ch, newValue);
192 QLowEnergyHandle charHandle,
const QString &interface,
193 const QVariantMap &changedProperties,
198 if (interface != QStringLiteral(
"org.bluez.GattCharacteristic1"))
201 if (!changedProperties.contains(QStringLiteral(
"Value")))
204 const QLowEnergyCharacteristic changedChar = characteristicForHandle(charHandle);
205 const QLowEnergyDescriptor ccnDescriptor = changedChar.descriptor(
206 QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration);
207 if (!ccnDescriptor.isValid())
210 const QByteArray newValue = changedProperties.value(QStringLiteral(
"Value")).toByteArray();
211 if (changedChar.properties() & QLowEnergyCharacteristic::Read)
212 updateValueOfCharacteristic(charHandle, newValue,
false);
214 auto service = serviceForHandle(charHandle);
216 if (!service.isNull())
217 emit service->characteristicChanged(changedChar, newValue);
221 const QStringList &interfaces)
223 if (objectPath.path() == device->path()) {
224 if (interfaces.contains(QStringLiteral(
"org.bluez.Device1"))) {
225 qCWarning(QT_BT_BLUEZ) <<
"DBus Device1 was removed";
226 executeClose(QLowEnergyController::UnknownRemoteDeviceError);
228 qCDebug(QT_BT_BLUEZ) <<
"DBus interfaces" << interfaces <<
"were removed from"
229 << objectPath.path();
231 }
else if (objectPath.path() == adapter->path()) {
232 qCWarning(QT_BT_BLUEZ) <<
"DBus Adapter was removed";
233 executeClose(QLowEnergyController::InvalidBluetoothAdapterError);
241 managerBluez =
nullptr;
255 delete deviceMonitor;
256 deviceMonitor =
nullptr;
261 advertiser =
nullptr;
264 if (peripheralApplication)
267 if (peripheralConnectionManager)
273 dbusServices.clear();
277 pendingConnect = disconnectSignalRequired =
false;
286 const QString hostAdapterPath = findAdapterForAddress(localAdapter, &ok);
287 if (!ok || hostAdapterPath.isEmpty()) {
288 qCWarning(QT_BT_BLUEZ) <<
"Cannot find suitable bluetooth adapter";
289 setError(QLowEnergyController::InvalidBluetoothAdapterError);
293 auto manager = std::make_unique<OrgFreedesktopDBusObjectManagerInterface>(
294 QStringLiteral(
"org.bluez"), QStringLiteral(
"/"), QDBusConnection::systemBus());
296 QDBusPendingReply<ManagedObjectList> reply = manager->GetManagedObjects();
297 reply.waitForFinished();
298 if (reply.isError()) {
299 qCWarning(QT_BT_BLUEZ) <<
"Cannot enumerate Bluetooth devices for GATT connect";
300 setError(QLowEnergyController::ConnectionError);
306 for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) {
309 for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) {
310 const QString &iface = jt.key();
311 const QVariantMap &ifaceValues = jt.value();
313 if (iface == QStringLiteral(
"org.bluez.Device1")) {
314 if (remoteDevice.toString() == ifaceValues.value(QStringLiteral(
"Address")).toString())
316 const QVariant adapterForCurrentDevice = ifaceValues.value(QStringLiteral(
"Adapter"));
317 if (qvariant_cast<QDBusObjectPath>(adapterForCurrentDevice).path() == hostAdapterPath) {
318 devicePath = it.key().path();
325 if (!devicePath.isEmpty())
329 if (devicePath.isEmpty()) {
330 qCDebug(QT_BT_BLUEZ) <<
"Cannot find targeted remote device. "
331 "Re-running device discovery might help";
332 setError(QLowEnergyController::UnknownRemoteDeviceError);
336 managerBluez = manager.release();
337 connect(managerBluez, &OrgFreedesktopDBusObjectManagerInterface::InterfacesRemoved,
338 this, &QLowEnergyControllerPrivateBluezDBus::interfacesRemoved);
339 adapter =
new OrgBluezAdapter1Interface(
340 QStringLiteral(
"org.bluez"), hostAdapterPath,
341 QDBusConnection::systemBus(),
this);
342 device =
new OrgBluezDevice1Interface(
343 QStringLiteral(
"org.bluez"), devicePath,
344 QDBusConnection::systemBus(),
this);
345 deviceMonitor =
new OrgFreedesktopDBusPropertiesInterface(
346 QStringLiteral(
"org.bluez"), devicePath,
347 QDBusConnection::systemBus(),
this);
348 connect(deviceMonitor, &OrgFreedesktopDBusPropertiesInterface::PropertiesChanged,
349 this, &QLowEnergyControllerPrivateBluezDBus::devicePropertiesChanged);
354 qCDebug(QT_BT_BLUEZ) <<
"QLowEnergyControllerPrivateBluezDBus::connectToDevice()";
356 connectToDeviceHelper();
358 if (!adapter || !device)
361 if (!adapter->powered()) {
362 qCWarning(QT_BT_BLUEZ) <<
"Error: Local adapter is powered off";
363 setError(QLowEnergyController::ConnectionError);
367 setState(QLowEnergyController::ConnectingState);
371 if (device->connected() && device->servicesResolved()) {
373 disconnectSignalRequired =
true;
375 setState(QLowEnergyController::ConnectedState);
376 Q_Q(QLowEnergyController);
381 pendingConnect =
true;
383 QDBusPendingReply<> reply = device->Connect();
384 QDBusPendingCallWatcher* watcher =
new QDBusPendingCallWatcher(reply,
this);
385 connect(watcher, &QDBusPendingCallWatcher::finished,
this,
386 [
this](QDBusPendingCallWatcher* call) {
387 QDBusPendingReply<> reply = *call;
388 if (reply.isError()) {
389 qCDebug(QT_BT_BLUEZ) <<
"BTLE_DBUS::connect() failed"
390 << reply.reply().errorName()
391 << reply.reply().errorMessage();
392 executeClose(QLowEnergyController::UnknownError);
400 if (role == QLowEnergyController::CentralRole) {
404 setState(QLowEnergyController::ClosingState);
406 QDBusPendingReply<> reply = device->Disconnect();
407 QDBusPendingCallWatcher* watcher =
new QDBusPendingCallWatcher(reply,
this);
408 connect(watcher, &QDBusPendingCallWatcher::finished,
this,
409 [
this](QDBusPendingCallWatcher* call) {
410 QDBusPendingReply<> reply = *call;
411 if (reply.isError()) {
412 qCDebug(QT_BT_BLUEZ) <<
"BTLE_DBUS::disconnect() failed"
413 << reply.reply().errorName()
414 << reply.reply().errorMessage();
415 executeClose(QLowEnergyController::UnknownError);
417 executeClose(QLowEnergyController::NoError);
422 Q_Q(QLowEnergyController);
425 remoteDevice.clear();
426 const auto emitDisconnected = (state == QLowEnergyController::ConnectedState);
427 setState(QLowEnergyController::UnconnectedState);
428 if (emitDisconnected)
429 emit q->disconnected();
435 QDBusPendingReply<ManagedObjectList> reply = managerBluez->GetManagedObjects();
436 reply.waitForFinished();
437 if (reply.isError()) {
438 qCWarning(QT_BT_BLUEZ) <<
"Cannot discover services";
439 setError(QLowEnergyController::UnknownError);
440 setState(QLowEnergyController::DiscoveredState);
444 Q_Q(QLowEnergyController);
446 auto setupServicePrivate = [&, q](
447 QLowEnergyService::ServiceType type,
const QBluetoothUuid &uuid,
448 const QString &path,
const bool battery1Interface =
false){
449 QSharedPointer<QLowEnergyServicePrivate> priv = QSharedPointer<QLowEnergyServicePrivate>::create();
452 priv->setController(
this);
454 GattService serviceContainer;
455 serviceContainer.servicePath = path;
457 if (battery1Interface) {
458 qCDebug(QT_BT_BLUEZ) <<
"Using Battery1 interface to emulate generic interface";
459 serviceContainer.hasBatteryService =
true;
462 serviceList.insert(priv->uuid, priv);
463 dbusServices.insert(priv->uuid, serviceContainer);
465 emit q->serviceDiscovered(priv->uuid);
469 const QString servicePathPrefix = device->path().append(QStringLiteral(
"/service"));
487 bool gattBatteryService{
false};
488 QString batteryServicePath;
490 for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) {
493 if (!it.key().path().startsWith(device->path()))
496 if (it.key().path() == device->path()) {
498 for (InterfaceList::const_iterator battIter = ifaceList.constBegin(); battIter != ifaceList.constEnd(); ++battIter) {
499 const QString &iface = battIter.key();
500 if (iface == QStringLiteral(
"org.bluez.Battery1")) {
501 qCDebug(QT_BT_BLUEZ) <<
"Dedicated Battery1 service available";
502 batteryServicePath = it.key().path();
504 }
else if (iface == QStringLiteral(
"org.bluez.Device1")) {
505 for (
auto const& uuid :
506 battIter.value()[QStringLiteral(
"UUIDs")].toStringList()) {
507 if (QBluetoothUuid(uuid) ==
508 QBluetoothUuid::ServiceClassUuid::BatteryService) {
509 qCDebug(QT_BT_BLUEZ) <<
"Battery service listed as available service";
510 batteryServicePath = it.key().path();
519 if (!it.key().path().startsWith(servicePathPrefix))
522 for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) {
523 const QString &iface = jt.key();
525 if (iface == QStringLiteral(
"org.bluez.GattService1")) {
526 QScopedPointer<OrgBluezGattService1Interface> service(
new OrgBluezGattService1Interface(
527 QStringLiteral(
"org.bluez"),it.key().path(),
528 QDBusConnection::systemBus(),
this));
529 if (QBluetoothUuid(service->uUID()) ==
530 QBluetoothUuid::ServiceClassUuid::BatteryService) {
531 qCDebug(QT_BT_BLUEZ) <<
"Using battery service via GattService1 interface";
532 gattBatteryService =
true;
534 setupServicePrivate(service->primary()
535 ? QLowEnergyService::PrimaryService
536 : QLowEnergyService::IncludedService,
537 QBluetoothUuid(service->uUID()), it.key().path());
542 if (!gattBatteryService && !batteryServicePath.isEmpty()) {
543 setupServicePrivate(QLowEnergyService::PrimaryService,
544 QBluetoothUuid::ServiceClassUuid::BatteryService,
545 batteryServicePath,
true);
548 setState(QLowEnergyController::DiscoveredState);
549 emit q->discoveryFinished();
553 GattService &dbusData, QSharedPointer<QLowEnergyServicePrivate> serviceData)
559 auto batteryService = QSharedPointer<OrgBluezBattery1Interface>::create(
560 QStringLiteral(
"org.bluez"), dbusData.servicePath,
561 QDBusConnection::systemBus());
562 dbusData.batteryInterface = batteryService;
564 serviceData->startHandle = runningHandle++;
567 QLowEnergyHandle indexHandle = runningHandle++;
570 charData.valueHandle = runningHandle++;
571 charData.properties.setFlag(QLowEnergyCharacteristic::Read);
572 charData.properties.setFlag(QLowEnergyCharacteristic::Notify);
573 charData.uuid = QBluetoothUuid::CharacteristicType::BatteryLevel;
574 charData.value = QByteArray(1,
char(batteryService->percentage()));
579 QLowEnergyHandle descriptorHandle = runningHandle++;
580 descData.uuid = QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration;
581 descData.value = QByteArray::fromHex(
"0000");
582 charData.descriptorList.insert(descriptorHandle, descData);
584 descriptorHandle = runningHandle++;
585 descData.uuid = QBluetoothUuid::DescriptorType::CharacteristicPresentationFormat;
589 descData.value = QByteArray::fromHex(
"0400ad27011131");
590 charData.descriptorList.insert(descriptorHandle, descData);
592 descriptorHandle = runningHandle++;
593 descData.uuid = QBluetoothUuid::DescriptorType::ReportReference;
594 descData.value = QByteArray::fromHex(
"0401");
595 charData.descriptorList.insert(descriptorHandle, descData);
597 serviceData->characteristicList[indexHandle] = charData;
598 serviceData->endHandle = runningHandle++;
600 serviceData->setState(QLowEnergyService::RemoteServiceDiscovered);
605 const bool emitDisconnect = disconnectSignalRequired;
608 if (newError != QLowEnergyController::NoError)
611 setState(QLowEnergyController::UnconnectedState);
612 if (emitDisconnect) {
613 Q_Q(QLowEnergyController);
614 emit q->disconnected();
619 const QBluetoothUuid &service, QLowEnergyService::DiscoveryMode mode)
621 if (!serviceList.contains(service) || !dbusServices.contains(service)) {
622 qCWarning(QT_BT_BLUEZ) <<
"Discovery of unknown service" << service.toString()
628 QSharedPointer<QLowEnergyServicePrivate> serviceData = serviceList.value(service);
629 serviceData->characteristicList.clear();
631 GattService &dbusData = dbusServices[service];
632 dbusData.characteristics.clear();
634 if (dbusData.hasBatteryService) {
635 qCDebug(QT_BT_BLUEZ) <<
"Triggering Battery1 service discovery on " << dbusData.servicePath;
636 discoverBatteryServiceDetails(dbusData, serviceData);
640 QDBusPendingReply<ManagedObjectList> reply = managerBluez->GetManagedObjects();
641 reply.waitForFinished();
642 if (reply.isError()) {
643 qCWarning(QT_BT_BLUEZ) <<
"Cannot discover services";
644 setError(QLowEnergyController::UnknownError);
645 setState(QLowEnergyController::DiscoveredState);
650 for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) {
652 if (!it.key().path().startsWith(dbusData.servicePath))
655 for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) {
656 const QString &iface = jt.key();
657 if (iface == QStringLiteral(
"org.bluez.GattCharacteristic1")) {
658 auto charInterface = QSharedPointer<OrgBluezGattCharacteristic1Interface>::create(
659 QStringLiteral(
"org.bluez"), it.key().path(),
660 QDBusConnection::systemBus());
661 GattCharacteristic dbusCharData;
662 dbusCharData.characteristic = charInterface;
663 dbusData.characteristics.append(dbusCharData);
664 }
else if (iface == QStringLiteral(
"org.bluez.GattDescriptor1")) {
665 auto descInterface = QSharedPointer<OrgBluezGattDescriptor1Interface>::create(
666 QStringLiteral(
"org.bluez"), it.key().path(),
667 QDBusConnection::systemBus());
669 for (GattCharacteristic &dbusCharData : dbusData.characteristics) {
670 if (!descInterface->path().startsWith(
671 dbusCharData.characteristic->path()))
675 dbusCharData.descriptors.append(descInterface);
681 qCWarning(QT_BT_BLUEZ) <<
"Descriptor discovery error";
687 serviceData->startHandle = runningHandle++;
688 for (GattCharacteristic &dbusChar : dbusData.characteristics) {
689 const QLowEnergyHandle indexHandle = runningHandle++;
690 QLowEnergyServicePrivate::CharData charData;
693 charData.valueHandle = runningHandle++;
694 const QStringList properties = dbusChar.characteristic->flags();
696 for (
const auto &entry : properties) {
697 if (entry == QStringLiteral(
"broadcast"))
698 charData.properties.setFlag(QLowEnergyCharacteristic::Broadcasting,
true);
699 else if (entry == QStringLiteral(
"read"))
700 charData.properties.setFlag(QLowEnergyCharacteristic::Read,
true);
701 else if (entry == QStringLiteral(
"write-without-response"))
702 charData.properties.setFlag(QLowEnergyCharacteristic::WriteNoResponse,
true);
703 else if (entry == QStringLiteral(
"write"))
704 charData.properties.setFlag(QLowEnergyCharacteristic::Write,
true);
705 else if (entry == QStringLiteral(
"notify"))
706 charData.properties.setFlag(QLowEnergyCharacteristic::Notify,
true);
707 else if (entry == QStringLiteral(
"indicate"))
708 charData.properties.setFlag(QLowEnergyCharacteristic::Indicate,
true);
709 else if (entry == QStringLiteral(
"authenticated-signed-writes"))
710 charData.properties.setFlag(QLowEnergyCharacteristic::WriteSigned,
true);
711 else if (entry == QStringLiteral(
"reliable-write"))
712 charData.properties.setFlag(QLowEnergyCharacteristic::ExtendedProperty,
true);
713 else if (entry == QStringLiteral(
"writable-auxiliaries"))
714 charData.properties.setFlag(QLowEnergyCharacteristic::ExtendedProperty,
true);
718 charData.uuid = QBluetoothUuid(dbusChar.characteristic->uUID());
721 if (mode == QLowEnergyService::FullDiscovery
722 && charData.properties.testFlag(QLowEnergyCharacteristic::Read)) {
724 job.flags = GattJob::JobFlags({GattJob::CharRead, GattJob::ServiceDiscovery});
725 job.service = serviceData;
726 job.handle = indexHandle;
731 for (
const auto &descEntry : std::as_const(dbusChar.descriptors)) {
732 const QLowEnergyHandle descriptorHandle = runningHandle++;
733 QLowEnergyServicePrivate::DescData descData;
734 descData.uuid = QBluetoothUuid(descEntry->uUID());
735 charData.descriptorList.insert(descriptorHandle, descData);
740 == QBluetoothUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration)) {
741 dbusChar.charMonitor = QSharedPointer<OrgFreedesktopDBusPropertiesInterface>::create(
742 QStringLiteral(
"org.bluez"),
743 dbusChar.characteristic->path(),
744 QDBusConnection::systemBus(),
this);
745 connect(dbusChar.charMonitor.data(), &OrgFreedesktopDBusPropertiesInterface::PropertiesChanged,
746 this, [
this, indexHandle](
const QString &interface,
const QVariantMap &changedProperties,
747 const QStringList &removedProperties) {
749 characteristicPropertiesChanged(indexHandle, interface,
750 changedProperties, removedProperties);
754 if (mode == QLowEnergyService::FullDiscovery) {
757 job.flags = GattJob::JobFlags({ GattJob::DescRead, GattJob::ServiceDiscovery });
758 job.service = serviceData;
759 job.handle = descriptorHandle;
764 serviceData->characteristicList[indexHandle] = charData;
767 serviceData->endHandle = runningHandle++;
770 if (!jobs.isEmpty()) {
771 GattJob &lastJob = jobs.last();
772 lastJob.flags.setFlag(GattJob::LastServiceDiscovery,
true);
774 serviceData->setState(QLowEnergyService::RemoteServiceDiscovered);
790 if (!jobPending || jobs.isEmpty()) {
792 qCWarning(QT_BT_BLUEZ) <<
"Aborting onCharReadFinished due to disconnect";
793 Q_ASSERT(state == QLowEnergyController::UnconnectedState);
797 const GattJob nextJob = jobs.constFirst();
798 Q_ASSERT(nextJob.flags.testFlag(GattJob::CharRead));
800 QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(nextJob.handle);
801 if (service.isNull() || !dbusServices.contains(service->uuid)) {
802 qCWarning(QT_BT_BLUEZ) <<
"onCharReadFinished: Invalid GATT job. Skipping.";
808 service->characteristicList.value(nextJob.handle);
810 bool isServiceDiscovery = nextJob.flags.testFlag(GattJob::ServiceDiscovery);
811 QDBusPendingReply<QByteArray> reply = *call;
812 if (reply.isError()) {
813 qCWarning(QT_BT_BLUEZ) <<
"Cannot initiate reading of" << charData.uuid
814 <<
"of service" << service->uuid
815 << reply.error().name() << reply.error().message();
816 if (!isServiceDiscovery)
817 service->setError(QLowEnergyService::CharacteristicReadError);
819 qCDebug(QT_BT_BLUEZ) <<
"Read Char:" << charData.uuid << reply.value().toHex();
820 if (charData.properties.testFlag(QLowEnergyCharacteristic::Read))
821 updateValueOfCharacteristic(nextJob.handle, reply.value(),
false);
823 if (isServiceDiscovery) {
824 if (nextJob.flags.testFlag(GattJob::LastServiceDiscovery))
825 service->setState(QLowEnergyService::RemoteServiceDiscovered);
827 QLowEnergyCharacteristic ch(service, nextJob.handle);
828 emit service->characteristicRead(ch, reply.value());
838 if (!jobPending || jobs.isEmpty()) {
840 qCWarning(QT_BT_BLUEZ) <<
"Aborting onDescReadFinished due to disconnect";
841 Q_ASSERT(state == QLowEnergyController::UnconnectedState);
845 const GattJob nextJob = jobs.constFirst();
846 Q_ASSERT(nextJob.flags.testFlag(GattJob::DescRead));
848 QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(nextJob.handle);
849 if (service.isNull() || !dbusServices.contains(service->uuid)) {
850 qCWarning(QT_BT_BLUEZ) <<
"onDescReadFinished: Invalid GATT job. Skipping.";
856 QLowEnergyCharacteristic ch = characteristicForHandle(nextJob.handle);
858 qCWarning(QT_BT_BLUEZ) <<
"Cannot find char for desc read (onDescReadFinished 1).";
865 service->characteristicList.value(ch.attributeHandle());
867 if (!charData.descriptorList.contains(nextJob.handle)) {
868 qCWarning(QT_BT_BLUEZ) <<
"Cannot find descriptor (onDescReadFinished 2).";
874 bool isServiceDiscovery = nextJob.flags.testFlag(GattJob::ServiceDiscovery);
876 QDBusPendingReply<QByteArray> reply = *call;
877 if (reply.isError()) {
878 qCWarning(QT_BT_BLUEZ) <<
"Cannot read descriptor (onDescReadFinished 3): "
879 << charData.descriptorList[nextJob.handle].uuid
881 << reply.error().name() << reply.error().message();
882 if (!isServiceDiscovery)
883 service->setError(QLowEnergyService::DescriptorReadError);
885 qCDebug(QT_BT_BLUEZ) <<
"Read Desc:" << reply.value();
886 updateValueOfDescriptor(ch.attributeHandle(), nextJob.handle, reply.value(),
false);
888 if (isServiceDiscovery) {
889 if (nextJob.flags.testFlag(GattJob::LastServiceDiscovery))
890 service->setState(QLowEnergyService::RemoteServiceDiscovered);
892 QLowEnergyDescriptor desc(service, ch.attributeHandle(), nextJob.handle);
893 emit service->descriptorRead(desc, reply.value());
903 if (!jobPending || jobs.isEmpty()) {
905 qCWarning(QT_BT_BLUEZ) <<
"Aborting onCharWriteFinished due to disconnect";
906 Q_ASSERT(state == QLowEnergyController::UnconnectedState);
910 const GattJob nextJob = jobs.constFirst();
911 Q_ASSERT(nextJob.flags.testFlag(GattJob::CharWrite));
913 QSharedPointer<QLowEnergyServicePrivate> service = nextJob.service;
914 if (!dbusServices.contains(service->uuid)) {
915 qCWarning(QT_BT_BLUEZ) <<
"onCharWriteFinished: Invalid GATT job. Skipping.";
922 service->characteristicList.value(nextJob.handle);
924 QDBusPendingReply<> reply = *call;
925 if (reply.isError()) {
926 qCWarning(QT_BT_BLUEZ) <<
"Cannot initiate writing of" << charData.uuid
927 <<
"of service" << service->uuid
928 << reply.error().name() << reply.error().message();
929 service->setError(QLowEnergyService::CharacteristicWriteError);
931 if (charData.properties.testFlag(QLowEnergyCharacteristic::Read))
932 updateValueOfCharacteristic(nextJob.handle, nextJob.value,
false);
934 QLowEnergyCharacteristic ch(service, nextJob.handle);
936 if (nextJob.writeMode == QLowEnergyService::WriteWithResponse) {
937 qCDebug(QT_BT_BLUEZ) <<
"Written Char:" << charData.uuid << nextJob.value.toHex();
938 emit service->characteristicWritten(ch, nextJob.value);
948 if (!jobPending || jobs.isEmpty()) {
950 qCWarning(QT_BT_BLUEZ) <<
"Aborting onDescWriteFinished due to disconnect";
951 Q_ASSERT(state == QLowEnergyController::UnconnectedState);
955 const GattJob nextJob = jobs.constFirst();
956 Q_ASSERT(nextJob.flags.testFlag(GattJob::DescWrite));
958 QSharedPointer<QLowEnergyServicePrivate> service = nextJob.service;
959 if (!dbusServices.contains(service->uuid)) {
960 qCWarning(QT_BT_BLUEZ) <<
"onDescWriteFinished: Invalid GATT job. Skipping.";
966 const QLowEnergyCharacteristic associatedChar = characteristicForHandle(nextJob.handle);
967 const QLowEnergyDescriptor descriptor = descriptorForHandle(nextJob.handle);
968 if (!associatedChar.isValid() || !descriptor.isValid()) {
969 qCWarning(QT_BT_BLUEZ) <<
"onDescWriteFinished: Cannot find associated char/desc: "
970 << associatedChar.isValid();
976 QDBusPendingReply<> reply = *call;
977 if (reply.isError()) {
978 qCWarning(QT_BT_BLUEZ) <<
"Cannot initiate writing of" << descriptor.uuid()
979 <<
"of char" << associatedChar.uuid()
980 <<
"of service" << service->uuid
981 << reply.error().name() << reply.error().message();
982 service->setError(QLowEnergyService::DescriptorWriteError);
984 qCDebug(QT_BT_BLUEZ) <<
"Write Desc:" << descriptor.uuid() << nextJob.value.toHex();
985 updateValueOfDescriptor(associatedChar.attributeHandle(), nextJob.handle,
986 nextJob.value,
false);
987 emit service->descriptorWritten(descriptor, nextJob.value);
996 if (jobPending || jobs.isEmpty())
1001 const GattJob nextJob = jobs.constFirst();
1002 QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(nextJob.handle);
1003 if (service.isNull() || !dbusServices.contains(service->uuid)) {
1004 qCWarning(QT_BT_BLUEZ) <<
"Invalid GATT job (scheduleNextJob). Skipping.";
1009 const GattService &dbusServiceData = dbusServices[service->uuid];
1011 if (nextJob.flags.testFlag(GattJob::CharRead)) {
1013 if (!service->characteristicList.contains(nextJob.handle)) {
1014 qCWarning(QT_BT_BLUEZ) <<
"Invalid Char handle when reading. Skipping.";
1020 service->characteristicList.value(nextJob.handle);
1021 bool foundChar =
false;
1022 for (
const auto &gattChar : std::as_const(dbusServiceData.characteristics)) {
1023 if (charData.uuid != QBluetoothUuid(gattChar.characteristic->uUID()))
1026 QDBusPendingReply<QByteArray> reply = gattChar.characteristic->ReadValue(QVariantMap());
1027 QDBusPendingCallWatcher* watcher =
new QDBusPendingCallWatcher(reply,
this);
1028 connect(watcher, &QDBusPendingCallWatcher::finished,
1029 this, &QLowEnergyControllerPrivateBluezDBus::onCharReadFinished);
1036 qCWarning(QT_BT_BLUEZ) <<
"Cannot find char for reading. Skipping.";
1040 }
else if (nextJob.flags.testFlag(GattJob::CharWrite)) {
1042 if (!service->characteristicList.contains(nextJob.handle)) {
1043 qCWarning(QT_BT_BLUEZ) <<
"Invalid Char handle when writing. Skipping.";
1049 service->characteristicList.value(nextJob.handle);
1050 bool foundChar =
false;
1051 for (
const auto &gattChar : std::as_const(dbusServiceData.characteristics)) {
1052 if (charData.uuid != QBluetoothUuid(gattChar.characteristic->uUID()))
1055 QVariantMap options;
1057 options[QStringLiteral(
"type")] = nextJob.writeMode == QLowEnergyService::WriteWithoutResponse ?
1058 QStringLiteral(
"command") : QStringLiteral(
"request");
1059 QDBusPendingReply<> reply = gattChar.characteristic->WriteValue(nextJob.value, options);
1061 QDBusPendingCallWatcher* watcher =
new QDBusPendingCallWatcher(reply,
this);
1062 connect(watcher, &QDBusPendingCallWatcher::finished,
1063 this, &QLowEnergyControllerPrivateBluezDBus::onCharWriteFinished);
1070 qCWarning(QT_BT_BLUEZ) <<
"Cannot find char for writing. Skipping.";
1074 }
else if (nextJob.flags.testFlag(GattJob::DescRead)) {
1076 QLowEnergyCharacteristic ch = characteristicForHandle(nextJob.handle);
1077 if (!ch.isValid()) {
1078 qCWarning(QT_BT_BLUEZ) <<
"Invalid GATT job (scheduleReadDesc 1). Skipping.";
1084 service->characteristicList.value(ch.attributeHandle());
1085 if (!charData.descriptorList.contains(nextJob.handle)) {
1086 qCWarning(QT_BT_BLUEZ) <<
"Invalid GATT job (scheduleReadDesc 2). Skipping.";
1091 const QBluetoothUuid descUuid = charData.descriptorList[nextJob.handle].uuid;
1092 bool foundDesc =
false;
1093 for (
const auto &gattChar : std::as_const(dbusServiceData.characteristics)) {
1094 if (charData.uuid != QBluetoothUuid(gattChar.characteristic->uUID()))
1097 for (
const auto &gattDesc : std::as_const(gattChar.descriptors)) {
1098 if (descUuid != QBluetoothUuid(gattDesc->uUID()))
1101 QDBusPendingReply<QByteArray> reply = gattDesc->ReadValue(QVariantMap());
1102 QDBusPendingCallWatcher* watcher =
new QDBusPendingCallWatcher(reply,
this);
1103 connect(watcher, &QDBusPendingCallWatcher::finished,
1104 this, &QLowEnergyControllerPrivateBluezDBus::onDescReadFinished);
1114 qCWarning(QT_BT_BLUEZ) <<
"Cannot find descriptor for reading. Skipping.";
1118 }
else if (nextJob.flags.testFlag(GattJob::DescWrite)) {
1120 const QLowEnergyCharacteristic ch = characteristicForHandle(nextJob.handle);
1121 if (!ch.isValid()) {
1122 qCWarning(QT_BT_BLUEZ) <<
"Invalid GATT job (scheduleWriteDesc 1). Skipping.";
1128 service->characteristicList.value(ch.attributeHandle());
1129 if (!charData.descriptorList.contains(nextJob.handle)) {
1130 qCWarning(QT_BT_BLUEZ) <<
"Invalid GATT job (scheduleWriteDesc 2). Skipping.";
1135 const QBluetoothUuid descUuid = charData.descriptorList[nextJob.handle].uuid;
1136 bool foundDesc =
false;
1137 for (
const auto &gattChar : std::as_const(dbusServiceData.characteristics)) {
1138 if (charData.uuid != QBluetoothUuid(gattChar.characteristic->uUID()))
1141 for (
const auto &gattDesc : std::as_const(gattChar.descriptors)) {
1142 if (descUuid != QBluetoothUuid(gattDesc->uUID()))
1147 if (descUuid == QBluetoothUuid(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration)) {
1148 const QByteArray value = nextJob.value;
1150 QDBusPendingReply<> reply;
1151 qCDebug(QT_BT_BLUEZ) <<
"Init CCC change to" << value.toHex()
1152 << charData.uuid << service->uuid;
1153 if (value == QByteArray::fromHex(
"0100") || value == QByteArray::fromHex(
"0200"))
1154 reply = gattChar.characteristic->StartNotify();
1156 reply = gattChar.characteristic->StopNotify();
1157 QDBusPendingCallWatcher* watcher =
new QDBusPendingCallWatcher(reply,
this);
1158 connect(watcher, &QDBusPendingCallWatcher::finished,
1159 this, &QLowEnergyControllerPrivateBluezDBus::onDescWriteFinished);
1161 QDBusPendingReply<> reply = gattDesc->WriteValue(nextJob.value, QVariantMap());
1162 QDBusPendingCallWatcher* watcher =
new QDBusPendingCallWatcher(reply,
this);
1163 connect(watcher, &QDBusPendingCallWatcher::finished,
1164 this, &QLowEnergyControllerPrivateBluezDBus::onDescWriteFinished);
1177 qCWarning(QT_BT_BLUEZ) <<
"Cannot find descriptor for writing. Skipping.";
1182 qCWarning(QT_BT_BLUEZ) <<
"Unknown gatt job type. Skipping.";
1188 const QSharedPointer<QLowEnergyServicePrivate> service,
1189 const QLowEnergyHandle charHandle)
1191 Q_ASSERT(!service.isNull());
1192 if (!service->characteristicList.contains(charHandle)) {
1193 qCWarning(QT_BT_BLUEZ) <<
"Read characteristic does not belong to service"
1199 = service->characteristicList[charHandle];
1200 if (!(charDetails.properties & QLowEnergyCharacteristic::Read)) {
1204 qCWarning(QT_BT_BLUEZ) <<
"Reading non-readable char" << charHandle;
1207 const GattService &gattService = dbusServices[service->uuid];
1208 if (gattService.hasBatteryService && !gattService.batteryInterface.isNull()) {
1210 const QByteArray newValue(1,
char(gattService.batteryInterface->percentage()));
1211 quint16 result = updateValueOfCharacteristic(charHandle, newValue,
false);
1213 QLowEnergyCharacteristic ch(service, charHandle);
1214 emit service->characteristicRead(ch, newValue);
1216 service->setError(QLowEnergyService::CharacteristicReadError);
1222 job.flags = GattJob::JobFlags({GattJob::CharRead});
1223 job.service = service;
1224 job.handle = charHandle;
1231 const QSharedPointer<QLowEnergyServicePrivate> service,
1232 const QLowEnergyHandle charHandle,
1233 const QLowEnergyHandle descriptorHandle)
1235 Q_ASSERT(!service.isNull());
1236 if (!service->characteristicList.contains(charHandle))
1240 = service->characteristicList[charHandle];
1241 if (!charDetails.descriptorList.contains(descriptorHandle))
1244 const GattService &gattService = dbusServices[service->uuid];
1245 if (gattService.hasBatteryService && !gattService.batteryInterface.isNull()) {
1246 auto descriptor = descriptorForHandle(descriptorHandle);
1247 if (descriptor.isValid())
1248 emit service->descriptorRead(descriptor, descriptor.value());
1250 service->setError(QLowEnergyService::DescriptorReadError);
1256 job.flags = GattJob::JobFlags({GattJob::DescRead});
1257 job.service = service;
1258 job.handle = descriptorHandle;
1265 const QSharedPointer<QLowEnergyServicePrivate> service,
1266 const QLowEnergyHandle charHandle,
1267 const QByteArray &newValue,
1268 QLowEnergyService::WriteMode writeMode)
1270 Q_ASSERT(!service.isNull());
1271 if (!service->characteristicList.contains(charHandle)) {
1272 qCWarning(QT_BT_BLUEZ) <<
"Write characteristic does not belong to service"
1277 if (role == QLowEnergyController::CentralRole) {
1278 const GattService &gattService = dbusServices[service->uuid];
1279 if (gattService.hasBatteryService && !gattService.batteryInterface.isNull()) {
1281 service->setError(QLowEnergyService::CharacteristicWriteError);
1287 job.flags = GattJob::JobFlags({GattJob::CharWrite});
1288 job.service = service;
1289 job.handle = charHandle;
1290 job.value = newValue;
1291 job.writeMode = writeMode;
1297 Q_ASSERT(peripheralApplication);
1298 if (!peripheralApplication->localCharacteristicWrite(charHandle, newValue)) {
1299 qCWarning(QT_BT_BLUEZ) <<
"Characteristic write failed"
1300 << characteristicForHandle(charHandle).uuid();
1301 service->setError(QLowEnergyService::CharacteristicWriteError);
1305 charData.value = newValue;
1310 const QSharedPointer<QLowEnergyServicePrivate> service,
1311 const QLowEnergyHandle charHandle,
1312 const QLowEnergyHandle descriptorHandle,
1313 const QByteArray &newValue)
1315 Q_ASSERT(!service.isNull());
1316 if (!service->characteristicList.contains(charHandle))
1319 if (role == QLowEnergyController::CentralRole) {
1320 const GattService &gattService = dbusServices[service->uuid];
1321 if (gattService.hasBatteryService && !gattService.batteryInterface.isNull()) {
1322 auto descriptor = descriptorForHandle(descriptorHandle);
1323 if (!descriptor.isValid())
1326 if (descriptor.uuid() == QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration) {
1327 if (newValue == QByteArray::fromHex(
"0000")
1328 || newValue == QByteArray::fromHex(
"0100")
1329 || newValue == QByteArray::fromHex(
"0200")) {
1330 quint16 result = updateValueOfDescriptor(charHandle, descriptorHandle, newValue,
false);
1332 emit service->descriptorWritten(descriptor, newValue);
1334 emit service->setError(QLowEnergyService::DescriptorWriteError);
1338 service->setError(QLowEnergyService::DescriptorWriteError);
1345 job.flags = GattJob::JobFlags({GattJob::DescWrite});
1346 job.service = service;
1347 job.handle = descriptorHandle;
1348 job.value = newValue;
1354 Q_ASSERT(peripheralApplication);
1356 auto desc = descriptorForHandle(descriptorHandle);
1357 if (desc.uuid() == QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration) {
1358 qCWarning(QT_BT_BLUEZ) <<
"CCCD write not supported in peripheral role";
1359 service->setError(QLowEnergyService::DescriptorWriteError);
1361 }
else if (!peripheralApplication->localDescriptorWrite(descriptorHandle, newValue)) {
1362 qCWarning(QT_BT_BLUEZ) <<
"Descriptor write failed" << desc.uuid();
1363 service->setError(QLowEnergyService::DescriptorWriteError);
1366 service->characteristicList[charHandle].descriptorList[descriptorHandle].value = newValue;
1371 const QLowEnergyAdvertisingParameters ¶ms,
1372 const QLowEnergyAdvertisingData &advertisingData,
1373 const QLowEnergyAdvertisingData &scanResponseData)
1375 error = QLowEnergyController::NoError;
1376 errorString.clear();
1378 Q_ASSERT(peripheralApplication);
1379 Q_ASSERT(!adapterPathWithPeripheralSupport.isEmpty());
1385 advertiser =
nullptr;
1387 advertiser =
new QLeDBusAdvertiser(params, advertisingData, scanResponseData,
1388 adapterPathWithPeripheralSupport,
this);
1389 connect(advertiser, &QLeDBusAdvertiser::errorOccurred,
1390 this, &QLowEnergyControllerPrivateBluezDBus::handleAdvertisingError);
1392 setState(QLowEnergyController::AdvertisingState);
1401 advertiser->startAdvertising();
1407 setState(QLowEnergyController::UnconnectedState);
1409 advertiser->stopAdvertising();
1411 advertiser =
nullptr;
1420 if (advertiser && state == QLowEnergyController::AdvertisingState)
1421 advertiser->startAdvertising();
1427 QLowEnergyHandle handle,
const QByteArray& value)
1429 const auto characteristic = characteristicForHandle(handle);
1430 if (characteristic.d_ptr
1431 && updateValueOfCharacteristic(handle, value,
false) == value.size()) {
1432 emit characteristic.d_ptr->characteristicChanged(characteristic, value);
1434 qCWarning(QT_BT_BLUEZ) <<
"Remote characteristic write failed";
1439 QLowEnergyHandle characteristicHandle,
1440 QLowEnergyHandle descriptorHandle,
1441 const QByteArray& value)
1443 const auto descriptor = descriptorForHandle(descriptorHandle);
1444 if (descriptor.d_ptr && updateValueOfDescriptor(
1445 characteristicHandle, descriptorHandle, value,
false) == value.size()) {
1446 emit descriptor.d_ptr->descriptorWritten(descriptor, value);
1448 qCWarning(QT_BT_BLUEZ) <<
"Remote descriptor write failed";
1453 const QBluetoothAddress& address,
1454 const QString& name,
1457 remoteDevice = address;
1464 Q_ASSERT(peripheralApplication);
1465 qCWarning(QT_BT_BLUEZ) <<
"An advertising error occurred";
1466 setError(QLowEnergyController::AdvertisingError);
1467 setState(QLowEnergyController::UnconnectedState);
1473 qCWarning(QT_BT_BLUEZ) <<
"A Bluez peripheral application error occurred";
1474 setError(QLowEnergyController::UnknownError);
1475 setState(QLowEnergyController::UnconnectedState);
1480 Q_Q(QLowEnergyController);
1481 qCDebug(QT_BT_BLUEZ) <<
"Peripheral application connected change to:" << connected;
1483 setState(QLowEnergyController::ConnectedState);
1486 remoteDevice.clear();
1487 setState(QLowEnergyController::UnconnectedState);
1488 emit q->disconnected();
1493 const QLowEnergyConnectionParameters & )
1495 qCWarning(QT_BT_BLUEZ) <<
"Connection update requests not supported on Bluez DBus";
1499 const QLowEnergyServiceData &serviceData,
1500 QLowEnergyHandle startHandle)
1502 Q_ASSERT(peripheralApplication);
1503 QSharedPointer<QLowEnergyServicePrivate> servicePrivate = serviceForHandle(startHandle);
1504 if (servicePrivate.isNull())
1506 peripheralApplication->addService(serviceData, servicePrivate, startHandle);
1517#include "moc_qlowenergycontroller_bluezdbus_p.cpp"
QMap< QDBusObjectPath, InterfaceList > ManagedObjectList
QMap< QString, QVariantMap > InterfaceList
void requestConnectionUpdate(const QLowEnergyConnectionParameters ¶ms) override
QLowEnergyControllerPrivateBluezDBus(const QString &adapterPathWithPeripheralSupport={})
void startAdvertising(const QLowEnergyAdvertisingParameters ¶ms, const QLowEnergyAdvertisingData &advertisingData, const QLowEnergyAdvertisingData &scanResponseData) override
void discoverServiceDetails(const QBluetoothUuid &service, QLowEnergyService::DiscoveryMode mode) override
void discoverServices() override
~QLowEnergyControllerPrivateBluezDBus() override
void addToGenericAttributeList(const QLowEnergyServiceData &service, QLowEnergyHandle startHandle) override
void writeCharacteristic(const QSharedPointer< QLowEnergyServicePrivate > service, const QLowEnergyHandle charHandle, const QByteArray &newValue, QLowEnergyService::WriteMode writeMode) override
void writeDescriptor(const QSharedPointer< QLowEnergyServicePrivate > service, const QLowEnergyHandle charHandle, const QLowEnergyHandle descriptorHandle, const QByteArray &newValue) override
void disconnectFromDevice() override
void readDescriptor(const QSharedPointer< QLowEnergyServicePrivate > service, const QLowEnergyHandle charHandle, const QLowEnergyHandle descriptorHandle) override
void readCharacteristic(const QSharedPointer< QLowEnergyServicePrivate > service, const QLowEnergyHandle charHandle) override
void stopAdvertising() override
void connectToDevice() override
void invalidateServices()
void unregisterApplication()
void registerApplication()
bool registrationNeeded()