diff options
124 files changed, 3860 insertions, 1370 deletions
diff --git a/.qmake.conf b/.qmake.conf index 0338efe0..dc68d388 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -1,3 +1,3 @@ load(qt_build_config) -MODULE_VERSION = 5.10.1 +MODULE_VERSION = 5.11.0 diff --git a/src/android/bluetooth/bluetooth.pri b/src/android/bluetooth/bluetooth.pri deleted file mode 100644 index fa811ac1..00000000 --- a/src/android/bluetooth/bluetooth.pri +++ /dev/null @@ -1,17 +0,0 @@ -CONFIG += java -DESTDIR = $$[QT_INSTALL_PREFIX/get]/jar -API_VERSION = android-21 - -PATHPREFIX = $$PWD/src/org/qtproject/qt5/android/bluetooth - -JAVACLASSPATH += $$PWD/src/ -JAVASOURCES += \ - $$PATHPREFIX/QtBluetoothBroadcastReceiver.java \ - $$PATHPREFIX/QtBluetoothSocketServer.java \ - $$PATHPREFIX/QtBluetoothInputStreamThread.java \ - $$PATHPREFIX/QtBluetoothLE.java \ - $$PATHPREFIX/QtBluetoothLEServer.java - -# install -target.path = $$[QT_INSTALL_PREFIX]/jar -INSTALLS += target diff --git a/src/android/bluetooth/bluetooth.pro b/src/android/bluetooth/bluetooth.pro index 8d19c1b7..b76b392c 100644 --- a/src/android/bluetooth/bluetooth.pro +++ b/src/android/bluetooth/bluetooth.pro @@ -1,2 +1,19 @@ -TEMPLATE = subdirs -SUBDIRS += bundledjar.pro distributedjar.pro +TARGET = QtAndroidBluetooth + +CONFIG += java +DESTDIR = $$[QT_INSTALL_PREFIX/get]/jar +API_VERSION = android-21 + +PATHPREFIX = $$PWD/src/org/qtproject/qt5/android/bluetooth + +JAVACLASSPATH += $$PWD/src/ +JAVASOURCES += \ + $$PATHPREFIX/QtBluetoothBroadcastReceiver.java \ + $$PATHPREFIX/QtBluetoothSocketServer.java \ + $$PATHPREFIX/QtBluetoothInputStreamThread.java \ + $$PATHPREFIX/QtBluetoothLE.java \ + $$PATHPREFIX/QtBluetoothLEServer.java + +# install +target.path = $$[QT_INSTALL_PREFIX]/jar +INSTALLS += target diff --git a/src/android/bluetooth/bundledjar.pro b/src/android/bluetooth/bundledjar.pro deleted file mode 100644 index 8912674a..00000000 --- a/src/android/bluetooth/bundledjar.pro +++ /dev/null @@ -1,3 +0,0 @@ -TARGET = QtAndroidBluetooth-bundled -CONFIG += bundled_jar_file -include(bluetooth.pri) diff --git a/src/android/bluetooth/distributedjar.pro b/src/android/bluetooth/distributedjar.pro deleted file mode 100644 index a155bdf2..00000000 --- a/src/android/bluetooth/distributedjar.pro +++ /dev/null @@ -1,2 +0,0 @@ -TARGET = QtAndroidBluetooth -include(bluetooth.pri) diff --git a/src/android/nfc/bundledjar.pro b/src/android/nfc/bundledjar.pro deleted file mode 100644 index 37f7fc82..00000000 --- a/src/android/nfc/bundledjar.pro +++ /dev/null @@ -1,3 +0,0 @@ -TARGET = QtNfc-bundled -CONFIG += bundled_jar_file -include(nfc.pri) diff --git a/src/android/nfc/distributedjar.pro b/src/android/nfc/distributedjar.pro deleted file mode 100644 index ed65c50a..00000000 --- a/src/android/nfc/distributedjar.pro +++ /dev/null @@ -1,2 +0,0 @@ -TARGET = QtNfc -include(nfc.pri) diff --git a/src/android/nfc/nfc.pri b/src/android/nfc/nfc.pri deleted file mode 100644 index 3f6e26aa..00000000 --- a/src/android/nfc/nfc.pri +++ /dev/null @@ -1,12 +0,0 @@ -CONFIG += java -DESTDIR = $$[QT_INSTALL_PREFIX/get]/jar - -PATHPREFIX = $$PWD/src/org/qtproject/qt5/android/nfc - -JAVACLASSPATH += $$PWD/src/ -JAVASOURCES += \ - $$PWD/src/org/qtproject/qt5/android/nfc/QtNfc.java - -# install -target.path = $$[QT_INSTALL_PREFIX]/jar -INSTALLS += target diff --git a/src/android/nfc/nfc.pro b/src/android/nfc/nfc.pro index 70373fe1..89026b75 100644 --- a/src/android/nfc/nfc.pro +++ b/src/android/nfc/nfc.pro @@ -1,3 +1,14 @@ -TEMPLATE = subdirs -SUBDIRS += bundledjar.pro distributedjar.pro +TARGET = QtNfc +CONFIG += java +DESTDIR = $$[QT_INSTALL_PREFIX/get]/jar + +PATHPREFIX = $$PWD/src/org/qtproject/qt5/android/nfc + +JAVACLASSPATH += $$PWD/src/ +JAVASOURCES += \ + $$PWD/src/org/qtproject/qt5/android/nfc/QtNfc.java + +# install +target.path = $$[QT_INSTALL_PREFIX]/jar +INSTALLS += target diff --git a/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp b/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp index 5acf761d..131fb48d 100644 --- a/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp +++ b/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp @@ -120,7 +120,7 @@ static const MajorClassJavaToQtMapping majorMappings[] = { { "TOY", QBluetoothDeviceInfo::ToyDevice }, { "UNCATEGORIZED", QBluetoothDeviceInfo::UncategorizedDevice }, { "WEARABLE", QBluetoothDeviceInfo::WearableDevice }, - { Q_NULLPTR, QBluetoothDeviceInfo::UncategorizedDevice } //end of list + { nullptr, QBluetoothDeviceInfo::UncategorizedDevice } //end of list }; // QBluetoothDeviceInfo::MajorDeviceClass value plus 1 matches index @@ -164,7 +164,7 @@ static const MinorClassJavaToQtMapping minorMappings[] = { { "AUDIO_VIDEO_VIDEO_GAMING_TOY", QBluetoothDeviceInfo::GamingDevice }, { "AUDIO_VIDEO_VIDEO_MONITOR", QBluetoothDeviceInfo::VideoMonitor }, { "AUDIO_VIDEO_WEARABLE_HEADSET", QBluetoothDeviceInfo::WearableHeadsetDevice }, - { Q_NULLPTR, 0 }, // separator + { nullptr, 0 }, // separator // QBluetoothDevice::ComputerDevice -> 7 entries { "COMPUTER_UNCATEGORIZED", QBluetoothDeviceInfo::UncategorizedComputer }, // index 18 @@ -174,7 +174,7 @@ static const MinorClassJavaToQtMapping minorMappings[] = { { "COMPUTER_PALM_SIZE_PC_PDA", QBluetoothDeviceInfo::HandheldClamShellComputer }, { "COMPUTER_SERVER", QBluetoothDeviceInfo::ServerComputer }, { "COMPUTER_WEARABLE", QBluetoothDeviceInfo::WearableComputer }, - { Q_NULLPTR, 0 }, // separator + { nullptr, 0 }, // separator // QBluetoothDevice::HealthDevice -> 8 entries { "HEALTH_BLOOD_PRESSURE", QBluetoothDeviceInfo::HealthBloodPressureMonitor }, // index 26 @@ -185,7 +185,7 @@ static const MinorClassJavaToQtMapping minorMappings[] = { { "HEALTH_THERMOMETER", QBluetoothDeviceInfo::HealthThermometer }, { "HEALTH_UNCATEGORIZED", QBluetoothDeviceInfo::UncategorizedHealthDevice }, { "HEALTH_WEIGHING", QBluetoothDeviceInfo::HealthWeightScale }, - { Q_NULLPTR, 0 }, // separator + { nullptr, 0 }, // separator // QBluetoothDevice::PhoneDevice -> 6 entries { "PHONE_CELLULAR", QBluetoothDeviceInfo::CellularPhone }, // index 35 @@ -194,7 +194,7 @@ static const MinorClassJavaToQtMapping minorMappings[] = { { "PHONE_MODEM_OR_GATEWAY", QBluetoothDeviceInfo::WiredModemOrVoiceGatewayPhone }, { "PHONE_SMART", QBluetoothDeviceInfo::SmartPhone }, { "PHONE_UNCATEGORIZED", QBluetoothDeviceInfo::UncategorizedPhone }, - { Q_NULLPTR, 0 }, // separator + { nullptr, 0 }, // separator // QBluetoothDevice::ToyDevice -> 6 entries { "TOY_CONTROLLER", QBluetoothDeviceInfo::ToyController }, // index 42 @@ -203,7 +203,7 @@ static const MinorClassJavaToQtMapping minorMappings[] = { { "TOY_ROBOT", QBluetoothDeviceInfo::ToyRobot }, { "TOY_UNCATEGORIZED", QBluetoothDeviceInfo::UncategorizedToy }, { "TOY_VEHICLE", QBluetoothDeviceInfo::ToyVehicle }, - { Q_NULLPTR, 0 }, // separator + { nullptr, 0 }, // separator // QBluetoothDevice::WearableDevice -> 6 entries { "WEARABLE_GLASSES", QBluetoothDeviceInfo::WearableGlasses }, // index 49 @@ -212,7 +212,7 @@ static const MinorClassJavaToQtMapping minorMappings[] = { { "WEARABLE_PAGER", QBluetoothDeviceInfo::WearablePager }, { "WEARABLE_UNCATEGORIZED", QBluetoothDeviceInfo::UncategorizedWearableDevice }, { "WEARABLE_WRIST_WATCH", QBluetoothDeviceInfo::WearableWristWatch }, - { Q_NULLPTR, 0 }, // separator + { nullptr, 0 }, // separator // QBluetoothDevice::PeripheralDevice -> 3 entries // For some reason these are not mentioned in Android docs but still exist @@ -220,21 +220,21 @@ static const MinorClassJavaToQtMapping minorMappings[] = { { "PERIPHERAL_KEYBOARD", QBluetoothDeviceInfo::KeyboardPeripheral }, { "PERIPHERAL_POINTING", QBluetoothDeviceInfo::PointingDevicePeripheral }, { "PERIPHERAL_KEYBOARD_POINTING", QBluetoothDeviceInfo::KeyboardWithPointingDevicePeripheral }, - { Q_NULLPTR, 0 }, // separator + { nullptr, 0 }, // separator // the following entries do not exist on Android // we map them to the unknown minor version case // QBluetoothDevice::Miscellaneous - { Q_NULLPTR, 0 }, // index 61 & separator + { nullptr, 0 }, // index 61 & separator // QBluetoothDevice::LANAccessDevice - { Q_NULLPTR, 0 }, // index 62 & separator + { nullptr, 0 }, // index 62 & separator // QBluetoothDevice::ImagingDevice - { Q_NULLPTR, 0 }, // index 63 & separator + { nullptr, 0 }, // index 63 & separator // QBluetoothDevice::UncategorizedDevice - { Q_NULLPTR, 0 }, // index 64 & separator + { nullptr, 0 }, // index 64 & separator }; /* Advertising Data Type (AD type) for LE scan records, as defined in Bluetooth CSS v6. */ @@ -308,7 +308,7 @@ QBluetoothDeviceInfo::MajorDeviceClass resolveAndroidMajorClass(jint javaType) int i = 0; jint fieldValue; QBluetoothDeviceInfo::MajorDeviceClass result = QBluetoothDeviceInfo::UncategorizedDevice; - while (majorMappings[i].javaFieldName != Q_NULLPTR) { + while (majorMappings[i].javaFieldName != nullptr) { fieldValue = QAndroidJniObject::getStaticField<jint>( javaBluetoothClassDeviceMajorClassName, majorMappings[i].javaFieldName); if (env->ExceptionCheck()) { @@ -359,7 +359,7 @@ void triggerCachingOfMinorsForMajor(QBluetoothDeviceInfo::MajorDeviceClass major int sizeIndex = minorIndexSizes[mappingIndex]; QAndroidJniEnvironment env; - while (minorMappings[sizeIndex].javaFieldName != Q_NULLPTR) { + while (minorMappings[sizeIndex].javaFieldName != nullptr) { jint fieldValue = QAndroidJniObject::getStaticField<jint>( javaBluetoothClassDeviceClassName, minorMappings[sizeIndex].javaFieldName); if (env->ExceptionCheck()) { // field lookup failed? skip it diff --git a/src/bluetooth/android/lowenergynotificationhub_p.h b/src/bluetooth/android/lowenergynotificationhub_p.h index 4a384a8c..da651e68 100644 --- a/src/bluetooth/android/lowenergynotificationhub_p.h +++ b/src/bluetooth/android/lowenergynotificationhub_p.h @@ -56,10 +56,11 @@ #include <QtCore/private/qjnihelpers_p.h> #include <QtAndroidExtras/QAndroidJniObject> #include <QtBluetooth/QBluetoothAddress> +#include <QtBluetooth/QLowEnergyController> +#include <QtBluetooth/QLowEnergyService> #include <jni.h> #include <QtBluetooth/QLowEnergyCharacteristic> -#include "qlowenergycontroller_p.h" QT_BEGIN_NAMESPACE diff --git a/src/bluetooth/bluetooth.pro b/src/bluetooth/bluetooth.pro index 84919f98..ee548208 100644 --- a/src/bluetooth/bluetooth.pro +++ b/src/bluetooth/bluetooth.pro @@ -46,7 +46,7 @@ PRIVATE_HEADERS += \ qbluetoothtransferrequest_p.h \ qprivatelinearbuffer_p.h \ qbluetoothlocaldevice_p.h \ - qlowenergycontroller_p.h \ + qlowenergycontrollerbase_p.h \ qlowenergyserviceprivate_p.h \ qleadvertiser_p.h \ lecmaccalculator_p.h @@ -76,6 +76,7 @@ SOURCES += \ qlowenergydescriptor.cpp \ qlowenergydescriptordata.cpp \ qlowenergycontroller.cpp \ + qlowenergycontrollerbase.cpp \ qlowenergyserviceprivate.cpp win32 { @@ -87,6 +88,9 @@ qtConfig(bluez) { QT_PRIVATE = concurrent QT_FOR_PRIVATE += dbus + # do not link against QtNetwork but use inline qt_safe_* functions + INCLUDEPATH += $$QT.network_private.includes + include(bluez/bluez.pri) PRIVATE_HEADERS += \ @@ -107,13 +111,20 @@ qtConfig(bluez) { SOURCES += \ qleadvertiser_bluez.cpp \ qlowenergycontroller_bluez.cpp \ - lecmaccalculator.cpp + lecmaccalculator.cpp \ + qlowenergycontroller_bluezdbus.cpp + + PRIVATE_HEADERS += qlowenergycontroller_bluezdbus_p.h \ + qlowenergycontroller_bluez_p.h + qtConfig(linux_crypto_api): DEFINES += CONFIG_LINUX_CRYPTO_API } else { DEFINES += QT_BLUEZ_NO_BTLE include(dummy/dummy.pri) SOURCES += \ qlowenergycontroller_p.cpp + + PRIVATE_HEADERS += qlowenergycontroller_p.h } } else:android:!android-embedded { @@ -126,8 +137,6 @@ qtConfig(bluez) { android.permission.BLUETOOTH_ADMIN \ android.permission.ACCESS_COARSE_LOCATION # since Android 6.0 (API lvl 23) ANDROID_BUNDLED_JAR_DEPENDENCIES = \ - jar/QtAndroidBluetooth-bundled.jar:org.qtproject.qt5.android.bluetooth.QtBluetoothBroadcastReceiver - ANDROID_JAR_DEPENDENCIES = \ jar/QtAndroidBluetooth.jar:org.qtproject.qt5.android.bluetooth.QtBluetoothBroadcastReceiver SOURCES += \ @@ -139,6 +148,8 @@ qtConfig(bluez) { qbluetoothserver_android.cpp \ qlowenergycontroller_android.cpp + PRIVATE_HEADERS += qlowenergycontroller_android_p.h + } else:osx { QT_PRIVATE = concurrent DEFINES += QT_OSX_BLUETOOTH @@ -170,6 +181,7 @@ qtConfig(bluez) { SOURCES -= qlowenergyservice_p.cpp SOURCES -= qlowenergyservice.cpp SOURCES -= qlowenergycontroller.cpp + SOURCES -= qlowenergycontrollerbase.cpp } else:ios|tvos { DEFINES += QT_IOS_BLUETOOTH LIBS_PRIVATE += -framework Foundation -framework CoreBluetooth @@ -193,6 +205,7 @@ qtConfig(bluez) { SOURCES -= qbluetoothdevicediscoveryagent.cpp SOURCES -= qlowenergyservice.cpp SOURCES -= qlowenergycontroller.cpp + SOURCES -= qlowenergycontrollerbase.cpp } else: qtConfig(winrt_bt) { DEFINES += QT_WINRT_BLUETOOTH !winrt { @@ -212,6 +225,8 @@ qtConfig(bluez) { qbluetoothsocket_winrt.cpp \ qlowenergycontroller_winrt.cpp + PRIVATE_HEADERS += qlowenergycontroller_winrt_p.h + lessThan(WINDOWS_SDK_VERSION, 14393) { DEFINES += QT_WINRT_LIMITED_SERVICEDISCOVERY DEFINES += QT_UCRTVERSION=$$WINDOWS_SDK_VERSION @@ -228,6 +243,8 @@ qtConfig(bluez) { qbluetoothsocket_p.cpp \ qbluetoothserver_p.cpp \ qlowenergycontroller_p.cpp + + PRIVATE_HEADERS += qlowenergycontroller_p.h } winrt { diff --git a/src/bluetooth/bluez/adapter.cpp b/src/bluetooth/bluez/adapter.cpp index 10b46f3b..eaea76f8 100644 --- a/src/bluetooth/bluez/adapter.cpp +++ b/src/bluetooth/bluez/adapter.cpp @@ -1,8 +1,8 @@ /* - * This file was generated by qdbusxml2cpp version 0.7 + * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp -p adapter_p.h:adapter.cpp org.bluez.all.xml org.bluez.Adapter * - * Copyright (C) 2015 The Qt Company Ltd. + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * * This is an auto-generated file. * This file may have been hand-edited. Look for HAND-EDIT comments diff --git a/src/bluetooth/bluez/adapter_p.h b/src/bluetooth/bluez/adapter_p.h index d9b6a0c7..236fe7e4 100644 --- a/src/bluetooth/bluez/adapter_p.h +++ b/src/bluetooth/bluez/adapter_p.h @@ -1,15 +1,15 @@ /* - * This file was generated by qdbusxml2cpp version 0.7 + * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp -p adapter_p.h:adapter.cpp org.bluez.all.xml org.bluez.Adapter * - * Copyright (C) 2015 The Qt Company Ltd. + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * * This is an auto-generated file. * Do not edit! All changes made to it will be lost. */ -#ifndef ADAPTER_P_H_1273205927 -#define ADAPTER_P_H_1273205927 +#ifndef ADAPTER_P_H +#define ADAPTER_P_H #include <QtCore/QObject> #include <QtCore/QByteArray> @@ -31,7 +31,7 @@ public: { return "org.bluez.Adapter"; } public: - OrgBluezAdapterInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); + OrgBluezAdapterInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); ~OrgBluezAdapterInterface(); @@ -39,106 +39,106 @@ public Q_SLOTS: // METHODS inline QDBusPendingReply<> CancelDeviceCreation(const QString &in0) { QList<QVariant> argumentList; - argumentList << qVariantFromValue(in0); - return asyncCallWithArgumentList(QLatin1String("CancelDeviceCreation"), argumentList); + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QStringLiteral("CancelDeviceCreation"), argumentList); } inline QDBusPendingReply<QDBusObjectPath> CreateDevice(const QString &in0) { QList<QVariant> argumentList; - argumentList << qVariantFromValue(in0); - return asyncCallWithArgumentList(QLatin1String("CreateDevice"), argumentList); + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QStringLiteral("CreateDevice"), argumentList); } inline QDBusPendingReply<QDBusObjectPath> CreatePairedDevice(const QString &in0, const QDBusObjectPath &in1, const QString &in2) { QList<QVariant> argumentList; - argumentList << qVariantFromValue(in0) << qVariantFromValue(in1) << qVariantFromValue(in2); - return asyncCallWithArgumentList(QLatin1String("CreatePairedDevice"), argumentList); + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1) << QVariant::fromValue(in2); + return asyncCallWithArgumentList(QStringLiteral("CreatePairedDevice"), argumentList); } inline QDBusPendingReply<QDBusObjectPath> FindDevice(const QString &in0) { QList<QVariant> argumentList; - argumentList << qVariantFromValue(in0); - return asyncCallWithArgumentList(QLatin1String("FindDevice"), argumentList); + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QStringLiteral("FindDevice"), argumentList); } inline QDBusPendingReply<QVariantMap> GetProperties() { QList<QVariant> argumentList; - return asyncCallWithArgumentList(QLatin1String("GetProperties"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("GetProperties"), argumentList); } inline QDBusPendingReply<QList<QDBusObjectPath> > ListDevices() { QList<QVariant> argumentList; - return asyncCallWithArgumentList(QLatin1String("ListDevices"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("ListDevices"), argumentList); } inline QDBusPendingReply<> RegisterAgent(const QDBusObjectPath &in0, const QString &in1) { QList<QVariant> argumentList; - argumentList << qVariantFromValue(in0) << qVariantFromValue(in1); - return asyncCallWithArgumentList(QLatin1String("RegisterAgent"), argumentList); + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); + return asyncCallWithArgumentList(QStringLiteral("RegisterAgent"), argumentList); } inline QDBusPendingReply<> ReleaseMode() { QList<QVariant> argumentList; - return asyncCallWithArgumentList(QLatin1String("ReleaseMode"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("ReleaseMode"), argumentList); } inline QDBusPendingReply<> ReleaseSession() { QList<QVariant> argumentList; - return asyncCallWithArgumentList(QLatin1String("ReleaseSession"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("ReleaseSession"), argumentList); } inline QDBusPendingReply<> RemoveDevice(const QDBusObjectPath &in0) { QList<QVariant> argumentList; - argumentList << qVariantFromValue(in0); - return asyncCallWithArgumentList(QLatin1String("RemoveDevice"), argumentList); + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QStringLiteral("RemoveDevice"), argumentList); } inline QDBusPendingReply<> RequestMode(const QString &in0) { QList<QVariant> argumentList; - argumentList << qVariantFromValue(in0); - return asyncCallWithArgumentList(QLatin1String("RequestMode"), argumentList); + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QStringLiteral("RequestMode"), argumentList); } inline QDBusPendingReply<> RequestSession() { QList<QVariant> argumentList; - return asyncCallWithArgumentList(QLatin1String("RequestSession"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("RequestSession"), argumentList); } inline QDBusPendingReply<> SetProperty(const QString &in0, const QDBusVariant &in1) { QList<QVariant> argumentList; - argumentList << qVariantFromValue(in0) << qVariantFromValue(in1); - return asyncCallWithArgumentList(QLatin1String("SetProperty"), argumentList); + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); + return asyncCallWithArgumentList(QStringLiteral("SetProperty"), argumentList); } inline QDBusPendingReply<> StartDiscovery() { QList<QVariant> argumentList; - return asyncCallWithArgumentList(QLatin1String("StartDiscovery"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("StartDiscovery"), argumentList); } inline QDBusPendingReply<> StopDiscovery() { QList<QVariant> argumentList; - return asyncCallWithArgumentList(QLatin1String("StopDiscovery"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("StopDiscovery"), argumentList); } inline QDBusPendingReply<> UnregisterAgent(const QDBusObjectPath &in0) { QList<QVariant> argumentList; - argumentList << qVariantFromValue(in0); - return asyncCallWithArgumentList(QLatin1String("UnregisterAgent"), argumentList); + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QStringLiteral("UnregisterAgent"), argumentList); } Q_SIGNALS: // SIGNALS diff --git a/src/bluetooth/bluez/agent.cpp b/src/bluetooth/bluez/agent.cpp index 89840531..6fa80176 100644 --- a/src/bluetooth/bluez/agent.cpp +++ b/src/bluetooth/bluez/agent.cpp @@ -1,8 +1,8 @@ /* - * This file was generated by qdbusxml2cpp version 0.7 + * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp -c OrgBluezAgentAdaptor -a agent_p.h:agent.cpp org.bluez.Agent.xml org.bluez.Agent * - * Copyright (C) 2015 The Qt Company Ltd. + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * * This is an auto-generated file. * Do not edit! All changes made to it will be lost. diff --git a/src/bluetooth/bluez/agent_p.h b/src/bluetooth/bluez/agent_p.h index 8329089f..32efa62e 100644 --- a/src/bluetooth/bluez/agent_p.h +++ b/src/bluetooth/bluez/agent_p.h @@ -1,20 +1,19 @@ /* - * This file was generated by qdbusxml2cpp version 0.7 + * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp -c OrgBluezAgentAdaptor -a agent_p.h:agent.cpp org.bluez.Agent.xml org.bluez.Agent * - * Copyright (C) 2015 The Qt Company Ltd. + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * * This is an auto-generated file. * This file may have been hand-edited. Look for HAND-EDIT comments * before re-generating it. */ -#ifndef AGENT_P_H_1291941396 -#define AGENT_P_H_1291941396 +#ifndef AGENT_P_H +#define AGENT_P_H #include <QtCore/QObject> #include <QtDBus/QtDBus> - QT_BEGIN_NAMESPACE class QByteArray; template<class T> class QList; diff --git a/src/bluetooth/bluez/bluez.pri b/src/bluetooth/bluez/bluez.pri index b99f2712..a8ca8e22 100644 --- a/src/bluetooth/bluez/bluez.pri +++ b/src/bluetooth/bluez/bluez.pri @@ -17,6 +17,9 @@ HEADERS += bluez/manager_p.h \ bluez/obex_client1_bluez5_p.h \ bluez/obex_objectpush1_bluez5_p.h \ bluez/obex_transfer1_bluez5_p.h \ + bluez/gattchar1_p.h \ + bluez/gattdesc1_p.h \ + bluez/gattservice1_p.h \ bluez/bluez_data_p.h \ bluez/hcimanager_p.h \ bluez/remotedevicemanager_p.h \ @@ -41,6 +44,9 @@ SOURCES += bluez/manager.cpp \ bluez/obex_client1_bluez5.cpp \ bluez/obex_objectpush1_bluez5.cpp \ bluez/obex_transfer1_bluez5.cpp \ + bluez/gattchar1.cpp \ + bluez/gattdesc1.cpp \ + bluez/gattservice1.cpp \ bluez/hcimanager.cpp \ bluez/remotedevicemanager.cpp \ bluez/bluetoothmanagement.cpp diff --git a/src/bluetooth/bluez/bluez5_helper.cpp b/src/bluetooth/bluez/bluez5_helper.cpp index de41003f..90b7e5e0 100644 --- a/src/bluetooth/bluez/bluez5_helper.cpp +++ b/src/bluetooth/bluez/bluez5_helper.cpp @@ -40,7 +40,10 @@ #include <QtCore/QGlobalStatic> #include <QtCore/QLoggingCategory> #include <QtCore/QMap> +#include <QtCore/QVersionNumber> +#include <QtNetwork/private/qnet_unix_p.h> #include "bluez5_helper_p.h" +#include "bluez_data_p.h" #include "objectmanager_p.h" #include "properties_p.h" #include "adapter1_bluez5_p.h" @@ -59,6 +62,7 @@ typedef enum Bluez5TestResultType } Bluez5TestResult; Q_GLOBAL_STATIC_WITH_ARGS(Bluez5TestResult, bluezVersion, (BluezVersionUnknown)); +Q_GLOBAL_STATIC_WITH_ARGS(QVersionNumber, bluezDaemonVersion, (QVersionNumber())); bool isBluez5() { @@ -97,6 +101,183 @@ bool isBluez5() return (*bluezVersion() == BluezVersion5); } +/* + Checks that the mandatory Bluetooth HCI ioctls are offered + by Linux kernel. Returns \c true if the ictls are available; otherwise \c false. + + Mandatory ioctls: + - HCIGETCONNLIST + - HCIGETDEVINFO + - HCIGETDEVLIST + */ +bool mandatoryHciIoctlsAvailable() +{ + // open hci socket + int hciSocket = ::qt_safe_socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); + if (hciSocket < 0) { + qCWarning(QT_BT_BLUEZ) << "Cannot open HCI socket:" << qt_error_string(errno); + return false; + } + + // check HCIGETDEVLIST & HCIGETDEVLIST + struct hci_dev_req *devRequest = 0; + struct hci_dev_list_req *devRequestList = 0; + struct hci_dev_info devInfo; + const int devListSize = sizeof(struct hci_dev_list_req) + + HCI_MAX_DEV * sizeof(struct hci_dev_req); + + devRequestList = (hci_dev_list_req *) malloc(devListSize); + if (!devRequestList) { + qt_safe_close(hciSocket); + return false; // if we cannot malloc nothing will help anyway + } + + QScopedPointer<hci_dev_list_req, QScopedPointerPodDeleter> pDevList(devRequestList); + memset(pDevList.data(), 0, devListSize); + pDevList->dev_num = HCI_MAX_DEV; + devRequest = pDevList->dev_req; + + if (qt_safe_ioctl(hciSocket, HCIGETDEVLIST, devRequestList) < 0) { + qt_safe_close(hciSocket); + qCWarning(QT_BT_BLUEZ) << "HCI icotl HCIGETDEVLIST:" << qt_error_string(errno); + return false; + } + + if (devRequestList->dev_num > 0) { + devInfo.dev_id = devRequest->dev_id; + if (qt_safe_ioctl(hciSocket, HCIGETDEVINFO, &devInfo) < 0) { + qt_safe_close(hciSocket); + qCWarning(QT_BT_BLUEZ) << "HCI icotl HCIGETDEVINFO:" << qt_error_string(errno); + return false; + } + } + + // check HCIGETCONNLIST + const int maxNoOfConnections = 20; + hci_conn_list_req *infoList = nullptr; + infoList = (hci_conn_list_req *) + malloc(sizeof(hci_conn_list_req) + maxNoOfConnections * sizeof(hci_conn_info)); + + if (!infoList) { + qt_safe_close(hciSocket); + return false; + } + + QScopedPointer<hci_conn_list_req, QScopedPointerPodDeleter> pInfoList(infoList); + pInfoList->conn_num = maxNoOfConnections; + pInfoList->dev_id = devInfo.dev_id; + + if (qt_safe_ioctl(hciSocket, HCIGETCONNLIST, (void *) infoList) < 0) { + qCWarning(QT_BT_BLUEZ) << "HCI icotl HCIGETCONNLIST:" << qt_error_string(errno); + qt_safe_close(hciSocket); + return false; + } + + qt_safe_close(hciSocket); + return true; +} + +/*! + * This function returns the version of bluetoothd in use on the system. + * This is required to determine which QLEControllerPrivate implementation + * is required. The following version tags are of significance: + * + * Version < 4.0 -> QLEControllerPrivateCommon + * Version < 5.42 -> QLEControllerPrivateBluez + * Version >= 5.42 -> QLEControllerPrivateBluezDBus + * + * This function utilizes a singleton pattern. It always returns a cached + * version tag which is determined on first call. This is necessary to + * avoid continuesly running the somewhat expensive tests. + * + * The function must never return a null QVersionNumber. + */ +QVersionNumber bluetoothdVersion() +{ + if (bluezDaemonVersion()->isNull()) { + qCDebug(QT_BT_BLUEZ) << "Detecting bluetoothd version"; + //Order of matching + // 1. Pick whatever the user decides via BLUETOOTH_USE_BLUEZ_DBUS_LE + const QString version = qEnvironmentVariable("BLUETOOTH_USE_BLUEZ_DBUS_LE"); + if (!version.isNull()) { + const QVersionNumber vn = QVersionNumber::fromString(version); + if (!vn.isNull()) { + *bluezDaemonVersion() = vn; + qCDebug(QT_BT_BLUEZ) << "Forcing Bluez LE API selection:" + << bluezDaemonVersion()->toString(); + } + } + + // 2. Find bluetoothd binary and check "bluetoothd --version" + if (bluezDaemonVersion()->isNull() && qt_haveLinuxProcfs()) { + QDBusConnection session = QDBusConnection::systemBus(); + qint64 pid = session.interface()->servicePid(QStringLiteral("org.bluez")).value(); + QByteArray buffer; + + auto determineBinaryVersion = [](const QString &binary) -> QVersionNumber { + QProcess process; + process.start(binary, {QStringLiteral("--version")}); + process.waitForFinished(); + + const QString version = QString::fromLocal8Bit(process.readAll()); + const QVersionNumber vn = QVersionNumber::fromString(version); + if (!vn.isNull()) + qCDebug(QT_BT_BLUEZ) << "Detected bluetoothd version" << vn; + return vn; + }; + + //try reading /proc/<pid>/exe first -> requires process owner + qCDebug(QT_BT_BLUEZ) << "Using /proc/<pid>/exe"; + const QString procExe = QStringLiteral("/proc/%1/exe").arg(pid); + const QVersionNumber vn = determineBinaryVersion(procExe); + if (!vn.isNull()) + *bluezDaemonVersion() = vn; + + if (bluezDaemonVersion()->isNull()) { + qCDebug(QT_BT_BLUEZ) << "Using /proc/<pid>/cmdline"; + //try to reading /proc/<pid>/cmdline (does not require additional process rights) + QFile procFile(QStringLiteral("/proc/%1/cmdline").arg(pid)); + if (procFile.open(QIODevice::ReadOnly|QIODevice::Text)) { + buffer = procFile.readAll(); + procFile.close(); + + // cmdline params separated by character \0 -> first is bluetoothd binary + const QString binary = QString::fromLocal8Bit(buffer.split('\0').at(0)); + QFileInfo info(binary); + if (info.isExecutable()) + *bluezDaemonVersion() = determineBinaryVersion(binary); + else + qCDebug(QT_BT_BLUEZ) << "Cannot determine bluetoothd version via cmdline:" + << binary; + } + } + } + + // 3. Fall back to custom ATT backend, if possible? + if (bluezDaemonVersion()->isNull()) { + // Check mandatory HCI ioctls are available + if (mandatoryHciIoctlsAvailable()) { + // default 4.0 for now -> implies custom (G)ATT implementation + *bluezDaemonVersion() = QVersionNumber(4, 0); + } + } + + // 4. Ultimate fallback -> enable dummy backend + if (bluezDaemonVersion()->isNull()) { + // version 3 represents disabled BTLE + // bluezDaemonVersion should not be null to avoid repeated version tests + *bluezDaemonVersion() = QVersionNumber(3, 0); + qCWarning(QT_BT_BLUEZ) << "Cannot determine bluetoothd version and required Bluetooth HCI ioctols"; + qCWarning(QT_BT_BLUEZ) << "Disabling Qt Bluetooth LE feature"; + } + + qCDebug(QT_BT_BLUEZ) << "Bluetoothd:" << bluezDaemonVersion()->toString(); + } + + Q_ASSERT(!bluezDaemonVersion()->isNull()); + return *bluezDaemonVersion(); +} + struct AdapterData { public: diff --git a/src/bluetooth/bluez/bluez5_helper_p.h b/src/bluetooth/bluez/bluez5_helper_p.h index 2d72caf1..1747f249 100644 --- a/src/bluetooth/bluez/bluez5_helper_p.h +++ b/src/bluetooth/bluez/bluez5_helper_p.h @@ -54,6 +54,7 @@ #include <QtCore/QObject> #include <QtDBus/QtDBus> #include <QtBluetooth/QBluetoothAddress> +#include <QtBluetooth/private/qtbluetoothglobal_p.h> typedef QMap<QString, QVariantMap> InterfaceList; typedef QMap<QDBusObjectPath, InterfaceList> ManagedObjectList; @@ -67,6 +68,9 @@ QT_BEGIN_NAMESPACE bool isBluez5(); +// exported for unit test purposes +Q_BLUETOOTH_PRIVATE_EXPORT QVersionNumber bluetoothdVersion(); + QString sanitizeNameForDBus(const QString& text); QString findAdapterForAddress(const QBluetoothAddress &wantedAddress, bool *ok); diff --git a/src/bluetooth/bluez/bluez_data_p.h b/src/bluetooth/bluez/bluez_data_p.h index 684cd5b8..2a2e597c 100644 --- a/src/bluetooth/bluez/bluez_data_p.h +++ b/src/bluetooth/bluez/bluez_data_p.h @@ -123,6 +123,10 @@ struct bt_security { #error "Unknown byte order" #endif +#define HCIGETCONNLIST _IOR('H', 212, int) +#define HCIGETDEVINFO _IOR('H', 211, int) +#define HCIGETDEVLIST _IOR('H', 210, int) + // Bluetooth address typedef struct { quint8 b[6]; diff --git a/src/bluetooth/bluez/device.cpp b/src/bluetooth/bluez/device.cpp index 5dc814dc..14b91ad0 100644 --- a/src/bluetooth/bluez/device.cpp +++ b/src/bluetooth/bluez/device.cpp @@ -1,8 +1,8 @@ /* - * This file was generated by qdbusxml2cpp version 0.7 + * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp -i servicemap_p.h -p device_p.h:device.cpp org.bluez.Device.xml org.bluez.Device * - * Copyright (C) 2015 The Qt Company Ltd. + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * * This is an auto-generated file. * This file may have been hand-edited. Look for HAND-EDIT comments diff --git a/src/bluetooth/bluez/device1_bluez5.cpp b/src/bluetooth/bluez/device1_bluez5.cpp index 491a365d..cd6453ad 100644 --- a/src/bluetooth/bluez/device1_bluez5.cpp +++ b/src/bluetooth/bluez/device1_bluez5.cpp @@ -1,5 +1,6 @@ /* * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -p device1_bluez5_p.h:device1_bluez5.cpp org.bluez.Device1.xml * * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * diff --git a/src/bluetooth/bluez/device1_bluez5_p.h b/src/bluetooth/bluez/device1_bluez5_p.h index 4feb5318..b9523a56 100644 --- a/src/bluetooth/bluez/device1_bluez5_p.h +++ b/src/bluetooth/bluez/device1_bluez5_p.h @@ -1,5 +1,6 @@ /* * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -p device1_bluez5_p.h:device1_bluez5.cpp org.bluez.Device1.xml * * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * diff --git a/src/bluetooth/bluez/device_p.h b/src/bluetooth/bluez/device_p.h index 417db3d9..2e1e39ad 100644 --- a/src/bluetooth/bluez/device_p.h +++ b/src/bluetooth/bluez/device_p.h @@ -1,15 +1,15 @@ /* - * This file was generated by qdbusxml2cpp version 0.7 + * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp -i servicemap_p.h -p device_p.h:device.cpp org.bluez.Device.xml org.bluez.Device * - * Copyright (C) 2015 The Qt Company Ltd. + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * * This is an auto-generated file. * Do not edit! All changes made to it will be lost. */ -#ifndef DEVICE_P_H_1273205927 -#define DEVICE_P_H_1273205927 +#ifndef DEVICE_P_H +#define DEVICE_P_H #include <QtCore/QObject> #include <QtCore/QByteArray> @@ -32,7 +32,7 @@ public: { return "org.bluez.Device"; } public: - OrgBluezDeviceInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); + OrgBluezDeviceInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); ~OrgBluezDeviceInterface(); @@ -40,53 +40,53 @@ public Q_SLOTS: // METHODS inline QDBusPendingReply<> CancelDiscovery() { QList<QVariant> argumentList; - return asyncCallWithArgumentList(QLatin1String("CancelDiscovery"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("CancelDiscovery"), argumentList); } inline QDBusPendingReply<QDBusObjectPath> CreateNode(const QString &in0) { QList<QVariant> argumentList; - argumentList << qVariantFromValue(in0); - return asyncCallWithArgumentList(QLatin1String("CreateNode"), argumentList); + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QStringLiteral("CreateNode"), argumentList); } inline QDBusPendingReply<> Disconnect() { QList<QVariant> argumentList; - return asyncCallWithArgumentList(QLatin1String("Disconnect"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("Disconnect"), argumentList); } inline QDBusPendingReply<ServiceMap> DiscoverServices(const QString &in0) { QList<QVariant> argumentList; - argumentList << qVariantFromValue(in0); - return asyncCallWithArgumentList(QLatin1String("DiscoverServices"), argumentList); + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QStringLiteral("DiscoverServices"), argumentList); } inline QDBusPendingReply<QVariantMap> GetProperties() { QList<QVariant> argumentList; - return asyncCallWithArgumentList(QLatin1String("GetProperties"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("GetProperties"), argumentList); } inline QDBusPendingReply<QList<QDBusObjectPath> > ListNodes() { QList<QVariant> argumentList; - return asyncCallWithArgumentList(QLatin1String("ListNodes"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("ListNodes"), argumentList); } inline QDBusPendingReply<> RemoveNode(const QDBusObjectPath &in0) { QList<QVariant> argumentList; - argumentList << qVariantFromValue(in0); - return asyncCallWithArgumentList(QLatin1String("RemoveNode"), argumentList); + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QStringLiteral("RemoveNode"), argumentList); } inline QDBusPendingReply<> SetProperty(const QString &in0, const QDBusVariant &in1) { QList<QVariant> argumentList; - argumentList << qVariantFromValue(in0) << qVariantFromValue(in1); - return asyncCallWithArgumentList(QLatin1String("SetProperty"), argumentList); + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); + return asyncCallWithArgumentList(QStringLiteral("SetProperty"), argumentList); } Q_SIGNALS: // SIGNALS diff --git a/src/bluetooth/bluez/gattchar1.cpp b/src/bluetooth/bluez/gattchar1.cpp new file mode 100644 index 00000000..cdb3fc0d --- /dev/null +++ b/src/bluetooth/bluez/gattchar1.cpp @@ -0,0 +1,26 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -p gattchar1_p.h:gattchar1.cpp org.bluez.GattCharacteristic1.xml + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "gattchar1_p.h" + +/* + * Implementation of interface class OrgBluezGattCharacteristic1Interface + */ + +OrgBluezGattCharacteristic1Interface::OrgBluezGattCharacteristic1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +OrgBluezGattCharacteristic1Interface::~OrgBluezGattCharacteristic1Interface() +{ +} + diff --git a/src/bluetooth/bluez/gattchar1_p.h b/src/bluetooth/bluez/gattchar1_p.h new file mode 100644 index 00000000..c19e9f58 --- /dev/null +++ b/src/bluetooth/bluez/gattchar1_p.h @@ -0,0 +1,93 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -p gattchar1_p.h:gattchar1.cpp org.bluez.GattCharacteristic1.xml + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef GATTCHAR1_P_H +#define GATTCHAR1_P_H + +#include <QtCore/QObject> +#include <QtCore/QByteArray> +#include <QtCore/QList> +#include <QtCore/QMap> +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QVariant> +#include <QtDBus/QtDBus> + +/* + * Proxy class for interface org.bluez.GattCharacteristic1 + */ +class OrgBluezGattCharacteristic1Interface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "org.bluez.GattCharacteristic1"; } + +public: + OrgBluezGattCharacteristic1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); + + ~OrgBluezGattCharacteristic1Interface(); + + Q_PROPERTY(QStringList Flags READ flags) + inline QStringList flags() const + { return qvariant_cast< QStringList >(property("Flags")); } + + Q_PROPERTY(bool Notifying READ notifying) + inline bool notifying() const + { return qvariant_cast< bool >(property("Notifying")); } + + Q_PROPERTY(QDBusObjectPath Service READ service) + inline QDBusObjectPath service() const + { return qvariant_cast< QDBusObjectPath >(property("Service")); } + + Q_PROPERTY(QString UUID READ uUID) + inline QString uUID() const + { return qvariant_cast< QString >(property("UUID")); } + + Q_PROPERTY(QByteArray Value READ value) + inline QByteArray value() const + { return qvariant_cast< QByteArray >(property("Value")); } + +public Q_SLOTS: // METHODS + inline QDBusPendingReply<QByteArray> ReadValue(const QVariantMap &options) + { + QList<QVariant> argumentList; + argumentList << QVariant::fromValue(options); + return asyncCallWithArgumentList(QStringLiteral("ReadValue"), argumentList); + } + + inline QDBusPendingReply<> StartNotify() + { + QList<QVariant> argumentList; + return asyncCallWithArgumentList(QStringLiteral("StartNotify"), argumentList); + } + + inline QDBusPendingReply<> StopNotify() + { + QList<QVariant> argumentList; + return asyncCallWithArgumentList(QStringLiteral("StopNotify"), argumentList); + } + + inline QDBusPendingReply<> WriteValue(const QByteArray &value, const QVariantMap &options) + { + QList<QVariant> argumentList; + argumentList << QVariant::fromValue(value) << QVariant::fromValue(options); + return asyncCallWithArgumentList(QStringLiteral("WriteValue"), argumentList); + } + +Q_SIGNALS: // SIGNALS +}; + +namespace org { + namespace bluez { + typedef ::OrgBluezGattCharacteristic1Interface GattCharacteristic1; + } +} +#endif diff --git a/src/bluetooth/bluez/gattdesc1.cpp b/src/bluetooth/bluez/gattdesc1.cpp new file mode 100644 index 00000000..8447e49b --- /dev/null +++ b/src/bluetooth/bluez/gattdesc1.cpp @@ -0,0 +1,26 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -p gattdesc1_p.h:gattdesc1.cpp org.bluez.GattDescriptor1.xml + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "gattdesc1_p.h" + +/* + * Implementation of interface class OrgBluezGattDescriptor1Interface + */ + +OrgBluezGattDescriptor1Interface::OrgBluezGattDescriptor1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +OrgBluezGattDescriptor1Interface::~OrgBluezGattDescriptor1Interface() +{ +} + diff --git a/src/bluetooth/bluez/gattdesc1_p.h b/src/bluetooth/bluez/gattdesc1_p.h new file mode 100644 index 00000000..6ade7a42 --- /dev/null +++ b/src/bluetooth/bluez/gattdesc1_p.h @@ -0,0 +1,73 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -p gattdesc1_p.h:gattdesc1.cpp org.bluez.GattDescriptor1.xml + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef GATTDESC1_P_H +#define GATTDESC1_P_H + +#include <QtCore/QObject> +#include <QtCore/QByteArray> +#include <QtCore/QList> +#include <QtCore/QMap> +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QVariant> +#include <QtDBus/QtDBus> + +/* + * Proxy class for interface org.bluez.GattDescriptor1 + */ +class OrgBluezGattDescriptor1Interface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "org.bluez.GattDescriptor1"; } + +public: + OrgBluezGattDescriptor1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); + + ~OrgBluezGattDescriptor1Interface(); + + Q_PROPERTY(QDBusObjectPath Characteristic READ characteristic) + inline QDBusObjectPath characteristic() const + { return qvariant_cast< QDBusObjectPath >(property("Characteristic")); } + + Q_PROPERTY(QString UUID READ uUID) + inline QString uUID() const + { return qvariant_cast< QString >(property("UUID")); } + + Q_PROPERTY(QByteArray Value READ value) + inline QByteArray value() const + { return qvariant_cast< QByteArray >(property("Value")); } + +public Q_SLOTS: // METHODS + inline QDBusPendingReply<QByteArray> ReadValue(const QVariantMap &options) + { + QList<QVariant> argumentList; + argumentList << QVariant::fromValue(options); + return asyncCallWithArgumentList(QStringLiteral("ReadValue"), argumentList); + } + + inline QDBusPendingReply<> WriteValue(const QByteArray &value, const QVariantMap &options) + { + QList<QVariant> argumentList; + argumentList << QVariant::fromValue(value) << QVariant::fromValue(options); + return asyncCallWithArgumentList(QStringLiteral("WriteValue"), argumentList); + } + +Q_SIGNALS: // SIGNALS +}; + +namespace org { + namespace bluez { + typedef ::OrgBluezGattDescriptor1Interface GattDescriptor1; + } +} +#endif diff --git a/src/bluetooth/bluez/gattservice1.cpp b/src/bluetooth/bluez/gattservice1.cpp new file mode 100644 index 00000000..0b80ac90 --- /dev/null +++ b/src/bluetooth/bluez/gattservice1.cpp @@ -0,0 +1,26 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -p gattservice1_p.h:gattservice1.cpp org.bluez.GattService1.xml + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "gattservice1_p.h" + +/* + * Implementation of interface class OrgBluezGattService1Interface + */ + +OrgBluezGattService1Interface::OrgBluezGattService1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +OrgBluezGattService1Interface::~OrgBluezGattService1Interface() +{ +} + diff --git a/src/bluetooth/bluez/gattservice1_p.h b/src/bluetooth/bluez/gattservice1_p.h new file mode 100644 index 00000000..128305f1 --- /dev/null +++ b/src/bluetooth/bluez/gattservice1_p.h @@ -0,0 +1,63 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -p gattservice1_p.h:gattservice1.cpp org.bluez.GattService1.xml + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef GATTSERVICE1_P_H +#define GATTSERVICE1_P_H + +#include <QtCore/QObject> +#include <QtCore/QByteArray> +#include <QtCore/QList> +#include <QtCore/QMap> +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QVariant> +#include <QtDBus/QtDBus> + +/* + * Proxy class for interface org.bluez.GattService1 + */ +class OrgBluezGattService1Interface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "org.bluez.GattService1"; } + +public: + OrgBluezGattService1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); + + ~OrgBluezGattService1Interface(); + + Q_PROPERTY(QDBusObjectPath Device READ device) + inline QDBusObjectPath device() const + { return qvariant_cast< QDBusObjectPath >(property("Device")); } + + Q_PROPERTY(QList<QDBusObjectPath> Includes READ includes) + inline QList<QDBusObjectPath> includes() const + { return qvariant_cast< QList<QDBusObjectPath> >(property("Includes")); } + + Q_PROPERTY(bool Primary READ primary) + inline bool primary() const + { return qvariant_cast< bool >(property("Primary")); } + + Q_PROPERTY(QString UUID READ uUID) + inline QString uUID() const + { return qvariant_cast< QString >(property("UUID")); } + +public Q_SLOTS: // METHODS +Q_SIGNALS: // SIGNALS +}; + +namespace org { + namespace bluez { + typedef ::OrgBluezGattService1Interface GattService1; + } +} +#endif diff --git a/src/bluetooth/bluez/generate b/src/bluetooth/bluez/generate index cdba18c4..caae92f6 100755 --- a/src/bluetooth/bluez/generate +++ b/src/bluetooth/bluez/generate @@ -20,3 +20,7 @@ qdbusxml2cpp -p properties_p.h:properties.cpp org.freedesktop.dbus.properties.xm qdbusxml2cpp -p obex_client1_bluez5_p.h:obex_client1_bluez5_p.h org.bluez.Client1.xml qdbusxml2cpp -p obex_objectpush1_bluez5_p.h:obex_objectpush1_bluez5.cpp org.bluez.obex.ObjectPush1.xml qdbusxml2cpp -p obex_transfer1_bluez5_p.h:obex_transfer1_bluez5_p.h org.bluez.obex.Transfer1.xml +qdbusxml2cpp -p gattchar1_p.h:gattchar1.cpp org.bluez.GattCharacteristic1.xml +qdbusxml2cpp -p gattdesc1_p.h:gattdesc1.cpp org.bluez.GattDescriptor1.xml +qdbusxml2cpp -p gattservice1_p.h:gattservice1.cpp org.bluez.GattService1.xml + diff --git a/src/bluetooth/bluez/hcimanager.cpp b/src/bluetooth/bluez/hcimanager.cpp index c524117c..be62c881 100644 --- a/src/bluetooth/bluez/hcimanager.cpp +++ b/src/bluetooth/bluez/hcimanager.cpp @@ -53,10 +53,6 @@ #include <sys/uio.h> #include <unistd.h> -#define HCIGETCONNLIST _IOR('H', 212, int) -#define HCIGETDEVINFO _IOR('H', 211, int) -#define HCIGETDEVLIST _IOR('H', 210, int) - QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ) diff --git a/src/bluetooth/bluez/manager.cpp b/src/bluetooth/bluez/manager.cpp index b5d6590d..8ca6fb42 100644 --- a/src/bluetooth/bluez/manager.cpp +++ b/src/bluetooth/bluez/manager.cpp @@ -1,8 +1,8 @@ /* - * This file was generated by qdbusxml2cpp version 0.7 + * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp -p manager_p.h:manager.cpp org.bluez.Manager.xml org.bluez.Manager * - * Copyright (C) 2015 The Qt Company Ltd. + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * * This is an auto-generated file. * This file may have been hand-edited. Look for HAND-EDIT comments diff --git a/src/bluetooth/bluez/manager_p.h b/src/bluetooth/bluez/manager_p.h index edb1c73b..a969e067 100644 --- a/src/bluetooth/bluez/manager_p.h +++ b/src/bluetooth/bluez/manager_p.h @@ -1,15 +1,15 @@ /* - * This file was generated by qdbusxml2cpp version 0.7 + * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp -p manager_p.h:manager.cpp org.bluez.Manager.xml org.bluez.Manager * - * Copyright (C) 2015 The Qt Company Ltd. + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * * This is an auto-generated file. * Do not edit! All changes made to it will be lost. */ -#ifndef MANAGER_P_H_1273205927 -#define MANAGER_P_H_1273205927 +#ifndef MANAGER_P_H +#define MANAGER_P_H #include <QtCore/QObject> #include <QtCore/QByteArray> @@ -31,7 +31,7 @@ public: { return "org.bluez.Manager"; } public: - OrgBluezManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); + OrgBluezManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); ~OrgBluezManagerInterface(); @@ -39,20 +39,20 @@ public Q_SLOTS: // METHODS inline QDBusPendingReply<QDBusObjectPath> DefaultAdapter() { QList<QVariant> argumentList; - return asyncCallWithArgumentList(QLatin1String("DefaultAdapter"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("DefaultAdapter"), argumentList); } inline QDBusPendingReply<QDBusObjectPath> FindAdapter(const QString &in0) { QList<QVariant> argumentList; - argumentList << qVariantFromValue(in0); - return asyncCallWithArgumentList(QLatin1String("FindAdapter"), argumentList); + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QStringLiteral("FindAdapter"), argumentList); } inline QDBusPendingReply<QList<QDBusObjectPath> > ListAdapters() { QList<QVariant> argumentList; - return asyncCallWithArgumentList(QLatin1String("ListAdapters"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("ListAdapters"), argumentList); } Q_SIGNALS: // SIGNALS diff --git a/src/bluetooth/bluez/obex_agent.cpp b/src/bluetooth/bluez/obex_agent.cpp index c5252898..5bc05f87 100644 --- a/src/bluetooth/bluez/obex_agent.cpp +++ b/src/bluetooth/bluez/obex_agent.cpp @@ -1,8 +1,8 @@ /* - * This file was generated by qdbusxml2cpp version 0.7 - * Command line was: qdbusxml2cpp -a obex_agent_p.h:obex_agent.cpp org.openobex.agent.xml + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -a obex_agent_p.h:obex_agent.cpp org.openobex.agent.xml org.openobex.Agent * - * Copyright (C) 2015 The Qt Company Ltd. + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * * This is an auto-generated file. * Do not edit! All changes made to it will be lost. diff --git a/src/bluetooth/bluez/obex_agent_p.h b/src/bluetooth/bluez/obex_agent_p.h index 8af38d86..242b2598 100644 --- a/src/bluetooth/bluez/obex_agent_p.h +++ b/src/bluetooth/bluez/obex_agent_p.h @@ -1,20 +1,19 @@ /* - * This file was generated by qdbusxml2cpp version 0.7 - * Command line was: qdbusxml2cpp -a obex_agent_p.h:obex_agent.cpp org.openobex.agent.xml + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -a obex_agent_p.h:obex_agent.cpp org.openobex.agent.xml org.openobex.Agent * - * Copyright (C) 2015 The Qt Company Ltd. + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * * This is an auto-generated file. * This file may have been hand-edited. Look for HAND-EDIT comments * before re-generating it. */ -#ifndef OBEX_AGENT_P_H_1291359033 -#define OBEX_AGENT_P_H_1291359033 +#ifndef OBEX_AGENT_P_H +#define OBEX_AGENT_P_H #include <QtCore/QObject> #include <QtDBus/QtDBus> - QT_BEGIN_NAMESPACE class QByteArray; template<class T> class QList; diff --git a/src/bluetooth/bluez/obex_client.cpp b/src/bluetooth/bluez/obex_client.cpp index 07730d42..bef9155a 100644 --- a/src/bluetooth/bluez/obex_client.cpp +++ b/src/bluetooth/bluez/obex_client.cpp @@ -1,8 +1,8 @@ /* - * This file was generated by qdbusxml2cpp version 0.7 + * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp -p obex_client_p.h:obex_client.cpp org.openobex.client.xml org.openobex.Client * - * Copyright (C) 2015 The Qt Company Ltd. + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * * This is an auto-generated file. * This file may have been hand-edited. Look for HAND-EDIT comments diff --git a/src/bluetooth/bluez/obex_client1_bluez5_p.h b/src/bluetooth/bluez/obex_client1_bluez5_p.h index 5133faea..ccd5b0d6 100644 --- a/src/bluetooth/bluez/obex_client1_bluez5_p.h +++ b/src/bluetooth/bluez/obex_client1_bluez5_p.h @@ -1,15 +1,15 @@ /* * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp org.bluez.Client1.xml -p asd + * Command line was: qdbusxml2cpp -p obex_client1_bluez5_p.h:obex_client1_bluez5_p.h org.bluez.Client1.xml * - * qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd. + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * * This is an auto-generated file. * Do not edit! All changes made to it will be lost. */ -#ifndef ASD_H_1399976174 -#define ASD_H_1399976174 +#ifndef OBEX_CLIENT1_BLUEZ5_P_H +#define OBEX_CLIENT1_BLUEZ5_P_H #include <QtCore/QObject> #include <QtCore/QByteArray> @@ -31,7 +31,7 @@ public: { return "org.bluez.obex.Client1"; } public: - OrgBluezObexClient1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); + OrgBluezObexClient1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); ~OrgBluezObexClient1Interface(); @@ -40,14 +40,14 @@ public Q_SLOTS: // METHODS { QList<QVariant> argumentList; argumentList << QVariant::fromValue(destination) << QVariant::fromValue(args); - return asyncCallWithArgumentList(QLatin1String("CreateSession"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("CreateSession"), argumentList); } inline QDBusPendingReply<> RemoveSession(const QDBusObjectPath &session) { QList<QVariant> argumentList; argumentList << QVariant::fromValue(session); - return asyncCallWithArgumentList(QLatin1String("RemoveSession"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("RemoveSession"), argumentList); } Q_SIGNALS: // SIGNALS diff --git a/src/bluetooth/bluez/obex_client_p.h b/src/bluetooth/bluez/obex_client_p.h index b2dd0f61..13b638b6 100644 --- a/src/bluetooth/bluez/obex_client_p.h +++ b/src/bluetooth/bluez/obex_client_p.h @@ -1,15 +1,15 @@ /* - * This file was generated by qdbusxml2cpp version 0.7 + * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp -p obex_client_p.h:obex_client.cpp org.openobex.client.xml org.openobex.Client * - * Copyright (C) 2015 The Qt Company Ltd. + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * * This is an auto-generated file. * Do not edit! All changes made to it will be lost. */ -#ifndef OBEX_CLIENT_P_H_1291349694 -#define OBEX_CLIENT_P_H_1291349694 +#ifndef OBEX_CLIENT_P_H +#define OBEX_CLIENT_P_H #include <QtCore/QObject> #include <QtCore/QByteArray> @@ -31,7 +31,7 @@ public: { return "org.openobex.Client"; } public: - OrgOpenobexClientInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); + OrgOpenobexClientInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); ~OrgOpenobexClientInterface(); @@ -39,36 +39,36 @@ public Q_SLOTS: // METHODS inline QDBusPendingReply<QDBusObjectPath> CreateSession(const QVariantMap &in0) { QList<QVariant> argumentList; - argumentList << qVariantFromValue(in0); - return asyncCallWithArgumentList(QLatin1String("CreateSession"), argumentList); + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QStringLiteral("CreateSession"), argumentList); } inline QDBusPendingReply<> ExchangeBusinessCards(const QVariantMap &in0, const QString &in1, const QString &in2) { QList<QVariant> argumentList; - argumentList << qVariantFromValue(in0) << qVariantFromValue(in1) << qVariantFromValue(in2); - return asyncCallWithArgumentList(QLatin1String("ExchangeBusinessCards"), argumentList); + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1) << QVariant::fromValue(in2); + return asyncCallWithArgumentList(QStringLiteral("ExchangeBusinessCards"), argumentList); } inline QDBusPendingReply<QString> GetCapabilities(const QVariantMap &in0) { QList<QVariant> argumentList; - argumentList << qVariantFromValue(in0); - return asyncCallWithArgumentList(QLatin1String("GetCapabilities"), argumentList); + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QStringLiteral("GetCapabilities"), argumentList); } inline QDBusPendingReply<> PullBusinessCard(const QVariantMap &in0, const QString &in1) { QList<QVariant> argumentList; - argumentList << qVariantFromValue(in0) << qVariantFromValue(in1); - return asyncCallWithArgumentList(QLatin1String("PullBusinessCard"), argumentList); + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); + return asyncCallWithArgumentList(QStringLiteral("PullBusinessCard"), argumentList); } inline QDBusPendingReply<> SendFiles(const QVariantMap &in0, const QStringList &in1, const QDBusObjectPath &in2) { QList<QVariant> argumentList; - argumentList << qVariantFromValue(in0) << qVariantFromValue(in1) << qVariantFromValue(in2); - return asyncCallWithArgumentList(QLatin1String("SendFiles"), argumentList); + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1) << QVariant::fromValue(in2); + return asyncCallWithArgumentList(QStringLiteral("SendFiles"), argumentList); } Q_SIGNALS: // SIGNALS diff --git a/src/bluetooth/bluez/obex_manager.cpp b/src/bluetooth/bluez/obex_manager.cpp index 0eb5d1c8..cc6e0ecb 100644 --- a/src/bluetooth/bluez/obex_manager.cpp +++ b/src/bluetooth/bluez/obex_manager.cpp @@ -1,8 +1,8 @@ /* - * This file was generated by qdbusxml2cpp version 0.7 + * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp -p obex_manager_p.h:obex_manager.cpp org.openobex.all.xml org.openobex.Manager * - * Copyright (C) 2015 The Qt Company Ltd. + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * * This is an auto-generated file. * This file may have been hand-edited. Look for HAND-EDIT comments diff --git a/src/bluetooth/bluez/obex_manager_p.h b/src/bluetooth/bluez/obex_manager_p.h index a6e4d189..822954ab 100644 --- a/src/bluetooth/bluez/obex_manager_p.h +++ b/src/bluetooth/bluez/obex_manager_p.h @@ -1,15 +1,15 @@ /* - * This file was generated by qdbusxml2cpp version 0.7 + * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp -p obex_manager_p.h:obex_manager.cpp org.openobex.all.xml org.openobex.Manager * - * Copyright (C) 2015 The Qt Company Ltd. + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * * This is an auto-generated file. * Do not edit! All changes made to it will be lost. */ -#ifndef OBEX_MANAGER_P_H_1291186314 -#define OBEX_MANAGER_P_H_1291186314 +#ifndef OBEX_MANAGER_P_H +#define OBEX_MANAGER_P_H #include <QtCore/QObject> #include <QtCore/QByteArray> @@ -31,7 +31,7 @@ public: { return "org.openobex.Manager"; } public: - OrgOpenobexManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); + OrgOpenobexManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); ~OrgOpenobexManagerInterface(); @@ -39,15 +39,15 @@ public Q_SLOTS: // METHODS inline QDBusPendingReply<> RegisterAgent(const QDBusObjectPath &in0) { QList<QVariant> argumentList; - argumentList << qVariantFromValue(in0); - return asyncCallWithArgumentList(QLatin1String("RegisterAgent"), argumentList); + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QStringLiteral("RegisterAgent"), argumentList); } inline QDBusPendingReply<> UnregisterAgent(const QDBusObjectPath &in0) { QList<QVariant> argumentList; - argumentList << qVariantFromValue(in0); - return asyncCallWithArgumentList(QLatin1String("UnregisterAgent"), argumentList); + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QStringLiteral("UnregisterAgent"), argumentList); } Q_SIGNALS: // SIGNALS diff --git a/src/bluetooth/bluez/obex_objectpush1_bluez5.cpp b/src/bluetooth/bluez/obex_objectpush1_bluez5.cpp index 6edb27a8..59b94e80 100644 --- a/src/bluetooth/bluez/obex_objectpush1_bluez5.cpp +++ b/src/bluetooth/bluez/obex_objectpush1_bluez5.cpp @@ -1,8 +1,8 @@ /* * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp org.bluez.obex.ObjectPush1.xml -p obex_objectpush1_bluez5 + * Command line was: qdbusxml2cpp -p obex_objectpush1_bluez5_p.h:obex_objectpush1_bluez5.cpp org.bluez.obex.ObjectPush1.xml * - * qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd. + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * * This is an auto-generated file. * This file may have been hand-edited. Look for HAND-EDIT comments diff --git a/src/bluetooth/bluez/obex_objectpush1_bluez5_p.h b/src/bluetooth/bluez/obex_objectpush1_bluez5_p.h index ba5f090d..5fa1703b 100644 --- a/src/bluetooth/bluez/obex_objectpush1_bluez5_p.h +++ b/src/bluetooth/bluez/obex_objectpush1_bluez5_p.h @@ -1,15 +1,15 @@ /* * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp org.bluez.obex.ObjectPush1.xml -p obex_objectpush1_bluez5 + * Command line was: qdbusxml2cpp -p obex_objectpush1_bluez5_p.h:obex_objectpush1_bluez5.cpp org.bluez.obex.ObjectPush1.xml * - * qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd. + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * * This is an auto-generated file. * Do not edit! All changes made to it will be lost. */ -#ifndef OBEX_OBJECTPUSH1_BLUEZ5_H_1399989318 -#define OBEX_OBJECTPUSH1_BLUEZ5_H_1399989318 +#ifndef OBEX_OBJECTPUSH1_BLUEZ5_P_H +#define OBEX_OBJECTPUSH1_BLUEZ5_P_H #include <QtCore/QObject> #include <QtCore/QByteArray> @@ -31,7 +31,7 @@ public: { return "org.bluez.obex.ObjectPush1"; } public: - OrgBluezObexObjectPush1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); + OrgBluezObexObjectPush1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); ~OrgBluezObexObjectPush1Interface(); @@ -40,13 +40,13 @@ public Q_SLOTS: // METHODS { QList<QVariant> argumentList; argumentList << QVariant::fromValue(clientfile) << QVariant::fromValue(targetfile); - return asyncCallWithArgumentList(QLatin1String("ExchangeBusinessCards"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("ExchangeBusinessCards"), argumentList); } inline QDBusReply<QDBusObjectPath> ExchangeBusinessCards(const QString &clientfile, const QString &targetfile, QVariantMap &properties) { QList<QVariant> argumentList; argumentList << QVariant::fromValue(clientfile) << QVariant::fromValue(targetfile); - QDBusMessage reply = callWithArgumentList(QDBus::Block, QLatin1String("ExchangeBusinessCards"), argumentList); + QDBusMessage reply = callWithArgumentList(QDBus::Block, QStringLiteral("ExchangeBusinessCards"), argumentList); if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 2) { properties = qdbus_cast<QVariantMap>(reply.arguments().at(1)); } @@ -57,13 +57,13 @@ public Q_SLOTS: // METHODS { QList<QVariant> argumentList; argumentList << QVariant::fromValue(targetfile); - return asyncCallWithArgumentList(QLatin1String("PullBusinessCard"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("PullBusinessCard"), argumentList); } inline QDBusReply<QDBusObjectPath> PullBusinessCard(const QString &targetfile, QVariantMap &properties) { QList<QVariant> argumentList; argumentList << QVariant::fromValue(targetfile); - QDBusMessage reply = callWithArgumentList(QDBus::Block, QLatin1String("PullBusinessCard"), argumentList); + QDBusMessage reply = callWithArgumentList(QDBus::Block, QStringLiteral("PullBusinessCard"), argumentList); if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 2) { properties = qdbus_cast<QVariantMap>(reply.arguments().at(1)); } @@ -74,13 +74,13 @@ public Q_SLOTS: // METHODS { QList<QVariant> argumentList; argumentList << QVariant::fromValue(sourcefile); - return asyncCallWithArgumentList(QLatin1String("SendFile"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("SendFile"), argumentList); } inline QDBusReply<QDBusObjectPath> SendFile(const QString &sourcefile, QVariantMap &properties) { QList<QVariant> argumentList; argumentList << QVariant::fromValue(sourcefile); - QDBusMessage reply = callWithArgumentList(QDBus::Block, QLatin1String("SendFile"), argumentList); + QDBusMessage reply = callWithArgumentList(QDBus::Block, QStringLiteral("SendFile"), argumentList); if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 2) { properties = qdbus_cast<QVariantMap>(reply.arguments().at(1)); } diff --git a/src/bluetooth/bluez/obex_transfer.cpp b/src/bluetooth/bluez/obex_transfer.cpp index 49e1f7c9..be27362f 100644 --- a/src/bluetooth/bluez/obex_transfer.cpp +++ b/src/bluetooth/bluez/obex_transfer.cpp @@ -1,8 +1,8 @@ /* - * This file was generated by qdbusxml2cpp version 0.7 + * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp -p obex_transfer_p.h:obex_transfer.cpp org.openobex.transfer.xml org.openobex.Transfer * - * Copyright (C) 2015 The Qt Company Ltd. + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * * This is an auto-generated file. * This file may have been hand-edited. Look for HAND-EDIT comments diff --git a/src/bluetooth/bluez/obex_transfer1_bluez5_p.h b/src/bluetooth/bluez/obex_transfer1_bluez5_p.h index 2307f2ae..ccde588e 100644 --- a/src/bluetooth/bluez/obex_transfer1_bluez5_p.h +++ b/src/bluetooth/bluez/obex_transfer1_bluez5_p.h @@ -1,15 +1,15 @@ /* * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp org.bluez.obex.Transfer1.xml -p obex_transfer1_bluez5 + * Command line was: qdbusxml2cpp -p obex_transfer1_bluez5_p.h:obex_transfer1_bluez5_p.h org.bluez.obex.Transfer1.xml * - * qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd. + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * * This is an auto-generated file. * Do not edit! All changes made to it will be lost. */ -#ifndef OBEX_TRANSFER1_BLUEZ5_H_1400058158 -#define OBEX_TRANSFER1_BLUEZ5_H_1400058158 +#ifndef OBEX_TRANSFER1_BLUEZ5_P_H +#define OBEX_TRANSFER1_BLUEZ5_P_H #include <QtCore/QObject> #include <QtCore/QByteArray> @@ -31,7 +31,7 @@ public: { return "org.bluez.obex.Transfer1"; } public: - OrgBluezObexTransfer1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); + OrgBluezObexTransfer1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); ~OrgBluezObexTransfer1Interface(); @@ -63,19 +63,19 @@ public Q_SLOTS: // METHODS inline QDBusPendingReply<> Cancel() { QList<QVariant> argumentList; - return asyncCallWithArgumentList(QLatin1String("Cancel"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("Cancel"), argumentList); } inline QDBusPendingReply<> Resume() { QList<QVariant> argumentList; - return asyncCallWithArgumentList(QLatin1String("Resume"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("Resume"), argumentList); } inline QDBusPendingReply<> Suspend() { QList<QVariant> argumentList; - return asyncCallWithArgumentList(QLatin1String("Suspend"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("Suspend"), argumentList); } Q_SIGNALS: // SIGNALS diff --git a/src/bluetooth/bluez/obex_transfer_p.h b/src/bluetooth/bluez/obex_transfer_p.h index 81b9eb22..b8fa0a5d 100644 --- a/src/bluetooth/bluez/obex_transfer_p.h +++ b/src/bluetooth/bluez/obex_transfer_p.h @@ -1,15 +1,15 @@ /* - * This file was generated by qdbusxml2cpp version 0.7 + * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp -p obex_transfer_p.h:obex_transfer.cpp org.openobex.transfer.xml org.openobex.Transfer * - * Copyright (C) 2015 The Qt Company Ltd. + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * * This is an auto-generated file. * Do not edit! All changes made to it will be lost. */ -#ifndef OBEX_TRANSFER_P_H_1291853849 -#define OBEX_TRANSFER_P_H_1291853849 +#ifndef OBEX_TRANSFER_P_H +#define OBEX_TRANSFER_P_H #include <QtCore/QObject> #include <QtCore/QByteArray> @@ -31,7 +31,7 @@ public: { return "org.openobex.Transfer"; } public: - OrgOpenobexTransferInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); + OrgOpenobexTransferInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); ~OrgOpenobexTransferInterface(); @@ -39,13 +39,13 @@ public Q_SLOTS: // METHODS inline QDBusPendingReply<> Cancel() { QList<QVariant> argumentList; - return asyncCallWithArgumentList(QLatin1String("Cancel"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("Cancel"), argumentList); } inline QDBusPendingReply<QVariantMap> GetProperties() { QList<QVariant> argumentList; - return asyncCallWithArgumentList(QLatin1String("GetProperties"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("GetProperties"), argumentList); } Q_SIGNALS: // SIGNALS diff --git a/src/bluetooth/bluez/objectmanager.cpp b/src/bluetooth/bluez/objectmanager.cpp index a8e8fdba..4484ea27 100644 --- a/src/bluetooth/bluez/objectmanager.cpp +++ b/src/bluetooth/bluez/objectmanager.cpp @@ -1,8 +1,8 @@ /* * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -p objectmanager -v -i bluez5_helper.h org.freedesktop.dbus.objectmanager.xml + * Command line was: qdbusxml2cpp -p objectmanager_p.h:objectmanager.cpp org.freedesktop.dbus.objectmanager.xml * - * qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd. + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * * This is an auto-generated file. * This file may have been hand-edited. Look for HAND-EDIT comments diff --git a/src/bluetooth/bluez/objectmanager_p.h b/src/bluetooth/bluez/objectmanager_p.h index 74f5ab43..7aa2f35b 100644 --- a/src/bluetooth/bluez/objectmanager_p.h +++ b/src/bluetooth/bluez/objectmanager_p.h @@ -1,15 +1,15 @@ /* * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -p objectmanager -v -i bluez5_helper.h org.freedesktop.dbus.objectmanager.xml + * Command line was: qdbusxml2cpp -p objectmanager_p.h:objectmanager.cpp org.freedesktop.dbus.objectmanager.xml * - * qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd. + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * * This is an auto-generated file. * Do not edit! All changes made to it will be lost. */ -#ifndef OBJECTMANAGER_H_1396883000 -#define OBJECTMANAGER_H_1396883000 +#ifndef OBJECTMANAGER_P_H +#define OBJECTMANAGER_P_H #include <QtCore/QObject> #include <QtCore/QByteArray> @@ -33,7 +33,7 @@ public: { return "org.freedesktop.DBus.ObjectManager"; } public: - OrgFreedesktopDBusObjectManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); + OrgFreedesktopDBusObjectManagerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); ~OrgFreedesktopDBusObjectManagerInterface(); @@ -41,7 +41,7 @@ public Q_SLOTS: // METHODS inline QDBusPendingReply<ManagedObjectList> GetManagedObjects() { QList<QVariant> argumentList; - return asyncCallWithArgumentList(QLatin1String("GetManagedObjects"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("GetManagedObjects"), argumentList); } Q_SIGNALS: // SIGNALS diff --git a/src/bluetooth/bluez/org.bluez.GattCharacteristic1.xml b/src/bluetooth/bluez/org.bluez.GattCharacteristic1.xml new file mode 100644 index 00000000..f62014cf --- /dev/null +++ b/src/bluetooth/bluez/org.bluez.GattCharacteristic1.xml @@ -0,0 +1,22 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node> + <interface name="org.bluez.GattCharacteristic1"> + <method name="ReadValue"> + <arg name="options" type="a{sv}" direction="in"/> + <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QVariantMap"/> + <arg name="value" type="ay" direction="out"/> + </method> + <method name="WriteValue"> + <arg name="value" type="ay" direction="in"/> + <arg name="options" type="a{sv}" direction="in"/> + <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/> + </method> + <method name="StartNotify"></method> + <method name="StopNotify"></method> + <property name="UUID" type="s" access="read"></property> + <property name="Service" type="o" access="read"></property> + <property name="Value" type="ay" access="read"></property> + <property name="Notifying" type="b" access="read"></property> + <property name="Flags" type="as" access="read"></property> + </interface> +</node> diff --git a/src/bluetooth/bluez/org.bluez.GattDescriptor1.xml b/src/bluetooth/bluez/org.bluez.GattDescriptor1.xml new file mode 100644 index 00000000..fc7ebce0 --- /dev/null +++ b/src/bluetooth/bluez/org.bluez.GattDescriptor1.xml @@ -0,0 +1,18 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node> + <interface name="org.bluez.GattDescriptor1"> + <method name="ReadValue"> + <arg name="options" type="a{sv}" direction="in"/> + <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QVariantMap"/> + <arg name="value" type="ay" direction="out"/> + </method> + <method name="WriteValue"> + <arg name="value" type="ay" direction="in"/> + <arg name="options" type="a{sv}" direction="in"/> + <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/> + </method> + <property name="UUID" type="s" access="read"></property> + <property name="Characteristic" type="o" access="read"></property> + <property name="Value" type="ay" access="read"></property> + </interface> +</node> diff --git a/src/bluetooth/bluez/org.bluez.GattService1.xml b/src/bluetooth/bluez/org.bluez.GattService1.xml new file mode 100644 index 00000000..e90eeda7 --- /dev/null +++ b/src/bluetooth/bluez/org.bluez.GattService1.xml @@ -0,0 +1,9 @@ +<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> +<node> + <interface name="org.bluez.GattService1"> + <property name="UUID" type="s" access="read"></property> + <property name="Device" type="o" access="read"></property> + <property name="Primary" type="b" access="read"></property> + <property name="Includes" type="ao" access="read"></property> + </interface> +</node> diff --git a/src/bluetooth/bluez/profile1.cpp b/src/bluetooth/bluez/profile1.cpp index c289c89b..26d42c7c 100644 --- a/src/bluetooth/bluez/profile1.cpp +++ b/src/bluetooth/bluez/profile1.cpp @@ -1,8 +1,8 @@ /* * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -p profile1 org.bluez.ProfileManager1.xml + * Command line was: qdbusxml2cpp -p profile1_p.h:profile1.cpp org.bluez.ProfileManager1.xml * - * qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd. + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * * This is an auto-generated file. * This file may have been hand-edited. Look for HAND-EDIT comments diff --git a/src/bluetooth/bluez/profile1_p.h b/src/bluetooth/bluez/profile1_p.h index a08f10e0..e61fb2a9 100644 --- a/src/bluetooth/bluez/profile1_p.h +++ b/src/bluetooth/bluez/profile1_p.h @@ -1,15 +1,15 @@ /* * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -p profile1 org.bluez.ProfileManager1.xml + * Command line was: qdbusxml2cpp -p profile1_p.h:profile1.cpp org.bluez.ProfileManager1.xml * - * qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd. + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * * This is an auto-generated file. * Do not edit! All changes made to it will be lost. */ -#ifndef PROFILE1_H_1400142085 -#define PROFILE1_H_1400142085 +#ifndef PROFILE1_P_H +#define PROFILE1_P_H #include <QtCore/QObject> #include <QtCore/QByteArray> @@ -31,7 +31,7 @@ public: { return "org.bluez.ProfileManager1"; } public: - OrgBluezProfileManager1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); + OrgBluezProfileManager1Interface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); ~OrgBluezProfileManager1Interface(); @@ -40,14 +40,14 @@ public Q_SLOTS: // METHODS { QList<QVariant> argumentList; argumentList << QVariant::fromValue(profile) << QVariant::fromValue(UUID) << QVariant::fromValue(options); - return asyncCallWithArgumentList(QLatin1String("RegisterProfile"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("RegisterProfile"), argumentList); } inline QDBusPendingReply<> UnregisterProfile(const QDBusObjectPath &profile) { QList<QVariant> argumentList; argumentList << QVariant::fromValue(profile); - return asyncCallWithArgumentList(QLatin1String("UnregisterProfile"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("UnregisterProfile"), argumentList); } Q_SIGNALS: // SIGNALS diff --git a/src/bluetooth/bluez/properties.cpp b/src/bluetooth/bluez/properties.cpp index 4ddbc30c..1c10bfdc 100644 --- a/src/bluetooth/bluez/properties.cpp +++ b/src/bluetooth/bluez/properties.cpp @@ -1,8 +1,8 @@ /* * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -p properties -v org.freedesktop.dbus.properties.xml + * Command line was: qdbusxml2cpp -p properties_p.h:properties.cpp org.freedesktop.dbus.properties.xml * - * qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd. + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * * This is an auto-generated file. * This file may have been hand-edited. Look for HAND-EDIT comments diff --git a/src/bluetooth/bluez/properties_p.h b/src/bluetooth/bluez/properties_p.h index daadfefc..16a43e80 100644 --- a/src/bluetooth/bluez/properties_p.h +++ b/src/bluetooth/bluez/properties_p.h @@ -1,15 +1,15 @@ /* * This file was generated by qdbusxml2cpp version 0.8 - * Command line was: qdbusxml2cpp -p properties -v org.freedesktop.dbus.properties.xml + * Command line was: qdbusxml2cpp -p properties_p.h:properties.cpp org.freedesktop.dbus.properties.xml * - * qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd. + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * * This is an auto-generated file. * Do not edit! All changes made to it will be lost. */ -#ifndef PROPERTIES_H_1396952220 -#define PROPERTIES_H_1396952220 +#ifndef PROPERTIES_P_H +#define PROPERTIES_P_H #include <QtCore/QObject> #include <QtCore/QByteArray> @@ -31,7 +31,7 @@ public: { return "org.freedesktop.DBus.Properties"; } public: - OrgFreedesktopDBusPropertiesInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); + OrgFreedesktopDBusPropertiesInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); ~OrgFreedesktopDBusPropertiesInterface(); @@ -40,21 +40,21 @@ public Q_SLOTS: // METHODS { QList<QVariant> argumentList; argumentList << QVariant::fromValue(interface) << QVariant::fromValue(name); - return asyncCallWithArgumentList(QLatin1String("Get"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("Get"), argumentList); } inline QDBusPendingReply<QVariantMap> GetAll(const QString &interface) { QList<QVariant> argumentList; argumentList << QVariant::fromValue(interface); - return asyncCallWithArgumentList(QLatin1String("GetAll"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("GetAll"), argumentList); } inline QDBusPendingReply<> Set(const QString &interface, const QString &name, const QDBusVariant &value) { QList<QVariant> argumentList; argumentList << QVariant::fromValue(interface) << QVariant::fromValue(name) << QVariant::fromValue(value); - return asyncCallWithArgumentList(QLatin1String("Set"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("Set"), argumentList); } Q_SIGNALS: // SIGNALS diff --git a/src/bluetooth/bluez/service.cpp b/src/bluetooth/bluez/service.cpp index 2004bea7..d2b15fc2 100644 --- a/src/bluetooth/bluez/service.cpp +++ b/src/bluetooth/bluez/service.cpp @@ -1,8 +1,8 @@ /* - * This file was generated by qdbusxml2cpp version 0.7 + * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp -p service_p.h:service.cpp org.bluez.all.xml org.bluez.Service * - * Copyright (C) 2015 The Qt Company Ltd. + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * * This is an auto-generated file. * This file may have been hand-edited. Look for HAND-EDIT comments diff --git a/src/bluetooth/bluez/service_p.h b/src/bluetooth/bluez/service_p.h index e8c5e1f4..573265a8 100644 --- a/src/bluetooth/bluez/service_p.h +++ b/src/bluetooth/bluez/service_p.h @@ -1,15 +1,15 @@ /* - * This file was generated by qdbusxml2cpp version 0.7 + * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp -p service_p.h:service.cpp org.bluez.all.xml org.bluez.Service * - * Copyright (C) 2015 The Qt Company Ltd. + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. * * This is an auto-generated file. * Do not edit! All changes made to it will be lost. */ -#ifndef SERVICE_P_H_1277421939 -#define SERVICE_P_H_1277421939 +#ifndef SERVICE_P_H +#define SERVICE_P_H #include <QtCore/QObject> #include <QtCore/QByteArray> @@ -31,7 +31,7 @@ public: { return "org.bluez.Service"; } public: - OrgBluezServiceInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); + OrgBluezServiceInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); ~OrgBluezServiceInterface(); @@ -39,35 +39,35 @@ public Q_SLOTS: // METHODS inline QDBusPendingReply<uint> AddRecord(const QString &in0) { QList<QVariant> argumentList; - argumentList << qVariantFromValue(in0); - return asyncCallWithArgumentList(QLatin1String("AddRecord"), argumentList); + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QStringLiteral("AddRecord"), argumentList); } inline QDBusPendingReply<> CancelAuthorization() { QList<QVariant> argumentList; - return asyncCallWithArgumentList(QLatin1String("CancelAuthorization"), argumentList); + return asyncCallWithArgumentList(QStringLiteral("CancelAuthorization"), argumentList); } inline QDBusPendingReply<> RemoveRecord(uint in0) { QList<QVariant> argumentList; - argumentList << qVariantFromValue(in0); - return asyncCallWithArgumentList(QLatin1String("RemoveRecord"), argumentList); + argumentList << QVariant::fromValue(in0); + return asyncCallWithArgumentList(QStringLiteral("RemoveRecord"), argumentList); } inline QDBusPendingReply<> RequestAuthorization(const QString &in0, uint in1) { QList<QVariant> argumentList; - argumentList << qVariantFromValue(in0) << qVariantFromValue(in1); - return asyncCallWithArgumentList(QLatin1String("RequestAuthorization"), argumentList); + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); + return asyncCallWithArgumentList(QStringLiteral("RequestAuthorization"), argumentList); } inline QDBusPendingReply<> UpdateRecord(uint in0, const QString &in1) { QList<QVariant> argumentList; - argumentList << qVariantFromValue(in0) << qVariantFromValue(in1); - return asyncCallWithArgumentList(QLatin1String("UpdateRecord"), argumentList); + argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1); + return asyncCallWithArgumentList(QStringLiteral("UpdateRecord"), argumentList); } Q_SIGNALS: // SIGNALS diff --git a/src/bluetooth/osx/osxbluetooth_p.h b/src/bluetooth/osx/osxbluetooth_p.h index 93842e77..ea1b388f 100644 --- a/src/bluetooth/osx/osxbluetooth_p.h +++ b/src/bluetooth/osx/osxbluetooth_p.h @@ -54,47 +54,10 @@ #include <QtCore/qglobal.h> -#ifndef QT_OSX_BLUETOOTH - #include <CoreBluetooth/CoreBluetooth.h> -#else - -#if QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_12) - -#include <CoreBluetooth/CoreBluetooth.h> -#include <IOBluetooth/IOBluetooth.h> - -#else - -// CoreBluetooth with SDK 10.9 seems to be broken: the class CBPeripheralManager is enabled on macOS -// but some of its declarations are using a disabled enum CBPeripheralAuthorizationStatus -// (disabled using __attribute__ syntax and NS_ENUM_AVAILABLE macro). -// This + -std=c++11 ends with a compilation error. For the SDK 10.9 we can: -// 1. either undefine NS_ENUM_AVAILABLE macro (it works somehow) and redefine it as an empty sequence -// of pp-tokens or -// 2. define __attribute__ as an empty sequence. Both solutions look quite ugly. - -#if QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9) && !QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_10) - -// Must be included BEFORE CoreBluetooth.h: -#include <Foundation/Foundation.h> - -#define CB_ERROR_WORKAROUND_REQUIRED -#undef NS_ENUM_AVAILABLE -#define NS_ENUM_AVAILABLE(_mac, _ios) - -#endif // SDK version == 10.9 - -// In SDK below 10.12 IOBluetooth.h includes CoreBluetooth.h. +#ifdef Q_OS_MACOS #include <IOBluetooth/IOBluetooth.h> +#endif -#ifdef CB_ERROR_WORKAROUND_REQUIRED -#undef __attribute__ -#undef CB_ERROR_WORKAROUND_REQUIRED -#endif // WORKAROUND - -#endif // SDK - -#endif // QT_OSX_BLUETOOTH #endif // OSXBLUETOOTH_P_H diff --git a/src/bluetooth/osx/osxbtl2capchannel.mm b/src/bluetooth/osx/osxbtl2capchannel.mm index 02ec4f90..474fe04b 100644 --- a/src/bluetooth/osx/osxbtl2capchannel.mm +++ b/src/bluetooth/osx/osxbtl2capchannel.mm @@ -210,7 +210,7 @@ QT_USE_NAMESPACE - (BluetoothDeviceAddress)peerAddress { const BluetoothDeviceAddress *const addr = device ? [device getAddress] - : Q_NULLPTR; + : nullptr; if (addr) return *addr; @@ -245,7 +245,7 @@ QT_USE_NAMESPACE Q_ASSERT_X(length, Q_FUNC_INFO, "invalid data size"); Q_ASSERT_X(connected && channel, Q_FUNC_INFO, "invalid L2CAP channel"); - return [channel writeAsync:data length:length refcon:Q_NULLPTR]; + return [channel writeAsync:data length:length refcon:nullptr]; } diff --git a/src/bluetooth/osx/osxbtobexsession.mm b/src/bluetooth/osx/osxbtobexsession.mm index b8e604c8..e228d6db 100644 --- a/src/bluetooth/osx/osxbtobexsession.mm +++ b/src/bluetooth/osx/osxbtobexsession.mm @@ -489,11 +489,11 @@ QT_USE_NAMESPACE const OBEXError status = [session OBEXConnect:kOBEXConnectFlagNone maxPacketLength:[QT_MANGLE_NAMESPACE(OSXBTOBEXSession) maxPacketLength] - optionalHeaders:Q_NULLPTR + optionalHeaders:nullptr optionalHeadersLength:0 eventSelector:@selector(OBEXConnectHandler:) selectorTarget:self - refCon:Q_NULLPTR]; + refCon:nullptr]; if (status != kOBEXSuccess) { currentRequest = OSXBluetooth::OBEXNoop; @@ -572,11 +572,11 @@ QT_USE_NAMESPACE return kOBEXSessionNotConnectedError; currentRequest = OBEXAbort; - const OBEXError status = [session OBEXAbort:Q_NULLPTR + const OBEXError status = [session OBEXAbort:nullptr optionalHeadersLength:0 eventSelector:@selector(OBEXAbortHandler:) selectorTarget:self - refCon:Q_NULLPTR]; + refCon:nullptr]; if (status != kOBEXSuccess) currentRequest = OBEXNoop; @@ -677,7 +677,7 @@ QT_USE_NAMESPACE bodyDataLength:[chunk length] eventSelector:@selector(OBEXPutHandler:) selectorTarget:self - refCon:Q_NULLPTR]; + refCon:nullptr]; if (status == kOBEXSuccess) { if (delegate && fileSize && !input->isSequential()) @@ -737,16 +737,16 @@ QT_USE_NAMESPACE return; } - void *dataPtr = chunk ? [chunk mutableBytes] : Q_NULLPTR; + void *dataPtr = chunk ? [chunk mutableBytes] : nullptr; const NSUInteger dataSize = chunk ? [chunk length] : 0; const OBEXError status = [session OBEXPut:lastChunk - headersData:Q_NULLPTR + headersData:nullptr headersDataLength:0 bodyData:dataPtr bodyDataLength:dataSize eventSelector:@selector(OBEXPutHandler:) selectorTarget:self - refCon:Q_NULLPTR]; + refCon:nullptr]; if (status != kOBEXSuccess) { qCWarning(QT_BT_OSX) << "failed to send the next memory chunk"; @@ -778,11 +778,11 @@ QT_USE_NAMESPACE currentRequest = OSXBluetooth::OBEXDisconnect; - [session OBEXDisconnect:Q_NULLPTR + [session OBEXDisconnect:nullptr optionalHeadersLength:0 eventSelector:@selector(OBEXDisconnectHandler:) selectorTarget:self - refCon:Q_NULLPTR]; + refCon:nullptr]; } - (void)OBEXDisconnectHandler:(const OBEXSessionEvent*)event @@ -806,7 +806,7 @@ QT_USE_NAMESPACE // Clear the delegate and reset the request, // do not try any of OBEX commands - the session will be deleted // immediately. - delegate = Q_NULLPTR; + delegate = nullptr; // This will stop any handler (callback) preventing // any read/write to potentially deleted objects. currentRequest = OSXBluetooth::OBEXNoop; diff --git a/src/bluetooth/osx/osxbtrfcommchannel.mm b/src/bluetooth/osx/osxbtrfcommchannel.mm index ea679ec8..bd87aae0 100644 --- a/src/bluetooth/osx/osxbtrfcommchannel.mm +++ b/src/bluetooth/osx/osxbtrfcommchannel.mm @@ -210,7 +210,7 @@ QT_USE_NAMESPACE - (BluetoothDeviceAddress)peerAddress { const BluetoothDeviceAddress *const addr = device ? [device getAddress] - : Q_NULLPTR; + : nullptr; if (addr) return *addr; @@ -248,7 +248,7 @@ QT_USE_NAMESPACE Q_ASSERT_X(length, Q_FUNC_INFO, "invalid data size"); Q_ASSERT_X(connected && channel, Q_FUNC_INFO, "invalid RFCOMM channel"); - return [channel writeAsync:data length:length refcon:Q_NULLPTR]; + return [channel writeAsync:data length:length refcon:nullptr]; } diff --git a/src/bluetooth/osx/osxbtutility_p.h b/src/bluetooth/osx/osxbtutility_p.h index 3312af12..c2bc6cf8 100644 --- a/src/bluetooth/osx/osxbtutility_p.h +++ b/src/bluetooth/osx/osxbtutility_p.h @@ -82,7 +82,7 @@ public: // add a default ctor??? This will make the semantics more // transparent + will simplify the future transition to ARC // (if it will ever happen). - explicit ObjCScopedPointer(T *ptr = Q_NULLPTR) : QScopedPointer(ptr){} + explicit ObjCScopedPointer(T *ptr = nullptr) : QScopedPointer(ptr){} operator T*() const { return data(); @@ -196,7 +196,7 @@ template<class T> class CFStrongReference { public: CFStrongReference() - : m_ptr(Q_NULLPTR) + : m_ptr(nullptr) { } @@ -230,13 +230,13 @@ public: CFStrongReference(CFStrongReference &&xval) { m_ptr = xval.m_ptr; - xval.m_ptr = Q_NULLPTR; + xval.m_ptr = nullptr; } CFStrongReference &operator = (CFStrongReference &&xval) { m_ptr = xval.m_ptr; - xval.m_ptr = Q_NULLPTR; + xval.m_ptr = nullptr; return *this; } #endif @@ -270,7 +270,7 @@ public: T take() { T p = m_ptr; - m_ptr = Q_NULLPTR; + m_ptr = nullptr; return p; } private: diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent.h b/src/bluetooth/qbluetoothdevicediscoveryagent.h index 62050282..d3e41265 100644 --- a/src/bluetooth/qbluetoothdevicediscoveryagent.h +++ b/src/bluetooth/qbluetoothdevicediscoveryagent.h @@ -85,9 +85,9 @@ public: Q_DECLARE_FLAGS(DiscoveryMethods, DiscoveryMethod) Q_FLAG(DiscoveryMethods) - explicit QBluetoothDeviceDiscoveryAgent(QObject *parent = Q_NULLPTR); + explicit QBluetoothDeviceDiscoveryAgent(QObject *parent = nullptr); explicit QBluetoothDeviceDiscoveryAgent(const QBluetoothAddress &deviceAdapter, - QObject *parent = Q_NULLPTR); + QObject *parent = nullptr); ~QBluetoothDeviceDiscoveryAgent(); // TODO Remove inquiry type in Qt 6 -> not really used anywhere diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_ios.mm b/src/bluetooth/qbluetoothdevicediscoveryagent_ios.mm index 3f4c6755..c50d546d 100644 --- a/src/bluetooth/qbluetoothdevicediscoveryagent_ios.mm +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_ios.mm @@ -127,7 +127,7 @@ QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate(con Q_UNUSED(adapter); registerQDeviceDiscoveryMetaType(); - Q_ASSERT_X(q != Q_NULLPTR, Q_FUNC_INFO, "invalid q_ptr (null)"); + Q_ASSERT_X(q != nullptr, Q_FUNC_INFO, "invalid q_ptr (null)"); } QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate() diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_osx.mm b/src/bluetooth/qbluetoothdevicediscoveryagent_osx.mm index 7f037596..fed33bb2 100644 --- a/src/bluetooth/qbluetoothdevicediscoveryagent_osx.mm +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_osx.mm @@ -90,7 +90,7 @@ public: QBluetoothDeviceDiscoveryAgentPrivate(const QBluetoothAddress & address, QBluetoothDeviceDiscoveryAgent *q); - ~QBluetoothDeviceDiscoveryAgentPrivate() Q_DECL_OVERRIDE; + ~QBluetoothDeviceDiscoveryAgentPrivate() override; bool isValid() const; bool isActive() const; @@ -108,9 +108,9 @@ private: }; // DeviceInquiryDelegate: - void inquiryFinished(IOBluetoothDeviceInquiry *inq) Q_DECL_OVERRIDE; - void error(IOBluetoothDeviceInquiry *inq, IOReturn error) Q_DECL_OVERRIDE; - void deviceFound(IOBluetoothDeviceInquiry *inq, IOBluetoothDevice *device) Q_DECL_OVERRIDE; + void inquiryFinished(IOBluetoothDeviceInquiry *inq) override; + void error(IOBluetoothDeviceInquiry *inq, IOReturn error) override; + void deviceFound(IOBluetoothDeviceInquiry *inq, IOBluetoothDevice *device) override; void LEinquiryFinished(); void LEinquiryError(QBluetoothDeviceDiscoveryAgent::Error error); @@ -168,7 +168,7 @@ QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate(con { registerQDeviceDiscoveryMetaType(); - Q_ASSERT_X(q != Q_NULLPTR, Q_FUNC_INFO, "invalid q_ptr (null)"); + Q_ASSERT_X(q != nullptr, Q_FUNC_INFO, "invalid q_ptr (null)"); HostController controller([[IOBluetoothHostController defaultController] retain]); if (!controller || [controller powerState] != kBluetoothHCIPowerStateON) { diff --git a/src/bluetooth/qbluetoothdeviceinfo.h b/src/bluetooth/qbluetoothdeviceinfo.h index 33cd40b7..f2558bbf 100644 --- a/src/bluetooth/qbluetoothdeviceinfo.h +++ b/src/bluetooth/qbluetoothdeviceinfo.h @@ -232,7 +232,7 @@ public: void setRssi(qint16 signal); void setServiceUuids(const QList<QBluetoothUuid> &uuids, DataCompleteness completeness); - QList<QBluetoothUuid> serviceUuids(DataCompleteness *completeness = Q_NULLPTR) const; + QList<QBluetoothUuid> serviceUuids(DataCompleteness *completeness = nullptr) const; DataCompleteness serviceUuidsCompleteness() const; void setCoreConfigurations(QBluetoothDeviceInfo::CoreConfigurations coreConfigs); diff --git a/src/bluetooth/qbluetoothlocaldevice.h b/src/bluetooth/qbluetoothlocaldevice.h index 9363a116..9f6d1e1b 100644 --- a/src/bluetooth/qbluetoothlocaldevice.h +++ b/src/bluetooth/qbluetoothlocaldevice.h @@ -79,8 +79,8 @@ public: }; Q_ENUM(Error) - explicit QBluetoothLocalDevice(QObject *parent = Q_NULLPTR); - explicit QBluetoothLocalDevice(const QBluetoothAddress &address, QObject *parent = Q_NULLPTR); + explicit QBluetoothLocalDevice(QObject *parent = nullptr); + explicit QBluetoothLocalDevice(const QBluetoothAddress &address, QObject *parent = nullptr); virtual ~QBluetoothLocalDevice(); bool isValid() const; diff --git a/src/bluetooth/qbluetoothlocaldevice_osx.mm b/src/bluetooth/qbluetoothlocaldevice_osx.mm index cb5625d6..52b7bba8 100644 --- a/src/bluetooth/qbluetoothlocaldevice_osx.mm +++ b/src/bluetooth/qbluetoothlocaldevice_osx.mm @@ -74,18 +74,18 @@ public: private: // PairingDelegate: - void connecting(ObjCPairingRequest *pair) Q_DECL_OVERRIDE; - void requestPIN(ObjCPairingRequest *pair) Q_DECL_OVERRIDE; + void connecting(ObjCPairingRequest *pair) override; + void requestPIN(ObjCPairingRequest *pair) override; void requestUserConfirmation(ObjCPairingRequest *pair, - BluetoothNumericValue) Q_DECL_OVERRIDE; + BluetoothNumericValue) override; void passkeyNotification(ObjCPairingRequest *pair, - BluetoothPasskey passkey) Q_DECL_OVERRIDE; - void error(ObjCPairingRequest *pair, IOReturn errorCode) Q_DECL_OVERRIDE; - void pairingFinished(ObjCPairingRequest *pair) Q_DECL_OVERRIDE; + BluetoothPasskey passkey) override; + void error(ObjCPairingRequest *pair, IOReturn errorCode) override; + void pairingFinished(ObjCPairingRequest *pair) override; // ConnectionMonitor - void deviceConnected(const QBluetoothAddress &deviceAddress) Q_DECL_OVERRIDE; - void deviceDisconnected(const QBluetoothAddress &deviceAddress) Q_DECL_OVERRIDE; + void deviceConnected(const QBluetoothAddress &deviceAddress) override; + void deviceDisconnected(const QBluetoothAddress &deviceAddress) override; void emitPairingFinished(const QBluetoothAddress &deviceAddress, Pairing pairing, bool queued); void emitError(QBluetoothLocalDevice::Error error, bool queued); diff --git a/src/bluetooth/qbluetoothserver.h b/src/bluetooth/qbluetoothserver.h index e6e4a68f..193101fc 100644 --- a/src/bluetooth/qbluetoothserver.h +++ b/src/bluetooth/qbluetoothserver.h @@ -70,7 +70,7 @@ public: }; Q_ENUM(Error) - explicit QBluetoothServer(QBluetoothServiceInfo::Protocol serverType, QObject *parent = Q_NULLPTR); + explicit QBluetoothServer(QBluetoothServiceInfo::Protocol serverType, QObject *parent = nullptr); ~QBluetoothServer(); void close(); diff --git a/src/bluetooth/qbluetoothserver_osx.mm b/src/bluetooth/qbluetoothserver_osx.mm index 8d7eeb29..a1774d14 100644 --- a/src/bluetooth/qbluetoothserver_osx.mm +++ b/src/bluetooth/qbluetoothserver_osx.mm @@ -237,7 +237,7 @@ QBluetoothServerPrivate *QBluetoothServerPrivate::registeredServer(quint16 port, qCWarning(QT_BT_OSX) << "invalid protocol"; } - return Q_NULLPTR; + return nullptr; } void QBluetoothServerPrivate::unregisterServer(QBluetoothServerPrivate *server) @@ -443,7 +443,7 @@ bool QBluetoothServer::hasPendingConnections() const QBluetoothSocket *QBluetoothServer::nextPendingConnection() { if (!d_ptr->pendingConnections.size()) - return Q_NULLPTR; + return nullptr; QScopedPointer<QBluetoothSocket> newSocket(new QBluetoothSocket); QBluetoothServerPrivate::PendingConnection channel(d_ptr->pendingConnections.front()); @@ -453,10 +453,10 @@ QBluetoothSocket *QBluetoothServer::nextPendingConnection() if (d_ptr->serverType == QSInfo::RfcommProtocol) { if (!newSocket->d_ptr->setChannel(static_cast<IOBluetoothRFCOMMChannel *>(channel))) - return Q_NULLPTR; + return nullptr; } else { if (!newSocket->d_ptr->setChannel(static_cast<IOBluetoothL2CAPChannel *>(channel))) - return Q_NULLPTR; + return nullptr; } return newSocket.take(); diff --git a/src/bluetooth/qbluetoothserver_osx_p.h b/src/bluetooth/qbluetoothserver_osx_p.h index 63d0f314..3116ca02 100644 --- a/src/bluetooth/qbluetoothserver_osx_p.h +++ b/src/bluetooth/qbluetoothserver_osx_p.h @@ -80,8 +80,8 @@ private: void stopListener(); // SocketListener (delegate): - void openNotify(IOBluetoothRFCOMMChannel *channel) Q_DECL_OVERRIDE; - void openNotify(IOBluetoothL2CAPChannel *channel) Q_DECL_OVERRIDE; + void openNotify(IOBluetoothRFCOMMChannel *channel) override; + void openNotify(IOBluetoothL2CAPChannel *channel) override; QBluetoothServiceInfo::Protocol serverType; QBluetoothServer *q_ptr; diff --git a/src/bluetooth/qbluetoothservicediscoveryagent.h b/src/bluetooth/qbluetoothservicediscoveryagent.h index 12df37a8..4a553c7d 100644 --- a/src/bluetooth/qbluetoothservicediscoveryagent.h +++ b/src/bluetooth/qbluetoothservicediscoveryagent.h @@ -80,8 +80,8 @@ public: }; Q_ENUM(DiscoveryMode) - explicit QBluetoothServiceDiscoveryAgent(QObject *parent = Q_NULLPTR); - explicit QBluetoothServiceDiscoveryAgent(const QBluetoothAddress &deviceAdapter, QObject *parent = Q_NULLPTR); + explicit QBluetoothServiceDiscoveryAgent(QObject *parent = nullptr); + explicit QBluetoothServiceDiscoveryAgent(const QBluetoothAddress &deviceAdapter, QObject *parent = nullptr); ~QBluetoothServiceDiscoveryAgent(); bool isActive() const; diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_osx.mm b/src/bluetooth/qbluetoothservicediscoveryagent_osx.mm index 0b2f593d..1d0cc7da 100644 --- a/src/bluetooth/qbluetoothservicediscoveryagent_osx.mm +++ b/src/bluetooth/qbluetoothservicediscoveryagent_osx.mm @@ -88,8 +88,8 @@ public: private: // SDPInquiryDelegate: - void SDPInquiryFinished(IOBluetoothDevice *device) Q_DECL_OVERRIDE; - void SDPInquiryError(IOBluetoothDevice *device, IOReturn errorCode) Q_DECL_OVERRIDE; + void SDPInquiryFinished(IOBluetoothDevice *device) override; + void SDPInquiryError(IOBluetoothDevice *device, IOReturn errorCode) override; void performMinimalServiceDiscovery(const QBluetoothAddress &deviceAddress); void setupDeviceDiscoveryAgent(); @@ -152,7 +152,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::stopDeviceDiscovery() Q_ASSERT_X(state == DeviceDiscovery, Q_FUNC_INFO, "invalid state"); deviceDiscoveryAgent->stop(); - deviceDiscoveryAgent.reset(Q_NULLPTR); + deviceDiscoveryAgent.reset(nullptr); state = Inactive; emit q_ptr->canceled(); @@ -268,7 +268,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_deviceDiscoveryError(QBluetoothD errorString = QCoreApplication::translate(DEV_DISCOVERY, DD_UNKNOWN_ERROR); deviceDiscoveryAgent->stop(); - deviceDiscoveryAgent.reset(Q_NULLPTR); + deviceDiscoveryAgent.reset(nullptr); state = QBluetoothServiceDiscoveryAgentPrivate::Inactive; emit q_ptr->error(error); @@ -283,12 +283,12 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_deviceDiscoveryFinished() //Forward the device discovery error error = static_cast<QBluetoothServiceDiscoveryAgent::Error>(deviceDiscoveryAgent->error()); errorString = deviceDiscoveryAgent->errorString(); - deviceDiscoveryAgent.reset(Q_NULLPTR); + deviceDiscoveryAgent.reset(nullptr); state = Inactive; emit q_ptr->error(error); emit q_ptr->finished(); } else { - deviceDiscoveryAgent.reset(Q_NULLPTR); + deviceDiscoveryAgent.reset(nullptr); startServiceDiscovery(); } } diff --git a/src/bluetooth/qbluetoothserviceinfo.cpp b/src/bluetooth/qbluetoothserviceinfo.cpp index 9e350cd7..d706e4a7 100644 --- a/src/bluetooth/qbluetoothserviceinfo.cpp +++ b/src/bluetooth/qbluetoothserviceinfo.cpp @@ -627,7 +627,7 @@ QDebug operator<<(QDebug dbg, const QBluetoothServiceInfo &info) QDebugStateSaver saver(dbg); dbg.noquote() << "\n"; foreach (quint16 id, info.attributes()) { - dumpAttributeVariant(dbg, info.attribute(id), QString::fromLatin1("(%1)\t").arg(id)); + dumpAttributeVariant(dbg, info.attribute(id), QStringLiteral("(%1)\t").arg(id)); } return dbg; } diff --git a/src/bluetooth/qbluetoothserviceinfo_osx.mm b/src/bluetooth/qbluetoothserviceinfo_osx.mm index a25653ab..6da9d7a2 100644 --- a/src/bluetooth/qbluetoothserviceinfo_osx.mm +++ b/src/bluetooth/qbluetoothserviceinfo_osx.mm @@ -127,7 +127,7 @@ bool QBluetoothServiceInfoPrivate::registerService(const QBluetoothAddress &loca const QSInfo::Protocol type = q_ptr->socketProtocol(); quint16 realPort = 0; - QBluetoothServerPrivate *server = Q_NULLPTR; + QBluetoothServerPrivate *server = nullptr; bool configured = false; if (type == QBluetoothServiceInfo::L2capProtocol) { @@ -179,7 +179,7 @@ bool QBluetoothServiceInfoPrivate::unregisterService() serviceRecord.reset(nil); const QSInfo::Protocol type = q_ptr->socketProtocol(); - QBluetoothServerPrivate *server = Q_NULLPTR; + QBluetoothServerPrivate *server = nullptr; const QMutexLocker lock(&QBluetoothServerPrivate::channelMapMutex()); if (type == QSInfo::RfcommProtocol) diff --git a/src/bluetooth/qbluetoothsocket.cpp b/src/bluetooth/qbluetoothsocket.cpp index 06b0668c..ddc6469f 100644 --- a/src/bluetooth/qbluetoothsocket.cpp +++ b/src/bluetooth/qbluetoothsocket.cpp @@ -387,6 +387,14 @@ void QBluetoothSocket::connectToService(const QBluetoothServiceInfo &service, Op } /*! + \fn void QBluetoothSocket::connectToService(const QBluetoothAddress &address, QBluetoothUuid::ServiceClassUuid uuid, OpenMode openMode = ReadWrite) + + \internal + + Exists to avoid QTBUG-65831. +*/ + +/*! Attempts to make a connection to the service identified by \a uuid on the device with address \a address. @@ -665,8 +673,10 @@ void QBluetoothSocket::doDeviceDiscovery(const QBluetoothServiceInfo &service, O //qDebug() << "Got agent"; - connect(d->discoveryAgent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)), this, SLOT(serviceDiscovered(QBluetoothServiceInfo))); - connect(d->discoveryAgent, SIGNAL(finished()), this, SLOT(discoveryFinished())); + connect(d->discoveryAgent, &QBluetoothServiceDiscoveryAgent::serviceDiscovered, + this, &QBluetoothSocket::serviceDiscovered); + connect(d->discoveryAgent, &QBluetoothServiceDiscoveryAgent::finished, + this, &QBluetoothSocket::discoveryFinished); d->openMode = openMode; diff --git a/src/bluetooth/qbluetoothsocket.h b/src/bluetooth/qbluetoothsocket.h index bbcecbf4..db8562ed 100644 --- a/src/bluetooth/qbluetoothsocket.h +++ b/src/bluetooth/qbluetoothsocket.h @@ -89,8 +89,8 @@ public: }; Q_ENUM(SocketError) - explicit QBluetoothSocket(QBluetoothServiceInfo::Protocol socketType, QObject *parent = Q_NULLPTR); // create socket of type socketType - explicit QBluetoothSocket(QObject *parent = Q_NULLPTR); // create a blank socket + explicit QBluetoothSocket(QBluetoothServiceInfo::Protocol socketType, QObject *parent = nullptr); // create socket of type socketType + explicit QBluetoothSocket(QObject *parent = nullptr); // create a blank socket virtual ~QBluetoothSocket(); void abort(); @@ -106,6 +106,11 @@ public: void connectToService(const QBluetoothServiceInfo &service, OpenMode openMode = ReadWrite); void connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid, OpenMode openMode = ReadWrite); void connectToService(const QBluetoothAddress &address, quint16 port, OpenMode openMode = ReadWrite); + inline void connectToService(const QBluetoothAddress &address, QBluetoothUuid::ServiceClassUuid uuid, + OpenMode openMode = ReadWrite) + { + connectToService(address, QBluetoothUuid(uuid), openMode); + } void disconnectFromService(); //bool flush(); @@ -164,7 +169,7 @@ protected: QBluetoothSocketPrivate *d_ptr; private: - friend class QLowEnergyControllerPrivate; + friend class QLowEnergyControllerPrivateBluez; }; #ifndef QT_NO_DEBUG_STREAM diff --git a/src/bluetooth/qbluetoothsocket_osx.mm b/src/bluetooth/qbluetoothsocket_osx.mm index 1bbc660e..de7e2120 100644 --- a/src/bluetooth/qbluetoothsocket_osx.mm +++ b/src/bluetooth/qbluetoothsocket_osx.mm @@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE QBluetoothSocketPrivate::QBluetoothSocketPrivate() - : q_ptr(Q_NULLPTR), + : q_ptr(nullptr), writeChunk(std::numeric_limits<UInt16>::max()), openMode(QIODevice::NotOpen), // That's what is set in public class' ctors. state(QBluetoothSocket::UnconnectedState), diff --git a/src/bluetooth/qbluetoothsocket_osx_p.h b/src/bluetooth/qbluetoothsocket_osx_p.h index 732d31aa..ce376702 100644 --- a/src/bluetooth/qbluetoothsocket_osx_p.h +++ b/src/bluetooth/qbluetoothsocket_osx_p.h @@ -104,7 +104,7 @@ public: quint16 peerPort() const; void _q_readNotify(); - void _q_writeNotify() Q_DECL_OVERRIDE; + void _q_writeNotify() override; private: // Create a socket from an external source (without connectToService). @@ -112,11 +112,11 @@ private: bool setChannel(IOBluetoothL2CAPChannel *channel); // L2CAP and RFCOMM delegate - void setChannelError(IOReturn errorCode) Q_DECL_OVERRIDE; - void channelOpenComplete() Q_DECL_OVERRIDE; - void channelClosed() Q_DECL_OVERRIDE; - void readChannelData(void *data, std::size_t size) Q_DECL_OVERRIDE; - void writeComplete() Q_DECL_OVERRIDE; + void setChannelError(IOReturn errorCode) override; + void channelOpenComplete() override; + void channelClosed() override; + void readChannelData(void *data, std::size_t size) override; + void writeComplete() override; qint64 writeData(const char *data, qint64 maxSize); qint64 readData(char *data, qint64 maxSize); diff --git a/src/bluetooth/qbluetoothtransfermanager.h b/src/bluetooth/qbluetoothtransfermanager.h index 756fe54f..98850392 100644 --- a/src/bluetooth/qbluetoothtransfermanager.h +++ b/src/bluetooth/qbluetoothtransfermanager.h @@ -58,7 +58,7 @@ class Q_BLUETOOTH_EXPORT QBluetoothTransferManager : public QObject Q_OBJECT public: - explicit QBluetoothTransferManager(QObject *parent = Q_NULLPTR); + explicit QBluetoothTransferManager(QObject *parent = nullptr); ~QBluetoothTransferManager(); QBluetoothTransferReply *put(const QBluetoothTransferRequest &request, QIODevice *data); diff --git a/src/bluetooth/qbluetoothtransferreply.h b/src/bluetooth/qbluetoothtransferreply.h index c2b0b622..8f0679f5 100644 --- a/src/bluetooth/qbluetoothtransferreply.h +++ b/src/bluetooth/qbluetoothtransferreply.h @@ -88,7 +88,7 @@ Q_SIGNALS: void error(QBluetoothTransferReply::TransferError lastError); protected: - explicit QBluetoothTransferReply(QObject *parent = Q_NULLPTR); + explicit QBluetoothTransferReply(QObject *parent = nullptr); void setManager(QBluetoothTransferManager *manager); void setRequest(const QBluetoothTransferRequest &request); diff --git a/src/bluetooth/qbluetoothtransferreply_osx.mm b/src/bluetooth/qbluetoothtransferreply_osx.mm index 02133860..65c8f82d 100644 --- a/src/bluetooth/qbluetoothtransferreply_osx.mm +++ b/src/bluetooth/qbluetoothtransferreply_osx.mm @@ -75,14 +75,14 @@ public: private: // OBEX session delegate: - void OBEXConnectError(OBEXError errorCode, OBEXOpCode response) Q_DECL_OVERRIDE; - void OBEXConnectSuccess() Q_DECL_OVERRIDE; + void OBEXConnectError(OBEXError errorCode, OBEXOpCode response) override; + void OBEXConnectSuccess() override; - void OBEXAbortSuccess() Q_DECL_OVERRIDE; + void OBEXAbortSuccess() override; - void OBEXPutDataSent(quint32 current, quint32 total) Q_DECL_OVERRIDE; - void OBEXPutSuccess() Q_DECL_OVERRIDE; - void OBEXPutError(OBEXError error, OBEXOpCode response) Q_DECL_OVERRIDE; + void OBEXPutDataSent(quint32 current, quint32 total) override; + void OBEXPutSuccess() override; + void OBEXPutError(OBEXError error, OBEXOpCode response) override; QBluetoothTransferReplyOSX *q_ptr; @@ -394,7 +394,7 @@ bool QBluetoothTransferReplyOSX::abort() // Reset a delegate. [osx_d_ptr->session closeSession]; // Should never be called from an OBEX callback! - osx_d_ptr->session.reset(Q_NULLPTR); + osx_d_ptr->session.reset(nullptr); // Not setReplyError, we emit finished only! osx_d_ptr->requestComplete = true; diff --git a/src/bluetooth/qbluetoothtransferreply_osx_p.h b/src/bluetooth/qbluetoothtransferreply_osx_p.h index d77d4913..e7b6f683 100644 --- a/src/bluetooth/qbluetoothtransferreply_osx_p.h +++ b/src/bluetooth/qbluetoothtransferreply_osx_p.h @@ -73,11 +73,11 @@ public: QBluetoothTransferManager *parent); ~QBluetoothTransferReplyOSX(); - TransferError error() const Q_DECL_OVERRIDE; - QString errorString() const Q_DECL_OVERRIDE; + TransferError error() const override; + QString errorString() const override; - bool isFinished() const Q_DECL_OVERRIDE; - bool isRunning() const Q_DECL_OVERRIDE; + bool isFinished() const override; + bool isRunning() const override; Q_SIGNALS: void error(QBluetoothTransferReply::TransferError lastError); diff --git a/src/bluetooth/qbluetoothuuid.h b/src/bluetooth/qbluetoothuuid.h index 2a2ce138..25c7896c 100644 --- a/src/bluetooth/qbluetoothuuid.h +++ b/src/bluetooth/qbluetoothuuid.h @@ -58,6 +58,7 @@ struct quint128 class Q_BLUETOOTH_EXPORT QBluetoothUuid : public QUuid { public: + //TODO Qt 6: Convert enums to scoped enums (see QTBUG-65831) enum ProtocolUuid { Sdp = 0x0001, Udp = 0x0002, @@ -381,10 +382,12 @@ public: bool operator==(const QBluetoothUuid &other) const; bool operator!=(const QBluetoothUuid &other) const { return !operator==(other); } + QBluetoothUuid &operator=(const QBluetoothUuid &other) = default; + int minimumSize() const; - quint16 toUInt16(bool *ok = Q_NULLPTR) const; - quint32 toUInt32(bool *ok = Q_NULLPTR) const; + quint16 toUInt16(bool *ok = nullptr) const; + quint32 toUInt32(bool *ok = nullptr) const; quint128 toUInt128() const; static QString serviceClassToString(ServiceClassUuid uuid); diff --git a/src/bluetooth/qlowenergycharacteristic.h b/src/bluetooth/qlowenergycharacteristic.h index 154c9936..f870a582 100644 --- a/src/bluetooth/qlowenergycharacteristic.h +++ b/src/bluetooth/qlowenergycharacteristic.h @@ -97,7 +97,12 @@ protected: friend class QLowEnergyService; friend class QLowEnergyControllerPrivate; + friend class QLowEnergyControllerPrivateAndroid; + friend class QLowEnergyControllerPrivateBluez; + friend class QLowEnergyControllerPrivateBluezDBus; + friend class QLowEnergyControllerPrivateCommon; friend class QLowEnergyControllerPrivateOSX; + friend class QLowEnergyControllerPrivateWinRT; QLowEnergyCharacteristicPrivate *data; QLowEnergyCharacteristic(QSharedPointer<QLowEnergyServicePrivate> p, QLowEnergyHandle handle); diff --git a/src/bluetooth/qlowenergycontroller.cpp b/src/bluetooth/qlowenergycontroller.cpp index 004ee3be..3be1aed3 100644 --- a/src/bluetooth/qlowenergycontroller.cpp +++ b/src/bluetooth/qlowenergycontroller.cpp @@ -38,7 +38,6 @@ ****************************************************************************/ #include "qlowenergycontroller.h" -#include "qlowenergycontroller_p.h" #include "qlowenergycharacteristicdata.h" #include "qlowenergyconnectionparameters.h" @@ -48,6 +47,19 @@ #include <QtBluetooth/QBluetoothLocalDevice> #include <QtCore/QLoggingCategory> + +#if QT_CONFIG(bluez) && !defined(QT_BLUEZ_NO_BTLE) +#include "bluez/bluez5_helper_p.h" +#include "qlowenergycontroller_bluezdbus_p.h" +#include "qlowenergycontroller_bluez_p.h" +#elif defined(QT_ANDROID_BLUETOOTH) +#include "qlowenergycontroller_android_p.h" +#elif defined(QT_WINRT_BLUETOOTH) +#include "qlowenergycontroller_winrt_p.h" +#else +#include "qlowenergycontroller_p.h" +#endif + #include <algorithm> QT_BEGIN_NAMESPACE @@ -274,212 +286,30 @@ void registerQLowEnergyControllerMetaType() qRegisterMetaType<QLowEnergyController::ControllerState>(); qRegisterMetaType<QLowEnergyController::Error>(); qRegisterMetaType<QLowEnergyConnectionParameters>(); + qRegisterMetaType<QLowEnergyCharacteristic>(); + qRegisterMetaType<QLowEnergyDescriptor>(); initDone = true; } } - -void QLowEnergyControllerPrivate::setError( - QLowEnergyController::Error newError) +static QLowEnergyControllerPrivate *privateController() { - Q_Q(QLowEnergyController); - error = newError; - - switch (newError) { - case QLowEnergyController::UnknownRemoteDeviceError: - errorString = QLowEnergyController::tr("Remote device cannot be found"); - break; - case QLowEnergyController::InvalidBluetoothAdapterError: - errorString = QLowEnergyController::tr("Cannot find local adapter"); - break; - case QLowEnergyController::NetworkError: - errorString = QLowEnergyController::tr("Error occurred during connection I/O"); - break; - case QLowEnergyController::ConnectionError: - errorString = QLowEnergyController::tr("Error occurred trying to connect to remote device."); - break; - case QLowEnergyController::AdvertisingError: - errorString = QLowEnergyController::tr("Error occurred trying to start advertising"); - break; - case QLowEnergyController::RemoteHostClosedError: - errorString = QLowEnergyController::tr("Remote device closed the connection"); - break; - case QLowEnergyController::NoError: - return; - default: - case QLowEnergyController::UnknownError: - errorString = QLowEnergyController::tr("Unknown Error"); - break; +#if QT_CONFIG(bluez) && !defined(QT_BLUEZ_NO_BTLE) + // for now Bluez DBus disabled + if (false && bluetoothdVersion() >= QVersionNumber(5, 42)) { + qCWarning(QT_BT) << "Using BlueZ LE DBus API"; + return new QLowEnergyControllerPrivateBluezDBus(); + } else { + qCWarning(QT_BT) << "Using BlueZ kernel ATT interface"; + return new QLowEnergyControllerPrivateBluez(); } - - emit q->error(newError); -} - -bool QLowEnergyControllerPrivate::isValidLocalAdapter() -{ -#ifdef QT_WINRT_BLUETOOTH - return true; +#elif defined(QT_ANDROID_BLUETOOTH) + return new QLowEnergyControllerPrivateAndroid(); +#elif defined(QT_WINRT_BLUETOOTH) + return new QLowEnergyControllerPrivateWinRT(); +#else + return new QLowEnergyControllerPrivateCommon(); #endif - if (localAdapter.isNull()) - return false; - - const QList<QBluetoothHostInfo> foundAdapters = QBluetoothLocalDevice::allDevices(); - bool adapterFound = false; - - foreach (const QBluetoothHostInfo &info, foundAdapters) { - if (info.address() == localAdapter) { - adapterFound = true; - break; - } - } - - return adapterFound; -} - -void QLowEnergyControllerPrivate::setState( - QLowEnergyController::ControllerState newState) -{ - Q_Q(QLowEnergyController); - if (state == newState) - return; - - state = newState; - if (state == QLowEnergyController::UnconnectedState - && role == QLowEnergyController::PeripheralRole) { - remoteDevice.clear(); - } - emit q->stateChanged(state); -} - -void QLowEnergyControllerPrivate::invalidateServices() -{ - foreach (const QSharedPointer<QLowEnergyServicePrivate> service, serviceList.values()) { - service->setController(0); - service->setState(QLowEnergyService::InvalidService); - } - - serviceList.clear(); -} - -QSharedPointer<QLowEnergyServicePrivate> QLowEnergyControllerPrivate::serviceForHandle( - QLowEnergyHandle handle) -{ - ServiceDataMap ¤tList = serviceList; - if (role == QLowEnergyController::PeripheralRole) - currentList = localServices; - - const QList<QSharedPointer<QLowEnergyServicePrivate>> values = currentList.values(); - for (auto service: values) - if (service->startHandle <= handle && handle <= service->endHandle) - return service; - - return QSharedPointer<QLowEnergyServicePrivate>(); -} - -/*! - Returns a valid characteristic if the given handle is the - handle of the characteristic itself or one of its descriptors - */ -QLowEnergyCharacteristic QLowEnergyControllerPrivate::characteristicForHandle( - QLowEnergyHandle handle) -{ - QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(handle); - if (service.isNull()) - return QLowEnergyCharacteristic(); - - if (service->characteristicList.isEmpty()) - return QLowEnergyCharacteristic(); - - // check whether it is the handle of a characteristic header - if (service->characteristicList.contains(handle)) - return QLowEnergyCharacteristic(service, handle); - - // check whether it is the handle of the characteristic value or its descriptors - QList<QLowEnergyHandle> charHandles = service->characteristicList.keys(); - std::sort(charHandles.begin(), charHandles.end()); - for (int i = charHandles.size() - 1; i >= 0; i--) { - if (charHandles.at(i) > handle) - continue; - - return QLowEnergyCharacteristic(service, charHandles.at(i)); - } - - return QLowEnergyCharacteristic(); -} - -/*! - Returns a valid descriptor if \a handle belongs to a descriptor; - otherwise an invalid one. - */ -QLowEnergyDescriptor QLowEnergyControllerPrivate::descriptorForHandle( - QLowEnergyHandle handle) -{ - const QLowEnergyCharacteristic matchingChar = characteristicForHandle(handle); - if (!matchingChar.isValid()) - return QLowEnergyDescriptor(); - - const QLowEnergyServicePrivate::CharData charData = matchingChar. - d_ptr->characteristicList[matchingChar.attributeHandle()]; - - if (charData.descriptorList.contains(handle)) - return QLowEnergyDescriptor(matchingChar.d_ptr, matchingChar.attributeHandle(), - handle); - - return QLowEnergyDescriptor(); -} - -/*! - Returns the length of the updated characteristic value. - */ -quint16 QLowEnergyControllerPrivate::updateValueOfCharacteristic( - QLowEnergyHandle charHandle,const QByteArray &value, bool appendValue) -{ - QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(charHandle); - if (!service.isNull()) { - CharacteristicDataMap::iterator charIt = service->characteristicList.find(charHandle); - if (charIt != service->characteristicList.end()) { - QLowEnergyServicePrivate::CharData &charDetails = charIt.value(); - - if (appendValue) - charDetails.value += value; - else - charDetails.value = value; - - return charDetails.value.size(); - } - } - - return 0; -} - -/*! - Returns the length of the updated descriptor value. - */ -quint16 QLowEnergyControllerPrivate::updateValueOfDescriptor( - QLowEnergyHandle charHandle, QLowEnergyHandle descriptorHandle, - const QByteArray &value, bool appendValue) -{ - QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(charHandle); - if (!service.isNull()) { - CharacteristicDataMap::iterator charIt = service->characteristicList.find(charHandle); - if (charIt != service->characteristicList.end()) { - QLowEnergyServicePrivate::CharData &charDetails = charIt.value(); - - DescriptorDataMap::iterator descIt = charDetails.descriptorList.find(descriptorHandle); - if (descIt != charDetails.descriptorList.end()) { - QLowEnergyServicePrivate::DescData &descDetails = descIt.value(); - - if (appendValue) - descDetails.value += value; - else - descDetails.value = value; - - return descDetails.value.size(); - } - } - } - - return 0; } /*! @@ -497,8 +327,10 @@ quint16 QLowEnergyControllerPrivate::updateValueOfDescriptor( QLowEnergyController::QLowEnergyController( const QBluetoothAddress &remoteDevice, QObject *parent) - : QObject(parent), d_ptr(new QLowEnergyControllerPrivate()) + : QObject(parent) { + d_ptr = privateController(); + Q_D(QLowEnergyController); d->q_ptr = this; d->role = CentralRole; @@ -524,8 +356,10 @@ QLowEnergyController::QLowEnergyController( QLowEnergyController::QLowEnergyController( const QBluetoothDeviceInfo &remoteDeviceInfo, QObject *parent) - : QObject(parent), d_ptr(new QLowEnergyControllerPrivate()) + : QObject(parent) { + d_ptr = privateController(); + Q_D(QLowEnergyController); d->q_ptr = this; d->role = CentralRole; @@ -555,8 +389,10 @@ QLowEnergyController::QLowEnergyController( const QBluetoothAddress &remoteDevice, const QBluetoothAddress &localDevice, QObject *parent) - : QObject(parent), d_ptr(new QLowEnergyControllerPrivate()) + : QObject(parent) { + d_ptr = privateController(); + Q_D(QLowEnergyController); d->q_ptr = this; d->role = CentralRole; @@ -598,8 +434,10 @@ QLowEnergyController *QLowEnergyController::createPeripheral(QObject *parent) } QLowEnergyController::QLowEnergyController(QObject *parent) - : QObject(parent), d_ptr(new QLowEnergyControllerPrivate()) + : QObject(parent) { + d_ptr = privateController(); + Q_D(QLowEnergyController); d->q_ptr = this; d->role = PeripheralRole; @@ -850,7 +688,7 @@ QLowEnergyService *QLowEnergyController::createServiceObject( { Q_D(QLowEnergyController); - QLowEnergyService *service = Q_NULLPTR; + QLowEnergyService *service = nullptr; ServiceDataMap::const_iterator it = d->serviceList.constFind(serviceUuid); if (it != d->serviceList.constEnd()) { @@ -944,55 +782,6 @@ QLowEnergyService *QLowEnergyController::addService(const QLowEnergyServiceData return newService; } -QLowEnergyService *QLowEnergyControllerPrivate::addServiceHelper( - const QLowEnergyServiceData &service) -{ - // Spec says services "should" be grouped by uuid length (16-bit first, then 128-bit). - // Since this is not mandatory, we ignore it here and let the caller take responsibility - // for it. - - const auto servicePrivate = QSharedPointer<QLowEnergyServicePrivate>::create(); - servicePrivate->state = QLowEnergyService::LocalService; - servicePrivate->setController(this); - servicePrivate->uuid = service.uuid(); - servicePrivate->type = service.type() == QLowEnergyServiceData::ServiceTypePrimary - ? QLowEnergyService::PrimaryService : QLowEnergyService::IncludedService; - foreach (QLowEnergyService * const includedService, service.includedServices()) { - servicePrivate->includedServices << includedService->serviceUuid(); - includedService->d_ptr->type |= QLowEnergyService::IncludedService; - } - - // Spec v4.2, Vol 3, Part G, Section 3. - const QLowEnergyHandle oldLastHandle = this->lastLocalHandle; - servicePrivate->startHandle = ++this->lastLocalHandle; // Service declaration. - this->lastLocalHandle += servicePrivate->includedServices.count(); // Include declarations. - foreach (const QLowEnergyCharacteristicData &cd, service.characteristics()) { - const QLowEnergyHandle declHandle = ++this->lastLocalHandle; - QLowEnergyServicePrivate::CharData charData; - charData.valueHandle = ++this->lastLocalHandle; - charData.uuid = cd.uuid(); - charData.properties = cd.properties(); - charData.value = cd.value(); - foreach (const QLowEnergyDescriptorData &dd, cd.descriptors()) { - QLowEnergyServicePrivate::DescData descData; - descData.uuid = dd.uuid(); - descData.value = dd.value(); - charData.descriptorList.insert(++this->lastLocalHandle, descData); - } - servicePrivate->characteristicList.insert(declHandle, charData); - } - servicePrivate->endHandle = this->lastLocalHandle; - const bool handleOverflow = this->lastLocalHandle <= oldLastHandle; - if (handleOverflow) { - qCWarning(QT_BT) << "Not enough attribute handles left to create this service"; - this->lastLocalHandle = oldLastHandle; - return nullptr; - } - - this->localServices.insert(servicePrivate->uuid, servicePrivate); - this->addToGenericAttributeList(service, servicePrivate->startHandle); - return new QLowEnergyService(servicePrivate); -} /*! Requests the controller to update the connection according to \a parameters. diff --git a/src/bluetooth/qlowenergycontroller.h b/src/bluetooth/qlowenergycontroller.h index 1a84b05b..f9e6ef5d 100644 --- a/src/bluetooth/qlowenergycontroller.h +++ b/src/bluetooth/qlowenergycontroller.h @@ -91,12 +91,12 @@ public: Q_ENUM(Role) explicit QLowEnergyController(const QBluetoothAddress &remoteDevice, - QObject *parent = Q_NULLPTR); // TODO Qt 6 remove ctor + QObject *parent = nullptr); // TODO Qt 6 remove ctor explicit QLowEnergyController(const QBluetoothDeviceInfo &remoteDevice, - QObject *parent = Q_NULLPTR); + QObject *parent = nullptr); explicit QLowEnergyController(const QBluetoothAddress &remoteDevice, const QBluetoothAddress &localDevice, - QObject *parent = Q_NULLPTR); // TODO Qt 6 remove ctor + QObject *parent = nullptr); // TODO Qt 6 remove ctor static QLowEnergyController *createCentral(const QBluetoothDeviceInfo &remoteDevice, QObject *parent = nullptr); @@ -122,7 +122,7 @@ public: void discoverServices(); QList<QBluetoothUuid> services() const; - QLowEnergyService *createServiceObject(const QBluetoothUuid &service, QObject *parent = Q_NULLPTR); + QLowEnergyService *createServiceObject(const QBluetoothUuid &service, QObject *parent = nullptr); void startAdvertising(const QLowEnergyAdvertisingParameters ¶meters, const QLowEnergyAdvertisingData &advertisingData, diff --git a/src/bluetooth/qlowenergycontroller_android.cpp b/src/bluetooth/qlowenergycontroller_android.cpp index a1decd96..8dccb859 100644 --- a/src/bluetooth/qlowenergycontroller_android.cpp +++ b/src/bluetooth/qlowenergycontroller_android.cpp @@ -37,7 +37,7 @@ ** ****************************************************************************/ -#include "qlowenergycontroller_p.h" +#include "qlowenergycontroller_android_p.h" #include <QtCore/QLoggingCategory> #include <QtAndroidExtras/QAndroidJniEnvironment> #include <QtBluetooth/QLowEnergyServiceData> @@ -69,16 +69,14 @@ static QAndroidJniObject javaUuidfromQtUuid(const QBluetoothUuid& uuid) return javaUuid; } -QLowEnergyControllerPrivate::QLowEnergyControllerPrivate() - : QObject(), - state(QLowEnergyController::UnconnectedState), - error(QLowEnergyController::NoError), +QLowEnergyControllerPrivateAndroid::QLowEnergyControllerPrivateAndroid() + : QLowEnergyControllerPrivate(), hub(0) { registerQLowEnergyControllerMetaType(); } -QLowEnergyControllerPrivate::~QLowEnergyControllerPrivate() +QLowEnergyControllerPrivateAndroid::~QLowEnergyControllerPrivateAndroid() { if (role == QLowEnergyController::PeripheralRole) { if (hub) @@ -86,7 +84,7 @@ QLowEnergyControllerPrivate::~QLowEnergyControllerPrivate() } } -void QLowEnergyControllerPrivate::init() +void QLowEnergyControllerPrivateAndroid::init() { // Android Central/Client support starts with v18 // Peripheral/Server support requires Android API v21 @@ -106,13 +104,13 @@ void QLowEnergyControllerPrivate::init() // we only connect to the peripheral role specific signals // TODO add connections as they get added later on connect(hub, &LowEnergyNotificationHub::connectionUpdated, - this, &QLowEnergyControllerPrivate::connectionUpdated); + this, &QLowEnergyControllerPrivateAndroid::connectionUpdated); connect(hub, &LowEnergyNotificationHub::advertisementError, - this, &QLowEnergyControllerPrivate::advertisementError); + this, &QLowEnergyControllerPrivateAndroid::advertisementError); connect(hub, &LowEnergyNotificationHub::serverCharacteristicChanged, - this, &QLowEnergyControllerPrivate::serverCharacteristicChanged); + this, &QLowEnergyControllerPrivateAndroid::serverCharacteristicChanged); connect(hub, &LowEnergyNotificationHub::serverDescriptorWritten, - this, &QLowEnergyControllerPrivate::serverDescriptorWritten); + this, &QLowEnergyControllerPrivateAndroid::serverDescriptorWritten); } else { if (version < 18) { qWarning() << "Qt Bluetooth LE Central/Client support not available" @@ -123,25 +121,25 @@ void QLowEnergyControllerPrivate::init() hub = new LowEnergyNotificationHub(remoteDevice, isPeripheral, this); // we only connect to the central role specific signals connect(hub, &LowEnergyNotificationHub::connectionUpdated, - this, &QLowEnergyControllerPrivate::connectionUpdated); + this, &QLowEnergyControllerPrivateAndroid::connectionUpdated); connect(hub, &LowEnergyNotificationHub::servicesDiscovered, - this, &QLowEnergyControllerPrivate::servicesDiscovered); + this, &QLowEnergyControllerPrivateAndroid::servicesDiscovered); connect(hub, &LowEnergyNotificationHub::serviceDetailsDiscoveryFinished, - this, &QLowEnergyControllerPrivate::serviceDetailsDiscoveryFinished); + this, &QLowEnergyControllerPrivateAndroid::serviceDetailsDiscoveryFinished); connect(hub, &LowEnergyNotificationHub::characteristicRead, - this, &QLowEnergyControllerPrivate::characteristicRead); + this, &QLowEnergyControllerPrivateAndroid::characteristicRead); connect(hub, &LowEnergyNotificationHub::descriptorRead, - this, &QLowEnergyControllerPrivate::descriptorRead); + this, &QLowEnergyControllerPrivateAndroid::descriptorRead); connect(hub, &LowEnergyNotificationHub::characteristicWritten, - this, &QLowEnergyControllerPrivate::characteristicWritten); + this, &QLowEnergyControllerPrivateAndroid::characteristicWritten); connect(hub, &LowEnergyNotificationHub::descriptorWritten, - this, &QLowEnergyControllerPrivate::descriptorWritten); + this, &QLowEnergyControllerPrivateAndroid::descriptorWritten); connect(hub, &LowEnergyNotificationHub::characteristicChanged, - this, &QLowEnergyControllerPrivate::characteristicChanged); + this, &QLowEnergyControllerPrivateAndroid::characteristicChanged); } } -void QLowEnergyControllerPrivate::connectToDevice() +void QLowEnergyControllerPrivateAndroid::connectToDevice() { if (!hub) return; // Android version below v18 @@ -170,7 +168,7 @@ void QLowEnergyControllerPrivate::connectToDevice() } } -void QLowEnergyControllerPrivate::disconnectFromDevice() +void QLowEnergyControllerPrivateAndroid::disconnectFromDevice() { /* Catch an Android timeout bug. If the device is connecting but cannot * physically connect it seems to ignore the disconnect call below. @@ -188,7 +186,7 @@ void QLowEnergyControllerPrivate::disconnectFromDevice() setState(QLowEnergyController::UnconnectedState); } -void QLowEnergyControllerPrivate::discoverServices() +void QLowEnergyControllerPrivateAndroid::discoverServices() { if (hub && hub->javaObject().callMethod<jboolean>("discoverServices")) { qCDebug(QT_BT_ANDROID) << "Service discovery initiated"; @@ -199,7 +197,7 @@ void QLowEnergyControllerPrivate::discoverServices() } } -void QLowEnergyControllerPrivate::discoverServiceDetails(const QBluetoothUuid &service) +void QLowEnergyControllerPrivateAndroid::discoverServiceDetails(const QBluetoothUuid &service) { if (!serviceList.contains(service)) { qCWarning(QT_BT_ANDROID) << "Discovery of unknown service" << service.toString() @@ -234,7 +232,7 @@ void QLowEnergyControllerPrivate::discoverServiceDetails(const QBluetoothUuid &s qCDebug(QT_BT_ANDROID) << "Discovery of" << service << "started"; } -void QLowEnergyControllerPrivate::writeCharacteristic( +void QLowEnergyControllerPrivateAndroid::writeCharacteristic( const QSharedPointer<QLowEnergyServicePrivate> service, const QLowEnergyHandle charHandle, const QByteArray &newValue, @@ -288,7 +286,7 @@ void QLowEnergyControllerPrivate::writeCharacteristic( service->setError(QLowEnergyService::CharacteristicWriteError); } -void QLowEnergyControllerPrivate::writeDescriptor( +void QLowEnergyControllerPrivateAndroid::writeDescriptor( const QSharedPointer<QLowEnergyServicePrivate> service, const QLowEnergyHandle charHandle, const QLowEnergyHandle descHandle, @@ -339,7 +337,7 @@ void QLowEnergyControllerPrivate::writeDescriptor( service->setError(QLowEnergyService::DescriptorWriteError); } -void QLowEnergyControllerPrivate::readCharacteristic( +void QLowEnergyControllerPrivateAndroid::readCharacteristic( const QSharedPointer<QLowEnergyServicePrivate> service, const QLowEnergyHandle charHandle) { @@ -367,7 +365,7 @@ void QLowEnergyControllerPrivate::readCharacteristic( service->setError(QLowEnergyService::CharacteristicReadError); } -void QLowEnergyControllerPrivate::readDescriptor( +void QLowEnergyControllerPrivateAndroid::readDescriptor( const QSharedPointer<QLowEnergyServicePrivate> service, const QLowEnergyHandle /*charHandle*/, const QLowEnergyHandle descriptorHandle) @@ -393,7 +391,7 @@ void QLowEnergyControllerPrivate::readDescriptor( service->setError(QLowEnergyService::DescriptorReadError); } -void QLowEnergyControllerPrivate::connectionUpdated( +void QLowEnergyControllerPrivateAndroid::connectionUpdated( QLowEnergyController::ControllerState newState, QLowEnergyController::Error errorCode) { @@ -409,7 +407,7 @@ void QLowEnergyControllerPrivate::connectionUpdated( } // called if server/peripheral -void QLowEnergyControllerPrivate::peripheralConnectionUpdated( +void QLowEnergyControllerPrivateAndroid::peripheralConnectionUpdated( QLowEnergyController::ControllerState newState, QLowEnergyController::Error errorCode) { @@ -439,7 +437,7 @@ void QLowEnergyControllerPrivate::peripheralConnectionUpdated( } // called if client/central -void QLowEnergyControllerPrivate::centralConnectionUpdated( +void QLowEnergyControllerPrivateAndroid::centralConnectionUpdated( QLowEnergyController::ControllerState newState, QLowEnergyController::Error errorCode) { @@ -484,7 +482,7 @@ void QLowEnergyControllerPrivate::centralConnectionUpdated( } } -void QLowEnergyControllerPrivate::servicesDiscovered( +void QLowEnergyControllerPrivateAndroid::servicesDiscovered( QLowEnergyController::Error errorCode, const QString &foundServices) { Q_Q(QLowEnergyController); @@ -515,7 +513,7 @@ void QLowEnergyControllerPrivate::servicesDiscovered( } } -void QLowEnergyControllerPrivate::serviceDetailsDiscoveryFinished( +void QLowEnergyControllerPrivateAndroid::serviceDetailsDiscoveryFinished( const QString &serviceUuid, int startHandle, int endHandle) { const QBluetoothUuid service(serviceUuid); @@ -563,7 +561,7 @@ void QLowEnergyControllerPrivate::serviceDetailsDiscoveryFinished( pointer->setState(QLowEnergyService::ServiceDiscovered); } -void QLowEnergyControllerPrivate::characteristicRead( +void QLowEnergyControllerPrivateAndroid::characteristicRead( const QBluetoothUuid &serviceUuid, int handle, const QBluetoothUuid &charUuid, int properties, const QByteArray &data) { @@ -594,7 +592,7 @@ void QLowEnergyControllerPrivate::characteristicRead( } } -void QLowEnergyControllerPrivate::descriptorRead( +void QLowEnergyControllerPrivateAndroid::descriptorRead( const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid, int descHandle, const QBluetoothUuid &descUuid, const QByteArray &data) { @@ -635,7 +633,7 @@ void QLowEnergyControllerPrivate::descriptorRead( } } -void QLowEnergyControllerPrivate::characteristicWritten( +void QLowEnergyControllerPrivateAndroid::characteristicWritten( int charHandle, const QByteArray &data, QLowEnergyService::ServiceError errorCode) { QSharedPointer<QLowEnergyServicePrivate> service = @@ -664,7 +662,7 @@ void QLowEnergyControllerPrivate::characteristicWritten( emit service->characteristicWritten(characteristic, data); } -void QLowEnergyControllerPrivate::descriptorWritten( +void QLowEnergyControllerPrivateAndroid::descriptorWritten( int descHandle, const QByteArray &data, QLowEnergyService::ServiceError errorCode) { QSharedPointer<QLowEnergyServicePrivate> service = @@ -691,7 +689,7 @@ void QLowEnergyControllerPrivate::descriptorWritten( emit service->descriptorWritten(descriptor, data); } -void QLowEnergyControllerPrivate::serverDescriptorWritten( +void QLowEnergyControllerPrivateAndroid::serverDescriptorWritten( const QAndroidJniObject &jniDesc, const QByteArray &newValue) { qCDebug(QT_BT_ANDROID) << "Server descriptor change notification" << newValue.toHex(); @@ -756,7 +754,7 @@ void QLowEnergyControllerPrivate::serverDescriptorWritten( } } -void QLowEnergyControllerPrivate::characteristicChanged( +void QLowEnergyControllerPrivateAndroid::characteristicChanged( int charHandle, const QByteArray &data) { QSharedPointer<QLowEnergyServicePrivate> service = @@ -781,7 +779,7 @@ void QLowEnergyControllerPrivate::characteristicChanged( emit service->characteristicChanged(characteristic, data); } -void QLowEnergyControllerPrivate::serverCharacteristicChanged( +void QLowEnergyControllerPrivateAndroid::serverCharacteristicChanged( const QAndroidJniObject &characteristic, const QByteArray &newValue) { qCDebug(QT_BT_ANDROID) << "Server characteristic change notification" << newValue.toHex(); @@ -830,7 +828,7 @@ void QLowEnergyControllerPrivate::serverCharacteristicChanged( QLowEnergyCharacteristic(servicePrivate, foundHandle), newValue); } -void QLowEnergyControllerPrivate::serviceError( +void QLowEnergyControllerPrivateAndroid::serviceError( int attributeHandle, QLowEnergyService::ServiceError errorCode) { // ignore call if it isn't really an error @@ -846,7 +844,7 @@ void QLowEnergyControllerPrivate::serviceError( service->setError(errorCode); } -void QLowEnergyControllerPrivate::advertisementError(int errorCode) +void QLowEnergyControllerPrivateAndroid::advertisementError(int errorCode) { Q_Q(QLowEnergyController); @@ -997,7 +995,7 @@ static QAndroidJniObject createJavaAdvertiseSettings(const QLowEnergyAdvertising } -void QLowEnergyControllerPrivate::startAdvertising(const QLowEnergyAdvertisingParameters ¶ms, +void QLowEnergyControllerPrivateAndroid::startAdvertising(const QLowEnergyAdvertisingParameters ¶ms, const QLowEnergyAdvertisingData &advertisingData, const QLowEnergyAdvertisingData &scanResponseData) { @@ -1024,13 +1022,13 @@ void QLowEnergyControllerPrivate::startAdvertising(const QLowEnergyAdvertisingPa } } -void QLowEnergyControllerPrivate::stopAdvertising() +void QLowEnergyControllerPrivateAndroid::stopAdvertising() { setState(QLowEnergyController::UnconnectedState); hub->javaObject().callMethod<void>("stopAdvertising"); } -void QLowEnergyControllerPrivate::requestConnectionUpdate(const QLowEnergyConnectionParameters ¶ms) +void QLowEnergyControllerPrivateAndroid::requestConnectionUpdate(const QLowEnergyConnectionParameters ¶ms) { // Possible since Android v21 // Android does not permit specification of specific latency or min/max @@ -1169,7 +1167,7 @@ static int setupDescPermissions(const QLowEnergyDescriptorData &descData) return permissions; } -void QLowEnergyControllerPrivate::addToGenericAttributeList(const QLowEnergyServiceData &serviceData, +void QLowEnergyControllerPrivateAndroid::addToGenericAttributeList(const QLowEnergyServiceData &serviceData, QLowEnergyHandle startHandle) { QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(startHandle); diff --git a/src/bluetooth/qlowenergycontroller_android_p.h b/src/bluetooth/qlowenergycontroller_android_p.h new file mode 100644 index 00000000..e575d96e --- /dev/null +++ b/src/bluetooth/qlowenergycontroller_android_p.h @@ -0,0 +1,171 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtBluetooth module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLOWENERGYCONTROLLERPRIVATEANDROID_P_H +#define QLOWENERGYCONTROLLERPRIVATEANDROID_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + + +#include <qglobal.h> +#include <QtCore/QQueue> +#include <QtCore/QVector> +#include <QtBluetooth/qbluetooth.h> +#include <QtBluetooth/qlowenergycharacteristic.h> +#include "qlowenergycontroller.h" +#include "qlowenergycontrollerbase_p.h" + +#if QT_CONFIG(bluez) && !defined(QT_BLUEZ_NO_BTLE) +#include <QtBluetooth/QBluetoothSocket> +#elif defined(QT_ANDROID_BLUETOOTH) +#include <QtAndroidExtras/QAndroidJniObject> +#include "android/lowenergynotificationhub_p.h" +#elif defined(QT_WINRT_BLUETOOTH) +#include <wrl.h> +#include <windows.devices.bluetooth.h> +#endif + +#include <functional> + +QT_BEGIN_NAMESPACE + +class QLowEnergyServiceData; +class QTimer; + +#if QT_CONFIG(bluez) && !defined(QT_BLUEZ_NO_BTLE) +class HciManager; +class LeCmacCalculator; +class QSocketNotifier; +class RemoteDeviceManager; +#elif defined(QT_ANDROID_BLUETOOTH) +class LowEnergyNotificationHub; +#elif defined(QT_WINRT_BLUETOOTH) +class QWinRTLowEnergyServiceHandler; +#endif + +extern void registerQLowEnergyControllerMetaType(); + +class QLeAdvertiser; + +class QLowEnergyControllerPrivateAndroid : public QLowEnergyControllerPrivate +{ + Q_OBJECT +public: + QLowEnergyControllerPrivateAndroid(); + ~QLowEnergyControllerPrivateAndroid(); + + void init() override; + + void connectToDevice() override; + void disconnectFromDevice() override; + + void discoverServices() override; + void discoverServiceDetails(const QBluetoothUuid &service) override; + + void startAdvertising(const QLowEnergyAdvertisingParameters ¶ms, + const QLowEnergyAdvertisingData &advertisingData, + const QLowEnergyAdvertisingData &scanResponseData) override; + void stopAdvertising() override; + + void requestConnectionUpdate(const QLowEnergyConnectionParameters ¶ms) override; + + // read data + void readCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service, + const QLowEnergyHandle charHandle) override; + void readDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle) override; + + // write data + void writeCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service, + const QLowEnergyHandle charHandle, + const QByteArray &newValue, QLowEnergyService::WriteMode mode) override; + void writeDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle, + const QByteArray &newValue) override; + + void addToGenericAttributeList(const QLowEnergyServiceData &service, + QLowEnergyHandle startHandle) override; + +private: + + LowEnergyNotificationHub *hub; + +private slots: + void connectionUpdated(QLowEnergyController::ControllerState newState, + QLowEnergyController::Error errorCode); + void servicesDiscovered(QLowEnergyController::Error errorCode, + const QString &foundServices); + void serviceDetailsDiscoveryFinished(const QString& serviceUuid, + int startHandle, int endHandle); + void characteristicRead(const QBluetoothUuid &serviceUuid, int handle, + const QBluetoothUuid &charUuid, int properties, + const QByteArray& data); + void descriptorRead(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid, + int handle, const QBluetoothUuid &descUuid, const QByteArray &data); + void characteristicWritten(int charHandle, const QByteArray &data, + QLowEnergyService::ServiceError errorCode); + void descriptorWritten(int descHandle, const QByteArray &data, + QLowEnergyService::ServiceError errorCode); + void serverDescriptorWritten(const QAndroidJniObject &jniDesc, const QByteArray &newValue); + void characteristicChanged(int charHandle, const QByteArray &data); + void serverCharacteristicChanged(const QAndroidJniObject &jniChar, const QByteArray &newValue); + void serviceError(int attributeHandle, QLowEnergyService::ServiceError errorCode); + void advertisementError(int errorCode); + +private: + void peripheralConnectionUpdated(QLowEnergyController::ControllerState newState, + QLowEnergyController::Error errorCode); + void centralConnectionUpdated(QLowEnergyController::ControllerState newState, + QLowEnergyController::Error errorCode); +}; + +QT_END_NAMESPACE + +#endif // QLOWENERGYCONTROLLERPRIVATEANDROID_P_H diff --git a/src/bluetooth/qlowenergycontroller_bluez.cpp b/src/bluetooth/qlowenergycontroller_bluez.cpp index d038a8e8..c4ff0e7f 100644 --- a/src/bluetooth/qlowenergycontroller_bluez.cpp +++ b/src/bluetooth/qlowenergycontroller_bluez.cpp @@ -39,7 +39,7 @@ ****************************************************************************/ #include "lecmaccalculator_p.h" -#include "qlowenergycontroller_p.h" +#include "qlowenergycontroller_bluez_p.h" #include "qbluetoothsocket_p.h" #include "qleadvertiser_p.h" #include "bluez/bluez_data_p.h" @@ -263,11 +263,8 @@ template<> void putDataAndIncrement(const QByteArray &value, char *&dst) dst += value.count(); } -QLowEnergyControllerPrivate::QLowEnergyControllerPrivate() - : QObject(), - state(QLowEnergyController::UnconnectedState), - error(QLowEnergyController::NoError), - lastLocalHandle(0), +QLowEnergyControllerPrivateBluez::QLowEnergyControllerPrivateBluez() + : QLowEnergyControllerPrivate(), l2cpSocket(0), requestPending(false), mtuSize(ATT_DEFAULT_LE_MTU), securityLevelValue(-1), @@ -280,7 +277,7 @@ QLowEnergyControllerPrivate::QLowEnergyControllerPrivate() qRegisterMetaType<QList<QLowEnergyHandle> >(); } -void QLowEnergyControllerPrivate::init() +void QLowEnergyControllerPrivateBluez::init() { hciManager = new HciManager(localAdapter, this); if (!hciManager->isValid()) @@ -331,12 +328,12 @@ void QLowEnergyControllerPrivate::init() requestTimer->setSingleShot(true); requestTimer->setInterval(gattRequestTimeout); connect(requestTimer, &QTimer::timeout, - this, &QLowEnergyControllerPrivate::handleGattRequestTimeout); + this, &QLowEnergyControllerPrivateBluez::handleGattRequestTimeout); } } } -void QLowEnergyControllerPrivate::handleGattRequestTimeout() +void QLowEnergyControllerPrivateBluez::handleGattRequestTimeout() { // antyhing open that might require cancellation or a warning? if (encryptionChangePending) { @@ -415,7 +412,7 @@ void QLowEnergyControllerPrivate::handleGattRequestTimeout() } } -QLowEnergyControllerPrivate::~QLowEnergyControllerPrivate() +QLowEnergyControllerPrivateBluez::~QLowEnergyControllerPrivateBluez() { closeServerSocket(); delete cmacCalculator; @@ -471,7 +468,7 @@ private: }; -void QLowEnergyControllerPrivate::startAdvertising(const QLowEnergyAdvertisingParameters ¶ms, +void QLowEnergyControllerPrivateBluez::startAdvertising(const QLowEnergyAdvertisingParameters ¶ms, const QLowEnergyAdvertisingData &advertisingData, const QLowEnergyAdvertisingData &scanResponseData) { @@ -480,7 +477,7 @@ void QLowEnergyControllerPrivate::startAdvertising(const QLowEnergyAdvertisingPa advertiser = new QLeAdvertiserBluez(params, advertisingData, scanResponseData, *hciManager, this); connect(advertiser, &QLeAdvertiser::errorOccurred, this, - &QLowEnergyControllerPrivate::handleAdvertisingError); + &QLowEnergyControllerPrivateBluez::handleAdvertisingError); } setState(QLowEnergyController::AdvertisingState); advertiser->startAdvertising(); @@ -501,16 +498,16 @@ void QLowEnergyControllerPrivate::startAdvertising(const QLowEnergyAdvertisingPa const int socketFd = serverSocket.takeSocket(); serverSocketNotifier = new QSocketNotifier(socketFd, QSocketNotifier::Read, this); connect(serverSocketNotifier, &QSocketNotifier::activated, this, - &QLowEnergyControllerPrivate::handleConnectionRequest); + &QLowEnergyControllerPrivateBluez::handleConnectionRequest); } -void QLowEnergyControllerPrivate::stopAdvertising() +void QLowEnergyControllerPrivateBluez::stopAdvertising() { setState(QLowEnergyController::UnconnectedState); advertiser->stopAdvertising(); } -void QLowEnergyControllerPrivate::requestConnectionUpdate(const QLowEnergyConnectionParameters ¶ms) +void QLowEnergyControllerPrivateBluez::requestConnectionUpdate(const QLowEnergyConnectionParameters ¶ms) { // The spec says that the connection update command can be used by both slave and master // devices, but BlueZ allows it only for master devices. So for slave devices, we have to use a @@ -522,7 +519,7 @@ void QLowEnergyControllerPrivate::requestConnectionUpdate(const QLowEnergyConnec hciManager->sendConnectionParameterUpdateRequest(connectionHandle, params); } -void QLowEnergyControllerPrivate::connectToDevice() +void QLowEnergyControllerPrivateBluez::connectToDevice() { if (remoteDevice.isNull()) { qCWarning(QT_BT_BLUEZ) << "Invalid/null remote device address"; @@ -556,7 +553,7 @@ void QLowEnergyControllerPrivate::connectToDevice() if (!device1Manager) { device1Manager = new RemoteDeviceManager(localAdapter, this); connect(device1Manager, &RemoteDeviceManager::finished, - this, &QLowEnergyControllerPrivate::activeConnectionTerminationDone); + this, &QLowEnergyControllerPrivateBluez::activeConnectionTerminationDone); } QVector<QBluetoothAddress> connectedAddresses; @@ -574,7 +571,7 @@ void QLowEnergyControllerPrivate::connectToDevice() /*! * Handles outcome of attempts to close external connections. */ -void QLowEnergyControllerPrivate::activeConnectionTerminationDone() +void QLowEnergyControllerPrivateBluez::activeConnectionTerminationDone() { if (!device1Manager) return; @@ -597,7 +594,7 @@ void QLowEnergyControllerPrivate::activeConnectionTerminationDone() /*! * Establishes the L2CP client socket. */ -void QLowEnergyControllerPrivate::establishL2cpClientSocket() +void QLowEnergyControllerPrivateBluez::establishL2cpClientSocket() { //we are already in Connecting state @@ -653,7 +650,7 @@ void QLowEnergyControllerPrivate::establishL2cpClientSocket() loadSigningDataIfNecessary(LocalSigningKey); } -void QLowEnergyControllerPrivate::createServicesForCentralIfRequired() +void QLowEnergyControllerPrivateBluez::createServicesForCentralIfRequired() { bool ok = false; int value = qEnvironmentVariableIntValue("QT_DEFAULT_CENTRAL_SERVICES", &ok); @@ -719,7 +716,7 @@ void QLowEnergyControllerPrivate::createServicesForCentralIfRequired() service->setParent(q); } -void QLowEnergyControllerPrivate::l2cpConnected() +void QLowEnergyControllerPrivateBluez::l2cpConnected() { Q_Q(QLowEnergyController); @@ -730,7 +727,7 @@ void QLowEnergyControllerPrivate::l2cpConnected() emit q->connected(); } -void QLowEnergyControllerPrivate::disconnectFromDevice() +void QLowEnergyControllerPrivateBluez::disconnectFromDevice() { setState(QLowEnergyController::ClosingState); if (l2cpSocket) @@ -745,7 +742,7 @@ void QLowEnergyControllerPrivate::disconnectFromDevice() } } -void QLowEnergyControllerPrivate::l2cpDisconnected() +void QLowEnergyControllerPrivateBluez::l2cpDisconnected() { Q_Q(QLowEnergyController); @@ -757,7 +754,7 @@ void QLowEnergyControllerPrivate::l2cpDisconnected() emit q->disconnected(); } -void QLowEnergyControllerPrivate::l2cpErrorChanged(QBluetoothSocket::SocketError e) +void QLowEnergyControllerPrivateBluez::l2cpErrorChanged(QBluetoothSocket::SocketError e) { switch (e) { case QBluetoothSocket::HostNotFoundError: @@ -790,7 +787,7 @@ void QLowEnergyControllerPrivate::l2cpErrorChanged(QBluetoothSocket::SocketError } -void QLowEnergyControllerPrivate::resetController() +void QLowEnergyControllerPrivateBluez::resetController() { openRequests.clear(); openPrepareWriteRequests.clear(); @@ -807,7 +804,7 @@ void QLowEnergyControllerPrivate::resetController() advertiser->stopAdvertising(); } -void QLowEnergyControllerPrivate::restartRequestTimer() +void QLowEnergyControllerPrivateBluez::restartRequestTimer() { if (!requestTimer) return; @@ -816,7 +813,7 @@ void QLowEnergyControllerPrivate::restartRequestTimer() requestTimer->start(gattRequestTimeout); } -void QLowEnergyControllerPrivate::l2cpReadyRead() +void QLowEnergyControllerPrivateBluez::l2cpReadyRead() { const QByteArray incomingPacket = l2cpSocket->readAll(); qCDebug(QT_BT_BLUEZ) << "Received size:" << incomingPacket.size() << "data:" @@ -914,7 +911,7 @@ void QLowEnergyControllerPrivate::l2cpReadyRead() * callback is called. The first pending request in the queue is the request * that triggered the encryption request. */ -void QLowEnergyControllerPrivate::encryptionChangedEvent( +void QLowEnergyControllerPrivateBluez::encryptionChangedEvent( const QBluetoothAddress &address, bool wasSuccess) { if (!encryptionChangePending) // somebody else caused change event @@ -963,7 +960,7 @@ void QLowEnergyControllerPrivate::encryptionChangedEvent( sendNextPendingRequest(); } -void QLowEnergyControllerPrivate::sendPacket(const QByteArray &packet) +void QLowEnergyControllerPrivateBluez::sendPacket(const QByteArray &packet) { qint64 result = l2cpSocket->write(packet.constData(), packet.size()); @@ -982,7 +979,7 @@ void QLowEnergyControllerPrivate::sendPacket(const QByteArray &packet) } -void QLowEnergyControllerPrivate::sendNextPendingRequest() +void QLowEnergyControllerPrivateBluez::sendNextPendingRequest() { if (openRequests.isEmpty() || requestPending || encryptionChangePending) return; @@ -1047,7 +1044,7 @@ QLowEnergyHandle parseReadByTypeIncludeDiscovery( return attributeHandle; } -void QLowEnergyControllerPrivate::processReply( +void QLowEnergyControllerPrivateBluez::processReply( const Request &request, const QByteArray &response) { Q_Q(QLowEnergyController); @@ -1585,12 +1582,12 @@ void QLowEnergyControllerPrivate::processReply( } } -void QLowEnergyControllerPrivate::discoverServices() +void QLowEnergyControllerPrivateBluez::discoverServices() { sendReadByGroupRequest(0x0001, 0xFFFF, GATT_PRIMARY_SERVICE); } -void QLowEnergyControllerPrivate::sendReadByGroupRequest( +void QLowEnergyControllerPrivateBluez::sendReadByGroupRequest( QLowEnergyHandle start, QLowEnergyHandle end, quint16 type) { //call for primary and secondary services @@ -1615,7 +1612,7 @@ void QLowEnergyControllerPrivate::sendReadByGroupRequest( sendNextPendingRequest(); } -void QLowEnergyControllerPrivate::discoverServiceDetails(const QBluetoothUuid &service) +void QLowEnergyControllerPrivateBluez::discoverServiceDetails(const QBluetoothUuid &service) { if (!serviceList.contains(service)) { qCWarning(QT_BT_BLUEZ) << "Discovery of unknown service" << service.toString() @@ -1628,7 +1625,7 @@ void QLowEnergyControllerPrivate::discoverServiceDetails(const QBluetoothUuid &s sendReadByTypeRequest(serviceData, serviceData->startHandle, GATT_INCLUDED_SERVICE); } -void QLowEnergyControllerPrivate::sendReadByTypeRequest( +void QLowEnergyControllerPrivateBluez::sendReadByTypeRequest( QSharedPointer<QLowEnergyServicePrivate> serviceData, QLowEnergyHandle nextHandle, quint16 attributeType) { @@ -1664,7 +1661,7 @@ void QLowEnergyControllerPrivate::sendReadByTypeRequest( \a readCharacteristics determines whether we intend to read a characteristic; otherwise we read a descriptor. */ -void QLowEnergyControllerPrivate::readServiceValues( +void QLowEnergyControllerPrivateBluez::readServiceValues( const QBluetoothUuid &serviceUuid, bool readCharacteristics) { quint8 packet[READ_REQUEST_HEADER_SIZE]; @@ -1758,7 +1755,7 @@ void QLowEnergyControllerPrivate::readServiceValues( open requests to finish the current value read up before starting the next read request. */ -void QLowEnergyControllerPrivate::readServiceValuesByOffset( +void QLowEnergyControllerPrivateBluez::readServiceValuesByOffset( uint handleData, quint16 offset, bool isLastValue) { const QLowEnergyHandle charHandle = (handleData & 0xffff); @@ -1797,7 +1794,7 @@ void QLowEnergyControllerPrivate::readServiceValuesByOffset( openRequests.prepend(request); } -void QLowEnergyControllerPrivate::discoverServiceDescriptors( +void QLowEnergyControllerPrivateBluez::discoverServiceDescriptors( const QBluetoothUuid &serviceUuid) { qCDebug(QT_BT_BLUEZ) << "Discovering descriptor values for" @@ -1817,7 +1814,7 @@ void QLowEnergyControllerPrivate::discoverServiceDescriptors( discoverNextDescriptor(service, keys, keys[0]); } -void QLowEnergyControllerPrivate::processUnsolicitedReply(const QByteArray &payload) +void QLowEnergyControllerPrivateBluez::processUnsolicitedReply(const QByteArray &payload) { const char *data = payload.constData(); bool isNotification = (data[0] == ATT_OP_HANDLE_VAL_NOTIFICATION); @@ -1841,7 +1838,7 @@ void QLowEnergyControllerPrivate::processUnsolicitedReply(const QByteArray &payl } } -void QLowEnergyControllerPrivate::exchangeMTU() +void QLowEnergyControllerPrivateBluez::exchangeMTU() { qCDebug(QT_BT_BLUEZ) << "Exchanging MTU"; @@ -1860,7 +1857,7 @@ void QLowEnergyControllerPrivate::exchangeMTU() sendNextPendingRequest(); } -int QLowEnergyControllerPrivate::securityLevel() const +int QLowEnergyControllerPrivateBluez::securityLevel() const { int socket = l2cpSocket->socketDescriptor(); if (socket < 0) { @@ -1899,7 +1896,7 @@ int QLowEnergyControllerPrivate::securityLevel() const return -1; } -bool QLowEnergyControllerPrivate::setSecurityLevel(int level) +bool QLowEnergyControllerPrivateBluez::setSecurityLevel(int level) { if (level > BT_SECURITY_HIGH || level < BT_SECURITY_LOW) return false; @@ -1946,7 +1943,7 @@ bool QLowEnergyControllerPrivate::setSecurityLevel(int level) return false; } -void QLowEnergyControllerPrivate::discoverNextDescriptor( +void QLowEnergyControllerPrivateBluez::discoverNextDescriptor( QSharedPointer<QLowEnergyServicePrivate> serviceData, const QList<QLowEnergyHandle> pendingCharHandles, const QLowEnergyHandle startingHandle) @@ -1983,7 +1980,7 @@ void QLowEnergyControllerPrivate::discoverNextDescriptor( sendNextPendingRequest(); } -void QLowEnergyControllerPrivate::sendNextPrepareWriteRequest( +void QLowEnergyControllerPrivateBluez::sendNextPrepareWriteRequest( const QLowEnergyHandle handle, const QByteArray &newValue, quint16 offset) { @@ -2038,7 +2035,7 @@ void QLowEnergyControllerPrivate::sendNextPrepareWriteRequest( Otherwise this function sends an execute request for all pending prepare write requests. */ -void QLowEnergyControllerPrivate::sendExecuteWriteRequest( +void QLowEnergyControllerPrivateBluez::sendExecuteWriteRequest( const QLowEnergyHandle attrHandle, const QByteArray &newValue, bool isCancelation) { @@ -2070,7 +2067,7 @@ void QLowEnergyControllerPrivate::sendExecuteWriteRequest( TODO Reliable/prepare write across multiple characteristics is not supported */ -void QLowEnergyControllerPrivate::writeCharacteristic( +void QLowEnergyControllerPrivateBluez::writeCharacteristic( const QSharedPointer<QLowEnergyServicePrivate> service, const QLowEnergyHandle charHandle, const QByteArray &newValue, @@ -2088,7 +2085,7 @@ void QLowEnergyControllerPrivate::writeCharacteristic( writeCharacteristicForCentral(service, charHandle, charData.valueHandle, newValue, mode); } -void QLowEnergyControllerPrivate::writeDescriptor( +void QLowEnergyControllerPrivateBluez::writeDescriptor( const QSharedPointer<QLowEnergyServicePrivate> service, const QLowEnergyHandle charHandle, const QLowEnergyHandle descriptorHandle, @@ -2107,7 +2104,7 @@ void QLowEnergyControllerPrivate::writeDescriptor( Reads the value of one specific characteristic. */ -void QLowEnergyControllerPrivate::readCharacteristic( +void QLowEnergyControllerPrivateBluez::readCharacteristic( const QSharedPointer<QLowEnergyServicePrivate> service, const QLowEnergyHandle charHandle) { @@ -2145,7 +2142,7 @@ void QLowEnergyControllerPrivate::readCharacteristic( sendNextPendingRequest(); } -void QLowEnergyControllerPrivate::readDescriptor( +void QLowEnergyControllerPrivateBluez::readDescriptor( const QSharedPointer<QLowEnergyServicePrivate> service, const QLowEnergyHandle charHandle, const QLowEnergyHandle descriptorHandle) @@ -2184,7 +2181,7 @@ void QLowEnergyControllerPrivate::readDescriptor( * Returns true if the encryption change was successfully requested. * The request is triggered if we got a related ATT error. */ -bool QLowEnergyControllerPrivate::increaseEncryptLevelfRequired(quint8 errorCode) +bool QLowEnergyControllerPrivateBluez::increaseEncryptLevelfRequired(quint8 errorCode) { if (securityLevelValue == BT_SECURITY_HIGH) return false; @@ -2212,14 +2209,14 @@ bool QLowEnergyControllerPrivate::increaseEncryptLevelfRequired(quint8 errorCode return false; } -void QLowEnergyControllerPrivate::handleAdvertisingError() +void QLowEnergyControllerPrivateBluez::handleAdvertisingError() { qCWarning(QT_BT_BLUEZ) << "received advertising error"; setError(QLowEnergyController::AdvertisingError); setState(QLowEnergyController::UnconnectedState); } -bool QLowEnergyControllerPrivate::checkPacketSize(const QByteArray &packet, int minSize, +bool QLowEnergyControllerPrivateBluez::checkPacketSize(const QByteArray &packet, int minSize, int maxSize) { if (maxSize == -1) @@ -2232,7 +2229,7 @@ bool QLowEnergyControllerPrivate::checkPacketSize(const QByteArray &packet, int return false; } -bool QLowEnergyControllerPrivate::checkHandle(const QByteArray &packet, QLowEnergyHandle handle) +bool QLowEnergyControllerPrivateBluez::checkHandle(const QByteArray &packet, QLowEnergyHandle handle) { if (handle != 0 && handle <= lastLocalHandle) return true; @@ -2240,7 +2237,7 @@ bool QLowEnergyControllerPrivate::checkHandle(const QByteArray &packet, QLowEner return false; } -bool QLowEnergyControllerPrivate::checkHandlePair(quint8 request, QLowEnergyHandle startingHandle, +bool QLowEnergyControllerPrivateBluez::checkHandlePair(quint8 request, QLowEnergyHandle startingHandle, QLowEnergyHandle endingHandle) { if (startingHandle == 0 || startingHandle > endingHandle) { @@ -2251,7 +2248,7 @@ bool QLowEnergyControllerPrivate::checkHandlePair(quint8 request, QLowEnergyHand return true; } -void QLowEnergyControllerPrivate::handleExchangeMtuRequest(const QByteArray &packet) +void QLowEnergyControllerPrivateBluez::handleExchangeMtuRequest(const QByteArray &packet) { // Spec v4.2, Vol 3, Part F, 3.4.2 @@ -2278,7 +2275,7 @@ void QLowEnergyControllerPrivate::handleExchangeMtuRequest(const QByteArray &pac qCDebug(QT_BT_BLUEZ) << "Sending server RX MTU" << ATT_MAX_LE_MTU; } -void QLowEnergyControllerPrivate::handleFindInformationRequest(const QByteArray &packet) +void QLowEnergyControllerPrivateBluez::handleFindInformationRequest(const QByteArray &packet) { // Spec v4.2, Vol 3, Part F, 3.4.3.1-2 @@ -2311,7 +2308,7 @@ void QLowEnergyControllerPrivate::handleFindInformationRequest(const QByteArray } -void QLowEnergyControllerPrivate::handleFindByTypeValueRequest(const QByteArray &packet) +void QLowEnergyControllerPrivateBluez::handleFindByTypeValueRequest(const QByteArray &packet) { // Spec v4.2, Vol 3, Part F, 3.4.3.3-4 @@ -2346,7 +2343,7 @@ void QLowEnergyControllerPrivate::handleFindByTypeValueRequest(const QByteArray sendListResponse(responsePrefix, elemSize, results, elemWriter); } -void QLowEnergyControllerPrivate::handleReadByTypeRequest(const QByteArray &packet) +void QLowEnergyControllerPrivateBluez::handleReadByTypeRequest(const QByteArray &packet) { // Spec v4.2, Vol 3, Part F, 3.4.4.1-2 @@ -2399,7 +2396,7 @@ void QLowEnergyControllerPrivate::handleReadByTypeRequest(const QByteArray &pack sendListResponse(responsePrefix, elementSize, results, elemWriter); } -void QLowEnergyControllerPrivate::handleReadRequest(const QByteArray &packet) +void QLowEnergyControllerPrivateBluez::handleReadRequest(const QByteArray &packet) { // Spec v4.2, Vol 3, Part F, 3.4.4.3-4 @@ -2426,7 +2423,7 @@ void QLowEnergyControllerPrivate::handleReadRequest(const QByteArray &packet) sendPacket(response); } -void QLowEnergyControllerPrivate::handleReadBlobRequest(const QByteArray &packet) +void QLowEnergyControllerPrivateBluez::handleReadBlobRequest(const QByteArray &packet) { // Spec v4.2, Vol 3, Part F, 3.4.4.5-6 @@ -2465,7 +2462,7 @@ void QLowEnergyControllerPrivate::handleReadBlobRequest(const QByteArray &packet sendPacket(response); } -void QLowEnergyControllerPrivate::handleReadMultipleRequest(const QByteArray &packet) +void QLowEnergyControllerPrivateBluez::handleReadMultipleRequest(const QByteArray &packet) { // Spec v4.2, Vol 3, Part F, 3.4.4.7-8 @@ -2501,7 +2498,7 @@ void QLowEnergyControllerPrivate::handleReadMultipleRequest(const QByteArray &pa sendPacket(response); } -void QLowEnergyControllerPrivate::handleReadByGroupTypeRequest(const QByteArray &packet) +void QLowEnergyControllerPrivateBluez::handleReadByGroupTypeRequest(const QByteArray &packet) { // Spec v4.2, Vol 3, Part F, 3.4.4.9-10 @@ -2560,7 +2557,7 @@ void QLowEnergyControllerPrivate::handleReadByGroupTypeRequest(const QByteArray sendListResponse(responsePrefix, elementSize, results, elemWriter); } -void QLowEnergyControllerPrivate::updateLocalAttributeValue( +void QLowEnergyControllerPrivateBluez::updateLocalAttributeValue( QLowEnergyHandle handle, const QByteArray &value, QLowEnergyCharacteristic &characteristic, @@ -2594,7 +2591,7 @@ void QLowEnergyControllerPrivate::updateLocalAttributeValue( static bool isNotificationEnabled(quint16 clientConfigValue) { return clientConfigValue & 0x1; } static bool isIndicationEnabled(quint16 clientConfigValue) { return clientConfigValue & 0x2; } -void QLowEnergyControllerPrivate::writeCharacteristicForPeripheral( +void QLowEnergyControllerPrivateBluez::writeCharacteristicForPeripheral( QLowEnergyServicePrivate::CharData &charData, const QByteArray &newValue) { @@ -2651,7 +2648,7 @@ void QLowEnergyControllerPrivate::writeCharacteristicForPeripheral( } } -void QLowEnergyControllerPrivate::writeCharacteristicForCentral(const QSharedPointer<QLowEnergyServicePrivate> &service, +void QLowEnergyControllerPrivateBluez::writeCharacteristicForCentral(const QSharedPointer<QLowEnergyServicePrivate> &service, QLowEnergyHandle charHandle, QLowEnergyHandle valueHandle, const QByteArray &newValue, @@ -2725,7 +2722,7 @@ void QLowEnergyControllerPrivate::writeCharacteristicForCentral(const QSharedPoi sendNextPendingRequest(); } -void QLowEnergyControllerPrivate::writeDescriptorForPeripheral( +void QLowEnergyControllerPrivateBluez::writeDescriptorForPeripheral( const QSharedPointer<QLowEnergyServicePrivate> &service, const QLowEnergyHandle charHandle, const QLowEnergyHandle descriptorHandle, @@ -2742,7 +2739,7 @@ void QLowEnergyControllerPrivate::writeDescriptorForPeripheral( service->characteristicList[charHandle].descriptorList[descriptorHandle].value = newValue; } -void QLowEnergyControllerPrivate::writeDescriptorForCentral( +void QLowEnergyControllerPrivateBluez::writeDescriptorForCentral( const QLowEnergyHandle charHandle, const QLowEnergyHandle descriptorHandle, const QByteArray &newValue) @@ -2775,7 +2772,7 @@ void QLowEnergyControllerPrivate::writeDescriptorForCentral( sendNextPendingRequest(); } -void QLowEnergyControllerPrivate::handleWriteRequestOrCommand(const QByteArray &packet) +void QLowEnergyControllerPrivateBluez::handleWriteRequestOrCommand(const QByteArray &packet) { // Spec v4.2, Vol 3, Part F, 3.4.5.1-3 @@ -2869,7 +2866,7 @@ void QLowEnergyControllerPrivate::handleWriteRequestOrCommand(const QByteArray & } } -void QLowEnergyControllerPrivate::handlePrepareWriteRequest(const QByteArray &packet) +void QLowEnergyControllerPrivateBluez::handlePrepareWriteRequest(const QByteArray &packet) { // Spec v4.2, Vol 3, Part F, 3.4.6.1 @@ -2900,7 +2897,7 @@ void QLowEnergyControllerPrivate::handlePrepareWriteRequest(const QByteArray &pa sendPacket(response); } -void QLowEnergyControllerPrivate::handleExecuteWriteRequest(const QByteArray &packet) +void QLowEnergyControllerPrivateBluez::handleExecuteWriteRequest(const QByteArray &packet) { // Spec v4.2, Vol 3, Part F, 3.4.6.3 @@ -2948,7 +2945,7 @@ void QLowEnergyControllerPrivate::handleExecuteWriteRequest(const QByteArray &pa emit descriptor.d_ptr->descriptorWritten(descriptor, descriptor.value()); } -void QLowEnergyControllerPrivate::sendErrorResponse(quint8 request, quint16 handle, quint8 code) +void QLowEnergyControllerPrivateBluez::sendErrorResponse(quint8 request, quint16 handle, quint8 code) { // An ATT command never receives an error response. if (request == ATT_OP_WRITE_COMMAND || request == ATT_OP_SIGNED_WRITE_COMMAND) @@ -2964,7 +2961,7 @@ void QLowEnergyControllerPrivate::sendErrorResponse(quint8 request, quint16 hand sendPacket(packet); } -void QLowEnergyControllerPrivate::sendListResponse(const QByteArray &packetStart, int elemSize, +void QLowEnergyControllerPrivateBluez::sendListResponse(const QByteArray &packetStart, int elemSize, const QVector<Attribute> &attributes, const ElemWriter &elemWriter) { const int offset = packetStart.count(); @@ -2980,19 +2977,19 @@ void QLowEnergyControllerPrivate::sendListResponse(const QByteArray &packetStart sendPacket(response); } -void QLowEnergyControllerPrivate::sendNotification(QLowEnergyHandle handle) +void QLowEnergyControllerPrivateBluez::sendNotification(QLowEnergyHandle handle) { sendNotificationOrIndication(ATT_OP_HANDLE_VAL_NOTIFICATION, handle); } -void QLowEnergyControllerPrivate::sendIndication(QLowEnergyHandle handle) +void QLowEnergyControllerPrivateBluez::sendIndication(QLowEnergyHandle handle) { Q_ASSERT(!indicationInFlight); indicationInFlight = true; sendNotificationOrIndication(ATT_OP_HANDLE_VAL_INDICATION, handle); } -void QLowEnergyControllerPrivate::sendNotificationOrIndication( +void QLowEnergyControllerPrivateBluez::sendNotificationOrIndication( quint8 opCode, QLowEnergyHandle handle) { @@ -3008,13 +3005,13 @@ void QLowEnergyControllerPrivate::sendNotificationOrIndication( sendPacket(packet); } -void QLowEnergyControllerPrivate::sendNextIndication() +void QLowEnergyControllerPrivateBluez::sendNextIndication() { if (!scheduledIndications.isEmpty()) sendIndication(scheduledIndications.takeFirst()); } -void QLowEnergyControllerPrivate::handleConnectionRequest() +void QLowEnergyControllerPrivateBluez::handleConnectionRequest() { if (state != QLowEnergyController::AdvertisingState) { qCWarning(QT_BT_BLUEZ) << "Incoming connection request in unexpected state" << state; @@ -3040,10 +3037,10 @@ void QLowEnergyControllerPrivate::handleConnectionRequest() closeServerSocket(); l2cpSocket = new QBluetoothSocket(QBluetoothServiceInfo::L2capProtocol, this); connect(l2cpSocket, &QBluetoothSocket::disconnected, - this, &QLowEnergyControllerPrivate::l2cpDisconnected); + this, &QLowEnergyControllerPrivateBluez::l2cpDisconnected); connect(l2cpSocket, static_cast<void (QBluetoothSocket::*)(QBluetoothSocket::SocketError)> - (&QBluetoothSocket::error), this, &QLowEnergyControllerPrivate::l2cpErrorChanged); - connect(l2cpSocket, &QIODevice::readyRead, this, &QLowEnergyControllerPrivate::l2cpReadyRead); + (&QBluetoothSocket::error), this, &QLowEnergyControllerPrivateBluez::l2cpErrorChanged); + connect(l2cpSocket, &QIODevice::readyRead, this, &QLowEnergyControllerPrivateBluez::l2cpReadyRead); l2cpSocket->d_ptr->lowEnergySocketType = addressType == QLowEnergyController::PublicAddress ? BDADDR_LE_PUBLIC : BDADDR_LE_RANDOM; l2cpSocket->setSocketDescriptor(clientSocket, QBluetoothServiceInfo::L2capProtocol, @@ -3056,7 +3053,7 @@ void QLowEnergyControllerPrivate::handleConnectionRequest() emit q->connected(); } -void QLowEnergyControllerPrivate::closeServerSocket() +void QLowEnergyControllerPrivateBluez::closeServerSocket() { if (!serverSocketNotifier) return; @@ -3066,7 +3063,7 @@ void QLowEnergyControllerPrivate::closeServerSocket() serverSocketNotifier = nullptr; } -bool QLowEnergyControllerPrivate::isBonded() const +bool QLowEnergyControllerPrivateBluez::isBonded() const { // Pairing does not necessarily imply bonding, but we don't know whether the // bonding flag was set in the original pairing request. @@ -3074,7 +3071,7 @@ bool QLowEnergyControllerPrivate::isBonded() const != QBluetoothLocalDevice::Unpaired; } -QVector<QLowEnergyControllerPrivate::TempClientConfigurationData> QLowEnergyControllerPrivate::gatherClientConfigData() +QVector<QLowEnergyControllerPrivateBluez::TempClientConfigurationData> QLowEnergyControllerPrivateBluez::gatherClientConfigData() { QVector<TempClientConfigurationData> data; foreach (const auto &service, localServices) { @@ -3095,7 +3092,7 @@ QVector<QLowEnergyControllerPrivate::TempClientConfigurationData> QLowEnergyCont return data; } -void QLowEnergyControllerPrivate::storeClientConfigurations() +void QLowEnergyControllerPrivateBluez::storeClientConfigurations() { if (!isBonded()) { clientConfigData.remove(remoteDevice.toUInt64()); @@ -3114,7 +3111,7 @@ void QLowEnergyControllerPrivate::storeClientConfigurations() clientConfigData.insert(remoteDevice.toUInt64(), clientConfigs); } -void QLowEnergyControllerPrivate::restoreClientConfigurations() +void QLowEnergyControllerPrivateBluez::restoreClientConfigurations() { const QVector<TempClientConfigurationData> &tempConfigList = gatherClientConfigData(); const QVector<ClientConfigurationData> &restoredClientConfigs = isBonded() @@ -3148,7 +3145,7 @@ void QLowEnergyControllerPrivate::restoreClientConfigurations() sendNextIndication(); } -void QLowEnergyControllerPrivate::loadSigningDataIfNecessary(SigningKeyType keyType) +void QLowEnergyControllerPrivateBluez::loadSigningDataIfNecessary(SigningKeyType keyType) { const auto signingDataIt = signingData.constFind(remoteDevice.toUInt64()); if (signingDataIt != signingData.constEnd()) @@ -3180,7 +3177,7 @@ void QLowEnergyControllerPrivate::loadSigningDataIfNecessary(SigningKeyType keyT signingData.insert(remoteDevice.toUInt64(), SigningData(csrk, counter - 1)); } -void QLowEnergyControllerPrivate::storeSignCounter(SigningKeyType keyType) const +void QLowEnergyControllerPrivateBluez::storeSignCounter(SigningKeyType keyType) const { const auto signingDataIt = signingData.constFind(remoteDevice.toUInt64()); if (signingDataIt == signingData.constEnd()) @@ -3201,12 +3198,12 @@ void QLowEnergyControllerPrivate::storeSignCounter(SigningKeyType keyType) const settings.setValue(counterKey, counterValue); } -QString QLowEnergyControllerPrivate::signingKeySettingsGroup(SigningKeyType keyType) const +QString QLowEnergyControllerPrivateBluez::signingKeySettingsGroup(SigningKeyType keyType) const { return QLatin1String(keyType == LocalSigningKey ? "LocalSignatureKey" : "RemoteSignatureKey"); } -QString QLowEnergyControllerPrivate::keySettingsFilePath() const +QString QLowEnergyControllerPrivateBluez::keySettingsFilePath() const { return QString::fromLatin1("/var/lib/bluetooth/%1/%2/info") .arg(localAdapter.toString(), remoteDevice.toString()); @@ -3228,7 +3225,7 @@ static QByteArray uuidToByteArray(const QBluetoothUuid &uuid) return ba; } -void QLowEnergyControllerPrivate::addToGenericAttributeList(const QLowEnergyServiceData &service, +void QLowEnergyControllerPrivateBluez::addToGenericAttributeList(const QLowEnergyServiceData &service, QLowEnergyHandle startHandle) { // Construct generic attribute data for the service with handles as keys. @@ -3338,7 +3335,7 @@ void QLowEnergyControllerPrivate::addToGenericAttributeList(const QLowEnergyServ localAttributes[serviceAttribute.handle] = serviceAttribute; } -void QLowEnergyControllerPrivate::ensureUniformAttributes(QVector<Attribute> &attributes, +void QLowEnergyControllerPrivateBluez::ensureUniformAttributes(QVector<Attribute> &attributes, const std::function<int (const Attribute &)> &getSize) { if (attributes.isEmpty()) @@ -3351,19 +3348,19 @@ void QLowEnergyControllerPrivate::ensureUniformAttributes(QVector<Attribute> &at } -void QLowEnergyControllerPrivate::ensureUniformUuidSizes(QVector<Attribute> &attributes) +void QLowEnergyControllerPrivateBluez::ensureUniformUuidSizes(QVector<Attribute> &attributes) { ensureUniformAttributes(attributes, [](const Attribute &attr) { return getUuidSize(attr.type); }); } -void QLowEnergyControllerPrivate::ensureUniformValueSizes(QVector<Attribute> &attributes) +void QLowEnergyControllerPrivateBluez::ensureUniformValueSizes(QVector<Attribute> &attributes) { ensureUniformAttributes(attributes, [](const Attribute &attr) { return attr.value.count(); }); } -QVector<QLowEnergyControllerPrivate::Attribute> QLowEnergyControllerPrivate::getAttributes(QLowEnergyHandle startHandle, +QVector<QLowEnergyControllerPrivateBluez::Attribute> QLowEnergyControllerPrivateBluez::getAttributes(QLowEnergyHandle startHandle, QLowEnergyHandle endHandle, const AttributePredicate &attributePredicate) { QVector<Attribute> results; @@ -3382,7 +3379,7 @@ QVector<QLowEnergyControllerPrivate::Attribute> QLowEnergyControllerPrivate::get return results; } -int QLowEnergyControllerPrivate::checkPermissions(const Attribute &attr, +int QLowEnergyControllerPrivateBluez::checkPermissions(const Attribute &attr, QLowEnergyCharacteristic::PropertyType type) { const bool isReadAccess = type == QLowEnergyCharacteristic::Read; @@ -3416,12 +3413,12 @@ int QLowEnergyControllerPrivate::checkPermissions(const Attribute &attr, return 0; } -int QLowEnergyControllerPrivate::checkReadPermissions(const Attribute &attr) +int QLowEnergyControllerPrivateBluez::checkReadPermissions(const Attribute &attr) { return checkPermissions(attr, QLowEnergyCharacteristic::Read); } -int QLowEnergyControllerPrivate::checkReadPermissions(QVector<Attribute> &attributes) +int QLowEnergyControllerPrivateBluez::checkReadPermissions(QVector<Attribute> &attributes) { if (attributes.isEmpty()) return 0; @@ -3441,7 +3438,7 @@ int QLowEnergyControllerPrivate::checkReadPermissions(QVector<Attribute> &attrib return 0; } -bool QLowEnergyControllerPrivate::verifyMac(const QByteArray &message, const quint128 &csrk, +bool QLowEnergyControllerPrivateBluez::verifyMac(const QByteArray &message, const quint128 &csrk, quint32 signCounter, quint64 expectedMac) { if (!cmacCalculator) diff --git a/src/bluetooth/qlowenergycontroller_bluez_p.h b/src/bluetooth/qlowenergycontroller_bluez_p.h new file mode 100644 index 00000000..55a8a482 --- /dev/null +++ b/src/bluetooth/qlowenergycontroller_bluez_p.h @@ -0,0 +1,357 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtBluetooth module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLOWENERGYCONTROLLERBLUEZ_P_H +#define QLOWENERGYCONTROLLERBLUEZ_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <qglobal.h> +#include <QtCore/QQueue> +#include <QtCore/QVector> +#include <QtBluetooth/qbluetooth.h> +#include <QtBluetooth/qlowenergycharacteristic.h> +#include "qlowenergycontroller.h" +#include "qlowenergycontrollerbase_p.h" + +#include <QtBluetooth/QBluetoothSocket> +#include <functional> + +QT_BEGIN_NAMESPACE + +class QLowEnergyServiceData; +class QTimer; + +class HciManager; +class LeCmacCalculator; +class QSocketNotifier; +class RemoteDeviceManager; + +extern void registerQLowEnergyControllerMetaType(); + +class QLeAdvertiser; + +class QLowEnergyControllerPrivateBluez : public QLowEnergyControllerPrivate +{ + Q_OBJECT +public: + QLowEnergyControllerPrivateBluez(); + ~QLowEnergyControllerPrivateBluez(); + + void init() override; + + void connectToDevice() override; + void disconnectFromDevice() override; + + void discoverServices() override; + void discoverServiceDetails(const QBluetoothUuid &service) override; + + void startAdvertising(const QLowEnergyAdvertisingParameters ¶ms, + const QLowEnergyAdvertisingData &advertisingData, + const QLowEnergyAdvertisingData &scanResponseData) override; + void stopAdvertising() override; + + void requestConnectionUpdate(const QLowEnergyConnectionParameters ¶ms) override; + + // read data + void readCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service, + const QLowEnergyHandle charHandle) override; + void readDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle) override; + + // write data + void writeCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service, + const QLowEnergyHandle charHandle, + const QByteArray &newValue, QLowEnergyService::WriteMode mode) override; + void writeDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle, + const QByteArray &newValue) override; + + void addToGenericAttributeList(const QLowEnergyServiceData &service, + QLowEnergyHandle startHandle) override; + + struct Attribute { + Attribute() : handle(0) {} + + QLowEnergyHandle handle; + QLowEnergyHandle groupEndHandle; + QLowEnergyCharacteristic::PropertyTypes properties; + QBluetooth::AttAccessConstraints readConstraints; + QBluetooth::AttAccessConstraints writeConstraints; + QBluetoothUuid type; + QByteArray value; + int minLength; + int maxLength; + }; + QVector<Attribute> localAttributes; + +private: + quint16 connectionHandle = 0; + QBluetoothSocket *l2cpSocket; + struct Request { + quint8 command; + QByteArray payload; + // TODO reference below is ugly but until we know all commands and their + // requirements this is WIP + QVariant reference; + QVariant reference2; + }; + QQueue<Request> openRequests; + + struct WriteRequest { + WriteRequest() {} + WriteRequest(quint16 h, quint16 o, const QByteArray &v) + : handle(h), valueOffset(o), value(v) {} + quint16 handle; + quint16 valueOffset; + QByteArray value; + }; + QVector<WriteRequest> openPrepareWriteRequests; + + // Invariant: !scheduledIndications.isEmpty => indicationInFlight == true + QVector<QLowEnergyHandle> scheduledIndications; + bool indicationInFlight = false; + + struct TempClientConfigurationData { + TempClientConfigurationData(QLowEnergyServicePrivate::DescData *dd = nullptr, + QLowEnergyHandle chHndl = 0, QLowEnergyHandle coHndl = 0) + : descData(dd), charValueHandle(chHndl), configHandle(coHndl) {} + + QLowEnergyServicePrivate::DescData *descData; + QLowEnergyHandle charValueHandle; + QLowEnergyHandle configHandle; + }; + + struct ClientConfigurationData { + ClientConfigurationData(QLowEnergyHandle chHndl = 0, QLowEnergyHandle coHndl = 0, + quint16 val = 0) + : charValueHandle(chHndl), configHandle(coHndl), configValue(val) {} + + QLowEnergyHandle charValueHandle; + QLowEnergyHandle configHandle; + quint16 configValue; + bool charValueWasUpdated = false; + }; + QHash<quint64, QVector<ClientConfigurationData>> clientConfigData; + + struct SigningData { + SigningData() = default; + SigningData(const quint128 &csrk, quint32 signCounter = quint32(-1)) + : key(csrk), counter(signCounter) {} + + quint128 key; + quint32 counter = quint32(-1); + }; + QHash<quint64, SigningData> signingData; + LeCmacCalculator *cmacCalculator = nullptr; + + bool requestPending; + quint16 mtuSize; + int securityLevelValue; + bool encryptionChangePending; + bool receivedMtuExchangeRequest = false; + + HciManager *hciManager; + QLeAdvertiser *advertiser; + QSocketNotifier *serverSocketNotifier; + QTimer *requestTimer = nullptr; + RemoteDeviceManager* device1Manager = nullptr; + + /* + Defines the maximum number of milliseconds the implementation will + wait for requests that require a response. + + This addresses the problem that some non-conformant BTLE devices + do not implement the request/response system properly. In such cases + the queue system would hang forever. + + Once timeout has been triggered we gracefully continue with the next request. + Depending on the type of the timed out ATT command we either ignore it + or artifically trigger an error response to ensure the API gives the + appropriate response. Potentially this can cause problems when the + response for the dropped requests arrives very late. That's why a big warning + is printed about the compromised state when a timeout is triggered. + */ + int gattRequestTimeout = 20000; + + void handleConnectionRequest(); + void closeServerSocket(); + + bool isBonded() const; + QVector<TempClientConfigurationData> gatherClientConfigData(); + void storeClientConfigurations(); + void restoreClientConfigurations(); + + enum SigningKeyType { LocalSigningKey, RemoteSigningKey }; + void loadSigningDataIfNecessary(SigningKeyType keyType); + void storeSignCounter(SigningKeyType keyType) const; + QString signingKeySettingsGroup(SigningKeyType keyType) const; + QString keySettingsFilePath() const; + + void sendPacket(const QByteArray &packet); + void sendNextPendingRequest(); + void processReply(const Request &request, const QByteArray &reply); + + void sendReadByGroupRequest(QLowEnergyHandle start, QLowEnergyHandle end, + quint16 type); + void sendReadByTypeRequest(QSharedPointer<QLowEnergyServicePrivate> serviceData, + QLowEnergyHandle nextHandle, quint16 attributeType); + void sendReadValueRequest(QLowEnergyHandle attributeHandle, bool isDescriptor); + void readServiceValues(const QBluetoothUuid &service, + bool readCharacteristics); + void readServiceValuesByOffset(uint handleData, quint16 offset, + bool isLastValue); + + void discoverServiceDescriptors(const QBluetoothUuid &serviceUuid); + void discoverNextDescriptor(QSharedPointer<QLowEnergyServicePrivate> serviceData, + const QList<QLowEnergyHandle> pendingCharHandles, + QLowEnergyHandle startingHandle); + void processUnsolicitedReply(const QByteArray &msg); + void exchangeMTU(); + bool setSecurityLevel(int level); + int securityLevel() const; + void sendExecuteWriteRequest(const QLowEnergyHandle attrHandle, + const QByteArray &newValue, + bool isCancelation); + void sendNextPrepareWriteRequest(const QLowEnergyHandle handle, + const QByteArray &newValue, quint16 offset); + bool increaseEncryptLevelfRequired(quint8 errorCode); + + void resetController(); + + void handleAdvertisingError(); + + bool checkPacketSize(const QByteArray &packet, int minSize, int maxSize = -1); + bool checkHandle(const QByteArray &packet, QLowEnergyHandle handle); + bool checkHandlePair(quint8 request, QLowEnergyHandle startingHandle, + QLowEnergyHandle endingHandle); + + void handleExchangeMtuRequest(const QByteArray &packet); + void handleFindInformationRequest(const QByteArray &packet); + void handleFindByTypeValueRequest(const QByteArray &packet); + void handleReadByTypeRequest(const QByteArray &packet); + void handleReadRequest(const QByteArray &packet); + void handleReadBlobRequest(const QByteArray &packet); + void handleReadMultipleRequest(const QByteArray &packet); + void handleReadByGroupTypeRequest(const QByteArray &packet); + void handleWriteRequestOrCommand(const QByteArray &packet); + void handlePrepareWriteRequest(const QByteArray &packet); + void handleExecuteWriteRequest(const QByteArray &packet); + + void sendErrorResponse(quint8 request, quint16 handle, quint8 code); + + using ElemWriter = std::function<void(const Attribute &, char *&)>; + void sendListResponse(const QByteArray &packetStart, int elemSize, + const QVector<Attribute> &attributes, const ElemWriter &elemWriter); + + void sendNotification(QLowEnergyHandle handle); + void sendIndication(QLowEnergyHandle handle); + void sendNotificationOrIndication(quint8 opCode, QLowEnergyHandle handle); + void sendNextIndication(); + + void ensureUniformAttributes(QVector<Attribute> &attributes, const std::function<int(const Attribute &)> &getSize); + void ensureUniformUuidSizes(QVector<Attribute> &attributes); + void ensureUniformValueSizes(QVector<Attribute> &attributes); + + using AttributePredicate = std::function<bool(const Attribute &)>; + QVector<Attribute> getAttributes(QLowEnergyHandle startHandle, QLowEnergyHandle endHandle, + const AttributePredicate &attributePredicate = [](const Attribute &) { return true; }); + + int checkPermissions(const Attribute &attr, QLowEnergyCharacteristic::PropertyType type); + int checkReadPermissions(const Attribute &attr); + int checkReadPermissions(QVector<Attribute> &attributes); + + bool verifyMac(const QByteArray &message, const quint128 &csrk, quint32 signCounter, + quint64 expectedMac); + + void updateLocalAttributeValue( + QLowEnergyHandle handle, + const QByteArray &value, + QLowEnergyCharacteristic &characteristic, + QLowEnergyDescriptor &descriptor); + + void writeCharacteristicForPeripheral( + QLowEnergyServicePrivate::CharData &charData, + const QByteArray &newValue); + void writeCharacteristicForCentral(const QSharedPointer<QLowEnergyServicePrivate> &service, + QLowEnergyHandle charHandle, + QLowEnergyHandle valueHandle, + const QByteArray &newValue, + QLowEnergyService::WriteMode mode); + + void writeDescriptorForPeripheral( + const QSharedPointer<QLowEnergyServicePrivate> &service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle, + const QByteArray &newValue); + void writeDescriptorForCentral( + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle, + const QByteArray &newValue); + + void restartRequestTimer(); + void establishL2cpClientSocket(); + void createServicesForCentralIfRequired(); + +private slots: + void l2cpConnected(); + void l2cpDisconnected(); + void l2cpErrorChanged(QBluetoothSocket::SocketError); + void l2cpReadyRead(); + void encryptionChangedEvent(const QBluetoothAddress&, bool); + void handleGattRequestTimeout(); + void activeConnectionTerminationDone(); +}; + +Q_DECLARE_TYPEINFO(QLowEnergyControllerPrivateBluez::Attribute, Q_MOVABLE_TYPE); + +QT_END_NAMESPACE + +#endif //QLOWENERGYCONTROLLERBLUEZ_P_H diff --git a/src/bluetooth/qlowenergycontroller_bluezdbus.cpp b/src/bluetooth/qlowenergycontroller_bluezdbus.cpp new file mode 100644 index 00000000..e9087642 --- /dev/null +++ b/src/bluetooth/qlowenergycontroller_bluezdbus.cpp @@ -0,0 +1,1067 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtBluetooth module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qlowenergycontroller_bluezdbus_p.h" +#include "bluez/adapter1_bluez5_p.h" +#include "bluez/bluez5_helper_p.h" +#include "bluez/device1_bluez5_p.h" +#include "bluez/gattservice1_p.h" + +#include "bluez/gattchar1_p.h" +#include "bluez/gattdesc1_p.h" +#include "bluez/objectmanager_p.h" +#include "bluez/properties_p.h" + + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ) + +QLowEnergyControllerPrivateBluezDBus::QLowEnergyControllerPrivateBluezDBus() + : QLowEnergyControllerPrivate() +{ +} + +QLowEnergyControllerPrivateBluezDBus::~QLowEnergyControllerPrivateBluezDBus() +{ +} + +void QLowEnergyControllerPrivateBluezDBus::init() +{ +} + +void QLowEnergyControllerPrivateBluezDBus::devicePropertiesChanged( + const QString &interface, const QVariantMap &changedProperties, + const QStringList &/*removedProperties*/) +{ + if (interface == QStringLiteral("org.bluez.Device1")) { + qCDebug(QT_BT_BLUEZ) << "######" << interface << changedProperties; + if (changedProperties.contains(QStringLiteral("ServicesResolved"))) { + //we could check for Connected property as well, but we choose to wait + //for ServicesResolved being true + + if (pendingConnect) { + bool isResolved = changedProperties.value(QStringLiteral("ServicesResolved")).toBool(); + if (isResolved) { + setState(QLowEnergyController::ConnectedState); + pendingConnect = false; + disconnectSignalRequired = true; + Q_Q(QLowEnergyController); + emit q->connected(); + } + } + } + + if (changedProperties.contains(QStringLiteral("Connected"))) { + bool isConnected = changedProperties.value(QStringLiteral("Connected")).toBool(); + if (!isConnected) { + switch (state) { + case QLowEnergyController::ConnectingState: + case QLowEnergyController::ConnectedState: + case QLowEnergyController::DiscoveringState: + case QLowEnergyController::DiscoveredState: + case QLowEnergyController::ClosingState: + { + bool emitDisconnect = disconnectSignalRequired; + bool emitError = pendingConnect; + + resetController(); + + if (emitError) + setError(QLowEnergyController::ConnectionError); + setState(QLowEnergyController::UnconnectedState); + + if (emitDisconnect) { + Q_Q(QLowEnergyController); + emit q->disconnected(); + } + } + break; + case QLowEnergyController::AdvertisingState: + case QLowEnergyController::UnconnectedState: + //ignore + break; + } + } + } + } +} + +void QLowEnergyControllerPrivateBluezDBus::characteristicPropertiesChanged( + QLowEnergyHandle charHandle, const QString &interface, + const QVariantMap &changedProperties, + const QStringList &/*removedProperties*/) +{ + //qCDebug(QT_BT_BLUEZ) << "$$$$$$$$$$$$$$$$$$ char monitor" + // << interface << changedProperties << charHandle; + if (interface != QStringLiteral("org.bluez.GattCharacteristic1")) + return; + + if (!changedProperties.contains(QStringLiteral("Value"))) + return; + + const QLowEnergyCharacteristic changedChar = characteristicForHandle(charHandle); + const QLowEnergyDescriptor ccnDescriptor = changedChar.descriptor( + QBluetoothUuid::ClientCharacteristicConfiguration); + if (!ccnDescriptor.isValid()) + return; + + const QByteArray newValue = changedProperties.value(QStringLiteral("Value")).toByteArray(); + if (changedChar.properties() & QLowEnergyCharacteristic::Read) + updateValueOfCharacteristic(charHandle, newValue, false); //TODO upgrade to NEW_VALUE/APPEND_VALUE + + auto service = serviceForHandle(charHandle); + + if (!service.isNull()) + emit service->characteristicChanged(changedChar, newValue); +} + +void QLowEnergyControllerPrivateBluezDBus::interfacesRemoved( + const QDBusObjectPath &objectPath, const QStringList &/*interfaces*/) +{ + if (objectPath.path() == device->path()) { + resetController(); + setError(QLowEnergyController::UnknownRemoteDeviceError); + qCWarning(QT_BT_BLUEZ) << "DBus Device1 was removed"; + setState(QLowEnergyController::UnconnectedState); + } else if (objectPath.path() == adapter->path()) { + resetController(); + setError(QLowEnergyController::InvalidBluetoothAdapterError); + qCWarning(QT_BT_BLUEZ) << "DBus Adapter was removed"; + setState(QLowEnergyController::UnconnectedState); + } +} + +void QLowEnergyControllerPrivateBluezDBus::resetController() +{ + if (managerBluez) { + delete managerBluez; + managerBluez = nullptr; + } + + if (adapter) { + delete adapter; + adapter = nullptr; + } + + if (device) { + delete device; + device = nullptr; + } + + if (deviceMonitor) { + delete deviceMonitor; + deviceMonitor = nullptr; + } + + dbusServices.clear(); + jobs.clear(); + invalidateServices(); + + pendingConnect = pendingDisconnect = disconnectSignalRequired = false; + jobPending = false; +} + +void QLowEnergyControllerPrivateBluezDBus::connectToDeviceHelper() +{ + resetController(); + + bool ok = false; + const QString hostAdapterPath = findAdapterForAddress(localAdapter, &ok); + if (!ok || hostAdapterPath.isEmpty()) { + qCWarning(QT_BT_BLUEZ) << "Cannot find suitable bluetooth adapter"; + setError(QLowEnergyController::InvalidBluetoothAdapterError); + return; + } + + QScopedPointer<OrgFreedesktopDBusObjectManagerInterface> manager( + new OrgFreedesktopDBusObjectManagerInterface( + QStringLiteral("org.bluez"), QStringLiteral("/"), + QDBusConnection::systemBus())); + + QDBusPendingReply<ManagedObjectList> reply = manager->GetManagedObjects(); + reply.waitForFinished(); + if (reply.isError()) { + qCWarning(QT_BT_BLUEZ) << "Cannot enumerate Bluetooth devices for GATT connect"; + setError(QLowEnergyController::ConnectionError); + return; + } + + QString devicePath; + ManagedObjectList managedObjectList = reply.value(); + for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) { + const InterfaceList &ifaceList = it.value(); + + for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) { + const QString &iface = jt.key(); + const QVariantMap &ifaceValues = jt.value(); + + if (iface == QStringLiteral("org.bluez.Device1")) { + if (remoteDevice.toString() == ifaceValues.value(QStringLiteral("Address")).toString()) { + devicePath = it.key().path(); + break; + } + } + } + + if (!devicePath.isEmpty()) + break; + } + + if (devicePath.isEmpty()) { + qCDebug(QT_BT_BLUEZ) << "Cannot find targeted remote device. " + "Re-running device discovery might help"; + setError(QLowEnergyController::UnknownRemoteDeviceError); + return; + } + + managerBluez = manager.take(); + connect(managerBluez, &OrgFreedesktopDBusObjectManagerInterface::InterfacesRemoved, + this, &QLowEnergyControllerPrivateBluezDBus::interfacesRemoved); + adapter = new OrgBluezAdapter1Interface( + QStringLiteral("org.bluez"), hostAdapterPath, + QDBusConnection::systemBus(), this); + device = new OrgBluezDevice1Interface( + QStringLiteral("org.bluez"), devicePath, + QDBusConnection::systemBus(), this); + deviceMonitor = new OrgFreedesktopDBusPropertiesInterface( + QStringLiteral("org.bluez"), devicePath, + QDBusConnection::systemBus(), this); + connect(deviceMonitor, &OrgFreedesktopDBusPropertiesInterface::PropertiesChanged, + this, &QLowEnergyControllerPrivateBluezDBus::devicePropertiesChanged); +} + +void QLowEnergyControllerPrivateBluezDBus::connectToDevice() +{ + qCDebug(QT_BT_BLUEZ) << "QLowEnergyControllerPrivateBluezDBus::connectToDevice()"; + + connectToDeviceHelper(); + + if (!adapter || !device) + return; + + if (!adapter->powered()) { + qCWarning(QT_BT_BLUEZ) << "Error: Local adapter is powered off"; + setError(QLowEnergyController::ConnectionError); + return; + } + + setState(QLowEnergyController::ConnectingState); + + //Bluez interface is shared among all platform processes + //and hence we might be connected already + if (device->connected() && device->servicesResolved()) { + //connectToDevice is noop + disconnectSignalRequired = true; + setState(QLowEnergyController::ConnectedState); + return; + } + + pendingConnect = true; + + QDBusPendingReply<> reply = device->Connect(); + QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, &QDBusPendingCallWatcher::finished, this, + [=](QDBusPendingCallWatcher* call) { + QDBusPendingReply<> reply = *call; + if (reply.isError()) { + qCDebug(QT_BT_BLUEZ) << "BTLE_DBUS::connect() failed" + << reply.reply().errorName() + << reply.reply().errorMessage(); + bool emitDisconnect = disconnectSignalRequired; + resetController(); + setError(QLowEnergyController::UnknownError); + setState(QLowEnergyController::UnconnectedState); + if (emitDisconnect) { + Q_Q(QLowEnergyController); + emit q->disconnected(); + } + } // else -> connected when Connected property is set to true (see devicePropertiesChanged()) + call->deleteLater(); + }); +} + +void QLowEnergyControllerPrivateBluezDBus::disconnectFromDevice() +{ + setState(QLowEnergyController::ClosingState); + + pendingDisconnect = true; + + QDBusPendingReply<> reply = device->Disconnect(); + QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, &QDBusPendingCallWatcher::finished, this, + [=](QDBusPendingCallWatcher* call) { + QDBusPendingReply<> reply = *call; + if (reply.isError()) { + qCDebug(QT_BT_BLUEZ) << "BTLE_DBUS::disconnect() failed" + << reply.reply().errorName() + << reply.reply().errorMessage(); + bool emitDisconnect = disconnectSignalRequired; + resetController(); + setState(QLowEnergyController::UnconnectedState); + if (emitDisconnect) { + Q_Q(QLowEnergyController); + emit q->disconnected(); + } + } + call->deleteLater(); + }); +} + +void QLowEnergyControllerPrivateBluezDBus::discoverServices() +{ + QDBusPendingReply<ManagedObjectList> reply = managerBluez->GetManagedObjects(); + reply.waitForFinished(); + if (reply.isError()) { + qCWarning(QT_BT_BLUEZ) << "Cannot discover services"; + setError(QLowEnergyController::UnknownError); + setState(QLowEnergyController::DiscoveredState); + return; + } + + Q_Q(QLowEnergyController); + + const ManagedObjectList managedObjectList = reply.value(); + const QString servicePathPrefix = device->path().append(QStringLiteral("/service")); + for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) { + const InterfaceList &ifaceList = it.value(); + if (!it.key().path().startsWith(servicePathPrefix)) + continue; + + for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) { + const QString &iface = jt.key(); + + if (iface == QStringLiteral("org.bluez.GattService1")) { + QScopedPointer<OrgBluezGattService1Interface> service(new OrgBluezGattService1Interface( + QStringLiteral("org.bluez"),it.key().path(), + QDBusConnection::systemBus(), this)); + + QSharedPointer<QLowEnergyServicePrivate> priv = QSharedPointer<QLowEnergyServicePrivate>::create(); + priv->uuid = QBluetoothUuid(service->uUID()); + service->primary() + ? priv->type = QLowEnergyService::PrimaryService + : priv->type = QLowEnergyService::IncludedService; + priv->setController(this); + + GattService serviceContainer; + serviceContainer.servicePath = it.key().path(); + + serviceList.insert(priv->uuid, priv); + dbusServices.insert(priv->uuid, serviceContainer); + + emit q->serviceDiscovered(priv->uuid); + } + } + } + + setState(QLowEnergyController::DiscoveredState); + emit q->discoveryFinished(); +} + +void QLowEnergyControllerPrivateBluezDBus::discoverServiceDetails(const QBluetoothUuid &service) +{ + if (!serviceList.contains(service) || !dbusServices.contains(service)) { + qCWarning(QT_BT_BLUEZ) << "Discovery of unknown service" << service.toString() + << "not possible"; + return; + } + + //clear existing service data and run new discovery + QSharedPointer<QLowEnergyServicePrivate> serviceData = serviceList.value(service); + serviceData->characteristicList.clear(); + + GattService &dbusData = dbusServices[service]; + dbusData.characteristics.clear(); + + QDBusPendingReply<ManagedObjectList> reply = managerBluez->GetManagedObjects(); + reply.waitForFinished(); + if (reply.isError()) { + qCWarning(QT_BT_BLUEZ) << "Cannot discover services"; + setError(QLowEnergyController::UnknownError); + setState(QLowEnergyController::DiscoveredState); + return; + } + + QStringList descriptorPaths; + const ManagedObjectList managedObjectList = reply.value(); + for (ManagedObjectList::const_iterator it = managedObjectList.constBegin(); it != managedObjectList.constEnd(); ++it) { + const InterfaceList &ifaceList = it.value(); + if (!it.key().path().startsWith(dbusData.servicePath)) + continue; + + for (InterfaceList::const_iterator jt = ifaceList.constBegin(); jt != ifaceList.constEnd(); ++jt) { + const QString &iface = jt.key(); + if (iface == QStringLiteral("org.bluez.GattCharacteristic1")) { + auto charInterface = QSharedPointer<OrgBluezGattCharacteristic1Interface>::create( + QStringLiteral("org.bluez"), it.key().path(), + QDBusConnection::systemBus()); + GattCharacteristic dbusCharData; + dbusCharData.characteristic = charInterface; + dbusData.characteristics.append(dbusCharData); + } else if (iface == QStringLiteral("org.bluez.GattDescriptor1")) { + auto descInterface = QSharedPointer<OrgBluezGattDescriptor1Interface>::create( + QStringLiteral("org.bluez"), it.key().path(), + QDBusConnection::systemBus()); + bool found = false; + for (GattCharacteristic &dbusCharData : dbusData.characteristics) { + if (!descInterface->path().startsWith( + dbusCharData.characteristic->path())) + continue; + + found = true; + dbusCharData.descriptors.append(descInterface); + break; + } + + Q_ASSERT(found); + if (!found) + qCWarning(QT_BT_BLUEZ) << "Descriptor discovery error"; + } + } + } + + //populate servicePrivate based on dbus data + serviceData->startHandle = runningHandle++; + for (GattCharacteristic &dbusChar : dbusData.characteristics) { + const QLowEnergyHandle indexHandle = runningHandle++; + QLowEnergyServicePrivate::CharData charData; + + // characteristic data + charData.valueHandle = runningHandle++; + const QStringList properties = dbusChar.characteristic->flags(); + + for (const auto &entry : properties) { + if (entry == QStringLiteral("broadcast")) + charData.properties.setFlag(QLowEnergyCharacteristic::Broadcasting, true); + else if (entry == QStringLiteral("read")) + charData.properties.setFlag(QLowEnergyCharacteristic::Read, true); + else if (entry == QStringLiteral("write-without-response")) + charData.properties.setFlag(QLowEnergyCharacteristic::WriteNoResponse, true); + else if (entry == QStringLiteral("write")) + charData.properties.setFlag(QLowEnergyCharacteristic::Write, true); + else if (entry == QStringLiteral("notify")) + charData.properties.setFlag(QLowEnergyCharacteristic::Notify, true); + else if (entry == QStringLiteral("indicate")) + charData.properties.setFlag(QLowEnergyCharacteristic::Indicate, true); + else if (entry == QStringLiteral("authenticated-signed-writes")) + charData.properties.setFlag(QLowEnergyCharacteristic::WriteSigned, true); + else if (entry == QStringLiteral("reliable-write")) + charData.properties.setFlag(QLowEnergyCharacteristic::ExtendedProperty, true); + else if (entry == QStringLiteral("writable-auxiliaries")) + charData.properties.setFlag(QLowEnergyCharacteristic::ExtendedProperty, true); + //all others ignored - not relevant for this API + } + + charData.uuid = QBluetoothUuid(dbusChar.characteristic->uUID()); + + // schedule read for initial char value + if (charData.properties.testFlag(QLowEnergyCharacteristic::Read)) { + GattJob job; + job.flags = GattJob::JobFlags({GattJob::CharRead, GattJob::ServiceDiscovery}); + job.service = serviceData; + job.handle = indexHandle; + jobs.append(job); + } + + // descriptor data + for (const auto &descEntry : qAsConst(dbusChar.descriptors)) { + const QLowEnergyHandle descriptorHandle = runningHandle++; + QLowEnergyServicePrivate::DescData descData; + descData.uuid = QBluetoothUuid(descEntry->uUID()); + charData.descriptorList.insert(descriptorHandle, descData); + + + // every ClientCharacteristicConfiguration needs to track property changes + if (descData.uuid + == QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)) { + dbusChar.charMonitor = QSharedPointer<OrgFreedesktopDBusPropertiesInterface>::create( + QStringLiteral("org.bluez"), + dbusChar.characteristic->path(), + QDBusConnection::systemBus(), this); + connect(dbusChar.charMonitor.data(), &OrgFreedesktopDBusPropertiesInterface::PropertiesChanged, + this, [this, indexHandle](const QString &interface, const QVariantMap &changedProperties, + const QStringList &removedProperties) { + + characteristicPropertiesChanged(indexHandle, interface, + changedProperties, removedProperties); + }); + } + + // schedule read for initial descriptor value + GattJob job; + job.flags = GattJob::JobFlags({GattJob::DescRead, GattJob::ServiceDiscovery}); + job.service = serviceData; + job.handle = descriptorHandle; + jobs.append(job); + } + + serviceData->characteristicList[indexHandle] = charData; + } + + serviceData->endHandle = runningHandle++; + + // last job is last step of service discovery + GattJob &lastJob = jobs.last(); + lastJob.flags.setFlag(GattJob::LastServiceDiscovery, true); + + scheduleNextJob(); +} + +void QLowEnergyControllerPrivateBluezDBus::prepareNextJob() +{ + jobs.takeFirst(); // finish last job + jobPending = false; + + scheduleNextJob(); // continue with next job - if available +} + +void QLowEnergyControllerPrivateBluezDBus::onCharReadFinished(QDBusPendingCallWatcher *call) +{ + Q_ASSERT(jobPending); + Q_ASSERT(!jobs.isEmpty()); + + const GattJob nextJob = jobs.constFirst(); + Q_ASSERT(nextJob.flags.testFlag(GattJob::CharRead)); + + QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(nextJob.handle); + if (service.isNull() || !dbusServices.contains(service->uuid)) { + qCWarning(QT_BT_BLUEZ) << "onCharReadFinished: Invalid GATT job. Skipping."; + call->deleteLater(); + prepareNextJob(); + return; + } + const QLowEnergyServicePrivate::CharData &charData = + service->characteristicList.value(nextJob.handle); + + bool isServiceDiscovery = nextJob.flags.testFlag(GattJob::ServiceDiscovery); + QDBusPendingReply<QByteArray> reply = *call; + if (reply.isError()) { + qCWarning(QT_BT_BLUEZ) << "Cannot initiate reading of" << charData.uuid + << "of service" << service->uuid + << reply.error().name() << reply.error().message(); + if (!isServiceDiscovery) + service->setError(QLowEnergyService::CharacteristicReadError); + } else { + qCDebug(QT_BT_BLUEZ) << "Read Char:" << charData.uuid << reply.value().toHex(); + if (charData.properties.testFlag(QLowEnergyCharacteristic::Read)) + updateValueOfCharacteristic(nextJob.handle, reply.value(), false); + + if (isServiceDiscovery) { + if (nextJob.flags.testFlag(GattJob::LastServiceDiscovery)) + service->setState(QLowEnergyService::ServiceDiscovered); + } else { + QLowEnergyCharacteristic ch(service, nextJob.handle); + emit service->characteristicRead(ch, reply.value()); + } + } + + call->deleteLater(); + prepareNextJob(); +} + +void QLowEnergyControllerPrivateBluezDBus::onDescReadFinished(QDBusPendingCallWatcher *call) +{ + Q_ASSERT(jobPending); + Q_ASSERT(!jobs.isEmpty()); + + const GattJob nextJob = jobs.constFirst(); + Q_ASSERT(nextJob.flags.testFlag(GattJob::DescRead)); + + QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(nextJob.handle); + if (service.isNull() || !dbusServices.contains(service->uuid)) { + qCWarning(QT_BT_BLUEZ) << "onDescReadFinished: Invalid GATT job. Skipping."; + call->deleteLater(); + prepareNextJob(); + return; + } + + QLowEnergyCharacteristic ch = characteristicForHandle(nextJob.handle); + if (!ch.isValid()) { + qCWarning(QT_BT_BLUEZ) << "Cannot find char for desc read (onDescReadFinished 1)."; + call->deleteLater(); + prepareNextJob(); + return; + } + + const QLowEnergyServicePrivate::CharData &charData = + service->characteristicList.value(ch.attributeHandle()); + + if (!charData.descriptorList.contains(nextJob.handle)) { + qCWarning(QT_BT_BLUEZ) << "Cannot find descriptor (onDescReadFinished 2)."; + call->deleteLater(); + prepareNextJob(); + return; + } + + bool isServiceDiscovery = nextJob.flags.testFlag(GattJob::ServiceDiscovery); + const QBluetoothUuid descUuid = charData.descriptorList[nextJob.handle].uuid; + + QDBusPendingReply<QByteArray> reply = *call; + if (reply.isError()) { + qCWarning(QT_BT_BLUEZ) << "Cannot read descriptor (onDescReadFinished 3): " + << charData.descriptorList[nextJob.handle].uuid + << charData.uuid + << reply.error().name() << reply.error().message(); + if (!isServiceDiscovery) + service->setError(QLowEnergyService::DescriptorReadError); + } else { + qCDebug(QT_BT_BLUEZ) << "Read Desc:" << reply.value(); + updateValueOfDescriptor(ch.attributeHandle(), nextJob.handle, reply.value(), false); + + if (isServiceDiscovery) { + if (nextJob.flags.testFlag(GattJob::LastServiceDiscovery)) + service->setState(QLowEnergyService::ServiceDiscovered); + } else { + QLowEnergyDescriptor desc(service, ch.attributeHandle(), nextJob.handle); + emit service->descriptorRead(desc, reply.value()); + } + } + + call->deleteLater(); + prepareNextJob(); +} + +void QLowEnergyControllerPrivateBluezDBus::onCharWriteFinished(QDBusPendingCallWatcher *call) +{ + Q_ASSERT(jobPending); + Q_ASSERT(!jobs.isEmpty()); + + const GattJob nextJob = jobs.constFirst(); + Q_ASSERT(nextJob.flags.testFlag(GattJob::CharWrite)); + + QSharedPointer<QLowEnergyServicePrivate> service = nextJob.service; + if (!dbusServices.contains(service->uuid)) { + qCWarning(QT_BT_BLUEZ) << "onCharWriteFinished: Invalid GATT job. Skipping."; + call->deleteLater(); + prepareNextJob(); + return; + } + + const QLowEnergyServicePrivate::CharData &charData = + service->characteristicList.value(nextJob.handle); + + QDBusPendingReply<> reply = *call; + if (reply.isError()) { + qCWarning(QT_BT_BLUEZ) << "Cannot initiate writing of" << charData.uuid + << "of service" << service->uuid + << reply.error().name() << reply.error().message(); + service->setError(QLowEnergyService::CharacteristicWriteError); + } else { + if (charData.properties.testFlag(QLowEnergyCharacteristic::Read)) + updateValueOfCharacteristic(nextJob.handle, nextJob.value, false); + + QLowEnergyCharacteristic ch(service, nextJob.handle); + // write without respone implies zero feedback + if (nextJob.writeMode == QLowEnergyService::WriteWithResponse) { + qCDebug(QT_BT_BLUEZ) << "Written Char:" << charData.uuid << nextJob.value.toHex(); + emit service->characteristicWritten(ch, nextJob.value); + } + } + + call->deleteLater(); + prepareNextJob(); +} + +void QLowEnergyControllerPrivateBluezDBus::onDescWriteFinished(QDBusPendingCallWatcher *call) +{ + Q_ASSERT(jobPending); + Q_ASSERT(!jobs.isEmpty()); + + const GattJob nextJob = jobs.constFirst(); + Q_ASSERT(nextJob.flags.testFlag(GattJob::DescWrite)); + + QSharedPointer<QLowEnergyServicePrivate> service = nextJob.service; + if (!dbusServices.contains(service->uuid)) { + qCWarning(QT_BT_BLUEZ) << "onDescWriteFinished: Invalid GATT job. Skipping."; + call->deleteLater(); + prepareNextJob(); + return; + } + + const QLowEnergyCharacteristic associatedChar = characteristicForHandle(nextJob.handle); + const QLowEnergyDescriptor descriptor = descriptorForHandle(nextJob.handle); + if (!associatedChar.isValid() || !descriptor.isValid()) { + qCWarning(QT_BT_BLUEZ) << "onDescWriteFinished: Cannot find associated char/desc: " + << associatedChar.isValid(); + call->deleteLater(); + prepareNextJob(); + return; + } + + QDBusPendingReply<> reply = *call; + if (reply.isError()) { + qCWarning(QT_BT_BLUEZ) << "Cannot initiate writing of" << descriptor.uuid() + << "of char" << associatedChar.uuid() + << "of service" << service->uuid + << reply.error().name() << reply.error().message(); + service->setError(QLowEnergyService::DescriptorWriteError); + } else { + qCDebug(QT_BT_BLUEZ) << "Write Desc:" << descriptor.uuid() << nextJob.value.toHex(); + updateValueOfDescriptor(associatedChar.attributeHandle(), nextJob.handle, + nextJob.value, false); + emit service->descriptorWritten(descriptor, nextJob.value); + } + + call->deleteLater(); + prepareNextJob(); +} + +void QLowEnergyControllerPrivateBluezDBus::scheduleNextJob() +{ + if (jobPending || jobs.isEmpty()) + return; + + jobPending = true; + + const GattJob nextJob = jobs.constFirst(); + QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(nextJob.handle); + if (service.isNull() || !dbusServices.contains(service->uuid)) { + qCWarning(QT_BT_BLUEZ) << "Invalid GATT job (scheduleReadChar). Skipping."; + prepareNextJob(); + return; + } + + const GattService &dbusServiceData = dbusServices[service->uuid]; + + if (nextJob.flags.testFlag(GattJob::CharRead)) { + // characteristic reading *************************************** + if (!service->characteristicList.contains(nextJob.handle)) { + qCWarning(QT_BT_BLUEZ) << "Invalid Char handle when reading. Skipping."; + prepareNextJob(); + return; + } + + const QLowEnergyServicePrivate::CharData &charData = + service->characteristicList.value(nextJob.handle); + bool foundChar = false; + for (const auto &gattChar : qAsConst(dbusServiceData.characteristics)) { + if (charData.uuid != QBluetoothUuid(gattChar.characteristic->uUID())) + continue; + + QDBusPendingReply<QByteArray> reply = gattChar.characteristic->ReadValue(QVariantMap()); + QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, &QDBusPendingCallWatcher::finished, + this, &QLowEnergyControllerPrivateBluezDBus::onCharReadFinished); + + foundChar = true; + break; + } + + if (!foundChar) { + qCWarning(QT_BT_BLUEZ) << "Cannot find char for reading. Skipping."; + prepareNextJob(); + return; + } + } else if (nextJob.flags.testFlag(GattJob::CharWrite)) { + // characteristic writing *************************************** + if (!service->characteristicList.contains(nextJob.handle)) { + qCWarning(QT_BT_BLUEZ) << "Invalid Char handle when writing. Skipping."; + prepareNextJob(); + return; + } + + const QLowEnergyServicePrivate::CharData &charData = + service->characteristicList.value(nextJob.handle); + bool foundChar = false; + for (const auto &gattChar : qAsConst(dbusServiceData.characteristics)) { + if (charData.uuid != QBluetoothUuid(gattChar.characteristic->uUID())) + continue; + + QDBusPendingReply<> reply = gattChar.characteristic->WriteValue(nextJob.value, QVariantMap()); + QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, &QDBusPendingCallWatcher::finished, + this, &QLowEnergyControllerPrivateBluezDBus::onCharWriteFinished); + + foundChar = true; + break; + } + + if (!foundChar) { + qCWarning(QT_BT_BLUEZ) << "Cannot find char for writing. Skipping."; + prepareNextJob(); + return; + } + } else if (nextJob.flags.testFlag(GattJob::DescRead)) { + // descriptor reading *************************************** + QLowEnergyCharacteristic ch = characteristicForHandle(nextJob.handle); + if (!ch.isValid()) { + qCWarning(QT_BT_BLUEZ) << "Invalid GATT job (scheduleReadDesc 1). Skipping."; + prepareNextJob(); + return; + } + + const QLowEnergyServicePrivate::CharData &charData = + service->characteristicList.value(ch.attributeHandle()); + if (!charData.descriptorList.contains(nextJob.handle)) { + qCWarning(QT_BT_BLUEZ) << "Invalid GATT job (scheduleReadDesc 2). Skipping."; + prepareNextJob(); + return; + } + + const QBluetoothUuid descUuid = charData.descriptorList[nextJob.handle].uuid; + bool foundDesc = false; + for (const auto &gattChar : qAsConst(dbusServiceData.characteristics)) { + if (charData.uuid != QBluetoothUuid(gattChar.characteristic->uUID())) + continue; + + for (const auto &gattDesc : qAsConst(gattChar.descriptors)) { + if (descUuid != QBluetoothUuid(gattDesc->uUID())) + continue; + + QDBusPendingReply<QByteArray> reply = gattDesc->ReadValue(QVariantMap()); + QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, &QDBusPendingCallWatcher::finished, + this, &QLowEnergyControllerPrivateBluezDBus::onDescReadFinished); + foundDesc = true; + break; + } + + if (foundDesc) + break; + } + + if (!foundDesc) { + qCWarning(QT_BT_BLUEZ) << "Cannot find descriptor for reading. Skipping."; + prepareNextJob(); + return; + } + } else if (nextJob.flags.testFlag(GattJob::DescWrite)) { + // descriptor writing *************************************** + const QLowEnergyCharacteristic ch = characteristicForHandle(nextJob.handle); + if (!ch.isValid()) { + qCWarning(QT_BT_BLUEZ) << "Invalid GATT job (scheduleWriteDesc 1). Skipping."; + prepareNextJob(); + return; + } + + const QLowEnergyServicePrivate::CharData &charData = + service->characteristicList.value(ch.attributeHandle()); + if (!charData.descriptorList.contains(nextJob.handle)) { + qCWarning(QT_BT_BLUEZ) << "Invalid GATT job (scheduleWriteDesc 2). Skipping."; + prepareNextJob(); + return; + } + + const QBluetoothUuid descUuid = charData.descriptorList[nextJob.handle].uuid; + bool foundDesc = false; + for (const auto &gattChar : qAsConst(dbusServiceData.characteristics)) { + if (charData.uuid != QBluetoothUuid(gattChar.characteristic->uUID())) + continue; + + for (const auto &gattDesc : qAsConst(gattChar.descriptors)) { + if (descUuid != QBluetoothUuid(gattDesc->uUID())) + continue; + + //notifications enabled via characteristics Start/StopNotify() functions + //otherwise regular WriteValue() calls on descriptor interface + if (descUuid == QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)) { + const QByteArray value = nextJob.value; + + QDBusPendingReply<> reply; + qCDebug(QT_BT_BLUEZ) << "Init CCC change to" << value.toHex() + << charData.uuid << service->uuid; + if (value == QByteArray::fromHex("0100") || value == QByteArray::fromHex("0200")) + reply = gattChar.characteristic->StartNotify(); + else + reply = gattChar.characteristic->StopNotify(); + QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, &QDBusPendingCallWatcher::finished, + this, &QLowEnergyControllerPrivateBluezDBus::onDescWriteFinished); + } else { + QDBusPendingReply<> reply = gattDesc->WriteValue(nextJob.value, QVariantMap()); + QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(reply, this); + connect(watcher, &QDBusPendingCallWatcher::finished, + this, &QLowEnergyControllerPrivateBluezDBus::onDescWriteFinished); + + } + + foundDesc = true; + break; + } + + if (foundDesc) + break; + } + + if (!foundDesc) { + qCWarning(QT_BT_BLUEZ) << "Cannot find descriptor for writing. Skipping."; + prepareNextJob(); + return; + } + } else { + qCWarning(QT_BT_BLUEZ) << "Unknown gatt job type. Skipping."; + prepareNextJob(); + } +} + +void QLowEnergyControllerPrivateBluezDBus::readCharacteristic( + const QSharedPointer<QLowEnergyServicePrivate> service, + const QLowEnergyHandle charHandle) +{ + Q_ASSERT(!service.isNull()); + if (!service->characteristicList.contains(charHandle)) { + qCWarning(QT_BT_BLUEZ) << "Read characteristic does not belong to service" + << service->uuid; + return; + } + + const QLowEnergyServicePrivate::CharData &charDetails + = service->characteristicList[charHandle]; + if (!(charDetails.properties & QLowEnergyCharacteristic::Read)) { + // if this succeeds the device has a bug, char is advertised as + // non-readable. We try to be permissive and let the remote + // device answer to the read attempt + qCWarning(QT_BT_BLUEZ) << "Reading non-readable char" << charHandle; + } + + GattJob job; + job.flags = GattJob::JobFlags({GattJob::CharRead}); + job.service = service; + job.handle = charHandle; + jobs.append(job); + + scheduleNextJob(); +} + +void QLowEnergyControllerPrivateBluezDBus::readDescriptor( + const QSharedPointer<QLowEnergyServicePrivate> service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle) +{ + Q_ASSERT(!service.isNull()); + if (!service->characteristicList.contains(charHandle)) + return; + + const QLowEnergyServicePrivate::CharData &charDetails + = service->characteristicList[charHandle]; + if (!charDetails.descriptorList.contains(descriptorHandle)) + return; + + GattJob job; + job.flags = GattJob::JobFlags({GattJob::DescRead}); + job.service = service; + job.handle = descriptorHandle; + jobs.append(job); + + scheduleNextJob(); +} + +void QLowEnergyControllerPrivateBluezDBus::writeCharacteristic( + const QSharedPointer<QLowEnergyServicePrivate> service, + const QLowEnergyHandle charHandle, + const QByteArray &newValue, + QLowEnergyService::WriteMode writeMode) +{ + Q_ASSERT(!service.isNull()); + if (!service->characteristicList.contains(charHandle)) { + qCWarning(QT_BT_BLUEZ) << "Write characteristic does not belong to service" + << service->uuid; + return; + } + + if (role == QLowEnergyController::CentralRole) { + GattJob job; + job.flags = GattJob::JobFlags({GattJob::CharWrite}); + job.service = service; + job.handle = charHandle; + job.value = newValue; + job.writeMode = writeMode; + jobs.append(job); + + scheduleNextJob(); + } else { + qWarning(QT_BT_BLUEZ) << "writeCharacteristic() not implemented for DBus Bluez GATT"; + service->setError(QLowEnergyService::CharacteristicWriteError); + } +} + +void QLowEnergyControllerPrivateBluezDBus::writeDescriptor( + const QSharedPointer<QLowEnergyServicePrivate> service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle, + const QByteArray &newValue) +{ + Q_ASSERT(!service.isNull()); + if (!service->characteristicList.contains(charHandle)) + return; + + if (role == QLowEnergyController::CentralRole) { + GattJob job; + job.flags = GattJob::JobFlags({GattJob::DescWrite}); + job.service = service; + job.handle = descriptorHandle; + job.value = newValue; + jobs.append(job); + + scheduleNextJob(); + } else { + qWarning(QT_BT_BLUEZ) << "writeDescriptor() peripheral not implemented for DBus Bluez GATT"; + service->setError(QLowEnergyService::CharacteristicWriteError); + } +} + +void QLowEnergyControllerPrivateBluezDBus::startAdvertising( + const QLowEnergyAdvertisingParameters &/* params */, + const QLowEnergyAdvertisingData &/* advertisingData */, + const QLowEnergyAdvertisingData &/* scanResponseData */) +{ +} + +void QLowEnergyControllerPrivateBluezDBus::stopAdvertising() +{ +} + +void QLowEnergyControllerPrivateBluezDBus::requestConnectionUpdate( + const QLowEnergyConnectionParameters & /* params */) +{ +} + +void QLowEnergyControllerPrivateBluezDBus::addToGenericAttributeList( + const QLowEnergyServiceData &/* service */, + QLowEnergyHandle /* startHandle */) +{ +} + +QLowEnergyService *QLowEnergyControllerPrivateBluezDBus::addServiceHelper( + const QLowEnergyServiceData &/*service*/) +{ + return nullptr; +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qlowenergycontroller_bluezdbus_p.h b/src/bluetooth/qlowenergycontroller_bluezdbus_p.h new file mode 100644 index 00000000..7ac1808f --- /dev/null +++ b/src/bluetooth/qlowenergycontroller_bluezdbus_p.h @@ -0,0 +1,191 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtBluetooth module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLOWENERGYCONTROLLERPRIVATEDBUS_P_H +#define QLOWENERGYCONTROLLERPRIVATEDBUS_P_H + + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qlowenergycontroller.h" +#include "qlowenergycontrollerbase_p.h" + +#include <QtDBus/QDBusObjectPath> + +class OrgBluezAdapter1Interface; +class OrgBluezDevice1Interface; +class OrgBluezGattCharacteristic1Interface; +class OrgBluezGattDescriptor1Interface; +class OrgBluezGattService1Interface; +class OrgFreedesktopDBusObjectManagerInterface; +class OrgFreedesktopDBusPropertiesInterface; + +QT_BEGIN_NAMESPACE + +class QDBusPendingCallWatcher; + +class QLowEnergyControllerPrivateBluezDBus : public QLowEnergyControllerPrivate +{ + Q_OBJECT +public: + QLowEnergyControllerPrivateBluezDBus(); + ~QLowEnergyControllerPrivateBluezDBus(); + + void init() override; + void connectToDevice() override; + void disconnectFromDevice() override; + + void discoverServices() override; + void discoverServiceDetails(const QBluetoothUuid &/*service*/) override; + + void readCharacteristic( + const QSharedPointer<QLowEnergyServicePrivate> /*service*/, + const QLowEnergyHandle /*charHandle*/) override; + void readDescriptor( + const QSharedPointer<QLowEnergyServicePrivate> /*service*/, + const QLowEnergyHandle /*charHandle*/, + const QLowEnergyHandle /*descriptorHandle*/) override; + + void writeCharacteristic( + const QSharedPointer<QLowEnergyServicePrivate> /*service*/, + const QLowEnergyHandle /*charHandle*/, + const QByteArray &/*newValue*/, + QLowEnergyService::WriteMode /*writeMode*/) override; + void writeDescriptor( + const QSharedPointer<QLowEnergyServicePrivate> /*service*/, + const QLowEnergyHandle /*charHandle*/, + const QLowEnergyHandle /*descriptorHandle*/, + const QByteArray &/*newValue*/) override; + + void startAdvertising( + const QLowEnergyAdvertisingParameters &/* params */, + const QLowEnergyAdvertisingData &/* advertisingData */, + const QLowEnergyAdvertisingData &/* scanResponseData */) override; + void stopAdvertising() override; + + void requestConnectionUpdate( + const QLowEnergyConnectionParameters & /* params */) override; + void addToGenericAttributeList( + const QLowEnergyServiceData &/* service */, + QLowEnergyHandle /* startHandle */) override; + + QLowEnergyService *addServiceHelper(const QLowEnergyServiceData &service) override; + + +private: + void connectToDeviceHelper(); + void resetController(); + + void scheduleNextJob(); + +private slots: + void devicePropertiesChanged(const QString &interface, const QVariantMap &changedProperties, + const QStringList &/*invalidatedProperties*/); + void characteristicPropertiesChanged(QLowEnergyHandle charHandle, const QString &interface, + const QVariantMap &changedProperties, + const QStringList &invalidatedProperties); + void interfacesRemoved(const QDBusObjectPath &objectPath, const QStringList &interfaces); + + void onCharReadFinished(QDBusPendingCallWatcher *call); + void onDescReadFinished(QDBusPendingCallWatcher *call); + void onCharWriteFinished(QDBusPendingCallWatcher *call); + void onDescWriteFinished(QDBusPendingCallWatcher *call); +private: + OrgBluezAdapter1Interface* adapter{}; + OrgBluezDevice1Interface* device{}; + OrgFreedesktopDBusObjectManagerInterface* managerBluez{}; + OrgFreedesktopDBusPropertiesInterface* deviceMonitor{}; + + bool pendingConnect = false; + bool pendingDisconnect = false; + bool disconnectSignalRequired = false; + + struct GattCharacteristic + { + QSharedPointer<OrgBluezGattCharacteristic1Interface> characteristic; + QSharedPointer<OrgFreedesktopDBusPropertiesInterface> charMonitor; + QVector<QSharedPointer<OrgBluezGattDescriptor1Interface>> descriptors; + }; + + struct GattService + { + QString servicePath; + QVector<GattCharacteristic> characteristics; + }; + + QHash<QBluetoothUuid, GattService> dbusServices; + QLowEnergyHandle runningHandle = 1; + + struct GattJob { + enum JobFlag { + Unset = 0x00, + CharRead = 0x01, + CharWrite = 0x02, + DescRead = 0x04, + DescWrite = 0x08, + ServiceDiscovery = 0x10, + LastServiceDiscovery = 0x20 + }; + Q_DECLARE_FLAGS(JobFlags, JobFlag) + + JobFlags flags = GattJob::Unset; + QLowEnergyHandle handle; + QByteArray value; + QLowEnergyService::WriteMode writeMode = QLowEnergyService::WriteWithResponse; + QSharedPointer<QLowEnergyServicePrivate> service; + }; + + QVector<GattJob> jobs; + bool jobPending = false; + + void prepareNextJob(); +}; + +QT_END_NAMESPACE + +#endif // QLOWENERGYCONTROLLERPRIVATEDBUS_P_H diff --git a/src/bluetooth/qlowenergycontroller_osx.mm b/src/bluetooth/qlowenergycontroller_osx.mm index a2923d81..2958e6ed 100644 --- a/src/bluetooth/qlowenergycontroller_osx.mm +++ b/src/bluetooth/qlowenergycontroller_osx.mm @@ -72,6 +72,8 @@ static void registerQLowEnergyControllerMetaType() qRegisterMetaType<QLowEnergyController::Error>(); qRegisterMetaType<QLowEnergyHandle>("QLowEnergyHandle"); qRegisterMetaType<QSharedPointer<QLowEnergyServicePrivate> >(); + qRegisterMetaType<QLowEnergyCharacteristic>(); + qRegisterMetaType<QLowEnergyDescriptor>(); initDone = true; } } @@ -962,7 +964,7 @@ void QLowEnergyControllerPrivateOSX::setErrorDescription(QLowEnergyController::E void QLowEnergyControllerPrivateOSX::invalidateServices() { foreach (const QSharedPointer<QLowEnergyServicePrivate> service, discoveredServices.values()) { - service->setController(Q_NULLPTR); + service->setController(nullptr); service->setState(QLowEnergyService::InvalidService); } @@ -1228,7 +1230,7 @@ QLowEnergyService *QLowEnergyController::createServiceObject(const QBluetoothUui { OSX_D_PTR; - QLowEnergyService *service = Q_NULLPTR; + QLowEnergyService *service = nullptr; QLowEnergyControllerPrivateOSX::ServiceMap::const_iterator it = osx_d_ptr->discoveredServices.constFind(serviceUuid); if (it != osx_d_ptr->discoveredServices.constEnd()) { diff --git a/src/bluetooth/qlowenergycontroller_osx_p.h b/src/bluetooth/qlowenergycontroller_osx_p.h index 5cceb9e6..24b7c6e9 100644 --- a/src/bluetooth/qlowenergycontroller_osx_p.h +++ b/src/bluetooth/qlowenergycontroller_osx_p.h @@ -54,7 +54,7 @@ #include "osx/osxbtperipheralmanager_p.h" #include "qlowenergyserviceprivate_p.h" #include "osx/osxbtcentralmanager_p.h" -#include "qlowenergycontroller_p.h" +#include "qlowenergycontrollerbase_p.h" #include "qlowenergycontroller.h" #include "osx/osxbtnotifier_p.h" #include "osx/osxbtutility_p.h" diff --git a/src/bluetooth/qlowenergycontroller_p.cpp b/src/bluetooth/qlowenergycontroller_p.cpp index 27d16093..c3605f05 100644 --- a/src/bluetooth/qlowenergycontroller_p.cpp +++ b/src/bluetooth/qlowenergycontroller_p.cpp @@ -38,33 +38,26 @@ ****************************************************************************/ #include "qlowenergycontroller_p.h" -#ifndef QT_IOS_BLUETOOTH #include "dummy/dummy_helper_p.h" -#endif QT_BEGIN_NAMESPACE -QLowEnergyControllerPrivate::QLowEnergyControllerPrivate() - : QObject(), - state(QLowEnergyController::UnconnectedState), - error(QLowEnergyController::NoError), - lastLocalHandle(0) +QLowEnergyControllerPrivateCommon::QLowEnergyControllerPrivateCommon() + : QLowEnergyControllerPrivate() { -#ifndef QT_IOS_BLUETOOTH printDummyWarning(); -#endif registerQLowEnergyControllerMetaType(); } -QLowEnergyControllerPrivate::~QLowEnergyControllerPrivate() +QLowEnergyControllerPrivateCommon::~QLowEnergyControllerPrivateCommon() { } -void QLowEnergyControllerPrivate::init() +void QLowEnergyControllerPrivateCommon::init() { } -void QLowEnergyControllerPrivate::connectToDevice() +void QLowEnergyControllerPrivateCommon::connectToDevice() { // required to pass unit test on default backend if (remoteDevice.isNull()) { @@ -73,39 +66,39 @@ void QLowEnergyControllerPrivate::connectToDevice() return; } - qWarning() << "QLowEnergyControllerPrivate::connectToDevice(): Not implemented"; + qWarning() << "QLowEnergyControllerPrivateCommon::connectToDevice(): Not implemented"; setError(QLowEnergyController::UnknownError); } -void QLowEnergyControllerPrivate::disconnectFromDevice() +void QLowEnergyControllerPrivateCommon::disconnectFromDevice() { } -void QLowEnergyControllerPrivate::discoverServices() +void QLowEnergyControllerPrivateCommon::discoverServices() { } -void QLowEnergyControllerPrivate::discoverServiceDetails(const QBluetoothUuid &/*service*/) +void QLowEnergyControllerPrivateCommon::discoverServiceDetails(const QBluetoothUuid &/*service*/) { } -void QLowEnergyControllerPrivate::readCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> /*service*/, +void QLowEnergyControllerPrivateCommon::readCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> /*service*/, const QLowEnergyHandle /*charHandle*/) { } -void QLowEnergyControllerPrivate::readDescriptor(const QSharedPointer<QLowEnergyServicePrivate> /*service*/, +void QLowEnergyControllerPrivateCommon::readDescriptor(const QSharedPointer<QLowEnergyServicePrivate> /*service*/, const QLowEnergyHandle /*charHandle*/, const QLowEnergyHandle /*descriptorHandle*/) { } -void QLowEnergyControllerPrivate::writeCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> /*service*/, +void QLowEnergyControllerPrivateCommon::writeCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> /*service*/, const QLowEnergyHandle /*charHandle*/, const QByteArray &/*newValue*/, QLowEnergyService::WriteMode /*writeMode*/) @@ -113,7 +106,7 @@ void QLowEnergyControllerPrivate::writeCharacteristic(const QSharedPointer<QLowE } -void QLowEnergyControllerPrivate::writeDescriptor( +void QLowEnergyControllerPrivateCommon::writeDescriptor( const QSharedPointer<QLowEnergyServicePrivate> /*service*/, const QLowEnergyHandle /*charHandle*/, const QLowEnergyHandle /*descriptorHandle*/, @@ -122,21 +115,21 @@ void QLowEnergyControllerPrivate::writeDescriptor( } -void QLowEnergyControllerPrivate::startAdvertising(const QLowEnergyAdvertisingParameters &/* params */, +void QLowEnergyControllerPrivateCommon::startAdvertising(const QLowEnergyAdvertisingParameters &/* params */, const QLowEnergyAdvertisingData &/* advertisingData */, const QLowEnergyAdvertisingData &/* scanResponseData */) { } -void QLowEnergyControllerPrivate::stopAdvertising() +void QLowEnergyControllerPrivateCommon::stopAdvertising() { } -void QLowEnergyControllerPrivate::requestConnectionUpdate(const QLowEnergyConnectionParameters & /* params */) +void QLowEnergyControllerPrivateCommon::requestConnectionUpdate(const QLowEnergyConnectionParameters & /* params */) { } -void QLowEnergyControllerPrivate::addToGenericAttributeList(const QLowEnergyServiceData &/* service */, +void QLowEnergyControllerPrivateCommon::addToGenericAttributeList(const QLowEnergyServiceData &/* service */, QLowEnergyHandle /* startHandle */) { } diff --git a/src/bluetooth/qlowenergycontroller_p.h b/src/bluetooth/qlowenergycontroller_p.h index 6e866144..623c71a2 100644 --- a/src/bluetooth/qlowenergycontroller_p.h +++ b/src/bluetooth/qlowenergycontroller_p.h @@ -51,452 +51,62 @@ // We mean it. // -#if defined(QT_OSX_BLUETOOTH) || defined(QT_IOS_BLUETOOTH) - -#include <QtCore/qglobal.h> -#include <QtCore/qobject.h> - -QT_BEGIN_NAMESPACE - -class QLowEnergyControllerPrivate : public QObject -{ -public: - // This class is required to make shared pointer machinery and - // moc (== Obj-C syntax) happy on both OS X and iOS. -}; - -QT_END_NAMESPACE - -#else - #include <qglobal.h> #include <QtCore/QQueue> #include <QtCore/QVector> #include <QtBluetooth/qbluetooth.h> #include <QtBluetooth/qlowenergycharacteristic.h> #include "qlowenergycontroller.h" -#include "qlowenergyserviceprivate_p.h" - -#if QT_CONFIG(bluez) && !defined(QT_BLUEZ_NO_BTLE) -#include <QtBluetooth/QBluetoothSocket> -#elif defined(QT_ANDROID_BLUETOOTH) -#include <QtAndroidExtras/QAndroidJniObject> -#include "android/lowenergynotificationhub_p.h" -#elif defined(QT_WINRT_BLUETOOTH) -#include <wrl.h> -#include <windows.devices.bluetooth.h> -#endif - -#include <functional> +#include "qlowenergycontrollerbase_p.h" QT_BEGIN_NAMESPACE class QLowEnergyServiceData; -class QTimer; - -#if QT_CONFIG(bluez) && !defined(QT_BLUEZ_NO_BTLE) -class HciManager; -class LeCmacCalculator; -class QSocketNotifier; -class RemoteDeviceManager; -#elif defined(QT_ANDROID_BLUETOOTH) -class LowEnergyNotificationHub; -#elif defined(QT_WINRT_BLUETOOTH) -class QWinRTLowEnergyServiceHandler; -#endif extern void registerQLowEnergyControllerMetaType(); -typedef QMap<QBluetoothUuid, QSharedPointer<QLowEnergyServicePrivate> > ServiceDataMap; -class QLeAdvertiser; - -class QLowEnergyControllerPrivate : public QObject +class QLowEnergyControllerPrivateCommon : public QLowEnergyControllerPrivate { Q_OBJECT - Q_DECLARE_PUBLIC(QLowEnergyController) public: - QLowEnergyControllerPrivate(); - ~QLowEnergyControllerPrivate(); + QLowEnergyControllerPrivateCommon(); + ~QLowEnergyControllerPrivateCommon(); - void init(); + void init() override; - void setError(QLowEnergyController::Error newError); - bool isValidLocalAdapter(); + void connectToDevice() override; + void disconnectFromDevice() override; - void setState(QLowEnergyController::ControllerState newState); - - void connectToDevice(); - void disconnectFromDevice(); - - void discoverServices(); - void invalidateServices(); - - void discoverServiceDetails(const QBluetoothUuid &service); + void discoverServices() override; + void discoverServiceDetails(const QBluetoothUuid &service) override; void startAdvertising(const QLowEnergyAdvertisingParameters ¶ms, const QLowEnergyAdvertisingData &advertisingData, - const QLowEnergyAdvertisingData &scanResponseData); - void stopAdvertising(); - - void requestConnectionUpdate(const QLowEnergyConnectionParameters ¶ms); + const QLowEnergyAdvertisingData &scanResponseData) override; + void stopAdvertising() override; - // misc helpers - QSharedPointer<QLowEnergyServicePrivate> serviceForHandle( - QLowEnergyHandle handle); - QLowEnergyCharacteristic characteristicForHandle( - QLowEnergyHandle handle); - QLowEnergyDescriptor descriptorForHandle( - QLowEnergyHandle handle); - QLowEnergyService *addServiceHelper(const QLowEnergyServiceData &service); - - - quint16 updateValueOfCharacteristic(QLowEnergyHandle charHandle, - const QByteArray &value, - bool appendValue); - quint16 updateValueOfDescriptor(QLowEnergyHandle charHandle, - QLowEnergyHandle descriptorHandle, - const QByteArray &value, - bool appendValue); + void requestConnectionUpdate(const QLowEnergyConnectionParameters ¶ms) override; // read data void readCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service, - const QLowEnergyHandle charHandle); + const QLowEnergyHandle charHandle) override; void readDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service, const QLowEnergyHandle charHandle, - const QLowEnergyHandle descriptorHandle); + const QLowEnergyHandle descriptorHandle) override; // write data void writeCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service, const QLowEnergyHandle charHandle, - const QByteArray &newValue, QLowEnergyService::WriteMode mode); + const QByteArray &newValue, QLowEnergyService::WriteMode mode) override; void writeDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service, const QLowEnergyHandle charHandle, const QLowEnergyHandle descriptorHandle, - const QByteArray &newValue); + const QByteArray &newValue) override; void addToGenericAttributeList(const QLowEnergyServiceData &service, - QLowEnergyHandle startHandle); - - QBluetoothAddress remoteDevice; - QBluetoothAddress localAdapter; - QLowEnergyController::Role role; - - QString remoteName; - - QLowEnergyController::ControllerState state; - QLowEnergyController::Error error; - QString errorString; - - // list of all found service uuids on remote device - ServiceDataMap serviceList; - - QLowEnergyHandle lastLocalHandle; - // list of all service uuids on local peripheral device - ServiceDataMap localServices; - - struct Attribute { - Attribute() : handle(0) {} - - QLowEnergyHandle handle; - QLowEnergyHandle groupEndHandle; - QLowEnergyCharacteristic::PropertyTypes properties; - QBluetooth::AttAccessConstraints readConstraints; - QBluetooth::AttAccessConstraints writeConstraints; - QBluetoothUuid type; - QByteArray value; - int minLength; - int maxLength; - }; - QVector<Attribute> localAttributes; - - QLowEnergyController::RemoteAddressType addressType; - -private: -#if QT_CONFIG(bluez) && !defined(QT_BLUEZ_NO_BTLE) - quint16 connectionHandle = 0; - QBluetoothSocket *l2cpSocket; - struct Request { - quint8 command; - QByteArray payload; - // TODO reference below is ugly but until we know all commands and their - // requirements this is WIP - QVariant reference; - QVariant reference2; - }; - QQueue<Request> openRequests; - - struct WriteRequest { - WriteRequest() {} - WriteRequest(quint16 h, quint16 o, const QByteArray &v) - : handle(h), valueOffset(o), value(v) {} - quint16 handle; - quint16 valueOffset; - QByteArray value; - }; - QVector<WriteRequest> openPrepareWriteRequests; - - // Invariant: !scheduledIndications.isEmpty => indicationInFlight == true - QVector<QLowEnergyHandle> scheduledIndications; - bool indicationInFlight = false; - - struct TempClientConfigurationData { - TempClientConfigurationData(QLowEnergyServicePrivate::DescData *dd = nullptr, - QLowEnergyHandle chHndl = 0, QLowEnergyHandle coHndl = 0) - : descData(dd), charValueHandle(chHndl), configHandle(coHndl) {} - - QLowEnergyServicePrivate::DescData *descData; - QLowEnergyHandle charValueHandle; - QLowEnergyHandle configHandle; - }; - - struct ClientConfigurationData { - ClientConfigurationData(QLowEnergyHandle chHndl = 0, QLowEnergyHandle coHndl = 0, - quint16 val = 0) - : charValueHandle(chHndl), configHandle(coHndl), configValue(val) {} - - QLowEnergyHandle charValueHandle; - QLowEnergyHandle configHandle; - quint16 configValue; - bool charValueWasUpdated = false; - }; - QHash<quint64, QVector<ClientConfigurationData>> clientConfigData; - - struct SigningData { - SigningData() = default; - SigningData(const quint128 &csrk, quint32 signCounter = quint32(-1)) - : key(csrk), counter(signCounter) {} - - quint128 key; - quint32 counter = quint32(-1); - }; - QHash<quint64, SigningData> signingData; - LeCmacCalculator *cmacCalculator = nullptr; - - bool requestPending; - quint16 mtuSize; - int securityLevelValue; - bool encryptionChangePending; - bool receivedMtuExchangeRequest = false; - - HciManager *hciManager; - QLeAdvertiser *advertiser; - QSocketNotifier *serverSocketNotifier; - QTimer *requestTimer = nullptr; - RemoteDeviceManager* device1Manager = nullptr; - - /* - Defines the maximum number of milliseconds the implementation will - wait for requests that require a response. - - This addresses the problem that some non-conformant BTLE devices - do not implement the request/response system properly. In such cases - the queue system would hang forever. - - Once timeout has been triggered we gracefully continue with the next request. - Depending on the type of the timed out ATT command we either ignore it - or artifically trigger an error response to ensure the API gives the - appropriate response. Potentially this can cause problems when the - response for the dropped requests arrives very late. That's why a big warning - is printed about the compromised state when a timeout is triggered. - */ - int gattRequestTimeout = 20000; - - void handleConnectionRequest(); - void closeServerSocket(); - - bool isBonded() const; - QVector<TempClientConfigurationData> gatherClientConfigData(); - void storeClientConfigurations(); - void restoreClientConfigurations(); - - enum SigningKeyType { LocalSigningKey, RemoteSigningKey }; - void loadSigningDataIfNecessary(SigningKeyType keyType); - void storeSignCounter(SigningKeyType keyType) const; - QString signingKeySettingsGroup(SigningKeyType keyType) const; - QString keySettingsFilePath() const; - - void sendPacket(const QByteArray &packet); - void sendNextPendingRequest(); - void processReply(const Request &request, const QByteArray &reply); - - void sendReadByGroupRequest(QLowEnergyHandle start, QLowEnergyHandle end, - quint16 type); - void sendReadByTypeRequest(QSharedPointer<QLowEnergyServicePrivate> serviceData, - QLowEnergyHandle nextHandle, quint16 attributeType); - void sendReadValueRequest(QLowEnergyHandle attributeHandle, bool isDescriptor); - void readServiceValues(const QBluetoothUuid &service, - bool readCharacteristics); - void readServiceValuesByOffset(uint handleData, quint16 offset, - bool isLastValue); - - void discoverServiceDescriptors(const QBluetoothUuid &serviceUuid); - void discoverNextDescriptor(QSharedPointer<QLowEnergyServicePrivate> serviceData, - const QList<QLowEnergyHandle> pendingCharHandles, - QLowEnergyHandle startingHandle); - void processUnsolicitedReply(const QByteArray &msg); - void exchangeMTU(); - bool setSecurityLevel(int level); - int securityLevel() const; - void sendExecuteWriteRequest(const QLowEnergyHandle attrHandle, - const QByteArray &newValue, - bool isCancelation); - void sendNextPrepareWriteRequest(const QLowEnergyHandle handle, - const QByteArray &newValue, quint16 offset); - bool increaseEncryptLevelfRequired(quint8 errorCode); - - void resetController(); - - void handleAdvertisingError(); - - bool checkPacketSize(const QByteArray &packet, int minSize, int maxSize = -1); - bool checkHandle(const QByteArray &packet, QLowEnergyHandle handle); - bool checkHandlePair(quint8 request, QLowEnergyHandle startingHandle, - QLowEnergyHandle endingHandle); - - void handleExchangeMtuRequest(const QByteArray &packet); - void handleFindInformationRequest(const QByteArray &packet); - void handleFindByTypeValueRequest(const QByteArray &packet); - void handleReadByTypeRequest(const QByteArray &packet); - void handleReadRequest(const QByteArray &packet); - void handleReadBlobRequest(const QByteArray &packet); - void handleReadMultipleRequest(const QByteArray &packet); - void handleReadByGroupTypeRequest(const QByteArray &packet); - void handleWriteRequestOrCommand(const QByteArray &packet); - void handlePrepareWriteRequest(const QByteArray &packet); - void handleExecuteWriteRequest(const QByteArray &packet); - - void sendErrorResponse(quint8 request, quint16 handle, quint8 code); - - using ElemWriter = std::function<void(const Attribute &, char *&)>; - void sendListResponse(const QByteArray &packetStart, int elemSize, - const QVector<Attribute> &attributes, const ElemWriter &elemWriter); - - void sendNotification(QLowEnergyHandle handle); - void sendIndication(QLowEnergyHandle handle); - void sendNotificationOrIndication(quint8 opCode, QLowEnergyHandle handle); - void sendNextIndication(); - - void ensureUniformAttributes(QVector<Attribute> &attributes, const std::function<int(const Attribute &)> &getSize); - void ensureUniformUuidSizes(QVector<Attribute> &attributes); - void ensureUniformValueSizes(QVector<Attribute> &attributes); - - using AttributePredicate = std::function<bool(const Attribute &)>; - QVector<Attribute> getAttributes(QLowEnergyHandle startHandle, QLowEnergyHandle endHandle, - const AttributePredicate &attributePredicate = [](const Attribute &) { return true; }); - - int checkPermissions(const Attribute &attr, QLowEnergyCharacteristic::PropertyType type); - int checkReadPermissions(const Attribute &attr); - int checkReadPermissions(QVector<Attribute> &attributes); - - bool verifyMac(const QByteArray &message, const quint128 &csrk, quint32 signCounter, - quint64 expectedMac); - - void updateLocalAttributeValue( - QLowEnergyHandle handle, - const QByteArray &value, - QLowEnergyCharacteristic &characteristic, - QLowEnergyDescriptor &descriptor); - - void writeCharacteristicForPeripheral( - QLowEnergyServicePrivate::CharData &charData, - const QByteArray &newValue); - void writeCharacteristicForCentral(const QSharedPointer<QLowEnergyServicePrivate> &service, - QLowEnergyHandle charHandle, - QLowEnergyHandle valueHandle, - const QByteArray &newValue, - QLowEnergyService::WriteMode mode); - - void writeDescriptorForPeripheral( - const QSharedPointer<QLowEnergyServicePrivate> &service, - const QLowEnergyHandle charHandle, - const QLowEnergyHandle descriptorHandle, - const QByteArray &newValue); - void writeDescriptorForCentral( - const QLowEnergyHandle charHandle, - const QLowEnergyHandle descriptorHandle, - const QByteArray &newValue); - - void restartRequestTimer(); - void establishL2cpClientSocket(); - void createServicesForCentralIfRequired(); - -private slots: - void l2cpConnected(); - void l2cpDisconnected(); - void l2cpErrorChanged(QBluetoothSocket::SocketError); - void l2cpReadyRead(); - void encryptionChangedEvent(const QBluetoothAddress&, bool); - void handleGattRequestTimeout(); - void activeConnectionTerminationDone(); -#elif defined(QT_ANDROID_BLUETOOTH) - LowEnergyNotificationHub *hub; - -private slots: - void connectionUpdated(QLowEnergyController::ControllerState newState, - QLowEnergyController::Error errorCode); - void servicesDiscovered(QLowEnergyController::Error errorCode, - const QString &foundServices); - void serviceDetailsDiscoveryFinished(const QString& serviceUuid, - int startHandle, int endHandle); - void characteristicRead(const QBluetoothUuid &serviceUuid, int handle, - const QBluetoothUuid &charUuid, int properties, - const QByteArray& data); - void descriptorRead(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid, - int handle, const QBluetoothUuid &descUuid, const QByteArray &data); - void characteristicWritten(int charHandle, const QByteArray &data, - QLowEnergyService::ServiceError errorCode); - void descriptorWritten(int descHandle, const QByteArray &data, - QLowEnergyService::ServiceError errorCode); - void serverDescriptorWritten(const QAndroidJniObject &jniDesc, const QByteArray &newValue); - void characteristicChanged(int charHandle, const QByteArray &data); - void serverCharacteristicChanged(const QAndroidJniObject &jniChar, const QByteArray &newValue); - void serviceError(int attributeHandle, QLowEnergyService::ServiceError errorCode); - void advertisementError(int errorCode); - -private: - void peripheralConnectionUpdated(QLowEnergyController::ControllerState newState, - QLowEnergyController::Error errorCode); - void centralConnectionUpdated(QLowEnergyController::ControllerState newState, - QLowEnergyController::Error errorCode); - -#elif defined(QT_WINRT_BLUETOOTH) -private slots: - void characteristicChanged(int charHandle, const QByteArray &data); - -private: - Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::IBluetoothLEDevice> mDevice; - EventRegistrationToken mStatusChangedToken; - struct ValueChangedEntry { - ValueChangedEntry() {} - ValueChangedEntry(Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattCharacteristic> c, - EventRegistrationToken t) - : characteristic(c) - , token(t) - { - } - - Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattCharacteristic> characteristic; - EventRegistrationToken token; - }; - QVector<ValueChangedEntry> mValueChangedTokens; - - Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattDeviceService> getNativeService(const QBluetoothUuid &serviceUuid); - Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattCharacteristic> getNativeCharacteristic(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid); - - void registerForValueChanges(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid); - - void obtainIncludedServices(QSharedPointer<QLowEnergyServicePrivate> servicePointer, - Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattDeviceService> nativeService); -#endif -private: - QLowEnergyController *q_ptr; - + QLowEnergyHandle startHandle) override; }; -Q_DECLARE_TYPEINFO(QLowEnergyControllerPrivate::Attribute, Q_MOVABLE_TYPE); - QT_END_NAMESPACE -#endif // QT_OSX_BLUETOOTH || QT_IOS_BLUETOOTH - #endif // QLOWENERGYCONTROLLERPRIVATE_P_H diff --git a/src/bluetooth/qlowenergycontroller_winrt.cpp b/src/bluetooth/qlowenergycontroller_winrt.cpp index c9c30b44..628f1195 100644 --- a/src/bluetooth/qlowenergycontroller_winrt.cpp +++ b/src/bluetooth/qlowenergycontroller_winrt.cpp @@ -37,7 +37,10 @@ ** ****************************************************************************/ -#include "qlowenergycontroller_p.h" +#include "qlowenergycontroller_winrt_p.h" + +#include <QtBluetooth/QLowEnergyCharacteristicData> +#include <QtBluetooth/QLowEnergyDescriptorData> #ifdef CLASSIC_APP_BUILD #define Q_OS_WINRT @@ -275,18 +278,15 @@ signals: QLowEnergyHandle startHandle, QLowEnergyHandle endHandle); }; -QLowEnergyControllerPrivate::QLowEnergyControllerPrivate() - : QObject(), - state(QLowEnergyController::UnconnectedState), - error(QLowEnergyController::NoError) +QLowEnergyControllerPrivateWinRT::QLowEnergyControllerPrivateWinRT() + : QLowEnergyControllerPrivate() { qCDebug(QT_BT_WINRT) << __FUNCTION__; - qRegisterMetaType<QLowEnergyCharacteristic>(); - qRegisterMetaType<QLowEnergyDescriptor>(); + registerQLowEnergyControllerMetaType(); } -QLowEnergyControllerPrivate::~QLowEnergyControllerPrivate() +QLowEnergyControllerPrivateWinRT::~QLowEnergyControllerPrivateWinRT() { if (mDevice && mStatusChangedToken.value) mDevice->remove_ConnectionStatusChanged(mStatusChangedToken); @@ -296,11 +296,11 @@ QLowEnergyControllerPrivate::~QLowEnergyControllerPrivate() entry.characteristic->remove_ValueChanged(entry.token); } -void QLowEnergyControllerPrivate::init() +void QLowEnergyControllerPrivateWinRT::init() { } -void QLowEnergyControllerPrivate::connectToDevice() +void QLowEnergyControllerPrivateWinRT::connectToDevice() { qCDebug(QT_BT_WINRT) << __FUNCTION__; Q_Q(QLowEnergyController); @@ -428,7 +428,7 @@ void QLowEnergyControllerPrivate::connectToDevice() } } -void QLowEnergyControllerPrivate::disconnectFromDevice() +void QLowEnergyControllerPrivateWinRT::disconnectFromDevice() { qCDebug(QT_BT_WINRT) << __FUNCTION__; Q_Q(QLowEnergyController); @@ -440,7 +440,7 @@ void QLowEnergyControllerPrivate::disconnectFromDevice() } } -ComPtr<IGattDeviceService> QLowEnergyControllerPrivate::getNativeService(const QBluetoothUuid &serviceUuid) +ComPtr<IGattDeviceService> QLowEnergyControllerPrivateWinRT::getNativeService(const QBluetoothUuid &serviceUuid) { ComPtr<IGattDeviceService> deviceService; HRESULT hr; @@ -450,7 +450,7 @@ ComPtr<IGattDeviceService> QLowEnergyControllerPrivate::getNativeService(const Q return deviceService; } -ComPtr<IGattCharacteristic> QLowEnergyControllerPrivate::getNativeCharacteristic(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid) +ComPtr<IGattCharacteristic> QLowEnergyControllerPrivateWinRT::getNativeCharacteristic(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid) { ComPtr<IGattDeviceService> service = getNativeService(serviceUuid); if (!service) @@ -465,7 +465,7 @@ ComPtr<IGattCharacteristic> QLowEnergyControllerPrivate::getNativeCharacteristic return characteristic; } -void QLowEnergyControllerPrivate::registerForValueChanges(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid) +void QLowEnergyControllerPrivateWinRT::registerForValueChanges(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid) { qCDebug(QT_BT_WINRT) << "Registering characteristic" << charUuid << "in service" << serviceUuid << "for value changes"; @@ -498,7 +498,7 @@ void QLowEnergyControllerPrivate::registerForValueChanges(const QBluetoothUuid & << serviceUuid << "registered for value changes"; } -void QLowEnergyControllerPrivate::obtainIncludedServices(QSharedPointer<QLowEnergyServicePrivate> servicePointer, +void QLowEnergyControllerPrivateWinRT::obtainIncludedServices(QSharedPointer<QLowEnergyServicePrivate> servicePointer, ComPtr<IGattDeviceService> service) { Q_Q(QLowEnergyController); @@ -542,7 +542,7 @@ void QLowEnergyControllerPrivate::obtainIncludedServices(QSharedPointer<QLowEner } } -void QLowEnergyControllerPrivate::discoverServices() +void QLowEnergyControllerPrivateWinRT::discoverServices() { Q_Q(QLowEnergyController); @@ -584,7 +584,7 @@ void QLowEnergyControllerPrivate::discoverServices() emit q->discoveryFinished(); } -void QLowEnergyControllerPrivate::discoverServiceDetails(const QBluetoothUuid &service) +void QLowEnergyControllerPrivateWinRT::discoverServiceDetails(const QBluetoothUuid &service) { qCDebug(QT_BT_WINRT) << __FUNCTION__ << service; if (!serviceList.contains(service)) { @@ -674,23 +674,23 @@ void QLowEnergyControllerPrivate::discoverServiceDetails(const QBluetoothUuid &s thread->start(); } -void QLowEnergyControllerPrivate::startAdvertising(const QLowEnergyAdvertisingParameters &, const QLowEnergyAdvertisingData &, const QLowEnergyAdvertisingData &) +void QLowEnergyControllerPrivateWinRT::startAdvertising(const QLowEnergyAdvertisingParameters &, const QLowEnergyAdvertisingData &, const QLowEnergyAdvertisingData &) { setError(QLowEnergyController::AdvertisingError); Q_UNIMPLEMENTED(); } -void QLowEnergyControllerPrivate::stopAdvertising() +void QLowEnergyControllerPrivateWinRT::stopAdvertising() { Q_UNIMPLEMENTED(); } -void QLowEnergyControllerPrivate::requestConnectionUpdate(const QLowEnergyConnectionParameters &) +void QLowEnergyControllerPrivateWinRT::requestConnectionUpdate(const QLowEnergyConnectionParameters &) { Q_UNIMPLEMENTED(); } -void QLowEnergyControllerPrivate::readCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service, +void QLowEnergyControllerPrivateWinRT::readCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service, const QLowEnergyHandle charHandle) { qCDebug(QT_BT_WINRT) << __FUNCTION__ << service << charHandle; @@ -754,7 +754,7 @@ void QLowEnergyControllerPrivate::readCharacteristic(const QSharedPointer<QLowEn Q_ASSERT_SUCCEEDED(hr); } -void QLowEnergyControllerPrivate::readDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service, +void QLowEnergyControllerPrivateWinRT::readDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service, const QLowEnergyHandle charHandle, const QLowEnergyHandle descHandle) { @@ -885,7 +885,7 @@ void QLowEnergyControllerPrivate::readDescriptor(const QSharedPointer<QLowEnergy Q_ASSERT_SUCCEEDED(hr); } -void QLowEnergyControllerPrivate::writeCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service, +void QLowEnergyControllerPrivateWinRT::writeCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service, const QLowEnergyHandle charHandle, const QByteArray &newValue, QLowEnergyService::WriteMode mode) @@ -973,7 +973,7 @@ void QLowEnergyControllerPrivate::writeCharacteristic(const QSharedPointer<QLowE Q_ASSERT_SUCCEEDED(hr); } -void QLowEnergyControllerPrivate::writeDescriptor( +void QLowEnergyControllerPrivateWinRT::writeDescriptor( const QSharedPointer<QLowEnergyServicePrivate> service, const QLowEnergyHandle charHandle, const QLowEnergyHandle descHandle, @@ -1118,12 +1118,12 @@ void QLowEnergyControllerPrivate::writeDescriptor( } -void QLowEnergyControllerPrivate::addToGenericAttributeList(const QLowEnergyServiceData &, QLowEnergyHandle) +void QLowEnergyControllerPrivateWinRT::addToGenericAttributeList(const QLowEnergyServiceData &, QLowEnergyHandle) { Q_UNIMPLEMENTED(); } -void QLowEnergyControllerPrivate::characteristicChanged( +void QLowEnergyControllerPrivateWinRT::characteristicChanged( int charHandle, const QByteArray &data) { QSharedPointer<QLowEnergyServicePrivate> service = diff --git a/src/bluetooth/qlowenergycontroller_winrt_p.h b/src/bluetooth/qlowenergycontroller_winrt_p.h new file mode 100644 index 00000000..7edc4702 --- /dev/null +++ b/src/bluetooth/qlowenergycontroller_winrt_p.h @@ -0,0 +1,149 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtBluetooth module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLOWENERGYCONTROLLERPRIVATEWINRT_P_H +#define QLOWENERGYCONTROLLERPRIVATEWINRT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <qglobal.h> +#include <QtCore/QQueue> +#include <QtCore/QVector> +#include <QtBluetooth/qbluetooth.h> +#include <QtBluetooth/qlowenergycharacteristic.h> +#include <QtBluetooth/qlowenergyservicedata.h> +#include "qlowenergycontroller.h" +#include "qlowenergycontrollerbase_p.h" + +#include <wrl.h> +#include <windows.devices.bluetooth.h> + +#include <functional> + +QT_BEGIN_NAMESPACE + +class QLowEnergyServiceData; +class QTimer; +class QWinRTLowEnergyServiceHandler; + +extern void registerQLowEnergyControllerMetaType(); + +class QLowEnergyControllerPrivateWinRT : public QLowEnergyControllerPrivate +{ + Q_OBJECT +public: + QLowEnergyControllerPrivateWinRT(); + ~QLowEnergyControllerPrivateWinRT(); + + void init() override; + + void connectToDevice() override; + void disconnectFromDevice() override; + + void discoverServices() override; + void discoverServiceDetails(const QBluetoothUuid &service) override; + + void startAdvertising(const QLowEnergyAdvertisingParameters ¶ms, + const QLowEnergyAdvertisingData &advertisingData, + const QLowEnergyAdvertisingData &scanResponseData) override; + void stopAdvertising() override; + + void requestConnectionUpdate(const QLowEnergyConnectionParameters ¶ms) override; + + // read data + void readCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service, + const QLowEnergyHandle charHandle) override; + void readDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle) override; + + // write data + void writeCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service, + const QLowEnergyHandle charHandle, + const QByteArray &newValue, QLowEnergyService::WriteMode mode) override; + void writeDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service, + const QLowEnergyHandle charHandle, + const QLowEnergyHandle descriptorHandle, + const QByteArray &newValue) override; + + void addToGenericAttributeList(const QLowEnergyServiceData &service, + QLowEnergyHandle startHandle) override; + +private slots: + void characteristicChanged(int charHandle, const QByteArray &data); + +private: + Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::IBluetoothLEDevice> mDevice; + EventRegistrationToken mStatusChangedToken; + struct ValueChangedEntry { + ValueChangedEntry() {} + ValueChangedEntry(Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattCharacteristic> c, + EventRegistrationToken t) + : characteristic(c) + , token(t) + { + } + + Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattCharacteristic> characteristic; + EventRegistrationToken token; + }; + QVector<ValueChangedEntry> mValueChangedTokens; + + Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattDeviceService> getNativeService(const QBluetoothUuid &serviceUuid); + Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattCharacteristic> getNativeCharacteristic(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid); + + void registerForValueChanges(const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid); + + void obtainIncludedServices(QSharedPointer<QLowEnergyServicePrivate> servicePointer, + Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattDeviceService> nativeService); + +}; + +QT_END_NAMESPACE + +#endif // QLOWENERGYCONTROLLERPRIVATEWINRT_P_H diff --git a/src/bluetooth/qlowenergycontrollerbase.cpp b/src/bluetooth/qlowenergycontrollerbase.cpp new file mode 100644 index 00000000..687f5b9e --- /dev/null +++ b/src/bluetooth/qlowenergycontrollerbase.cpp @@ -0,0 +1,316 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtBluetooth module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qlowenergycontrollerbase_p.h" + +#include <QtCore/QLoggingCategory> + +#include <QtBluetooth/QBluetoothLocalDevice> +#include <QtBluetooth/QLowEnergyCharacteristicData> +#include <QtBluetooth/QLowEnergyDescriptorData> +#include <QtBluetooth/QLowEnergyServiceData> + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(QT_BT) + +QLowEnergyControllerPrivate::QLowEnergyControllerPrivate() + : QObject() +{ +} + +QLowEnergyControllerPrivate::~QLowEnergyControllerPrivate() +{ +} + +bool QLowEnergyControllerPrivate::isValidLocalAdapter() +{ +#ifdef QT_WINRT_BLUETOOTH + return true; +#endif + if (localAdapter.isNull()) + return false; + + const QList<QBluetoothHostInfo> foundAdapters = QBluetoothLocalDevice::allDevices(); + bool adapterFound = false; + + foreach (const QBluetoothHostInfo &info, foundAdapters) { + if (info.address() == localAdapter) { + adapterFound = true; + break; + } + } + + return adapterFound; +} + + +void QLowEnergyControllerPrivate::setError( + QLowEnergyController::Error newError) +{ + Q_Q(QLowEnergyController); + error = newError; + + switch (newError) { + case QLowEnergyController::UnknownRemoteDeviceError: + errorString = QLowEnergyController::tr("Remote device cannot be found"); + break; + case QLowEnergyController::InvalidBluetoothAdapterError: + errorString = QLowEnergyController::tr("Cannot find local adapter"); + break; + case QLowEnergyController::NetworkError: + errorString = QLowEnergyController::tr("Error occurred during connection I/O"); + break; + case QLowEnergyController::ConnectionError: + errorString = QLowEnergyController::tr("Error occurred trying to connect to remote device."); + break; + case QLowEnergyController::AdvertisingError: + errorString = QLowEnergyController::tr("Error occurred trying to start advertising"); + break; + case QLowEnergyController::RemoteHostClosedError: + errorString = QLowEnergyController::tr("Remote device closed the connection"); + break; + case QLowEnergyController::NoError: + return; + default: + case QLowEnergyController::UnknownError: + errorString = QLowEnergyController::tr("Unknown Error"); + break; + } + + emit q->error(newError); +} + +void QLowEnergyControllerPrivate::setState( + QLowEnergyController::ControllerState newState) +{ + Q_Q(QLowEnergyController); + if (state == newState) + return; + + state = newState; + if (state == QLowEnergyController::UnconnectedState + && role == QLowEnergyController::PeripheralRole) { + remoteDevice.clear(); + } + emit q->stateChanged(state); +} + +QSharedPointer<QLowEnergyServicePrivate> QLowEnergyControllerPrivate::serviceForHandle( + QLowEnergyHandle handle) +{ + ServiceDataMap ¤tList = serviceList; + if (role == QLowEnergyController::PeripheralRole) + currentList = localServices; + + const QList<QSharedPointer<QLowEnergyServicePrivate>> values = currentList.values(); + for (auto service: values) + if (service->startHandle <= handle && handle <= service->endHandle) + return service; + + return QSharedPointer<QLowEnergyServicePrivate>(); +} + +/*! + Returns a valid characteristic if the given handle is the + handle of the characteristic itself or one of its descriptors + */ +QLowEnergyCharacteristic QLowEnergyControllerPrivate::characteristicForHandle( + QLowEnergyHandle handle) +{ + QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(handle); + if (service.isNull()) + return QLowEnergyCharacteristic(); + + if (service->characteristicList.isEmpty()) + return QLowEnergyCharacteristic(); + + // check whether it is the handle of a characteristic header + if (service->characteristicList.contains(handle)) + return QLowEnergyCharacteristic(service, handle); + + // check whether it is the handle of the characteristic value or its descriptors + QList<QLowEnergyHandle> charHandles = service->characteristicList.keys(); + std::sort(charHandles.begin(), charHandles.end()); + for (int i = charHandles.size() - 1; i >= 0; i--) { + if (charHandles.at(i) > handle) + continue; + + return QLowEnergyCharacteristic(service, charHandles.at(i)); + } + + return QLowEnergyCharacteristic(); +} + +/*! + Returns a valid descriptor if \a handle belongs to a descriptor; + otherwise an invalid one. + */ +QLowEnergyDescriptor QLowEnergyControllerPrivate::descriptorForHandle( + QLowEnergyHandle handle) +{ + const QLowEnergyCharacteristic matchingChar = characteristicForHandle(handle); + if (!matchingChar.isValid()) + return QLowEnergyDescriptor(); + + const QLowEnergyServicePrivate::CharData charData = matchingChar. + d_ptr->characteristicList[matchingChar.attributeHandle()]; + + if (charData.descriptorList.contains(handle)) + return QLowEnergyDescriptor(matchingChar.d_ptr, matchingChar.attributeHandle(), + handle); + + return QLowEnergyDescriptor(); +} + +/*! + Returns the length of the updated characteristic value. + */ +quint16 QLowEnergyControllerPrivate::updateValueOfCharacteristic( + QLowEnergyHandle charHandle,const QByteArray &value, bool appendValue) +{ + QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(charHandle); + if (!service.isNull()) { + CharacteristicDataMap::iterator charIt = service->characteristicList.find(charHandle); + if (charIt != service->characteristicList.end()) { + QLowEnergyServicePrivate::CharData &charDetails = charIt.value(); + + if (appendValue) + charDetails.value += value; + else + charDetails.value = value; + + return charDetails.value.size(); + } + } + + return 0; +} + +/*! + Returns the length of the updated descriptor value. + */ +quint16 QLowEnergyControllerPrivate::updateValueOfDescriptor( + QLowEnergyHandle charHandle, QLowEnergyHandle descriptorHandle, + const QByteArray &value, bool appendValue) +{ + QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(charHandle); + if (!service.isNull()) { + CharacteristicDataMap::iterator charIt = service->characteristicList.find(charHandle); + if (charIt != service->characteristicList.end()) { + QLowEnergyServicePrivate::CharData &charDetails = charIt.value(); + + DescriptorDataMap::iterator descIt = charDetails.descriptorList.find(descriptorHandle); + if (descIt != charDetails.descriptorList.end()) { + QLowEnergyServicePrivate::DescData &descDetails = descIt.value(); + + if (appendValue) + descDetails.value += value; + else + descDetails.value = value; + + return descDetails.value.size(); + } + } + } + + return 0; +} + +void QLowEnergyControllerPrivate::invalidateServices() +{ + foreach (const QSharedPointer<QLowEnergyServicePrivate> service, serviceList.values()) { + service->setController(0); + service->setState(QLowEnergyService::InvalidService); + } + + serviceList.clear(); +} + +QLowEnergyService *QLowEnergyControllerPrivate::addServiceHelper( + const QLowEnergyServiceData &service) +{ + // Spec says services "should" be grouped by uuid length (16-bit first, then 128-bit). + // Since this is not mandatory, we ignore it here and let the caller take responsibility + // for it. + + const auto servicePrivate = QSharedPointer<QLowEnergyServicePrivate>::create(); + servicePrivate->state = QLowEnergyService::LocalService; + servicePrivate->setController(this); + servicePrivate->uuid = service.uuid(); + servicePrivate->type = service.type() == QLowEnergyServiceData::ServiceTypePrimary + ? QLowEnergyService::PrimaryService : QLowEnergyService::IncludedService; + foreach (QLowEnergyService * const includedService, service.includedServices()) { + servicePrivate->includedServices << includedService->serviceUuid(); + includedService->d_ptr->type |= QLowEnergyService::IncludedService; + } + + // Spec v4.2, Vol 3, Part G, Section 3. + const QLowEnergyHandle oldLastHandle = this->lastLocalHandle; + servicePrivate->startHandle = ++this->lastLocalHandle; // Service declaration. + this->lastLocalHandle += servicePrivate->includedServices.count(); // Include declarations. + foreach (const QLowEnergyCharacteristicData &cd, service.characteristics()) { + const QLowEnergyHandle declHandle = ++this->lastLocalHandle; + QLowEnergyServicePrivate::CharData charData; + charData.valueHandle = ++this->lastLocalHandle; + charData.uuid = cd.uuid(); + charData.properties = cd.properties(); + charData.value = cd.value(); + foreach (const QLowEnergyDescriptorData &dd, cd.descriptors()) { + QLowEnergyServicePrivate::DescData descData; + descData.uuid = dd.uuid(); + descData.value = dd.value(); + charData.descriptorList.insert(++this->lastLocalHandle, descData); + } + servicePrivate->characteristicList.insert(declHandle, charData); + } + servicePrivate->endHandle = this->lastLocalHandle; + const bool handleOverflow = this->lastLocalHandle <= oldLastHandle; + if (handleOverflow) { + qCWarning(QT_BT) << "Not enough attribute handles left to create this service"; + this->lastLocalHandle = oldLastHandle; + return nullptr; + } + + this->localServices.insert(servicePrivate->uuid, servicePrivate); + this->addToGenericAttributeList(service, servicePrivate->startHandle); + return new QLowEnergyService(servicePrivate); +} + +QT_END_NAMESPACE diff --git a/src/bluetooth/qlowenergycontrollerbase_p.h b/src/bluetooth/qlowenergycontrollerbase_p.h new file mode 100644 index 00000000..a8d1c676 --- /dev/null +++ b/src/bluetooth/qlowenergycontrollerbase_p.h @@ -0,0 +1,186 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtBluetooth module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLOWENERGYCONTROLLERPRIVATEBASE_P_H +#define QLOWENERGYCONTROLLERPRIVATEBASE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#if defined(QT_OSX_BLUETOOTH) || defined(QT_IOS_BLUETOOTH) + +#include <QtCore/qglobal.h> +#include <QtCore/qobject.h> + +QT_BEGIN_NAMESPACE + +class QLowEnergyControllerPrivate : public QObject +{ +public: + // This class is required to make shared pointer machinery and + // moc (== Obj-C syntax) happy on both OS X and iOS. +}; + +QT_END_NAMESPACE + +#else + +#include <qglobal.h> +#include <QtCore/qobject.h> + +#include <QtBluetooth/qlowenergycontroller.h> + +#include "qlowenergyserviceprivate_p.h" + +QT_BEGIN_NAMESPACE + +typedef QMap<QBluetoothUuid, QSharedPointer<QLowEnergyServicePrivate> > ServiceDataMap; + +class QLowEnergyControllerPrivate : public QObject +{ + Q_OBJECT +public: + // This class is required to enable selection of multiple + // alternative QLowEnergyControllerPrivate implementations on BlueZ. + // Bluez has a low level ATT protocol stack implementation and a DBus + // implementation. + + QLowEnergyControllerPrivate(); + virtual ~QLowEnergyControllerPrivate(); + + // interface definition + virtual void init() = 0; + virtual void connectToDevice() = 0; + virtual void disconnectFromDevice() = 0; + + virtual void discoverServices() = 0; + virtual void discoverServiceDetails(const QBluetoothUuid &/*service*/) = 0; + + virtual void readCharacteristic( + const QSharedPointer<QLowEnergyServicePrivate> /*service*/, + const QLowEnergyHandle /*charHandle*/) = 0; + virtual void readDescriptor( + const QSharedPointer<QLowEnergyServicePrivate> /*service*/, + const QLowEnergyHandle /*charHandle*/, + const QLowEnergyHandle /*descriptorHandle*/) = 0; + + virtual void writeCharacteristic( + const QSharedPointer<QLowEnergyServicePrivate> /*service*/, + const QLowEnergyHandle /*charHandle*/, + const QByteArray &/*newValue*/, + QLowEnergyService::WriteMode /*writeMode*/) = 0; + virtual void writeDescriptor( + const QSharedPointer<QLowEnergyServicePrivate> /*service*/, + const QLowEnergyHandle /*charHandle*/, + const QLowEnergyHandle /*descriptorHandle*/, + const QByteArray &/*newValue*/) = 0; + + virtual void startAdvertising( + const QLowEnergyAdvertisingParameters &/* params */, + const QLowEnergyAdvertisingData &/* advertisingData */, + const QLowEnergyAdvertisingData &/* scanResponseData */) = 0; + virtual void stopAdvertising() = 0; + + virtual void requestConnectionUpdate( + const QLowEnergyConnectionParameters & /* params */) = 0; + virtual void addToGenericAttributeList( + const QLowEnergyServiceData &/* service */, + QLowEnergyHandle /* startHandle */) = 0; + + + virtual QLowEnergyService *addServiceHelper( + const QLowEnergyServiceData &service); + + + // common backend methods + bool isValidLocalAdapter(); + void setError(QLowEnergyController::Error newError); + void setState(QLowEnergyController::ControllerState newState); + + // public variables + QLowEnergyController::Role role; + QLowEnergyController::RemoteAddressType addressType; + + // list of all found service uuids on remote device + ServiceDataMap serviceList; + // list of all found service uuids on local peripheral device + ServiceDataMap localServices; + + //common helper functions + QSharedPointer<QLowEnergyServicePrivate> serviceForHandle(QLowEnergyHandle handle); + QLowEnergyCharacteristic characteristicForHandle(QLowEnergyHandle handle); + QLowEnergyDescriptor descriptorForHandle(QLowEnergyHandle handle); + quint16 updateValueOfCharacteristic(QLowEnergyHandle charHandle, + const QByteArray &value, + bool appendValue); + quint16 updateValueOfDescriptor(QLowEnergyHandle charHandle, + QLowEnergyHandle descriptorHandle, + const QByteArray &value, + bool appendValue); + void invalidateServices(); + +protected: + QLowEnergyController::ControllerState state = QLowEnergyController::UnconnectedState; + QLowEnergyController::Error error = QLowEnergyController::NoError; + QString errorString; + + QBluetoothAddress remoteDevice; + QBluetoothAddress localAdapter; + + QLowEnergyHandle lastLocalHandle{}; + + QString remoteName; // device name of the remote + + Q_DECLARE_PUBLIC(QLowEnergyController) + QLowEnergyController *q_ptr; +}; + +QT_END_NAMESPACE + +#endif //defined(QT_OSX_BLUETOOTH) || defined(QT_IOS_BLUETOOTH) + +#endif // QLOWENERGYCONTROLLERPRIVATEBASE_P_H diff --git a/src/bluetooth/qlowenergydescriptor.h b/src/bluetooth/qlowenergydescriptor.h index 9e71fc56..fca1be76 100644 --- a/src/bluetooth/qlowenergydescriptor.h +++ b/src/bluetooth/qlowenergydescriptor.h @@ -79,7 +79,12 @@ protected: friend class QLowEnergyCharacteristic; friend class QLowEnergyService; friend class QLowEnergyControllerPrivate; + friend class QLowEnergyControllerPrivateAndroid; + friend class QLowEnergyControllerPrivateBluez; + friend class QLowEnergyControllerPrivateBluezDBus; + friend class QLowEnergyControllerPrivateCommon; friend class QLowEnergyControllerPrivateOSX; + friend class QLowEnergyControllerPrivateWinRT; QLowEnergyDescriptorPrivate *data; QLowEnergyDescriptor(QSharedPointer<QLowEnergyServicePrivate> p, diff --git a/src/bluetooth/qlowenergyservice.cpp b/src/bluetooth/qlowenergyservice.cpp index 9d3129fd..39de9d01 100644 --- a/src/bluetooth/qlowenergyservice.cpp +++ b/src/bluetooth/qlowenergyservice.cpp @@ -44,7 +44,7 @@ #include <algorithm> -#include "qlowenergycontroller_p.h" +#include "qlowenergycontrollerbase_p.h" #include "qlowenergyserviceprivate_p.h" QT_BEGIN_NAMESPACE @@ -380,23 +380,21 @@ QLowEnergyService::QLowEnergyService(QSharedPointer<QLowEnergyServicePrivate> p, qRegisterMetaType<QLowEnergyService::ServiceError>(); qRegisterMetaType<QLowEnergyService::ServiceType>(); qRegisterMetaType<QLowEnergyService::WriteMode>(); - qRegisterMetaType<QLowEnergyCharacteristic>(); - qRegisterMetaType<QLowEnergyDescriptor>(); - - connect(p.data(), SIGNAL(error(QLowEnergyService::ServiceError)), - this, SIGNAL(error(QLowEnergyService::ServiceError))); - connect(p.data(), SIGNAL(stateChanged(QLowEnergyService::ServiceState)), - this, SIGNAL(stateChanged(QLowEnergyService::ServiceState))); - connect(p.data(), SIGNAL(characteristicChanged(QLowEnergyCharacteristic,QByteArray)), - this, SIGNAL(characteristicChanged(QLowEnergyCharacteristic,QByteArray))); - connect(p.data(), SIGNAL(characteristicWritten(QLowEnergyCharacteristic,QByteArray)), - this, SIGNAL(characteristicWritten(QLowEnergyCharacteristic,QByteArray))); - connect(p.data(), SIGNAL(descriptorWritten(QLowEnergyDescriptor,QByteArray)), - this, SIGNAL(descriptorWritten(QLowEnergyDescriptor,QByteArray))); - connect(p.data(), SIGNAL(characteristicRead(QLowEnergyCharacteristic,QByteArray)), - this, SIGNAL(characteristicRead(QLowEnergyCharacteristic,QByteArray))); - connect(p.data(), SIGNAL(descriptorRead(QLowEnergyDescriptor,QByteArray)), - this, SIGNAL(descriptorRead(QLowEnergyDescriptor,QByteArray))); + + connect(p.data(), &QLowEnergyServicePrivate::error, + this, QOverload<QLowEnergyService::ServiceError>::of(&QLowEnergyService::error)); + connect(p.data(), &QLowEnergyServicePrivate::stateChanged, + this, &QLowEnergyService::stateChanged); + connect(p.data(), &QLowEnergyServicePrivate::characteristicChanged, + this, &QLowEnergyService::characteristicChanged); + connect(p.data(), &QLowEnergyServicePrivate::characteristicWritten, + this, &QLowEnergyService::characteristicWritten); + connect(p.data(), &QLowEnergyServicePrivate::descriptorWritten, + this, &QLowEnergyService::descriptorWritten); + connect(p.data(), &QLowEnergyServicePrivate::characteristicRead, + this, &QLowEnergyService::characteristicRead); + connect(p.data(), &QLowEnergyServicePrivate::descriptorRead, + this, &QLowEnergyService::descriptorRead); } /*! @@ -632,7 +630,7 @@ void QLowEnergyService::readCharacteristic( { Q_D(QLowEnergyService); - if (d->controller == Q_NULLPTR || state() != ServiceDiscovered || !contains(characteristic)) { + if (d->controller == nullptr || state() != ServiceDiscovered || !contains(characteristic)) { d->setError(QLowEnergyService::OperationError); return; } @@ -703,7 +701,7 @@ void QLowEnergyService::writeCharacteristic( //TODO check behavior when writing to WriteSigned characteristic Q_D(QLowEnergyService); - if (d->controller == Q_NULLPTR + if (d->controller == nullptr || (d->controller->role == QLowEnergyController::CentralRole && state() != ServiceDiscovered) || !contains(characteristic)) { @@ -762,7 +760,7 @@ void QLowEnergyService::readDescriptor( { Q_D(QLowEnergyService); - if (d->controller == Q_NULLPTR || state() != ServiceDiscovered || !contains(descriptor)) { + if (d->controller == nullptr || state() != ServiceDiscovered || !contains(descriptor)) { d->setError(QLowEnergyService::OperationError); return; } @@ -804,7 +802,7 @@ void QLowEnergyService::writeDescriptor(const QLowEnergyDescriptor &descriptor, { Q_D(QLowEnergyService); - if (d->controller == Q_NULLPTR + if (d->controller == nullptr || (d->controller->role == QLowEnergyController::CentralRole && state() != ServiceDiscovered) || !contains(descriptor)) { diff --git a/src/bluetooth/qlowenergyservice.h b/src/bluetooth/qlowenergyservice.h index f138459f..f413e7f7 100644 --- a/src/bluetooth/qlowenergyservice.h +++ b/src/bluetooth/qlowenergyservice.h @@ -47,7 +47,7 @@ QT_BEGIN_NAMESPACE class QLowEnergyServicePrivate; -class QLowEnergyControllerPrivate; +class QLowEnergyControllerPrivateCommon; class Q_BLUETOOTH_EXPORT QLowEnergyService : public QObject { Q_OBJECT @@ -135,8 +135,10 @@ private: // QLowEnergyController is the factory for this class friend class QLowEnergyController; friend class QLowEnergyControllerPrivate; + friend class QLowEnergyControllerPrivateBluez; + friend class QLowEnergyControllerPrivateAndroid; QLowEnergyService(QSharedPointer<QLowEnergyServicePrivate> p, - QObject *parent = Q_NULLPTR); + QObject *parent = nullptr); }; Q_DECLARE_OPERATORS_FOR_FLAGS(QLowEnergyService::ServiceTypes) diff --git a/src/bluetooth/qlowenergyservice_osx.mm b/src/bluetooth/qlowenergyservice_osx.mm index 52c2ac87..4423887a 100644 --- a/src/bluetooth/qlowenergyservice_osx.mm +++ b/src/bluetooth/qlowenergyservice_osx.mm @@ -58,7 +58,7 @@ namespace { QLowEnergyControllerPrivateOSX *qt_mac_le_controller(QSharedPointer<QLowEnergyServicePrivate> d_ptr) { if (d_ptr.isNull()) - return Q_NULLPTR; + return nullptr; return static_cast<QLowEnergyControllerPrivateOSX *>(d_ptr->controller.data()); } @@ -195,7 +195,7 @@ bool QLowEnergyService::contains(const QLowEnergyCharacteristic &characteristic) void QLowEnergyService::readCharacteristic(const QLowEnergyCharacteristic &characteristic) { QLowEnergyControllerPrivateOSX *const controller = qt_mac_le_controller(d_ptr); - if (controller == Q_NULLPTR || state() != ServiceDiscovered || !contains(characteristic)) { + if (controller == nullptr || state() != ServiceDiscovered || !contains(characteristic)) { d_ptr->setError(OperationError); return; } @@ -208,7 +208,7 @@ void QLowEnergyService::writeCharacteristic(const QLowEnergyCharacteristic &ch, WriteMode mode) { QLowEnergyControllerPrivateOSX *const controller = qt_mac_le_controller(d_ptr); - if (controller == Q_NULLPTR || + if (controller == nullptr || (controller->role == QLowEnergyController::CentralRole && state() != ServiceDiscovered) || !contains(ch)) { d_ptr->setError(QLowEnergyService::OperationError); @@ -239,7 +239,7 @@ bool QLowEnergyService::contains(const QLowEnergyDescriptor &descriptor) const void QLowEnergyService::readDescriptor(const QLowEnergyDescriptor &descriptor) { QLowEnergyControllerPrivateOSX *const controller = qt_mac_le_controller(d_ptr); - if (controller == Q_NULLPTR || state() != ServiceDiscovered || !contains(descriptor)) { + if (controller == nullptr || state() != ServiceDiscovered || !contains(descriptor)) { d_ptr->setError(OperationError); return; } @@ -251,7 +251,7 @@ void QLowEnergyService::writeDescriptor(const QLowEnergyDescriptor &descriptor, const QByteArray &newValue) { QLowEnergyControllerPrivateOSX *const controller = qt_mac_le_controller(d_ptr); - if (controller == Q_NULLPTR || state() != ServiceDiscovered || !contains(descriptor)) { + if (controller == nullptr || state() != ServiceDiscovered || !contains(descriptor)) { // This operation error also includes LE controller in the peripheral role: // on iOS/OS X - descriptors are immutable. d_ptr->setError(OperationError); diff --git a/src/bluetooth/qlowenergyserviceprivate.cpp b/src/bluetooth/qlowenergyserviceprivate.cpp index 83724d4e..0b8d8be0 100644 --- a/src/bluetooth/qlowenergyserviceprivate.cpp +++ b/src/bluetooth/qlowenergyserviceprivate.cpp @@ -39,7 +39,7 @@ #include "qlowenergyserviceprivate_p.h" -#include "qlowenergycontroller_p.h" +#include "qlowenergycontrollerbase_p.h" QT_BEGIN_NAMESPACE diff --git a/src/bluetooth/qtbluetoothglobal_p.h b/src/bluetooth/qtbluetoothglobal_p.h index ffbfc4fe..59944593 100644 --- a/src/bluetooth/qtbluetoothglobal_p.h +++ b/src/bluetooth/qtbluetoothglobal_p.h @@ -56,4 +56,10 @@ #include <QtBluetooth/qtbluetoothglobal.h> #include <QtBluetooth/private/qtbluetooth-config_p.h> +QT_BEGIN_NAMESPACE + +#define Q_BLUETOOTH_PRIVATE_EXPORT Q_BLUETOOTH_EXPORT + +QT_END_NAMESPACE + #endif // QTBLUETOOTHGLOBAL_P_H diff --git a/src/imports/bluetooth/qdeclarativebluetoothdiscoverymodel.cpp b/src/imports/bluetooth/qdeclarativebluetoothdiscoverymodel.cpp index f2486e81..fc1accbd 100644 --- a/src/imports/bluetooth/qdeclarativebluetoothdiscoverymodel.cpp +++ b/src/imports/bluetooth/qdeclarativebluetoothdiscoverymodel.cpp @@ -142,22 +142,30 @@ QDeclarativeBluetoothDiscoveryModel::QDeclarativeBluetoothDiscoveryModel(QObject d(new QDeclarativeBluetoothDiscoveryModelPrivate) { d->m_deviceAgent = new QBluetoothDeviceDiscoveryAgent(this); - connect(d->m_deviceAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)), - this, SLOT(deviceDiscovered(QBluetoothDeviceInfo))); - connect(d->m_deviceAgent, SIGNAL(finished()), this, SLOT(finishedDiscovery())); - connect(d->m_deviceAgent, SIGNAL(canceled()), this, SLOT(finishedDiscovery())); - connect(d->m_deviceAgent, SIGNAL(error(QBluetoothDeviceDiscoveryAgent::Error)), - this, SLOT(errorDeviceDiscovery(QBluetoothDeviceDiscoveryAgent::Error))); - d->m_deviceAgent->setObjectName("DeviceDiscoveryAgent"); + connect(d->m_deviceAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, + this, QOverload<const QBluetoothDeviceInfo&>::of(&QDeclarativeBluetoothDiscoveryModel::deviceDiscovered)); + connect(d->m_deviceAgent, &QBluetoothDeviceDiscoveryAgent::finished, + this, &QDeclarativeBluetoothDiscoveryModel::finishedDiscovery); + connect(d->m_deviceAgent, &QBluetoothDeviceDiscoveryAgent::canceled, + this, &QDeclarativeBluetoothDiscoveryModel::finishedDiscovery); + connect(d->m_deviceAgent, + QOverload<QBluetoothDeviceDiscoveryAgent::Error>::of(&QBluetoothDeviceDiscoveryAgent::error), + this, + &QDeclarativeBluetoothDiscoveryModel::errorDeviceDiscovery); + d->m_deviceAgent->setObjectName(QStringLiteral("DeviceDiscoveryAgent")); d->m_serviceAgent = new QBluetoothServiceDiscoveryAgent(this); - connect(d->m_serviceAgent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)), - this, SLOT(serviceDiscovered(QBluetoothServiceInfo))); - connect(d->m_serviceAgent, SIGNAL(finished()), this, SLOT(finishedDiscovery())); - connect(d->m_serviceAgent, SIGNAL(canceled()), this, SLOT(finishedDiscovery())); - connect(d->m_serviceAgent, SIGNAL(error(QBluetoothServiceDiscoveryAgent::Error)), - this, SLOT(errorDiscovery(QBluetoothServiceDiscoveryAgent::Error))); - d->m_serviceAgent->setObjectName("ServiceDiscoveryAgent"); + connect(d->m_serviceAgent, &QBluetoothServiceDiscoveryAgent::serviceDiscovered, + this, QOverload<const QBluetoothServiceInfo&>::of(&QDeclarativeBluetoothDiscoveryModel::serviceDiscovered)); + connect(d->m_serviceAgent, &QBluetoothServiceDiscoveryAgent::finished, + this, &QDeclarativeBluetoothDiscoveryModel::finishedDiscovery); + connect(d->m_serviceAgent, &QBluetoothServiceDiscoveryAgent::canceled, + this, &QDeclarativeBluetoothDiscoveryModel::finishedDiscovery); + connect(d->m_serviceAgent, + QOverload<QBluetoothServiceDiscoveryAgent::Error>::of(&QBluetoothServiceDiscoveryAgent::error), + this, + &QDeclarativeBluetoothDiscoveryModel::errorDiscovery); + d->m_serviceAgent->setObjectName(QStringLiteral("ServiceDiscoveryAgent")); QHash<int, QByteArray> roleNames; roleNames = QAbstractItemModel::roleNames(); diff --git a/src/imports/bluetooth/qdeclarativebluetoothservice.cpp b/src/imports/bluetooth/qdeclarativebluetoothservice.cpp index efbf217b..48c9da9a 100644 --- a/src/imports/bluetooth/qdeclarativebluetoothservice.cpp +++ b/src/imports/bluetooth/qdeclarativebluetoothservice.cpp @@ -297,7 +297,8 @@ void QDeclarativeBluetoothService::setRegistered(bool registered) } d->m_server = server; - connect(d->m_server, SIGNAL(newConnection()), this, SLOT(new_connection())); + connect(d->m_server, &QBluetoothServer::newConnection, + this, &QDeclarativeBluetoothService::new_connection); d->m_service->setAttribute(QBluetoothServiceInfo::ServiceRecordHandle, (uint)0x00010010); diff --git a/src/imports/bluetooth/qdeclarativebluetoothsocket.cpp b/src/imports/bluetooth/qdeclarativebluetoothsocket.cpp index 0d5a5eae..07de35bc 100644 --- a/src/imports/bluetooth/qdeclarativebluetoothsocket.cpp +++ b/src/imports/bluetooth/qdeclarativebluetoothsocket.cpp @@ -112,11 +112,16 @@ public: m_socket = new QBluetoothSocket(socketProtocol); m_socket->connectToService(*m_service->serviceInfo()); - QObject::connect(m_socket, SIGNAL(connected()), m_dbs, SLOT(socket_connected())); - QObject::connect(m_socket, SIGNAL(disconnected()), m_dbs, SLOT(socket_disconnected())); - QObject::connect(m_socket, SIGNAL(error(QBluetoothSocket::SocketError)), m_dbs, SLOT(socket_error(QBluetoothSocket::SocketError))); - QObject::connect(m_socket, SIGNAL(stateChanged(QBluetoothSocket::SocketState)), m_dbs, SLOT(socket_state(QBluetoothSocket::SocketState))); - QObject::connect(m_socket, SIGNAL(readyRead()), m_dbs, SLOT(socket_readyRead())); + QObject::connect(m_socket, &QBluetoothSocket::connected, + m_dbs, &QDeclarativeBluetoothSocket::socket_connected); + QObject::connect(m_socket, &QBluetoothSocket::disconnected, + m_dbs, &QDeclarativeBluetoothSocket::socket_disconnected); + QObject::connect(m_socket, QOverload<QBluetoothSocket::SocketError>::of(&QBluetoothSocket::error), + m_dbs, &QDeclarativeBluetoothSocket::socket_error); + QObject::connect(m_socket, &QBluetoothSocket::stateChanged, + m_dbs, &QDeclarativeBluetoothSocket::socket_state); + QObject::connect(m_socket, &QIODevice::readyRead, + m_dbs, &QDeclarativeBluetoothSocket::socket_readyRead); } QDeclarativeBluetoothSocket *m_dbs; @@ -363,11 +368,16 @@ void QDeclarativeBluetoothSocket::newSocket(QBluetoothSocket *socket, QDeclarati d->m_componentCompleted = true; d->m_error = NoError; - QObject::connect(socket, SIGNAL(connected()), this, SLOT(socket_connected())); - QObject::connect(socket, SIGNAL(disconnected()), this, SLOT(socket_disconnected())); - QObject::connect(socket, SIGNAL(error(QBluetoothSocket::SocketError)), this, SLOT(socket_error(QBluetoothSocket::SocketError))); - QObject::connect(socket, SIGNAL(stateChanged(QBluetoothSocket::SocketState)), this, SLOT(socket_state(QBluetoothSocket::SocketState))); - QObject::connect(socket, SIGNAL(readyRead()), this, SLOT(socket_readyRead())); + QObject::connect(socket, &QBluetoothSocket::connected, + this, &QDeclarativeBluetoothSocket::socket_connected); + QObject::connect(socket, &QBluetoothSocket::disconnected, + this, &QDeclarativeBluetoothSocket::socket_disconnected); + QObject::connect(socket, QOverload<QBluetoothSocket::SocketError>::of(&QBluetoothSocket::error), + this, &QDeclarativeBluetoothSocket::socket_error); + QObject::connect(socket, &QBluetoothSocket::stateChanged, + this, &QDeclarativeBluetoothSocket::socket_state); + QObject::connect(socket, &QIODevice::readyRead, + this, &QDeclarativeBluetoothSocket::socket_readyRead); socket_state(socket->state()); diff --git a/src/nfc/nfc.pro b/src/nfc/nfc.pro index 5282170e..ae65640a 100644 --- a/src/nfc/nfc.pro +++ b/src/nfc/nfc.pro @@ -86,8 +86,6 @@ linux:!android:qtHaveModule(dbus) { ANDROID_PERMISSIONS = \ android.permission.NFC ANDROID_BUNDLED_JAR_DEPENDENCIES = \ - jar/QtNfc-bundled.jar:org.qtproject.qt5.android.nfc.QtNfc - ANDROID_JAR_DEPENDENCIES = \ jar/QtNfc.jar:org.qtproject.qt5.android.nfc.QtNfc DEFINES += ANDROID_NFC QT_PRIVATE += core-private gui androidextras diff --git a/src/nfc/qndefnfcsmartposterrecord.cpp b/src/nfc/qndefnfcsmartposterrecord.cpp index 73f2cd21..bc7acfab 100644 --- a/src/nfc/qndefnfcsmartposterrecord.cpp +++ b/src/nfc/qndefnfcsmartposterrecord.cpp @@ -566,7 +566,7 @@ void QNdefNfcSmartPosterRecord::addIcon(const QByteArray &type, const QByteArray rec.setType(type); rec.setData(data); - return addIcon(rec); + addIcon(rec); } /*! diff --git a/src/nfc/qnearfieldmanager.h b/src/nfc/qnearfieldmanager.h index 8b0d92fa..9583e01f 100644 --- a/src/nfc/qnearfieldmanager.h +++ b/src/nfc/qnearfieldmanager.h @@ -65,8 +65,8 @@ public: Q_ENUM(TargetAccessMode) Q_DECLARE_FLAGS(TargetAccessModes, TargetAccessMode) - explicit QNearFieldManager(QObject *parent = Q_NULLPTR); - explicit QNearFieldManager(QNearFieldManagerPrivate *backend, QObject *parent = Q_NULLPTR); + explicit QNearFieldManager(QObject *parent = nullptr); + explicit QNearFieldManager(QNearFieldManagerPrivate *backend, QObject *parent = nullptr); ~QNearFieldManager(); bool isAvailable() const; diff --git a/src/nfc/qnearfieldsharemanager.cpp b/src/nfc/qnearfieldsharemanager.cpp index 515a9d62..0709f60e 100644 --- a/src/nfc/qnearfieldsharemanager.cpp +++ b/src/nfc/qnearfieldsharemanager.cpp @@ -149,7 +149,7 @@ QNearFieldShareManager::~QNearFieldShareManager() void QNearFieldShareManager::setShareModes(ShareModes mode) { Q_D(QNearFieldShareManager); - return d->setShareModes(mode); + d->setShareModes(mode); } /*! diff --git a/src/nfc/qnearfieldsharemanager.h b/src/nfc/qnearfieldsharemanager.h index 45778df0..e34e9a64 100644 --- a/src/nfc/qnearfieldsharemanager.h +++ b/src/nfc/qnearfieldsharemanager.h @@ -53,7 +53,7 @@ class Q_NFC_EXPORT QNearFieldShareManager : public QObject Q_OBJECT public: - explicit QNearFieldShareManager(QObject *parent = Q_NULLPTR); + explicit QNearFieldShareManager(QObject *parent = nullptr); ~QNearFieldShareManager(); enum ShareError { diff --git a/src/nfc/qnearfieldsharetarget.h b/src/nfc/qnearfieldsharetarget.h index bde5e8b7..441ffda7 100644 --- a/src/nfc/qnearfieldsharetarget.h +++ b/src/nfc/qnearfieldsharetarget.h @@ -69,7 +69,7 @@ Q_SIGNALS: void shareFinished(); private: - explicit QNearFieldShareTarget(QNearFieldShareManager::ShareModes modes, QObject *parent = Q_NULLPTR); + explicit QNearFieldShareTarget(QNearFieldShareManager::ShareModes modes, QObject *parent = nullptr); QNearFieldShareTargetPrivate *d_ptr; Q_DECLARE_PRIVATE(QNearFieldShareTarget) diff --git a/src/nfc/qnearfieldtarget.h b/src/nfc/qnearfieldtarget.h index 330164f5..e51960f7 100644 --- a/src/nfc/qnearfieldtarget.h +++ b/src/nfc/qnearfieldtarget.h @@ -118,7 +118,7 @@ public: QSharedDataPointer<RequestIdPrivate> d; }; - explicit QNearFieldTarget(QObject *parent = Q_NULLPTR); + explicit QNearFieldTarget(QObject *parent = nullptr); virtual ~QNearFieldTarget(); virtual QByteArray uid() const = 0; diff --git a/src/nfc/qnearfieldtarget_android.cpp b/src/nfc/qnearfieldtarget_android.cpp index dcdc872d..690fc272 100644 --- a/src/nfc/qnearfieldtarget_android.cpp +++ b/src/nfc/qnearfieldtarget_android.cpp @@ -149,7 +149,7 @@ QNearFieldTarget::RequestId NearFieldTarget::readNdefMessages() if (!m_intent.isValid()) { QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::TargetOutOfRangeError), - Q_ARG(const QNearFieldTarget::RequestId&, requestId)); + Q_ARG(QNearFieldTarget::RequestId&, requestId)); return requestId; } @@ -157,7 +157,7 @@ QNearFieldTarget::RequestId NearFieldTarget::readNdefMessages() if (!setTagTechnology({NDEFTECHNOLOGY})) { QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::UnsupportedError), - Q_ARG(const QNearFieldTarget::RequestId&, requestId)); + Q_ARG(QNearFieldTarget::RequestId&, requestId)); return requestId; } @@ -165,7 +165,7 @@ QNearFieldTarget::RequestId NearFieldTarget::readNdefMessages() if (!connect()) { QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::TargetOutOfRangeError), - Q_ARG(const QNearFieldTarget::RequestId&, requestId)); + Q_ARG(QNearFieldTarget::RequestId&, requestId)); return requestId; } @@ -176,7 +176,7 @@ QNearFieldTarget::RequestId NearFieldTarget::readNdefMessages() if (!ndefMessage.isValid()) { QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::NdefReadError), - Q_ARG(const QNearFieldTarget::RequestId&, requestId)); + Q_ARG(QNearFieldTarget::RequestId&, requestId)); return requestId; } @@ -192,12 +192,12 @@ QNearFieldTarget::RequestId NearFieldTarget::readNdefMessages() // Sending QNdefMessage, requestCompleted and exit. QNdefMessage qNdefMessage = QNdefMessage::fromByteArray(ndefMessageQBA); QMetaObject::invokeMethod(this, "ndefMessageRead", Qt::QueuedConnection, - Q_ARG(const QNdefMessage&, qNdefMessage)); + Q_ARG(QNdefMessage&, qNdefMessage)); QMetaObject::invokeMethod(this, "requestCompleted", Qt::QueuedConnection, - Q_ARG(const QNearFieldTarget::RequestId&, requestId)); + Q_ARG(QNearFieldTarget::RequestId&, requestId)); QMetaObject::invokeMethod(this, "ndefMessageRead", Qt::QueuedConnection, - Q_ARG(const QNdefMessage&, qNdefMessage), - Q_ARG(const QNearFieldTarget::RequestId&, requestId)); + Q_ARG(QNdefMessage&, qNdefMessage), + Q_ARG(QNearFieldTarget::RequestId&, requestId)); return requestId; } @@ -247,7 +247,7 @@ QNearFieldTarget::RequestId NearFieldTarget::sendCommand(const QByteArray &comma if (!connect()) { QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::TargetOutOfRangeError), - Q_ARG(const QNearFieldTarget::RequestId&, requestId)); + Q_ARG(QNearFieldTarget::RequestId&, requestId)); return requestId; } @@ -261,7 +261,7 @@ QNearFieldTarget::RequestId NearFieldTarget::sendCommand(const QByteArray &comma if (catchJavaExceptions()) { QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::CommandError), - Q_ARG(const QNearFieldTarget::RequestId&, requestId)); + Q_ARG(QNearFieldTarget::RequestId&, requestId)); return requestId; } QByteArray result = jbyteArrayToQByteArray(myNewVal.object<jbyteArray>()); @@ -274,7 +274,7 @@ QNearFieldTarget::RequestId NearFieldTarget::sendCommand(const QByteArray &comma disconnect(); // IOException at this point does not matter anymore. } QMetaObject::invokeMethod(this, "requestCompleted", Qt::QueuedConnection, - Q_ARG(const QNearFieldTarget::RequestId&, requestId)); + Q_ARG(QNearFieldTarget::RequestId&, requestId)); return requestId; } @@ -312,7 +312,7 @@ QNearFieldTarget::RequestId NearFieldTarget::writeNdefMessages(const QList<QNdef if (!connect()) { QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::TargetOutOfRangeError), - Q_ARG(const QNearFieldTarget::RequestId&, requestId)); + Q_ARG(QNearFieldTarget::RequestId&, requestId)); return requestId; } @@ -325,7 +325,7 @@ QNearFieldTarget::RequestId NearFieldTarget::writeNdefMessages(const QList<QNdef if (catchJavaExceptions()) { QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::UnknownError), - Q_ARG(const QNearFieldTarget::RequestId&, requestId)); + Q_ARG(QNearFieldTarget::RequestId&, requestId)); return requestId; } @@ -334,7 +334,7 @@ QNearFieldTarget::RequestId NearFieldTarget::writeNdefMessages(const QList<QNdef if (catchJavaExceptions()) { QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::NdefWriteError), - Q_ARG(const QNearFieldTarget::RequestId&, requestId)); + Q_ARG(QNearFieldTarget::RequestId&, requestId)); return requestId; } diff --git a/src/nfc/qnearfieldtarget_neard_p.h b/src/nfc/qnearfieldtarget_neard_p.h index c84e033f..78dedeeb 100644 --- a/src/nfc/qnearfieldtarget_neard_p.h +++ b/src/nfc/qnearfieldtarget_neard_p.h @@ -353,14 +353,14 @@ private: if (!newNdefMessage.isEmpty()) { QMetaObject::invokeMethod(this, "ndefMessageRead", Qt::QueuedConnection, - Q_ARG(const QNdefMessage, newNdefMessage)); + Q_ARG(QNdefMessage, newNdefMessage)); // the request id in requestCompleted has to match the one created in readNdefMessages QMetaObject::invokeMethod(this, "requestCompleted", Qt::QueuedConnection, - Q_ARG(const QNearFieldTarget::RequestId, m_currentReadRequestId)); + Q_ARG(QNearFieldTarget::RequestId, m_currentReadRequestId)); } else { QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, - Q_ARG(const QNearFieldTarget::Error, QNearFieldTarget::UnknownError), - Q_ARG(const QNearFieldTarget::RequestId, m_currentReadRequestId)); + Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::UnknownError), + Q_ARG(QNearFieldTarget::RequestId, m_currentReadRequestId)); } m_readRequested = false; @@ -389,13 +389,13 @@ private: if (reply.isError()) { qCWarning(QT_NFC_NEARD) << "Error writing to NFC tag" << reply.error(); QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, - Q_ARG(const QNearFieldTarget::Error, QNearFieldTarget::UnknownError), - Q_ARG(const QNearFieldTarget::RequestId, m_currentWriteRequestId)); + Q_ARG(QNearFieldTarget::Error, QNearFieldTarget::UnknownError), + Q_ARG(QNearFieldTarget::RequestId, m_currentWriteRequestId)); } QMetaObject::invokeMethod(this, "ndefMessagesWritten", Qt::QueuedConnection); QMetaObject::invokeMethod(this, "requestCompleted", Qt::QueuedConnection, - Q_ARG(const QNearFieldTarget::RequestId, m_currentWriteRequestId)); + Q_ARG(QNearFieldTarget::RequestId, m_currentWriteRequestId)); } // invalidate current write request diff --git a/src/nfc/qqmlndefrecord.cpp b/src/nfc/qqmlndefrecord.cpp index cd6620cc..a7304f00 100644 --- a/src/nfc/qqmlndefrecord.cpp +++ b/src/nfc/qqmlndefrecord.cpp @@ -228,7 +228,7 @@ QQmlNdefRecord *qNewDeclarativeNdefRecordForNdefRecord(const QNdefRecord &record continue; return static_cast<QQmlNdefRecord *>(metaObject->newInstance( - Q_ARG(QNdefRecord, record), Q_ARG(QObject *, 0))); + Q_ARG(QNdefRecord, record), Q_ARG(QObject*, 0))); } return new QQmlNdefRecord(record); diff --git a/src/nfc/qqmlndefrecord.h b/src/nfc/qqmlndefrecord.h index 9e8d8bbd..0f624505 100644 --- a/src/nfc/qqmlndefrecord.h +++ b/src/nfc/qqmlndefrecord.h @@ -69,8 +69,8 @@ public: }; Q_ENUM(TypeNameFormat) - explicit QQmlNdefRecord(QObject *parent = Q_NULLPTR); - explicit QQmlNdefRecord(const QNdefRecord &record, QObject *parent = Q_NULLPTR); + explicit QQmlNdefRecord(QObject *parent = nullptr); + explicit QQmlNdefRecord(const QNdefRecord &record, QObject *parent = nullptr); ~QQmlNdefRecord(); QString type() const; diff --git a/sync.profile b/sync.profile index 77a4cb6c..5d103a33 100644 --- a/sync.profile +++ b/sync.profile @@ -15,12 +15,13 @@ @ignore_for_include_check = ( - # OBEX auto-generated headers + # BlueZ & OBEX auto-generated headers "adapter1_bluez5_p.h", "adapter_p.h", "agent_p.h", "device1_bluez5_p.h", "device_p.h", "manager_p.h", "obex_agent_p.h", "obex_client1_bluez5_p.h", "obex_client_p.h", "obex_manager_p.h", "obex_objectpush1_bluez5_p.h", "obex_transfer1_bluez5_p.h", "obex_transfer_p.h", "objectmanager_p.h", - "profile1_p.h", "properties_p.h", "service_p.h", + "profile1_p.h", "properties_p.h", "service_p.h", "gattchar1_p.h", + "gattdesc1_p.h", "gattservice1_p.h", # NFC auto-generated headers # Note: "adapter_p.h", "agent_p.h" and "manager_p.h" are duplicated here "dbusobjectmanager_p.h", "dbusproperties_p.h", "tag_p.h"); diff --git a/tests/auto/qlowenergycontroller-gattserver/test/tst_qlowenergycontroller-gattserver.cpp b/tests/auto/qlowenergycontroller-gattserver/test/tst_qlowenergycontroller-gattserver.cpp index 81dfd286..30b2fb75 100644 --- a/tests/auto/qlowenergycontroller-gattserver/test/tst_qlowenergycontroller-gattserver.cpp +++ b/tests/auto/qlowenergycontroller-gattserver/test/tst_qlowenergycontroller-gattserver.cpp @@ -294,9 +294,6 @@ void TestQLowEnergyControllerGattServer::advertisedData() void TestQLowEnergyControllerGattServer::serverCommunication() { - qRegisterMetaType<QLowEnergyCharacteristic>(); - qRegisterMetaType<QLowEnergyDescriptor>(); - if (m_serverAddress.isNull()) QSKIP("No server address provided"); m_leController.reset(QLowEnergyController::createCentral(m_serverInfo)); diff --git a/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp b/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp index aa779f47..53c2f754 100644 --- a/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp +++ b/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp @@ -29,6 +29,9 @@ #include <QtTest/QtTest> #include <private/qtbluetoothglobal_p.h> +#if QT_CONFIG(bluez) +#include <QtBluetooth/private/bluez5_helper_p.h> +#endif #include <QBluetoothAddress> #include <QBluetoothLocalDevice> #include <QBluetoothDeviceDiscoveryAgent> @@ -58,7 +61,10 @@ QT_USE_NAMESPACE #endif #ifdef HANDLES_PROVIDED_BY_PLATFORM -#define HANDLE_COMPARE(actual,expected) QCOMPARE(actual,expected) +#define HANDLE_COMPARE(actual,expected) \ + if (!isBluezDbusLE) {\ + QCOMPARE(actual, expected);\ + }; #else #define HANDLE_COMPARE(actual,expected) #endif @@ -86,18 +92,17 @@ private slots: void tst_errorCases(); private: void verifyServiceProperties(const QLowEnergyService *info); + bool verifyClientCharacteristicValue(const QByteArray& value); QBluetoothDeviceDiscoveryAgent *devAgent; QBluetoothAddress remoteDevice; QBluetoothDeviceInfo remoteDeviceInfo; QList<QBluetoothUuid> foundServices; + bool isBluezDbusLE = false; }; tst_QLowEnergyController::tst_QLowEnergyController() { - qRegisterMetaType<QLowEnergyCharacteristic>(); - qRegisterMetaType<QLowEnergyDescriptor>(); - //QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true")); #ifndef Q_OS_MAC // Core Bluetooth (OS X and iOS) does not work with addresses, @@ -110,6 +115,12 @@ tst_QLowEnergyController::tst_QLowEnergyController() qWarning() << "Not using any remote device for testing. Set BT_TEST_DEVICE env to run manual tests involving a remote device"; } #endif + +#if QT_CONFIG(bluez) + // This debug is needed to determine runtime configuration in the Qt CI. + isBluezDbusLE = (bluetoothdVersion() >= QVersionNumber(5, 42)); + qDebug() << "isDBusBluez:" << isBluezDbusLE; +#endif } tst_QLowEnergyController::~tst_QLowEnergyController() @@ -138,6 +149,7 @@ void tst_QLowEnergyController::initTestCase() #endif devAgent = new QBluetoothDeviceDiscoveryAgent(this); + devAgent->setLowEnergyDiscoveryTimeout(5000); QSignalSpy finishedSpy(devAgent, SIGNAL(finished())); // there should be no changes yet @@ -166,7 +178,8 @@ void tst_QLowEnergyController::initTestCase() // These are the services exported by the TI SensorTag #ifndef Q_OS_MAC // Core Bluetooth somehow ignores/hides/fails to discover these services. - foundServices << QBluetoothUuid(QString("00001800-0000-1000-8000-00805f9b34fb")); + if (!isBluezDbusLE) // Bluez LE Dbus intentionally hides 0x1800 service + foundServices << QBluetoothUuid(QString("00001800-0000-1000-8000-00805f9b34fb")); foundServices << QBluetoothUuid(QString("00001801-0000-1000-8000-00805f9b34fb")); #endif foundServices << QBluetoothUuid(QString("0000180a-0000-1000-8000-00805f9b34fb")); @@ -452,9 +465,38 @@ void tst_QLowEnergyController::tst_concurrentDiscovery() QCOMPARE(control.state(), QLowEnergyController::ConnectedState); QCOMPARE(control2.state(), QLowEnergyController::UnconnectedState); #else - // see QTBUG-42519 - // Linux cannot maintain two controller connections at the same time - QVERIFY(control2.error() != QLowEnergyController::NoError); + if (!isBluezDbusLE) { + // see QTBUG-42519 + // Linux non-DBus GATT cannot maintain two controller connections at the same time + QCOMPARE(control.state(), QLowEnergyController::UnconnectedState); + QCOMPARE(control2.state(), QLowEnergyController::ConnectedState); + control2.disconnectFromDevice(); + QTRY_COMPARE(control2.state(), QLowEnergyController::UnconnectedState); + QTRY_COMPARE(control2.error(), QLowEnergyController::NoError); + + // reconnect control + control.connectToDevice(); + { + QTRY_VERIFY_WITH_TIMEOUT(control.state() != QLowEnergyController::ConnectingState, + 30000); + } + QCOMPARE(control.state(), QLowEnergyController::ConnectedState); + } else { + QCOMPARE(control.state(), QLowEnergyController::ConnectedState); + QCOMPARE(control2.state(), QLowEnergyController::ConnectedState); + control2.disconnectFromDevice(); + QTRY_COMPARE(control2.state(), QLowEnergyController::UnconnectedState); + QTRY_COMPARE(control2.error(), QLowEnergyController::NoError); + QTRY_COMPARE(control.state(), QLowEnergyController::UnconnectedState); + + // reconnect control + control.connectToDevice(); + { + QTRY_VERIFY_WITH_TIMEOUT(control.state() != QLowEnergyController::ConnectingState, + 30000); + } + QCOMPARE(control.state(), QLowEnergyController::ConnectedState); + } #endif } @@ -667,7 +709,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)); QCOMPARE(chars[0].descriptors().at(0).type(), QBluetoothUuid::ClientCharacteristicConfiguration); - QCOMPARE(chars[0].descriptors().at(0).value(), QByteArray::fromHex("0000")); + QVERIFY(verifyClientCharacteristicValue(chars[0].descriptors().at(0).value())); QVERIFY(info->contains(chars[0].descriptors().at(0))); } else if (info->serviceUuid() == QBluetoothUuid(QString("0000180a-0000-1000-8000-00805f9b34fb"))) { @@ -800,7 +842,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)); QCOMPARE(chars[0].descriptors().at(0).type(), QBluetoothUuid::ClientCharacteristicConfiguration); - QCOMPARE(chars[0].descriptors().at(0).value(), QByteArray::fromHex("0000")); + QVERIFY(verifyClientCharacteristicValue(chars[0].descriptors().at(0).value())); QVERIFY(info->contains(chars[0].descriptors().at(0))); QCOMPARE(chars[0].descriptors().at(1).isValid(), true); @@ -887,7 +929,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)); QCOMPARE(chars[0].descriptors().at(0).type(), QBluetoothUuid::ClientCharacteristicConfiguration); - QCOMPARE(chars[0].descriptors().at(0).value(), QByteArray::fromHex("0000")); + QVERIFY(verifyClientCharacteristicValue(chars[0].descriptors().at(0).value())); QVERIFY(info->contains(chars[0].descriptors().at(0))); QCOMPARE(chars[0].descriptors().at(1).isValid(), true); @@ -927,7 +969,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)); QCOMPARE(chars[0].descriptors().at(0).type(), QBluetoothUuid::ClientCharacteristicConfiguration); - QCOMPARE(chars[0].descriptors().at(0).value(), QByteArray::fromHex("0000")); + QVERIFY(verifyClientCharacteristicValue(chars[0].descriptors().at(0).value())); QVERIFY(info->contains(chars[0].descriptors().at(0))); QCOMPARE(chars[0].descriptors().at(1).isValid(), true); @@ -1014,7 +1056,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)); QCOMPARE(chars[0].descriptors().at(0).type(), QBluetoothUuid::ClientCharacteristicConfiguration); - QCOMPARE(chars[0].descriptors().at(0).value(), QByteArray::fromHex("0000")); + QVERIFY(verifyClientCharacteristicValue(chars[0].descriptors().at(0).value())); QVERIFY(info->contains(chars[0].descriptors().at(0))); QCOMPARE(chars[0].descriptors().at(1).isValid(), true); @@ -1102,7 +1144,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)); QCOMPARE(chars[0].descriptors().at(0).type(), QBluetoothUuid::ClientCharacteristicConfiguration); - QCOMPARE(chars[0].descriptors().at(0).value(), QByteArray::fromHex("0000")); + QVERIFY(verifyClientCharacteristicValue(chars[0].descriptors().at(0).value())); QVERIFY(info->contains(chars[0].descriptors().at(0))); QCOMPARE(chars[0].descriptors().at(1).isValid(), true); @@ -1189,7 +1231,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)); QCOMPARE(chars[0].descriptors().at(0).type(), QBluetoothUuid::ClientCharacteristicConfiguration); - QCOMPARE(chars[0].descriptors().at(0).value(), QByteArray::fromHex("0000")); + QVERIFY(verifyClientCharacteristicValue(chars[0].descriptors().at(0).value())); QVERIFY(info->contains(chars[0].descriptors().at(0))); QCOMPARE(chars[0].descriptors().at(1).isValid(), true); @@ -1258,7 +1300,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)); QCOMPARE(calibration.descriptors().at(0).type(), QBluetoothUuid::ClientCharacteristicConfiguration); - QCOMPARE(calibration.descriptors().at(0).value(), QByteArray::fromHex("0000")); + QVERIFY(verifyClientCharacteristicValue(calibration.descriptors().at(0).value())); QVERIFY(info->contains(calibration.descriptors().at(0))); QCOMPARE(calibration.descriptors().at(1).isValid(), true); @@ -1324,7 +1366,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)); QCOMPARE(chars[0].descriptors().at(0).type(), QBluetoothUuid::ClientCharacteristicConfiguration); - QCOMPARE(chars[0].descriptors().at(0).value(), QByteArray::fromHex("0000")); + QVERIFY(verifyClientCharacteristicValue(chars[0].descriptors().at(0).value())); QVERIFY(info->contains(chars[0].descriptors().at(0))); QCOMPARE(chars[0].descriptors().at(1).isValid(), true); @@ -1462,8 +1504,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)); QCOMPARE(chars[0].descriptors().at(0).type(), QBluetoothUuid::ClientCharacteristicConfiguration); - // value different in other revisions and test may fail - QCOMPARE(chars[0].descriptors().at(0).value(), QByteArray::fromHex("0100")); + QVERIFY(verifyClientCharacteristicValue(chars[0].descriptors().at(0).value())); QVERIFY(info->contains(chars[0].descriptors().at(0))); QCOMPARE(chars[0].descriptors().at(1).isValid(), true); @@ -1541,8 +1582,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)); QCOMPARE(chars[0].descriptors().at(0).type(), QBluetoothUuid::ClientCharacteristicConfiguration); - // value different in other revisions and test may fail - QCOMPARE(chars[0].descriptors().at(0).value(), QByteArray::fromHex("0100")); + QVERIFY(verifyClientCharacteristicValue(chars[0].descriptors().at(0).value())); QVERIFY(info->contains(chars[0].descriptors().at(0))); QCOMPARE(chars[0].descriptors().at(1).isValid(), true); @@ -1576,8 +1616,7 @@ void tst_QLowEnergyController::verifyServiceProperties( QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)); QCOMPARE(chars[1].descriptors().at(0).type(), QBluetoothUuid::ClientCharacteristicConfiguration); - // value different in other revisions and test may fail - QCOMPARE(chars[1].descriptors().at(0).value(), QByteArray::fromHex("0100")); + QVERIFY(verifyClientCharacteristicValue(chars[0].descriptors().at(0).value())); QVERIFY(info->contains(chars[1].descriptors().at(0))); QCOMPARE(chars[1].descriptors().at(1).isValid(), true); @@ -1595,6 +1634,29 @@ void tst_QLowEnergyController::verifyServiceProperties( } } +/* + * CCC descriptors can have one of three distinct values: + * 0000 - notifications and indications are off + * 0100 - notifications enabled + * 0200 - indications enabled + * + * The exact value is managed by the BTLE peripheral for each central + * that connects. The value of this field is session based and may be retained + * during multiple connections. + * + * This function returns \c true if the CCC value has a valid range. + * */ +bool tst_QLowEnergyController::verifyClientCharacteristicValue(const QByteArray &value) +{ + if (value == QByteArray::fromHex("0000") + || value == QByteArray::fromHex("0100") + || value == QByteArray::fromHex("0200") ) + return true; + + qWarning() << "Found incorrect CC value" << value.toHex(); + return false; +} + void tst_QLowEnergyController::tst_defaultBehavior() { QList<QBluetoothAddress> foundAddresses; @@ -1984,12 +2046,30 @@ void tst_QLowEnergyController::tst_readWriteDescriptor() QVERIFY(notification == signalDesc); descWrittenSpy.clear(); + // The series of wait calls below is required because toggling CCC via the notifying + // property consistently crashes BlueZ 5.47. BlueZ 5.48 does not crash but + // an error is thrown. For details see QTBUG-65729 + if (isBluezDbusLE) + QTest::qWait(1000); + // test concurrent writeRequests // they need to be queued up service->writeDescriptor(notification,QByteArray::fromHex("0100")); + if (isBluezDbusLE) + QTest::qWait(1000); + service->writeDescriptor(notification, QByteArray::fromHex("0000")); + if (isBluezDbusLE) + QTest::qWait(1000); + service->writeDescriptor(notification, QByteArray::fromHex("0100")); + if (isBluezDbusLE) + QTest::qWait(1000); + service->writeDescriptor(notification, QByteArray::fromHex("0000")); + if (isBluezDbusLE) + QTest::qWait(1000); + QTRY_VERIFY_WITH_TIMEOUT(descWrittenSpy.count() == 4, 10000); QCOMPARE(notification.value(), QByteArray::fromHex("0000")); @@ -2523,10 +2603,14 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse() QVERIFY(imageBlockChar.isValid()); // 2. Get "Image Identity" notification descriptor - const QLowEnergyDescriptor notification = imageIdentityChar.descriptor( + const QLowEnergyDescriptor identityNotification = imageIdentityChar.descriptor( + QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)); + const QLowEnergyDescriptor blockNotification = imageBlockChar.descriptor( QBluetoothUuid(QBluetoothUuid::ClientCharacteristicConfiguration)); - if (!notification.isValid() || !imageIdentityChar.isValid()) { + if (!identityNotification.isValid() + || !blockNotification.isValid() + || !imageIdentityChar.isValid()) { delete service; control.disconnectFromDevice(); QSKIP("Cannot find OAD char/notification"); @@ -2544,19 +2628,28 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse() QSignalSpy errorSpy(service, SIGNAL(error(QLowEnergyService::ServiceError))); + //enable notifications on both characteristics + if (identityNotification.value() != QByteArray::fromHex("0100")) { + service->writeDescriptor(identityNotification, QByteArray::fromHex("0100")); + QTRY_VERIFY_WITH_TIMEOUT(!descWrittenSpy.isEmpty(), 3000); + QCOMPARE(identityNotification.value(), QByteArray::fromHex("0100")); + QList<QVariant> firstSignalData = descWrittenSpy.first(); + QLowEnergyDescriptor signalDesc = firstSignalData[0].value<QLowEnergyDescriptor>(); + QByteArray signalValue = firstSignalData[1].toByteArray(); + QCOMPARE(signalValue, QByteArray::fromHex("0100")); + QVERIFY(identityNotification == signalDesc); + descWrittenSpy.clear(); + } - // by default the device enables the notification bit already - // no need to enable it. If notifications fail to arrive the - // platform must check default enabled notifications. - if (notification.value() != QByteArray::fromHex("0100")) { - service->writeDescriptor(notification, QByteArray::fromHex("0100")); + if (blockNotification.value() != QByteArray::fromHex("0100")) { + service->writeDescriptor(blockNotification, QByteArray::fromHex("0100")); QTRY_VERIFY_WITH_TIMEOUT(!descWrittenSpy.isEmpty(), 3000); - QCOMPARE(notification.value(), QByteArray::fromHex("0100")); + QCOMPARE(blockNotification.value(), QByteArray::fromHex("0100")); QList<QVariant> firstSignalData = descWrittenSpy.first(); QLowEnergyDescriptor signalDesc = firstSignalData[0].value<QLowEnergyDescriptor>(); QByteArray signalValue = firstSignalData[1].toByteArray(); QCOMPARE(signalValue, QByteArray::fromHex("0100")); - QVERIFY(notification == signalDesc); + QVERIFY(blockNotification == signalDesc); descWrittenSpy.clear(); } @@ -2580,8 +2673,8 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse() // Write triggers a notification and write confirmation service->writeCharacteristic(imageIdentityChar, QByteArray::fromHex("0")); QTest::qWait(1000); - QTRY_VERIFY_WITH_TIMEOUT(charChangedSpy.count() == 1, 5000); - QTRY_VERIFY_WITH_TIMEOUT(charWrittenSpy.count() == 1, 5000); + QTRY_COMPARE_WITH_TIMEOUT(charChangedSpy.count(), 1, 5000); + QTRY_COMPARE_WITH_TIMEOUT(charWrittenSpy.count(), 1, 5000); // This is very SensorTag specific logic. // If the image block is empty the current firmware @@ -2595,8 +2688,7 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse() QCOMPARE(imageIdentityChar, first); foundOneImage = true; } else { - // we received a notification for imageBlockChar without explicitly - // enabling them. This is caused by the device's default settings. + // we received a notification for imageBlockChar QCOMPARE(imageBlockChar, first); qWarning() << "Invalid image A ident info"; } @@ -2617,8 +2709,8 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse() // Image B service->writeCharacteristic(imageIdentityChar, QByteArray::fromHex("1")); QTest::qWait(1000); - QTRY_VERIFY_WITH_TIMEOUT(charChangedSpy.count() == 1, 5000); - QTRY_VERIFY_WITH_TIMEOUT(charWrittenSpy.count() == 1, 5000); + QTRY_COMPARE_WITH_TIMEOUT(charChangedSpy.count(), 1, 5000); + QTRY_COMPARE_WITH_TIMEOUT(charWrittenSpy.count(), 1, 5000);; entry = charChangedSpy[0]; first = entry[0].value<QLowEnergyCharacteristic>(); @@ -2663,7 +2755,8 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse() // we only expect one signal (the notification but not the write confirmation) // Wait at least a second for a potential second signals QTest::qWait(1000); - QTRY_VERIFY_WITH_TIMEOUT(charChangedSpy.count() == 1, 10000); + QTRY_COMPARE_WITH_TIMEOUT(charChangedSpy.count(), 1, 10000); + QTRY_COMPARE_WITH_TIMEOUT(charWrittenSpy.count(), 0, 10000); entry = charChangedSpy[0]; first = entry[0].value<QLowEnergyCharacteristic>(); @@ -2698,7 +2791,8 @@ void tst_QLowEnergyController::tst_writeCharacteristicNoResponse() // we only expect one signal (the notification but not the write confirmation) // Wait at least a second for a potential second signals QTest::qWait(1000); - QTRY_VERIFY_WITH_TIMEOUT(charChangedSpy.count() == 1, 10000); + QTRY_COMPARE_WITH_TIMEOUT(charWrittenSpy.count(), 0, 10000); + QTRY_COMPARE_WITH_TIMEOUT(charChangedSpy.count(), 1, 10000); entry = charChangedSpy[0]; first = entry[0].value<QLowEnergyCharacteristic>(); |