/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtBluetooth module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qlowenergycontroller_bluezdbus_p.h"
#include "bluez/adapter1_bluez5_p.h"
#include "bluez/bluez5_helper_p.h"
#include "bluez/device1_bluez5_p.h"
#include "bluez/gattservice1_p.h"
#include "bluez/gattchar1_p.h"
#include "bluez/gattdesc1_p.h"
#include "bluez/battery1_p.h"
#include "bluez/objectmanager_p.h"
#include "bluez/properties_p.h"


QT_BEGIN_NAMESPACE

Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ)

QLowEnergyControllerPrivateBluezDBus::QLowEnergyControllerPrivateBluezDBus()
    : QLowEnergyControllerPrivate()
{
}

QLowEnergyControllerPrivateBluezDBus::~QLowEnergyControllerPrivateBluezDBus()
{
}

void QLowEnergyControllerPrivateBluezDBus::init()
{
}

void QLowEnergyControllerPrivateBluezDBus::devicePropertiesChanged(
        const QString &interface, const QVariantMap &changedProperties,
        const QStringList &/*removedProperties*/)
{
    if (interface == QStringLiteral("org.bluez.Device1")) {
        qCDebug(QT_BT_BLUEZ) << "######" << interface << changedProperties;
        if (changedProperties.contains(QStringLiteral("ServicesResolved"))) {
            //we could check for Connected property as well, but we choose to wait
            //for ServicesResolved being true

            if (pendingConnect) {
                bool isResolved = changedProperties.value(QStringLiteral("ServicesResolved")).toBool();
                if (isResolved) {
                    setState(QLowEnergyController::ConnectedState);
                    pendingConnect = false;
                    disconnectSignalRequired = true;
                    Q_Q(QLowEnergyController);
                    emit q->connected();
                }
            }
        }

        if (changedProperties.contains(QStringLiteral("Connected"))) {
            bool isConnected = changedProperties.value(QStringLiteral("Connected")).toBool();
            if (!isConnected) {
                switch (state) {
                case QLowEnergyController::ConnectingState:
                case QLowEnergyController::ConnectedState:
                case QLowEnergyController::DiscoveringState:
                case QLowEnergyController::DiscoveredState:
                case QLowEnergyController::ClosingState:
                {
                    QLowEnergyController::Error newError = QLowEnergyController::NoError;
                    if (pendingConnect)
                        newError = QLowEnergyController::ConnectionError;

                    executeClose(newError);
                }
                    break;
                case QLowEnergyController::AdvertisingState:
                case QLowEnergyController::UnconnectedState:
                    //ignore
                    break;
                }
            }
        }

        if (changedProperties.contains(QStringLiteral("UUIDs"))) {
            const QStringList newUuidStringList = changedProperties.value(QStringLiteral("UUIDs")).toStringList();
            QVector<QBluetoothUuid> newUuidList;
            for (const QString &uuidString : newUuidStringList)
                newUuidList.append(QBluetoothUuid(uuidString));

            for (const QBluetoothUuid &uuid : serviceList.keys()) {
                if (!newUuidList.contains(uuid)) {
                    qCDebug(QT_BT_BLUEZ) << __func__ << "Service" << uuid << "has been removed";
                    QSharedPointer<QLowEnergyServicePrivate> service = serviceList.take(uuid);
                    service->setController(nullptr);
                    dbusServices.remove(uuid);
                }
            }
        }

    } else if (interface == QStringLiteral("org.bluez.Battery1")) {
        qCDebug(QT_BT_BLUEZ) << "######" << interface << changedProperties;
        if (changedProperties.contains(QStringLiteral("Percentage"))) {
            // if battery service is discovered and ClientCharConfig is enabled
            // emit characteristicChanged() signal
            const QBluetoothUuid uuid(QBluetoothUuid::BatteryService);
            if (!serviceList.contains(uuid) || !dbusServices.contains(uuid)
                    || !dbusServices[uuid].hasBatteryService
                    || dbusServices[uuid].batteryInterface.isNull())
                return;

            QSharedPointer<QLowEnergyServicePrivate> serviceData = serviceList.value(uuid);
            if (serviceData->state != QLowEnergyService::ServiceDiscovered)
                return;

            QHash<QLowEnergyHandle, QLowEnergyServicePrivate::CharData>::iterator iter;
            iter = serviceData->characteristicList.begin();
            while (iter != serviceData->characteristicList.end()) {
                auto &charData = iter.value();
                if (charData.uuid != QBluetoothUuid::BatteryLevel)
                    continue;

                // Client Characteristic Notification enabled?
                bool cccActive = false;
                for (const QLowEnergyServicePrivate::DescData &descData : qAsConst(charData.descriptorList)) {
                    if (descData.uuid != QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration))
                        continue;
                    if (descData.value == QByteArray::fromHex("0100")
                            || descData.value == QByteArray::fromHex("0200")) {
                        cccActive = true;
                        break;
                    }
                }

                const QByteArray newValue(1, char(dbusServices[uuid].batteryInterface->percentage()));
                qCDebug(QT_BT_BLUEZ) << "Battery1 char update" << cccActive
                                     << charData.value.toHex() << "->" << newValue.toHex();
                if (cccActive && newValue != charData.value) {
                    qCDebug(QT_BT_BLUEZ) << "Property update for Battery1";
                    charData.value = newValue;
                    QLowEnergyCharacteristic ch(serviceData, iter.key());
                    emit serviceData->characteristicChanged(ch, newValue);
                }

                break;
            }
        }
    }
}

void QLowEnergyControllerPrivateBluezDBus::characteristicPropertiesChanged(
        QLowEnergyHandle charHandle, const QString &interface,
        const QVariantMap &changedProperties,
        const QStringList &/*removedProperties*/)
{
    //qCDebug(QT_BT_BLUEZ) << "$$$$$$$$$$$$$$$$$$ char monitor"
    //                     << interface << changedProperties << charHandle;
    if (interface != QStringLiteral("org.bluez.GattCharacteristic1"))
        return;

    if (!changedProperties.contains(QStringLiteral("Value")))
        return;

    const QLowEnergyCharacteristic changedChar = characteristicForHandle(charHandle);
    const QLowEnergyDescriptor ccnDescriptor = changedChar.descriptor(
                                    QBluetoothUuid::ClientCharacteristicConfiguration);
    if (!ccnDescriptor.isValid())
        return;

    const QByteArray newValue = changedProperties.value(QStringLiteral("Value")).toByteArray();
    if (changedChar.properties() & QLowEnergyCharacteristic::Read)
        updateValueOfCharacteristic(charHandle, newValue, false); //TODO upgrade to NEW_VALUE/APPEND_VALUE

    auto service = serviceForHandle(charHandle);

    if (!service.isNull())
        emit service->characteristicChanged(changedChar, newValue);
}

