diff --git a/dist/changes-5.12.4 b/dist/changes-5.12.4
new file mode 100644
index 0000000000000000000000000000000000000000..cb7ef2bf571586a2ffebf8e1ce5599587423e534
--- /dev/null
+++ b/dist/changes-5.12.4
@@ -0,0 +1,39 @@
+Qt 5.12.4 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 5.12.0 through 5.12.3.
+
+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.12 series is binary compatible with the 5.11.x series.
+Applications compiled for 5.11 will continue to run with 5.12.
+
+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.12.3 Changes                           *
+****************************************************************************
+
+QtBluetooth
+-----------
+
+ - Fixed a memory leak in QBluetoothServiceDiscoveryAgent on Android.
+
+ - [QTBUG-75035] Improved likelihood of
+   QBluetoothSocket::connectToService(QBluetoothServiceInfo,..) succeeding when
+   QBluetoothServiceInfo::socketProtocol() returns a non-RFCOMM type. Since Android
+   does not support anything but RFCOMM it always assumes RFCOMM.
+
+ - Fixed reading of descriptor values on WinRT.
+
+ - [QTBUG-75043] Fixed behavior when a peripheral changes its service list at runtime
+
+ - [QTBUG-75278] Fixed socket leak when running QLowEnergyController Peripheral mode
+   on Linux.
diff --git a/src/bluetooth/qbluetooth.cpp b/src/bluetooth/qbluetooth.cpp
index 6eab11fb502d520831e9799d1072173064d18371..b14c79cd61d8848eb45a0bf8b527515144bafc72 100644
--- a/src/bluetooth/qbluetooth.cpp
+++ b/src/bluetooth/qbluetooth.cpp
@@ -102,5 +102,6 @@ Q_LOGGING_CATEGORY(QT_BT, "qt.bluetooth")
 Q_LOGGING_CATEGORY(QT_BT_ANDROID, "qt.bluetooth.android")
 Q_LOGGING_CATEGORY(QT_BT_BLUEZ, "qt.bluetooth.bluez")
 Q_LOGGING_CATEGORY(QT_BT_WINRT, "qt.bluetooth.winrt")
+Q_LOGGING_CATEGORY(QT_BT_WINRT_SERVICE_THREAD, "qt.bluetooth.winrt.service.thread")
 
 QT_END_NAMESPACE
