/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com>
** 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_win_p.h"
#include "qbluetoothdevicediscoveryagent_p.h"

#include <QtCore/QLoggingCategory>
#include <QtCore/QIODevice> // for open modes
#include <QtCore/QEvent>
#include <QtCore/QMutex>
#include <QtCore/QThread>
#include <QtCore/QDataStream>
#include <QtCore/QCoreApplication>

#include <algorithm> // for std::max

#include <SetupAPI.h>

QT_BEGIN_NAMESPACE

Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINDOWS)

Q_GLOBAL_STATIC(QLibrary, bluetoothapis)

Q_GLOBAL_STATIC(QVector<QLowEnergyControllerPrivateWin32 *>, qControllers)
static QMutex controllersGuard(QMutex::NonRecursive);

const QEvent::Type CharactericticValueEventType = static_cast<QEvent::Type>(QEvent::User + 1);

class CharactericticValueEvent : public QEvent
{
public:
    explicit CharactericticValueEvent(const PBLUETOOTH_GATT_VALUE_CHANGED_EVENT gattValueChangedEvent)
        : QEvent(CharactericticValueEventType)
        , m_handle(0)
    {
        if (!gattValueChangedEvent || gattValueChangedEvent->CharacteristicValueDataSize == 0)
            return;

        m_handle = gattValueChangedEvent->ChangedAttributeHandle;

        const PBTH_LE_GATT_CHARACTERISTIC_VALUE gattValue = gattValueChangedEvent->CharacteristicValue;
        if (!gattValue)
            return;

        m_value = QByteArray(reinterpret_cast<const char *>(&gattValue->Data[0]),
                int(gattValue->DataSize));
    }

    QByteArray m_value;
    QLowEnergyHandle m_handle;
};

// Bit masks of ClientCharacteristicConfiguration value, see btle spec.
namespace ClientCharacteristicConfigurationValue {
enum { UseNotifications = 0x1, UseIndications = 0x2 };
}

static bool gattFunctionsResolved = false;

static QBluetoothAddress getDeviceAddress(const QString &servicePath)
{
    const int firstbound = servicePath.lastIndexOf(QStringLiteral("_"));
    const int lastbound = servicePath.indexOf(QLatin1Char('#'), firstbound);
    const QString hex = servicePath.mid(firstbound + 1, lastbound - firstbound - 1);
    bool ok = false;
    return QBluetoothAddress(hex.toULongLong(&ok, 16));
}

static QString getServiceSystemPath(const QBluetoothAddress &deviceAddress,
                                    const QBluetoothUuid &serviceUuid, int *systemErrorCode)
{
    const HDEVINFO deviceInfoSet = ::SetupDiGetClassDevs(
                reinterpret_cast<const GUID *>(&serviceUuid),
                nullptr,
                nullptr,
                DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

    if (deviceInfoSet == INVALID_HANDLE_VALUE) {
        *systemErrorCode = int(::GetLastError());
        return QString();
    }

    QString foundSystemPath;
    DWORD index = 0;

    for (;;) {
        SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
        ::ZeroMemory(&deviceInterfaceData, sizeof(deviceInterfaceData));
        deviceInterfaceData.cbSize = sizeof(deviceInterfaceData);

        if (!::SetupDiEnumDeviceInterfaces(
                    deviceInfoSet,
                    nullptr,
                    reinterpret_cast<const GUID *>(&serviceUuid),
                    index++,
                    &deviceInterfaceData)) {
            *systemErrorCode = int(::GetLastError());
            break;
        }

        DWORD deviceInterfaceDetailDataSize = 0;
        if (!::SetupDiGetDeviceInterfaceDetail(
                    deviceInfoSet,
                    &deviceInterfaceData,
                    nullptr,
                    deviceInterfaceDetailDataSize,
                    &deviceInterfaceDetailDataSize,
                    nullptr)) {
            const int error = int(::GetLastError());
            if (error != ERROR_INSUFFICIENT_BUFFER) {
                *systemErrorCode = error;
                break;
            }
        }

        SP_DEVINFO_DATA deviceInfoData;
        ::ZeroMemory(&deviceInfoData, sizeof(deviceInfoData));
        deviceInfoData.cbSize = sizeof(deviceInfoData);

        QByteArray deviceInterfaceDetailDataBuffer(
                    int(deviceInterfaceDetailDataSize), 0);

        PSP_INTERFACE_DEVICE_DETAIL_DATA deviceInterfaceDetailData =
                reinterpret_cast<PSP_INTERFACE_DEVICE_DETAIL_DATA>
                (deviceInterfaceDetailDataBuffer.data());

        deviceInterfaceDetailData->cbSize =
                sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);

        if (!::SetupDiGetDeviceInterfaceDetail(
                    deviceInfoSet,
                    &deviceInterfaceData,
                    deviceInterfaceDetailData,
                    DWORD(deviceInterfaceDetailDataBuffer.size()),
                    &deviceInterfaceDetailDataSize,
                    &deviceInfoData)) {
            *systemErrorCode = int(::GetLastError());
            break;
        }

        // We need to check on required device address which contains in a
        // system path. As it is not enough to use only service UUID for this.
        const auto candidateSystemPath = QString::fromWCharArray(deviceInterfaceDetailData->DevicePath);
        const auto candidateDeviceAddress = getDeviceAddress(candidateSystemPath);
        if (candidateDeviceAddress == deviceAddress) {
            foundSystemPath = candidateSystemPath;
            *systemErrorCode = NO_ERROR;
            break;
        }
    }

    ::SetupDiDestroyDeviceInfoList(deviceInfoSet);
    return foundSystemPath;
}

static HANDLE openSystemDevice(
        const QString &systemPath, QIODevice::OpenMode openMode, int *systemErrorCode)
{
    DWORD desiredAccess = 0;
    DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;

    if (openMode & QIODevice::ReadOnly) {
        desiredAccess |= GENERIC_READ;
    }

    if (openMode & QIODevice::WriteOnly) {
        desiredAccess |= GENERIC_WRITE;
        shareMode &= ~DWORD(FILE_SHARE_WRITE);
    }

    const HANDLE hDevice = ::CreateFile(
                reinterpret_cast<const wchar_t *>(systemPath.utf16()),
                desiredAccess,
                shareMode,
                nullptr,
                OPEN_EXISTING,
                0,
                nullptr);

    *systemErrorCode = (INVALID_HANDLE_VALUE == hDevice)
            ? int(::GetLastError()) : NO_ERROR;
    return hDevice;
}