void QLowEnergyControllerPrivateBluezDBus::interfacesRemoved(
        const QDBusObjectPath &objectPath, const QStringList &/*interfaces*/)
{
    if (objectPath.path() == device->path()) {
        qCWarning(QT_BT_BLUEZ) << "DBus Device1 was removed";
        executeClose(QLowEnergyController::UnknownRemoteDeviceError);
    } else if (objectPath.path() == adapter->path()) {
        qCWarning(QT_BT_BLUEZ) << "DBus Adapter was removed";
        executeClose(QLowEnergyController::InvalidBluetoothAdapterError);
    }
}

void QLowEnergyControllerPrivateBluezDBus::resetController()
{
    if (managerBluez) {
        delete managerBluez;
        managerBluez = nullptr;
    }

    if (adapter) {
        delete adapter;
        adapter = nullptr;
    }

    if (device) {
        delete device;
        device = nullptr;
    }

    if (deviceMonitor) {
        delete deviceMonitor;
        deviceMonitor = nullptr;
    }

    dbusServices.clear();
    jobs.clear();
    invalidateServices();

    pendingConnect = disconnectSignalRequired = false;
    jobPending = false;
}

void QLowEnergyControllerPrivateBluezDBus::connectToDeviceHelper()
{
    resetController();

    bool ok = false;
    const QString hostAdapterPath = findAdapterForAddress(localAdapter, &ok);
    if (!ok || hostAdapterPath.isEmpty()) {
        qCWarning(QT_BT_BLUEZ) << "Cannot find suitable bluetooth adapter";
        setError(QLowEnergyController::InvalidBluetoothAdapterError);
        return;
    }

    QScopedPointer<OrgFreedesktopDBusObjectManagerInterface> manager(
                            new OrgFreedesktopDBusObjectManagerInterface(
                                QStringLiteral("org.bluez"), QStringLiteral("/"),
                                QDBusConnection::systemBus()));

    QDBusPendingReply<ManagedObjectList> reply = manager->GetManagedObjects();
    reply.waitForFinished();
    if (reply.isError()) {
        qCWarning(QT_BT_BLUEZ) << "Cannot enumerate Bluetooth devices for GATT connect";
        setError(QLowEnergyController::ConnectionError);
        return;
    }

    QString devicePath;
    ManagedObjectList managedObjectList = reply.value();
    for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) {
        const InterfaceList &ifaceList = it.value();

        for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) {
            const QString &iface = jt.key();
            const QVariantMap &ifaceValues = jt.value();

            if (iface == QStringLiteral("org.bluez.Device1")) {
                if (remoteDevice.toString() == ifaceValues.value(QStringLiteral("Address")).toString())
                {
                    const QVariant adapterForCurrentDevice = ifaceValues.value(QStringLiteral("Adapter"));
                    if (qvariant_cast<QDBusObjectPath>(adapterForCurrentDevice).path() == hostAdapterPath) {
                        devicePath = it.key().path();
                        break;
                    }
                }
            }
        }

        if (!devicePath.isEmpty())
            break;
    }

    if (devicePath.isEmpty()) {
        qCDebug(QT_BT_BLUEZ) << "Cannot find targeted remote device. "
                                "Re-running device discovery might help";
        setError(QLowEnergyController::UnknownRemoteDeviceError);
        return;
    }

    managerBluez = manager.take();
    connect(managerBluez, &OrgFreedesktopDBusObjectManagerInterface::InterfacesRemoved,
            this, &QLowEnergyControllerPrivateBluezDBus::interfacesRemoved);
    adapter = new OrgBluezAdapter1Interface(
                                QStringLiteral("org.bluez"), hostAdapterPath,
                                QDBusConnection::systemBus(), this);
    device = new OrgBluezDevice1Interface(
                                QStringLiteral("org.bluez"), devicePath,
                                QDBusConnection::systemBus(), this);
    deviceMonitor = new OrgFreedesktopDBusPropertiesInterface(
                                QStringLiteral("org.bluez"), devicePath,
                                QDBusConnection::systemBus(), this);
    connect(deviceMonitor, &OrgFreedesktopDBusPropertiesInterface::PropertiesChanged,
            this, &QLowEnergyControllerPrivateBluezDBus::devicePropertiesChanged);
}

void QLowEnergyControllerPrivateBluezDBus::connectToDevice()
{
    qCDebug(QT_BT_BLUEZ) << "QLowEnergyControllerPrivateBluezDBus::connectToDevice()";

    connectToDeviceHelper();

    if (!adapter || !device)
        return;

    if (!adapter->powered()) {
        qCWarning(QT_BT_BLUEZ) << "Error: Local adapter is powered off";
        setError(QLowEnergyController::ConnectionError);
        return;
    }

    setState(QLowEnergyController::ConnectingState);

    //Bluez interface is shared among all platform processes
    //and hence we might be connected already
    if (device->connected() && device->servicesResolved()) {
        //connectToDevice is noop
        disconnectSignalRequired = true;

        setState(QLowEnergyController::ConnectedState);
        Q_Q(QLowEnergyController);
        emit q->connected();
        return;
    }

    pendingConnect = true;

    QDBusPendingReply<> reply = device->Connect();
    QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this);
    connect(watcher, &QDBusPendingCallWatcher::finished, this,
            [this](QDBusPendingCallWatcher* call) {
        QDBusPendingReply<> reply = *call;
        if (reply.isError()) {
            qCDebug(QT_BT_BLUEZ) << "BTLE_DBUS::connect() failed"
                                 << reply.reply().errorName()
                                 << reply.reply().errorMessage();
            executeClose(QLowEnergyController::UnknownError);
        } // else -> connected when Connected property is set to true (see devicePropertiesChanged())
        call->deleteLater();
    });
}