diff --git a/src/bluetooth/qbluetoothsocket_winrt.cpp b/src/bluetooth/qbluetoothsocket_winrt.cpp
index 72d72040323eca6aa8fbc8629a8ebca97a1e0265..48b147579fbb9bbbcceebf7b4254607e910f1030 100644
--- a/src/bluetooth/qbluetoothsocket_winrt.cpp
+++ b/src/bluetooth/qbluetoothsocket_winrt.cpp
@@ -94,15 +94,22 @@ static inline QString qt_QStringFromHString(const HString &string)
 {
     UINT32 length;
     PCWSTR rawString = string.GetRawBuffer(&length);
-    return QString::fromWCharArray(rawString, length);
+    if (length > INT_MAX)
+        length = INT_MAX;
+    return QString::fromWCharArray(rawString, int(length));
 }
 
 static qint64 writeIOStream(ComPtr<IOutputStream> stream, const char *data, qint64 len)
 {
     ComPtr<IBuffer> buffer;
-    HRESULT hr = g->bufferFactory->Create(len, &buffer);
+    if (len > UINT32_MAX) {
+        qCWarning(QT_BT_WINRT) << "writeIOStream can only write up to" << UINT32_MAX << "bytes.";
+        len = UINT32_MAX;
+    }
+    quint32 ulen = static_cast<quint32>(len);
+    HRESULT hr = g->bufferFactory->Create(ulen, &buffer);
     Q_ASSERT_SUCCEEDED(hr);
-    hr = buffer->put_Length(len);
+    hr = buffer->put_Length(ulen);
     Q_ASSERT_SUCCEEDED(hr);
     ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteArrayAccess;
     hr = buffer.As(&byteArrayAccess);
@@ -110,7 +117,7 @@ static qint64 writeIOStream(ComPtr<IOutputStream> stream, const char *data, qint
     byte *bytes;
     hr = byteArrayAccess->Buffer(&bytes);
     Q_ASSERT_SUCCEEDED(hr);
-    memcpy(bytes, data, len);
+    memcpy(bytes, data, ulen);
     ComPtr<IAsyncOperationWithProgress<UINT32, UINT32>> op;
     hr = stream->WriteAsync(buffer.Get(), &op);
     RETURN_IF_FAILED("Failed to write to stream", return -1);
@@ -257,7 +264,7 @@ public:
             return S_OK;
         }
 
-        QByteArray newData(reinterpret_cast<const char*>(data), qint64(bufferLength));
+        QByteArray newData(reinterpret_cast<const char*>(data), int(bufferLength));
         QMutexLocker readLocker(&m_mutex);
         if (m_pendingData.isEmpty())
             QMetaObject::invokeMethod(this, "notifyAboutNewData", Qt::QueuedConnection);
@@ -448,7 +455,8 @@ void QBluetoothSocketPrivateWinRT::connectToService(
            q->setSocketError(QBluetoothSocket::UnknownSocketError);
            return;
        }
-       connectToServiceHelper(service.device().address(), service.protocolServiceMultiplexer(), openMode);
+       connectToServiceHelper(service.device().address(),
+                              quint16(service.protocolServiceMultiplexer()), openMode);
     } else if (!connectionHostName.isEmpty() && !connectionServiceName.isEmpty()) {
         Q_ASSERT(service.socketProtocol() == QBluetoothServiceInfo::RfcommProtocol);
         if (!ensureNativeSocket(QBluetoothServiceInfo::RfcommProtocol)) {
@@ -472,7 +480,8 @@ void QBluetoothSocketPrivateWinRT::connectToService(
            q->setSocketError(QBluetoothSocket::UnknownSocketError);
            return;
        }
-       connectToServiceHelper(service.device().address(), service.serverChannel(), openMode);
+       connectToServiceHelper(service.device().address(), quint16(service.serverChannel()),
+                              openMode);
     } else {
        // try doing service discovery to see if we can find the socket
        if (service.serviceUuid().isNull()
@@ -597,7 +606,13 @@ quint16 QBluetoothSocketPrivateWinRT::localPort() const
     HString localPortString;
     hr = info->get_LocalPort(localPortString.GetAddressOf());
     Q_ASSERT_SUCCEEDED(hr);
-    return qt_QStringFromHString(localPortString).toInt();
+    bool ok = true;
+    const uint port = qt_QStringFromHString(localPortString).toUInt(&ok);
+    if (!ok || port > UINT16_MAX) {
+        qCWarning(QT_BT_WINRT) << "Unexpected local port";
+        return 0;
+    }
+    return quint16(port);
 }
 
 QString QBluetoothSocketPrivateWinRT::peerName() const
@@ -648,7 +663,13 @@ quint16 QBluetoothSocketPrivateWinRT::peerPort() const
     HString remotePortString;
     hr = info->get_LocalPort(remotePortString.GetAddressOf());
     Q_ASSERT_SUCCEEDED(hr);
-    return qt_QStringFromHString(remotePortString).toInt();
+    bool ok = true;
+    const uint port = qt_QStringFromHString(remotePortString).toUInt(&ok);
+    if (!ok || port > UINT16_MAX) {
+        qCWarning(QT_BT_WINRT) << "Unexpected remote port";
+        return 0;
+    }
+    return quint16(port);
 }
 
 qint64 QBluetoothSocketPrivateWinRT::writeData(const char *data, qint64 maxSize)
@@ -687,8 +708,11 @@ qint64 QBluetoothSocketPrivateWinRT::readData(char *data, qint64 maxSize)
         return -1;
     }
 
-    if (!buffer.isEmpty())
-        return buffer.read(data, maxSize);
+    if (!buffer.isEmpty()) {
+        if (maxSize > INT_MAX)
+            maxSize = INT_MAX;
+        return buffer.read(data, int(maxSize));
+    }
 
     return 0;
 }
