diff --git a/dist/changes-5.13.0 b/dist/changes-5.13.0
new file mode 100644
index 0000000000000000000000000000000000000000..921b45a92b14cdcf15a23bd6bf01766862c1da9e
--- /dev/null
+++ b/dist/changes-5.13.0
@@ -0,0 +1,59 @@
+Qt 5.13 introduces many new features and improvements as well as bugfixes
+over the 5.12.x series. For more details, refer to the online documentation
+included in this distribution. The documentation is also available online:
+
+https://doc.qt.io/qt-5/index.html
+
+The Qt version 5.13 series is binary compatible with the 5.12.x series.
+Applications compiled for 5.12 will continue to run with 5.13.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+*                         Qt 5.13.0 Changes                                *
+****************************************************************************
+
+QtBluetooth
+-----------
+
+ - [QTBUG-58660] Added ability to connect to BLE devices on WinRT without
+   pairing.
+
+ - [QTBUG-69954] Fixed potential crash due to late callbacks on WinRT.
+
+ - Improved WinRT implementation signficantly. This incorporates a large
+   number of patches (each improving the stability and general robustness of
+   the code base). During the process the number of potential asserts was
+   reduced as well.
+
+ - Deprecated QBluetoothDeviceInfo::DataCompleteness related APIs.
+
+ - Replaced QBluetoothDeviceInfo::LanAccessDevice with QBluetoothDeviceInfo::NetworkDevice.
+   LanAccessDevice was deprecated.
+
+ - Implemented support for QBluetoothDeviceDiscoveryAgent::deviceUpdated() on Apple and WinRT
+   platforms.
+
+ - [QTBUG-71943] Implemented RSSI and manufacturer data discovery on WinRT.
+
+ - [QTBUG-74394] Fixed broken QLowEnergyController::disconnectFromDevice() on WinRT.
+
+ - Added a compile fix for g++ 8.
+
+ - [QTBUG-73717] Fixed warnings in QDeclarativeBluetoothDiscoveryModel.
+
+QtNfc
+-----
+
+ - QNearFieldManager:
+   * adapterStateChanged() now has a fully qualified parameter
+     QNearFieldManager::AdapterState. This can cause a problem if the
+     connection/method invocation was done with just AdapterState as the
+     parameter type, in which case these need to be changed to use
+     QNearFieldManager::AdapaterState instead.
diff --git a/src/bluetooth/bluetooth.pro b/src/bluetooth/bluetooth.pro
index d2b711d9cebf02e79c5c2039cd90b62bae07fa60..974d8e8a1da3dd595f68a63e3b84f781ab13761e 100644
--- a/src/bluetooth/bluetooth.pro
+++ b/src/bluetooth/bluetooth.pro
@@ -211,7 +211,7 @@ qtConfig(bluez) {
 
     SOURCES += \
         qbluetoothdevicediscoveryagent_winrt.cpp \
-        qbluetoothlocaldevice_p.cpp \
+        qbluetoothlocaldevice_winrt.cpp \
         qbluetoothserver_winrt.cpp \
         qbluetoothservicediscoveryagent_winrt.cpp \
         qbluetoothserviceinfo_winrt.cpp \
diff --git a/src/bluetooth/qbluetoothlocaldevice_p.cpp b/src/bluetooth/qbluetoothlocaldevice_p.cpp
index 793a8311bc76a54791612492bea4ddd8c3c2062c..fa4a509eb5fa8fff1bef35b7803e74cb23bd6c90 100644
--- a/src/bluetooth/qbluetoothlocaldevice_p.cpp
+++ b/src/bluetooth/qbluetoothlocaldevice_p.cpp
@@ -51,7 +51,7 @@ QBluetoothLocalDevice::QBluetoothLocalDevice(QObject *parent) :
     QObject(parent),
     d_ptr(new QBluetoothLocalDevicePrivate(this, QBluetoothAddress()))
 {
-#if !defined(QT_IOS_BLUETOOTH) && !defined(QT_WINRT_BLUETOOTH)
+#if !defined(QT_IOS_BLUETOOTH)
     printDummyWarning();
 #endif
     registerQBluetoothLocalDeviceMetaType();
@@ -85,11 +85,7 @@ void QBluetoothLocalDevice::setHostMode(QBluetoothLocalDevice::HostMode mode)
 
 QBluetoothLocalDevice::HostMode QBluetoothLocalDevice::hostMode() const
 {
-#ifdef QT_WINRT_BLUETOOTH
-    return HostConnectable;
-#else
     return HostPoweredOff;
-#endif
 }
 
 QList<QBluetoothAddress> QBluetoothLocalDevice::connectedDevices() const
@@ -116,11 +112,7 @@ QBluetoothLocalDevice::Pairing QBluetoothLocalDevice::pairingStatus(
     const QBluetoothAddress &address) const
 {
     Q_UNUSED(address);
-#ifdef QT_WINRT_BLUETOOTH
-    return Paired;
-#else
     return Unpaired;
-#endif
 }
 
 void QBluetoothLocalDevice::pairingConfirmation(bool confirmation)
diff --git a/src/bluetooth/qbluetoothlocaldevice_p.h b/src/bluetooth/qbluetoothlocaldevice_p.h
index 98c62151462634a01573bc97bfcfd057dd0e43e1..8f3e2b437e5489a59905b96ff37ed7612aadd889 100644
--- a/src/bluetooth/qbluetoothlocaldevice_p.h
+++ b/src/bluetooth/qbluetoothlocaldevice_p.h
@@ -84,6 +84,21 @@ QT_END_NAMESPACE
 #include <QtCore/QPair>
 #endif
 
+#ifdef QT_WINRT_BLUETOOTH
+#include <wrl.h>
+
+namespace ABI {
+    namespace Windows {
+        namespace Devices {
+            namespace Bluetooth {
+                struct IBluetoothDeviceStatics;
+                struct IBluetoothLEDeviceStatics;
+            }
+        }
+    }
+}
+#endif
+
 QT_BEGIN_NAMESPACE
 
 extern void registerQBluetoothLocalDeviceMetaType();
@@ -208,7 +223,22 @@ private:
     void initializeAdapter();
     void initializeAdapterBluez5();
 };
-#elif !defined(QT_OSX_BLUETOOTH) // winrt and dummy backend
+#elif defined(QT_WINRT_BLUETOOTH)
+class QBluetoothLocalDevicePrivate : public QObject
+{
+    Q_DECLARE_PUBLIC(QBluetoothLocalDevice)
+public:
+    QBluetoothLocalDevicePrivate(QBluetoothLocalDevice *q,
+                                 QBluetoothAddress = QBluetoothAddress());
+
+    bool isValid() const;
+
+private:
+    QBluetoothLocalDevice *q_ptr;
+    Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::IBluetoothDeviceStatics> mStatics;
+    Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::IBluetoothLEDeviceStatics> mLEStatics;
+};
+#elif !defined(QT_OSX_BLUETOOTH) // dummy backend
 class QBluetoothLocalDevicePrivate : public QObject
 {
 public:
@@ -219,11 +249,7 @@ public:
 
     bool isValid() const
     {
-#ifndef QT_WINRT_BLUETOOTH
         return false;
-#else
-        return true;
-#endif
     }
 };
 #endif
diff --git a/src/bluetooth/qbluetoothlocaldevice_winrt.cpp b/src/bluetooth/qbluetoothlocaldevice_winrt.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ae794db025217879a86d5bc9c7b88ea91c1cf629
--- /dev/null
+++ b/src/bluetooth/qbluetoothlocaldevice_winrt.cpp
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "qbluetoothlocaldevice.h"
+#include "qbluetoothaddress.h"
+
+#include "qbluetoothlocaldevice_p.h"
+
+#ifdef CLASSIC_APP_BUILD
+#define Q_OS_WINRT
+#endif
+#include <QtCore/qfunctions_winrt.h>
+
+#include <robuffer.h>
+#include <windows.devices.bluetooth.h>
+#include <wrl.h>
+
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Devices::Bluetooth;
+using namespace ABI::Windows::Devices::Enumeration;
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+
+QT_BEGIN_NAMESPACE
+
+template <class DeviceStatics, class OpResult, class Device, class Device2>
+ComPtr<IDeviceInformationPairing> getPairingInfo(ComPtr<DeviceStatics> deviceStatics,
+                                                  const QBluetoothAddress &address)
+{
+    ComPtr<IAsyncOperation<OpResult *>> op;
+    if (!deviceStatics)
+        return nullptr;
+    HRESULT hr = deviceStatics->FromBluetoothAddressAsync(address.toUInt64(), &op);
+    RETURN_IF_FAILED("Could not obtain device from address", return nullptr);
+    ComPtr<Device> device;
+    hr = QWinRTFunctions::await(op, device.GetAddressOf(),
+                                QWinRTFunctions::ProcessMainThreadEvents, 5000);
+    if (FAILED(hr) || !device) {
+        qErrnoWarning("Could not obtain device from address");
+        return nullptr;
+    }
+    ComPtr<Device2> device2;
+    hr = device.As(&device2);
+    RETURN_IF_FAILED("Could not cast device", return nullptr);
+    ComPtr<IDeviceInformation> deviceInfo;
+    hr = device2->get_DeviceInformation(&deviceInfo);
+    if (FAILED(hr) || !deviceInfo) {
+        qErrnoWarning("Could not obtain device information");
+        return nullptr;
+    }
+    ComPtr<IDeviceInformation2> deviceInfo2;
+    hr = deviceInfo.As(&deviceInfo2);
+    RETURN_IF_FAILED("Could not cast device information", return nullptr);
+    ComPtr<IDeviceInformationPairing> pairingInfo;
+    hr = deviceInfo2->get_Pairing(&pairingInfo);
+    RETURN_IF_FAILED("Could not obtain pairing information", return nullptr);
+    return pairingInfo;
+}
+
+QBluetoothLocalDevice::QBluetoothLocalDevice(QObject *parent) :
+    QObject(parent),
+    d_ptr(new QBluetoothLocalDevicePrivate(this, QBluetoothAddress()))
+{
+    registerQBluetoothLocalDeviceMetaType();
+}
+
+QBluetoothLocalDevice::QBluetoothLocalDevice(const QBluetoothAddress &address, QObject *parent) :
+    QObject(parent),
+    d_ptr(new QBluetoothLocalDevicePrivate(this, address))
+{
+    registerQBluetoothLocalDeviceMetaType();
+}
+
+QBluetoothLocalDevicePrivate::QBluetoothLocalDevicePrivate(QBluetoothLocalDevice *q, QBluetoothAddress)
+    : q_ptr(q)
+{
+    GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Devices_Bluetooth_BluetoothLEDevice).Get(), &mLEStatics);
+    GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Devices_Bluetooth_BluetoothDevice).Get(), &mStatics);
+}
+
+bool QBluetoothLocalDevicePrivate::isValid() const
+{
+    return (mStatics != nullptr && mLEStatics != nullptr);
+}
+
+void QBluetoothLocalDevice::requestPairing(const QBluetoothAddress &address, Pairing pairing)
+{
+    Q_UNUSED(address);
+    Q_UNUSED(pairing);
+    QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
+                              Q_ARG(QBluetoothLocalDevice::Error,
+                                    QBluetoothLocalDevice::PairingError));
+}
+
+QBluetoothLocalDevice::Pairing QBluetoothLocalDevice::pairingStatus(
+    const QBluetoothAddress &address) const
+{
+    if (!isValid() || address.isNull())
+        return QBluetoothLocalDevice::Unpaired;
+
+    ComPtr<IDeviceInformationPairing> pairingInfo = getPairingInfo<IBluetoothLEDeviceStatics,
+            BluetoothLEDevice, IBluetoothLEDevice, IBluetoothLEDevice2>(d_ptr->mLEStatics, address);
+    if (!pairingInfo)
+        pairingInfo = getPairingInfo<IBluetoothDeviceStatics, BluetoothDevice,
+                IBluetoothDevice, IBluetoothDevice2>(d_ptr->mStatics, address);
+    if (!pairingInfo)
+        return QBluetoothLocalDevice::Unpaired;
+    boolean isPaired;
+    HRESULT hr = pairingInfo->get_IsPaired(&isPaired);
+    RETURN_IF_FAILED("Could not obtain device pairing", return QBluetoothLocalDevice::Unpaired);
+    if (!isPaired)
+        return QBluetoothLocalDevice::Unpaired;
+
+    ComPtr<IDeviceInformationPairing2> pairingInfo2;
+    hr = pairingInfo.As(&pairingInfo2);
+    RETURN_IF_FAILED("Could not cast pairing info", return QBluetoothLocalDevice::Paired);
+    DevicePairingProtectionLevel protection = DevicePairingProtectionLevel_None;
+    hr = pairingInfo2->get_ProtectionLevel(&protection);
+    RETURN_IF_FAILED("Could not obtain pairing protection level", return QBluetoothLocalDevice::Paired);
+    if (protection == DevicePairingProtectionLevel_Encryption
+            || protection == DevicePairingProtectionLevel_EncryptionAndAuthentication)
+        return QBluetoothLocalDevice::AuthorizedPaired;
+    return QBluetoothLocalDevice::Paired;
+}
+
+void QBluetoothLocalDevice::pairingConfirmation(bool confirmation)
+{
+    Q_UNUSED(confirmation);
+}
+
+void QBluetoothLocalDevice::setHostMode(QBluetoothLocalDevice::HostMode mode)
+{
+    Q_UNUSED(mode);
+}
+
+QBluetoothLocalDevice::HostMode QBluetoothLocalDevice::hostMode() const
+{
+    return HostConnectable;
+}
+
+QList<QBluetoothAddress> QBluetoothLocalDevice::connectedDevices() const
+{
+    return QList<QBluetoothAddress>();
+}
+
+void QBluetoothLocalDevice::powerOn()
+{
+}
+
+QString QBluetoothLocalDevice::name() const
+{
+    return QString();
+}
+
+QBluetoothAddress QBluetoothLocalDevice::address() const
+{
+    return QBluetoothAddress();
+}
+
+QList<QBluetoothHostInfo> QBluetoothLocalDevice::allDevices()
+{
+    QList<QBluetoothHostInfo> localDevices;
+    return localDevices;
+}
+
+QT_END_NAMESPACE
diff --git a/src/bluetooth/qlowenergycontroller_winrt_new.cpp b/src/bluetooth/qlowenergycontroller_winrt_new.cpp
index 45a802521dc72688782521553f52a73b676a1e07..bb9894ff2b870678ddfead0d14855dddaafd6391 100644
--- a/src/bluetooth/qlowenergycontroller_winrt_new.cpp
+++ b/src/bluetooth/qlowenergycontroller_winrt_new.cpp
@@ -41,6 +41,7 @@
 #include "qlowenergycontroller_winrt_p.h"
 #include "qbluetoothutils_winrt_p.h"
 