void QLowEnergyControllerPrivateBluezDBus::disconnectFromDevice()
{
    if (!device)
        return;

    setState(QLowEnergyController::ClosingState);

    QDBusPendingReply<> reply = device->Disconnect();
    QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this);
    connect(watcher, &QDBusPendingCallWatcher::finished, this,
            [this](QDBusPendingCallWatcher* call) {
        QDBusPendingReply<> reply = *call;
        if (reply.isError()) {
            qCDebug(QT_BT_BLUEZ) << "BTLE_DBUS::disconnect() failed"
                                 << reply.reply().errorName()
                                 << reply.reply().errorMessage();
            executeClose(QLowEnergyController::NoError);
        }
        call->deleteLater();
    });
}

void QLowEnergyControllerPrivateBluezDBus::discoverServices()
{
    QDBusPendingReply<ManagedObjectList> reply = managerBluez->GetManagedObjects();
    reply.waitForFinished();
    if (reply.isError()) {
        qCWarning(QT_BT_BLUEZ) << "Cannot discover services";
        setError(QLowEnergyController::UnknownError);
        setState(QLowEnergyController::DiscoveredState);
        return;
    }

    Q_Q(QLowEnergyController);

    auto setupServicePrivate = [&, q](
            QLowEnergyService::ServiceType type, const QBluetoothUuid &uuid, const QString &path){
        QSharedPointer<QLowEnergyServicePrivate> priv = QSharedPointer<QLowEnergyServicePrivate>::create();
        priv->uuid = uuid;
        priv->type = type; // we make a guess we cannot validate
        priv->setController(this);

        GattService serviceContainer;
        serviceContainer.servicePath = path;
        if (uuid == QBluetoothUuid::BatteryService)
            serviceContainer.hasBatteryService = true;

        serviceList.insert(priv->uuid, priv);
        dbusServices.insert(priv->uuid, serviceContainer);

        emit q->serviceDiscovered(priv->uuid);
    };

    const ManagedObjectList managedObjectList = reply.value();
    const QString servicePathPrefix = device->path().append(QStringLiteral("/service"));
    for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) {
        const InterfaceList &ifaceList = it.value();

        if (!it.key().path().startsWith(device->path()))
            continue;

        // Since Bluez 5.48 battery services (0x180f) are no longer exposed
        // as generic services under servicePathPrefix.
        // A dedicated org.bluez.Battery1 interface is exposed. Here we are going to revert
        // Bettery1 to the generic pattern.
        if (it.key().path() == device->path())  {
            // find Battery1 service
            for (InterfaceList::const_iterator battIter = ifaceList.constBegin(); battIter != ifaceList.constEnd(); ++battIter) {
                const QString &iface = battIter.key();
                if (iface == QStringLiteral("org.bluez.Battery1")) {
                    qCDebug(QT_BT_BLUEZ) << "Found dedicated Battery service -> emulating generic btle access";
                    setupServicePrivate(QLowEnergyService::PrimaryService,
                                        QBluetoothUuid::BatteryService,
                                        it.key().path());
                }
            }
            continue;
        }

        if (!it.key().path().startsWith(servicePathPrefix))
            continue;

        for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) {
            const QString &iface = jt.key();

            if (iface == QStringLiteral("org.bluez.GattService1")) {
                QScopedPointer<OrgBluezGattService1Interface> service(new OrgBluezGattService1Interface(
                                    QStringLiteral("org.bluez"),it.key().path(),
                                    QDBusConnection::systemBus(), this));
                setupServicePrivate(service->primary()
                                    ? QLowEnergyService::PrimaryService
                                    : QLowEnergyService::IncludedService,
                                    QBluetoothUuid(service->uUID()), it.key().path());
            }
        }
    }

    setState(QLowEnergyController::DiscoveredState);
    emit q->discoveryFinished();
}

void QLowEnergyControllerPrivateBluezDBus::discoverBatteryServiceDetails(
        GattService &dbusData,  QSharedPointer<QLowEnergyServicePrivate> serviceData)
{
    // This process exists to work around the fact that Battery services (0x180f)
    // are not mapped as generic services but use the Battery1 interface.
    // Artificial chararacteristics and descriptors are created to emulate the generic behavior.

    auto batteryService = QSharedPointer<OrgBluezBattery1Interface>::create(
                                QStringLiteral("org.bluez"), dbusData.servicePath,
                                QDBusConnection::systemBus());
    dbusData.batteryInterface = batteryService;

    serviceData->startHandle = runningHandle++; //service start handle

    // Create BatteryLevel char
    QLowEnergyHandle indexHandle = runningHandle++; // char handle index
    QLowEnergyServicePrivate::CharData charData;

    charData.valueHandle = runningHandle++;
    charData.properties.setFlag(QLowEnergyCharacteristic::Read);
    charData.properties.setFlag(QLowEnergyCharacteristic::Notify);
    charData.uuid = QBluetoothUuid::BatteryLevel;
    charData.value = QByteArray(1, char(batteryService->percentage()));

    // Create the descriptors for the BatteryLevel
    // They are hardcoded although CCC may change
    QLowEnergyServicePrivate::DescData descData;
    QLowEnergyHandle descriptorHandle = runningHandle++;
    descData.uuid = QBluetoothUuid::ClientCharacteristicConfiguration;
    descData.value = QByteArray::fromHex("0000"); // all configs off
    charData.descriptorList.insert(descriptorHandle, descData);

    descriptorHandle = runningHandle++;
    descData.uuid = QBluetoothUuid::CharacteristicPresentationFormat;
    //for details see Characteristic Presentation Format Vol3, Part G 3.3.3.5
    // unsigend 8 bit, exp=1, org.bluetooth.unit.percentage, namespace & description
    // bit order: little endian
    descData.value = QByteArray::fromHex("0400ad27011131");
    charData.descriptorList.insert(descriptorHandle, descData);

    descriptorHandle = runningHandle++;
    descData.uuid = QBluetoothUuid::ReportReference;
    descData.value = QByteArray::fromHex("0401");
    charData.descriptorList.insert(descriptorHandle, descData);

    serviceData->characteristicList[indexHandle] = charData;
    serviceData->endHandle = runningHandle++;

    serviceData->setState(QLowEnergyService::ServiceDiscovered);
}

