summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTarja Sundqvist <tarja.sundqvist@qt.io>2024-01-22 22:33:45 +0200
committerTarja Sundqvist <tarja.sundqvist@qt.io>2024-02-20 15:20:01 +0000
commit9c1fe537717255453f86822c959f44360cfa9a27 (patch)
treebbd27b74963847a409ef476dff106327d37d8b48
parent32748a3b04f67af77573eefdc36586d4f7f49e98 (diff)
parentddfb06fb8a2df4d9bf13eabb52edd3ad858b8c14 (diff)
Merge remote-tracking branch 'origin/tqtc/lts-6.2.8' into tqtc/lts-6.2-opensource
Conflicts solved in a file: dependencies.yaml Change-Id: Id3187c943acccb6d77a377f205a7822e2d0a54d4
-rw-r--r--.cmake.conf2
-rw-r--r--.qmake.conf2
-rw-r--r--cmake/FindBlueZ.cmake6
-rw-r--r--dependencies.yaml4
-rw-r--r--src/bluetooth/configure.cmake2
-rw-r--r--src/bluetooth/doc/src/bluetooth-le-overview.qdoc8
-rw-r--r--src/bluetooth/qbluetoothdevicewatcher_winrt_p.h1
-rw-r--r--src/bluetooth/qbluetoothutils_winrt_p.h1
-rw-r--r--src/bluetooth/qlowenergycontroller_winrt.cpp64
-rw-r--r--src/bluetooth/qlowenergycontroller_winrt_p.h1
-rw-r--r--src/tools/sdpscanner/main.cpp15
11 files changed, 73 insertions, 33 deletions
diff --git a/.cmake.conf b/.cmake.conf
index 07d90b8a..e62fae5e 100644
--- a/.cmake.conf
+++ b/.cmake.conf
@@ -1,2 +1,2 @@
-set(QT_REPO_MODULE_VERSION "6.2.7")
+set(QT_REPO_MODULE_VERSION "6.2.8")
set(QT_REPO_MODULE_PRERELEASE_VERSION_SEGMENT "")
diff --git a/.qmake.conf b/.qmake.conf
index 24e796fe..a0cf48b9 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -2,4 +2,4 @@ load(qt_build_config)
DEFINES += QT_NO_FOREACH QT_NO_JAVA_STYLE_ITERATORS
-MODULE_VERSION = 6.2.7
+MODULE_VERSION = 6.2.8
diff --git a/cmake/FindBlueZ.cmake b/cmake/FindBlueZ.cmake
index aa192f10..6a0cbbe0 100644
--- a/cmake/FindBlueZ.cmake
+++ b/cmake/FindBlueZ.cmake
@@ -1,7 +1,9 @@
+set(BlueZ_FOUND 0)
+
find_package(PkgConfig QUIET)
pkg_check_modules(BLUEZ bluez IMPORTED_TARGET)
-if (NOT TARGET PkgConfig::BLUEZ)
- set(BLUEZ_FOUND 0)
+if(TARGET PkgConfig::BLUEZ)
+ set(BlueZ_FOUND 1)
endif()
diff --git a/dependencies.yaml b/dependencies.yaml
index b12c2dd5..734f5d12 100644
--- a/dependencies.yaml
+++ b/dependencies.yaml
@@ -1,7 +1,7 @@
dependencies:
../tqtc-qtbase:
- ref: 694575a59b5370afc494fbf700eee8db1d1ec091
+ ref: 67934c103800bae50c2ec1977758d40fa8e4e507
required: true
../tqtc-qtdeclarative:
- ref: 02277e3753613d9e19bbb36367c7d2b1d13d7545
+ ref: 302ab20d46280e11042f3896460c55d8b8146e41
required: false
diff --git a/src/bluetooth/configure.cmake b/src/bluetooth/configure.cmake
index 2090a255..f9a2b3c3 100644
--- a/src/bluetooth/configure.cmake
+++ b/src/bluetooth/configure.cmake
@@ -6,7 +6,7 @@
#### Libraries
-qt_find_package(BlueZ PROVIDED_TARGETS PkgConfig::BlueZ)
+qt_find_package(BlueZ PROVIDED_TARGETS PkgConfig::BLUEZ)
#### Tests
diff --git a/src/bluetooth/doc/src/bluetooth-le-overview.qdoc b/src/bluetooth/doc/src/bluetooth-le-overview.qdoc
index 7fc7d7c6..e4e66db4 100644
--- a/src/bluetooth/doc/src/bluetooth-le-overview.qdoc
+++ b/src/bluetooth/doc/src/bluetooth-le-overview.qdoc
@@ -34,11 +34,9 @@ Low Energy devices.
\tableofcontents
- The Qt Bluetooth Low Energy API for the central role was introduced by Qt 5.4.
- Since Qt 5.5 that part of the API is final and a compatibility guarantee is given for
- future releases.
- Since Qt 5.7, additional API supporting the peripheral role was added as a Technology Preview,
- with the backend implemented for Linux/BlueZ, iOS and macOS.
+ The Qt Bluetooth Low Energy API supports the peripheral/server and central/client roles.
+ It is supported on all major Qt platforms. The only exception is the missing peripheral role
+ support on Windows.
\section1 What Is Bluetooth Low Energy
diff --git a/src/bluetooth/qbluetoothdevicewatcher_winrt_p.h b/src/bluetooth/qbluetoothdevicewatcher_winrt_p.h
index b3dc4ec9..8f1bf423 100644
--- a/src/bluetooth/qbluetoothdevicewatcher_winrt_p.h
+++ b/src/bluetooth/qbluetoothdevicewatcher_winrt_p.h
@@ -57,6 +57,7 @@
#include <private/qbluetoothutils_winrt_p.h>
#include <winrt/base.h>
+#include <QtCore/private/qfactorycacheregistration_p.h>
#include <winrt/Windows.Devices.Enumeration.h>
QT_BEGIN_NAMESPACE
diff --git a/src/bluetooth/qbluetoothutils_winrt_p.h b/src/bluetooth/qbluetoothutils_winrt_p.h
index 96cfd8d6..42ec3a4f 100644
--- a/src/bluetooth/qbluetoothutils_winrt_p.h
+++ b/src/bluetooth/qbluetoothutils_winrt_p.h
@@ -54,6 +54,7 @@
// Workaround for Windows SDK bug.
// See https://github.com/microsoft/Windows.UI.Composition-Win32-Samples/issues/47
#include <winrt/base.h>
+#include <QtCore/private/qfactorycacheregistration_p.h>
namespace winrt::impl
{
template <typename Async>
diff --git a/src/bluetooth/qlowenergycontroller_winrt.cpp b/src/bluetooth/qlowenergycontroller_winrt.cpp
index d82732ea..376ee58e 100644
--- a/src/bluetooth/qlowenergycontroller_winrt.cpp
+++ b/src/bluetooth/qlowenergycontroller_winrt.cpp
@@ -138,13 +138,14 @@ static QByteArray byteArrayFromGattResult(const ComPtr<IGattReadResult> &gattRes
return byteArrayFromBuffer(buffer, isWCharString);
}
-static void closeDeviceService(ComPtr<IGattDeviceService> service)
+template <typename T>
+static void closeDeviceService(ComPtr<T> service)
{
ComPtr<IClosable> closableService;
HRESULT hr = service.As(&closableService);
- RETURN_IF_FAILED("Could not cast service to closable", return);
+ RETURN_IF_FAILED("Could not cast type to closable", return);
hr = closableService->Close();
- RETURN_IF_FAILED("Service Close() failed", return);
+ RETURN_IF_FAILED("Close() call failed", return);
}
class QWinRTLowEnergyServiceHandler : public QObject
@@ -161,12 +162,16 @@ public:
~QWinRTLowEnergyServiceHandler()
{
+ if (mAbortRequested)
+ closeDeviceService(mDeviceService);
qCDebug(QT_BT_WINDOWS) << __FUNCTION__;
}
public slots:
void obtainCharList()
{
+ auto exitCondition = [this]() { return mAbortRequested; };
+
mIndicateChars.clear();
qCDebug(QT_BT_WINDOWS) << __FUNCTION__;
ComPtr<IAsyncOperation<GattCharacteristicsResult *>> characteristicsOp;
@@ -174,7 +179,8 @@ public slots:
HRESULT hr = mDeviceService->GetCharacteristicsAsync(&characteristicsOp);
EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED(hr);
hr = QWinRTFunctions::await(characteristicsOp, characteristicsResult.GetAddressOf(),
- QWinRTFunctions::ProcessMainThreadEvents, 5000);
+ QWinRTFunctions::ProcessMainThreadEvents, 5000,
+ exitCondition);
EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED(hr);
GattCommunicationStatus status;
hr = characteristicsResult->get_Status(&status);
@@ -192,7 +198,7 @@ public slots:
EMIT_WORKER_ERROR_AND_QUIT_IF_FAILED(hr);
mCharacteristicsCountToBeDiscovered = characteristicsCount;
- for (uint i = 0; i < characteristicsCount; ++i) {
+ for (uint i = 0; !mAbortRequested && (i < characteristicsCount); ++i) {
ComPtr<IGattCharacteristic> characteristic;
hr = characteristics->GetAt(i, &characteristic);
if (FAILED(hr)) {
@@ -218,7 +224,9 @@ public slots:
DEC_CHAR_COUNT_AND_CONTINUE_IF_FAILED(hr, "Could not obtain list of descriptors")
ComPtr<IGattDescriptorsResult> descResult;
- hr = QWinRTFunctions::await(descAsyncOp, descResult.GetAddressOf());
+ hr = QWinRTFunctions::await(descAsyncOp, descResult.GetAddressOf(),
+ QWinRTFunctions::ProcessMainThreadEvents, 5000,
+ exitCondition);
DEC_CHAR_COUNT_AND_CONTINUE_IF_FAILED(hr, "Could not obtain descriptor read result")
quint16 handle;
@@ -247,7 +255,9 @@ public slots:
&readOp);
DEC_CHAR_COUNT_AND_CONTINUE_IF_FAILED(hr, "Could not read characteristic")
ComPtr<IGattReadResult> readResult;
- hr = QWinRTFunctions::await(readOp, readResult.GetAddressOf());
+ hr = QWinRTFunctions::await(readOp, readResult.GetAddressOf(),
+ QWinRTFunctions::ProcessMainThreadEvents, 5000,
+ exitCondition);
DEC_CHAR_COUNT_AND_CONTINUE_IF_FAILED(hr,
"Could not obtain characteristic read result")
if (!readResult)
@@ -273,7 +283,7 @@ public slots:
uint descriptorCount;
hr = descriptors->get_Size(&descriptorCount);
DEC_CHAR_COUNT_AND_CONTINUE_IF_FAILED(hr, "Could not obtain list of descriptors' size")
- for (uint j = 0; j < descriptorCount; ++j) {
+ for (uint j = 0; !mAbortRequested && (j < descriptorCount); ++j) {
QLowEnergyServicePrivate::DescData descData;
ComPtr<IGattDescriptor> descriptor;
hr = descriptors->GetAt(j, &descriptor);
@@ -293,7 +303,9 @@ public slots:
&readOp);
WARN_AND_CONTINUE_IF_FAILED(hr, "Could not read descriptor value")
ComPtr<IClientCharConfigDescriptorResult> readResult;
- hr = QWinRTFunctions::await(readOp, readResult.GetAddressOf());
+ hr = QWinRTFunctions::await(readOp, readResult.GetAddressOf(),
+ QWinRTFunctions::ProcessMainThreadEvents, 5000,
+ exitCondition);
WARN_AND_CONTINUE_IF_FAILED(hr, "Could not await descriptor read result")
GattClientCharacteristicConfigurationDescriptorValue value;
hr = readResult->get_ClientCharacteristicConfigurationDescriptor(&value);
@@ -325,8 +337,10 @@ public slots:
&readOp);
WARN_AND_CONTINUE_IF_FAILED(hr, "Could not read descriptor value")
ComPtr<IGattReadResult> readResult;
- hr = QWinRTFunctions::await(readOp, readResult.GetAddressOf());
- WARN_AND_CONTINUE_IF_FAILED(hr, "Could await descriptor read result")
+ hr = QWinRTFunctions::await(readOp, readResult.GetAddressOf(),
+ QWinRTFunctions::ProcessMainThreadEvents, 5000,
+ exitCondition);
+ WARN_AND_CONTINUE_IF_FAILED(hr, "Could not await descriptor read result")
if (descData.uuid == QBluetoothUuid::DescriptorType::CharacteristicUserDescription)
descData.value = byteArrayFromGattResult(readResult, true);
else
@@ -342,8 +356,13 @@ public slots:
checkAllCharacteristicsDiscovered();
}
+ void setAbortRequested()
+ {
+ mAbortRequested = true;
+ }
+
private:
- bool checkAllCharacteristicsDiscovered();
+ void checkAllCharacteristicsDiscovered();
void emitErrorAndQuitThread(HRESULT hr);
void emitErrorAndQuitThread(const QString &error);
@@ -356,6 +375,7 @@ public:
quint16 mStartHandle = 0;
quint16 mEndHandle = 0;
QList<QBluetoothUuid> mIndicateChars;
+ bool mAbortRequested = false;
signals:
void charListObtained(const QBluetoothUuid &service,
@@ -365,16 +385,13 @@ signals:
void errorOccured(const QString &error);
};
-bool QWinRTLowEnergyServiceHandler::checkAllCharacteristicsDiscovered()
+void QWinRTLowEnergyServiceHandler::checkAllCharacteristicsDiscovered()
{
- if (mCharacteristicsCountToBeDiscovered == 0) {
+ if (!mAbortRequested && (mCharacteristicsCountToBeDiscovered == 0)) {
emit charListObtained(mService, mCharacteristicList, mIndicateChars,
mStartHandle, mEndHandle);
- QThread::currentThread()->quit();
- return true;
}
-
- return false;
+ QThread::currentThread()->quit();
}
void QWinRTLowEnergyServiceHandler::emitErrorAndQuitThread(HRESULT hr)
@@ -384,6 +401,7 @@ void QWinRTLowEnergyServiceHandler::emitErrorAndQuitThread(HRESULT hr)
void QWinRTLowEnergyServiceHandler::emitErrorAndQuitThread(const QString &error)
{
+ mAbortRequested = true; // so that the service is closed during cleanup
emit errorOccured(error);
QThread::currentThread()->quit();
}
@@ -1175,6 +1193,12 @@ HRESULT QLowEnergyControllerPrivateWinRT::onServiceDiscoveryFinished(ABI::Window
void QLowEnergyControllerPrivateWinRT::clearAllServices()
{
+ // These services will be closed in the respective
+ // QWinRTLowEnergyServiceHandler workers (in background threads).
+ for (auto &uuid : m_requestDetailsServiceUuids)
+ m_openedServices.remove(uuid);
+ m_requestDetailsServiceUuids.clear();
+
for (auto service : m_openedServices) {
closeDeviceService(service);
}
@@ -1312,11 +1336,14 @@ void QLowEnergyControllerPrivateWinRT::discoverServiceDetailsHelper(
QWinRTLowEnergyServiceHandler *worker =
new QWinRTLowEnergyServiceHandler(service, deviceService3, mode);
+ m_requestDetailsServiceUuids.insert(service);
QThread *thread = new QThread;
worker->moveToThread(thread);
connect(thread, &QThread::started, worker, &QWinRTLowEnergyServiceHandler::obtainCharList);
connect(thread, &QThread::finished, worker, &QObject::deleteLater);
connect(worker, &QObject::destroyed, thread, &QObject::deleteLater);
+ connect(this, &QLowEnergyControllerPrivateWinRT::abortConnection,
+ worker, &QWinRTLowEnergyServiceHandler::setAbortRequested);
connect(worker, &QWinRTLowEnergyServiceHandler::errorOccured,
this, &QLowEnergyControllerPrivateWinRT::handleServiceHandlerError);
connect(worker, &QWinRTLowEnergyServiceHandler::charListObtained, this,
@@ -1328,6 +1355,7 @@ void QLowEnergyControllerPrivateWinRT::discoverServiceDetailsHelper(
<< "Discovery complete for unknown service:" << service.toString();
return;
}
+ m_requestDetailsServiceUuids.remove(service);
QSharedPointer<QLowEnergyServicePrivate> pointer = serviceList.value(service);
pointer->startHandle = startHandle;
diff --git a/src/bluetooth/qlowenergycontroller_winrt_p.h b/src/bluetooth/qlowenergycontroller_winrt_p.h
index 984e2e77..e1806d6c 100644
--- a/src/bluetooth/qlowenergycontroller_winrt_p.h
+++ b/src/bluetooth/qlowenergycontroller_winrt_p.h
@@ -162,6 +162,7 @@ private:
using GattDeviceServiceComPtr = Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattDeviceService>;
QMap<QBluetoothUuid, GattDeviceServiceComPtr> m_openedServices;
+ QSet<QBluetoothUuid> m_requestDetailsServiceUuids;
using NativeServiceCallback = std::function<void(GattDeviceServiceComPtr)>;
HRESULT getNativeService(const QBluetoothUuid &serviceUuid, NativeServiceCallback callback);
diff --git a/src/tools/sdpscanner/main.cpp b/src/tools/sdpscanner/main.cpp
index 7e09ca6e..c39ff8f3 100644
--- a/src/tools/sdpscanner/main.cpp
+++ b/src/tools/sdpscanner/main.cpp
@@ -39,6 +39,7 @@
#include <QtCore/QByteArray>
#include <QtCore/QDebug>
+#include <QtCore/QUrl>
#include <stdio.h>
#include <string>
#include <bluetooth/bluetooth.h>
@@ -159,7 +160,9 @@ static void parseAttributeValues(sdp_data_t *data, int indentation, QByteArray &
break;
} else if (!isprint(text[i])) {
hasNonPrintableChar = true;
- text.resize(text.indexOf('\0')); // cut trailing content
+ const auto firstNullIdx = text.indexOf('\0');
+ if (firstNullIdx > 0)
+ text.resize(firstNullIdx); // cut trailing content
break;
}
}
@@ -211,11 +214,17 @@ static void parseAttributeValues(sdp_data_t *data, int indentation, QByteArray &
case SDP_URL_STR8:
case SDP_URL_STR16:
case SDP_URL_STR32:
- strncpy(snBuffer, data->val.str, data->unitSize - 1);
+ {
xmlOutput.append("<url value=\"");
- xmlOutput.append(snBuffer);
+ const QByteArray urlData =
+ QByteArray::fromRawData(data->val.str, qstrnlen(data->val.str, data->unitSize));
+ const QUrl url = QUrl::fromEncoded(urlData);
+ // Encoded url %-encodes all of the XML special characters except '&',
+ // so we need to do that manually
+ xmlOutput.append(url.toEncoded().replace('&', "&amp;"));
xmlOutput.append("\"/>\n");
break;
+ }
default:
fprintf(stderr, "Unknown dtd type\n");
}