static HANDLE openSystemService(const QBluetoothAddress &deviceAddress,
        const QBluetoothUuid &service, QIODevice::OpenMode openMode, int *systemErrorCode)
{
    const QString serviceSystemPath = getServiceSystemPath(
                deviceAddress, service, systemErrorCode);

    if (*systemErrorCode != NO_ERROR)
        return INVALID_HANDLE_VALUE;

    const HANDLE hService = openSystemDevice(
                serviceSystemPath, openMode, systemErrorCode);

    if (*systemErrorCode != NO_ERROR)
        return INVALID_HANDLE_VALUE;

    return hService;
}

static void closeSystemDevice(HANDLE hDevice)
{
    if (hDevice && hDevice != INVALID_HANDLE_VALUE)
        ::CloseHandle(hDevice);
}

static QVector<BTH_LE_GATT_SERVICE> enumeratePrimaryGattServices(
        HANDLE hDevice, int *systemErrorCode)
{
    if (!gattFunctionsResolved) {
        *systemErrorCode = ERROR_NOT_SUPPORTED;
        return QVector<BTH_LE_GATT_SERVICE>();
    }

    QVector<BTH_LE_GATT_SERVICE> foundServices;
    USHORT servicesCount = 0;
    for (;;) {
        const HRESULT hr = ::BluetoothGATTGetServices(
                    hDevice,
                    servicesCount,
                    foundServices.isEmpty() ? nullptr : &foundServices[0],
                    &servicesCount,
                    BLUETOOTH_GATT_FLAG_NONE);

        if (SUCCEEDED(hr)) {
            *systemErrorCode = NO_ERROR;
            return foundServices;
        } else {
            const int error = WIN32_FROM_HRESULT(hr);
            if (error == ERROR_MORE_DATA) {
                foundServices.resize(servicesCount);
            } else {
                *systemErrorCode = error;
                return QVector<BTH_LE_GATT_SERVICE>();
            }
        }
    }
}

static QVector<BTH_LE_GATT_CHARACTERISTIC> enumerateGattCharacteristics(
        HANDLE hService, PBTH_LE_GATT_SERVICE gattService, int *systemErrorCode)
{
    if (!gattFunctionsResolved) {
        *systemErrorCode = ERROR_NOT_SUPPORTED;
        return QVector<BTH_LE_GATT_CHARACTERISTIC>();
    }

    QVector<BTH_LE_GATT_CHARACTERISTIC> foundCharacteristics;
    USHORT characteristicsCount = 0;
    for (;;) {
        const HRESULT hr = ::BluetoothGATTGetCharacteristics(
                    hService,
                    gattService,
                    characteristicsCount,
                    foundCharacteristics.isEmpty() ? nullptr : &foundCharacteristics[0],
                    &characteristicsCount,
                    BLUETOOTH_GATT_FLAG_NONE);

        if (SUCCEEDED(hr)) {
            *systemErrorCode = NO_ERROR;
            return foundCharacteristics;
        } else {
            const int error = WIN32_FROM_HRESULT(hr);
            if (error == ERROR_MORE_DATA) {
                foundCharacteristics.resize(characteristicsCount);
            } else {
                *systemErrorCode = error;
                return QVector<BTH_LE_GATT_CHARACTERISTIC>();
            }
        }
    }
}

static QByteArray getGattCharacteristicValue(
        HANDLE hService, PBTH_LE_GATT_CHARACTERISTIC gattCharacteristic, int *systemErrorCode)
{
    if (!gattFunctionsResolved) {
        *systemErrorCode = ERROR_NOT_SUPPORTED;
        return QByteArray();
    }

    QByteArray valueBuffer;
    USHORT valueBufferSize = 0;
    for (;;) {
        const auto valuePtr = valueBuffer.isEmpty()
                ? nullptr
                : reinterpret_cast<PBTH_LE_GATT_CHARACTERISTIC_VALUE>(valueBuffer.data());

        const HRESULT hr = ::BluetoothGATTGetCharacteristicValue(
                    hService,
                    gattCharacteristic,
                    valueBufferSize,
                    valuePtr,
                    &valueBufferSize,
                    BLUETOOTH_GATT_FLAG_NONE);

        if (SUCCEEDED(hr)) {
            *systemErrorCode = NO_ERROR;
            return QByteArray(reinterpret_cast<const char *>(&valuePtr->Data[0]),
                    int(valuePtr->DataSize));
        } else {
            const int error = WIN32_FROM_HRESULT(hr);
            if (error == ERROR_MORE_DATA) {
                valueBuffer.resize(valueBufferSize);
                valueBuffer.fill(0);
            } else {
                *systemErrorCode = error;
                return QByteArray();
            }
        }
    }
}

static void setGattCharacteristicValue(
        HANDLE hService, PBTH_LE_GATT_CHARACTERISTIC gattCharacteristic,
        const QByteArray &value, DWORD flags, int *systemErrorCode)
{
    if (!gattFunctionsResolved) {
        *systemErrorCode = ERROR_NOT_SUPPORTED;
        return;
    }

    QByteArray valueBuffer;
    QDataStream out(&valueBuffer, QIODevice::WriteOnly);
    ULONG dataSize = ULONG(value.size());
    out.writeRawData(reinterpret_cast<const char *>(&dataSize), sizeof(dataSize));
    out.writeRawData(value.constData(), value.size());

    BTH_LE_GATT_RELIABLE_WRITE_CONTEXT reliableWriteContext = 0;

    const HRESULT hr = ::BluetoothGATTSetCharacteristicValue(
                hService,
                gattCharacteristic,
                reinterpret_cast<PBTH_LE_GATT_CHARACTERISTIC_VALUE>(valueBuffer.data()),
                reliableWriteContext,
                flags);

    if (SUCCEEDED(hr))
        *systemErrorCode = NO_ERROR;
    else
        *systemErrorCode = WIN32_FROM_HRESULT(hr);
}