void QLowEnergyControllerPrivateBluezDBus::executeClose(QLowEnergyController::Error newError)
{
    const bool emitDisconnect = disconnectSignalRequired;

    resetController();
    if (newError != QLowEnergyController::NoError)
        setError(newError);

    setState(QLowEnergyController::UnconnectedState);
    if (emitDisconnect) {
        Q_Q(QLowEnergyController);
        emit q->disconnected();
    }
}

void QLowEnergyControllerPrivateBluezDBus::discoverServiceDetails(const QBluetoothUuid &service)
{
    if (!serviceList.contains(service) || !dbusServices.contains(service)) {
        qCWarning(QT_BT_BLUEZ) << "Discovery of unknown service" << service.toString()
                               << "not possible";
        return;
    }

    //clear existing service data and run new discovery
    QSharedPointer<QLowEnergyServicePrivate> serviceData = serviceList.value(service);
    serviceData->characteristicList.clear();

    GattService &dbusData = dbusServices[service];
    dbusData.characteristics.clear();

    if (dbusData.hasBatteryService) {
        qCDebug(QT_BT_BLUEZ) << "Triggering Battery1 service discovery on " << dbusData.servicePath;
        discoverBatteryServiceDetails(dbusData, serviceData);
        return;
    }

    QDBusPendingReply<ManagedObjectList> reply = managerBluez->GetManagedObjects();
    reply.waitForFinished();
    if (reply.isError()) {
        qCWarning(QT_BT_BLUEZ) << "Cannot discover services";
        setError(QLowEnergyController::UnknownError);
        setState(QLowEnergyController::DiscoveredState);
        return;
    }

    QStringList descriptorPaths;
    const ManagedObjectList managedObjectList = reply.value();
    for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) {
        const InterfaceList &ifaceList = it.value();
        if (!it.key().path().startsWith(dbusData.servicePath))
            continue;

        for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) {
            const QString &iface = jt.key();
            if (iface == QStringLiteral("org.bluez.GattCharacteristic1")) {
                auto charInterface = QSharedPointer<OrgBluezGattCharacteristic1Interface>::create(
                                            QStringLiteral("org.bluez"), it.key().path(),
                                            QDBusConnection::systemBus());
                GattCharacteristic dbusCharData;
                dbusCharData.characteristic = charInterface;
                dbusData.characteristics.append(dbusCharData);
            } else if (iface == QStringLiteral("org.bluez.GattDescriptor1")) {
                auto descInterface = QSharedPointer<OrgBluezGattDescriptor1Interface>::create(
                                            QStringLiteral("org.bluez"), it.key().path(),
                                            QDBusConnection::systemBus());
                bool found = false;
                for (GattCharacteristic &dbusCharData : dbusData.characteristics) {
                    if (!descInterface->path().startsWith(
                                dbusCharData.characteristic->path()))
                        continue;

                    found = true;
                    dbusCharData.descriptors.append(descInterface);
                    break;
                }

                Q_ASSERT(found);
                if (!found)
                    qCWarning(QT_BT_BLUEZ) << "Descriptor discovery error";
            }
        }
    }

    //populate servicePrivate based on dbus data
    serviceData->startHandle = runningHandle++;
    for (GattCharacteristic &dbusChar : dbusData.characteristics) {
        const QLowEnergyHandle indexHandle = runningHandle++;
        QLowEnergyServicePrivate::CharData charData;

        // characteristic data
        charData.valueHandle = runningHandle++;
        const QStringList properties = dbusChar.characteristic->flags();

        for (const auto &entry : properties) {
            if (entry == QStringLiteral("broadcast"))
                charData.properties.setFlag(QLowEnergyCharacteristic::Broadcasting, true);
            else if (entry == QStringLiteral("read"))
                charData.properties.setFlag(QLowEnergyCharacteristic::Read, true);
            else if (entry == QStringLiteral("write-without-response"))
                charData.properties.setFlag(QLowEnergyCharacteristic::WriteNoResponse, true);
            else if (entry == QStringLiteral("write"))
                charData.properties.setFlag(QLowEnergyCharacteristic::Write, true);
            else if (entry == QStringLiteral("notify"))
                charData.properties.setFlag(QLowEnergyCharacteristic::Notify, true);
            else if (entry == QStringLiteral("indicate"))
                charData.properties.setFlag(QLowEnergyCharacteristic::Indicate, true);
            else if (entry == QStringLiteral("authenticated-signed-writes"))
                charData.properties.setFlag(QLowEnergyCharacteristic::WriteSigned, true);
            else if (entry == QStringLiteral("reliable-write"))
                charData.properties.setFlag(QLowEnergyCharacteristic::ExtendedProperty, true);
            else if (entry == QStringLiteral("writable-auxiliaries"))
                charData.properties.setFlag(QLowEnergyCharacteristic::ExtendedProperty, true);
            //all others ignored - not relevant for this API
        }

        charData.uuid = QBluetoothUuid(dbusChar.characteristic->uUID());

        // schedule read for initial char value
        if (charData.properties.testFlag(QLowEnergyCharacteristic::Read)) {
            GattJob job;
            job.flags = GattJob::JobFlags({GattJob::CharRead, GattJob::ServiceDiscovery});
            job.service = serviceData;
            job.handle = indexHandle;
            jobs.append(job);
        }

        // descriptor data
        for (const auto &descEntry : qAsConst(dbusChar.descriptors)) {
            const QLowEnergyHandle descriptorHandle = runningHandle++;
            QLowEnergyServicePrivate::DescData descData;
            descData.uuid = QBluetoothUuid(descEntry->uUID());
            charData.descriptorList.insert(descriptorHandle, descData);


            // every ClientCharacteristicConfiguration needs to track property changes
            if (descData.uuid
                        == QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)) {
                dbusChar.charMonitor = QSharedPointer<OrgFreedesktopDBusPropertiesInterface>::create(
                                                QStringLiteral("org.bluez"),
                                                dbusChar.characteristic->path(),
                                                QDBusConnection::systemBus(), this);
                connect(dbusChar.charMonitor.data(), &OrgFreedesktopDBusPropertiesInterface::PropertiesChanged,
                        this, [this, indexHandle](const QString &interface, const QVariantMap &changedProperties,
                        const QStringList &removedProperties) {

                    characteristicPropertiesChanged(indexHandle, interface,
                                                    changedProperties, removedProperties);
                });
            }

            // schedule read for initial descriptor value
            GattJob job;
            job.flags = GattJob::JobFlags({GattJob::DescRead, GattJob::ServiceDiscovery});
            job.service = serviceData;
            job.handle = descriptorHandle;
            jobs.append(job);
        }

        serviceData->characteristicList[indexHandle] = charData;
    }

    serviceData->endHandle = runningHandle++;

    // last job is last step of service discovery
    if (!jobs.isEmpty()) {
        GattJob &lastJob = jobs.last();
        lastJob.flags.setFlag(GattJob::LastServiceDiscovery, true);
    } else {
        serviceData->setState(QLowEnergyService::ServiceDiscovered);
    }

    scheduleNextJob();
}