+#include <QtBluetooth/qbluetoothlocaldevice.h>
 #include <QtBluetooth/QLowEnergyCharacteristicData>
 #include <QtBluetooth/QLowEnergyDescriptorData>
 #include <QtBluetooth/private/qbluetoothutils_winrt_p.h>
@@ -57,6 +58,7 @@
 #include <robuffer.h>
 #include <windows.devices.enumeration.h>
 #include <windows.devices.bluetooth.h>
+#include <windows.devices.bluetooth.genericattributeprofile.h>
 #include <windows.foundation.collections.h>
 #include <windows.foundation.metadata.h>
 #include <windows.storage.streams.h>
@@ -91,15 +93,18 @@ typedef IGattReadClientCharacteristicConfigurationDescriptorResult IClientCharCo
         continue; \
     }
 
-#define CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, msg, ret) \
+#define CHECK_FOR_DEVICE_CONNECTION_ERROR_IMPL(this, hr, msg, ret) \
     if (FAILED(hr)) { \
         qCWarning(QT_BT_WINRT) << msg; \
-        unregisterFromStatusChanges(); \
-        setError(QLowEnergyController::ConnectionError); \
-        setState(QLowEnergyController::UnconnectedState); \
+        this->unregisterFromStatusChanges(); \
+        this->setError(QLowEnergyController::ConnectionError); \
+        this->setState(QLowEnergyController::UnconnectedState); \
         ret; \
     }
 