static QVector<BTH_LE_GATT_DESCRIPTOR> enumerateGattDescriptors(
        HANDLE hService, PBTH_LE_GATT_CHARACTERISTIC gattCharacteristic, int *systemErrorCode)
{
    if (!gattFunctionsResolved) {
        *systemErrorCode = ERROR_NOT_SUPPORTED;
        return QVector<BTH_LE_GATT_DESCRIPTOR>();
    }

    QVector<BTH_LE_GATT_DESCRIPTOR> foundDescriptors;
    USHORT descriptorsCount = 0;
    for (;;) {
        const HRESULT hr = ::BluetoothGATTGetDescriptors(
                    hService,
                    gattCharacteristic,
                    descriptorsCount,
                    foundDescriptors.isEmpty() ? nullptr : &foundDescriptors[0],
                    &descriptorsCount,
                    BLUETOOTH_GATT_FLAG_NONE);

        if (SUCCEEDED(hr)) {
            *systemErrorCode = NO_ERROR;
            return foundDescriptors;
        } else {
            const int error = WIN32_FROM_HRESULT(hr);
            if (error == ERROR_MORE_DATA) {
                foundDescriptors.resize(descriptorsCount);
            } else {
                *systemErrorCode = error;
                return QVector<BTH_LE_GATT_DESCRIPTOR>();
            }
        }
    }
}

static QByteArray getGattDescriptorValue(
        HANDLE hService, PBTH_LE_GATT_DESCRIPTOR gattDescriptor, int *systemErrorCode)
{
    if (!gattFunctionsResolved) {
        *systemErrorCode = ERROR_NOT_SUPPORTED;
        return QByteArray();
    }

    QByteArray valueBuffer;
    USHORT valueBufferSize = 0;
    for (;;) {
        const auto valuePtr = valueBuffer.isEmpty()
                ? nullptr
                : reinterpret_cast<PBTH_LE_GATT_DESCRIPTOR_VALUE>(valueBuffer.data());

        const HRESULT hr = ::BluetoothGATTGetDescriptorValue(
                    hService,
                    gattDescriptor,
                    valueBufferSize,
                    valuePtr,
                    &valueBufferSize,
                    BLUETOOTH_GATT_FLAG_NONE);

        if (SUCCEEDED(hr)) {
            *systemErrorCode = NO_ERROR;
            if (gattDescriptor->DescriptorType == CharacteristicUserDescription) {
                QString valueString = QString::fromUtf16(reinterpret_cast<const ushort *>(&valuePtr->Data[0]),
                        valuePtr->DataSize/2);
                return valueString.toUtf8();
            }
            return QByteArray(reinterpret_cast<const char *>(&valuePtr->Data[0]),
                    int(valuePtr->DataSize));
        } else {
            const int error = WIN32_FROM_HRESULT(hr);
            if (error == ERROR_MORE_DATA) {
                valueBuffer.resize(valueBufferSize);
                valueBuffer.fill(0);
            } else {
                *systemErrorCode = error;
                return QByteArray();
            }
        }
    }
}

static void setGattDescriptorValue(
        HANDLE hService, PBTH_LE_GATT_DESCRIPTOR gattDescriptor,
        QByteArray value, int *systemErrorCode)
{
    if (!gattFunctionsResolved) {
        *systemErrorCode = ERROR_NOT_SUPPORTED;
        return;
    }

    const int requiredValueBufferSize = int(sizeof(BTH_LE_GATT_DESCRIPTOR_VALUE))
                + value.size();

    QByteArray valueBuffer(requiredValueBufferSize, 0);

    PBTH_LE_GATT_DESCRIPTOR_VALUE gattValue = reinterpret_cast<
                PBTH_LE_GATT_DESCRIPTOR_VALUE>(valueBuffer.data());

    gattValue->DescriptorType = gattDescriptor->DescriptorType;

    if (gattValue->DescriptorType == ClientCharacteristicConfiguration) {
        QDataStream in(value);
        quint8 u;
        in >> u;

        // We need to setup appropriate fields that allow to subscribe for events.
        gattValue->ClientCharacteristicConfiguration.IsSubscribeToNotification =
                bool(u & ClientCharacteristicConfigurationValue::UseNotifications);
        gattValue->ClientCharacteristicConfiguration.IsSubscribeToIndication =
                bool(u & ClientCharacteristicConfigurationValue::UseIndications);
    }

    gattValue->DataSize = ULONG(value.size());
    ::memcpy(gattValue->Data, value.constData(), size_t(value.size()));

    const HRESULT hr = ::BluetoothGATTSetDescriptorValue(
                hService,
                gattDescriptor,
                gattValue,
                BLUETOOTH_GATT_FLAG_NONE);

    if (SUCCEEDED(hr))
        *systemErrorCode = NO_ERROR;
    else
        *systemErrorCode = WIN32_FROM_HRESULT(hr);
}

static void WINAPI eventChangedCallbackEntry(
        BTH_LE_GATT_EVENT_TYPE eventType, PVOID eventOutParameter, PVOID context)
{
    if ((eventType != CharacteristicValueChangedEvent) || !eventOutParameter || !context)
        return;

    QMutexLocker locker(&controllersGuard);
    const auto target = static_cast<QLowEnergyControllerPrivateWin32 *>(context);
    if (!qControllers->contains(target))
        return;

    CharactericticValueEvent *e = new CharactericticValueEvent(
                reinterpret_cast<const PBLUETOOTH_GATT_VALUE_CHANGED_EVENT>(eventOutParameter));

    QCoreApplication::postEvent(target, e);
}

static HANDLE registerEvent(
        HANDLE hService, BTH_LE_GATT_CHARACTERISTIC gattCharacteristic,
        PVOID context, int *systemErrorCode)
{
    if (!gattFunctionsResolved) {
        *systemErrorCode = ERROR_NOT_SUPPORTED;
        return INVALID_HANDLE_VALUE;
    }

    HANDLE hEvent = INVALID_HANDLE_VALUE;

    BLUETOOTH_GATT_VALUE_CHANGED_EVENT_REGISTRATION registration;
    ::ZeroMemory(&registration, sizeof(registration));
    registration.NumCharacteristics = 1;
    registration.Characteristics[0] = gattCharacteristic;

    const HRESULT hr = ::BluetoothGATTRegisterEvent(
                hService,
                CharacteristicValueChangedEvent,
                &registration,
                eventChangedCallbackEntry,
                context,
                &hEvent,
                BLUETOOTH_GATT_FLAG_NONE);

    if (SUCCEEDED(hr))
        *systemErrorCode = NO_ERROR;
    else
        *systemErrorCode = WIN32_FROM_HRESULT(hr);

    return hEvent;
}