void QLowEnergyControllerPrivateBluezDBus::prepareNextJob()
{
    jobs.takeFirst(); // finish last job
    jobPending = false;

    scheduleNextJob(); // continue with next job - if available
}

void QLowEnergyControllerPrivateBluezDBus::onCharReadFinished(QDBusPendingCallWatcher *call)
{
    if (!jobPending || jobs.isEmpty()) {
        // this may happen when service disconnects before dbus watcher returns later on
        qCWarning(QT_BT_BLUEZ) << "Aborting onCharReadFinished due to disconnect";
        Q_ASSERT(state == QLowEnergyController::UnconnectedState);
        return;
    }

    const GattJob nextJob = jobs.constFirst();
    Q_ASSERT(nextJob.flags.testFlag(GattJob::CharRead));

    QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(nextJob.handle);
    if (service.isNull() || !dbusServices.contains(service->uuid)) {
        qCWarning(QT_BT_BLUEZ) << "onCharReadFinished: Invalid GATT job. Skipping.";
        call->deleteLater();
        prepareNextJob();
        return;
    }
    const QLowEnergyServicePrivate::CharData &charData =
                        service->characteristicList.value(nextJob.handle);

    bool isServiceDiscovery = nextJob.flags.testFlag(GattJob::ServiceDiscovery);
    QDBusPendingReply<QByteArray> reply = *call;
    if (reply.isError()) {
        qCWarning(QT_BT_BLUEZ) << "Cannot initiate reading of" << charData.uuid
                               << "of service" << service->uuid
                               << reply.error().name() << reply.error().message();
        if (!isServiceDiscovery)
            service->setError(QLowEnergyService::CharacteristicReadError);
    } else {
        qCDebug(QT_BT_BLUEZ) << "Read Char:" << charData.uuid << reply.value().toHex();
        if (charData.properties.testFlag(QLowEnergyCharacteristic::Read))
            updateValueOfCharacteristic(nextJob.handle, reply.value(), false);

        if (isServiceDiscovery) {
            if (nextJob.flags.testFlag(GattJob::LastServiceDiscovery))
                service->setState(QLowEnergyService::ServiceDiscovered);
        } else {
            QLowEnergyCharacteristic ch(service, nextJob.handle);
            emit service->characteristicRead(ch, reply.value());
        }
    }

    call->deleteLater();
    prepareNextJob();
}

void QLowEnergyControllerPrivateBluezDBus::onDescReadFinished(QDBusPendingCallWatcher *call)
{
    if (!jobPending || jobs.isEmpty()) {
        // this may happen when service disconnects before dbus watcher returns later on
        qCWarning(QT_BT_BLUEZ) << "Aborting onDescReadFinished due to disconnect";
        Q_ASSERT(state == QLowEnergyController::UnconnectedState);
        return;
    }

    const GattJob nextJob = jobs.constFirst();
    Q_ASSERT(nextJob.flags.testFlag(GattJob::DescRead));

    QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(nextJob.handle);
    if (service.isNull() || !dbusServices.contains(service->uuid)) {
        qCWarning(QT_BT_BLUEZ) << "onDescReadFinished: Invalid GATT job. Skipping.";
        call->deleteLater();
        prepareNextJob();
        return;
    }

    QLowEnergyCharacteristic ch = characteristicForHandle(nextJob.handle);
    if (!ch.isValid()) {
        qCWarning(QT_BT_BLUEZ) << "Cannot find char for desc read (onDescReadFinished 1).";
        call->deleteLater();
        prepareNextJob();
        return;
    }

    const QLowEnergyServicePrivate::CharData &charData =
                        service->characteristicList.value(ch.attributeHandle());

    if (!charData.descriptorList.contains(nextJob.handle)) {
        qCWarning(QT_BT_BLUEZ) << "Cannot find descriptor (onDescReadFinished 2).";
        call->deleteLater();
        prepareNextJob();
        return;
    }

    bool isServiceDiscovery = nextJob.flags.testFlag(GattJob::ServiceDiscovery);
    const QBluetoothUuid descUuid = charData.descriptorList[nextJob.handle].uuid;

    QDBusPendingReply<QByteArray> reply = *call;
    if (reply.isError()) {
        qCWarning(QT_BT_BLUEZ) << "Cannot read descriptor (onDescReadFinished 3): "
                             << charData.descriptorList[nextJob.handle].uuid
                             << charData.uuid
                             << reply.error().name() << reply.error().message();
        if (!isServiceDiscovery)
            service->setError(QLowEnergyService::DescriptorReadError);
    } else {
        qCDebug(QT_BT_BLUEZ) << "Read Desc:" << reply.value();
        updateValueOfDescriptor(ch.attributeHandle(), nextJob.handle, reply.value(), false);

        if (isServiceDiscovery) {
            if (nextJob.flags.testFlag(GattJob::LastServiceDiscovery))
                service->setState(QLowEnergyService::ServiceDiscovered);
        } else {
            QLowEnergyDescriptor desc(service, ch.attributeHandle(), nextJob.handle);
            emit service->descriptorRead(desc, reply.value());
        }
    }

    call->deleteLater();
    prepareNextJob();
}