+#define CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, msg, ret) \
+    CHECK_FOR_DEVICE_CONNECTION_ERROR_IMPL(this, hr, msg, ret)
+
 #define CHECK_HR_AND_SET_SERVICE_ERROR(hr, msg, service, error, ret) \
     if (FAILED(hr)) { \
         qCDebug(QT_BT_WINRT) << msg; \
@@ -436,6 +441,7 @@ QLowEnergyControllerPrivateWinRTNew::~QLowEnergyControllerPrivateWinRTNew()
 {
     unregisterFromStatusChanges();
     unregisterFromValueChanges();
+    mAbortPending = true;
 }
 
 void QLowEnergyControllerPrivateWinRTNew::init()
@@ -445,6 +451,7 @@ void QLowEnergyControllerPrivateWinRTNew::init()
 void QLowEnergyControllerPrivateWinRTNew::connectToDevice()
 {
     qCDebug(QT_BT_WINRT) << __FUNCTION__;
+    mAbortPending = false;
     Q_Q(QLowEnergyController);
     if (remoteDevice.isNull()) {
         qWarning() << "Invalid/null remote device address";
@@ -473,138 +480,18 @@ void QLowEnergyControllerPrivateWinRTNew::connectToDevice()
     BluetoothConnectionStatus status;
     hr = mDevice->get_ConnectionStatus(&status);
     CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain device's connection status", return)
-    hr = QEventDispatcherWinRT::runOnXamlThread([this, q]() {
-        HRESULT hr;
-        hr = mDevice->add_ConnectionStatusChanged(
-            Callback<StatusHandler>([this, q](IBluetoothLEDevice *dev, IInspectable *) {
-                BluetoothConnectionStatus status;
-                HRESULT hr;
-                hr = dev->get_ConnectionStatus(&status);
-                CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain connection status", return S_OK)
-                if (state == QLowEnergyController::ConnectingState
-                        && status == BluetoothConnectionStatus::BluetoothConnectionStatus_Connected) {
-                    setState(QLowEnergyController::ConnectedState);
-                    emit q->connected();
-                } else if (state != QLowEnergyController::UnconnectedState
-                           && status == BluetoothConnectionStatus::BluetoothConnectionStatus_Disconnected) {
-                    invalidateServices();
-                    unregisterFromValueChanges();
-                    unregisterFromStatusChanges();
-                    mDevice = nullptr;
-                    setError(QLowEnergyController::RemoteHostClosedError);
-                    setState(QLowEnergyController::UnconnectedState);
-                    emit q->disconnected();
-                }
-                return S_OK;
-            }).Get(), &mStatusChangedToken);
-        CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not register connection status callback", return S_OK)
-        return S_OK;
-    });
-    CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not add status callback on Xaml thread", return)
-
     if (status == BluetoothConnectionStatus::BluetoothConnectionStatus_Connected) {
         setState(QLowEnergyController::ConnectedState);
         emit q->connected();
         return;
     }
 
-    ComPtr<IBluetoothLEDevice3> device3;
-    hr = mDevice.As(&device3);
-    CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not cast device", return)
-    ComPtr<IAsyncOperation<GattDeviceServicesResult *>> deviceServicesOp;
-    hr = device3->GetGattServicesAsync(&deviceServicesOp);
-    CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain services", return)
-    ComPtr<IGattDeviceServicesResult> deviceServicesResult;
-    hr = QWinRTFunctions::await(deviceServicesOp, deviceServicesResult.GetAddressOf(),
-                                QWinRTFunctions::ProcessMainThreadEvents, 5000);
-    CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not await services operation", return)
-
-    GattCommunicationStatus commStatus;
-    hr = deviceServicesResult->get_Status(&commStatus);
-    if (FAILED(hr) || commStatus != GattCommunicationStatus_Success) {
-        qCWarning(QT_BT_WINRT()) << "Service operation failed";
-        setError(QLowEnergyController::ConnectionError);
-        setState(QLowEnergyController::UnconnectedState);
-        unregisterFromStatusChanges();
-        return;
-    }
-
-    ComPtr<IVectorView <GattDeviceService *>> deviceServices;
-    hr = deviceServicesResult->get_Services(&deviceServices);
-    CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain list of services", return)
-    uint serviceCount;
-    hr = deviceServices->get_Size(&serviceCount);
-    CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain service count", return)
-
-    // Windows automatically connects to the device as soon as a service value is read/written.
-    // Thus we read one value in order to establish the connection.
-    for (uint i = 0; i < serviceCount; ++i) {
-        ComPtr<IGattDeviceService> service;
-        hr = deviceServices->GetAt(i, &service);
-        WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain service");
-        ComPtr<IGattDeviceService3> service3;
-        hr = service.As(&service3);
-        WARN_AND_CONTINUE_IF_FAILED(hr, "Could not cast service");
-        ComPtr<IAsyncOperation<GattCharacteristicsResult *>> characteristicsOp;
-        hr = service3->GetCharacteristicsAsync(&characteristicsOp);
-        WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain characteristic");
-        ComPtr<IGattCharacteristicsResult> characteristicsResult;
-        hr = QWinRTFunctions::await(characteristicsOp, characteristicsResult.GetAddressOf(),
-                                    QWinRTFunctions::ProcessMainThreadEvents, 5000);
-        WARN_AND_CONTINUE_IF_FAILED(hr, "Could not await characteristic operation");
-        GattCommunicationStatus commStatus;
-        hr = characteristicsResult->get_Status(&commStatus);
-        if (FAILED(hr) || commStatus != GattCommunicationStatus_Success) {
-            qCWarning(QT_BT_WINRT) << "Characteristic operation failed";
-            continue;
-        }
-        ComPtr<IVectorView<GattCharacteristic *>> characteristics;
-        hr = characteristicsResult->get_Characteristics(&characteristics);
-        if (hr == E_ACCESSDENIED) {
-            // Everything will work as expected up until this point if the manifest capabilties
-            // for bluetooth LE are not set.
-            qCWarning(QT_BT_WINRT) << "Could not obtain characteristic list. Please check your "
-                                      "manifest capabilities";
-            setState(QLowEnergyController::UnconnectedState);
-            setError(QLowEnergyController::ConnectionError);
-            unregisterFromStatusChanges();
-            return;
-        }
-        WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain characteristic list");
-        uint characteristicsCount;
-        hr = characteristics->get_Size(&characteristicsCount);
-        WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain characteristic list's size");
-        for (uint j = 0; j < characteristicsCount; ++j) {
-            ComPtr<IGattCharacteristic> characteristic;
-            hr = characteristics->GetAt(j, &characteristic);
-            WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain characteristic");
-            ComPtr<IAsyncOperation<GattReadResult *>> op;
-            GattCharacteristicProperties props;
-            hr = characteristic->get_CharacteristicProperties(&props);
-            WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain characteristic's properties");
-            if (!(props & GattCharacteristicProperties_Read))
-                continue;
-            hr = characteristic->ReadValueWithCacheModeAsync(BluetoothCacheMode::BluetoothCacheMode_Uncached, &op);
-            WARN_AND_CONTINUE_IF_FAILED(hr, "Could not read characteristic value");
-            ComPtr<IGattReadResult> result;
-            hr = QWinRTFunctions::await(op, result.GetAddressOf());
-            WARN_AND_CONTINUE_IF_FAILED(hr, "Could await characteristic read");
-            ComPtr<ABI::Windows::Storage::Streams::IBuffer> buffer;
-            hr = result->get_Value(&buffer);
-            WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain characteristic value");
-            if (!buffer) {
-                qCDebug(QT_BT_WINRT) << "Problem reading value";
-                continue;
-            }
-            return;
-        }
-    }
-
-    qCWarning(QT_BT_WINRT) << "Could not obtain characteristic read result that triggers"
-                            "device connection. Is the device reachable?";
-    unregisterFromStatusChanges();
-    setError(QLowEnergyController::ConnectionError);
-    setState(QLowEnergyController::UnconnectedState);
+    QBluetoothLocalDevice localDevice;
+    QBluetoothLocalDevice::Pairing pairing = localDevice.pairingStatus(remoteDevice);
+    if (pairing == QBluetoothLocalDevice::Unpaired)
+        connectToUnpairedDevice();
+    else
+        connectToPairedDevice();
 }
 
 void QLowEnergyControllerPrivateWinRTNew::disconnectFromDevice()
@@ -614,6 +501,7 @@ void QLowEnergyControllerPrivateWinRTNew::disconnectFromDevice()
     setState(QLowEnergyController::ClosingState);
     unregisterFromValueChanges();
     unregisterFromStatusChanges();
+    mAbortPending = true;
     mDevice = nullptr;
     setState(QLowEnergyController::UnconnectedState);
     emit q->disconnected();
@@ -691,18 +579,8 @@ void QLowEnergyControllerPrivateWinRTNew::registerForValueChanges(const QBluetoo
     EventRegistrationToken token;
     HRESULT hr;
     hr = characteristic->add_ValueChanged(
-                Callback<ValueChangedHandler>(
-                    [this](IGattCharacteristic *characteristic, IGattValueChangedEventArgs *args) {
-                    HRESULT hr;
-                    quint16 handle;
-                    hr = characteristic->get_AttributeHandle(&handle);
-                    RETURN_IF_FAILED("Could not obtain characteristic's handle", return S_OK)
-                    ComPtr<IBuffer> buffer;
-                    hr = args->get_CharacteristicValue(&buffer);
-                    RETURN_IF_FAILED("Could not obtain characteristic's value", return S_OK)
-                    characteristicChanged(handle, byteArrayFromBuffer(buffer));
-                    return S_OK;
-                }).Get(), &token);
+                Callback<ValueChangedHandler>(this, &QLowEnergyControllerPrivateWinRTNew::onValueChange).Get(),
+                &token);
     RETURN_IF_FAILED("Could not register characteristic for value changes", return)
     mValueChangedTokens.append(ValueChangedEntry(characteristic, token));
     qCDebug(QT_BT_WINRT) << "Characteristic" << charUuid << "in service"
@@ -726,6 +604,39 @@ void QLowEnergyControllerPrivateWinRTNew::unregisterFromValueChanges()
     mValueChangedTokens.clear();
 }
 
+HRESULT QLowEnergyControllerPrivateWinRTNew::onValueChange(IGattCharacteristic *characteristic, IGattValueChangedEventArgs *args)
+{
+    HRESULT hr;
+    quint16 handle;
+    hr = characteristic->get_AttributeHandle(&handle);
+    RETURN_IF_FAILED("Could not obtain characteristic's handle", return S_OK)
+    ComPtr<IBuffer> buffer;
+    hr = args->get_CharacteristicValue(&buffer);
+    RETURN_IF_FAILED("Could not obtain characteristic's value", return S_OK)
+    characteristicChanged(handle, byteArrayFromBuffer(buffer));
+    return S_OK;
+}
+
+bool QLowEnergyControllerPrivateWinRTNew::registerForStatusChanges()
+{
+    if (!mDevice)
+        return false;
+
+    qCDebug(QT_BT_WINRT) << __FUNCTION__;
+
+    HRESULT hr;
+    hr = QEventDispatcherWinRT::runOnXamlThread([this]() {
+        HRESULT hr;
+        hr = mDevice->add_ConnectionStatusChanged(
+            Callback<StatusHandler>(this, &QLowEnergyControllerPrivateWinRTNew::onStatusChange).Get(),
+                                    &mStatusChangedToken);
+        RETURN_IF_FAILED("Could not register connection status callback", return hr)
+        return S_OK;
+    });
+    RETURN_FALSE_IF_FAILED("Could not add status callback on Xaml thread")
+    return true;
+}
+
 void QLowEnergyControllerPrivateWinRTNew::unregisterFromStatusChanges()
 {
     qCDebug(QT_BT_WINRT) << __FUNCTION__;
@@ -735,6 +646,30 @@ void QLowEnergyControllerPrivateWinRTNew::unregisterFromStatusChanges()
     }
 }
 