static void unregisterEvent(HANDLE hEvent, int *systemErrorCode)
{
    if (!gattFunctionsResolved) {
        *systemErrorCode = ERROR_NOT_SUPPORTED;
        return;
    }

    const HRESULT hr = ::BluetoothGATTUnregisterEvent(
                hEvent,
                BLUETOOTH_GATT_FLAG_NONE);

    if (SUCCEEDED(hr))
        *systemErrorCode = NO_ERROR;
    else
        *systemErrorCode = WIN32_FROM_HRESULT(hr);
}

static QBluetoothUuid qtBluetoothUuidFromNativeLeUuid(const BTH_LE_UUID &uuid)
{
    return uuid.IsShortUuid ? QBluetoothUuid(uuid.Value.ShortUuid)
                            : QBluetoothUuid(uuid.Value.LongUuid);
}

static BTH_LE_UUID nativeLeUuidFromQtBluetoothUuid(const QBluetoothUuid &uuid)
{
    BTH_LE_UUID gattUuid;
    ::ZeroMemory(&gattUuid, sizeof(gattUuid));
    if (uuid.minimumSize() == 2) {
        gattUuid.IsShortUuid = TRUE;
        gattUuid.Value.ShortUuid = USHORT(uuid.data1); // other fields should be empty!
    } else {
        gattUuid.Value.LongUuid = uuid;
    }
    return gattUuid;
}

static BTH_LE_GATT_CHARACTERISTIC recoverNativeLeGattCharacteristic(
        QLowEnergyHandle serviceHandle, QLowEnergyHandle characteristicHandle,
        const QLowEnergyServicePrivate::CharData &characteristicData)
{
    BTH_LE_GATT_CHARACTERISTIC gattCharacteristic;

    gattCharacteristic.ServiceHandle = serviceHandle;
    gattCharacteristic.AttributeHandle = characteristicHandle;
    gattCharacteristic.CharacteristicValueHandle = characteristicData.valueHandle;

    gattCharacteristic.CharacteristicUuid = nativeLeUuidFromQtBluetoothUuid(
                characteristicData.uuid);

    gattCharacteristic.HasExtendedProperties = bool(characteristicData.properties
            & QLowEnergyCharacteristic::ExtendedProperty);
    gattCharacteristic.IsBroadcastable = bool(characteristicData.properties
            & QLowEnergyCharacteristic::Broadcasting);
    gattCharacteristic.IsIndicatable = bool(characteristicData.properties
            & QLowEnergyCharacteristic::Indicate);
    gattCharacteristic.IsNotifiable = bool(characteristicData.properties
            & QLowEnergyCharacteristic::Notify);
    gattCharacteristic.IsReadable = bool(characteristicData.properties
            & QLowEnergyCharacteristic::Read);
    gattCharacteristic.IsSignedWritable = bool(characteristicData.properties
            & QLowEnergyCharacteristic::WriteSigned);
    gattCharacteristic.IsWritable = bool(characteristicData.properties
            & QLowEnergyCharacteristic::Write);
    gattCharacteristic.IsWritableWithoutResponse = bool(characteristicData.properties
            & QLowEnergyCharacteristic::WriteNoResponse);

    return gattCharacteristic;
}

static BTH_LE_GATT_DESCRIPTOR_TYPE nativeLeGattDescriptorTypeFromUuid(
        const QBluetoothUuid &uuid)
{
    switch (uuid.toUInt16()) {
    case QBluetoothUuid::CharacteristicExtendedProperties:
        return CharacteristicExtendedProperties;
    case QBluetoothUuid::CharacteristicUserDescription:
        return CharacteristicUserDescription;
    case QBluetoothUuid::ClientCharacteristicConfiguration:
        return ClientCharacteristicConfiguration;
    case QBluetoothUuid::ServerCharacteristicConfiguration:
        return ServerCharacteristicConfiguration;
    case QBluetoothUuid::CharacteristicPresentationFormat:
        return CharacteristicFormat;
    case QBluetoothUuid::CharacteristicAggregateFormat:
        return CharacteristicAggregateFormat;
    default:
        return CustomDescriptor;
    }
}

static BTH_LE_GATT_DESCRIPTOR recoverNativeLeGattDescriptor(
        QLowEnergyHandle serviceHandle, QLowEnergyHandle characteristicHandle,
        QLowEnergyHandle descriptorHandle,
         const QLowEnergyServicePrivate::DescData &descriptorData)
{
    BTH_LE_GATT_DESCRIPTOR gattDescriptor;

    gattDescriptor.ServiceHandle = serviceHandle;
    gattDescriptor.CharacteristicHandle = characteristicHandle;
    gattDescriptor.AttributeHandle = descriptorHandle;

    gattDescriptor.DescriptorUuid = nativeLeUuidFromQtBluetoothUuid(
                descriptorData.uuid);

    gattDescriptor.DescriptorType = nativeLeGattDescriptorTypeFromUuid
            (descriptorData.uuid);

    return gattDescriptor;
}

void QLowEnergyControllerPrivateWin32::customEvent(QEvent *e)
{
    if (e->type() != CharactericticValueEventType)
        return;

    const CharactericticValueEvent *characteristicEvent
            = static_cast<CharactericticValueEvent *>(e);

    updateValueOfCharacteristic(characteristicEvent->m_handle,
                                characteristicEvent->m_value, false);

    const QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(
                characteristicEvent->m_handle);
    if (service.isNull())
        return;

    const QLowEnergyCharacteristic ch(service, characteristicEvent->m_handle);
    emit service->characteristicChanged(ch, characteristicEvent->m_value);
}

QLowEnergyControllerPrivateWin32::QLowEnergyControllerPrivateWin32()
    : QLowEnergyControllerPrivate()
{
    QMutexLocker locker(&controllersGuard);
    qControllers()->append(this);

    gattFunctionsResolved = resolveFunctions(bluetoothapis());
    if (!gattFunctionsResolved) {
        qCWarning(QT_BT_WINDOWS) << "LE is not supported on this OS";
        return;
    }
}