@@ -779,7 +803,7 @@ void QBluetoothSocketPrivateWinRT::addToPendingData(const QVector<QByteArray> &d
     m_pendingData.append(data);
     for (const QByteArray &newData : data) {
         char *writePointer = buffer.reserve(newData.length());
-        memcpy(writePointer, newData.data(), newData.length());
+        memcpy(writePointer, newData.data(), size_t(newData.length()));
     }
     locker.unlock();
     emit q->readyRead();
@@ -795,19 +819,24 @@ HRESULT QBluetoothSocketPrivateWinRT::handleConnectOpFinished(ABI::Windows::Foun
         return S_OK;
     }
 
-    DWORD hr = action->GetResults();
+    HRESULT hr = action->GetResults();
     switch (hr) {
-    case 0x8007274c: // A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
+
+    // A connection attempt failed because the connected party did not properly respond after a
+    // period of time, or established connection failed because connected host has failed to respond.
+    case HRESULT_FROM_WIN32(WSAETIMEDOUT):
         errorString = QBluetoothSocket::tr("Connection timed out");
         q->setSocketError(QBluetoothSocket::NetworkError);
         q->setSocketState(QBluetoothSocket::UnconnectedState);
         return S_OK;
-    case 0x80072751: // A socket operation was attempted to an unreachable host.
+    // A socket operation was attempted to an unreachable host.
+    case HRESULT_FROM_WIN32(WSAEHOSTUNREACH):
         errorString = QBluetoothSocket::tr("Host not reachable");
         q->setSocketError(QBluetoothSocket::HostNotFoundError);
         q->setSocketState(QBluetoothSocket::UnconnectedState);
         return S_OK;
-    case 0x8007274d: // No connection could be made because the target machine actively refused it.
+    // No connection could be made because the target machine actively refused it.
+    case HRESULT_FROM_WIN32(WSAECONNREFUSED):
         errorString = QBluetoothSocket::tr("Host refused connection");
         q->setSocketError(QBluetoothSocket::HostNotFoundError);
         q->setSocketState(QBluetoothSocket::UnconnectedState);
@@ -832,8 +861,7 @@ HRESULT QBluetoothSocketPrivateWinRT::handleConnectOpFinished(ABI::Windows::Foun
             hr = info->Close();
             Q_ASSERT_SUCCEEDED(hr);
         }
-        hr = m_connectOp.Reset();
-        Q_ASSERT_SUCCEEDED(hr);
+        m_connectOp.Reset();
     }
 
     q->setOpenMode(requestedOpenMode);
diff --git a/src/bluetooth/qlowenergycontroller_winrt.cpp b/src/bluetooth/qlowenergycontroller_winrt.cpp
index e70b046b8466e9ac0c6c594a37f9529cfd5dc823..ab566bd9c7ed2466adf074d35cf14affb18b9080 100644
--- a/src/bluetooth/qlowenergycontroller_winrt.cpp
+++ b/src/bluetooth/qlowenergycontroller_winrt.cpp
@@ -76,6 +76,7 @@ typedef GattReadClientCharacteristicConfigurationDescriptorResult ClientCharConf
 typedef IGattReadClientCharacteristicConfigurationDescriptorResult IClientCharConfigDescriptorResult;
 
 Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINRT)
+Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINRT_SERVICE_THREAD)
 
 static QByteArray byteArrayFromGattResult(const ComPtr<IGattReadResult> &gattResult, bool isWCharString = false)
 {
@@ -239,6 +240,9 @@ QLowEnergyControllerPrivateWinRT::QLowEnergyControllerPrivateWinRT()
     qCDebug(QT_BT_WINRT) << __FUNCTION__;
 
     registerQLowEnergyControllerMetaType();
+    connect(this, &QLowEnergyControllerPrivateWinRT::characteristicChanged,
+            this, &QLowEnergyControllerPrivateWinRT::handleCharacteristicChanged,
+            Qt::QueuedConnection);
 }
 
 QLowEnergyControllerPrivateWinRT::~QLowEnergyControllerPrivateWinRT()
@@ -453,7 +457,7 @@ void QLowEnergyControllerPrivateWinRT::registerForValueChanges(const QBluetoothU
         ComPtr<IBuffer> buffer;
         hr = args->get_CharacteristicValue(&buffer);
         Q_ASSERT_SUCCEEDED(hr);
-        characteristicChanged(handle, byteArrayFromBuffer(buffer));
+        emit characteristicChanged(handle, byteArrayFromBuffer(buffer));
         return S_OK;
     }).Get(), &token);
     Q_ASSERT_SUCCEEDED(hr);