+HRESULT QLowEnergyControllerPrivateWinRTNew::onStatusChange(IBluetoothLEDevice *dev, IInspectable *)
+{
+    Q_Q(QLowEnergyController);
+    BluetoothConnectionStatus status;
+    HRESULT hr;
+    hr = dev->get_ConnectionStatus(&status);
+    RETURN_IF_FAILED("Could not obtain connection status", return S_OK)
+    if (state == QLowEnergyController::ConnectingState
+        && status == BluetoothConnectionStatus::BluetoothConnectionStatus_Connected) {
+        setState(QLowEnergyController::ConnectedState);
+        emit q->connected();
+    } else if (state != QLowEnergyController::UnconnectedState
+        && status == BluetoothConnectionStatus::BluetoothConnectionStatus_Disconnected) {
+        invalidateServices();
+        unregisterFromValueChanges();
+        unregisterFromStatusChanges();
+        mDevice = nullptr;
+        setError(QLowEnergyController::RemoteHostClosedError);
+        setState(QLowEnergyController::UnconnectedState);
+        emit q->disconnected();
+    }
+    return S_OK;
+}
+
 void QLowEnergyControllerPrivateWinRTNew::obtainIncludedServices(
         QSharedPointer<QLowEnergyServicePrivate> servicePointer,
         ComPtr<IGattDeviceService> service)