QLowEnergyControllerPrivateWin32::~QLowEnergyControllerPrivateWin32()
{
    QMutexLocker locker(&controllersGuard);
    qControllers()->removeAll(this);
}

void QLowEnergyControllerPrivateWin32::init()
{
}

void QLowEnergyControllerPrivateWin32::connectToDevice()
{
    // required to pass unit test on default backend
    if (remoteDevice.isNull()) {
        qWarning() << "Invalid/null remote device address";
        setError(QLowEnergyController::UnknownRemoteDeviceError);
        return;
    }

    if (!deviceSystemPath.isEmpty()) {
        qCDebug(QT_BT_WINDOWS) << "Already is connected";
        return;
    }

    setState(QLowEnergyController::ConnectingState);

    deviceSystemPath =
            QBluetoothDeviceDiscoveryAgentPrivate::discoveredLeDeviceSystemPath(
                remoteDevice);

    if (deviceSystemPath.isEmpty()) {
        qCWarning(QT_BT_WINDOWS) << qt_error_string(ERROR_PATH_NOT_FOUND);
        setError(QLowEnergyController::UnknownRemoteDeviceError);
        setState(QLowEnergyController::UnconnectedState);
        return;
    }

    setState(QLowEnergyController::ConnectedState);

    thread = new QThread;
    threadWorker = new ThreadWorker;
    threadWorker->moveToThread(thread);
    connect(threadWorker, &ThreadWorker::jobFinished, this, &QLowEnergyControllerPrivateWin32::jobFinished);
    connect(thread, &QThread::finished, threadWorker, &ThreadWorker::deleteLater);
    connect(thread, &QThread::finished, thread, &QThread::deleteLater);
    thread->start();

    Q_Q(QLowEnergyController);
    emit q->connected();
}

void QLowEnergyControllerPrivateWin32::disconnectFromDevice()
{
    if (deviceSystemPath.isEmpty()) {
        qCDebug(QT_BT_WINDOWS) << "Already is disconnected";
        return;
    }

    setState(QLowEnergyController::ClosingState);
    deviceSystemPath.clear();
    setState(QLowEnergyController::UnconnectedState);

    if (thread) {
        disconnect(threadWorker, &ThreadWorker::jobFinished, this, &QLowEnergyControllerPrivateWin32::jobFinished);
        thread->quit();
        thread = nullptr;
    }

    for (const auto &servicePrivate: serviceList)
        closeSystemDevice(servicePrivate->hService);

    Q_Q(QLowEnergyController);
    emit q->disconnected();
}

