diff options
author | Denis Shienkov <denis.shienkov@gmail.com> | 2015-10-14 18:49:15 +0300 |
---|---|---|
committer | Denis Shienkov <denis.shienkov@gmail.com> | 2015-10-16 09:53:48 +0000 |
commit | 4cb5575e9ce38f74c471bbecde139bf4f83fa22f (patch) | |
tree | 683c6e70f7d92049f839d8705f5f4a7d0676d672 /src | |
parent | e624e7e63c6ac2b330720fea465b05190c70023b (diff) |
Windows: Refactor code related to a services discovering
* We do not need QtConcurrent for a services discovering
because they returns from a cache immediately.
* We don't need to hold the opened device all the time after
connection to it. It is enough to open a device only for a
some time to request of services.
* Now the windows/qwinlowenergybluetooth_p.h file contains
only resolved system LE functions and data types.
Change-Id: I248666d78cc9141bf987987dfd5dd9280decf4b8
Reviewed-by: Alex Blasche <alexander.blasche@theqtcompany.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/bluetooth/qlowenergycontroller_p.h | 15 | ||||
-rw-r--r-- | src/bluetooth/qlowenergycontroller_win.cpp | 241 | ||||
-rw-r--r-- | src/bluetooth/windows/qwinlowenergybluetooth.cpp | 144 | ||||
-rw-r--r-- | src/bluetooth/windows/qwinlowenergybluetooth_p.h | 77 | ||||
-rw-r--r-- | src/bluetooth/windows/windows.pri | 3 |
5 files changed, 185 insertions, 295 deletions
diff --git a/src/bluetooth/qlowenergycontroller_p.h b/src/bluetooth/qlowenergycontroller_p.h index 6d81316d..fde057cf 100644 --- a/src/bluetooth/qlowenergycontroller_p.h +++ b/src/bluetooth/qlowenergycontroller_p.h @@ -65,12 +65,6 @@ QT_END_NAMESPACE #include "android/lowenergynotificationhub_p.h" #endif -#if defined(Q_OS_WIN32) -#include <QtConcurrent> -#include <QtBluetooth/qbluetoothuuid.h> -#include "windows/qwinlowenergybluetooth_p.h" -#endif - QT_BEGIN_NAMESPACE #if defined(QT_BLUEZ_BLUETOOTH) && !defined(QT_BLUEZ_NO_BTLE) @@ -227,15 +221,8 @@ private slots: void characteristicChanged(int charHandle, const QByteArray &data); void serviceError(int attributeHandle, QLowEnergyService::ServiceError errorCode); #elif defined(Q_OS_WIN32) -private slots: - void primaryServicesDiscoveryCompleted(); - private: - void startDiscoveryOfPrimaryServices(); - bool isConnected() const; - - HANDLE hRemoteDevice; - QFutureWatcher<WinLowEnergyBluetooth::ServicesDiscoveryResult> *primaryServicesDiscoveryWatcher; + QString deviceSystemPath; #endif private: QLowEnergyController *q_ptr; diff --git a/src/bluetooth/qlowenergycontroller_win.cpp b/src/bluetooth/qlowenergycontroller_win.cpp index ed33c5c8..0f629a0b 100644 --- a/src/bluetooth/qlowenergycontroller_win.cpp +++ b/src/bluetooth/qlowenergycontroller_win.cpp @@ -37,17 +37,80 @@ #include <QtCore/QLoggingCategory> +#include <windows/qwinlowenergybluetooth_p.h> + QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINDOWS) +Q_GLOBAL_STATIC(QLibrary, bluetoothapis) + +static bool gattFunctionsResolved = false; + +static HANDLE openSystemDevice(const QString &systemPath, int *systemErrorCode) +{ + const DWORD desiredAccess = GENERIC_READ | GENERIC_WRITE; + const DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; + const HANDLE serviceHandle = ::CreateFile( + reinterpret_cast<const wchar_t *>(systemPath.utf16()), + desiredAccess, + shareMode, + NULL, + OPEN_EXISTING, + 0, + NULL); + + *systemErrorCode = (INVALID_HANDLE_VALUE == serviceHandle) + ? ::GetLastError() : NO_ERROR; + return serviceHandle; +} + +static void closeSystemDevice(HANDLE deviceHandle) +{ + if (deviceHandle && deviceHandle != INVALID_HANDLE_VALUE) + ::CloseHandle(deviceHandle); +} + +static QVector<BTH_LE_GATT_SERVICE> enumeratePrimaryGattServices( + HANDLE deviceHandle, int *systemErrorCode) +{ + if (!gattFunctionsResolved) { + *systemErrorCode = ERROR_NOT_SUPPORTED; + return QVector<BTH_LE_GATT_SERVICE>(); + } + + QVector<BTH_LE_GATT_SERVICE> foundServices; + USHORT servicesCount = 0; + forever { + const HRESULT hr = ::BluetoothGATTGetServices( + deviceHandle, + servicesCount, + foundServices.isEmpty() ? NULL : &foundServices[0], + &servicesCount, + BLUETOOTH_GATT_FLAG_NONE); + + if (hr == HRESULT_FROM_WIN32(ERROR_MORE_DATA)) { + foundServices.resize(servicesCount); + } else if (hr == S_OK) { + *systemErrorCode = NO_ERROR; + return foundServices; + } else { + *systemErrorCode = ::GetLastError(); + return QVector<BTH_LE_GATT_SERVICE>(); + } + } +} + QLowEnergyControllerPrivate::QLowEnergyControllerPrivate() - : QObject(), - state(QLowEnergyController::UnconnectedState), - error(QLowEnergyController::NoError), - hRemoteDevice(INVALID_HANDLE_VALUE), - primaryServicesDiscoveryWatcher(0) + : QObject() + , state(QLowEnergyController::UnconnectedState) + , error(QLowEnergyController::NoError) { + gattFunctionsResolved = resolveFunctions(bluetoothapis()); + if (!gattFunctionsResolved) { + qCWarning(QT_BT_WINDOWS) << "LE is not supported on this OS"; + return; + } } QLowEnergyControllerPrivate::~QLowEnergyControllerPrivate() @@ -56,8 +119,6 @@ QLowEnergyControllerPrivate::~QLowEnergyControllerPrivate() void QLowEnergyControllerPrivate::connectToDevice() { - Q_Q(QLowEnergyController); - // required to pass unit test on default backend if (remoteDevice.isNull()) { qWarning() << "Invalid/null remote device address"; @@ -65,78 +126,97 @@ void QLowEnergyControllerPrivate::connectToDevice() return; } - if (!WinLowEnergyBluetooth::isSupported()) { - qWarning() << "Low energy is not supported by OS"; - setError(QLowEnergyController::UnknownError); - return; - } - - if (isConnected()) { + if (!deviceSystemPath.isEmpty()) { qCDebug(QT_BT_WINDOWS) << "Already is connected"; return; } setState(QLowEnergyController::ConnectingState); - const QString deviceSystemPath = QBluetoothDeviceDiscoveryAgentPrivate::discoveredLeDeviceSystemPath(remoteDevice); - - const DWORD desiredAccess = GENERIC_READ | GENERIC_WRITE; - const DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; - - hRemoteDevice = ::CreateFile( - reinterpret_cast<const wchar_t *>(deviceSystemPath.utf16()), - desiredAccess, - shareMode, - NULL, - OPEN_EXISTING, - 0, - NULL); + deviceSystemPath = + QBluetoothDeviceDiscoveryAgentPrivate::discoveredLeDeviceSystemPath( + remoteDevice); - if (hRemoteDevice == INVALID_HANDLE_VALUE) { - qCWarning(QT_BT_WINDOWS) << qt_error_string(::GetLastError()); - setError(QLowEnergyController::ConnectionError); + if (deviceSystemPath.isEmpty()) { + qCWarning(QT_BT_WINDOWS) << qt_error_string(ERROR_PATH_NOT_FOUND); + setError(QLowEnergyController::UnknownRemoteDeviceError); setState(QLowEnergyController::UnconnectedState); return; } setState(QLowEnergyController::ConnectedState); + + Q_Q(QLowEnergyController); emit q->connected(); } void QLowEnergyControllerPrivate::disconnectFromDevice() { - Q_Q(QLowEnergyController); - - if (!WinLowEnergyBluetooth::isSupported()) { - qWarning() << "Low energy is not supported by OS"; - setError(QLowEnergyController::UnknownError); - return; - } - - if (!isConnected()) { + if (deviceSystemPath.isEmpty()) { qCDebug(QT_BT_WINDOWS) << "Already is disconnected"; return; } setState(QLowEnergyController::ClosingState); - - if (!::CloseHandle(hRemoteDevice)) - qCWarning(QT_BT_WINDOWS) << qt_error_string(::GetLastError()); - - hRemoteDevice = INVALID_HANDLE_VALUE; + deviceSystemPath.clear(); setState(QLowEnergyController::UnconnectedState); + + Q_Q(QLowEnergyController); emit q->disconnected(); } void QLowEnergyControllerPrivate::discoverServices() { - if (!WinLowEnergyBluetooth::isSupported()) { - qWarning() << "Low energy is not supported by OS"; - setError(QLowEnergyController::UnknownError); + int systemErrorCode = NO_ERROR; + + const HANDLE deviceHandle = openSystemDevice(deviceSystemPath, &systemErrorCode); + + if (systemErrorCode != NO_ERROR) { + qCWarning(QT_BT_WINDOWS) << qt_error_string(systemErrorCode); + setError(QLowEnergyController::NetworkError); + setState(QLowEnergyController::ConnectedState); + return; + } + + const QVector<BTH_LE_GATT_SERVICE> foundServices = + enumeratePrimaryGattServices(deviceHandle, &systemErrorCode); + + closeSystemDevice(deviceHandle); + + if (systemErrorCode != NO_ERROR) { + qCWarning(QT_BT_WINDOWS) << qt_error_string(systemErrorCode); + setError(QLowEnergyController::NetworkError); + setState(QLowEnergyController::ConnectedState); return; } - startDiscoveryOfPrimaryServices(); + setState(QLowEnergyController::DiscoveringState); + + Q_Q(QLowEnergyController); + + foreach (const BTH_LE_GATT_SERVICE &service, foundServices) { + + const QBluetoothUuid uuid( + service.ServiceUuid.IsShortUuid + ? QBluetoothUuid(service.ServiceUuid.Value.ShortUuid) + : QBluetoothUuid(service.ServiceUuid.Value.LongUuid)); + + qCDebug(QT_BT_WINDOWS) << "Found uuid:" << uuid; + + QLowEnergyServicePrivate *priv = new QLowEnergyServicePrivate(); + priv->uuid = uuid; + priv->type = QLowEnergyService::PrimaryService; + priv->startHandle = service.AttributeHandle; + priv->setController(this); + + QSharedPointer<QLowEnergyServicePrivate> pointer(priv); + serviceList.insert(uuid, pointer); + + emit q->serviceDiscovered(uuid); + } + + setState(QLowEnergyController::DiscoveredState); + emit q->discoveryFinished(); } void QLowEnergyControllerPrivate::discoverServiceDetails( @@ -178,69 +258,4 @@ void QLowEnergyControllerPrivate::writeDescriptor( } -void QLowEnergyControllerPrivate::primaryServicesDiscoveryCompleted() -{ - Q_Q(QLowEnergyController); - - const WinLowEnergyBluetooth::ServicesDiscoveryResult result = - primaryServicesDiscoveryWatcher->result(); - - if (result.error != NO_ERROR) { - qCWarning(QT_BT_WINDOWS) << qt_error_string(result.error); - setError(QLowEnergyController::UnknownError); - return; - } - - foreach (const WinLowEnergyBluetooth::BTH_LE_GATT_SERVICE &service, - result.services) { - - const QBluetoothUuid uuid( - service.ServiceUuid.IsShortUuid - ? QBluetoothUuid(service.ServiceUuid.Value.ShortUuid) - : QBluetoothUuid(service.ServiceUuid.Value.LongUuid)); - - qCDebug(QT_BT_WINDOWS) << "Found uuid:" << uuid; - - QLowEnergyServicePrivate *priv = new QLowEnergyServicePrivate(); - priv->uuid = uuid; - priv->type = QLowEnergyService::PrimaryService; - priv->startHandle = service.AttributeHandle; - priv->setController(this); - - QSharedPointer<QLowEnergyServicePrivate> pointer(priv); - - serviceList.insert(uuid, pointer); - emit q->serviceDiscovered(uuid); - } - - setState(QLowEnergyController::DiscoveredState); - emit q->discoveryFinished(); -} - -void QLowEnergyControllerPrivate::startDiscoveryOfPrimaryServices() -{ - if (!primaryServicesDiscoveryWatcher) { - primaryServicesDiscoveryWatcher = new QFutureWatcher< - WinLowEnergyBluetooth::ServicesDiscoveryResult>(this); - - connect(primaryServicesDiscoveryWatcher, &QFutureWatcher<WinLowEnergyBluetooth::ServicesDiscoveryResult>::finished, - this, &QLowEnergyControllerPrivate::primaryServicesDiscoveryCompleted); - } - - if (primaryServicesDiscoveryWatcher->isRunning()) - return; - - const QFuture<WinLowEnergyBluetooth::ServicesDiscoveryResult> future = - QtConcurrent::run( - WinLowEnergyBluetooth::startDiscoveryOfPrimaryServices, - hRemoteDevice); - - primaryServicesDiscoveryWatcher->setFuture(future); -} - -bool QLowEnergyControllerPrivate::isConnected() const -{ - return hRemoteDevice && (hRemoteDevice != INVALID_HANDLE_VALUE); -} - QT_END_NAMESPACE diff --git a/src/bluetooth/windows/qwinlowenergybluetooth.cpp b/src/bluetooth/windows/qwinlowenergybluetooth.cpp deleted file mode 100644 index 8033a121..00000000 --- a/src/bluetooth/windows/qwinlowenergybluetooth.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Copyright (C) 2014 Denis Shienkov <denis.shienkov@gmail.com> -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtBluetooth module of the Qt Toolkit. -** -** $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 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 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. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qwinlowenergybluetooth_p.h" - -#include <QtCore/quuid.h> -#include <QtCore/qlibrary.h> -#include <QtCore/qglobal.h> - -QT_BEGIN_NAMESPACE - -namespace WinLowEnergyBluetooth { - -#define DEFINEFUNC(ret, func, ...) \ - typedef ret (WINAPI *fp_##func)(__VA_ARGS__); \ - static fp_##func func; - -#define RESOLVEFUNC(func) \ - func = (fp_##func)resolveFunction(library, #func); \ - if (!func) \ - return false; - -DEFINEFUNC(HRESULT, BluetoothGATTGetServices, HANDLE, USHORT, PBTH_LE_GATT_SERVICE, PUSHORT, ULONG) -DEFINEFUNC(HRESULT, BluetoothGATTGetIncludedServices, HANDLE, PBTH_LE_GATT_SERVICE, USHORT, PBTH_LE_GATT_SERVICE, PUSHORT, ULONG) -DEFINEFUNC(HRESULT, BluetoothGATTGetCharacteristics, HANDLE, PBTH_LE_GATT_SERVICE, USHORT, PBTH_LE_GATT_CHARACTERISTIC, PUSHORT, ULONG) -DEFINEFUNC(HRESULT, BluetoothGATTGetDescriptors, HANDLE, PBTH_LE_GATT_CHARACTERISTIC, USHORT, PBTH_LE_GATT_DESCRIPTOR, PUSHORT, ULONG) -DEFINEFUNC(HRESULT, BluetoothGATTGetCharacteristicValue, HANDLE, PBTH_LE_GATT_CHARACTERISTIC, ULONG, PBTH_LE_GATT_CHARACTERISTIC_VALUE, PUSHORT, ULONG) -DEFINEFUNC(HRESULT, BluetoothGATTGetDescriptorValue, HANDLE, PBTH_LE_GATT_DESCRIPTOR, ULONG, PBTH_LE_GATT_DESCRIPTOR_VALUE, PUSHORT, ULONG) -DEFINEFUNC(HRESULT, BluetoothGATTBeginReliableWrite, HANDLE, PBTH_LE_GATT_RELIABLE_WRITE_CONTEXT, ULONG) -DEFINEFUNC(HRESULT, BluetoothGATTEndReliableWrite, HANDLE, BTH_LE_GATT_RELIABLE_WRITE_CONTEXT, ULONG) -DEFINEFUNC(HRESULT, BluetoothGATTAbortReliableWrite, HANDLE, BTH_LE_GATT_RELIABLE_WRITE_CONTEXT, ULONG) -DEFINEFUNC(HRESULT, BluetoothGATTSetCharacteristicValue, HANDLE, PBTH_LE_GATT_CHARACTERISTIC, PBTH_LE_GATT_CHARACTERISTIC_VALUE, BTH_LE_GATT_RELIABLE_WRITE_CONTEXT, ULONG) -DEFINEFUNC(HRESULT, BluetoothGATTSetDescriptorValue, HANDLE, PBTH_LE_GATT_DESCRIPTOR, PBTH_LE_GATT_DESCRIPTOR_VALUE, ULONG) -DEFINEFUNC(HRESULT, BluetoothGATTRegisterEvent, HANDLE, BTH_LE_GATT_EVENT_TYPE, PVOID, PFNBLUETOOTH_GATT_EVENT_CALLBACK, PVOID, PHANDLE, ULONG) -DEFINEFUNC(HRESULT, BluetoothGATTUnregisterEvent, HANDLE, ULONG) - -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(BluetoothGATTGetServices) - RESOLVEFUNC(BluetoothGATTGetIncludedServices) - RESOLVEFUNC(BluetoothGATTGetCharacteristics) - RESOLVEFUNC(BluetoothGATTGetDescriptors) - RESOLVEFUNC(BluetoothGATTGetCharacteristicValue) - RESOLVEFUNC(BluetoothGATTGetDescriptorValue) - RESOLVEFUNC(BluetoothGATTBeginReliableWrite) - RESOLVEFUNC(BluetoothGATTEndReliableWrite) - RESOLVEFUNC(BluetoothGATTAbortReliableWrite) - RESOLVEFUNC(BluetoothGATTSetCharacteristicValue) - RESOLVEFUNC(BluetoothGATTSetDescriptorValue) - RESOLVEFUNC(BluetoothGATTRegisterEvent) - RESOLVEFUNC(BluetoothGATTUnregisterEvent) - - return true; -} - -Q_GLOBAL_STATIC(QLibrary, bluetoothapis) - -ServicesDiscoveryResult::ServicesDiscoveryResult() - : error(NO_ERROR) -{ -} - -ServicesDiscoveryResult startDiscoveryOfPrimaryServices( - HANDLE hDevice) -{ - ServicesDiscoveryResult result; - USHORT servicesCount = 0; - forever { - const HRESULT hr = BluetoothGATTGetServices( - hDevice, - result.services.count(), - result.services.isEmpty() ? NULL : &result.services[0], - &servicesCount, - BLUETOOTH_GATT_FLAG_NONE); - - if (hr == HRESULT_FROM_WIN32(ERROR_MORE_DATA)) { - result.services.resize(servicesCount); - } else if (hr == S_OK) { - break; - } else { - result.error = ::GetLastError(); - result.services.clear(); - break; - } - } - return result; -} - -bool isSupported() -{ - static bool resolved = resolveFunctions(bluetoothapis()); - return resolved; -} - -} // namespace WinLowEnergyBluetooth - -QT_END_NAMESPACE diff --git a/src/bluetooth/windows/qwinlowenergybluetooth_p.h b/src/bluetooth/windows/qwinlowenergybluetooth_p.h index c591a93d..c12ea4ae 100644 --- a/src/bluetooth/windows/qwinlowenergybluetooth_p.h +++ b/src/bluetooth/windows/qwinlowenergybluetooth_p.h @@ -35,17 +35,9 @@ #ifndef QWINLOWENERGYBLUETOOTH_P_H #define QWINLOWENERGYBLUETOOTH_P_H -#include <QtCore/qstringlist.h> -#include <QtCore/qvector.h> - -#include <QtBluetooth/qbluetoothaddress.h> +#include <QtCore/qlibrary.h> #include <qt_windows.h> -#include <setupapi.h> - -QT_BEGIN_NAMESPACE - -namespace WinLowEnergyBluetooth { #define BLUETOOTH_GATT_FLAG_NONE 0x00000000 #define BLUETOOTH_GATT_FLAG_CONNECTION_ENCRYPTED 0x00000001 @@ -157,19 +149,62 @@ typedef VOID (CALLBACK *PFNBLUETOOTH_GATT_EVENT_CALLBACK)( typedef ULONG64 BTH_LE_GATT_RELIABLE_WRITE_CONTEXT, *PBTH_LE_GATT_RELIABLE_WRITE_CONTEXT; -struct ServicesDiscoveryResult +#define DEFINEFUNC(ret, func, ...) \ + typedef ret (WINAPI *fp_##func)(__VA_ARGS__); \ + static fp_##func func; + +#define RESOLVEFUNC(func) \ + func = (fp_##func)resolveFunction(library, #func); \ + if (!func) \ + return false; + +DEFINEFUNC(HRESULT, BluetoothGATTGetServices, HANDLE, USHORT, PBTH_LE_GATT_SERVICE, PUSHORT, ULONG) +DEFINEFUNC(HRESULT, BluetoothGATTGetIncludedServices, HANDLE, PBTH_LE_GATT_SERVICE, USHORT, PBTH_LE_GATT_SERVICE, PUSHORT, ULONG) +DEFINEFUNC(HRESULT, BluetoothGATTGetCharacteristics, HANDLE, PBTH_LE_GATT_SERVICE, USHORT, PBTH_LE_GATT_CHARACTERISTIC, PUSHORT, ULONG) +DEFINEFUNC(HRESULT, BluetoothGATTGetDescriptors, HANDLE, PBTH_LE_GATT_CHARACTERISTIC, USHORT, PBTH_LE_GATT_DESCRIPTOR, PUSHORT, ULONG) +DEFINEFUNC(HRESULT, BluetoothGATTGetCharacteristicValue, HANDLE, PBTH_LE_GATT_CHARACTERISTIC, ULONG, PBTH_LE_GATT_CHARACTERISTIC_VALUE, PUSHORT, ULONG) +DEFINEFUNC(HRESULT, BluetoothGATTGetDescriptorValue, HANDLE, PBTH_LE_GATT_DESCRIPTOR, ULONG, PBTH_LE_GATT_DESCRIPTOR_VALUE, PUSHORT, ULONG) +DEFINEFUNC(HRESULT, BluetoothGATTBeginReliableWrite, HANDLE, PBTH_LE_GATT_RELIABLE_WRITE_CONTEXT, ULONG) +DEFINEFUNC(HRESULT, BluetoothGATTEndReliableWrite, HANDLE, BTH_LE_GATT_RELIABLE_WRITE_CONTEXT, ULONG) +DEFINEFUNC(HRESULT, BluetoothGATTAbortReliableWrite, HANDLE, BTH_LE_GATT_RELIABLE_WRITE_CONTEXT, ULONG) +DEFINEFUNC(HRESULT, BluetoothGATTSetCharacteristicValue, HANDLE, PBTH_LE_GATT_CHARACTERISTIC, PBTH_LE_GATT_CHARACTERISTIC_VALUE, BTH_LE_GATT_RELIABLE_WRITE_CONTEXT, ULONG) +DEFINEFUNC(HRESULT, BluetoothGATTSetDescriptorValue, HANDLE, PBTH_LE_GATT_DESCRIPTOR, PBTH_LE_GATT_DESCRIPTOR_VALUE, ULONG) +DEFINEFUNC(HRESULT, BluetoothGATTRegisterEvent, HANDLE, BTH_LE_GATT_EVENT_TYPE, PVOID, PFNBLUETOOTH_GATT_EVENT_CALLBACK, PVOID, PHANDLE, ULONG) +DEFINEFUNC(HRESULT, BluetoothGATTUnregisterEvent, HANDLE, ULONG) + +static inline QFunctionPointer resolveFunction(QLibrary *library, const char *func) { - ServicesDiscoveryResult(); - QVector<BTH_LE_GATT_SERVICE> services; - DWORD error; -}; - -bool isSupported(); + QFunctionPointer symbolFunctionPointer = library->resolve(func); + if (!symbolFunctionPointer) + qWarning("Cannot resolve '%s' in '%s'.", func, qPrintable(library->fileName())); + return symbolFunctionPointer; +} -ServicesDiscoveryResult startDiscoveryOfPrimaryServices(HANDLE hDevice); - -} // namespace WinLowEnergyBluetooth - -QT_END_NAMESPACE +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(BluetoothGATTGetServices) + RESOLVEFUNC(BluetoothGATTGetIncludedServices) + RESOLVEFUNC(BluetoothGATTGetCharacteristics) + RESOLVEFUNC(BluetoothGATTGetDescriptors) + RESOLVEFUNC(BluetoothGATTGetCharacteristicValue) + RESOLVEFUNC(BluetoothGATTGetDescriptorValue) + RESOLVEFUNC(BluetoothGATTBeginReliableWrite) + RESOLVEFUNC(BluetoothGATTEndReliableWrite) + RESOLVEFUNC(BluetoothGATTAbortReliableWrite) + RESOLVEFUNC(BluetoothGATTSetCharacteristicValue) + RESOLVEFUNC(BluetoothGATTSetDescriptorValue) + RESOLVEFUNC(BluetoothGATTRegisterEvent) + RESOLVEFUNC(BluetoothGATTUnregisterEvent) + + return true; +} #endif // QWINLOWENERGYBLUETOOTH_P_H diff --git a/src/bluetooth/windows/windows.pri b/src/bluetooth/windows/windows.pri index 019d67e4..bf35eaa4 100644 --- a/src/bluetooth/windows/windows.pri +++ b/src/bluetooth/windows/windows.pri @@ -1,5 +1,2 @@ PRIVATE_HEADERS += \ windows/qwinlowenergybluetooth_p.h - -SOURCES += \ - windows/qwinlowenergybluetooth.cpp |