From 98a7d7cac2be779befd12396a531d29a316ef804 Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Wed, 16 Jul 2014 21:00:56 +0400 Subject: Add a stub modules to compile on Windows It is the first commit which prepares possibility of build for Windows; still there is no Windows-specific implementation of bluetooth classes. Tested build with Qt5 (MinGW). Change-Id: I70d8c5cff4ac4e8b9192ab8556d81aad8432394a Reviewed-by: Alex Blasche --- .../qbluetoothservicediscoveryagent_win.cpp | 68 ++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/bluetooth/qbluetoothservicediscoveryagent_win.cpp (limited to 'src/bluetooth/qbluetoothservicediscoveryagent_win.cpp') diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp new file mode 100644 index 00000000..86874a6c --- /dev/null +++ b/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbluetoothservicediscoveryagent.h" +#include "qbluetoothservicediscoveryagent_p.h" + +QT_BEGIN_NAMESPACE + +QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate(const QBluetoothAddress &deviceAdapter) + : error(QBluetoothServiceDiscoveryAgent::NoError), state(Inactive), + deviceDiscoveryAgent(0), mode(QBluetoothServiceDiscoveryAgent::MinimalDiscovery), + singleDevice(false) +{ + Q_UNUSED(deviceAdapter); +} + +QBluetoothServiceDiscoveryAgentPrivate::~QBluetoothServiceDiscoveryAgentPrivate() +{ +} + +void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &address) +{ + Q_UNUSED(address); +} + +void QBluetoothServiceDiscoveryAgentPrivate::stop() +{ +} + +QT_END_NAMESPACE -- cgit v1.2.3 From e9be1330bad04c6afbc6894b621b68f3b32b696b Mon Sep 17 00:00:00 2001 From: Alex Blasche Date: Fri, 27 Feb 2015 10:56:30 +0100 Subject: Update Digia headers to QtCompany headers Change-Id: I07b67d4bd879994a480a70f4776d68256f51d736 Reviewed-by: Denis Shienkov Reviewed-by: Alex Blasche --- .../qbluetoothservicediscoveryagent_win.cpp | 38 +++++++++------------- 1 file changed, 15 insertions(+), 23 deletions(-) (limited to 'src/bluetooth/qbluetoothservicediscoveryagent_win.cpp') diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp index 86874a6c..738fe739 100644 --- a/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp +++ b/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp @@ -1,40 +1,32 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtBluetooth module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL$ +** $QT_BEGIN_LICENSE:LGPL21$ ** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** ** $QT_END_LICENSE$ ** ****************************************************************************/ -- cgit v1.2.3 From 3e6f15d111984536b0299a8b47caf0779ea52730 Mon Sep 17 00:00:00 2001 From: Eric Lemanissier Date: Thu, 22 Oct 2015 16:39:10 +0200 Subject: Bluetooth - service discovery on Windows Based on previous change by Philip Schuchardt Change-Id: If27e1fce63f2a832d19965219f1a5567f76ab770 Reviewed-by: Alex Blasche --- .../qbluetoothservicediscoveryagent_win.cpp | 377 ++++++++++++++++++++- 1 file changed, 373 insertions(+), 4 deletions(-) (limited to 'src/bluetooth/qbluetoothservicediscoveryagent_win.cpp') diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp index 738fe739..4e8bdac0 100644 --- a/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp +++ b/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp @@ -34,27 +34,396 @@ #include "qbluetoothservicediscoveryagent.h" #include "qbluetoothservicediscoveryagent_p.h" +#include +#include + +#include +#include +#include +#include +#include + +Q_GLOBAL_STATIC(QLibrary, bluetoothapis) + +#define DEFINEFUNC(ret, func, ...) \ + typedef ret (WINAPI *fp_##func)(__VA_ARGS__); \ + static fp_##func p##func; + +#define RESOLVEFUNC(func) \ + p##func = (fp_##func)resolveFunction(library, #func); \ + if (!p##func) \ + return false; + +DEFINEFUNC(DWORD, BluetoothSdpGetElementData, LPBYTE, ULONG, PSDP_ELEMENT_DATA) + QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINDOWS) + +static inline QFunctionPointer resolveFunction(QLibrary *library, const char *func) +{ + QFunctionPointer symbolFunctionPointer = library->resolve(func); + if (!symbolFunctionPointer) + qWarning("Cannot resolve '%s' in '%s'.", func, qPrintable(library->fileName())); + return symbolFunctionPointer; +} + +static inline bool resolveFunctions(QLibrary *library) +{ + if (!library->isLoaded()) { + library->setFileName(QStringLiteral("bluetoothapis")); + if (!library->load()) { + qWarning("Unable to load '%s' library.", qPrintable(library->fileName())); + return false; + } + } + + RESOLVEFUNC(BluetoothSdpGetElementData) + + return true; +} + +static QList spdContainerToVariantList(LPBYTE containerStream, ULONG containerLength); + +static QVariant spdElementToVariant(const SDP_ELEMENT_DATA &element) +{ + QVariant variant; + + switch (element.type) { + case SDP_TYPE_UINT: { + switch (element.specificType) { + case SDP_ST_UINT128: + //Not supported!!! + break; + case SDP_ST_UINT64: + variant = QVariant::fromValue(element.data.uint64); + break; + case SDP_ST_UINT32: + variant = QVariant::fromValue(element.data.uint32); + break; + case SDP_ST_UINT16: + variant = QVariant::fromValue(element.data.uint16); + break; + case SDP_ST_UINT8: + variant = QVariant::fromValue(element.data.uint8); + break; + default: + break; + } + break; + } + case SDP_TYPE_INT: { + switch (element.specificType) { + case SDP_ST_INT128: { + //Not supported!!! + break; + } + case SDP_ST_INT64: + variant = QVariant::fromValue(element.data.int64); + break; + case SDP_ST_INT32: + variant = QVariant::fromValue(element.data.int32); + break; + case SDP_ST_INT16: + variant = QVariant::fromValue(element.data.int16); + break; + case SDP_ST_INT8: + variant = QVariant::fromValue(element.data.int8); + break; + default: + break; + } + break; + } + case SDP_TYPE_UUID: { + switch (element.specificType) { + case SDP_ST_UUID128: { + //Not sure if this will work, might be evil + Q_ASSERT(sizeof(element.data.uuid128) == sizeof(quint128)); + + quint128 uuid128; + memcpy(&uuid128, &(element.data.uuid128), sizeof(quint128)); + + variant = QVariant::fromValue(QBluetoothUuid(uuid128)); + } + case SDP_ST_UUID32: + variant = QVariant::fromValue(QBluetoothUuid(quint32(element.data.uuid32))); + case SDP_ST_UUID16: + variant = QVariant::fromValue(QBluetoothUuid(quint16(element.data.uuid16))); + default: + break; + } + break; + } + case SDP_TYPE_STRING: { + QByteArray stringBuffer(reinterpret_cast(element.data.string.value), element.data.string.length); + variant = QVariant::fromValue(QString::fromLocal8Bit(stringBuffer)); + break; + } + case SDP_TYPE_URL: { + QString urlString = QString::fromLocal8Bit(reinterpret_cast(element.data.url.value), + (int)element.data.url.length); + QUrl url(urlString); + if (url.isValid()) + variant = QVariant::fromValue(url); + break; + } + case SDP_TYPE_SEQUENCE: { + QList sequenceList = spdContainerToVariantList(element.data.sequence.value, + element.data.sequence.length); + QBluetoothServiceInfo::Sequence sequence(sequenceList); + variant = QVariant::fromValue(sequence); + break; + } + case SDP_TYPE_ALTERNATIVE: { + QList alternativeList = spdContainerToVariantList(element.data.alternative.value, + element.data.alternative.length); + QBluetoothServiceInfo::Alternative alternative(alternativeList); + variant = QVariant::fromValue(alternative); + break; + } + case SDP_TYPE_BOOLEAN: + variant = QVariant::fromValue((bool)element.data.booleanVal); + break; + case SDP_TYPE_NIL: + break; + default: + break; + } + + return variant; +} + +static QList spdContainerToVariantList(LPBYTE containerStream, ULONG containerLength) +{ + HBLUETOOTH_CONTAINER_ELEMENT iter = NULL; + SDP_ELEMENT_DATA element; + + QList sequence; + + forever { + DWORD result = BluetoothSdpGetContainerElementData(containerStream, + containerLength, + &iter, + &element); + + if (result == ERROR_SUCCESS) { + const QVariant variant = spdElementToVariant(element); + sequence.append(variant); + } else if (result == ERROR_NO_MORE_ITEMS) { + break; + } else if (result == ERROR_INVALID_PARAMETER) { + break; + } + } + + return sequence; +} + +#if defined(Q_CC_MINGW) +# define SDP_CALLBACK +#else +# define SDP_CALLBACK QT_WIN_CALLBACK +#endif +static BOOL SDP_CALLBACK bluetoothSdpCallback(ULONG attributeId, LPBYTE valueStream, ULONG streamSize, LPVOID param) +{ + QBluetoothServiceInfo *result = static_cast(param); + + SDP_ELEMENT_DATA element; + + if (pBluetoothSdpGetElementData(valueStream, streamSize, &element) == ERROR_SUCCESS) + switch (element.type) { + case SDP_TYPE_UINT: + case SDP_TYPE_INT: + case SDP_TYPE_UUID: + case SDP_TYPE_STRING: + case SDP_TYPE_URL: + case SDP_TYPE_BOOLEAN: + case SDP_TYPE_SEQUENCE: + case SDP_TYPE_ALTERNATIVE: { + const QVariant variant = spdElementToVariant(element); + result->setAttribute(attributeId, variant); + break; + } + case SDP_TYPE_NIL: + break; + default: + break; + } + + return true; +} + +static void cleanupServiceDiscovery(HANDLE hSearch) +{ + if (hSearch != INVALID_HANDLE_VALUE) + WSALookupServiceEnd(hSearch); + WSACleanup(); +} + +enum { + WSAControlFlags = LUP_FLUSHCACHE + | LUP_RETURN_NAME + | LUP_RETURN_TYPE + | LUP_RETURN_ADDR + | LUP_RETURN_BLOB + | LUP_RETURN_COMMENT +}; + +static QBluetoothServiceInfo findNextService(HANDLE hSearch, int *systemError) +{ + QBluetoothServiceInfo result; + + QByteArray resultBuffer(2048, 0); + WSAQUERYSET *resultQuery = reinterpret_cast(resultBuffer.data()); + DWORD resultBufferSize = DWORD(resultBuffer.size()); + const int resultCode = WSALookupServiceNext(hSearch, + WSAControlFlags, + &resultBufferSize, + resultQuery); + + if (resultCode == SOCKET_ERROR) { + *systemError = ::WSAGetLastError(); + if (*systemError == WSA_E_NO_MORE) + cleanupServiceDiscovery(hSearch); + return QBluetoothServiceInfo(); + } + + if (resultQuery->lpBlob + && BluetoothSdpEnumAttributes(resultQuery->lpBlob->pBlobData, + resultQuery->lpBlob->cbSize, + bluetoothSdpCallback, + &result)) { + return result; + } else { + *systemError = GetLastError(); + } + + return result; +} + +static QBluetoothServiceInfo findFirstService(LPHANDLE hSearch, const QBluetoothAddress &address, int *systemError) +{ + //### should we try for 2.2 on all platforms ?? + WSAData wsadata; + + // IPv6 requires Winsock v2.0 or better. + if (WSAStartup(MAKEWORD(2, 0), &wsadata) != 0) { + *systemError = ::WSAGetLastError(); + return QBluetoothServiceInfo(); + } + + const QString addressAsString = QStringLiteral("(%1)").arg(address.toString()); + + QVector addressAsWChar(addressAsString.size()); + addressAsString.toWCharArray(addressAsWChar.data()); + + GUID protocol = L2CAP_PROTOCOL_UUID; //Search for L2CAP and RFCOMM services + + WSAQUERYSET serviceQuery; + ::ZeroMemory(&serviceQuery, sizeof(serviceQuery)); + serviceQuery.dwSize = sizeof(WSAQUERYSET); //As specified by the windows documentation + serviceQuery.lpServiceClassId = &protocol; //The protocal of the service what is being queried + serviceQuery.dwNameSpace = NS_BTH; //As specified by the windows documentation + serviceQuery.dwNumberOfCsAddrs = 0; //As specified by the windows documentation + serviceQuery.lpszContext = addressAsWChar.data(); //The remote address that query will run on + + const int resultCode = WSALookupServiceBegin(&serviceQuery, + WSAControlFlags, + hSearch); + if (resultCode == SOCKET_ERROR) { + *systemError = ::WSAGetLastError(); + cleanupServiceDiscovery(hSearch); + return QBluetoothServiceInfo(); + } + *systemError = NO_ERROR; + return findNextService(*hSearch, systemError); +} + QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate(const QBluetoothAddress &deviceAdapter) - : error(QBluetoothServiceDiscoveryAgent::NoError), state(Inactive), - deviceDiscoveryAgent(0), mode(QBluetoothServiceDiscoveryAgent::MinimalDiscovery), - singleDevice(false) + : error(QBluetoothServiceDiscoveryAgent::NoError), + state(Inactive), + deviceDiscoveryAgent(0), + mode(QBluetoothServiceDiscoveryAgent::MinimalDiscovery), + singleDevice(false), + systemError(NO_ERROR), + pendingStop(false), + pendingFinish(false), + searchWatcher(Q_NULLPTR), + hSearch(INVALID_HANDLE_VALUE) { Q_UNUSED(deviceAdapter); + resolveFunctions(bluetoothapis()); + searchWatcher = new QFutureWatcher(); } QBluetoothServiceDiscoveryAgentPrivate::~QBluetoothServiceDiscoveryAgentPrivate() { + if (pendingFinish) { + stop(); + searchWatcher->waitForFinished(); + } + delete searchWatcher; } void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &address) { - Q_UNUSED(address); + Q_Q(QBluetoothServiceDiscoveryAgent); + if (!pendingFinish) { + pendingFinish = true; + pendingStop = false; + + QObject::connect(searchWatcher, SIGNAL(finished()), q, SLOT(_q_nextSdpScan()), Qt::UniqueConnection); + const QFuture future = + QtConcurrent::run(&findFirstService, + &hSearch, + address, + &systemError); + searchWatcher->setFuture(future); + } } void QBluetoothServiceDiscoveryAgentPrivate::stop() { + pendingStop = true; +} + +void QBluetoothServiceDiscoveryAgentPrivate::_q_nextSdpScan() +{ + Q_Q(QBluetoothServiceDiscoveryAgent); + + if (pendingStop) { + pendingStop = false; + pendingFinish = false; + emit q->canceled(); + } else { + if (systemError == WSA_E_NO_MORE) { + systemError = NO_ERROR; + } else if (systemError != NO_ERROR) { + error = (systemError == ERROR_INVALID_HANDLE) ? + QBluetoothServiceDiscoveryAgent::InvalidBluetoothAdapterError + : QBluetoothServiceDiscoveryAgent::InputOutputError; + errorString = qt_error_string(systemError); + qCWarning(QT_BT_WINDOWS) << errorString; + emit q->error(this->error); + } else { + QBluetoothServiceInfo serviceInfo = searchWatcher->result(); + serviceInfo.setDevice(discoveredDevices.at(0)); + if (serviceInfo.isValid()) { + if (!isDuplicatedService(serviceInfo)) { + discoveredServices.append(serviceInfo); + emit q->serviceDiscovered(serviceInfo); + } + } + const QFuture future = + QtConcurrent::run(&findNextService, hSearch, &systemError); + searchWatcher->setFuture(future); + return; + } + hSearch = INVALID_HANDLE_VALUE; + pendingFinish = false; + _q_serviceDiscoveryFinished(); + } } QT_END_NAMESPACE -- cgit v1.2.3 From 78e0a1c6a5823a76bb85f04724dd4b1df80a8c44 Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Thu, 1 Jun 2017 16:36:30 +0300 Subject: Replace 'forever' macro with 'for (;;)' statement Change-Id: I402b856be06db0e55ec2efb21fc6cb8f35e57a0c Reviewed-by: Oliver Wolff --- src/bluetooth/qbluetoothservicediscoveryagent_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bluetooth/qbluetoothservicediscoveryagent_win.cpp') diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp index b92025ee..6e9dab96 100644 --- a/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp +++ b/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp @@ -201,7 +201,7 @@ static QList spdContainerToVariantList(LPBYTE containerStream, ULONG c QList sequence; - forever { + for (;;) { DWORD result = BluetoothSdpGetContainerElementData(containerStream, containerLength, &iter, -- cgit v1.2.3 From c38583ec73e8490b6373e9ac42503d41b4f28665 Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Thu, 1 Jun 2017 17:06:24 +0300 Subject: Use 'const' keyword a bit more Change-Id: If735ef8abf793fed46c43f692d413e76013a899e Reviewed-by: Oliver Wolff Reviewed-by: Alex Blasche --- src/bluetooth/qbluetoothservicediscoveryagent_win.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src/bluetooth/qbluetoothservicediscoveryagent_win.cpp') diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp index 6e9dab96..e8df3ebe 100644 --- a/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp +++ b/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp @@ -62,7 +62,7 @@ Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINDOWS) static inline QFunctionPointer resolveFunction(QLibrary *library, const char *func) { - QFunctionPointer symbolFunctionPointer = library->resolve(func); + const QFunctionPointer symbolFunctionPointer = library->resolve(func); if (!symbolFunctionPointer) qWarning("Cannot resolve '%s' in '%s'.", func, qPrintable(library->fileName())); return symbolFunctionPointer; @@ -156,29 +156,29 @@ static QVariant spdElementToVariant(const SDP_ELEMENT_DATA &element) break; } case SDP_TYPE_STRING: { - QByteArray stringBuffer(reinterpret_cast(element.data.string.value), element.data.string.length); + const QByteArray stringBuffer(reinterpret_cast(element.data.string.value), element.data.string.length); variant = QVariant::fromValue(QString::fromLocal8Bit(stringBuffer)); break; } case SDP_TYPE_URL: { - QString urlString = QString::fromLocal8Bit(reinterpret_cast(element.data.url.value), + const QString urlString = QString::fromLocal8Bit(reinterpret_cast(element.data.url.value), (int)element.data.url.length); - QUrl url(urlString); + const QUrl url(urlString); if (url.isValid()) variant = QVariant::fromValue(url); break; } case SDP_TYPE_SEQUENCE: { - QList sequenceList = spdContainerToVariantList(element.data.sequence.value, + const QList sequenceList = spdContainerToVariantList(element.data.sequence.value, element.data.sequence.length); - QBluetoothServiceInfo::Sequence sequence(sequenceList); + const QBluetoothServiceInfo::Sequence sequence(sequenceList); variant = QVariant::fromValue(sequence); break; } case SDP_TYPE_ALTERNATIVE: { - QList alternativeList = spdContainerToVariantList(element.data.alternative.value, + const QList alternativeList = spdContainerToVariantList(element.data.alternative.value, element.data.alternative.length); - QBluetoothServiceInfo::Alternative alternative(alternativeList); + const QBluetoothServiceInfo::Alternative alternative(alternativeList); variant = QVariant::fromValue(alternative); break; } @@ -202,7 +202,7 @@ static QList spdContainerToVariantList(LPBYTE containerStream, ULONG c QList sequence; for (;;) { - DWORD result = BluetoothSdpGetContainerElementData(containerStream, + const DWORD result = BluetoothSdpGetContainerElementData(containerStream, containerLength, &iter, &element); -- cgit v1.2.3 From e78eb675e89fba8d6a518b7a9f02dd3086f6f52a Mon Sep 17 00:00:00 2001 From: "Lubomir I. Ivanov (VMware)" Date: Mon, 19 Feb 2018 20:17:14 +0200 Subject: Update license information for Windows files Change-Id: Iec42df246c5faec4260bbeb0dbf806477530d30f Reviewed-by: Alex Blasche --- .../qbluetoothservicediscoveryagent_win.cpp | 34 +++++++++++++--------- 1 file changed, 20 insertions(+), 14 deletions(-) (limited to 'src/bluetooth/qbluetoothservicediscoveryagent_win.cpp') diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp index e8df3ebe..cae7968b 100644 --- a/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp +++ b/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2018 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:LGPL21$ +** $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 http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** 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 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** 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. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** 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$ ** -- cgit v1.2.3 From 3a90cf6d46dc6f34ccedb7f02515573d1db4704a Mon Sep 17 00:00:00 2001 From: "Lubomir I. Ivanov (VMware)" Date: Wed, 30 May 2018 00:49:58 +0200 Subject: win32: remove usage of QFuture in qbluetoothservicediscoveryagent Introduce usage of QThread for service discovery instead of QFuture. Details: - Make _q_nextSdpScan() accept arguments. - Make QBluetoothServiceDiscoveryAgentPrivate inherit QObject for QT_WIN_BLUETOOTH. - Remove usage of the member variables 'systemError', 'hSearch'. Pass values around, instead. - Add the helper structs 'FindServiceArguments' and 'FindServiceResult'. Change-Id: I4e2178b2a7b333c30a235a02807dd64526db4685 Reviewed-by: Oliver Wolff Reviewed-by: Alex Blasche --- .../qbluetoothservicediscoveryagent_win.cpp | 137 +++++++++++++-------- 1 file changed, 89 insertions(+), 48 deletions(-) (limited to 'src/bluetooth/qbluetoothservicediscoveryagent_win.cpp') diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp index cae7968b..8ee0f663 100644 --- a/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp +++ b/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp @@ -41,7 +41,10 @@ #include "qbluetoothservicediscoveryagent_p.h" #include -#include +#include +#include +#include +#include #include #include @@ -64,6 +67,18 @@ DEFINEFUNC(DWORD, BluetoothSdpGetElementData, LPBYTE, ULONG, PSDP_ELEMENT_DATA) QT_BEGIN_NAMESPACE +struct FindServiceArguments { + QBluetoothAddress address; + Qt::HANDLE hSearch; + int systemError; +}; + +struct FindServiceResult { + QBluetoothServiceInfo info; + Qt::HANDLE hSearch; + int systemError; +}; + Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINDOWS) static inline QFunctionPointer resolveFunction(QLibrary *library, const char *func) @@ -276,9 +291,11 @@ enum { | LUP_RETURN_COMMENT }; -static QBluetoothServiceInfo findNextService(HANDLE hSearch, int *systemError) +static FindServiceResult findNextService(HANDLE hSearch, int systemError) { - QBluetoothServiceInfo result; + FindServiceResult result; + result.systemError = systemError; + result.hSearch = INVALID_HANDLE_VALUE; QByteArray resultBuffer(2048, 0); WSAQUERYSET *resultQuery = reinterpret_cast(resultBuffer.data()); @@ -289,34 +306,36 @@ static QBluetoothServiceInfo findNextService(HANDLE hSearch, int *systemError) resultQuery); if (resultCode == SOCKET_ERROR) { - *systemError = ::WSAGetLastError(); - if (*systemError == WSA_E_NO_MORE) + result.systemError = ::WSAGetLastError(); + if (result.systemError == WSA_E_NO_MORE) cleanupServiceDiscovery(hSearch); - return QBluetoothServiceInfo(); + return result; } if (resultQuery->lpBlob && BluetoothSdpEnumAttributes(resultQuery->lpBlob->pBlobData, resultQuery->lpBlob->cbSize, bluetoothSdpCallback, - &result)) { + &result.info)) { return result; } else { - *systemError = GetLastError(); + result.systemError = GetLastError(); } - return result; } -static QBluetoothServiceInfo findFirstService(LPHANDLE hSearch, const QBluetoothAddress &address, int *systemError) +static FindServiceResult findFirstService(HANDLE hSearch, const QBluetoothAddress &address) { //### should we try for 2.2 on all platforms ?? WSAData wsadata; + FindServiceResult result; + result.systemError = NO_ERROR; + result.hSearch = INVALID_HANDLE_VALUE; // IPv6 requires Winsock v2.0 or better. if (WSAStartup(MAKEWORD(2, 0), &wsadata) != 0) { - *systemError = ::WSAGetLastError(); - return QBluetoothServiceInfo(); + result.systemError = ::WSAGetLastError(); + return result; } const QString addressAsString = QStringLiteral("(%1)").arg(address.toString()); @@ -336,14 +355,14 @@ static QBluetoothServiceInfo findFirstService(LPHANDLE hSearch, const QBluetooth const int resultCode = WSALookupServiceBegin(&serviceQuery, WSAControlFlags, - hSearch); + &hSearch); if (resultCode == SOCKET_ERROR) { - *systemError = ::WSAGetLastError(); - cleanupServiceDiscovery(hSearch); - return QBluetoothServiceInfo(); + result.systemError = ::WSAGetLastError(); + cleanupServiceDiscovery(&hSearch); + return result; } - *systemError = NO_ERROR; - return findNextService(*hSearch, systemError); + result.systemError = NO_ERROR; + return findNextService(hSearch, result.systemError); } QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate( @@ -353,41 +372,43 @@ QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate( deviceDiscoveryAgent(0), mode(QBluetoothServiceDiscoveryAgent::MinimalDiscovery), singleDevice(false), - systemError(NO_ERROR), pendingStop(false), pendingFinish(false), - searchWatcher(Q_NULLPTR), - hSearch(INVALID_HANDLE_VALUE), q_ptr(qp) { Q_UNUSED(deviceAdapter); + resolveFunctions(bluetoothapis()); - searchWatcher = new QFutureWatcher(); + + threadFind = new QThread; + threadWorkerFind = new ThreadWorkerFind; + threadWorkerFind->moveToThread(threadFind); + connect(threadWorkerFind, &ThreadWorkerFind::findFinished, this, &QBluetoothServiceDiscoveryAgentPrivate::_q_nextSdpScan); + connect(threadFind, &QThread::finished, threadWorkerFind, &ThreadWorkerFind::deleteLater); + connect(threadFind, &QThread::finished, threadFind, &QThread::deleteLater); + threadFind->start(); } QBluetoothServiceDiscoveryAgentPrivate::~QBluetoothServiceDiscoveryAgentPrivate() { if (pendingFinish) { stop(); - searchWatcher->waitForFinished(); } - delete searchWatcher; + if (threadFind) + threadFind->quit(); } void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &address) { - Q_Q(QBluetoothServiceDiscoveryAgent); if (!pendingFinish) { pendingFinish = true; pendingStop = false; - QObject::connect(searchWatcher, SIGNAL(finished()), q, SLOT(_q_nextSdpScan()), Qt::UniqueConnection); - const QFuture future = - QtConcurrent::run(&findFirstService, - &hSearch, - address, - &systemError); - searchWatcher->setFuture(future); + FindServiceArguments data; + data.address = address; + data.hSearch = INVALID_HANDLE_VALUE; + QMetaObject::invokeMethod(threadWorkerFind, "findFirst", Qt::QueuedConnection, + Q_ARG(QVariant, QVariant::fromValue(data))); } } @@ -396,42 +417,62 @@ void QBluetoothServiceDiscoveryAgentPrivate::stop() pendingStop = true; } -void QBluetoothServiceDiscoveryAgentPrivate::_q_nextSdpScan() +void QBluetoothServiceDiscoveryAgentPrivate::_q_nextSdpScan(QVariant input) { Q_Q(QBluetoothServiceDiscoveryAgent); + auto result = input.value(); if (pendingStop) { pendingStop = false; pendingFinish = false; emit q->canceled(); } else { - if (systemError == WSA_E_NO_MORE) { - systemError = NO_ERROR; - } else if (systemError != NO_ERROR) { - error = (systemError == ERROR_INVALID_HANDLE) ? + if (result.systemError == WSA_E_NO_MORE) { + result.systemError = NO_ERROR; + } else if (result.systemError != NO_ERROR) { + error = (result.systemError == ERROR_INVALID_HANDLE) ? QBluetoothServiceDiscoveryAgent::InvalidBluetoothAdapterError : QBluetoothServiceDiscoveryAgent::InputOutputError; - errorString = qt_error_string(systemError); + errorString = qt_error_string(result.systemError); qCWarning(QT_BT_WINDOWS) << errorString; emit q->error(this->error); } else { - QBluetoothServiceInfo serviceInfo = searchWatcher->result(); - serviceInfo.setDevice(discoveredDevices.at(0)); - if (serviceInfo.isValid()) { - if (!isDuplicatedService(serviceInfo)) { - discoveredServices.append(serviceInfo); - emit q->serviceDiscovered(serviceInfo); + result.info.setDevice(discoveredDevices.at(0)); + if (result.info.isValid()) { + if (!isDuplicatedService(result.info)) { + discoveredServices.append(result.info); + emit q->serviceDiscovered(result.info); } } - const QFuture future = - QtConcurrent::run(&findNextService, hSearch, &systemError); - searchWatcher->setFuture(future); + FindServiceArguments data; + data.hSearch = result.hSearch; + data.systemError = result.systemError; + QMetaObject::invokeMethod(threadWorkerFind, "findNext", Qt::QueuedConnection, + Q_ARG(QVariant, QVariant::fromValue(data))); return; } - hSearch = INVALID_HANDLE_VALUE; pendingFinish = false; _q_serviceDiscoveryFinished(); } } +void ThreadWorkerFind::findFirst(const QVariant data) +{ + auto args = data.value(); + FindServiceResult result = findFirstService(args.hSearch, args.address); + result.hSearch = args.hSearch; + emit findFinished(QVariant::fromValue(result)); +} + + void ThreadWorkerFind::findNext(const QVariant data) +{ + auto args = data.value(); + FindServiceResult result = findNextService(args.hSearch, args.systemError); + result.hSearch = args.hSearch; + emit findFinished(QVariant::fromValue(result)); +} + QT_END_NAMESPACE + +Q_DECLARE_METATYPE(FindServiceArguments) +Q_DECLARE_METATYPE(FindServiceResult) -- cgit v1.2.3 From 62efb446b56bc489c998f90e307aa12e72cb6b8e Mon Sep 17 00:00:00 2001 From: Eric Lemanissier Date: Tue, 19 Jun 2018 13:02:39 +0200 Subject: win32: modernize qbluetooth*discoveryagent arguments pass by ref NULL and 0 replaced with nullptr ::ZeroMemory replaced by default initialization range based for loop Change-Id: I393806f19155ee31e4ebe7f33ce22e9d14eafe40 Reviewed-by: Lubomir I. Ivanov Reviewed-by: Oliver Wolff --- src/bluetooth/qbluetoothservicediscoveryagent_win.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/bluetooth/qbluetoothservicediscoveryagent_win.cpp') diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp index 8ee0f663..35ab558e 100644 --- a/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp +++ b/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp @@ -345,8 +345,7 @@ static FindServiceResult findFirstService(HANDLE hSearch, const QBluetoothAddres GUID protocol = L2CAP_PROTOCOL_UUID; //Search for L2CAP and RFCOMM services - WSAQUERYSET serviceQuery; - ::ZeroMemory(&serviceQuery, sizeof(serviceQuery)); + WSAQUERYSET serviceQuery = {0}; serviceQuery.dwSize = sizeof(WSAQUERYSET); //As specified by the windows documentation serviceQuery.lpServiceClassId = &protocol; //The protocal of the service what is being queried serviceQuery.dwNameSpace = NS_BTH; //As specified by the windows documentation @@ -417,7 +416,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::stop() pendingStop = true; } -void QBluetoothServiceDiscoveryAgentPrivate::_q_nextSdpScan(QVariant input) +void QBluetoothServiceDiscoveryAgentPrivate::_q_nextSdpScan(const QVariant &input) { Q_Q(QBluetoothServiceDiscoveryAgent); auto result = input.value(); @@ -456,7 +455,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_nextSdpScan(QVariant input) } } -void ThreadWorkerFind::findFirst(const QVariant data) +void ThreadWorkerFind::findFirst(const QVariant &data) { auto args = data.value(); FindServiceResult result = findFirstService(args.hSearch, args.address); @@ -464,7 +463,7 @@ void ThreadWorkerFind::findFirst(const QVariant data) emit findFinished(QVariant::fromValue(result)); } - void ThreadWorkerFind::findNext(const QVariant data) + void ThreadWorkerFind::findNext(const QVariant &data) { auto args = data.value(); FindServiceResult result = findNextService(args.hSearch, args.systemError); -- cgit v1.2.3 From d6fb710c0a21fb58a73ff580b08d00e783337bfa Mon Sep 17 00:00:00 2001 From: Eric Lemanissier Date: Tue, 19 Jun 2018 13:00:24 +0200 Subject: win32: fix QBluetoothServiceDiscoveryAgent cleanup remove calls to WSACleanup, because it terminates use of the Winsock 2 DLL, including sockets operations. WSALookupServiceEnd only is needed. add missing WSALookupServiceEnd if pendingStop or error remove useless parameters of findFirst/NextService Change-Id: I587987b77c1be8f05a840e4333c31fd79af06ed3 Reviewed-by: Lubomir I. Ivanov Reviewed-by: Oliver Wolff --- .../qbluetoothservicediscoveryagent_win.cpp | 55 +++++++--------------- 1 file changed, 18 insertions(+), 37 deletions(-) (limited to 'src/bluetooth/qbluetoothservicediscoveryagent_win.cpp') diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp index 35ab558e..d4e00c0a 100644 --- a/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp +++ b/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp @@ -67,12 +67,6 @@ DEFINEFUNC(DWORD, BluetoothSdpGetElementData, LPBYTE, ULONG, PSDP_ELEMENT_DATA) QT_BEGIN_NAMESPACE -struct FindServiceArguments { - QBluetoothAddress address; - Qt::HANDLE hSearch; - int systemError; -}; - struct FindServiceResult { QBluetoothServiceInfo info; Qt::HANDLE hSearch; @@ -275,13 +269,6 @@ static BOOL SDP_CALLBACK bluetoothSdpCallback(ULONG attributeId, LPBYTE valueStr return true; } -static void cleanupServiceDiscovery(HANDLE hSearch) -{ - if (hSearch != INVALID_HANDLE_VALUE) - WSALookupServiceEnd(hSearch); - WSACleanup(); -} - enum { WSAControlFlags = LUP_FLUSHCACHE | LUP_RETURN_NAME @@ -291,11 +278,11 @@ enum { | LUP_RETURN_COMMENT }; -static FindServiceResult findNextService(HANDLE hSearch, int systemError) +static FindServiceResult findNextService(HANDLE hSearch) { FindServiceResult result; - result.systemError = systemError; - result.hSearch = INVALID_HANDLE_VALUE; + result.systemError = NO_ERROR; + result.hSearch = hSearch; QByteArray resultBuffer(2048, 0); WSAQUERYSET *resultQuery = reinterpret_cast(resultBuffer.data()); @@ -308,7 +295,7 @@ static FindServiceResult findNextService(HANDLE hSearch, int systemError) if (resultCode == SOCKET_ERROR) { result.systemError = ::WSAGetLastError(); if (result.systemError == WSA_E_NO_MORE) - cleanupServiceDiscovery(hSearch); + WSALookupServiceEnd(hSearch); return result; } @@ -324,12 +311,11 @@ static FindServiceResult findNextService(HANDLE hSearch, int systemError) return result; } -static FindServiceResult findFirstService(HANDLE hSearch, const QBluetoothAddress &address) +static FindServiceResult findFirstService(const QBluetoothAddress &address) { //### should we try for 2.2 on all platforms ?? WSAData wsadata; FindServiceResult result; - result.systemError = NO_ERROR; result.hSearch = INVALID_HANDLE_VALUE; // IPv6 requires Winsock v2.0 or better. @@ -352,16 +338,16 @@ static FindServiceResult findFirstService(HANDLE hSearch, const QBluetoothAddres serviceQuery.dwNumberOfCsAddrs = 0; //As specified by the windows documentation serviceQuery.lpszContext = addressAsWChar.data(); //The remote address that query will run on + HANDLE hSearch; const int resultCode = WSALookupServiceBegin(&serviceQuery, WSAControlFlags, &hSearch); if (resultCode == SOCKET_ERROR) { result.systemError = ::WSAGetLastError(); - cleanupServiceDiscovery(&hSearch); + WSALookupServiceEnd(hSearch); return result; } - result.systemError = NO_ERROR; - return findNextService(hSearch, result.systemError); + return findNextService(hSearch); } QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate( @@ -403,11 +389,8 @@ void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &addr pendingFinish = true; pendingStop = false; - FindServiceArguments data; - data.address = address; - data.hSearch = INVALID_HANDLE_VALUE; QMetaObject::invokeMethod(threadWorkerFind, "findFirst", Qt::QueuedConnection, - Q_ARG(QVariant, QVariant::fromValue(data))); + Q_ARG(QVariant, QVariant::fromValue(address))); } } @@ -422,6 +405,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_nextSdpScan(const QVariant &inpu auto result = input.value(); if (pendingStop) { + WSALookupServiceEnd(result.hSearch); pendingStop = false; pendingFinish = false; emit q->canceled(); @@ -429,6 +413,8 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_nextSdpScan(const QVariant &inpu if (result.systemError == WSA_E_NO_MORE) { result.systemError = NO_ERROR; } else if (result.systemError != NO_ERROR) { + if (result.hSearch != INVALID_HANDLE_VALUE) + WSALookupServiceEnd(result.hSearch); error = (result.systemError == ERROR_INVALID_HANDLE) ? QBluetoothServiceDiscoveryAgent::InvalidBluetoothAdapterError : QBluetoothServiceDiscoveryAgent::InputOutputError; @@ -443,11 +429,8 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_nextSdpScan(const QVariant &inpu emit q->serviceDiscovered(result.info); } } - FindServiceArguments data; - data.hSearch = result.hSearch; - data.systemError = result.systemError; QMetaObject::invokeMethod(threadWorkerFind, "findNext", Qt::QueuedConnection, - Q_ARG(QVariant, QVariant::fromValue(data))); + Q_ARG(QVariant, QVariant::fromValue(result.hSearch))); return; } pendingFinish = false; @@ -457,21 +440,19 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_nextSdpScan(const QVariant &inpu void ThreadWorkerFind::findFirst(const QVariant &data) { - auto args = data.value(); - FindServiceResult result = findFirstService(args.hSearch, args.address); - result.hSearch = args.hSearch; + auto address = data.value(); + FindServiceResult result = findFirstService(address); emit findFinished(QVariant::fromValue(result)); } void ThreadWorkerFind::findNext(const QVariant &data) { - auto args = data.value(); - FindServiceResult result = findNextService(args.hSearch, args.systemError); - result.hSearch = args.hSearch; + auto hSearch = data.value(); + FindServiceResult result = findNextService(hSearch); emit findFinished(QVariant::fromValue(result)); } QT_END_NAMESPACE -Q_DECLARE_METATYPE(FindServiceArguments) +Q_DECLARE_METATYPE(Qt::HANDLE) Q_DECLARE_METATYPE(FindServiceResult) -- cgit v1.2.3 From f1e305a362c759b0781b6dde3dce5f649b47017c Mon Sep 17 00:00:00 2001 From: Eric Lemanissier Date: Tue, 19 Jun 2018 13:24:41 +0200 Subject: win32: inline unnecessary functions in qbluetooth*discoveryagent by migrating to templated QMetaObject::invokeMethod Change-Id: I79e2dec7aa81987894a26859648d31da60cf47ee Reviewed-by: Lubomir I. Ivanov Reviewed-by: Alex Blasche --- .../qbluetoothservicediscoveryagent_win.cpp | 32 +++++++++------------- 1 file changed, 13 insertions(+), 19 deletions(-) (limited to 'src/bluetooth/qbluetoothservicediscoveryagent_win.cpp') diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp index d4e00c0a..2c3c6437 100644 --- a/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp +++ b/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp @@ -389,8 +389,12 @@ void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &addr pendingFinish = true; pendingStop = false; - QMetaObject::invokeMethod(threadWorkerFind, "findFirst", Qt::QueuedConnection, - Q_ARG(QVariant, QVariant::fromValue(address))); + const auto threadWorker = threadWorkerFind; + QMetaObject::invokeMethod(threadWorkerFind, [threadWorker, address]() + { + FindServiceResult result = findFirstService(address); + emit threadWorker->findFinished(QVariant::fromValue(result)); + }, Qt::QueuedConnection); } } @@ -429,8 +433,13 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_nextSdpScan(const QVariant &inpu emit q->serviceDiscovered(result.info); } } - QMetaObject::invokeMethod(threadWorkerFind, "findNext", Qt::QueuedConnection, - Q_ARG(QVariant, QVariant::fromValue(result.hSearch))); + const auto threadWorker = threadWorkerFind; + const auto hSearch = result.hSearch; + QMetaObject::invokeMethod(threadWorkerFind, [threadWorker, hSearch]() + { + FindServiceResult result = findNextService(hSearch); + emit threadWorker->findFinished(QVariant::fromValue(result)); + }, Qt::QueuedConnection); return; } pendingFinish = false; @@ -438,21 +447,6 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_nextSdpScan(const QVariant &inpu } } -void ThreadWorkerFind::findFirst(const QVariant &data) -{ - auto address = data.value(); - FindServiceResult result = findFirstService(address); - emit findFinished(QVariant::fromValue(result)); -} - - void ThreadWorkerFind::findNext(const QVariant &data) -{ - auto hSearch = data.value(); - FindServiceResult result = findNextService(hSearch); - emit findFinished(QVariant::fromValue(result)); -} - QT_END_NAMESPACE -Q_DECLARE_METATYPE(Qt::HANDLE) Q_DECLARE_METATYPE(FindServiceResult) -- cgit v1.2.3 From 6cdb8dc9cd8a518d050d08be79938feee7a9bde2 Mon Sep 17 00:00:00 2001 From: "Lubomir I. Ivanov" Date: Sat, 29 Sep 2018 04:10:59 +0300 Subject: qbluetoothservicediscoveryagent_win: use lowercase import The import of "WinSock2.h" fails on MXE environments because cross building from Linux to Windows makes it so that the filesystem is case sensitive. Change-Id: I6d89530f430eb45bf07154cffb5938eb3761ee1e Reviewed-by: Denis Shienkov --- src/bluetooth/qbluetoothservicediscoveryagent_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bluetooth/qbluetoothservicediscoveryagent_win.cpp') diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp index 2c3c6437..e76dd7b6 100644 --- a/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp +++ b/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp @@ -47,7 +47,7 @@ #include #include -#include +#include #include #include #include -- cgit v1.2.3 From 5a2c8a39d76d634161e87b1c55d36cbbcc778289 Mon Sep 17 00:00:00 2001 From: "Lubomir I. Ivanov" Date: Mon, 11 Feb 2019 02:08:53 +0200 Subject: win32-bt: fix warnings related to comparisons and initializers Silence a couple of type of warnings: 1) warning: missing initializer for member '_BLUETOOTH_DEVICE_INFO::Address' [-Wmissing-field-initializers] BLUETOOTH_DEVICE_INFO deviceInfo = {0}; Unlike C, C++ is not happy about this type of initializer Use '{}' instead to init all members to zero or 'NULL' properly. 2) warning: comparison between signed and unsigned integer expressions [-Wsign-compare] if (socket != INVALID_SOCKET) { 'socket' is defined as 'int', while 'INVALID_SOCKET' is derived from 'SOCKET' which is of type UINT. Cast 'socket' to 'SOCKET' before performing the comparison. Change-Id: I9fcbff1c60ae36b8a8fed63382a8ffc0157f4923 Reviewed-by: Oliver Wolff --- src/bluetooth/qbluetoothservicediscoveryagent_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bluetooth/qbluetoothservicediscoveryagent_win.cpp') diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp index e76dd7b6..98ec1952 100644 --- a/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp +++ b/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp @@ -331,7 +331,7 @@ static FindServiceResult findFirstService(const QBluetoothAddress &address) GUID protocol = L2CAP_PROTOCOL_UUID; //Search for L2CAP and RFCOMM services - WSAQUERYSET serviceQuery = {0}; + WSAQUERYSET serviceQuery = {}; serviceQuery.dwSize = sizeof(WSAQUERYSET); //As specified by the windows documentation serviceQuery.lpServiceClassId = &protocol; //The protocal of the service what is being queried serviceQuery.dwNameSpace = NS_BTH; //As specified by the windows documentation -- cgit v1.2.3 From 8b7b52d66f2616040ca4aaae3f2732be96e19ab8 Mon Sep 17 00:00:00 2001 From: Andre de la Rocha Date: Fri, 23 Nov 2018 18:04:40 +0100 Subject: Enable the use of the Win32 Bluetooth backend This change enables the optional use of the Win32-based Bluetooth backend on Windows. By default, the WinRT backend is used, if supported by the platform. The use of the Win32 backend must be selected by the -native-win32-bluetooth configuration option. Task-number: QTBUG-40698 Change-Id: I6904bf077467d826e3ff5ad026ebae5f955f2e37 Reviewed-by: Oliver Wolff Reviewed-by: Alex Blasche --- .../qbluetoothservicediscoveryagent_win.cpp | 157 ++++++++++----------- 1 file changed, 71 insertions(+), 86 deletions(-) (limited to 'src/bluetooth/qbluetoothservicediscoveryagent_win.cpp') diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp index 98ec1952..c34443aa 100644 --- a/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp +++ b/src/bluetooth/qbluetoothservicediscoveryagent_win.cpp @@ -49,55 +49,30 @@ #include #include #include -#include -#include - -Q_GLOBAL_STATIC(QLibrary, bluetoothapis) - -#define DEFINEFUNC(ret, func, ...) \ - typedef ret (WINAPI *fp_##func)(__VA_ARGS__); \ - static fp_##func p##func; -#define RESOLVEFUNC(func) \ - p##func = (fp_##func)resolveFunction(library, #func); \ - if (!p##func) \ - return false; +#if defined(Q_CC_MINGW) +// Workaround for MinGW headers declaring BluetoothSdpGetElementData incorrectly. +# define BluetoothSdpGetElementData _BluetoothSdpGetElementData_notok +# include +# undef BluetoothSdpGetElementData + extern "C" DWORD WINAPI BluetoothSdpGetElementData(LPBYTE, ULONG, PSDP_ELEMENT_DATA); +#else +# include +#endif -DEFINEFUNC(DWORD, BluetoothSdpGetElementData, LPBYTE, ULONG, PSDP_ELEMENT_DATA) +#include +#include QT_BEGIN_NAMESPACE struct FindServiceResult { QBluetoothServiceInfo info; - Qt::HANDLE hSearch; - int systemError; + Qt::HANDLE hSearch = INVALID_HANDLE_VALUE; + int systemError = NO_ERROR; }; Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINDOWS) -static inline QFunctionPointer resolveFunction(QLibrary *library, const char *func) -{ - const QFunctionPointer symbolFunctionPointer = library->resolve(func); - if (!symbolFunctionPointer) - qWarning("Cannot resolve '%s' in '%s'.", func, qPrintable(library->fileName())); - return symbolFunctionPointer; -} - -static inline bool resolveFunctions(QLibrary *library) -{ - if (!library->isLoaded()) { - library->setFileName(QStringLiteral("bluetoothapis")); - if (!library->load()) { - qWarning("Unable to load '%s' library.", qPrintable(library->fileName())); - return false; - } - } - - RESOLVEFUNC(BluetoothSdpGetElementData) - - return true; -} - static QList spdContainerToVariantList(LPBYTE containerStream, ULONG containerLength); static QVariant spdElementToVariant(const SDP_ELEMENT_DATA &element) @@ -152,19 +127,15 @@ static QVariant spdElementToVariant(const SDP_ELEMENT_DATA &element) } case SDP_TYPE_UUID: { switch (element.specificType) { - case SDP_ST_UUID128: { - //Not sure if this will work, might be evil - Q_ASSERT(sizeof(element.data.uuid128) == sizeof(quint128)); - - quint128 uuid128; - memcpy(&uuid128, &(element.data.uuid128), sizeof(quint128)); - - variant = QVariant::fromValue(QBluetoothUuid(uuid128)); - } + case SDP_ST_UUID128: + variant = QVariant::fromValue(QBluetoothUuid(element.data.uuid128)); + break; case SDP_ST_UUID32: variant = QVariant::fromValue(QBluetoothUuid(quint32(element.data.uuid32))); + break; case SDP_ST_UUID16: variant = QVariant::fromValue(QBluetoothUuid(quint16(element.data.uuid16))); + break; default: break; } @@ -177,7 +148,7 @@ static QVariant spdElementToVariant(const SDP_ELEMENT_DATA &element) } case SDP_TYPE_URL: { const QString urlString = QString::fromLocal8Bit(reinterpret_cast(element.data.url.value), - (int)element.data.url.length); + int(element.data.url.length)); const QUrl url(urlString); if (url.isValid()) variant = QVariant::fromValue(url); @@ -198,7 +169,7 @@ static QVariant spdElementToVariant(const SDP_ELEMENT_DATA &element) break; } case SDP_TYPE_BOOLEAN: - variant = QVariant::fromValue((bool)element.data.booleanVal); + variant = QVariant::fromValue(bool(element.data.booleanVal)); break; case SDP_TYPE_NIL: break; @@ -211,13 +182,13 @@ static QVariant spdElementToVariant(const SDP_ELEMENT_DATA &element) static QList spdContainerToVariantList(LPBYTE containerStream, ULONG containerLength) { - HBLUETOOTH_CONTAINER_ELEMENT iter = NULL; - SDP_ELEMENT_DATA element; + HBLUETOOTH_CONTAINER_ELEMENT iter = nullptr; + SDP_ELEMENT_DATA element = {}; QList sequence; for (;;) { - const DWORD result = BluetoothSdpGetContainerElementData(containerStream, + const DWORD result = ::BluetoothSdpGetContainerElementData(containerStream, containerLength, &iter, &element); @@ -244,9 +215,9 @@ static BOOL SDP_CALLBACK bluetoothSdpCallback(ULONG attributeId, LPBYTE valueStr { QBluetoothServiceInfo *result = static_cast(param); - SDP_ELEMENT_DATA element; + SDP_ELEMENT_DATA element = {}; - if (pBluetoothSdpGetElementData(valueStream, streamSize, &element) == ERROR_SUCCESS) + if (::BluetoothSdpGetElementData(valueStream, streamSize, &element) == ERROR_SUCCESS) { switch (element.type) { case SDP_TYPE_UINT: case SDP_TYPE_INT: @@ -257,6 +228,7 @@ static BOOL SDP_CALLBACK bluetoothSdpCallback(ULONG attributeId, LPBYTE valueStr case SDP_TYPE_SEQUENCE: case SDP_TYPE_ALTERNATIVE: { const QVariant variant = spdElementToVariant(element); + result->setAttribute(attributeId, variant); break; } @@ -265,7 +237,7 @@ static BOOL SDP_CALLBACK bluetoothSdpCallback(ULONG attributeId, LPBYTE valueStr default: break; } - + } return true; } @@ -281,13 +253,12 @@ enum { static FindServiceResult findNextService(HANDLE hSearch) { FindServiceResult result; - result.systemError = NO_ERROR; result.hSearch = hSearch; QByteArray resultBuffer(2048, 0); WSAQUERYSET *resultQuery = reinterpret_cast(resultBuffer.data()); DWORD resultBufferSize = DWORD(resultBuffer.size()); - const int resultCode = WSALookupServiceNext(hSearch, + const int resultCode = ::WSALookupServiceNext(hSearch, WSAControlFlags, &resultBufferSize, resultQuery); @@ -295,12 +266,12 @@ static FindServiceResult findNextService(HANDLE hSearch) if (resultCode == SOCKET_ERROR) { result.systemError = ::WSAGetLastError(); if (result.systemError == WSA_E_NO_MORE) - WSALookupServiceEnd(hSearch); + ::WSALookupServiceEnd(hSearch); return result; } if (resultQuery->lpBlob - && BluetoothSdpEnumAttributes(resultQuery->lpBlob->pBlobData, + && ::BluetoothSdpEnumAttributes(resultQuery->lpBlob->pBlobData, resultQuery->lpBlob->cbSize, bluetoothSdpCallback, &result.info)) { @@ -313,38 +284,35 @@ static FindServiceResult findNextService(HANDLE hSearch) static FindServiceResult findFirstService(const QBluetoothAddress &address) { - //### should we try for 2.2 on all platforms ?? - WSAData wsadata; + WSAData wsadata = {}; FindServiceResult result; - result.hSearch = INVALID_HANDLE_VALUE; // IPv6 requires Winsock v2.0 or better. - if (WSAStartup(MAKEWORD(2, 0), &wsadata) != 0) { + if (::WSAStartup(MAKEWORD(2, 0), &wsadata) != 0) { result.systemError = ::WSAGetLastError(); return result; } const QString addressAsString = QStringLiteral("(%1)").arg(address.toString()); - - QVector addressAsWChar(addressAsString.size()); + QVector addressAsWChar(addressAsString.size() + 1); addressAsString.toWCharArray(addressAsWChar.data()); GUID protocol = L2CAP_PROTOCOL_UUID; //Search for L2CAP and RFCOMM services WSAQUERYSET serviceQuery = {}; - serviceQuery.dwSize = sizeof(WSAQUERYSET); //As specified by the windows documentation - serviceQuery.lpServiceClassId = &protocol; //The protocal of the service what is being queried - serviceQuery.dwNameSpace = NS_BTH; //As specified by the windows documentation - serviceQuery.dwNumberOfCsAddrs = 0; //As specified by the windows documentation - serviceQuery.lpszContext = addressAsWChar.data(); //The remote address that query will run on - - HANDLE hSearch; - const int resultCode = WSALookupServiceBegin(&serviceQuery, + serviceQuery.dwSize = sizeof(WSAQUERYSET); + serviceQuery.lpServiceClassId = &protocol; + serviceQuery.dwNameSpace = NS_BTH; + serviceQuery.dwNumberOfCsAddrs = 0; + serviceQuery.lpszContext = addressAsWChar.data(); + + HANDLE hSearch = nullptr; + const int resultCode = ::WSALookupServiceBegin(&serviceQuery, WSAControlFlags, &hSearch); if (resultCode == SOCKET_ERROR) { result.systemError = ::WSAGetLastError(); - WSALookupServiceEnd(hSearch); + ::WSALookupServiceEnd(hSearch); return result; } return findNextService(hSearch); @@ -363,8 +331,6 @@ QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate( { Q_UNUSED(deviceAdapter); - resolveFunctions(bluetoothapis()); - threadFind = new QThread; threadWorkerFind = new ThreadWorkerFind; threadWorkerFind->moveToThread(threadFind); @@ -376,9 +342,8 @@ QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate( QBluetoothServiceDiscoveryAgentPrivate::~QBluetoothServiceDiscoveryAgentPrivate() { - if (pendingFinish) { + if (pendingFinish) stop(); - } if (threadFind) threadFind->quit(); } @@ -392,7 +357,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &addr const auto threadWorker = threadWorkerFind; QMetaObject::invokeMethod(threadWorkerFind, [threadWorker, address]() { - FindServiceResult result = findFirstService(address); + const FindServiceResult result = findFirstService(address); emit threadWorker->findFinished(QVariant::fromValue(result)); }, Qt::QueuedConnection); } @@ -403,13 +368,29 @@ void QBluetoothServiceDiscoveryAgentPrivate::stop() pendingStop = true; } +bool QBluetoothServiceDiscoveryAgentPrivate::serviceMatches(const QBluetoothServiceInfo &info) +{ + if (uuidFilter.isEmpty()) + return true; + + if (uuidFilter.contains(info.serviceUuid())) + return true; + + const QList serviceClassUuids = info.serviceClassUuids(); + for (const QBluetoothUuid &uuid : serviceClassUuids) + if (uuidFilter.contains(uuid)) + return true; + + return false; +} + void QBluetoothServiceDiscoveryAgentPrivate::_q_nextSdpScan(const QVariant &input) { Q_Q(QBluetoothServiceDiscoveryAgent); auto result = input.value(); if (pendingStop) { - WSALookupServiceEnd(result.hSearch); + ::WSALookupServiceEnd(result.hSearch); pendingStop = false; pendingFinish = false; emit q->canceled(); @@ -418,7 +399,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_nextSdpScan(const QVariant &inpu result.systemError = NO_ERROR; } else if (result.systemError != NO_ERROR) { if (result.hSearch != INVALID_HANDLE_VALUE) - WSALookupServiceEnd(result.hSearch); + ::WSALookupServiceEnd(result.hSearch); error = (result.systemError == ERROR_INVALID_HANDLE) ? QBluetoothServiceDiscoveryAgent::InvalidBluetoothAdapterError : QBluetoothServiceDiscoveryAgent::InputOutputError; @@ -426,13 +407,17 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_nextSdpScan(const QVariant &inpu qCWarning(QT_BT_WINDOWS) << errorString; emit q->error(this->error); } else { - result.info.setDevice(discoveredDevices.at(0)); - if (result.info.isValid()) { - if (!isDuplicatedService(result.info)) { - discoveredServices.append(result.info); - emit q->serviceDiscovered(result.info); + + if (serviceMatches(result.info)) { + result.info.setDevice(discoveredDevices.at(0)); + if (result.info.isValid()) { + if (!isDuplicatedService(result.info)) { + discoveredServices.append(result.info); + emit q->serviceDiscovered(result.info); + } } } + const auto threadWorker = threadWorkerFind; const auto hSearch = result.hSearch; QMetaObject::invokeMethod(threadWorkerFind, [threadWorker, hSearch]() -- cgit v1.2.3