void QLowEnergyControllerPrivateWin32::discoverServices()
{
    int systemErrorCode = NO_ERROR;

    const HANDLE hDevice = openSystemDevice(
                deviceSystemPath, QIODevice::ReadOnly, &systemErrorCode);

    if (systemErrorCode != NO_ERROR) {
        qCWarning(QT_BT_WINDOWS) << qt_error_string(systemErrorCode);
        setError(QLowEnergyController::NetworkError);
        setState(QLowEnergyController::ConnectedState);
        return;
    }

    const QVector<BTH_LE_GATT_SERVICE> foundServices =
            enumeratePrimaryGattServices(hDevice, &systemErrorCode);

    closeSystemDevice(hDevice);

    if (systemErrorCode != NO_ERROR) {
        qCWarning(QT_BT_WINDOWS) << qt_error_string(systemErrorCode);
        setError(QLowEnergyController::NetworkError);
        setState(QLowEnergyController::ConnectedState);
        return;
    }

    setState(QLowEnergyController::DiscoveringState);

    Q_Q(QLowEnergyController);

    for (const BTH_LE_GATT_SERVICE &service : foundServices) {
        const QBluetoothUuid uuid = qtBluetoothUuidFromNativeLeUuid(
                    service.ServiceUuid);
        qCDebug(QT_BT_WINDOWS) << "Found uuid:" << uuid;

        QLowEnergyServicePrivate *priv = new QLowEnergyServicePrivate();
        priv->uuid = uuid;
        priv->type = QLowEnergyService::PrimaryService;
        priv->startHandle = service.AttributeHandle;
        priv->setController(this);

        QSharedPointer<QLowEnergyServicePrivate> pointer(priv);
        serviceList.insert(uuid, pointer);

        emit q->serviceDiscovered(uuid);
    }

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

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

    const QSharedPointer<QLowEnergyServicePrivate> servicePrivate =
                serviceList.value(service);

    int systemErrorCode = NO_ERROR;

    // Only open a service once and close it in the QLowEnergyServicePrivate destructor
    if (!servicePrivate->hService || servicePrivate->hService == INVALID_HANDLE_VALUE) {
        servicePrivate->hService = openSystemService(remoteDevice, service,
                                                     QIODevice::ReadOnly | QIODevice::WriteOnly,
                                                     &systemErrorCode);
        if (systemErrorCode != NO_ERROR) {
            servicePrivate->hService = openSystemService(remoteDevice, service,
                                                         QIODevice::ReadOnly,
                                                         &systemErrorCode);
        }
    }

    if (systemErrorCode != NO_ERROR) {
        qCWarning(QT_BT_WINDOWS) << "Unable to open service" << service.toString()
                                 << ":" << qt_error_string(systemErrorCode);
        servicePrivate->setError(QLowEnergyService::UnknownError);
        servicePrivate->setState(QLowEnergyService::DiscoveryRequired);
        return;
    }

    // We assume that the service does not have any characteristics with descriptors.
    servicePrivate->endHandle = servicePrivate->startHandle;

    const QVector<BTH_LE_GATT_CHARACTERISTIC> foundCharacteristics =
            enumerateGattCharacteristics(servicePrivate->hService, nullptr, &systemErrorCode);

    if (systemErrorCode != NO_ERROR) {
        qCWarning(QT_BT_WINDOWS) << "Unable to get characteristics for service" << service.toString()
                                 << ":" << qt_error_string(systemErrorCode);
        servicePrivate->setError(QLowEnergyService::CharacteristicReadError);
        servicePrivate->setState(QLowEnergyService::DiscoveryRequired);
        return;
    }

    for (const BTH_LE_GATT_CHARACTERISTIC &gattCharacteristic : foundCharacteristics) {
        const QLowEnergyHandle characteristicHandle = gattCharacteristic.AttributeHandle;

        QLowEnergyServicePrivate::CharData detailsData;

        detailsData.hValueChangeEvent = nullptr;

        detailsData.uuid = qtBluetoothUuidFromNativeLeUuid(
                    gattCharacteristic.CharacteristicUuid);
        detailsData.valueHandle = gattCharacteristic.CharacteristicValueHandle;

        QLowEnergyCharacteristic::PropertyTypes properties = QLowEnergyCharacteristic::Unknown;
        if (gattCharacteristic.HasExtendedProperties)
            properties |= QLowEnergyCharacteristic::ExtendedProperty;
        if (gattCharacteristic.IsBroadcastable)
            properties |= QLowEnergyCharacteristic::Broadcasting;
        if (gattCharacteristic.IsIndicatable)
            properties |= QLowEnergyCharacteristic::Indicate;
        if (gattCharacteristic.IsNotifiable)
            properties |= QLowEnergyCharacteristic::Notify;
        if (gattCharacteristic.IsReadable)
            properties |= QLowEnergyCharacteristic::Read;
        if (gattCharacteristic.IsSignedWritable)
            properties |= QLowEnergyCharacteristic::WriteSigned;
        if (gattCharacteristic.IsWritable)
            properties |= QLowEnergyCharacteristic::Write;
        if (gattCharacteristic.IsWritableWithoutResponse)
            properties |= QLowEnergyCharacteristic::WriteNoResponse;

        detailsData.properties = properties;
        detailsData.value = getGattCharacteristicValue(
                    servicePrivate->hService, const_cast<PBTH_LE_GATT_CHARACTERISTIC>(
                        &gattCharacteristic), &systemErrorCode);

        if (systemErrorCode != NO_ERROR) {
            // We do not interrupt enumerating of characteristics
            // if value can not be read
            qCWarning(QT_BT_WINDOWS) << "Unable to get value for characteristic"
                                     << detailsData.uuid.toString()
                                     << "of the service" << service.toString()
                                     << ":" << qt_error_string(systemErrorCode);
        }

        // We assume that the characteristic has no any descriptors. So, the
        // biggest characteristic + 1 will indicate an end handle of service.
        servicePrivate->endHandle = std::max(
                    servicePrivate->endHandle,
                    QLowEnergyHandle(gattCharacteristic.AttributeHandle + 1));

        const QVector<BTH_LE_GATT_DESCRIPTOR> foundDescriptors = enumerateGattDescriptors(
                    servicePrivate->hService, const_cast<PBTH_LE_GATT_CHARACTERISTIC>(
                        &gattCharacteristic), &systemErrorCode);

        if (systemErrorCode != NO_ERROR) {
            if (systemErrorCode != ERROR_NOT_FOUND) {
                qCWarning(QT_BT_WINDOWS) << "Unable to get descriptor for characteristic"
                                         << detailsData.uuid.toString()
                                         << "of the service" << service.toString()
                                         << ":" << qt_error_string(systemErrorCode);
                servicePrivate->setError(QLowEnergyService::DescriptorReadError);
                servicePrivate->setState(QLowEnergyService::DiscoveryRequired);
                return;
            }
        }

        for (const BTH_LE_GATT_DESCRIPTOR &gattDescriptor : foundDescriptors) {
            const QLowEnergyHandle descriptorHandle = gattDescriptor.AttributeHandle;

            QLowEnergyServicePrivate::DescData data;
            data.uuid = qtBluetoothUuidFromNativeLeUuid(
                        gattDescriptor.DescriptorUuid);

            data.value = getGattDescriptorValue(servicePrivate->hService, const_cast<PBTH_LE_GATT_DESCRIPTOR>(
                                                    &gattDescriptor), &systemErrorCode);

            if (systemErrorCode != NO_ERROR) {
                qCWarning(QT_BT_WINDOWS) << "Unable to get value for descriptor"
                                         << data.uuid.toString()
                                         << "for characteristic"
                                         << detailsData.uuid.toString()
                                         << "of the service" << service.toString()
                                         << ":" << qt_error_string(systemErrorCode);
                servicePrivate->setError(QLowEnergyService::DescriptorReadError);
                servicePrivate->setState(QLowEnergyService::DiscoveryRequired);
                return;
            }

            // Biggest descriptor will contain an end handle of service.
            servicePrivate->endHandle = std::max(
                        servicePrivate->endHandle,
                        QLowEnergyHandle(gattDescriptor.AttributeHandle));

            detailsData.descriptorList.insert(descriptorHandle, data);
        }

        servicePrivate->characteristicList.insert(characteristicHandle, detailsData);
    }

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

void QLowEnergyControllerPrivateWin32::startAdvertising(const QLowEnergyAdvertisingParameters &, const QLowEnergyAdvertisingData &, const QLowEnergyAdvertisingData &)
{
    Q_UNIMPLEMENTED();
}

void QLowEnergyControllerPrivateWin32::stopAdvertising()
{
    Q_UNIMPLEMENTED();
}

void QLowEnergyControllerPrivateWin32::requestConnectionUpdate(const QLowEnergyConnectionParameters &)
{
    Q_UNIMPLEMENTED();
}

void QLowEnergyControllerPrivateWin32::readCharacteristic(
        const QSharedPointer<QLowEnergyServicePrivate> service,
        const QLowEnergyHandle charHandle)
{
    Q_ASSERT(!service.isNull());
    if (!service->characteristicList.contains(charHandle))
        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_WINDOWS) << "Reading non-readable char" << charHandle;
    }

    ReadCharData data;
    data.systemErrorCode = NO_ERROR;
    data.hService = service->hService;

    if (data.systemErrorCode != NO_ERROR) {
        qCWarning(QT_BT_WINDOWS) << "Unable to open service" << service->uuid.toString()
                                 << ":" << qt_error_string(data.systemErrorCode);
        service->setError(QLowEnergyService::CharacteristicReadError);
        return;
    }

    data.gattCharacteristic = recoverNativeLeGattCharacteristic(
                service->startHandle, charHandle, charDetails);

    ThreadWorkerJob job;
    job.operation = ThreadWorkerJob::ReadChar;
    job.data = QVariant::fromValue(data);

    QMetaObject::invokeMethod(threadWorker, "putJob", Qt::QueuedConnection,
                              Q_ARG(ThreadWorkerJob, job));
}