@@ -498,6 +502,9 @@ void QLowEnergyControllerPrivateWinRT::obtainIncludedServices(QSharedPointer<QLo
         Q_ASSERT_SUCCEEDED(hr);
         const QBluetoothUuid includedUuid(guuid);
         QSharedPointer<QLowEnergyServicePrivate> includedPointer;
+        qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__
+                                            << "Changing service pointer from thread"
+                                            << QThread::currentThread();
         if (serviceList.contains(includedUuid)) {
             includedPointer = serviceList.value(includedUuid);
         } else {
@@ -508,6 +515,9 @@ void QLowEnergyControllerPrivateWinRT::obtainIncludedServices(QSharedPointer<QLo
             includedPointer = QSharedPointer<QLowEnergyServicePrivate>(priv);
             serviceList.insert(includedUuid, includedPointer);
         }
+        qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__
+                                            << "Changing service pointer from thread"
+                                            << QThread::currentThread();
         includedPointer->type |= QLowEnergyService::IncludedService;
         servicePointer->includedServices.append(includedUuid);
 
@@ -537,6 +547,9 @@ void QLowEnergyControllerPrivateWinRT::discoverServices()
         Q_ASSERT_SUCCEEDED(hr);
         const QBluetoothUuid service(guuid);
 
+        qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__
+                                            << "Changing service pointer from thread"
+                                            << QThread::currentThread();
         QSharedPointer<QLowEnergyServicePrivate> pointer;
         if (serviceList.contains(service)) {
             pointer = serviceList.value(service);
@@ -576,6 +589,8 @@ void QLowEnergyControllerPrivateWinRT::discoverServiceDetails(const QBluetoothUu
 
     //update service data
     QSharedPointer<QLowEnergyServicePrivate> pointer = serviceList.value(service);
+    qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread"
+                                        << QThread::currentThread();
 
     pointer->setState(QLowEnergyService::DiscoveringServices);
     ComPtr<IGattDeviceService2> deviceService2;
@@ -669,6 +684,8 @@ void QLowEnergyControllerPrivateWinRT::readCharacteristic(const QSharedPointer<Q
                         const QLowEnergyHandle charHandle)
 {
     qCDebug(QT_BT_WINRT) << __FUNCTION__ << service << charHandle;
+    qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread"
+                                        << QThread::currentThread();
     Q_ASSERT(!service.isNull());
     if (role == QLowEnergyController::PeripheralRole) {
         service->setError(QLowEnergyService::CharacteristicReadError);
@@ -734,6 +751,8 @@ void QLowEnergyControllerPrivateWinRT::readDescriptor(const QSharedPointer<QLowE
                     const QLowEnergyHandle descHandle)
 {
     qCDebug(QT_BT_WINRT) << __FUNCTION__ << service << charHandle << descHandle;
+    qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread"
+                                        << QThread::currentThread();
     Q_ASSERT(!service.isNull());
     if (role == QLowEnergyController::PeripheralRole) {
         service->setError(QLowEnergyService::DescriptorReadError);
@@ -870,6 +889,8 @@ void QLowEnergyControllerPrivateWinRT::writeCharacteristic(const QSharedPointer<
         QLowEnergyService::WriteMode mode)
 {
     qCDebug(QT_BT_WINRT) << __FUNCTION__ << service << charHandle << newValue << mode;
+    qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread"
+                                        << QThread::currentThread();
     Q_ASSERT(!service.isNull());
     if (role == QLowEnergyController::PeripheralRole) {
         service->setError(QLowEnergyService::CharacteristicWriteError);
@@ -960,6 +981,8 @@ void QLowEnergyControllerPrivateWinRT::writeDescriptor(
         const QByteArray &newValue)
 {
     qCDebug(QT_BT_WINRT) << __FUNCTION__ << service << charHandle << descHandle << newValue;
+    qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread"
+                                        << QThread::currentThread();
     Q_ASSERT(!service.isNull());
     if (role == QLowEnergyController::PeripheralRole) {
         service->setError(QLowEnergyService::DescriptorWriteError);
@@ -1103,9 +1126,12 @@ void QLowEnergyControllerPrivateWinRT::addToGenericAttributeList(const QLowEnerg
     Q_UNIMPLEMENTED();
 }
 
-void QLowEnergyControllerPrivateWinRT::characteristicChanged(
-        int charHandle, const QByteArray &data)
+void QLowEnergyControllerPrivateWinRT::handleCharacteristicChanged(
+        quint16 charHandle, const QByteArray &data)
 {
+    qCDebug(QT_BT_WINRT) << __FUNCTION__ << charHandle << data;
+    qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread"
+                                        << QThread::currentThread();
     QSharedPointer<QLowEnergyServicePrivate> service =
             serviceForHandle(charHandle);
     if (service.isNull())
diff --git a/src/bluetooth/qlowenergycontroller_winrt_new.cpp b/src/bluetooth/qlowenergycontroller_winrt_new.cpp
index bb9894ff2b870678ddfead0d14855dddaafd6391..a22064fd4271e1812b9056a1ca894ebba8e9bdb5 100644
--- a/src/bluetooth/qlowenergycontroller_winrt_new.cpp
+++ b/src/bluetooth/qlowenergycontroller_winrt_new.cpp
@@ -113,6 +113,7 @@ typedef IGattReadClientCharacteristicConfigurationDescriptorResult IClientCharCo
     }
 
 Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINRT)
+Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINRT_SERVICE_THREAD)
 
 QLowEnergyControllerPrivate *createWinRTLowEnergyController()
 {
@@ -435,6 +436,9 @@ QLowEnergyControllerPrivateWinRTNew::QLowEnergyControllerPrivateWinRTNew()
     : QLowEnergyControllerPrivate()
 {
     registerQLowEnergyControllerMetaType();
+    connect(this, &QLowEnergyControllerPrivateWinRTNew::characteristicChanged,
+            this, &QLowEnergyControllerPrivateWinRTNew::handleCharacteristicChanged,
+            Qt::QueuedConnection);
 }
 
 QLowEnergyControllerPrivateWinRTNew::~QLowEnergyControllerPrivateWinRTNew()
@@ -613,7 +617,7 @@ HRESULT QLowEnergyControllerPrivateWinRTNew::onValueChange(IGattCharacteristic *
     ComPtr<IBuffer> buffer;
     hr = args->get_CharacteristicValue(&buffer);
     RETURN_IF_FAILED("Could not obtain characteristic's value", return S_OK)
-    characteristicChanged(handle, byteArrayFromBuffer(buffer));
+    emit characteristicChanged(handle, byteArrayFromBuffer(buffer));
     return S_OK;
 }
 
@@ -707,6 +711,9 @@ void QLowEnergyControllerPrivateWinRTNew::obtainIncludedServices(
         WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain included service's Uuid");
         const QBluetoothUuid includedUuid(guuid);
         QSharedPointer<QLowEnergyServicePrivate> includedPointer;
+        qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__
+                                            << "Changing service pointer from thread"
+                                            << QThread::currentThread();
         if (serviceList.contains(includedUuid)) {
             includedPointer = serviceList.value(includedUuid);
         } else {
@@ -762,6 +769,9 @@ HRESULT QLowEnergyControllerPrivateWinRTNew::onServiceDiscoveryFinished(ABI::Win
         WARN_AND_CONTINUE_IF_FAILED(hr, "Could not obtain service's Uuid");
         const QBluetoothUuid service(guuid);
 
+        qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__
+                                            << "Changing service pointer from thread"
+                                            << QThread::currentThread();
         QSharedPointer<QLowEnergyServicePrivate> pointer;
         if (serviceList.contains(service)) {
             pointer = serviceList.value(service);
@@ -825,7 +835,8 @@ void QLowEnergyControllerPrivateWinRTNew::discoverServiceDetails(const QBluetoot
 
     //update service data
     QSharedPointer<QLowEnergyServicePrivate> pointer = serviceList.value(service);
-
+    qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread"
+                                        << QThread::currentThread();
     pointer->setState(QLowEnergyService::DiscoveringServices);
     ComPtr<IGattDeviceService3> deviceService3;
     HRESULT hr = deviceService.As(&deviceService3);
@@ -939,6 +950,8 @@ void QLowEnergyControllerPrivateWinRTNew::readCharacteristic(
         const QLowEnergyHandle charHandle)
 {
     qCDebug(QT_BT_WINRT) << __FUNCTION__ << service << charHandle;
+    qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread"
+                                        << QThread::currentThread();
     Q_ASSERT(!service.isNull());
     if (role == QLowEnergyController::PeripheralRole) {
         service->setError(QLowEnergyService::CharacteristicReadError);
@@ -1006,6 +1019,8 @@ void QLowEnergyControllerPrivateWinRTNew::readDescriptor(
         const QLowEnergyHandle descHandle)
 {
     qCDebug(QT_BT_WINRT) << __FUNCTION__ << service << charHandle << descHandle;
+    qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread"
+                                        << QThread::currentThread();
     Q_ASSERT(!service.isNull());
     if (role == QLowEnergyController::PeripheralRole) {
         service->setError(QLowEnergyService::DescriptorReadError);
@@ -1182,6 +1197,8 @@ void QLowEnergyControllerPrivateWinRTNew::writeCharacteristic(
         QLowEnergyService::WriteMode mode)
 {
     qCDebug(QT_BT_WINRT) << __FUNCTION__ << service << charHandle << newValue << mode;
+    qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread"
+                                        << QThread::currentThread();
     Q_ASSERT(!service.isNull());
     if (role == QLowEnergyController::PeripheralRole) {
         service->setError(QLowEnergyService::CharacteristicWriteError);
@@ -1293,6 +1310,8 @@ void QLowEnergyControllerPrivateWinRTNew::writeDescriptor(
         const QByteArray &newValue)
 {
     qCDebug(QT_BT_WINRT) << __FUNCTION__ << service << charHandle << descHandle << newValue;
+    qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread"
+                                        << QThread::currentThread();
     Q_ASSERT(!service.isNull());
     if (role == QLowEnergyController::PeripheralRole) {
         service->setError(QLowEnergyService::DescriptorWriteError);
@@ -1487,9 +1506,12 @@ void QLowEnergyControllerPrivateWinRTNew::addToGenericAttributeList(const QLowEn
     Q_UNIMPLEMENTED();
 }
 
-void QLowEnergyControllerPrivateWinRTNew::characteristicChanged(
+void QLowEnergyControllerPrivateWinRTNew::handleCharacteristicChanged(
         quint16 charHandle, const QByteArray &data)
 {
+    qCDebug(QT_BT_WINRT) << __FUNCTION__ << charHandle << data;
+    qCDebug(QT_BT_WINRT_SERVICE_THREAD) << __FUNCTION__ << "Changing service pointer from thread"
+                                        << QThread::currentThread();
     QSharedPointer<QLowEnergyServicePrivate> service =
             serviceForHandle(charHandle);
     if (service.isNull())
diff --git a/src/bluetooth/qlowenergycontroller_winrt_new_p.h b/src/bluetooth/qlowenergycontroller_winrt_new_p.h
index 8cc5f9ce2a514e17f904fa628171de3678d11a50..c31408be4f153adb61e08352bb6837f95940e48c 100644
--- a/src/bluetooth/qlowenergycontroller_winrt_new_p.h
+++ b/src/bluetooth/qlowenergycontroller_winrt_new_p.h
@@ -64,13 +64,6 @@ namespace ABI {
     namespace Windows {
         namespace Devices {
             namespace Bluetooth {
-                namespace GenericAttributeProfile {
-                    class GattDeviceServicesResult;
-                    struct IGattCharacteristic;
-                    struct IGattDeviceService;
-                    struct IGattValueChangedEventArgs;
-                }
-
                 struct IBluetoothLEDevice;
             }
         }
@@ -82,6 +75,7 @@ namespace ABI {
 }
 
 #include <wrl.h>
+#include <windows.devices.bluetooth.genericattributeprofile.h>
 
 #include <functional>
 
@@ -97,6 +91,7 @@ QLowEnergyControllerPrivate *createWinRTLowEnergyController();
 
 class QLowEnergyControllerPrivateWinRTNew final : public QLowEnergyControllerPrivate
 {
+    Q_OBJECT
 public:
     QLowEnergyControllerPrivateWinRTNew();
     ~QLowEnergyControllerPrivateWinRTNew() override;
@@ -135,8 +130,11 @@ public:
     void addToGenericAttributeList(const QLowEnergyServiceData &service,
                                    QLowEnergyHandle startHandle) override;
 
-private slots:
+signals:
     void characteristicChanged(quint16 charHandle, const QByteArray &data);
+
+private slots:
+    void handleCharacteristicChanged(quint16 charHandle, const QByteArray &data);
     void handleServiceHandlerError(const QString &error);
 
 private:
diff --git a/src/bluetooth/qlowenergycontroller_winrt_p.h b/src/bluetooth/qlowenergycontroller_winrt_p.h
index da21353ff12a9c6cf49e36e7c27a1b85f1e1eb96..fedc52d9c9429f53f8f3cb027a60b1c68dbebae8 100644
--- a/src/bluetooth/qlowenergycontroller_winrt_p.h
+++ b/src/bluetooth/qlowenergycontroller_winrt_p.h
@@ -114,8 +114,11 @@ public:
     void addToGenericAttributeList(const QLowEnergyServiceData &service,
                                    QLowEnergyHandle startHandle) override;
 
+signals:
+    void characteristicChanged(quint16 charHandle, const QByteArray &data);
+
 private slots:
-    void characteristicChanged(int charHandle, const QByteArray &data);
+    void handleCharacteristicChanged(quint16 charHandle, const QByteArray &data);
 
 private:
     Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::IBluetoothLEDevice> mDevice;