@@ -791,10 +726,68 @@ void QLowEnergyControllerPrivateWinRTNew::obtainIncludedServices(
     }
 }
 
-void QLowEnergyControllerPrivateWinRTNew::discoverServices()
+HRESULT QLowEnergyControllerPrivateWinRTNew::onServiceDiscoveryFinished(ABI::Windows::Foundation::IAsyncOperation<GattDeviceServicesResult *> *op, AsyncStatus status)
 {
     Q_Q(QLowEnergyController);
+    if (status != AsyncStatus::Completed) {
+        qCDebug(QT_BT_WINRT) << "Could not obtain services";
+        return S_OK;
+    }
+    ComPtr<IGattDeviceServicesResult> result;
+    ComPtr<IVectorView<GattDeviceService *>> deviceServices;
+    HRESULT hr = op->GetResults(&result);
+    CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain service discovery result",
+                                      return S_OK);
+    GattCommunicationStatus commStatus;
+    hr = result->get_Status(&commStatus);
+    CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain service discovery status",
+                                      return S_OK);
+    if (commStatus != GattCommunicationStatus_Success)
+        return S_OK;
 
+    hr = result->get_Services(&deviceServices);
+    CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain service list",
+                                      return S_OK);
+
+    uint serviceCount;
+    hr = deviceServices->get_Size(&serviceCount);
+    CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain service list size",
+                                      return S_OK);
+    for (uint i = 0; i < serviceCount; ++i) {
+        ComPtr<IGattDeviceService> deviceService;
+        hr = deviceServices->GetAt(i, &deviceService);
+        WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain service");
+        GUID guuid;
+        hr = deviceService->get_Uuid(&guuid);
+        WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain service's Uuid");
+        const QBluetoothUuid service(guuid);
+
+        QSharedPointer<QLowEnergyServicePrivate> pointer;
+        if (serviceList.contains(service)) {
+            pointer = serviceList.value(service);
+        } else {
+            QLowEnergyServicePrivate *priv = new QLowEnergyServicePrivate();
+            priv->uuid = service;
+            priv->setController(this);
+
+            pointer = QSharedPointer<QLowEnergyServicePrivate>(priv);
+            serviceList.insert(service, pointer);
+        }
+        pointer->type |= QLowEnergyService::PrimaryService;
+
+        obtainIncludedServices(pointer, deviceService);
+
+        emit q->serviceDiscovered(service);
+    }
+
+    setState(QLowEnergyController::DiscoveredState);
+    emit q->discoveryFinished();
+
+    return S_OK;
+}
+
+void QLowEnergyControllerPrivateWinRTNew::discoverServices()
+{
     qCDebug(QT_BT_WINRT) << "Service discovery initiated";
 
     ComPtr<IBluetoothLEDevice3> device3;
@@ -803,67 +796,10 @@ void QLowEnergyControllerPrivateWinRTNew::discoverServices()
     ComPtr<IAsyncOperation<GenericAttributeProfile::GattDeviceServicesResult *>> asyncResult;
     hr = device3->GetGattServicesAsync(&asyncResult);
     CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain services", return);
-    hr = QEventDispatcherWinRT::runOnXamlThread( [asyncResult, q, this] () {
+    hr = QEventDispatcherWinRT::runOnXamlThread( [asyncResult, this] () {
         HRESULT hr = asyncResult->put_Completed(
             Callback<IAsyncOperationCompletedHandler<GenericAttributeProfile::GattDeviceServicesResult *>>(
-                    [this, q](IAsyncOperation<GenericAttributeProfile::GattDeviceServicesResult *> *op,
-                        AsyncStatus status) {
-                if (status != AsyncStatus::Completed) {
-                    qCDebug(QT_BT_WINRT) << "Could not obtain services";
-                    return S_OK;
-                }
-                ComPtr<IGattDeviceServicesResult> result;
-                ComPtr<IVectorView<GattDeviceService *>> deviceServices;
-                HRESULT hr = op->GetResults(&result);
-                CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain service discovery result",
-                                                  return S_OK);
-                GattCommunicationStatus commStatus;
-                hr = result->get_Status(&commStatus);
-                CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain service discovery status",
-                                                  return S_OK);
-                if (commStatus != GattCommunicationStatus_Success)
-                    return S_OK;
-
-                hr = result->get_Services(&deviceServices);
-                CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain service list",
-                                                  return S_OK);
-
-                uint serviceCount;
-                hr = deviceServices->get_Size(&serviceCount);
-                CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain service list size",
-                                                  return S_OK);
-                for (uint i = 0; i < serviceCount; ++i) {
-                    ComPtr<IGattDeviceService> deviceService;
-                    hr = deviceServices->GetAt(i, &deviceService);
-                    WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain service");
-                    GUID guuid;
-                    hr = deviceService->get_Uuid(&guuid);
-                    WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain service's Uuid");
-                    const QBluetoothUuid service(guuid);
-
-                    QSharedPointer<QLowEnergyServicePrivate> pointer;
-                    if (serviceList.contains(service)) {
-                        pointer = serviceList.value(service);
-                    } else {
-                        QLowEnergyServicePrivate *priv = new QLowEnergyServicePrivate();
-                        priv->uuid = service;
-                        priv->setController(this);
-
-                        pointer = QSharedPointer<QLowEnergyServicePrivate>(priv);
-                        serviceList.insert(service, pointer);
-                    }
-                    pointer->type |= QLowEnergyService::PrimaryService;
-
-                    obtainIncludedServices(pointer, deviceService);
-
-                    emit q->serviceDiscovered(service);
-                }
-
-                setState(QLowEnergyController::DiscoveredState);
-                emit q->discoveryFinished();
-
-                return S_OK;
-            }).Get());
+                    this, &QLowEnergyControllerPrivateWinRTNew::onServiceDiscoveryFinished).Get());
         CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not register service discovery callback",
                                           return S_OK)
         return hr;