void QLowEnergyControllerPrivateWin32::writeCharacteristic(
        const QSharedPointer<QLowEnergyServicePrivate> service,
        const QLowEnergyHandle charHandle,
        const QByteArray &newValue,
        QLowEnergyService::WriteMode mode)
{
    Q_ASSERT(!service.isNull());

    if (!service->characteristicList.contains(charHandle)) {
        service->setError(QLowEnergyService::CharacteristicWriteError);
        return;
    }

    WriteCharData data;
    data.systemErrorCode = NO_ERROR;
    data.hService = service->hService;

    if (data.systemErrorCode != NO_ERROR) {
        qCWarning(QT_BT_WINDOWS) << "Unable to open service" << service->uuid.toString()
                                 << ":" << qt_error_string(data.systemErrorCode);
        service->setError(QLowEnergyService::CharacteristicWriteError);
        return;
    }

    const QLowEnergyServicePrivate::CharData &charDetails
            = service->characteristicList[charHandle];

    data.gattCharacteristic = recoverNativeLeGattCharacteristic(
                service->startHandle, charHandle, charDetails);

    data.flags = (mode == QLowEnergyService::WriteWithResponse)
            ? BLUETOOTH_GATT_FLAG_NONE
            : BLUETOOTH_GATT_FLAG_WRITE_WITHOUT_RESPONSE;

    ThreadWorkerJob job;
    job.operation = ThreadWorkerJob::WriteChar;
    data.newValue = newValue;
    data.mode = mode;
    job.data = QVariant::fromValue(data);

    QMetaObject::invokeMethod(threadWorker, "putJob", Qt::QueuedConnection,
                              Q_ARG(ThreadWorkerJob, job));
}

void QLowEnergyControllerPrivateWin32::jobFinished(const ThreadWorkerJob &job)
{
    switch (job.operation) {
    case ThreadWorkerJob::WriteChar:
    {
        const WriteCharData data = job.data.value<WriteCharData>();
        const QLowEnergyHandle charHandle = static_cast<QLowEnergyHandle>(data.gattCharacteristic.AttributeHandle);
        const QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(charHandle);

        if (data.systemErrorCode != NO_ERROR) {
            const QLowEnergyServicePrivate::CharData &charDetails = service->characteristicList[charHandle];
            qCWarning(QT_BT_WINDOWS) << "Unable to set value for characteristic"
                                     << charDetails.uuid.toString()
                                     << "of the service" << service->uuid.toString()
                                     << ":" << qt_error_string(data.systemErrorCode);
            service->setError(QLowEnergyService::CharacteristicWriteError);
            return;
        }

        updateValueOfCharacteristic(charHandle, data.newValue, false);

        if (data.mode == QLowEnergyService::WriteWithResponse) {
            const QLowEnergyCharacteristic ch = characteristicForHandle(charHandle);
            emit service->characteristicWritten(ch, data.newValue);
        }
    }
        break;
    case ThreadWorkerJob::ReadChar:
    {
        const ReadCharData data = job.data.value<ReadCharData>();
        const QLowEnergyHandle charHandle = static_cast<QLowEnergyHandle>(data.gattCharacteristic.AttributeHandle);
        const QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(charHandle);

        if (data.systemErrorCode != NO_ERROR) {
            const QLowEnergyServicePrivate::CharData &charDetails = service->characteristicList[charHandle];
            qCWarning(QT_BT_WINDOWS) << "Unable to get value for characteristic"
                                     << charDetails.uuid.toString()
                                     << "of the service" << service->uuid.toString()
                                     << ":" << qt_error_string(data.systemErrorCode);
            service->setError(QLowEnergyService::CharacteristicReadError);
            return;
        }

        updateValueOfCharacteristic(charHandle, data.value, false);

        const QLowEnergyCharacteristic ch(service, charHandle);
        emit service->characteristicRead(ch, data.value);
    }
        break;
    case ThreadWorkerJob::WriteDescr:
    {
        WriteDescData data = job.data.value<WriteDescData>();
        const QLowEnergyHandle descriptorHandle = static_cast<QLowEnergyHandle>(data.gattDescriptor.AttributeHandle);
        const QLowEnergyHandle charHandle = static_cast<QLowEnergyHandle>(data.gattDescriptor.CharacteristicHandle);
        const QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(charHandle);
        QLowEnergyServicePrivate::CharData &charDetails = service->characteristicList[charHandle];
        const QLowEnergyServicePrivate::DescData &dscrDetails = charDetails.descriptorList[descriptorHandle];

        if (data.systemErrorCode != NO_ERROR) {
            qCWarning(QT_BT_WINDOWS) << "Unable to set value for descriptor"
                                     << dscrDetails.uuid.toString()
                                     << "for characteristic"
                                     << charDetails.uuid.toString()
                                     << "of the service" << service->uuid.toString()
                                     << ":" << qt_error_string(data.systemErrorCode);
            service->setError(QLowEnergyService::DescriptorWriteError);
            return;
        }

        if (data.gattDescriptor.DescriptorType == ClientCharacteristicConfiguration) {

            QDataStream in(data.newValue);
            quint8 u;
            in >> u;

            if (u & ClientCharacteristicConfigurationValue::UseNotifications
                    || u & ClientCharacteristicConfigurationValue::UseIndications) {
                if (!charDetails.hValueChangeEvent) {
                    BTH_LE_GATT_CHARACTERISTIC gattCharacteristic = recoverNativeLeGattCharacteristic(
                                service->startHandle, charHandle, charDetails);

                    // note: if the service handle is closed the event registration is no longer valid.
                    charDetails.hValueChangeEvent = registerEvent(
                                data.hService, gattCharacteristic, this, &data.systemErrorCode);
                }
            } else {
                if (charDetails.hValueChangeEvent) {
                    unregisterEvent(charDetails.hValueChangeEvent, &data.systemErrorCode);
                    charDetails.hValueChangeEvent = nullptr;
                }
            }

            if (data.systemErrorCode != NO_ERROR) {
                qCWarning(QT_BT_WINDOWS) << "Unable to subscribe events for descriptor"
                                         << dscrDetails.uuid.toString()
                                         << "for characteristic"
                                         << charDetails.uuid.toString()
                                         << "of the service" << service->uuid.toString()
                                         << ":" << qt_error_string(data.systemErrorCode);
                service->setError(QLowEnergyService::DescriptorWriteError);
                return;
            }
        }

        updateValueOfDescriptor(charHandle, descriptorHandle, data.newValue, false);

        const QLowEnergyDescriptor dscr(service, charHandle, descriptorHandle);
        emit service->descriptorWritten(dscr, data.newValue);
    }
        break;
    case ThreadWorkerJob::ReadDescr:
    {
        ReadDescData data = job.data.value<ReadDescData>();
        const QLowEnergyHandle descriptorHandle = static_cast<QLowEnergyHandle>(data.gattDescriptor.AttributeHandle);
        const QLowEnergyHandle charHandle = static_cast<QLowEnergyHandle>(data.gattDescriptor.CharacteristicHandle);
        const QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(charHandle);
        QLowEnergyServicePrivate::CharData &charDetails = service->characteristicList[charHandle];
        const QLowEnergyServicePrivate::DescData &dscrDetails = charDetails.descriptorList[descriptorHandle];

        if (data.systemErrorCode != NO_ERROR) {
            qCWarning(QT_BT_WINDOWS) << "Unable to get value for descriptor"
                                     << dscrDetails.uuid.toString()
                                     << "for characteristic"
                                     << charDetails.uuid.toString()
                                     << "of the service" << service->uuid.toString()
                                     << ":" << qt_error_string(data.systemErrorCode);
            service->setError(QLowEnergyService::DescriptorReadError);
            return;
        }

        updateValueOfDescriptor(charHandle, descriptorHandle, data.value, false);

        QLowEnergyDescriptor dscr(service, charHandle, descriptorHandle);
        emit service->descriptorRead(dscr, data.value);
    }
        break;
    }

    QMetaObject::invokeMethod(threadWorker, "runPendingJob", Qt::QueuedConnection);
}