void QLowEnergyControllerPrivateBluezDBus::onCharWriteFinished(QDBusPendingCallWatcher *call)
{
    if (!jobPending || jobs.isEmpty()) {
        // this may happen when service disconnects before dbus watcher returns later on
        qCWarning(QT_BT_BLUEZ) << "Aborting onCharWriteFinished due to disconnect";
        Q_ASSERT(state == QLowEnergyController::UnconnectedState);
        return;
    }

    const GattJob nextJob = jobs.constFirst();
    Q_ASSERT(nextJob.flags.testFlag(GattJob::CharWrite));

    QSharedPointer<QLowEnergyServicePrivate> service = nextJob.service;
    if (!dbusServices.contains(service->uuid)) {
        qCWarning(QT_BT_BLUEZ) << "onCharWriteFinished: Invalid GATT job. Skipping.";
        call->deleteLater();
        prepareNextJob();
        return;
    }

    const QLowEnergyServicePrivate::CharData &charData =
                        service->characteristicList.value(nextJob.handle);

    QDBusPendingReply<> reply = *call;
    if (reply.isError()) {
        qCWarning(QT_BT_BLUEZ) << "Cannot initiate writing of" << charData.uuid
                               << "of service" << service->uuid
                               << reply.error().name() << reply.error().message();
        service->setError(QLowEnergyService::CharacteristicWriteError);
    } else {
        if (charData.properties.testFlag(QLowEnergyCharacteristic::Read))
            updateValueOfCharacteristic(nextJob.handle, nextJob.value, false);

        QLowEnergyCharacteristic ch(service, nextJob.handle);
        // write without response implies zero feedback
        if (nextJob.writeMode == QLowEnergyService::WriteWithResponse) {
            qCDebug(QT_BT_BLUEZ) << "Written Char:" << charData.uuid << nextJob.value.toHex();
            emit service->characteristicWritten(ch, nextJob.value);
        }
    }

    call->deleteLater();
    prepareNextJob();
}

void QLowEnergyControllerPrivateBluezDBus::onDescWriteFinished(QDBusPendingCallWatcher *call)
{
    if (!jobPending || jobs.isEmpty()) {
        // this may happen when service disconnects before dbus watcher returns later on
        qCWarning(QT_BT_BLUEZ) << "Aborting onDescWriteFinished due to disconnect";
        Q_ASSERT(state == QLowEnergyController::UnconnectedState);
        return;
    }

    const GattJob nextJob = jobs.constFirst();
    Q_ASSERT(nextJob.flags.testFlag(GattJob::DescWrite));

    QSharedPointer<QLowEnergyServicePrivate> service = nextJob.service;
    if (!dbusServices.contains(service->uuid)) {
        qCWarning(QT_BT_BLUEZ) << "onDescWriteFinished: Invalid GATT job. Skipping.";
        call->deleteLater();
        prepareNextJob();
        return;
    }

    const QLowEnergyCharacteristic associatedChar = characteristicForHandle(nextJob.handle);
    const QLowEnergyDescriptor descriptor = descriptorForHandle(nextJob.handle);
    if (!associatedChar.isValid() || !descriptor.isValid()) {
        qCWarning(QT_BT_BLUEZ) << "onDescWriteFinished: Cannot find associated char/desc: "
                               << associatedChar.isValid();
        call->deleteLater();
        prepareNextJob();
        return;
    }

    QDBusPendingReply<> reply = *call;
    if (reply.isError()) {
        qCWarning(QT_BT_BLUEZ) << "Cannot initiate writing of" << descriptor.uuid()
                               << "of char" << associatedChar.uuid()
                               << "of service" << service->uuid
                               << reply.error().name() << reply.error().message();
        service->setError(QLowEnergyService::DescriptorWriteError);
    } else {
        qCDebug(QT_BT_BLUEZ) << "Write Desc:" << descriptor.uuid() << nextJob.value.toHex();
        updateValueOfDescriptor(associatedChar.attributeHandle(), nextJob.handle,
                                nextJob.value, false);
        emit service->descriptorWritten(descriptor, nextJob.value);
    }

    call->deleteLater();
    prepareNextJob();
}