@@ -1305,7 +1241,8 @@ void QLowEnergyControllerPrivateWinRTNew::writeCharacteristic(
         hr = characteristic->WriteValueWithOptionAsync(buffer.Get(), option, &writeOp);
         CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could write characteristic",
                                        service, QLowEnergyService::CharacteristicWriteError, return S_OK)
-        auto writeCompletedLambda =[charData, charHandle, newValue, service, writeWithResponse, this]
+        QPointer<QLowEnergyControllerPrivateWinRTNew> thisPtr(this);
+        auto writeCompletedLambda = [charData, charHandle, newValue, service, writeWithResponse, thisPtr]
                 (IAsyncOperation<GattCommunicationStatus> *op, AsyncStatus status)
         {
             if (status == AsyncStatus::Canceled || status == AsyncStatus::Error) {
@@ -1332,7 +1269,7 @@ void QLowEnergyControllerPrivateWinRTNew::writeCharacteristic(
             // only update cache when property is readable. Otherwise it remains
             // empty.
             if (charData.properties & QLowEnergyCharacteristic::Read)
-                updateValueOfCharacteristic(charHandle, newValue, false);
+                thisPtr->updateValueOfCharacteristic(charHandle, newValue, false);
             if (writeWithResponse)
                 emit service->characteristicWritten(QLowEnergyCharacteristic(service, charHandle),
                                                     newValue);
@@ -1412,7 +1349,8 @@ void QLowEnergyControllerPrivateWinRTNew::writeDescriptor(
             HRESULT hr = characteristic->WriteClientCharacteristicConfigurationDescriptorAsync(value, &writeOp);
             CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not write client characteristic configuration",
                                            service, QLowEnergyService::DescriptorWriteError, return S_OK)
-            auto writeCompletedLambda = [charHandle, descHandle, newValue, service, this]
+            QPointer<QLowEnergyControllerPrivateWinRTNew> thisPtr(this);
+            auto writeCompletedLambda = [charHandle, descHandle, newValue, service, thisPtr]
                     (IAsyncOperation<GattCommunicationStatus> *op, AsyncStatus status)
             {
                 if (status == AsyncStatus::Canceled || status == AsyncStatus::Error) {
@@ -1430,7 +1368,7 @@ void QLowEnergyControllerPrivateWinRTNew::writeDescriptor(
                     service->setError(QLowEnergyService::DescriptorWriteError);
                     return S_OK;
                 }
-                updateValueOfDescriptor(charHandle, descHandle, newValue, false);
+                thisPtr->updateValueOfDescriptor(charHandle, descHandle, newValue, false);
                 emit service->descriptorWritten(QLowEnergyDescriptor(service, charHandle, descHandle),
                                                 newValue);
                 return S_OK;
@@ -1505,7 +1443,8 @@ void QLowEnergyControllerPrivateWinRTNew::writeDescriptor(
             hr = descriptor->WriteValueAsync(buffer.Get(), &writeOp);
             CHECK_HR_AND_SET_SERVICE_ERROR(hr, "Could not write descriptor value",
                                            service, QLowEnergyService::DescriptorWriteError, return S_OK)
-            auto writeCompletedLambda = [charHandle, descHandle, newValue, service, this]
+            QPointer<QLowEnergyControllerPrivateWinRTNew> thisPtr(this);
+            auto writeCompletedLambda = [charHandle, descHandle, newValue, service, thisPtr]
                     (IAsyncOperation<GattCommunicationStatus> *op, AsyncStatus status)
             {
                 if (status == AsyncStatus::Canceled || status == AsyncStatus::Error) {
@@ -1523,7 +1462,7 @@ void QLowEnergyControllerPrivateWinRTNew::writeDescriptor(
                     service->setError(QLowEnergyService::DescriptorWriteError);
                     return S_OK;
                 }
-                updateValueOfDescriptor(charHandle, descHandle, newValue, false);
+                thisPtr->updateValueOfDescriptor(charHandle, descHandle, newValue, false);
                 emit service->descriptorWritten(QLowEnergyDescriptor(service, charHandle, descHandle),
                                                 newValue);
                 return S_OK;
@@ -1583,6 +1522,160 @@ void QLowEnergyControllerPrivateWinRTNew::handleServiceHandlerError(const QStrin
     setError(QLowEnergyController::ConnectionError);
 }
 
+void QLowEnergyControllerPrivateWinRTNew::connectToPairedDevice()
+{
+    Q_Q(QLowEnergyController);
+    ComPtr<IBluetoothLEDevice3> device3;
+    HRESULT hr = mDevice.As(&device3);
+    CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not cast device", return)
+    ComPtr<IAsyncOperation<GattDeviceServicesResult *>> deviceServicesOp;
+    while (!mAbortPending) {
+        hr = device3->GetGattServicesAsync(&deviceServicesOp);
+        CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain services", return)
+        ComPtr<IGattDeviceServicesResult> deviceServicesResult;
+        hr = QWinRTFunctions::await(deviceServicesOp, deviceServicesResult.GetAddressOf(),
+                                    QWinRTFunctions::ProcessThreadEvents, 5000);
+        CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not await services operation", return)
+
+        GattCommunicationStatus commStatus;
+        hr = deviceServicesResult->get_Status(&commStatus);
+        if (FAILED(hr) || commStatus != GattCommunicationStatus_Success) {
+            qCWarning(QT_BT_WINRT()) << "Service operation failed";
+            setError(QLowEnergyController::ConnectionError);
+            setState(QLowEnergyController::UnconnectedState);
+            unregisterFromStatusChanges();
+            return;
+        }
+
+        ComPtr<IVectorView <GattDeviceService *>> deviceServices;
+        hr = deviceServicesResult->get_Services(&deviceServices);
+        CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain list of services", return)
+            uint serviceCount;
+        hr = deviceServices->get_Size(&serviceCount);
+        CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain service count", return)
+
+        if (serviceCount == 0) {
+            qCWarning(QT_BT_WINRT()) << "Found devices without services";
+            setError(QLowEnergyController::ConnectionError);
+            setState(QLowEnergyController::UnconnectedState);
+            unregisterFromStatusChanges();
+            return;
+        }
+
+        // Windows automatically connects to the device as soon as a service value is read/written.
+        // Thus we read one value in order to establish the connection.
+        for (uint i = 0; i < serviceCount; ++i) {
+            ComPtr<IGattDeviceService> service;
+            hr = deviceServices->GetAt(i, &service);
+            CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain service", return);
+            ComPtr<IGattDeviceService3> service3;
+            hr = service.As(&service3);
+            CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not cast service", return);
+            ComPtr<IAsyncOperation<GattCharacteristicsResult *>> characteristicsOp;
+            hr = service3->GetCharacteristicsAsync(&characteristicsOp);
+            CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain characteristic", return);
+            ComPtr<IGattCharacteristicsResult> characteristicsResult;
+            hr = QWinRTFunctions::await(characteristicsOp, characteristicsResult.GetAddressOf(),
+                QWinRTFunctions::ProcessThreadEvents, 5000);
+            CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not await characteristic operation", return);
+            GattCommunicationStatus commStatus;
+            hr = characteristicsResult->get_Status(&commStatus);
+            if (FAILED(hr) || commStatus != GattCommunicationStatus_Success) {
+                qCWarning(QT_BT_WINRT) << "Characteristic operation failed";
+                break;
+            }
+            ComPtr<IVectorView<GattCharacteristic *>> characteristics;
+            hr = characteristicsResult->get_Characteristics(&characteristics);
+            if (hr == E_ACCESSDENIED) {
+                // Everything will work as expected up until this point if the manifest capabilties
+                // for bluetooth LE are not set.
+                qCWarning(QT_BT_WINRT) << "Could not obtain characteristic list. Please check your "
+                    "manifest capabilities";
+                setState(QLowEnergyController::UnconnectedState);
+                setError(QLowEnergyController::ConnectionError);
+                unregisterFromStatusChanges();
+                return;
+            }
+            CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain characteristic list", return);
+            uint characteristicsCount;
+            hr = characteristics->get_Size(&characteristicsCount);
+            CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain characteristic list's size", return);
+            for (uint j = 0; j < characteristicsCount; ++j) {
+                ComPtr<IGattCharacteristic> characteristic;
+                hr = characteristics->GetAt(j, &characteristic);
+                CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain characteristic", return);
+                ComPtr<IAsyncOperation<GattReadResult *>> op;
+                GattCharacteristicProperties props;
+                hr = characteristic->get_CharacteristicProperties(&props);
+                CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain characteristic's properties", return);
+                if (!(props & GattCharacteristicProperties_Read))
+                    continue;
+                hr = characteristic->ReadValueWithCacheModeAsync(BluetoothCacheMode::BluetoothCacheMode_Uncached, &op);
+                CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not read characteristic value", return);
+                ComPtr<IGattReadResult> result;
+                hr = QWinRTFunctions::await(op, result.GetAddressOf(), QWinRTFunctions::ProcessThreadEvents, 500);
+                // E_ILLEGAL_METHOD_CALL will be the result for a device, that is not reachable at
+                // the moment. In this case we should jump back into the outer loop and keep trying.
+                if (hr == E_ILLEGAL_METHOD_CALL)
+                    break;
+                CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not await characteristic read", return);
+                ComPtr<ABI::Windows::Storage::Streams::IBuffer> buffer;
+                hr = result->get_Value(&buffer);
+                CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain characteristic value", return);
+                if (!buffer) {
+                    qCDebug(QT_BT_WINRT) << "Problem reading value";
+                    break;
+                }
+
+                setState(QLowEnergyController::ConnectedState);
+                emit q->connected();
+                if (!registerForStatusChanges()) {
+                    setError(QLowEnergyController::ConnectionError);
+                    setState(QLowEnergyController::UnconnectedState);
+                    return;
+                }
+                return;
+            }
+        }
+    }
+}
+
+void QLowEnergyControllerPrivateWinRTNew::connectToUnpairedDevice()
+{
+    if (!registerForStatusChanges()) {
+        setError(QLowEnergyController::ConnectionError);
+        setState(QLowEnergyController::UnconnectedState);
+        return;
+    }
+    ComPtr<IBluetoothLEDevice3> device3;
+    HRESULT hr = mDevice.As(&device3);
+    CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not cast device", return)
+    ComPtr<IGattDeviceServicesResult> deviceServicesResult;
+    while (!mAbortPending) {
+        ComPtr<IAsyncOperation<GattDeviceServicesResult *>> deviceServicesOp;
+        hr = device3->GetGattServicesAsync(&deviceServicesOp);
+        CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not obtain services", return)
+        hr = QWinRTFunctions::await(deviceServicesOp, deviceServicesResult.GetAddressOf(),
+                                    QWinRTFunctions::ProcessMainThreadEvents);
+        CHECK_FOR_DEVICE_CONNECTION_ERROR(hr, "Could not await services operation", return)
+
+        GattCommunicationStatus commStatus;
+        hr = deviceServicesResult->get_Status(&commStatus);
+        if (commStatus == GattCommunicationStatus_Unreachable)
+            continue;
+
+        if (FAILED(hr) || commStatus != GattCommunicationStatus_Success) {
+            qCWarning(QT_BT_WINRT()) << "Service operation failed";
+            setError(QLowEnergyController::ConnectionError);
+            setState(QLowEnergyController::UnconnectedState);
+            unregisterFromStatusChanges();
+            return;
+        }
+
+        break;
+    }
+}
+
 QT_END_NAMESPACE
 
 #include "qlowenergycontroller_winrt_new.moc"
diff --git a/src/bluetooth/qlowenergycontroller_winrt_new_p.h b/src/bluetooth/qlowenergycontroller_winrt_new_p.h
index bf40974566375cabbfa30290885aec2ad5fdf67a..8cc5f9ce2a514e17f904fa628171de3678d11a50 100644
--- a/src/bluetooth/qlowenergycontroller_winrt_new_p.h
+++ b/src/bluetooth/qlowenergycontroller_winrt_new_p.h
@@ -60,8 +60,28 @@
 #include "qlowenergycontroller.h"
 #include "qlowenergycontrollerbase_p.h"
 
+namespace ABI {
+    namespace Windows {
+        namespace Devices {
+            namespace Bluetooth {
+                namespace GenericAttributeProfile {
+                    class GattDeviceServicesResult;
+                    struct IGattCharacteristic;
+                    struct IGattDeviceService;
+                    struct IGattValueChangedEventArgs;
+                }
+
+                struct IBluetoothLEDevice;
+            }
+        }
+        namespace Foundation {
+            template <typename T> struct IAsyncOperation;
+            enum class AsyncStatus;
+        }
+    }
+}
+
 #include <wrl.h>
-#include <windows.devices.bluetooth.h>
 
 #include <functional>
 
@@ -77,7 +97,6 @@ QLowEnergyControllerPrivate *createWinRTLowEnergyController();
 
 class QLowEnergyControllerPrivateWinRTNew final : public QLowEnergyControllerPrivate
 {
-    Q_OBJECT
 public:
     QLowEnergyControllerPrivateWinRTNew();
     ~QLowEnergyControllerPrivateWinRTNew() override;
@@ -121,6 +140,10 @@ private slots:
     void handleServiceHandlerError(const QString &error);
 
 private:
+    void connectToPairedDevice();
+    void connectToUnpairedDevice();
+
+    bool mAbortPending = false;
     Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::IBluetoothLEDevice> mDevice;
     EventRegistrationToken mStatusChangedToken;
     struct ValueChangedEntry {
@@ -142,12 +165,17 @@ private:
 
     void registerForValueChanges(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid);
     void unregisterFromValueChanges();
+    HRESULT onValueChange(ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattCharacteristic *characteristic,
+                          ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattValueChangedEventArgs *args);
 
+    bool registerForStatusChanges();
     void unregisterFromStatusChanges();
+    HRESULT onStatusChange(ABI::Windows::Devices::Bluetooth::IBluetoothLEDevice *dev, IInspectable *);
 
     void obtainIncludedServices(QSharedPointer<QLowEnergyServicePrivate> servicePointer,
         Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattDeviceService> nativeService);
-
+    HRESULT onServiceDiscoveryFinished(ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::GattDeviceServicesResult *> *op,
+                                       ABI::Windows::Foundation::AsyncStatus status);
 };
 
 QT_END_NAMESPACE