Index: CMakeLists.txt =================================================================== --- CMakeLists.txt +++ CMakeLists.txt @@ -4,7 +4,7 @@ project(BluezQt VERSION ${KF5_VERSION}) include(FeatureSummary) -find_package(ECM 5.59.0 NO_MODULE) +find_package(ECM 5.49.0 NO_MODULE) set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://projects.kde.org/projects/kdesupport/extra-cmake-modules") feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND FATAL_ON_MISSING_REQUIRED_PACKAGES) Index: autotests/CMakeLists.txt =================================================================== --- autotests/CMakeLists.txt +++ autotests/CMakeLists.txt @@ -32,6 +32,8 @@ mediaplayertest jobstest mediatest + leadvertisingmanagertest + gattmanagertest ) if(Qt5Qml_FOUND AND Qt5QuickTest_FOUND) Index: autotests/fakebluez/CMakeLists.txt =================================================================== --- autotests/fakebluez/CMakeLists.txt +++ autotests/fakebluez/CMakeLists.txt @@ -14,6 +14,8 @@ obexagentmanager.cpp obexclient.cpp mediainterface.cpp + leadvertisingmanagerinterface.cpp + gattmanagerinterface.cpp ) add_executable(fakebluez ${fakebluez_SRCS}) Index: autotests/fakebluez/adapterinterface.h =================================================================== --- autotests/fakebluez/adapterinterface.h +++ autotests/fakebluez/adapterinterface.h @@ -27,6 +27,8 @@ class QDBusObjectPath; +class GattManagerInterface; +class LEAdvertisingManagerInterface; class MediaInterface; class AdapterObject : public QObject @@ -87,6 +89,10 @@ MediaInterface *media() const; + LEAdvertisingManagerInterface *leAdvertisingManager() const; + + GattManagerInterface *gattManager() const; + public Q_SLOTS: void StartDiscovery(); void StopDiscovery(); @@ -98,6 +104,8 @@ private: MediaInterface *m_media; + LEAdvertisingManagerInterface *m_leAdvertisingManager; + GattManagerInterface *m_gattManager; }; #endif // ADAPTERINTERFACE_H Index: autotests/fakebluez/adapterinterface.cpp =================================================================== --- autotests/fakebluez/adapterinterface.cpp +++ autotests/fakebluez/adapterinterface.cpp @@ -21,6 +21,8 @@ #include "adapterinterface.h" #include "objectmanager.h" #include "mediainterface.h" +#include "leadvertisingmanagerinterface.h" +#include "gattmanagerinterface.h" #include #include @@ -48,6 +50,14 @@ m_media = new MediaInterface(path, parent); ObjectManager *manager = ObjectManager::self(); manager->addObject(m_media); + + // LEAdvertisingManager interface + m_leAdvertisingManager = new LEAdvertisingManagerInterface(path, parent); + manager->addObject(m_leAdvertisingManager); + + // GattManager interface + m_gattManager = new GattManagerInterface(path, parent); + manager->addObject(m_gattManager); } QString AdapterInterface::address() const @@ -153,6 +163,16 @@ return m_media; } +LEAdvertisingManagerInterface *AdapterInterface::leAdvertisingManager() const +{ + return m_leAdvertisingManager; +} + +GattManagerInterface *AdapterInterface::gattManager() const +{ + return m_gattManager; +} + void AdapterInterface::StartDiscovery() { Object::changeProperty(QStringLiteral("Discovering"), true); Index: autotests/fakebluez/devicemanager.h =================================================================== --- autotests/fakebluez/devicemanager.h +++ autotests/fakebluez/devicemanager.h @@ -42,6 +42,8 @@ void runChangeAdapterProperty(const QVariantMap &properties); void runChangeDeviceProperty(const QVariantMap &properties); void runAdapterMediaAction(const QString action, const QVariantMap &properties); + void runAdapterLeAdvertisingManagerAction(const QString action, const QVariantMap &properties); + void runAdapterGattManagerAction(const QString action, const QVariantMap &properties); void runBug377405(); void runBug403289(const QVariantMap &properties); Index: autotests/fakebluez/devicemanager.cpp =================================================================== --- autotests/fakebluez/devicemanager.cpp +++ autotests/fakebluez/devicemanager.cpp @@ -23,6 +23,8 @@ #include "adapterinterface.h" #include "deviceinterface.h" #include "mediainterface.h" +#include "leadvertisingmanagerinterface.h" +#include "gattmanagerinterface.h" DeviceManager::DeviceManager(ObjectManager *parent) : QObject(parent) @@ -46,6 +48,10 @@ runChangeDeviceProperty(properties); } else if (actionName.startsWith(QLatin1String("adapter-media:"))) { runAdapterMediaAction(actionName.mid(14), properties); + } else if (actionName.startsWith(QLatin1String("adapter-leadvertisingmanager:"))) { + runAdapterLeAdvertisingManagerAction(actionName.mid(29), properties); + } else if (actionName.startsWith(QLatin1String("adapter-gattmanager:"))) { + runAdapterGattManagerAction(actionName.mid(20), properties); } else if (actionName == QLatin1String("bug377405")) { runBug377405(); } else if (actionName == QLatin1String("bug403289")) { @@ -121,6 +127,26 @@ adapter->media()->runAction(action, properties); } +void DeviceManager::runAdapterLeAdvertisingManagerAction(const QString action, const QVariantMap &properties) +{ + const QDBusObjectPath &path = properties.value(QStringLiteral("AdapterPath")).value(); + AdapterInterface *adapter = dynamic_cast(m_objectManager->objectByPath(path)); + if (!adapter) { + return; + } + adapter->leAdvertisingManager()->runAction(action, properties); +} + +void DeviceManager::runAdapterGattManagerAction(const QString action, const QVariantMap &properties) +{ + const QDBusObjectPath &path = properties.value(QStringLiteral("AdapterPath")).value(); + AdapterInterface *adapter = dynamic_cast(m_objectManager->objectByPath(path)); + if (!adapter) { + return; + } + adapter->gattManager()->runAction(action, properties); +} + void DeviceManager::runBug377405() { QDBusObjectPath adapter1path = QDBusObjectPath(QStringLiteral("/org/bluez/hci0")); Index: autotests/fakebluez/gattmanagerinterface.h =================================================================== --- autotests/fakebluez/gattmanagerinterface.h +++ autotests/fakebluez/gattmanagerinterface.h @@ -41,7 +41,7 @@ void UnregisterApplication(const QDBusObjectPath &path, const QDBusMessage &msg); private: - void runGetObjectsAction(const QVariantMap &properties); + void runGetObjectsAction(); void runReadCharcAction(const QVariantMap &properties); void runWriteCharcAction(const QVariantMap &properties); Index: autotests/fakebluez/gattmanagerinterface.cpp =================================================================== --- autotests/fakebluez/gattmanagerinterface.cpp +++ autotests/fakebluez/gattmanagerinterface.cpp @@ -37,7 +37,7 @@ void GattManagerInterface::runAction(const QString &actionName, const QVariantMap &properties) { if (actionName == QLatin1String("get-objects")) { - runGetObjectsAction(properties); + runGetObjectsAction(); } else if (actionName == QLatin1String("read-charc")) { runReadCharcAction(properties); } else if (actionName == QLatin1String("write-charc")) { @@ -59,7 +59,7 @@ } } -void GattManagerInterface::runGetObjectsAction(const QVariantMap &properties) +void GattManagerInterface::runGetObjectsAction() { QDBusMessage call = QDBusMessage::createMethodCall(m_service, m_application.path(), Index: autotests/fakebluez/leadvertisingmanagerinterface.h =================================================================== --- autotests/fakebluez/leadvertisingmanagerinterface.h +++ autotests/fakebluez/leadvertisingmanagerinterface.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2015 David Rosca + * Copyright (C) 2019 Manuel Weichselbaumer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,35 +18,31 @@ * License along with this library. If not, see . */ -#ifndef DEVICEMANAGER_H -#define DEVICEMANAGER_H +#pragma once -#include +#include "object.h" -class ObjectManager; +#include -class DeviceManager : public QObject +class QDBusMessage; + +class LEAdvertisingManagerInterface : public QDBusAbstractAdaptor, public Object { Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.bluez.LEAdvertisingManager1") public: - explicit DeviceManager(ObjectManager *parent = nullptr); + explicit LEAdvertisingManagerInterface(const QDBusObjectPath &path, QObject *parent = nullptr); void runAction(const QString &actionName, const QVariantMap &properties); +public Q_SLOTS: + void RegisterAdvertisement(const QDBusObjectPath &path, const QVariantMap &options, const QDBusMessage &msg); + void UnregisterAdvertisement(const QDBusObjectPath &path, const QDBusMessage &msg); + private: - void runCreateAdapterAction(const QVariantMap &properties); - void runCreateDeviceAction(const QVariantMap &properties); - void runRemoveAdapterAction(const QVariantMap &properties); - void runRemoveDeviceAction(const QVariantMap &properties); - void runChangeAdapterProperty(const QVariantMap &properties); - void runChangeDeviceProperty(const QVariantMap &properties); - void runAdapterMediaAction(const QString action, const QVariantMap &properties); - void runBug377405(); - void runBug403289(const QVariantMap &properties); - - ObjectManager *m_objectManager; + void runReleaseAction(); + QDBusObjectPath m_advertisement; + QString m_service; }; - -#endif // DEVICEMANAGER_H Index: autotests/fakebluez/leadvertisingmanagerinterface.cpp =================================================================== --- /dev/null +++ autotests/fakebluez/leadvertisingmanagerinterface.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2019 Manuel Weichselbaumer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) version 3, or any + * later version accepted by the membership of KDE e.V. (or its + * successor approved by the membership of KDE e.V.), which shall + * act as a proxy defined in Section 6 of version 3 of the license. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "leadvertisingmanagerinterface.h" + +#include +#include +#include +#include + +LEAdvertisingManagerInterface::LEAdvertisingManagerInterface(const QDBusObjectPath &path, QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + setName(QStringLiteral("org.bluez.LEAdvertisingManager1")); + setPath(path); +} + +void LEAdvertisingManagerInterface::runAction(const QString &actionName, const QVariantMap &/*properties*/) +{ + if (actionName == QLatin1String("release")) { + runReleaseAction(); + } +} + +void LEAdvertisingManagerInterface::RegisterAdvertisement(const QDBusObjectPath &path, const QVariantMap &/*options*/, const QDBusMessage &msg) +{ + m_advertisement = path; + m_service = msg.service(); +} + +void LEAdvertisingManagerInterface::UnregisterAdvertisement(const QDBusObjectPath &path, const QDBusMessage &msg) +{ + if (m_advertisement == path && m_service == msg.service()) { + m_advertisement = QDBusObjectPath(); + m_service.clear(); + } +} + +void LEAdvertisingManagerInterface::runReleaseAction() +{ + QDBusMessage call = QDBusMessage::createMethodCall(m_service, + m_advertisement.path(), + QStringLiteral("org.bluez.LEAdvertisement1"), + QStringLiteral("Release")); + QDBusConnection::sessionBus().asyncCall(call); +} Index: autotests/gattmanagertest.h =================================================================== --- /dev/null +++ autotests/gattmanagertest.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2019 Manuel Weichselbaumer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) version 3, or any + * later version accepted by the membership of KDE e.V. (or its + * successor approved by the membership of KDE e.V.), which shall + * act as a proxy defined in Section 6 of version 3 of the license. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#pragma once + +#include "gattapplication.h" +#include "gattcharacteristic.h" +#include "adapter.h" + +class TestApplication : public BluezQt::GattApplication +{ +public: + using BluezQt::GattApplication::GattApplication; + DBusManagerStruct getManagedObjects() const override; + + mutable bool m_getObjectsCalled = false; +}; + +class GattManagerTest : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + + void getObjectsTest(); + void readCharcTest(); + void writeCharcTest(); + +private: + TestApplication *m_application; + BluezQt::GattCharacteristic *m_characteristic; + BluezQt::AdapterPtr m_adapter; +}; Index: autotests/gattmanagertest.cpp =================================================================== --- autotests/gattmanagertest.cpp +++ autotests/gattmanagertest.cpp @@ -66,7 +66,7 @@ m_adapter = manager->adapters().at(0); QVERIFY(m_adapter->gattManager()); - m_application = new TestApplication(this); + m_application = new TestApplication(QStringLiteral("/org/kde/bluez-qt"), this); auto service = new GattService(QStringLiteral("ad100000-d901-11e8-9f8b-f2801f1b9fd1"), true, m_application); m_characteristic = new GattCharacteristic(QStringLiteral("ad10e100-d901-11e8-9f8b-f2801f1b9fd1"), service); m_adapter->gattManager()->registerApplication(m_application)->waitForFinished(); Index: autotests/leadvertisingmanagertest.h =================================================================== --- /dev/null +++ autotests/leadvertisingmanagertest.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2019 Manuel Weichselbaumer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) version 3, or any + * later version accepted by the membership of KDE e.V. (or its + * successor approved by the membership of KDE e.V.), which shall + * act as a proxy defined in Section 6 of version 3 of the license. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#pragma once + +#include "leadvertisement.h" +#include "adapter.h" + +class TestAdvertisement : public BluezQt::LEAdvertisement +{ + Q_OBJECT + +public: + using BluezQt::LEAdvertisement::LEAdvertisement; + void release() override; + + // release + bool m_releaseCalled = false; +}; + +class LEAdvertisingManagerTest : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + + void releaseTest(); + +private: + TestAdvertisement* m_advertisement; + BluezQt::AdapterPtr m_adapter; +}; Index: autotests/leadvertisingmanagertest.cpp =================================================================== --- /dev/null +++ autotests/leadvertisingmanagertest.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2019 Manuel Weichselbaumer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) version 3, or any + * later version accepted by the membership of KDE e.V. (or its + * successor approved by the membership of KDE e.V.), which shall + * act as a proxy defined in Section 6 of version 3 of the license. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "leadvertisingmanagertest.h" +#include "autotests.h" +#include "initmanagerjob.h" +#include "leadvertisingmanager.h" +#include "manager.h" +#include "pendingcall.h" + +#include +#include +#include + +namespace BluezQt +{ +extern void bluezqt_initFakeBluezTestRun(); +} + +using namespace BluezQt; + +void TestAdvertisement::release() +{ + m_releaseCalled = true; +} + +void LEAdvertisingManagerTest::initTestCase() +{ + bluezqt_initFakeBluezTestRun(); + FakeBluez::start(); + FakeBluez::runTest(QStringLiteral("bluez-standard")); + + // Create adapter + QString adapter = QStringLiteral("/org/bluez/hci0"); + QVariantMap adapterProps; + adapterProps[QStringLiteral("Path")] = QVariant::fromValue(QDBusObjectPath(adapter)); + adapterProps[QStringLiteral("Address")] = QStringLiteral("1C:E5:C3:BC:94:7E"); + adapterProps[QStringLiteral("Name")] = QStringLiteral("TestAdapter"); + FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("create-adapter"), adapterProps); + + Manager *manager = new Manager(this); + InitManagerJob *initJob = manager->init(); + initJob->exec(); + QVERIFY(!initJob->error()); + QCOMPARE(manager->adapters().count(), 1); + + m_adapter = manager->adapters().at(0); + QVERIFY(m_adapter->leAdvertisingManager()); + + m_advertisement = new TestAdvertisement({QStringLiteral("ad100000-d901-11e8-9f8b-f2801f1b9fd1")}, this); + auto call = m_adapter->leAdvertisingManager()->registerAdvertisement(m_advertisement); + call->waitForFinished(); + QVERIFY(!call->error()); +} + +void LEAdvertisingManagerTest::cleanupTestCase() +{ + FakeBluez::stop(); +} + +void LEAdvertisingManagerTest::releaseTest() +{ + QCOMPARE(m_advertisement->m_releaseCalled, false); + + QVariantMap params; + params.insert(QStringLiteral("AdapterPath"), QVariant::fromValue(QDBusObjectPath(m_adapter->ubi()))); + FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("adapter-leadvertisingmanager:release"), params); + + QTRY_COMPARE(m_advertisement->m_releaseCalled, true); +} + +QTEST_MAIN(LEAdvertisingManagerTest) Index: src/CMakeLists.txt =================================================================== --- src/CMakeLists.txt +++ src/CMakeLists.txt @@ -12,6 +12,7 @@ gattcharacteristic_p.cpp gattcharacteristicadaptor.cpp gattmanager.cpp + gattmanager_p.cpp gattservice.cpp gattservice_p.cpp gattserviceadaptor.cpp Index: src/adapter.h =================================================================== --- src/adapter.h +++ src/adapter.h @@ -60,6 +60,7 @@ Q_PROPERTY(bool discovering READ isDiscovering NOTIFY discoveringChanged) Q_PROPERTY(QStringList uuids READ uuids NOTIFY uuidsChanged) Q_PROPERTY(QString modalias READ modalias NOTIFY modaliasChanged) + Q_PROPERTY(LEAdvertisingManagerPtr leAdvertisingManager READ leAdvertisingManager NOTIFY leAdvertisingManagerChanged) Q_PROPERTY(MediaPtr media READ media NOTIFY mediaChanged) Q_PROPERTY(QList devices READ devices) @@ -231,6 +232,20 @@ */ QString modalias() const; + /** + * Returns the GATT manager interface for the adapter. + * + * @return null if adapter have no GATT manager + */ + GattManagerPtr gattManager() const; + + /** + * Returns the LE advertising manager interface for the adapter. + * + * @return null if adapter have no Bluetooth LE + */ + LEAdvertisingManagerPtr leAdvertisingManager() const; + /** * Returns the media interface for the adapter. * @@ -350,6 +365,16 @@ */ void modaliasChanged(const QString &modalias); + /** + * Indicates that adapter's GATT manager have changed. + */ + void gattManagerChanged(GattManagerPtr gattManager); + + /** + * Indicates that adapter's LE advertising manager have changed. + */ + void leAdvertisingManagerChanged(LEAdvertisingManagerPtr leAdvertisingManager); + /** * Indicates that adapter's media have changed. */ Index: src/adapter.cpp =================================================================== --- src/adapter.cpp +++ src/adapter.cpp @@ -146,6 +146,16 @@ return d->m_modalias; } +GattManagerPtr Adapter::gattManager() const +{ + return d->m_gattManager; +} + +LEAdvertisingManagerPtr Adapter::leAdvertisingManager() const +{ + return d->m_leAdvertisingManager; +} + MediaPtr Adapter::media() const { return d->m_media; Index: src/adapter_p.h =================================================================== --- src/adapter_p.h +++ src/adapter_p.h @@ -73,6 +73,8 @@ QList m_devices; QString m_modalias; MediaPtr m_media; + GattManagerPtr m_gattManager; + LEAdvertisingManagerPtr m_leAdvertisingManager; }; } // namespace BluezQt Index: src/adapter_p.cpp =================================================================== --- src/adapter_p.cpp +++ src/adapter_p.cpp @@ -24,6 +24,9 @@ #include "adapter.h" #include "utils.h" #include "macros.h" +#include "gattmanager.h" +#include "leadvertisingmanager.h" +#include "leadvertisingmanager_p.h" #include "media.h" #include "media_p.h" @@ -74,6 +77,14 @@ m_media = MediaPtr(new Media(path)); Q_EMIT q.data()->mediaChanged(m_media); changed = true; + } else if (it.key() == Strings::orgBluezLEAdvertisingManager1()) { + m_leAdvertisingManager = LEAdvertisingManagerPtr(new LEAdvertisingManager(path)); + Q_EMIT q.data()->leAdvertisingManagerChanged(m_leAdvertisingManager); + changed = true; + } else if (it.key() == Strings::orgBluezGattManager1()) { + m_gattManager = GattManagerPtr(new GattManager(path)); + Q_EMIT q.data()->gattManagerChanged(m_gattManager); + changed = true; } } @@ -91,6 +102,10 @@ m_media.clear(); Q_EMIT q.data()->mediaChanged(m_media); changed = true; + } else if (interface == Strings::orgBluezLEAdvertisingManager1() && m_leAdvertisingManager && m_leAdvertisingManager->d->m_path == path) { + m_leAdvertisingManager.clear(); + Q_EMIT q.data()->leAdvertisingManagerChanged(m_leAdvertisingManager); + changed = true; } } Index: src/gattapplication.h =================================================================== --- src/gattapplication.h +++ src/gattapplication.h @@ -1,7 +1,7 @@ /* * BluezQt - Asynchronous BlueZ wrapper library * - * Copyright (C) 2018 Manuel Weichselbaumer + * Copyright (C) 2019 Manuel Weichselbaumer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -44,7 +44,7 @@ * * @param parent */ - explicit GattApplication(QObject *parent = nullptr); + explicit GattApplication(const QString &objectPathPrefix, QObject *parent = nullptr); /** * Destroys a GattApplication object. Index: src/gattapplication.cpp =================================================================== --- src/gattapplication.cpp +++ src/gattapplication.cpp @@ -1,7 +1,7 @@ /* * BluezQt - Asynchronous Bluez wrapper library * - * Copyright (C) 2018 Manuel Weichselbaumer + * Copyright (C) 2019 Manuel Weichselbaumer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -35,9 +35,9 @@ namespace BluezQt { -GattApplication::GattApplication(QObject *parent) : - ObjectManager(parent), - d(new GattApplicationPrivate()) +GattApplication::GattApplication(const QString &objectPathPrefix, QObject *parent) + : ObjectManager(parent) + , d(new GattApplicationPrivate(objectPathPrefix)) { } @@ -50,8 +50,8 @@ { DBusManagerStruct objects; - auto serviceAdaptors = findChildren(); - auto charcAdaptors = findChildren(); + const auto serviceAdaptors = findChildren(); + const auto charcAdaptors = findChildren(); for (const GattServiceAdaptor *serviceAdaptor : serviceAdaptors) { QVariantMap properties; @@ -61,7 +61,7 @@ properties.insert(QString::fromLatin1(propertyName), serviceAdaptor->property(propertyName)); } - GattService* service = qobject_cast(serviceAdaptor->parent()); + GattService *service = qobject_cast(serviceAdaptor->parent()); if (service) { objects[service->objectPath()].insert(QStringLiteral("org.bluez.GattService1"), properties); } Index: src/gattapplication_p.h =================================================================== --- src/gattapplication_p.h +++ src/gattapplication_p.h @@ -1,7 +1,7 @@ /* * BluezQt - Asynchronous BlueZ wrapper library * - * Copyright (C) 2018 Manuel Weichselbaumer + * Copyright (C) 2019 Manuel Weichselbaumer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -30,7 +30,7 @@ class GattApplicationPrivate { public: - GattApplicationPrivate(); + GattApplicationPrivate(const QString &objectPathPrefix); QDBusObjectPath m_objectPath; }; Index: src/gattapplication_p.cpp =================================================================== --- src/gattapplication_p.cpp +++ src/gattapplication_p.cpp @@ -1,7 +1,7 @@ /* * BluezQt - Asynchronous Bluez wrapper library * - * Copyright (C) 2018 Manuel Weichselbaumer + * Copyright (C) 2019 Manuel Weichselbaumer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,10 +25,10 @@ namespace BluezQt { -GattApplicationPrivate::GattApplicationPrivate() +GattApplicationPrivate::GattApplicationPrivate(const QString &objectPathPrefix) { static uint8_t appNumber = 0; - m_objectPath.setPath(QStringLiteral("/org/bluez/app") + QString::number(appNumber++)); + m_objectPath.setPath(objectPathPrefix + QStringLiteral("/app") + QString::number(appNumber++)); } } // namespace BluezQt Index: src/gattcharacteristic.h =================================================================== --- src/gattcharacteristic.h +++ src/gattcharacteristic.h @@ -1,7 +1,7 @@ /* * BluezQt - Asynchronous BlueZ wrapper library * - * Copyright (C) 2018 Manuel Weichselbaumer + * Copyright (C) 2019 Manuel Weichselbaumer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public Index: src/gattcharacteristic.cpp =================================================================== --- src/gattcharacteristic.cpp +++ src/gattcharacteristic.cpp @@ -1,7 +1,7 @@ /* * BluezQt - Asynchronous Bluez wrapper library * - * Copyright (C) 2018 Manuel Weichselbaumer + * Copyright (C) 2019 Manuel Weichselbaumer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,8 +28,8 @@ { GattCharacteristic::GattCharacteristic(const QString &uuid, GattService *service) - : QObject(service), - d(new GattCharacterisiticPrivate(uuid, service)) + : QObject(service) + , d(new GattCharacterisiticPrivate(uuid, service)) { } @@ -47,7 +47,7 @@ return d->m_value; } -void GattCharacteristic::writeValue(const QByteArray& value) +void GattCharacteristic::writeValue(const QByteArray &value) { d->m_value = value; emit valueWritten(d->m_value); Index: src/gattcharacteristic_p.h =================================================================== --- src/gattcharacteristic_p.h +++ src/gattcharacteristic_p.h @@ -1,7 +1,7 @@ /* * BluezQt - Asynchronous BlueZ wrapper library * - * Copyright (C) 2018 Manuel Weichselbaumer + * Copyright (C) 2019 Manuel Weichselbaumer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -36,7 +36,7 @@ QString m_uuid; const GattService *m_service; QDBusObjectPath m_objectPath; - QByteArray m_value; + QByteArray m_value; GattCharacteristic::ReadCallback m_readCallback = nullptr; }; Index: src/gattcharacteristic_p.cpp =================================================================== --- src/gattcharacteristic_p.cpp +++ src/gattcharacteristic_p.cpp @@ -1,7 +1,7 @@ /* * BluezQt - Asynchronous Bluez wrapper library * - * Copyright (C) 2018 Manuel Weichselbaumer + * Copyright (C) 2019 Manuel Weichselbaumer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -27,8 +27,8 @@ { GattCharacterisiticPrivate::GattCharacterisiticPrivate(const QString &uuid, const GattService *service) - : m_uuid(uuid), - m_service(service) + : m_uuid(uuid) + , m_service(service) { static uint8_t charcNumber = 0; m_objectPath.setPath(m_service->objectPath().path() + QStringLiteral("/char") + QString::number(charcNumber++)); Index: src/gattcharacteristicadaptor.h =================================================================== --- src/gattcharacteristicadaptor.h +++ src/gattcharacteristicadaptor.h @@ -55,7 +55,7 @@ void StopNotify(); private: - GattCharacteristic* m_gattCharacteristic; + GattCharacteristic *m_gattCharacteristic; }; } // namespace BluezQt Index: src/gattcharacteristicadaptor.cpp =================================================================== --- src/gattcharacteristicadaptor.cpp +++ src/gattcharacteristicadaptor.cpp @@ -55,6 +55,7 @@ { return m_gattCharacteristic->readValue(); } + void GattCharacteristicAdaptor::WriteValue(const QByteArray &value, const QVariantMap &/*options*/) { m_gattCharacteristic->writeValue(value); Index: src/gattmanager.h =================================================================== --- src/gattmanager.h +++ src/gattmanager.h @@ -1,7 +1,7 @@ /* * BluezQt - Asynchronous BlueZ wrapper library * - * Copyright (C) 2018 Manuel Weichselbaumer + * Copyright (C) 2019 Manuel Weichselbaumer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -27,8 +27,6 @@ #include "bluezqt_dbustypes.h" #include "bluezqt_export.h" -class QDBusInterface; - namespace BluezQt { @@ -102,7 +100,7 @@ private: explicit GattManager(const QString &path, QObject *parent = nullptr); - QDBusInterface *m_dbusInterface = nullptr; + class GattManagerPrivate *const d; friend class AdapterPrivate; }; Index: src/gattmanager.cpp =================================================================== --- src/gattmanager.cpp +++ src/gattmanager.cpp @@ -25,11 +25,11 @@ #include "gattapplication.h" #include "gattcharacteristic.h" #include "gattcharacteristicadaptor.h" +#include "gattmanager_p.h" #include "gattservice.h" #include "gattserviceadaptor.h" #include "objectmanageradaptor.h" #include "pendingcall.h" -#include "propertiesadaptor.h" #include "utils.h" #include "debug.h" @@ -41,34 +41,25 @@ GattManager::GattManager(const QString &path, QObject *parent) : QObject(parent) + , d(new GattManagerPrivate(path)) { - m_dbusInterface = new QDBusInterface(Strings::orgBluez(), - path, - QStringLiteral("org.bluez.GattManager1"), - DBusConnection::orgBluez(), - this); } GattManager::~GattManager() { + delete d; } PendingCall *GattManager::registerApplication(GattApplication *application) { Q_ASSERT(application); - for (auto child : application->children()) { - GattService* service = qobject_cast(child); - if (!service) { - continue; - } + const auto services = application->findChildren(); + for (auto service : services) { new GattServiceAdaptor(service); - for (auto serviceChild : service->children()) { - GattCharacteristic* charc = qobject_cast(serviceChild); - if (!charc) { - continue; - } + const auto charcs = service->findChildren(); + for (auto charc : charcs) { new GattCharacteristicAdaptor(charc); if (!DBusConnection::orgBluez().registerObject(charc->objectPath().path(), charc, @@ -94,7 +85,7 @@ QList argumentList; argumentList << QVariant::fromValue(application->objectPath()) << QVariantMap(); - return new PendingCall(m_dbusInterface->asyncCallWithArgumentList(QStringLiteral("RegisterApplication"), argumentList), + return new PendingCall(d->m_dbusInterface->asyncCallWithArgumentList(QStringLiteral("RegisterApplication"), argumentList), PendingCall::ReturnVoid, this); } @@ -106,7 +97,7 @@ QList argumentList; argumentList << QVariant::fromValue(application->objectPath()); - return new PendingCall(m_dbusInterface->asyncCallWithArgumentList(QStringLiteral("UnregisterApplication"), argumentList), + return new PendingCall(d->m_dbusInterface->asyncCallWithArgumentList(QStringLiteral("UnregisterApplication"), argumentList), PendingCall::ReturnVoid, this); } Index: src/gattmanager_p.h =================================================================== --- src/gattmanager_p.h +++ src/gattmanager_p.h @@ -1,7 +1,7 @@ /* * BluezQt - Asynchronous BlueZ wrapper library * - * Copyright (C) 2018 Manuel Weichselbaumer + * Copyright (C) 2019 Manuel Weichselbaumer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,17 +22,19 @@ #pragma once -#include +class QDBusInterface; +class QString; namespace BluezQt { -class GattApplicationPrivate +class GattManagerPrivate { public: - GattApplicationPrivate(); + GattManagerPrivate(const QString &path); + ~GattManagerPrivate(); - QDBusObjectPath m_objectPath; + QDBusInterface *m_dbusInterface = nullptr; }; } // namespace BluezQt Index: src/gattmanager_p.cpp =================================================================== --- src/gattmanager_p.cpp +++ src/gattmanager_p.cpp @@ -1,7 +1,7 @@ /* * BluezQt - Asynchronous Bluez wrapper library * - * Copyright (C) 2018 Manuel Weichselbaumer + * Copyright (C) 2019 Manuel Weichselbaumer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,31 +20,25 @@ * License along with this library. If not, see . */ -#include "gattserviceadaptor.h" +#include "gattmanager_p.h" +#include "utils.h" -#include "gattservice.h" -#include "request.h" - -#include -#include +#include namespace BluezQt { -GattServiceAdaptor::GattServiceAdaptor(GattService *parent) - : QDBusAbstractAdaptor(parent) - , m_gattService(parent) -{ -} - -QString GattServiceAdaptor::uuid() const +GattManagerPrivate::GattManagerPrivate(const QString &path) { - return m_gattService->uuid(); + m_dbusInterface = new QDBusInterface(Strings::orgBluez(), + path, + QStringLiteral("org.bluez.GattManager1"), + DBusConnection::orgBluez()); } -bool GattServiceAdaptor::primary() const +GattManagerPrivate::~GattManagerPrivate() { - return m_gattService->isPrimary(); + delete m_dbusInterface; } } // namespace BluezQt Index: src/gattservice.h =================================================================== --- src/gattservice.h +++ src/gattservice.h @@ -1,7 +1,7 @@ /* * BluezQt - Asynchronous BlueZ wrapper library * - * Copyright (C) 2018 Manuel Weichselbaumer + * Copyright (C) 2019 Manuel Weichselbaumer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public Index: src/gattservice.cpp =================================================================== --- src/gattservice.cpp +++ src/gattservice.cpp @@ -1,7 +1,7 @@ /* * BluezQt - Asynchronous Bluez wrapper library * - * Copyright (C) 2018 Manuel Weichselbaumer + * Copyright (C) 2019 Manuel Weichselbaumer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,8 +28,8 @@ { GattService::GattService(const QString &uuid, bool isPrimary, GattApplication *parent) - : QObject(parent), - d(new GattServicePrivate(uuid, isPrimary, parent->objectPath().path())) + : QObject(parent) + , d(new GattServicePrivate(uuid, isPrimary, parent->objectPath().path())) { } Index: src/gattservice_p.h =================================================================== --- src/gattservice_p.h +++ src/gattservice_p.h @@ -1,7 +1,7 @@ /* * BluezQt - Asynchronous BlueZ wrapper library * - * Copyright (C) 2018 Manuel Weichselbaumer + * Copyright (C) 2019 Manuel Weichselbaumer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public Index: src/gattservice_p.cpp =================================================================== --- src/gattservice_p.cpp +++ src/gattservice_p.cpp @@ -1,7 +1,7 @@ /* * BluezQt - Asynchronous Bluez wrapper library * - * Copyright (C) 2018 Manuel Weichselbaumer + * Copyright (C) 2019 Manuel Weichselbaumer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -26,8 +26,8 @@ { GattServicePrivate::GattServicePrivate(const QString &uuid, bool isPrimary, const QString &appPath) - : m_uuid(uuid), - m_isPrimary(isPrimary) + : m_uuid(uuid) + , m_isPrimary(isPrimary) { static uint8_t serviceNumber = 0; m_objectPath.setPath(appPath + QStringLiteral("/service") + QString::number(serviceNumber++)); Index: src/gattserviceadaptor.h =================================================================== --- src/gattserviceadaptor.h +++ src/gattserviceadaptor.h @@ -1,7 +1,7 @@ /* * BluezQt - Asynchronous Bluez wrapper library * - * Copyright (C) 2018 Manuel Weichselbaumer + * Copyright (C) 2019 Manuel Weichselbaumer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public Index: src/gattserviceadaptor.cpp =================================================================== --- src/gattserviceadaptor.cpp +++ src/gattserviceadaptor.cpp @@ -1,7 +1,7 @@ /* * BluezQt - Asynchronous Bluez wrapper library * - * Copyright (C) 2018 Manuel Weichselbaumer + * Copyright (C) 2019 Manuel Weichselbaumer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public Index: src/interfaces/org.bluez.GattCharacteristic1.xml =================================================================== --- /dev/null +++ src/interfaces/org.bluez.GattCharacteristic1.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + Index: src/interfaces/org.bluez.GattManager1.xml =================================================================== --- /dev/null +++ src/interfaces/org.bluez.GattManager1.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + Index: src/interfaces/org.bluez.LEAdvertisement1.xml =================================================================== --- /dev/null +++ src/interfaces/org.bluez.LEAdvertisement1.xml @@ -0,0 +1,7 @@ + + + + + + + Index: src/interfaces/org.bluez.LEAdvertisingManager1.xml =================================================================== --- /dev/null +++ src/interfaces/org.bluez.LEAdvertisingManager1.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + Index: src/leadvertisement.h =================================================================== --- /dev/null +++ src/leadvertisement.h @@ -0,0 +1,96 @@ +/* + * BluezQt - Asynchronous BlueZ wrapper library + * + * Copyright (C) 2019 Manuel Weichselbaumer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) version 3, or any + * later version accepted by the membership of KDE e.V. (or its + * successor approved by the membership of KDE e.V.), which shall + * act as a proxy defined in Section 6 of version 3 of the license. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef BLUEZQT_LEADVERTISEMENT_H +#define BLUEZQT_LEADVERTISEMENT_H + +#include + +#include "bluezqt_export.h" + +class QDBusObjectPath; + +namespace BluezQt +{ + +/** + * @class BluezQt::LEAdvertisement leadvertisement.h + * + * Bluetooth LE advertisement. + * + * This class represents a Bluetooth LE advertisement. + */ +class BLUEZQT_EXPORT LEAdvertisement : public QObject +{ + Q_OBJECT + +public: + /** + * Creates a new LEAdvertisement object. + * + * @param parent + */ + explicit LEAdvertisement(const QStringList &serviceUuids, QObject *parent = nullptr); + + /** + * Destroys a LEAdvertisement object. + */ + ~LEAdvertisement(); + + /** + * List of UUIDs to include in the "Service UUID" field of the Advertising Data. + * + * @return UUIDs of the advertisement + */ + virtual QStringList serviceUuids() const; + + /** + * Indicates that the LEAdvertisement was unregistered. + * + * This method gets called when the service daemon removes the Advertisement. + * A client can use it to do cleanup tasks. There is no need to call + * UnregisterAdvertisement because when this method gets called it has + * already been unregistered. + */ + virtual void release(); + +protected: + /** + * D-Bus object path of the advertisement. + * + * The path where the advertisement will be registered. + * + * @note You must provide valid object path! + * + * @return object path of advertisement + */ + virtual QDBusObjectPath objectPath() const; + +private: + class LEAdvertisementPrivate *const d; + + friend class LEAdvertisingManager; +}; + +} // namespace BluezQt + +#endif // BLUEZQT_LEADVERTISEMENT_H Index: src/leadvertisement.cpp =================================================================== --- /dev/null +++ src/leadvertisement.cpp @@ -0,0 +1,54 @@ +/* + * BluezQt - Asynchronous Bluez wrapper library + * + * Copyright (C) 2019 Manuel Weichselbaumer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) version 3, or any + * later version accepted by the membership of KDE e.V. (or its + * successor approved by the membership of KDE e.V.), which shall + * act as a proxy defined in Section 6 of version 3 of the license. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "leadvertisement.h" +#include "leadvertisement_p.h" + +namespace BluezQt +{ + +LEAdvertisement::LEAdvertisement(const QStringList &serviceUuids, QObject *parent) + : QObject(parent), + d(new LEAdvertisementPrivate(serviceUuids)) +{ +} + +LEAdvertisement::~LEAdvertisement() +{ + delete d; +} + +QDBusObjectPath LEAdvertisement::objectPath() const +{ + return d->m_objectPath; +} + +QStringList LEAdvertisement::serviceUuids() const +{ + return d->m_serviceUuids; +} + +void LEAdvertisement::release() +{ +} + +} // namespace BluezQt Index: src/leadvertisement_p.h =================================================================== --- /dev/null +++ src/leadvertisement_p.h @@ -0,0 +1,41 @@ +/* + * BluezQt - Asynchronous Bluez wrapper library + * + * Copyright (C) 2019 Manuel Weichselbaumer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) version 3, or any + * later version accepted by the membership of KDE e.V. (or its + * successor approved by the membership of KDE e.V.), which shall + * act as a proxy defined in Section 6 of version 3 of the license. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef BLUEZQT_LEADVERTISEMENT_P_H +#define BLUEZQT_LEADVERTISEMENT_P_H + +#include + +namespace BluezQt +{ + +class LEAdvertisementPrivate +{ +public: + explicit LEAdvertisementPrivate(const QStringList &serviceUuids); + QStringList m_serviceUuids; + QDBusObjectPath m_objectPath; +}; + +} // namespace BluezQt + +#endif // BLUEZQT_LEADVERTISEMENT_P_H Index: src/leadvertisement_p.cpp =================================================================== --- /dev/null +++ src/leadvertisement_p.cpp @@ -0,0 +1,36 @@ +/* + * BluezQt - Asynchronous Bluez wrapper library + * + * Copyright (C) 2019 Manuel Weichselbaumer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) version 3, or any + * later version accepted by the membership of KDE e.V. (or its + * successor approved by the membership of KDE e.V.), which shall + * act as a proxy defined in Section 6 of version 3 of the license. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "leadvertisement_p.h" + +namespace BluezQt +{ + +LEAdvertisementPrivate::LEAdvertisementPrivate(const QStringList &serviceUuids) + : m_serviceUuids(serviceUuids) +{ + static uint8_t advNumber = 0; + QString objectPath = QStringLiteral("/org/bluez/lead") + QString::number(advNumber++); + m_objectPath.setPath(objectPath); +} + +} // namespace BluezQt Index: src/leadvertisementadaptor.h =================================================================== --- /dev/null +++ src/leadvertisementadaptor.h @@ -0,0 +1,56 @@ +/* + * BluezQt - Asynchronous Bluez wrapper library + * + * Copyright (C) 2019 Manuel Weichselbaumer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) version 3, or any + * later version accepted by the membership of KDE e.V. (or its + * successor approved by the membership of KDE e.V.), which shall + * act as a proxy defined in Section 6 of version 3 of the license. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef BLUEZQT_LEADVERTISEMENTADAPTOR_H +#define BLUEZQT_LEADVERTISEMENTADAPTOR_H + +#include + +namespace BluezQt +{ + +class LEAdvertisement; + +class LEAdvertisementAdaptor : public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.bluez.LEAdvertisement1") + Q_PROPERTY(QString Type READ type) + Q_PROPERTY(QStringList ServiceUUIDs READ serviceUuids) + +public: + explicit LEAdvertisementAdaptor(LEAdvertisement *parent); + + QString type() const; + + QStringList serviceUuids() const; + +public Q_SLOTS: + Q_NOREPLY void Release(); + +private: + LEAdvertisement *m_advertisement; +}; + +} // namespace BluezQt + +#endif // BLUEZQT_LEADVERTISEMENTADAPTOR_H Index: src/leadvertisementadaptor.cpp =================================================================== --- /dev/null +++ src/leadvertisementadaptor.cpp @@ -0,0 +1,53 @@ +/* + * BluezQt - Asynchronous Bluez wrapper library + * + * Copyright (C) 2019 Manuel Weichselbaumer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) version 3, or any + * later version accepted by the membership of KDE e.V. (or its + * successor approved by the membership of KDE e.V.), which shall + * act as a proxy defined in Section 6 of version 3 of the license. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "leadvertisementadaptor.h" +#include "leadvertisement.h" + +#include +#include + +namespace BluezQt +{ + +LEAdvertisementAdaptor::LEAdvertisementAdaptor(LEAdvertisement *parent) + : QDBusAbstractAdaptor(parent) + , m_advertisement(parent) +{ +} + +QString LEAdvertisementAdaptor::type() const +{ + return QStringLiteral("peripheral"); +} + +QStringList LEAdvertisementAdaptor::serviceUuids() const +{ + return m_advertisement->serviceUuids(); +} + +void LEAdvertisementAdaptor::Release() +{ + m_advertisement->release(); +} + +} // namespace BluezQt Index: src/leadvertisingmanager.h =================================================================== --- /dev/null +++ src/leadvertisingmanager.h @@ -0,0 +1,100 @@ +/* + * BluezQt - Asynchronous BlueZ wrapper library + * + * Copyright (C) 2019 Manuel Weichselbaumer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) version 3, or any + * later version accepted by the membership of KDE e.V. (or its + * successor approved by the membership of KDE e.V.), which shall + * act as a proxy defined in Section 6 of version 3 of the license. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef BLUEZQT_LEADVERTISINGMANAGER_H +#define BLUEZQT_LEADVERTISINGMANAGER_H + +#include + +#include "bluezqt_export.h" + +namespace BluezQt +{ + +class LEAdvertisement; +class PendingCall; + +/** + * @class BluezQt::LEAdvertisingManager leadvertisingmanager.h + * + * Bluetooth LE advertising manager. + * + * The Advertising Manager allows external applications to register Advertisement + * Data which should be broadcast to devices. Advertisement Data elements must + * follow the API for LE Advertisement Data. + * + * @see LEAdvertisement + */ +class BLUEZQT_EXPORT LEAdvertisingManager : public QObject +{ + Q_OBJECT + +public: + /** + * Destroys an LEAdvertisingManager object. + */ + ~LEAdvertisingManager(); + + /** + * Registers advertisement. + * + * Registers an advertisement object to be sent over the LE Advertising + * channel. The service must be exported under interface LEAdvertisement1. + * + * InvalidArguments error indicates invalid or conflicting properties. + * InvalidLength error indicates that provided data results in too long data packet. + * The properties of this object are parsed on register, any changes are ignored. + * If the same object is registered twice it will result in an AlreadyExists error. + * NotPermitted error indicates that the maximum number of advertisements is reached. + * + * Possible errors: PendingCall::InvalidArguments, PendingCall::AlreadyExists, + * PendingCall::InvalidLength, PendingCall::NotPermitted + * + * @param advertisement advertisement to be registered + * @return void pending call + */ + PendingCall *registerAdvertisement(LEAdvertisement *advertisement); + + /** + * Unregisters advertisement. + * + * This unregisters an advertisement that has been previously registered. + * The object path must match the same value that has been used on registration. + * + * Possible errors: PendingCall::InvalidArguments, PendingCall::DoesNotExist + * + * @param advertisement advertisement to be unregistered + * @return void pending call + */ + PendingCall *unregisterAdvertisement(LEAdvertisement *advertisement); + +private: + explicit LEAdvertisingManager(const QString &path, QObject *parent = nullptr); + + class LEAdvertisingManagerPrivate *const d; + + friend class AdapterPrivate; +}; + +} // namespace BluezQt + +#endif // BLUEZQT_LEADVERTISINGMANAGER_H Index: src/leadvertisingmanager.cpp =================================================================== --- /dev/null +++ src/leadvertisingmanager.cpp @@ -0,0 +1,79 @@ +/* + * BluezQt - Asynchronous Bluez wrapper library + * + * Copyright (C) 2019 Manuel Weichselbaumer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) version 3, or any + * later version accepted by the membership of KDE e.V. (or its + * successor approved by the membership of KDE e.V.), which shall + * act as a proxy defined in Section 6 of version 3 of the license. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "leadvertisingmanager.h" +#include "leadvertisingmanager_p.h" +#include "leadvertisement.h" +#include "leadvertisementadaptor.h" +#include "pendingcall.h" +#include "utils.h" +#include "debug.h" + +namespace BluezQt +{ + +LEAdvertisingManager::LEAdvertisingManager(const QString &path, QObject *parent) + : QObject(parent) + , d(new LEAdvertisingManagerPrivate()) +{ + d->m_path = path; + d->m_bluezLEAdvertisingManager = new BluezLEAdvertisingManager(Strings::orgBluez(), path, DBusConnection::orgBluez(), this); +} + +LEAdvertisingManager::~LEAdvertisingManager() +{ + delete d; +} + +PendingCall *LEAdvertisingManager::registerAdvertisement(LEAdvertisement *advertisement) +{ + Q_ASSERT(advertisement); + + if (!d->m_bluezLEAdvertisingManager) { + return new PendingCall(PendingCall::InternalError, QStringLiteral("LEAdvertisingManager not operational!")); + } + + new LEAdvertisementAdaptor(advertisement); + + if (!DBusConnection::orgBluez().registerObject(advertisement->objectPath().path(), advertisement)) { + qCDebug(BLUEZQT) << "Cannot register object" << advertisement->objectPath().path(); + } + + return new PendingCall(d->m_bluezLEAdvertisingManager->RegisterAdvertisement(advertisement->objectPath(), QVariantMap()), + PendingCall::ReturnVoid, this); +} + +PendingCall *LEAdvertisingManager::unregisterAdvertisement(LEAdvertisement *advertisement) +{ + Q_ASSERT(advertisement); + + if (!d->m_bluezLEAdvertisingManager) { + return new PendingCall(PendingCall::InternalError, QStringLiteral("LEAdvertisingManager not operational!")); + } + + DBusConnection::orgBluez().unregisterObject(advertisement->objectPath().path()); + + return new PendingCall(d->m_bluezLEAdvertisingManager->UnregisterAdvertisement(advertisement->objectPath()), + PendingCall::ReturnVoid, this); +} + +} // namespace BluezQt Index: src/leadvertisingmanager_p.h =================================================================== --- /dev/null +++ src/leadvertisingmanager_p.h @@ -0,0 +1,42 @@ +/* + * BluezQt - Asynchronous Bluez wrapper library + * + * Copyright (C) 2019 Manuel Weichselbaumer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) version 3, or any + * later version accepted by the membership of KDE e.V. (or its + * successor approved by the membership of KDE e.V.), which shall + * act as a proxy defined in Section 6 of version 3 of the license. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef BLUEZQT_LEADVERTISINGMANAGER_P_H +#define BLUEZQT_LEADVERTISINGMANAGER_P_H + +#include "bluezleadvertisingmanager1.h" + +namespace BluezQt +{ + +typedef org::bluez::LEAdvertisingManager1 BluezLEAdvertisingManager; + +class LEAdvertisingManagerPrivate +{ +public: + QString m_path; + BluezLEAdvertisingManager *m_bluezLEAdvertisingManager = nullptr; +}; + +} // namespace BluezQt + +#endif // BLUEZQT_LEADVERTISINGMANAGER_P_H Index: src/mediaendpoint.cpp =================================================================== --- src/mediaendpoint.cpp +++ src/mediaendpoint.cpp @@ -27,7 +27,7 @@ namespace BluezQt { -MediaEndpoint::MediaEndpoint(const Configuration& configuration, QObject *parent) +MediaEndpoint::MediaEndpoint(const Configuration &configuration, QObject *parent) : QObject(parent), d(new MediaEndpointPrivate(configuration)) { Index: src/objectmanager.h =================================================================== --- /dev/null +++ src/objectmanager.h @@ -0,0 +1,73 @@ +/* + * BluezQt - Asynchronous BlueZ wrapper library + * + * Copyright (C) 2019 Manuel Weichselbaumer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) version 3, or any + * later version accepted by the membership of KDE e.V. (or its + * successor approved by the membership of KDE e.V.), which shall + * act as a proxy defined in Section 6 of version 3 of the license. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#pragma once + +#include + +#include "bluezqt_dbustypes.h" +#include "bluezqt_export.h" + +namespace BluezQt +{ + +/** + * @class BluezQt::ObjectManager ObjectManager.h + * + * Bluetooth ObjectManager. + * + * An API can optionally make use of this interface for one or more sub-trees of + * objects. The root of each sub-tree implements this interface so other + * applications can get all objects, interfaces and properties in a single + * method call. It is appropriate to use this interface if users of the tree of + * objects are expected to be interested in all interfaces of all objects in the + * tree; a more granular API should be used if users of the objects are expected + * to be interested in a small subset of the objects, a small subset of their + * interfaces, or both. + */ +class BLUEZQT_EXPORT ObjectManager : public QObject +{ +public: + /** + * Destroys a ObjectManager object. + */ + virtual ~ObjectManager(); + + /** + * Gets all objects, interfaces and properties. + * + * The return value of this method is a dict whose keys are object paths. + * All returned object paths are children of the object path implementing + * this interface, i.e. their object paths start with the ObjectManager's + * object path plus '/'. + * + * Each value is a dict whose keys are interfaces names. Each value in this + * inner dict is another dict with property names (as key) and property + * values (as value). + */ + virtual DBusManagerStruct getManagedObjects() const = 0; + +protected: + explicit ObjectManager(QObject *parent = nullptr); +}; + +} // namespace BluezQt Index: src/objectmanager.cpp =================================================================== --- /dev/null +++ src/objectmanager.cpp @@ -0,0 +1,37 @@ +/* + * BluezQt - Asynchronous Bluez wrapper library + * + * Copyright (C) 2019 Manuel Weichselbaumer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) version 3, or any + * later version accepted by the membership of KDE e.V. (or its + * successor approved by the membership of KDE e.V.), which shall + * act as a proxy defined in Section 6 of version 3 of the license. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "objectmanager.h" + +namespace BluezQt +{ + +ObjectManager::ObjectManager(QObject *parent) + : QObject(parent) +{ +} + +ObjectManager::~ObjectManager() +{ +} + +} // namespace BluezQt Index: src/objectmanageradaptor.h =================================================================== --- src/objectmanageradaptor.h +++ src/objectmanageradaptor.h @@ -1,7 +1,7 @@ /* * BluezQt - Asynchronous Bluez wrapper library * - * Copyright (C) 2018 Manuel Weichselbaumer + * Copyright (C) 2019 Manuel Weichselbaumer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public Index: src/objectmanageradaptor.cpp =================================================================== --- src/objectmanageradaptor.cpp +++ src/objectmanageradaptor.cpp @@ -1,7 +1,7 @@ /* * BluezQt - Asynchronous Bluez wrapper library * - * Copyright (C) 2018 Manuel Weichselbaumer + * Copyright (C) 2019 Manuel Weichselbaumer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public Index: src/pendingcall.h =================================================================== --- src/pendingcall.h +++ src/pendingcall.h @@ -96,6 +96,10 @@ AuthenticationTimeout = 18, /** Indicates that the connection attempt have failed. */ ConnectionAttemptFailed = 19, + /** Indicates that the data provided generates a data packet which is too long. */ + InvalidLength = 20, + /** Indicates that the action is not permitted (e.g. maximum reached or socket locked). */ + NotPermitted = 21, /** Indicates an error with D-Bus. */ DBusError = 98, /** Indicates an internal error. */ @@ -192,6 +196,8 @@ friend class Manager; friend class Adapter; friend class Device; + friend class GattManager; + friend class LEAdvertisingManager; friend class Media; friend class MediaPlayer; friend class ObexManager; Index: src/pendingcall.cpp =================================================================== --- src/pendingcall.cpp +++ src/pendingcall.cpp @@ -67,6 +67,8 @@ FROM_BLUEZ_ERROR("AuthenticationRejected", PendingCall::AuthenticationRejected); FROM_BLUEZ_ERROR("AuthenticationTimeout", PendingCall::AuthenticationTimeout); FROM_BLUEZ_ERROR("ConnectionAttemptFailed", PendingCall::ConnectionAttemptFailed); + FROM_BLUEZ_ERROR("InvalidLength", PendingCall::InvalidLength); + FROM_BLUEZ_ERROR("NotPermitted", PendingCall::NotPermitted); #undef FROM_BLUEZ_ERROR return PendingCall::UnknownError; Index: src/types.h =================================================================== --- src/types.h +++ src/types.h @@ -32,6 +32,8 @@ class Adapter; class Device; class Input; +class GattManager; +class LEAdvertisingManager; class Media; class MediaPlayer; class MediaPlayerTrack; @@ -48,11 +50,14 @@ class ObexFileTransfer; class ObexFileTransferEntry; class ObexObjectPush; +class GattApplication; typedef QSharedPointer ManagerPtr; typedef QSharedPointer AdapterPtr; typedef QSharedPointer DevicePtr; typedef QSharedPointer InputPtr; +typedef QSharedPointer GattManagerPtr; +typedef QSharedPointer LEAdvertisingManagerPtr; typedef QSharedPointer MediaPtr; typedef QSharedPointer MediaPlayerPtr; typedef QSharedPointer ObexManagerPtr; Index: src/utils.h =================================================================== --- src/utils.h +++ src/utils.h @@ -41,6 +41,8 @@ QString orgBluezAdapter1(); QString orgBluezDevice1(); QString orgBluezInput1(); +QString orgBluezGattManager1(); +QString orgBluezLEAdvertisingManager1(); QString orgBluezMedia1(); QString orgBluezMediaPlayer1(); QString orgBluezAgentManager1(); Index: src/utils.cpp =================================================================== --- src/utils.cpp +++ src/utils.cpp @@ -44,6 +44,8 @@ QString orgBluezAdapter1; QString orgBluezDevice1; QString orgBluezInput1; + QString orgBluezGattManager1; + QString orgBluezLEAdvertisingManager1; QString orgBluezMedia1; QString orgBluezMediaPlayer1; QString orgBluezAgentManager1; @@ -66,6 +68,8 @@ orgBluezAdapter1 = QStringLiteral("org.bluez.Adapter1"); orgBluezDevice1 = QStringLiteral("org.bluez.Device1"); orgBluezInput1 = QStringLiteral("org.bluez.Input1"); + orgBluezGattManager1 = QStringLiteral("org.bluez.GattManager1"); + orgBluezLEAdvertisingManager1 = QStringLiteral("org.bluez.LEAdvertisingManager1"); orgBluezMedia1 = QStringLiteral("org.bluez.Media1"); orgBluezMediaPlayer1 = QStringLiteral("org.bluez.MediaPlayer1"); orgBluezAgentManager1 = QStringLiteral("org.bluez.AgentManager1"); @@ -117,6 +121,16 @@ return globalData->orgBluezInput1; } +QString Strings::orgBluezGattManager1() +{ + return globalData->orgBluezGattManager1; +} + +QString Strings::orgBluezLEAdvertisingManager1() +{ + return globalData->orgBluezLEAdvertisingManager1; +} + QString Strings::orgBluezMedia1() { return globalData->orgBluezMedia1; Index: tests/CMakeLists.txt =================================================================== --- tests/CMakeLists.txt +++ tests/CMakeLists.txt @@ -12,5 +12,6 @@ adaptersreceiver devicereceiver chatprofile + leserver mediaendpointconnector ) Index: tests/leserver.h =================================================================== --- tests/leserver.h +++ tests/leserver.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2015 David Rosca + * Copyright (C) 2019 Manuel Weichselbaumer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,35 +18,26 @@ * License along with this library. If not, see . */ -#ifndef DEVICEMANAGER_H -#define DEVICEMANAGER_H +#pragma once #include -class ObjectManager; +#include "types.h" -class DeviceManager : public QObject +namespace BluezQt +{ +class PendingCall; +} + +class LeServer : public QObject { Q_OBJECT public: - explicit DeviceManager(ObjectManager *parent = nullptr); - - void runAction(const QString &actionName, const QVariantMap &properties); + explicit LeServer(BluezQt::Manager *manager, QObject *parent = nullptr); private: - void runCreateAdapterAction(const QVariantMap &properties); - void runCreateDeviceAction(const QVariantMap &properties); - void runRemoveAdapterAction(const QVariantMap &properties); - void runRemoveDeviceAction(const QVariantMap &properties); - void runChangeAdapterProperty(const QVariantMap &properties); - void runChangeDeviceProperty(const QVariantMap &properties); - void runAdapterMediaAction(const QString action, const QVariantMap &properties); - void runBug377405(); - void runBug403289(const QVariantMap &properties); - - ObjectManager *m_objectManager; + void onCallFinished(BluezQt::PendingCall *call); + BluezQt::Manager *m_manager; }; - -#endif // DEVICEMANAGER_H Index: tests/leserver.cpp =================================================================== --- tests/leserver.cpp +++ tests/leserver.cpp @@ -45,7 +45,7 @@ auto call = m_manager->usableAdapter()->leAdvertisingManager()->registerAdvertisement(advertisement); connect(call, &PendingCall::finished, this, &LeServer::onCallFinished); - auto application = new GattApplication(this); + auto application = new GattApplication(QStringLiteral("/org/kde/bluez-qt"), this); auto service = new GattService(QStringLiteral("ad100000-d901-11e8-9f8b-f2801f1b9fd1"), true, application); new GattCharacteristic(QStringLiteral("ad10e100-d901-11e8-9f8b-f2801f1b9fd1"), service); auto call2 = m_manager->usableAdapter()->gattManager()->registerApplication(application);