void QLowEnergyControllerPrivateWin32::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;

    ReadDescData data;
    data.systemErrorCode = NO_ERROR;
    data.hService = service->hService;

    if (data.systemErrorCode != NO_ERROR) {
        qCWarning(QT_BT_WINDOWS) << "Unable to open service" << service->uuid.toString()
                                 << ":" << qt_error_string(data.systemErrorCode);
        service->setError(QLowEnergyService::DescriptorReadError);
        return;
    }

    const QLowEnergyServicePrivate::DescData &dscrDetails
            = charDetails.descriptorList[descriptorHandle];

    data.gattDescriptor = recoverNativeLeGattDescriptor(
                service->startHandle, charHandle, descriptorHandle, dscrDetails);

    ThreadWorkerJob job;
    job.operation = ThreadWorkerJob::ReadDescr;
    job.data = QVariant::fromValue(data);

    QMetaObject::invokeMethod(threadWorker, "putJob", Qt::QueuedConnection,
                              Q_ARG(ThreadWorkerJob, job));
}

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

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

    WriteDescData data;
    data.systemErrorCode = NO_ERROR;
    data.newValue = newValue;
    data.hService = service->hService;

    if (data.systemErrorCode != NO_ERROR) {
        qCWarning(QT_BT_WINDOWS) << "Unable to open service" << service->uuid.toString()
                                 << ":" << qt_error_string(data.systemErrorCode);
        service->setError(QLowEnergyService::DescriptorWriteError);
        return;
    }

    const QLowEnergyServicePrivate::DescData &dscrDetails
            = charDetails.descriptorList[descriptorHandle];

    data.gattDescriptor = recoverNativeLeGattDescriptor(
                service->startHandle, charHandle, descriptorHandle, dscrDetails);

    ThreadWorkerJob job;
    job.operation = ThreadWorkerJob::WriteDescr;
    job.data = QVariant::fromValue(data);

    QMetaObject::invokeMethod(threadWorker, "putJob", Qt::QueuedConnection,
                              Q_ARG(ThreadWorkerJob, job));
}

void QLowEnergyControllerPrivateWin32::addToGenericAttributeList(const QLowEnergyServiceData &, QLowEnergyHandle)
{
    Q_UNIMPLEMENTED();
}

void ThreadWorker::putJob(const ThreadWorkerJob &job)
{
    m_jobs.append(job);
    if (m_jobs.count() == 1)
        runPendingJob();
}

void ThreadWorker::runPendingJob()
{
    if (!m_jobs.count())
        return;

    ThreadWorkerJob job = m_jobs.first();

    switch (job.operation) {
    case ThreadWorkerJob::WriteChar:
    {
        WriteCharData data = job.data.value<WriteCharData>();
        setGattCharacteristicValue(data.hService, &data.gattCharacteristic,
                                   data.newValue, data.flags, &data.systemErrorCode);
        job.data = QVariant::fromValue(data);
    }
        break;
    case ThreadWorkerJob::ReadChar:
    {
        ReadCharData data = job.data.value<ReadCharData>();
        data.value = getGattCharacteristicValue(
                    data.hService, &data.gattCharacteristic, &data.systemErrorCode);
        job.data = QVariant::fromValue(data);
    }
        break;
    case ThreadWorkerJob::WriteDescr:
    {
        WriteDescData data = job.data.value<WriteDescData>();
        setGattDescriptorValue(data.hService, &data.gattDescriptor,
                               data.newValue, &data.systemErrorCode);
        job.data = QVariant::fromValue(data);
    }
        break;
    case ThreadWorkerJob::ReadDescr:
    {
        ReadDescData data = job.data.value<ReadDescData>();
        data.value = getGattDescriptorValue(
                    data.hService,
                    const_cast<PBTH_LE_GATT_DESCRIPTOR>(&data.gattDescriptor),
                    &data.systemErrorCode);
        job.data = QVariant::fromValue(data);
    }
        break;
    }

    m_jobs.removeFirst();
    emit jobFinished(job);
}

QT_END_NAMESPACE
