From 2d9c73c35b99453f8f36f9dcc4a4f6a8856d7877 Mon Sep 17 00:00:00 2001 From: Alex Blasche Date: Fri, 27 Nov 2015 09:17:57 +0100 Subject: Enforce unbuffered L2CAP socket for GATT The GATT protocol does not enforce a length indicator on each GATT command. Usually this is not a problem because each request is followed by a response and therefore we can assume the entire packet content is a single response/request. However the GATT WRITE_COMMAND does not have a response. Multiple requests can be sent in quick follow-up. If buffering is utilized the consecutive commands may be merged and received as single data blob on the remote device. Since Write commands don't have a length indicator they cannot be distinguished and ultimately the write command will set the wrong value. Change-Id: I02f3cd3cfaedfeae6a40272f5d22d3d88c39aa55 Task-number: QTBUG-49650 Reviewed-by: Christian Kandeler --- src/bluetooth/qlowenergycontroller_bluez.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/bluetooth/qlowenergycontroller_bluez.cpp b/src/bluetooth/qlowenergycontroller_bluez.cpp index 8906eb06..4cd3afe3 100644 --- a/src/bluetooth/qlowenergycontroller_bluez.cpp +++ b/src/bluetooth/qlowenergycontroller_bluez.cpp @@ -262,7 +262,9 @@ void QLowEnergyControllerPrivate::connectToDevice() } // connect - l2cpSocket->connectToService(remoteDevice, ATTRIBUTE_CHANNEL_ID); + // Unbuffered mode required to separate each GATT packet + l2cpSocket->connectToService(remoteDevice, ATTRIBUTE_CHANNEL_ID, + QIODevice::ReadWrite | QIODevice::Unbuffered); } void QLowEnergyControllerPrivate::l2cpConnected() -- cgit v1.2.3 From 741f5e26cd618aeff349dd612516148b50c85dde Mon Sep 17 00:00:00 2001 From: Alex Blasche Date: Fri, 27 Nov 2015 10:19:02 +0100 Subject: Don't register meta types during static init time The QMetaType register my not be up and running by the time we attempt these meta type registration. Change-Id: I1a857a936a24b4b00a49574fac311c08c09b3d5a Task-number: QTBUG-49455 Reviewed-by: Timur Pocheptsov Reviewed-by: Alex Blasche --- src/bluetooth/qbluetoothaddress.cpp | 15 ++++++++------ src/bluetooth/qbluetoothlocaldevice.cpp | 11 ++++------ src/bluetooth/qbluetoothlocaldevice_android.cpp | 2 ++ src/bluetooth/qbluetoothlocaldevice_bluez.cpp | 2 ++ src/bluetooth/qbluetoothlocaldevice_osx.mm | 2 ++ src/bluetooth/qbluetoothlocaldevice_p.cpp | 4 ++++ src/bluetooth/qbluetoothlocaldevice_p.h | 2 ++ src/bluetooth/qbluetoothlocaldevice_qnx.cpp | 2 ++ src/bluetooth/qbluetoothuuid.cpp | 27 ++++++++++++++++--------- src/bluetooth/qlowenergycontroller.cpp | 11 +++++----- src/bluetooth/qlowenergycontroller_android.cpp | 1 + src/bluetooth/qlowenergycontroller_bluez.cpp | 1 + src/bluetooth/qlowenergycontroller_osx.mm | 16 ++++++++------- src/bluetooth/qlowenergycontroller_p.cpp | 1 + src/bluetooth/qlowenergycontroller_p.h | 2 ++ 15 files changed, 63 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/bluetooth/qbluetoothaddress.cpp b/src/bluetooth/qbluetoothaddress.cpp index 8e3c29c6..5a0abf45 100644 --- a/src/bluetooth/qbluetoothaddress.cpp +++ b/src/bluetooth/qbluetoothaddress.cpp @@ -59,15 +59,13 @@ QT_BEGIN_NAMESPACE Returns true if the Bluetooth addresses are not equal, otherwise returns false. */ -namespace { -class BluetoothAddressRegisterMetaTypes +static void registerQBluetoothAddressMetaType() { -public: - BluetoothAddressRegisterMetaTypes() - { + static bool initDone = false; + if (!initDone) { qRegisterMetaType(); + initDone = true; } -} _registerBluetoothAddressMetaTypes; } /*! @@ -76,6 +74,7 @@ public: QBluetoothAddress::QBluetoothAddress() : d_ptr(new QBluetoothAddressPrivate) { + registerQBluetoothAddressMetaType(); } /*! @@ -84,6 +83,8 @@ QBluetoothAddress::QBluetoothAddress() : QBluetoothAddress::QBluetoothAddress(quint64 address) : d_ptr(new QBluetoothAddressPrivate) { + registerQBluetoothAddressMetaType(); + Q_D(QBluetoothAddress); d->m_address = address; } @@ -97,6 +98,8 @@ QBluetoothAddress::QBluetoothAddress(quint64 address) : QBluetoothAddress::QBluetoothAddress(const QString &address) : d_ptr(new QBluetoothAddressPrivate) { + registerQBluetoothAddressMetaType(); + Q_D(QBluetoothAddress); QString a = address; diff --git a/src/bluetooth/qbluetoothlocaldevice.cpp b/src/bluetooth/qbluetoothlocaldevice.cpp index 0eb97647..ddbce02b 100644 --- a/src/bluetooth/qbluetoothlocaldevice.cpp +++ b/src/bluetooth/qbluetoothlocaldevice.cpp @@ -97,20 +97,17 @@ QT_BEGIN_NAMESPACE */ -namespace { -class LocalDeviceRegisterMetaTypes +void registerQBluetoothLocalDeviceMetaType() { -public: - LocalDeviceRegisterMetaTypes() - { + static bool initDone = false; + if (!initDone) { qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); + initDone = true; } -} _registerLocalDeviceMetaTypes; } - #ifndef QT_OSX_BLUETOOTH /*! diff --git a/src/bluetooth/qbluetoothlocaldevice_android.cpp b/src/bluetooth/qbluetoothlocaldevice_android.cpp index 20ac3d0a..083bc190 100644 --- a/src/bluetooth/qbluetoothlocaldevice_android.cpp +++ b/src/bluetooth/qbluetoothlocaldevice_android.cpp @@ -52,6 +52,8 @@ QBluetoothLocalDevicePrivate::QBluetoothLocalDevicePrivate( obj(0), pendingHostModeTransition(false) { + registerQBluetoothLocalDeviceMetaType(); + initialize(address); receiver = new LocalDeviceBroadcastReceiver(q_ptr); diff --git a/src/bluetooth/qbluetoothlocaldevice_bluez.cpp b/src/bluetooth/qbluetoothlocaldevice_bluez.cpp index cae21e1b..9b550a1b 100644 --- a/src/bluetooth/qbluetoothlocaldevice_bluez.cpp +++ b/src/bluetooth/qbluetoothlocaldevice_bluez.cpp @@ -644,6 +644,8 @@ QBluetoothLocalDevicePrivate::QBluetoothLocalDevicePrivate(QBluetoothLocalDevice msgConnection(0), q_ptr(q) { + registerQBluetoothLocalDeviceMetaType(); + if (isBluez5()) initializeAdapterBluez5(); else diff --git a/src/bluetooth/qbluetoothlocaldevice_osx.mm b/src/bluetooth/qbluetoothlocaldevice_osx.mm index 71b7b81a..b1957d09 100644 --- a/src/bluetooth/qbluetoothlocaldevice_osx.mm +++ b/src/bluetooth/qbluetoothlocaldevice_osx.mm @@ -105,6 +105,8 @@ QBluetoothLocalDevicePrivate::QBluetoothLocalDevicePrivate(QBluetoothLocalDevice const QBluetoothAddress &address) : q_ptr(q) { + registerQBluetoothLocalDeviceMetaType(); + Q_ASSERT_X(q, Q_FUNC_INFO, "invalid q_ptr (null)"); QT_BT_MAC_AUTORELEASEPOOL; diff --git a/src/bluetooth/qbluetoothlocaldevice_p.cpp b/src/bluetooth/qbluetoothlocaldevice_p.cpp index 2785e84c..0b7c5c44 100644 --- a/src/bluetooth/qbluetoothlocaldevice_p.cpp +++ b/src/bluetooth/qbluetoothlocaldevice_p.cpp @@ -34,18 +34,22 @@ #include "qbluetoothlocaldevice.h" #include "qbluetoothaddress.h" +#include "qbluetoothlocaldevice_p.h" + QT_BEGIN_NAMESPACE QBluetoothLocalDevice::QBluetoothLocalDevice(QObject *parent) : QObject(parent), d_ptr(0) { + registerQBluetoothLocalDeviceMetaType(); } QBluetoothLocalDevice::QBluetoothLocalDevice(const QBluetoothAddress &, QObject *parent) : QObject(parent), d_ptr(0) { + registerQBluetoothLocalDeviceMetaType(); } QString QBluetoothLocalDevice::name() const diff --git a/src/bluetooth/qbluetoothlocaldevice_p.h b/src/bluetooth/qbluetoothlocaldevice_p.h index c47ceb9e..7bb343ac 100644 --- a/src/bluetooth/qbluetoothlocaldevice_p.h +++ b/src/bluetooth/qbluetoothlocaldevice_p.h @@ -83,6 +83,8 @@ QT_END_NAMESPACE QT_BEGIN_NAMESPACE +extern void registerQBluetoothLocalDeviceMetaType(); + class QBluetoothAddress; #ifdef QT_ANDROID_BLUETOOTH diff --git a/src/bluetooth/qbluetoothlocaldevice_qnx.cpp b/src/bluetooth/qbluetoothlocaldevice_qnx.cpp index c36fb89a..e4ac086a 100644 --- a/src/bluetooth/qbluetoothlocaldevice_qnx.cpp +++ b/src/bluetooth/qbluetoothlocaldevice_qnx.cpp @@ -211,6 +211,8 @@ void QBluetoothLocalDevice::pairingConfirmation(bool confirmation) QBluetoothLocalDevicePrivate::QBluetoothLocalDevicePrivate(QBluetoothLocalDevice *q) : q_ptr(q) { + registerQBluetoothLocalDeviceMetaType(); + ppsRegisterControl(); ppsRegisterForEvent(QStringLiteral("access_changed"), this); ppsRegisterForEvent(QStringLiteral("pairing_complete"), this); diff --git a/src/bluetooth/qbluetoothuuid.cpp b/src/bluetooth/qbluetoothuuid.cpp index cfce871c..3cef44b2 100644 --- a/src/bluetooth/qbluetoothuuid.cpp +++ b/src/bluetooth/qbluetoothuuid.cpp @@ -497,16 +497,13 @@ Q_GLOBAL_STATIC_WITH_ARGS(QUuid, baseUuid, ("{00000000-0000-1000-8000-00805F9B34 \value UnknownDescriptorType The descriptor type is unknown. */ -namespace +static void registerQBluetoothUuidMetaType() { - class BtUuidRegisterMetaTypes - { - public: - BtUuidRegisterMetaTypes() - { - qRegisterMetaType(); - } - } _registerBtUuidMetaTypes; + static bool initDone = false; + if (!initDone) { + qRegisterMetaType(); + initDone = true; + } } /*! @@ -514,6 +511,7 @@ namespace */ QBluetoothUuid::QBluetoothUuid() { + registerQBluetoothUuidMetaType(); } /*! @@ -525,6 +523,7 @@ QBluetoothUuid::QBluetoothUuid(ProtocolUuid uuid) baseUuid()->data4[2], baseUuid()->data4[3], baseUuid()->data4[4], baseUuid()->data4[5], baseUuid()->data4[6], baseUuid()->data4[7]) { + registerQBluetoothUuidMetaType(); } /*! @@ -535,6 +534,7 @@ QBluetoothUuid::QBluetoothUuid(ServiceClassUuid uuid) baseUuid()->data4[2], baseUuid()->data4[3], baseUuid()->data4[4], baseUuid()->data4[5], baseUuid()->data4[6], baseUuid()->data4[7]) { + registerQBluetoothUuidMetaType(); } /*! @@ -546,6 +546,7 @@ QBluetoothUuid::QBluetoothUuid(CharacteristicType uuid) baseUuid()->data4[2], baseUuid()->data4[3], baseUuid()->data4[4], baseUuid()->data4[5], baseUuid()->data4[6], baseUuid()->data4[7]) { + registerQBluetoothUuidMetaType(); } /*! @@ -557,7 +558,7 @@ QBluetoothUuid::QBluetoothUuid(DescriptorType uuid) baseUuid()->data4[2], baseUuid()->data4[3], baseUuid()->data4[4], baseUuid()->data4[5], baseUuid()->data4[6], baseUuid()->data4[7]) { - + registerQBluetoothUuidMetaType(); } /*! @@ -568,6 +569,7 @@ QBluetoothUuid::QBluetoothUuid(quint16 uuid) baseUuid()->data4[2], baseUuid()->data4[3], baseUuid()->data4[4], baseUuid()->data4[5], baseUuid()->data4[6], baseUuid()->data4[7]) { + registerQBluetoothUuidMetaType(); } /*! @@ -578,6 +580,7 @@ QBluetoothUuid::QBluetoothUuid(quint32 uuid) baseUuid()->data4[2], baseUuid()->data4[3], baseUuid()->data4[4], baseUuid()->data4[5], baseUuid()->data4[6], baseUuid()->data4[7]) { + registerQBluetoothUuidMetaType(); } /*! @@ -587,6 +590,7 @@ QBluetoothUuid::QBluetoothUuid(quint32 uuid) */ QBluetoothUuid::QBluetoothUuid(quint128 uuid) { + registerQBluetoothUuidMetaType(); QT_WARNING_PUSH QT_WARNING_DISABLE_GCC("-Wstrict-aliasing") data1 = qFromBigEndian(*reinterpret_cast(&uuid.data[0])); @@ -605,6 +609,7 @@ QT_WARNING_POP QBluetoothUuid::QBluetoothUuid(const QString &uuid) : QUuid(uuid) { + registerQBluetoothUuidMetaType(); } /*! @@ -613,6 +618,7 @@ QBluetoothUuid::QBluetoothUuid(const QString &uuid) QBluetoothUuid::QBluetoothUuid(const QBluetoothUuid &uuid) : QUuid(uuid) { + registerQBluetoothUuidMetaType(); } /*! @@ -621,6 +627,7 @@ QBluetoothUuid::QBluetoothUuid(const QBluetoothUuid &uuid) QBluetoothUuid::QBluetoothUuid(const QUuid &uuid) : QUuid(uuid) { + registerQBluetoothUuidMetaType(); } /*! diff --git a/src/bluetooth/qlowenergycontroller.cpp b/src/bluetooth/qlowenergycontroller.cpp index 44b6a6da..28012de5 100644 --- a/src/bluetooth/qlowenergycontroller.cpp +++ b/src/bluetooth/qlowenergycontroller.cpp @@ -194,18 +194,17 @@ QT_BEGIN_NAMESPACE \sa discoverServices(), error() */ -namespace { -class QLowEnergyControllerMetaTypes +void registerQLowEnergyControllerMetaType() { -public: - QLowEnergyControllerMetaTypes() - { + static bool initDone = false; + if (!initDone) { qRegisterMetaType(); qRegisterMetaType(); + initDone = true; } -} qLowEnergyControllerMetaTypes; } + void QLowEnergyControllerPrivate::setError( QLowEnergyController::Error newError) { diff --git a/src/bluetooth/qlowenergycontroller_android.cpp b/src/bluetooth/qlowenergycontroller_android.cpp index f48c0e85..3c462f8f 100644 --- a/src/bluetooth/qlowenergycontroller_android.cpp +++ b/src/bluetooth/qlowenergycontroller_android.cpp @@ -45,6 +45,7 @@ QLowEnergyControllerPrivate::QLowEnergyControllerPrivate() error(QLowEnergyController::NoError), hub(0) { + registerQLowEnergyControllerMetaType(); } QLowEnergyControllerPrivate::~QLowEnergyControllerPrivate() diff --git a/src/bluetooth/qlowenergycontroller_bluez.cpp b/src/bluetooth/qlowenergycontroller_bluez.cpp index 4cd3afe3..d9fea1e6 100644 --- a/src/bluetooth/qlowenergycontroller_bluez.cpp +++ b/src/bluetooth/qlowenergycontroller_bluez.cpp @@ -199,6 +199,7 @@ QLowEnergyControllerPrivate::QLowEnergyControllerPrivate() encryptionChangePending(false), hciManager(0) { + registerQLowEnergyControllerMetaType(); qRegisterMetaType >(); hciManager = new HciManager(localAdapter, this); diff --git a/src/bluetooth/qlowenergycontroller_osx.mm b/src/bluetooth/qlowenergycontroller_osx.mm index c4628069..4fbc5200 100644 --- a/src/bluetooth/qlowenergycontroller_osx.mm +++ b/src/bluetooth/qlowenergycontroller_osx.mm @@ -56,17 +56,15 @@ QT_BEGIN_NAMESPACE namespace { - -class QLowEnergyControllerMetaTypes +static void registerQLowEnergyControllerMetaType() { -public: - QLowEnergyControllerMetaTypes() - { + static bool initDone = false; + if (!initDone) { qRegisterMetaType(); qRegisterMetaType(); + initDone = true; } -} qLowEnergyControllerMetaTypes; - +} typedef QSharedPointer ServicePrivate; @@ -137,6 +135,8 @@ QLowEnergyControllerPrivateOSX::QLowEnergyControllerPrivateOSX(QLowEnergyControl controllerState(QLowEnergyController::UnconnectedState), addressType(QLowEnergyController::PublicAddress) { + registerQLowEnergyControllerMetaType(); + // This is the "wrong" constructor - no valid device UUID to connect later. Q_ASSERT_X(q, Q_FUNC_INFO, "invalid q_ptr (null)"); // We still create a manager, to simplify error handling later. @@ -157,6 +157,8 @@ QLowEnergyControllerPrivateOSX::QLowEnergyControllerPrivateOSX(QLowEnergyControl controllerState(QLowEnergyController::UnconnectedState), addressType(QLowEnergyController::PublicAddress) { + registerQLowEnergyControllerMetaType(); + Q_ASSERT_X(q, Q_FUNC_INFO, "invalid q_ptr (null)"); centralManager.reset([[ObjCCentralManager alloc] initWithDelegate:this]); if (!centralManager) { diff --git a/src/bluetooth/qlowenergycontroller_p.cpp b/src/bluetooth/qlowenergycontroller_p.cpp index b3c718b5..79addae2 100644 --- a/src/bluetooth/qlowenergycontroller_p.cpp +++ b/src/bluetooth/qlowenergycontroller_p.cpp @@ -40,6 +40,7 @@ QLowEnergyControllerPrivate::QLowEnergyControllerPrivate() state(QLowEnergyController::UnconnectedState), error(QLowEnergyController::NoError) { + registerQLowEnergyControllerMetaType(); } QLowEnergyControllerPrivate::~QLowEnergyControllerPrivate() diff --git a/src/bluetooth/qlowenergycontroller_p.h b/src/bluetooth/qlowenergycontroller_p.h index 810f0ff4..defc4127 100644 --- a/src/bluetooth/qlowenergycontroller_p.h +++ b/src/bluetooth/qlowenergycontroller_p.h @@ -73,6 +73,8 @@ class HciManager; class LowEnergyNotificationHub; #endif +extern void registerQLowEnergyControllerMetaType(); + typedef QMap > ServiceDataMap; class QLowEnergyControllerPrivate : public QObject -- cgit v1.2.3