void QLowEnergyControllerPrivateBluezDBus::scheduleNextJob()
{
    if (jobPending || jobs.isEmpty())
        return;

    jobPending = true;

    const GattJob nextJob = jobs.constFirst();
    QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(nextJob.handle);
    if (service.isNull() || !dbusServices.contains(service->uuid)) {
        qCWarning(QT_BT_BLUEZ) << "Invalid GATT job (scheduleNextJob). Skipping.";
        prepareNextJob();
        return;
    }

    const GattService &dbusServiceData = dbusServices[service->uuid];

    if (nextJob.flags.testFlag(GattJob::CharRead)) {
        // characteristic reading ***************************************
        if (!service->characteristicList.contains(nextJob.handle)) {
            qCWarning(QT_BT_BLUEZ) << "Invalid Char handle when reading. Skipping.";
            prepareNextJob();
            return;
        }

        const QLowEnergyServicePrivate::CharData &charData =
                            service->characteristicList.value(nextJob.handle);
        bool foundChar = false;
        for (const auto &gattChar : qAsConst(dbusServiceData.characteristics)) {
            if (charData.uuid != QBluetoothUuid(gattChar.characteristic->uUID()))
                continue;

            QDBusPendingReply<QByteArray> reply = gattChar.characteristic->ReadValue(QVariantMap());
            QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this);
            connect(watcher, &QDBusPendingCallWatcher::finished,
                    this, &QLowEnergyControllerPrivateBluezDBus::onCharReadFinished);

            foundChar = true;
            break;
        }

        if (!foundChar) {
            qCWarning(QT_BT_BLUEZ) << "Cannot find char for reading. Skipping.";
            prepareNextJob();
            return;
        }
    } else if (nextJob.flags.testFlag(GattJob::CharWrite)) {
        // characteristic writing ***************************************
        if (!service->characteristicList.contains(nextJob.handle)) {
            qCWarning(QT_BT_BLUEZ) << "Invalid Char handle when writing. Skipping.";
            prepareNextJob();
            return;
        }

        const QLowEnergyServicePrivate::CharData &charData =
                            service->characteristicList.value(nextJob.handle);
        bool foundChar = false;
        for (const auto &gattChar : qAsConst(dbusServiceData.characteristics)) {
            if (charData.uuid != QBluetoothUuid(gattChar.characteristic->uUID()))
                continue;

            QVariantMap options;
            // The "type" option only works with BlueZ >= 5.50, older versions always write with response
            options[QStringLiteral("type")] = nextJob.writeMode == QLowEnergyService::WriteWithoutResponse ?
                QStringLiteral("command") : QStringLiteral("request");
            QDBusPendingReply<> reply = gattChar.characteristic->WriteValue(nextJob.value, options);

            QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this);
            connect(watcher, &QDBusPendingCallWatcher::finished,
                    this, &QLowEnergyControllerPrivateBluezDBus::onCharWriteFinished);

            foundChar = true;
            break;
        }

        if (!foundChar) {
            qCWarning(QT_BT_BLUEZ) << "Cannot find char for writing. Skipping.";
            prepareNextJob();
            return;
        }
    } else if (nextJob.flags.testFlag(GattJob::DescRead)) {
        // descriptor reading ***************************************
        QLowEnergyCharacteristic ch = characteristicForHandle(nextJob.handle);
        if (!ch.isValid()) {
            qCWarning(QT_BT_BLUEZ) << "Invalid GATT job (scheduleReadDesc 1). Skipping.";
            prepareNextJob();
            return;
        }

        const QLowEnergyServicePrivate::CharData &charData =
                                service->characteristicList.value(ch.attributeHandle());
        if (!charData.descriptorList.contains(nextJob.handle)) {
            qCWarning(QT_BT_BLUEZ) << "Invalid GATT job (scheduleReadDesc 2). Skipping.";
            prepareNextJob();
            return;
        }

        const QBluetoothUuid descUuid = charData.descriptorList[nextJob.handle].uuid;
        bool foundDesc = false;
        for (const auto &gattChar : qAsConst(dbusServiceData.characteristics)) {
            if (charData.uuid != QBluetoothUuid(gattChar.characteristic->uUID()))
                continue;

            for (const auto &gattDesc : qAsConst(gattChar.descriptors)) {
                if (descUuid != QBluetoothUuid(gattDesc->uUID()))
                    continue;

                QDBusPendingReply<QByteArray> reply = gattDesc->ReadValue(QVariantMap());
                QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this);
                connect(watcher, &QDBusPendingCallWatcher::finished,
                        this, &QLowEnergyControllerPrivateBluezDBus::onDescReadFinished);
                foundDesc = true;
                break;
            }

            if (foundDesc)
                break;
        }

        if (!foundDesc) {
            qCWarning(QT_BT_BLUEZ) << "Cannot find descriptor for reading. Skipping.";
            prepareNextJob();
            return;
        }
    } else if (nextJob.flags.testFlag(GattJob::DescWrite)) {
        // descriptor writing ***************************************
        const QLowEnergyCharacteristic ch = characteristicForHandle(nextJob.handle);
        if (!ch.isValid()) {
            qCWarning(QT_BT_BLUEZ) << "Invalid GATT job (scheduleWriteDesc 1). Skipping.";
            prepareNextJob();
            return;
        }

        const QLowEnergyServicePrivate::CharData &charData =
                                service->characteristicList.value(ch.attributeHandle());
        if (!charData.descriptorList.contains(nextJob.handle)) {
            qCWarning(QT_BT_BLUEZ) << "Invalid GATT job (scheduleWriteDesc 2). Skipping.";
            prepareNextJob();
            return;
        }

        const QBluetoothUuid descUuid = charData.descriptorList[nextJob.handle].uuid;
        bool foundDesc = false;
        for (const auto &gattChar : qAsConst(dbusServiceData.characteristics)) {
            if (charData.uuid != QBluetoothUuid(gattChar.characteristic->uUID()))
                continue;

            for (const auto &gattDesc : qAsConst(gattChar.descriptors)) {
                if (descUuid != QBluetoothUuid(gattDesc->uUID()))
                    continue;

                //notifications enabled via characteristics Start/StopNotify() functions
                //otherwise regular WriteValue() calls on descriptor interface
                if (descUuid == QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)) {
                    const QByteArray value = nextJob.value;

                    QDBusPendingReply<> reply;
                    qCDebug(QT_BT_BLUEZ) << "Init CCC change to" << value.toHex()
                                         << charData.uuid << service->uuid;
                    if (value == QByteArray::fromHex("0100") || value == QByteArray::fromHex("0200"))
                        reply = gattChar.characteristic->StartNotify();
                    else
                        reply = gattChar.characteristic->StopNotify();
                    QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this);
                    connect(watcher, &QDBusPendingCallWatcher::finished,
                            this, &QLowEnergyControllerPrivateBluezDBus::onDescWriteFinished);
                } else {
                    QDBusPendingReply<> reply = gattDesc->WriteValue(nextJob.value, QVariantMap());
                    QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this);
                    connect(watcher, &QDBusPendingCallWatcher::finished,
                            this, &QLowEnergyControllerPrivateBluezDBus::onDescWriteFinished);

                }

                foundDesc = true;
                break;
            }

            if (foundDesc)
                break;
        }

        if (!foundDesc) {
            qCWarning(QT_BT_BLUEZ) << "Cannot find descriptor for writing. Skipping.";
            prepareNextJob();
            return;
        }
    } else {
        qCWarning(QT_BT_BLUEZ) << "Unknown gatt job type. Skipping.";
        prepareNextJob();
    }
}

