diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt --- a/autotests/CMakeLists.txt +++ b/autotests/CMakeLists.txt @@ -32,6 +32,8 @@ mediaplayertest jobstest mediatest + leadvertisingmanagertest + gattmanagertest ) if(Qt5Qml_FOUND AND Qt5QuickTest_FOUND) diff --git a/autotests/fakebluez/CMakeLists.txt b/autotests/fakebluez/CMakeLists.txt --- a/autotests/fakebluez/CMakeLists.txt +++ b/autotests/fakebluez/CMakeLists.txt @@ -14,6 +14,8 @@ obexagentmanager.cpp obexclient.cpp mediainterface.cpp + leadvertisingmanagerinterface.cpp + gattmanagerinterface.cpp ) add_executable(fakebluez ${fakebluez_SRCS}) diff --git a/autotests/fakebluez/adapterinterface.h b/autotests/fakebluez/adapterinterface.h --- a/autotests/fakebluez/adapterinterface.h +++ b/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 diff --git a/autotests/fakebluez/adapterinterface.cpp b/autotests/fakebluez/adapterinterface.cpp --- a/autotests/fakebluez/adapterinterface.cpp +++ b/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); diff --git a/autotests/fakebluez/devicemanager.h b/autotests/fakebluez/devicemanager.h --- a/autotests/fakebluez/devicemanager.h +++ b/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); diff --git a/autotests/fakebluez/devicemanager.cpp b/autotests/fakebluez/devicemanager.cpp --- a/autotests/fakebluez/devicemanager.cpp +++ b/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")); diff --git a/autotests/fakebluez/devicemanager.h b/autotests/fakebluez/gattmanagerinterface.h copy from autotests/fakebluez/devicemanager.h copy to autotests/fakebluez/gattmanagerinterface.h --- a/autotests/fakebluez/devicemanager.h +++ b/autotests/fakebluez/gattmanagerinterface.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,35 @@ * 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 GattManagerInterface : public QDBusAbstractAdaptor, public Object { Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.bluez.GattManager1") public: - explicit DeviceManager(ObjectManager *parent = nullptr); + explicit GattManagerInterface(const QDBusObjectPath &path, QObject *parent = nullptr); void runAction(const QString &actionName, const QVariantMap &properties); -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; +public Q_SLOTS: + void RegisterApplication(const QDBusObjectPath &path, const QVariantMap &options, const QDBusMessage &msg); + void UnregisterApplication(const QDBusObjectPath &path, const QDBusMessage &msg); +private: + void runGetObjectsAction(); + void runReadCharcAction(const QVariantMap &properties); + void runWriteCharcAction(const QVariantMap &properties); + + QDBusObjectPath m_application; + QDBusObjectPath m_characteristic; + QString m_service; + QVariantMap m_properties; }; - -#endif // DEVICEMANAGER_H diff --git a/autotests/fakebluez/gattmanagerinterface.cpp b/autotests/fakebluez/gattmanagerinterface.cpp new file mode 100644 --- /dev/null +++ b/autotests/fakebluez/gattmanagerinterface.cpp @@ -0,0 +1,106 @@ +/* + * 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 "gattmanagerinterface.h" +#include "objectmanager.h" + +#include +#include +#include +#include +#include + +GattManagerInterface::GattManagerInterface(const QDBusObjectPath &path, QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + setName(QStringLiteral("org.bluez.GattManager1")); + setPath(path); +} + +void GattManagerInterface::runAction(const QString &actionName, const QVariantMap &properties) +{ + if (actionName == QLatin1String("get-objects")) { + runGetObjectsAction(); + } else if (actionName == QLatin1String("read-charc")) { + runReadCharcAction(properties); + } else if (actionName == QLatin1String("write-charc")) { + runWriteCharcAction(properties); + } +} + +void GattManagerInterface::RegisterApplication(const QDBusObjectPath &path, const QVariantMap &/*options*/, const QDBusMessage &msg) +{ + m_application = path; + m_service = msg.service(); +} + +void GattManagerInterface::UnregisterApplication(const QDBusObjectPath &path, const QDBusMessage &msg) +{ + if (m_application == path && m_service == msg.service()) { + m_application = QDBusObjectPath(); + m_service.clear(); + } +} + +void GattManagerInterface::runGetObjectsAction() +{ + QDBusMessage call = QDBusMessage::createMethodCall(m_service, + m_application.path(), + QStringLiteral("org.freedesktop.DBus.ObjectManager"), + QStringLiteral("GetManagedObjects")); + + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(QDBusConnection::sessionBus().asyncCall(call)); + connect(watcher, &QDBusPendingCallWatcher::finished, [this](QDBusPendingCallWatcher *watcher) { + const QDBusPendingReply &reply = *watcher; + watcher->deleteLater(); + if (reply.isError()) { + return; + } + + DBusManagerStruct objects = reply.value(); + for (const auto& object : objects.keys()) { + if (object.path().contains(QStringLiteral("char"))) { + m_characteristic = object; + break; + } + } + }); +} + +void GattManagerInterface::runReadCharcAction(const QVariantMap &properties) +{ + QDBusMessage call = QDBusMessage::createMethodCall(m_service, + m_characteristic.path(), + QStringLiteral("org.bluez.GattCharacteristic1"), + QStringLiteral("ReadValue")); + call << properties.value(QStringLiteral("Options")); + QDBusConnection::sessionBus().asyncCall(call); +} + +void GattManagerInterface::runWriteCharcAction(const QVariantMap &properties) +{ + QDBusMessage call = QDBusMessage::createMethodCall(m_service, + m_characteristic.path(), + QStringLiteral("org.bluez.GattCharacteristic1"), + QStringLiteral("WriteValue")); + call << properties.value(QStringLiteral("Value")); + call << properties.value(QStringLiteral("Options")); + QDBusConnection::sessionBus().asyncCall(call); +} diff --git a/autotests/fakebluez/devicemanager.h b/autotests/fakebluez/leadvertisingmanagerinterface.h copy from autotests/fakebluez/devicemanager.h copy to autotests/fakebluez/leadvertisingmanagerinterface.h --- a/autotests/fakebluez/devicemanager.h +++ b/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 diff --git a/autotests/fakebluez/leadvertisingmanagerinterface.cpp b/autotests/fakebluez/leadvertisingmanagerinterface.cpp new file mode 100644 --- /dev/null +++ b/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); +} diff --git a/autotests/gattmanagertest.h b/autotests/gattmanagertest.h new file mode 100644 --- /dev/null +++ b/autotests/gattmanagertest.h @@ -0,0 +1,42 @@ +/* + * 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 GattManagerTest : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + + void readCharcTest(); + void writeCharcTest(); + +private: + BluezQt::GattApplication *m_application; + BluezQt::GattCharacteristic *m_characteristic; + BluezQt::AdapterPtr m_adapter; +}; diff --git a/autotests/gattmanagertest.cpp b/autotests/gattmanagertest.cpp new file mode 100644 --- /dev/null +++ b/autotests/gattmanagertest.cpp @@ -0,0 +1,112 @@ +/* + * 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 "gattmanagertest.h" +#include "autotests.h" +#include "initmanagerjob.h" +#include "manager.h" +#include "pendingcall.h" +#include "gattmanager.h" +#include "gattservice.h" + +#include +#include +#include + +namespace BluezQt +{ +extern void bluezqt_initFakeBluezTestRun(); +} + +using namespace BluezQt; + +void GattManagerTest::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->gattManager()); + + m_application = new GattApplication(QStringLiteral("/org/kde/bluezqt"), 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(); + + // Let FakeBluez read local characteristic + QVariantMap params; + params.insert(QStringLiteral("AdapterPath"), QVariant::fromValue(QDBusObjectPath(m_adapter->ubi()))); + FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("adapter-gattmanager:get-objects"), params); + // Process events to let getManagedObjects call from FakeBluez be finished + QTest::qWait(0); +} + +void GattManagerTest::cleanupTestCase() +{ + FakeBluez::stop(); +} + +void GattManagerTest::readCharcTest() +{ + QCOMPARE(m_characteristic->readValue(), QByteArray()); + + bool readCallbackCalled = false; + m_characteristic->setReadCallback([&readCallbackCalled]() { + readCallbackCalled = true; + return QByteArray("1234"); + }); + QVariantMap params; + params.insert(QStringLiteral("AdapterPath"), QVariant::fromValue(QDBusObjectPath(m_adapter->ubi()))); + params.insert(QStringLiteral("Options"), QVariant::fromValue(QVariantMap())); + FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("adapter-gattmanager:read-charc"), params); + + QTRY_COMPARE(readCallbackCalled, true); + QTRY_COMPARE(m_characteristic->readValue(), QByteArray("1234")); +} + +void GattManagerTest::writeCharcTest() +{ + m_characteristic->setReadCallback(nullptr); + + QVariantMap params; + params.insert(QStringLiteral("AdapterPath"), QVariant::fromValue(QDBusObjectPath(m_adapter->ubi()))); + params.insert(QStringLiteral("Value"), QVariant::fromValue(QByteArray("4321"))); + params.insert(QStringLiteral("Options"), QVariant::fromValue(QVariantMap())); + FakeBluez::runAction(QStringLiteral("devicemanager"), QStringLiteral("adapter-gattmanager:write-charc"), params); + + QTRY_COMPARE(m_characteristic->readValue(), QByteArray("4321")); +} + +QTEST_MAIN(GattManagerTest) diff --git a/autotests/leadvertisingmanagertest.h b/autotests/leadvertisingmanagertest.h new file mode 100644 --- /dev/null +++ b/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; +}; diff --git a/autotests/leadvertisingmanagertest.cpp b/autotests/leadvertisingmanagertest.cpp new file mode 100644 --- /dev/null +++ b/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) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,14 +6,29 @@ adapter_p.cpp device.cpp device_p.cpp + gattapplication.cpp + gattapplication_p.cpp + gattcharacteristic.cpp + gattcharacteristic_p.cpp + gattcharacteristicadaptor.cpp + gattmanager.cpp + gattmanager_p.cpp + gattservice.cpp + gattservice_p.cpp + gattserviceadaptor.cpp input.cpp + leadvertisement.cpp + leadvertisement_p.cpp + leadvertisementadaptor.cpp + leadvertisingmanager.cpp media.cpp mediaendpoint.cpp mediaendpoint_p.cpp mediaendpointadaptor.cpp mediaplayer.cpp mediaplayer_p.cpp mediaplayertrack.cpp + objectmanageradaptor.cpp devicesmodel.cpp job.cpp initmanagerjob.cpp @@ -50,8 +65,12 @@ qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.freedesktop.DBus.Properties.xml dbusproperties) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.Adapter1.xml bluezadapter1) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.AgentManager1.xml bluezagentmanager1) +qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.GattCharacteristic1.xml bluezgattcharacteristic1) +qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.GattManager1.xml bluezgattmanager1) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.ProfileManager1.xml bluezprofilemanager1) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.Device1.xml bluezdevice1) +qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.LEAdvertisement1.xml bluezleadvertisement1) +qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.LEAdvertisingManager1.xml bluezleadvertisingmanager1) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.Media1.xml bluezmedia1) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.MediaEndpoint1.xml bluezmediaendpoint1) qt5_add_dbus_interface(bluezqt_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/org.bluez.MediaPlayer1.xml bluezmediaplayer1) @@ -87,7 +106,13 @@ Manager Adapter Device + GattApplication + GattCharacteristic + GattManager + GattService Input + LEAdvertisement + LEAdvertisingManager Media MediaEndpoint MediaPlayer diff --git a/src/adapter.h b/src/adapter.h --- a/src/adapter.h +++ b/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. */ diff --git a/src/adapter.cpp b/src/adapter.cpp --- a/src/adapter.cpp +++ b/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; diff --git a/src/adapter_p.h b/src/adapter_p.h --- a/src/adapter_p.h +++ b/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 diff --git a/src/adapter_p.cpp b/src/adapter_p.cpp --- a/src/adapter_p.cpp +++ b/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; } } diff --git a/src/gattapplication.h b/src/gattapplication.h new file mode 100644 --- /dev/null +++ b/src/gattapplication.h @@ -0,0 +1,105 @@ +/* + * 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 "bluezqt_dbustypes.h" +#include "bluezqt_export.h" + +namespace BluezQt +{ + +/** + * @class BluezQt::GattApplication GattApplication.h + * + * Bluetooth GattApplication. + * + * This class represents a Bluetooth GattApplication, which is the root node of + * a GATT object hierarchy. Its child nodes can be GattServices, + * GattCharacteristics and GattDescriptors that belong to that GattApplication. + * The object path prefix for GattApplications is freely definable and its + * children's paths follow the application path hierarchy automatically, while + * all instances are enumerated automatically as well. + * + * Object path: [variable prefix]/appXX/serviceYY/charZZ + * + */ +class BLUEZQT_EXPORT GattApplication : public QObject +{ + Q_OBJECT + +public: + /** + * Creates a new GattApplication object with default object path prefix. + * + * Object path: /org/kde/bluezqt/appXX/serviceYY/charZZ + * + * @param parent + */ + explicit GattApplication(QObject *parent = nullptr); + + /** + * Creates a new GattApplication object with custom object path prefix. + * + * Object path: [objectPathPrefix]/appXX/serviceYY/charZZ + * + * @param objectPathPrefix + * @param parent + */ + explicit GattApplication(const QString &objectPathPrefix, QObject *parent = nullptr); + + /** + * Destroys a GattApplication object. + */ + ~GattApplication(); + +private: + /** + * D-Bus object path of the GATT application. + * + * The path where the GATT application will be registered. + * + * @note You must provide valid object path! + * + * @return object path of GATT application + */ + virtual QDBusObjectPath objectPath() const; + + /** + * Gets all GattServices, GattCharacteristics and GattDescriptors that + * belong to this GattApplication. + * + * The return value of this method is a dict whose keys are object paths. + * 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). + */ + DBusManagerStruct getManagedObjects() const; + + class GattApplicationPrivate *const d; + + friend class GattManager; + friend class GattService; + friend class ObjectManagerAdaptor; +}; + +} // namespace BluezQt diff --git a/src/gattapplication.cpp b/src/gattapplication.cpp new file mode 100644 --- /dev/null +++ b/src/gattapplication.cpp @@ -0,0 +1,97 @@ +/* + * 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 "gattapplication.h" + +#include "gattapplication_p.h" +#include "gattcharacteristic.h" +#include "gattcharacteristicadaptor.h" +#include "gattservice.h" +#include "gattserviceadaptor.h" + +#include +#include +#include + +namespace BluezQt +{ + +GattApplication::GattApplication(QObject *parent) + : GattApplication(QStringLiteral("/org/kde/bluezqt"), parent) +{ +} + +GattApplication::GattApplication(const QString &objectPathPrefix, QObject *parent) + : QObject(parent) + , d(new GattApplicationPrivate(objectPathPrefix)) +{ +} + +GattApplication::~GattApplication() +{ + delete d; +} + +DBusManagerStruct GattApplication::getManagedObjects() const +{ + DBusManagerStruct objects; + + const auto serviceAdaptors = findChildren(); + const auto charcAdaptors = findChildren(); + + for (const GattServiceAdaptor *serviceAdaptor : serviceAdaptors) { + QVariantMap properties; + for (int i = serviceAdaptor->metaObject()->propertyOffset(); + i < serviceAdaptor->metaObject()->propertyCount(); ++i) { + auto propertyName = serviceAdaptor->metaObject()->property(i).name(); + properties.insert(QString::fromLatin1(propertyName), serviceAdaptor->property(propertyName)); + } + + GattService *service = qobject_cast(serviceAdaptor->parent()); + if (service) { + objects[service->objectPath()].insert(QStringLiteral("org.bluez.GattService1"), properties); + } + } + + for (const GattCharacteristicAdaptor *charcAdaptor : charcAdaptors) { + QVariantMap properties; + for (int i = charcAdaptor->metaObject()->propertyOffset(); + i < charcAdaptor->metaObject()->propertyCount(); ++i) { + auto propertyName = charcAdaptor->metaObject()->property(i).name(); + properties.insert(QString::fromLatin1(propertyName), charcAdaptor->property(propertyName)); + } + + GattCharacteristic *charc = qobject_cast(charcAdaptor->parent()); + if (charc) { + objects[charc->objectPath()].insert(QStringLiteral("org.bluez.GattCharacteristic1"), properties); + } + } + + return objects; +} + +QDBusObjectPath GattApplication::objectPath() const +{ + return d->m_objectPath; +} + +} // namespace BluezQt diff --git a/src/gattapplication_p.h b/src/gattapplication_p.h new file mode 100644 --- /dev/null +++ b/src/gattapplication_p.h @@ -0,0 +1,38 @@ +/* + * 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 + +namespace BluezQt +{ + +class GattApplicationPrivate +{ +public: + GattApplicationPrivate(const QString &objectPathPrefix); + + QDBusObjectPath m_objectPath; +}; + +} // namespace BluezQt diff --git a/src/gattapplication_p.cpp b/src/gattapplication_p.cpp new file mode 100644 --- /dev/null +++ b/src/gattapplication_p.cpp @@ -0,0 +1,34 @@ +/* + * 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 "gattapplication_p.h" + +namespace BluezQt +{ + +GattApplicationPrivate::GattApplicationPrivate(const QString &objectPathPrefix) +{ + static uint8_t appNumber = 0; + m_objectPath.setPath(objectPathPrefix + QStringLiteral("/app") + QString::number(appNumber++)); +} + +} // namespace BluezQt diff --git a/src/gattcharacteristic.h b/src/gattcharacteristic.h new file mode 100644 --- /dev/null +++ b/src/gattcharacteristic.h @@ -0,0 +1,106 @@ +/* + * 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 "bluezqt_export.h" + +#include + +namespace BluezQt +{ +class GattService; + +class BLUEZQT_EXPORT GattCharacteristic : public QObject +{ + Q_OBJECT + +public: + /** + * Creates a new GattCharacteristic object. + * + * @param parent + */ + explicit GattCharacteristic(const QString &uuid, GattService *service); + + /** + * Destroys a GattCharacteristic object. + */ + ~GattCharacteristic(); + + /** + * Reads the value of the characteristic. + */ + QByteArray readValue(); + + /** + * Writes the value of the characteristic. + */ + void writeValue(const QByteArray &value); + + /** + * Provide a read callback to operate in *pull* mode. + */ + using ReadCallback = std::function; + void setReadCallback(ReadCallback callback); + + /** + * 128-bit GATT characteristic UUID. + * + * @return uuid of characteristic + */ + QString uuid() const; + + /** + * The GATT service the characteristic belongs to. + * + * @return service this characteristic belongs to + */ + const GattService *service() const; + +Q_SIGNALS: + /** + * Indicates that a value was written. + */ + void valueWritten(const QByteArray &value); + +protected: + /** + * D-Bus object path of the GattCharacteristic. + * + * The path where the GattCharacteristic will be registered. + * + * @note You must provide valid object path! + * + * @return object path of GattCharacteristic + */ + virtual QDBusObjectPath objectPath() const; + +private: + class GattCharacterisiticPrivate *const d; + + friend class GattApplication; + friend class GattCharacteristicAdaptor; + friend class GattManager; +}; + +} // namespace BluezQt diff --git a/src/gattcharacteristic.cpp b/src/gattcharacteristic.cpp new file mode 100644 --- /dev/null +++ b/src/gattcharacteristic.cpp @@ -0,0 +1,76 @@ +/* + * 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 "gattcharacteristic.h" +#include "gattcharacteristic_p.h" +#include "gattservice.h" + +namespace BluezQt +{ + +GattCharacteristic::GattCharacteristic(const QString &uuid, GattService *service) + : QObject(service) + , d(new GattCharacterisiticPrivate(uuid, service)) +{ +} + +GattCharacteristic::~GattCharacteristic() +{ + delete d; +} + +QByteArray GattCharacteristic::readValue() +{ + if (d->m_readCallback) { + d->m_value = d->m_readCallback(); + } + + return d->m_value; +} + +void GattCharacteristic::writeValue(const QByteArray &value) +{ + d->m_value = value; + emit valueWritten(d->m_value); +} + +QString GattCharacteristic::uuid() const +{ + return d->m_uuid; +} + +const GattService *GattCharacteristic::service() const +{ + return d->m_service; +} + +QDBusObjectPath GattCharacteristic::objectPath() const +{ + return d->m_objectPath; +} + +void GattCharacteristic::setReadCallback(ReadCallback callback) +{ + d->m_readCallback = callback; +} + +} // namespace BluezQt diff --git a/src/gattcharacteristic_p.h b/src/gattcharacteristic_p.h new file mode 100644 --- /dev/null +++ b/src/gattcharacteristic_p.h @@ -0,0 +1,43 @@ +/* + * 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 "gattcharacteristic.h" + +namespace BluezQt +{ +class GattServicePrivate; + +class GattCharacterisiticPrivate +{ +public: + GattCharacterisiticPrivate(const QString &uuid, const GattService *service); + + QString m_uuid; + const GattService *m_service; + QDBusObjectPath m_objectPath; + QByteArray m_value; + GattCharacteristic::ReadCallback m_readCallback = nullptr; +}; + +} // namespace BluezQt diff --git a/src/gattcharacteristic_p.cpp b/src/gattcharacteristic_p.cpp new file mode 100644 --- /dev/null +++ b/src/gattcharacteristic_p.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 "gattcharacteristic_p.h" +#include "gattservice.h" + +namespace BluezQt +{ + +GattCharacterisiticPrivate::GattCharacterisiticPrivate(const QString &uuid, const GattService *service) + : m_uuid(uuid) + , m_service(service) +{ + static uint8_t charcNumber = 0; + m_objectPath.setPath(m_service->objectPath().path() + QStringLiteral("/char") + QString::number(charcNumber++)); +} + +} // namespace BluezQt diff --git a/src/gattcharacteristicadaptor.h b/src/gattcharacteristicadaptor.h new file mode 100644 --- /dev/null +++ b/src/gattcharacteristicadaptor.h @@ -0,0 +1,61 @@ +/* + * 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 + +class QDBusObjectPath; + +namespace BluezQt +{ + +class GattCharacteristic; + +class GattCharacteristicAdaptor : public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.bluez.GattCharacteristic1") + Q_PROPERTY(QString UUID READ uuid) + Q_PROPERTY(QDBusObjectPath Service READ service) + Q_PROPERTY(QStringList Flags READ flags) + +public: + explicit GattCharacteristicAdaptor(GattCharacteristic *parent); + + QString uuid() const; + + QDBusObjectPath service() const; + + QStringList flags() const; + +public Q_SLOTS: + QByteArray ReadValue(const QVariantMap &options); + void WriteValue(const QByteArray &value, const QVariantMap &options); + void StartNotify(); + void StopNotify(); + +private: + GattCharacteristic *m_gattCharacteristic; +}; + +} // namespace BluezQt diff --git a/src/gattcharacteristicadaptor.cpp b/src/gattcharacteristicadaptor.cpp new file mode 100644 --- /dev/null +++ b/src/gattcharacteristicadaptor.cpp @@ -0,0 +1,74 @@ +/* + * 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 "gattcharacteristicadaptor.h" +#include "gattcharacteristic.h" +#include "gattservice.h" + +#include + +namespace BluezQt +{ + +GattCharacteristicAdaptor::GattCharacteristicAdaptor(GattCharacteristic *parent) + : QDBusAbstractAdaptor(parent) + , m_gattCharacteristic(parent) +{ +} + +QString GattCharacteristicAdaptor::uuid() const +{ + return m_gattCharacteristic->uuid(); +} + +QDBusObjectPath GattCharacteristicAdaptor::service() const +{ + return m_gattCharacteristic->service()->objectPath(); +} + +QStringList GattCharacteristicAdaptor::flags() const +{ + // TODO: implement flags + return { QStringLiteral("read"), QStringLiteral("write") }; +} + +QByteArray GattCharacteristicAdaptor::ReadValue(const QVariantMap &/*options*/) +{ + return m_gattCharacteristic->readValue(); +} + +void GattCharacteristicAdaptor::WriteValue(const QByteArray &value, const QVariantMap &/*options*/) +{ + m_gattCharacteristic->writeValue(value); +} + +void GattCharacteristicAdaptor::StartNotify() +{ + // TODO: implement +} + +void GattCharacteristicAdaptor::StopNotify() +{ + // TODO: implement +} + +} // namespace BluezQt diff --git a/src/gattmanager.h b/src/gattmanager.h new file mode 100644 --- /dev/null +++ b/src/gattmanager.h @@ -0,0 +1,109 @@ +/* + * 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 GattApplication; +class PendingCall; + +/** + * @class BluezQt::GattManager GattManager.h + * + * Bluetooth GattManager. + * + * GATT Manager allows external applications to register GATT services and + * profiles. + * + * Registering a profile allows applications to subscribe to *remote* services. + * These must implement the GattProfile1 interface defined above. + * + * Registering a service allows applications to publish a *local* GATT service, + * which then becomes available to remote devices. A GATT service is represented by + * a D-Bus object hierarchy where the root node corresponds to a service and the + * child nodes represent characteristics and descriptors that belong to that + * service. Each node must implement one of GattService1, GattCharacteristic1, + * or GattDescriptor1 interfaces described above, based on the attribute it + * represents. Each node must also implement the standard D-Bus Properties + * interface to expose their properties. These objects collectively represent a + * GATT service definition. + * + * @see GattApplication + */ +class BLUEZQT_EXPORT GattManager : public QObject +{ + Q_OBJECT + +public: + /** + * Destroys a GattManager object. + */ + ~GattManager(); + + /** + * Registers a local GATT services hierarchy as described + * above (GATT Server) and/or GATT profiles (GATT Client). + * + * The application object path together with the D-Bus + * system bus connection ID define the identification of + * the application registering a GATT based + * service or profile. + * + * Possible errors: org.bluez.Error.InvalidArguments + * org.bluez.Error.AlreadyExists + * + * @param application application to be registered + * @return void pending call + */ + PendingCall *registerApplication(GattApplication *application); + + /** + * This unregisters the services that has been + * previously registered. The object path parameter + * must match the same value that has been used + * on registration. + * + * Possible errors: org.bluez.Error.InvalidArguments + * org.bluez.Error.DoesNotExist + * + * @param application application to be unregistered + * @return void pending call + */ + PendingCall *unregisterApplication(GattApplication *application); + +private: + explicit GattManager(const QString &path, QObject *parent = nullptr); + + class GattManagerPrivate *const d; + + friend class AdapterPrivate; +}; + +} // namespace BluezQt + diff --git a/src/gattmanager.cpp b/src/gattmanager.cpp new file mode 100644 --- /dev/null +++ b/src/gattmanager.cpp @@ -0,0 +1,104 @@ +/* + * 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 "gattmanager.h" + +#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 "utils.h" +#include "debug.h" + +#include +#include + +namespace BluezQt +{ + +GattManager::GattManager(const QString &path, QObject *parent) + : QObject(parent) + , d(new GattManagerPrivate(path)) +{ +} + +GattManager::~GattManager() +{ + delete d; +} + +PendingCall *GattManager::registerApplication(GattApplication *application) +{ + Q_ASSERT(application); + + const auto services = application->findChildren(); + for (auto service : services) { + new GattServiceAdaptor(service); + + const auto charcs = service->findChildren(); + for (auto charc : charcs) { + new GattCharacteristicAdaptor(charc); + if (!DBusConnection::orgBluez().registerObject(charc->objectPath().path(), + charc, + QDBusConnection::ExportAdaptors)) { + qCDebug(BLUEZQT) << "Cannot register object" << charc->objectPath().path(); + } + } + + if (!DBusConnection::orgBluez().registerObject(service->objectPath().path(), + service, + QDBusConnection::ExportAdaptors)) { + qCDebug(BLUEZQT) << "Cannot register object" << service->objectPath().path(); + } + } + + new ObjectManagerAdaptor(application); + + if (!DBusConnection::orgBluez().registerObject(application->objectPath().path(), + application, + QDBusConnection::ExportAdaptors)) { + qCDebug(BLUEZQT) << "Cannot register object" << application->objectPath().path(); + } + + QList argumentList; + argumentList << QVariant::fromValue(application->objectPath()) << QVariantMap(); + return new PendingCall(d->m_dbusInterface->asyncCallWithArgumentList(QStringLiteral("RegisterApplication"), argumentList), + PendingCall::ReturnVoid, this); +} + +PendingCall *GattManager::unregisterApplication(GattApplication *application) +{ + Q_ASSERT(application); + + DBusConnection::orgBluez().unregisterObject(application->objectPath().path()); + + QList argumentList; + argumentList << QVariant::fromValue(application->objectPath()); + return new PendingCall(d->m_dbusInterface->asyncCallWithArgumentList(QStringLiteral("UnregisterApplication"), argumentList), + PendingCall::ReturnVoid, this); +} + +} // namespace BluezQt diff --git a/src/gattmanager_p.h b/src/gattmanager_p.h new file mode 100644 --- /dev/null +++ b/src/gattmanager_p.h @@ -0,0 +1,40 @@ +/* + * 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 + +class QDBusInterface; +class QString; + +namespace BluezQt +{ + +class GattManagerPrivate +{ +public: + GattManagerPrivate(const QString &path); + ~GattManagerPrivate(); + + QDBusInterface *m_dbusInterface = nullptr; +}; + +} // namespace BluezQt diff --git a/src/gattmanager_p.cpp b/src/gattmanager_p.cpp new file mode 100644 --- /dev/null +++ b/src/gattmanager_p.cpp @@ -0,0 +1,44 @@ +/* + * 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 "gattmanager_p.h" +#include "utils.h" + +#include + +namespace BluezQt +{ + +GattManagerPrivate::GattManagerPrivate(const QString &path) +{ + m_dbusInterface = new QDBusInterface(Strings::orgBluez(), + path, + QStringLiteral("org.bluez.GattManager1"), + DBusConnection::orgBluez()); +} + +GattManagerPrivate::~GattManagerPrivate() +{ + delete m_dbusInterface; +} + +} // namespace BluezQt diff --git a/src/gattservice.h b/src/gattservice.h new file mode 100644 --- /dev/null +++ b/src/gattservice.h @@ -0,0 +1,93 @@ +/* + * 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 "bluezqt_export.h" +#include "types.h" + +#include + +namespace BluezQt +{ + +/** + * @class BluezQt::GattService GattService.h + * + * Bluetooth GattService. + * + * This class represents a Bluetooth GattService. + */ +class BLUEZQT_EXPORT GattService : public QObject +{ + Q_OBJECT + +public: + /** + * Creates a new GattService object. + * + * @param parent + */ + explicit GattService(const QString &uuid, bool isPrimary, GattApplication *parent); + + /** + * Destroys a GattService object. + */ + ~GattService(); + + /** + * 128-bit service UUID. + * + * @return uuid of gatt service + */ + QString uuid() const; + + /** + * Indicates whether or not this GATT service is a + * primary service. If false, the service is secondary. + * + * @return true if gatt service is primary + */ + bool isPrimary() const; + +protected: + /** + * D-Bus object path of the GattService. + * + * The path where the GattService will be registered. + * + * @note You must provide valid object path! + * + * @return object path of GattService + */ + virtual QDBusObjectPath objectPath() const; + +private: + class GattServicePrivate *const d; + + friend class GattApplication; + friend class GattCharacterisiticPrivate; + friend class GattCharacteristicAdaptor; + friend class GattManager; +}; + +} // namespace BluezQt diff --git a/src/gattservice.cpp b/src/gattservice.cpp new file mode 100644 --- /dev/null +++ b/src/gattservice.cpp @@ -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 . + */ + +#include "gattservice.h" +#include "gattapplication.h" +#include "gattservice_p.h" + +namespace BluezQt +{ + +GattService::GattService(const QString &uuid, bool isPrimary, GattApplication *parent) + : QObject(parent) + , d(new GattServicePrivate(uuid, isPrimary, parent->objectPath().path())) +{ +} + +GattService::~GattService() +{ + delete d; +} + +QString GattService::uuid() const +{ + return d->m_uuid; +} + +bool GattService::isPrimary() const +{ + return d->m_isPrimary; +} + +QDBusObjectPath GattService::objectPath() const +{ + return d->m_objectPath; +} + +} // namespace BluezQt diff --git a/src/gattservice_p.h b/src/gattservice_p.h new file mode 100644 --- /dev/null +++ b/src/gattservice_p.h @@ -0,0 +1,40 @@ +/* + * 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 + +namespace BluezQt +{ + +class GattServicePrivate +{ +public: + GattServicePrivate(const QString &uuid, bool isPrimary, const QString &appPath); + + QString m_uuid; + bool m_isPrimary; + QDBusObjectPath m_objectPath; +}; + +} // namespace BluezQt diff --git a/src/gattservice_p.cpp b/src/gattservice_p.cpp new file mode 100644 --- /dev/null +++ b/src/gattservice_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 "gattservice_p.h" + +namespace BluezQt +{ + +GattServicePrivate::GattServicePrivate(const QString &uuid, bool isPrimary, const QString &appPath) + : m_uuid(uuid) + , m_isPrimary(isPrimary) +{ + static uint8_t serviceNumber = 0; + m_objectPath.setPath(appPath + QStringLiteral("/service") + QString::number(serviceNumber++)); +} + +} // namespace BluezQt diff --git a/src/gattserviceadaptor.h b/src/gattserviceadaptor.h new file mode 100644 --- /dev/null +++ b/src/gattserviceadaptor.h @@ -0,0 +1,50 @@ +/* + * 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 + +namespace BluezQt +{ + +class GattService; + +class GattServiceAdaptor : public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.bluez.GattService1") + Q_PROPERTY(QString UUID READ uuid) + Q_PROPERTY(bool Primary READ primary) + +public: + explicit GattServiceAdaptor(GattService *parent); + + QString uuid() const; + + bool primary() const; + +private: + GattService *m_gattService; +}; + +} // namespace BluezQt diff --git a/src/gattserviceadaptor.cpp b/src/gattserviceadaptor.cpp new file mode 100644 --- /dev/null +++ b/src/gattserviceadaptor.cpp @@ -0,0 +1,50 @@ +/* + * 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 "gattserviceadaptor.h" + +#include "gattservice.h" +#include "request.h" + +#include +#include + +namespace BluezQt +{ + +GattServiceAdaptor::GattServiceAdaptor(GattService *parent) + : QDBusAbstractAdaptor(parent) + , m_gattService(parent) +{ +} + +QString GattServiceAdaptor::uuid() const +{ + return m_gattService->uuid(); +} + +bool GattServiceAdaptor::primary() const +{ + return m_gattService->isPrimary(); +} + +} // namespace BluezQt diff --git a/src/interfaces/org.bluez.GattCharacteristic1.xml b/src/interfaces/org.bluez.GattCharacteristic1.xml new file mode 100644 --- /dev/null +++ b/src/interfaces/org.bluez.GattCharacteristic1.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/interfaces/org.bluez.GattManager1.xml b/src/interfaces/org.bluez.GattManager1.xml new file mode 100644 --- /dev/null +++ b/src/interfaces/org.bluez.GattManager1.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/interfaces/org.bluez.LEAdvertisement1.xml b/src/interfaces/org.bluez.LEAdvertisement1.xml new file mode 100644 --- /dev/null +++ b/src/interfaces/org.bluez.LEAdvertisement1.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/interfaces/org.bluez.LEAdvertisingManager1.xml b/src/interfaces/org.bluez.LEAdvertisingManager1.xml new file mode 100644 --- /dev/null +++ b/src/interfaces/org.bluez.LEAdvertisingManager1.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/leadvertisement.h b/src/leadvertisement.h new file mode 100644 --- /dev/null +++ b/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 diff --git a/src/leadvertisement.cpp b/src/leadvertisement.cpp new file mode 100644 --- /dev/null +++ b/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 diff --git a/src/leadvertisement_p.h b/src/leadvertisement_p.h new file mode 100644 --- /dev/null +++ b/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 diff --git a/src/leadvertisement_p.cpp b/src/leadvertisement_p.cpp new file mode 100644 --- /dev/null +++ b/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 diff --git a/src/leadvertisementadaptor.h b/src/leadvertisementadaptor.h new file mode 100644 --- /dev/null +++ b/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 diff --git a/src/leadvertisementadaptor.cpp b/src/leadvertisementadaptor.cpp new file mode 100644 --- /dev/null +++ b/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 diff --git a/src/leadvertisingmanager.h b/src/leadvertisingmanager.h new file mode 100644 --- /dev/null +++ b/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 diff --git a/src/leadvertisingmanager.cpp b/src/leadvertisingmanager.cpp new file mode 100644 --- /dev/null +++ b/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 diff --git a/src/leadvertisingmanager_p.h b/src/leadvertisingmanager_p.h new file mode 100644 --- /dev/null +++ b/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 diff --git a/src/mediaendpoint.cpp b/src/mediaendpoint.cpp --- a/src/mediaendpoint.cpp +++ b/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)) { diff --git a/src/objectmanageradaptor.h b/src/objectmanageradaptor.h new file mode 100644 --- /dev/null +++ b/src/objectmanageradaptor.h @@ -0,0 +1,52 @@ +/* + * 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" + +namespace BluezQt +{ +class GattApplication; + +class ObjectManagerAdaptor : public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.freedesktop.DBus.ObjectManager") + +public: + explicit ObjectManagerAdaptor(QObject *parent); + +public Q_SLOTS: + DBusManagerStruct GetManagedObjects(); + +Q_SIGNALS: + void InterfacesAdded(const QDBusObjectPath &object, const QVariantMapMap &interfaces); + void InterfacesRemoved(const QDBusObjectPath &object, const QStringList &interfaces); + +private: + GattApplication *m_gattApplication = nullptr; +}; + +} // namespace BluezQt diff --git a/src/objectmanageradaptor.cpp b/src/objectmanageradaptor.cpp new file mode 100644 --- /dev/null +++ b/src/objectmanageradaptor.cpp @@ -0,0 +1,44 @@ +/* + * 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 "objectmanageradaptor.h" +#include "gattapplication.h" + +namespace BluezQt +{ + +ObjectManagerAdaptor::ObjectManagerAdaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) + , m_gattApplication(qobject_cast(parent)) +{ +} + +DBusManagerStruct ObjectManagerAdaptor::GetManagedObjects() +{ + if (m_gattApplication) { + return m_gattApplication->getManagedObjects(); + } + + return {}; +} + +} // namespace BluezQt diff --git a/src/pendingcall.h b/src/pendingcall.h --- a/src/pendingcall.h +++ b/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; diff --git a/src/pendingcall.cpp b/src/pendingcall.cpp --- a/src/pendingcall.cpp +++ b/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; diff --git a/src/types.h b/src/types.h --- a/src/types.h +++ b/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; diff --git a/src/utils.h b/src/utils.h --- a/src/utils.h +++ b/src/utils.h @@ -41,6 +41,8 @@ QString orgBluezAdapter1(); QString orgBluezDevice1(); QString orgBluezInput1(); +QString orgBluezGattManager1(); +QString orgBluezLEAdvertisingManager1(); QString orgBluezMedia1(); QString orgBluezMediaPlayer1(); QString orgBluezAgentManager1(); diff --git a/src/utils.cpp b/src/utils.cpp --- a/src/utils.cpp +++ b/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; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -12,5 +12,6 @@ adaptersreceiver devicereceiver chatprofile + leserver mediaendpointconnector ) diff --git a/autotests/fakebluez/devicemanager.h b/tests/leserver.h copy from autotests/fakebluez/devicemanager.h copy to tests/leserver.h --- a/autotests/fakebluez/devicemanager.h +++ b/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 diff --git a/tests/leserver.cpp b/tests/leserver.cpp new file mode 100644 --- /dev/null +++ b/tests/leserver.cpp @@ -0,0 +1,93 @@ +/* + * 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 "leserver.h" + +#include +#include + +#include "adapter.h" +#include "device.h" +#include "gattapplication.h" +#include "gattcharacteristic.h" +#include "gattmanager.h" +#include "gattservice.h" +#include "initmanagerjob.h" +#include "leadvertisement.h" +#include "leadvertisingmanager.h" +#include "manager.h" +#include "pendingcall.h" + +using namespace BluezQt; + +LeServer::LeServer(Manager *manager, QObject *parent) + : QObject(parent), + m_manager(manager) +{ + auto advertisement = new LEAdvertisement({QStringLiteral("ad100000-d901-11e8-9f8b-f2801f1b9fd1")}, this); + auto call = m_manager->usableAdapter()->leAdvertisingManager()->registerAdvertisement(advertisement); + connect(call, &PendingCall::finished, this, &LeServer::onCallFinished); + + auto application = new GattApplication(QStringLiteral("/org/kde/bluezqt"), 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); + connect(call2, &PendingCall::finished, this, &LeServer::onCallFinished); +} + +void LeServer::onCallFinished(BluezQt::PendingCall *call) +{ + if (call->error()) { + qWarning() << "Error: " << call->errorText(); + return; + } +} + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + + qDebug() << "Advertising LE services. Ctrl + C to cancel..."; + + Manager *manager = new Manager(); + InitManagerJob *initJob = manager->init(); + initJob->exec(); + if (initJob->error()) { + qWarning() << "Error initializing manager:" << initJob->errorText(); + return 1; + } + + if (!manager->usableAdapter()) { + qWarning() << "No usable adapter"; + return 2; + } + if (!manager->usableAdapter()->leAdvertisingManager()) { + qWarning() << "No LE advertising manager"; + return 2; + } + if (!manager->usableAdapter()->gattManager()) { + qWarning() << "No GATT manager"; + return 2; + } + + new LeServer(manager); + + return app.exec(); +}