void QLowEnergyControllerPrivateBluezDBus::readCharacteristic(
                    const QSharedPointer<QLowEnergyServicePrivate> service,
                    const QLowEnergyHandle charHandle)
{
    Q_ASSERT(!service.isNull());
    if (!service->characteristicList.contains(charHandle)) {
        qCWarning(QT_BT_BLUEZ) << "Read characteristic does not belong to service"
                               << service->uuid;
        return;
    }

    const QLowEnergyServicePrivate::CharData &charDetails
            = service->characteristicList[charHandle];
    if (!(charDetails.properties & QLowEnergyCharacteristic::Read)) {
        // if this succeeds the device has a bug, char is advertised as
        // non-readable. We try to be permissive and let the remote
        // device answer to the read attempt
        qCWarning(QT_BT_BLUEZ) << "Reading non-readable char" << charHandle;
    }

    const GattService &gattService = dbusServices[service->uuid];
    if (gattService.hasBatteryService && !gattService.batteryInterface.isNull()) {
        // Reread from dbus interface and write to local cache
        const QByteArray newValue(1, char(gattService.batteryInterface->percentage()));
        quint16 result = updateValueOfCharacteristic(charHandle, newValue, false);
        if (result > 0) {
            QLowEnergyCharacteristic ch(service, charHandle);
            emit service->characteristicRead(ch, newValue);
        } else {
            service->setError(QLowEnergyService::CharacteristicReadError);
        }
        return;
    }

    GattJob job;
    job.flags = GattJob::JobFlags({GattJob::CharRead});
    job.service = service;
    job.handle = charHandle;
    jobs.append(job);

    scheduleNextJob();
}

void QLowEnergyControllerPrivateBluezDBus::readDescriptor(
                    const QSharedPointer<QLowEnergyServicePrivate> service,
                    const QLowEnergyHandle charHandle,
                    const QLowEnergyHandle descriptorHandle)
{
    Q_ASSERT(!service.isNull());
    if (!service->characteristicList.contains(charHandle))
        return;

    const QLowEnergyServicePrivate::CharData &charDetails
            = service->characteristicList[charHandle];
    if (!charDetails.descriptorList.contains(descriptorHandle))
        return;

    const GattService &gattService = dbusServices[service->uuid];
    if (gattService.hasBatteryService && !gattService.batteryInterface.isNull()) {
        auto descriptor = descriptorForHandle(descriptorHandle);
        if (descriptor.isValid())
            emit service->descriptorRead(descriptor, descriptor.value());
        else
            service->setError(QLowEnergyService::DescriptorReadError);

        return;
    }

    GattJob job;
    job.flags = GattJob::JobFlags({GattJob::DescRead});
    job.service = service;
    job.handle = descriptorHandle;
    jobs.append(job);

    scheduleNextJob();
}

void QLowEnergyControllerPrivateBluezDBus::writeCharacteristic(
                    const QSharedPointer<QLowEnergyServicePrivate> service,
                    const QLowEnergyHandle charHandle,
                    const QByteArray &newValue,
                    QLowEnergyService::WriteMode writeMode)
{
    Q_ASSERT(!service.isNull());
    if (!service->characteristicList.contains(charHandle)) {
        qCWarning(QT_BT_BLUEZ) << "Write characteristic does not belong to service"
                               << service->uuid;
        return;
    }

    if (role == QLowEnergyController::CentralRole) {
        const GattService &gattService = dbusServices[service->uuid];
        if (gattService.hasBatteryService && !gattService.batteryInterface.isNull()) {
            //Battery1 interface is readonly
            service->setError(QLowEnergyService::CharacteristicWriteError);
            return;
        }


        GattJob job;
        job.flags = GattJob::JobFlags({GattJob::CharWrite});
        job.service = service;
        job.handle = charHandle;
        job.value = newValue;
        job.writeMode = writeMode;
        jobs.append(job);

        scheduleNextJob();
    } else {
        qWarning(QT_BT_BLUEZ) << "writeCharacteristic() not implemented for DBus Bluez GATT";
        service->setError(QLowEnergyService::CharacteristicWriteError);
    }
}

void QLowEnergyControllerPrivateBluezDBus::writeDescriptor(
                    const QSharedPointer<QLowEnergyServicePrivate> service,
                    const QLowEnergyHandle charHandle,
                    const QLowEnergyHandle descriptorHandle,
                    const QByteArray &newValue)
{
    Q_ASSERT(!service.isNull());
    if (!service->characteristicList.contains(charHandle))
        return;

    if (role == QLowEnergyController::CentralRole) {
        const GattService &gattService = dbusServices[service->uuid];
        if (gattService.hasBatteryService && !gattService.batteryInterface.isNull()) {
            auto descriptor = descriptorForHandle(descriptorHandle);
            if (!descriptor.isValid())
                return;

            if (descriptor.uuid() == QBluetoothUuid::ClientCharacteristicConfiguration) {
                if (newValue == QByteArray::fromHex("0000")
                        || newValue == QByteArray::fromHex("0100")
                    || newValue == QByteArray::fromHex("0200")) {
                    quint16 result = updateValueOfDescriptor(charHandle, descriptorHandle, newValue, false);
                    if (result > 0)
                        emit service->descriptorWritten(descriptor, newValue);
                    else
                        emit service->setError(QLowEnergyService::DescriptorWriteError);

                }
            } else {
                service->setError(QLowEnergyService::DescriptorWriteError);
            }

            return;
        }

        GattJob job;
        job.flags = GattJob::JobFlags({GattJob::DescWrite});
        job.service = service;
        job.handle = descriptorHandle;
        job.value = newValue;
        jobs.append(job);

        scheduleNextJob();
    } else {
        qWarning(QT_BT_BLUEZ) << "writeDescriptor() peripheral not implemented for DBus Bluez GATT";
        service->setError(QLowEnergyService::CharacteristicWriteError);
    }
}

void QLowEnergyControllerPrivateBluezDBus::startAdvertising(
                    const QLowEnergyAdvertisingParameters &/* params */,
                    const QLowEnergyAdvertisingData &/* advertisingData */,
                    const QLowEnergyAdvertisingData &/* scanResponseData */)
{
}

void QLowEnergyControllerPrivateBluezDBus::stopAdvertising()
{
}

void QLowEnergyControllerPrivateBluezDBus::requestConnectionUpdate(
                    const QLowEnergyConnectionParameters & /* params */)
{
}

void QLowEnergyControllerPrivateBluezDBus::addToGenericAttributeList(
                    const QLowEnergyServiceData &/* service */,
                    QLowEnergyHandle /* startHandle */)
{
}

QLowEnergyService *QLowEnergyControllerPrivateBluezDBus::addServiceHelper(
                    const QLowEnergyServiceData &/*service*/)
{
    return nullptr;
}

QT_END_NAMESPACE
