summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Blasche <alexander.blasche@theqtcompany.com>2016-05-17 15:01:39 +0200
committerAlex Blasche <alexander.blasche@theqtcompany.com>2016-05-18 13:10:04 +0000
commit0690d4801ca5ee92d5e7511d48d95786212d5fb3 (patch)
treebb6eb9eb9d1a659ca6d2a1a1b3dcbe7f33326981
parent014df77d92fb0070b2d95b9747a1a988e654355f (diff)
Fix endianness conversion order bug when handling 128bit Qt Uuid
QBluetoothUuid.toUInt128() always returns big endian notation. We have to convert it to host order before we convert to Bluetooth order. Task-number: QTBUG-53421 Change-Id: Ibab4f06fa70739adb163523c803a203608454427 Reviewed-by: Christian Kandeler <christian.kandeler@theqtcompany.com>
-rw-r--r--src/bluetooth/qleadvertiser_bluez.cpp8
-rw-r--r--src/bluetooth/qlowenergycontroller_bluez.cpp15
-rw-r--r--tests/auto/qlowenergycontroller-gattserver/server/qlowenergycontroller-gattserver.cpp13
-rw-r--r--tests/auto/qlowenergycontroller-gattserver/test/tst_qlowenergycontroller-gattserver.cpp45
4 files changed, 67 insertions, 14 deletions
diff --git a/src/bluetooth/qleadvertiser_bluez.cpp b/src/bluetooth/qleadvertiser_bluez.cpp
index c1b38acb..ff00b2b1 100644
--- a/src/bluetooth/qleadvertiser_bluez.cpp
+++ b/src/bluetooth/qleadvertiser_bluez.cpp
@@ -285,7 +285,13 @@ void QLeAdvertiserBluez::setServicesData(const QLowEnergyAdvertisingData &src, A
services32 << service32;
continue;
}
- services128 << service.toUInt128();
+
+ // QBluetoothUuid::toUInt128() is always Big-Endian
+ // convert it to host order
+ quint128 hostOrder;
+ quint128 qtUuidOrder = service.toUInt128();
+ ntoh128(&qtUuidOrder, &hostOrder);
+ services128 << hostOrder;
}
addServicesData(dest, services16);
addServicesData(dest, services32);
diff --git a/src/bluetooth/qlowenergycontroller_bluez.cpp b/src/bluetooth/qlowenergycontroller_bluez.cpp
index adac55fc..d4fe0232 100644
--- a/src/bluetooth/qlowenergycontroller_bluez.cpp
+++ b/src/bluetooth/qlowenergycontroller_bluez.cpp
@@ -235,10 +235,14 @@ template<typename T> static void putDataAndIncrement(const T &src, char *&dst)
template<> void putDataAndIncrement(const QBluetoothUuid &uuid, char *&dst)
{
const int uuidSize = getUuidSize(uuid);
- if (uuidSize == 2)
+ if (uuidSize == 2) {
putBtData(uuid.toUInt16(), dst);
- else
- putBtData(uuid.toUInt128(), dst);
+ } else {
+ quint128 hostOrder;
+ quint128 qtUuidOrder = uuid.toUInt128();
+ ntoh128(&qtUuidOrder, &hostOrder);
+ putBtData(hostOrder, dst);
+ }
dst += uuidSize;
}
template<> void putDataAndIncrement(const QByteArray &value, char *&dst)
@@ -2925,7 +2929,10 @@ static QByteArray uuidToByteArray(const QBluetoothUuid &uuid)
putBtData(uuid.toUInt16(), ba.data());
} else {
ba.resize(16);
- putBtData(uuid.toUInt128(), ba.data());
+ quint128 hostOrder;
+ quint128 qtUuidOrder = uuid.toUInt128();
+ ntoh128(&qtUuidOrder, &hostOrder);
+ putBtData(hostOrder, ba.data());
}
return ba;
}
diff --git a/tests/auto/qlowenergycontroller-gattserver/server/qlowenergycontroller-gattserver.cpp b/tests/auto/qlowenergycontroller-gattserver/server/qlowenergycontroller-gattserver.cpp
index 6fa9b023..1275aa65 100644
--- a/tests/auto/qlowenergycontroller-gattserver/server/qlowenergycontroller-gattserver.cpp
+++ b/tests/auto/qlowenergycontroller-gattserver/server/qlowenergycontroller-gattserver.cpp
@@ -145,6 +145,19 @@ void addCustomService()
serviceData.addCharacteristic(charData);
addService(serviceData);
+
+ // service with full 128 bit custom uuids
+ QLowEnergyServiceData serviceData128;
+ serviceData128.setUuid(QBluetoothUuid(QString("c47774c7-f237-4523-8968-e4ae75431daf")));
+ serviceData128.setType(QLowEnergyServiceData::ServiceTypePrimary);
+
+ QLowEnergyCharacteristicData charData128;
+ charData128.setUuid(QBluetoothUuid(QString("c0ad61b1-79e7-42f9-ace0-0a9aa0d0a4f8")));
+ charData128.setProperties(QLowEnergyCharacteristic::Read);
+ charData128.setValue(QByteArray(15, 'a'));
+ serviceData128.addCharacteristic(charData128);
+
+ addService(serviceData128);
}
void startAdvertising()
diff --git a/tests/auto/qlowenergycontroller-gattserver/test/tst_qlowenergycontroller-gattserver.cpp b/tests/auto/qlowenergycontroller-gattserver/test/tst_qlowenergycontroller-gattserver.cpp
index 937b9b5c..3df27d92 100644
--- a/tests/auto/qlowenergycontroller-gattserver/test/tst_qlowenergycontroller-gattserver.cpp
+++ b/tests/auto/qlowenergycontroller-gattserver/test/tst_qlowenergycontroller-gattserver.cpp
@@ -39,6 +39,7 @@
#include <QtBluetooth/qlowenergyservicedata.h>
#include <QtCore/qendian.h>
#include <QtCore/qscopedpointer.h>
+//#include <QtCore/qloggingcategory.h>
#include <QtTest/qsignalspy.h>
#include <QtTest/QtTest>
@@ -80,6 +81,7 @@ private:
void TestQLowEnergyControllerGattServer::initTestCase()
{
+ //QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
const QString serverAddress = qgetenv("QT_BT_GATTSERVER_TEST_ADDRESS");
if (serverAddress.isEmpty())
return;
@@ -235,7 +237,7 @@ void TestQLowEnergyControllerGattServer::advertisedData()
// name is seen on the scanning machine.
// QCOMPARE(m_serverInfo.name(), QString("Qt GATT server"));
- QCOMPARE(m_serverInfo.serviceUuids().count(), 3);
+ QVERIFY(m_serverInfo.serviceUuids().count() >= 3);
QVERIFY(m_serverInfo.serviceUuids().contains(QBluetoothUuid::GenericAccess));
QVERIFY(m_serverInfo.serviceUuids().contains(QBluetoothUuid::RunningSpeedAndCadence));
QVERIFY(m_serverInfo.serviceUuids().contains(QBluetoothUuid(quint16(0x2000))));
@@ -262,10 +264,11 @@ void TestQLowEnergyControllerGattServer::serverCommunication()
spy.reset(new QSignalSpy(m_leController.data(), &QLowEnergyController::discoveryFinished));
QVERIFY(spy->wait(30000));
const QList<QBluetoothUuid> serviceUuids = m_leController->services();
- QCOMPARE(serviceUuids.count(), 3);
+ QCOMPARE(serviceUuids.count(), 4);
QVERIFY(serviceUuids.contains(QBluetoothUuid::GenericAccess));
QVERIFY(serviceUuids.contains(QBluetoothUuid::RunningSpeedAndCadence));
QVERIFY(serviceUuids.contains(QBluetoothUuid(quint16(0x2000))));
+ QVERIFY(serviceUuids.contains(QBluetoothUuid(QString("c47774c7-f237-4523-8968-e4ae75431daf"))));
const QScopedPointer<QLowEnergyService> genericAccessService(
m_leController->createServiceObject(QBluetoothUuid::GenericAccess));
@@ -324,6 +327,26 @@ void TestQLowEnergyControllerGattServer::serverCommunication()
featureChar.value().constData()));
QCOMPARE(value, quint16(1 << 2));
+ // 128 bit custom uuid service
+ QBluetoothUuid serviceUuid128(QString("c47774c7-f237-4523-8968-e4ae75431daf"));
+ QBluetoothUuid charUuid128(QString("c0ad61b1-79e7-42f9-ace0-0a9aa0d0a4f8"));
+ QScopedPointer<QLowEnergyService> customService128(
+ m_leController->createServiceObject(serviceUuid128));
+ QVERIFY(!customService128.isNull());
+ customService128->discoverDetails();
+ while (customService128->state() != QLowEnergyService::ServiceDiscovered) {
+ spy.reset(new QSignalSpy(customService128.data(), &QLowEnergyService::stateChanged));
+ QVERIFY(spy->wait(5000));
+ }
+ QCOMPARE(customService128->serviceUuid(), serviceUuid128);
+ QCOMPARE(customService128->includedServices().count(), 0);
+ QCOMPARE(customService128->characteristics().count(), 1);
+ QLowEnergyCharacteristic customChar128
+ = customService128->characteristic(charUuid128);
+ QVERIFY(customChar128.isValid());
+ QCOMPARE(customChar128.descriptors().count(), 0);
+ QCOMPARE(customChar128.value(), QByteArray(15, 'a'));
+
QScopedPointer<QLowEnergyService> customService(
m_leController->createServiceObject(QBluetoothUuid(quint16(0x2000))));
QVERIFY(!customService.isNull());
@@ -380,11 +403,14 @@ void TestQLowEnergyControllerGattServer::serverCommunication()
QVERIFY(spy->wait(3000));
QCOMPARE(customService->error(), QLowEnergyService::CharacteristicWriteError);
- const bool isBonded = QBluetoothLocalDevice().pairingStatus(m_serverAddress)
- != QBluetoothLocalDevice::Unpaired;
-
+ spy.reset(new QSignalSpy(customService.data(), static_cast<void (QLowEnergyService::*)
+ (QLowEnergyService::ServiceError)>(&QLowEnergyService::error)));
customService->writeCharacteristic(customChar5, "1", QLowEnergyService::WriteSigned);
- if (isBonded) {
+
+ // error might happen immediately or once event loop comes back
+ bool wasError = ((spy->count() > 0) || spy->wait(3000)); //
+
+ if (!wasError) {
// Signed write is done twice to test the sign counter stuff.
// Note: We assume here that the link is not encrypted, as this information is not exported.
customService->readCharacteristic(customChar5);
@@ -397,9 +423,6 @@ void TestQLowEnergyControllerGattServer::serverCommunication()
QVERIFY(spy->wait(3000));
QCOMPARE(customChar5.value(), QByteArray("2"));
} else {
- spy.reset(new QSignalSpy(customService.data(), static_cast<void (QLowEnergyService::*)
- (QLowEnergyService::ServiceError)>(&QLowEnergyService::error)));
- QVERIFY(spy->wait(3000));
QCOMPARE(customService->error(), QLowEnergyService::CharacteristicWriteError);
}
@@ -424,6 +447,7 @@ void TestQLowEnergyControllerGattServer::serverCommunication()
QCOMPARE(customChar3.value().constData(), "indicated");
QCOMPARE(customChar4.value().constData(), "notified");
+ // signal requires root privileges on Linux
spy.reset(new QSignalSpy(m_leController.data(), &QLowEnergyController::connectionUpdated));
QVERIFY(spy->wait(5000));
@@ -464,6 +488,9 @@ void TestQLowEnergyControllerGattServer::serverCommunication()
QVERIFY(cc3ClientConfig.isValid());
cc4ClientConfig = customChar4.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
QVERIFY(cc4ClientConfig.isValid());
+
+ const bool isBonded = QBluetoothLocalDevice().pairingStatus(m_serverAddress)
+ != QBluetoothLocalDevice::Unpaired;
if (isBonded) {
QCOMPARE(cc3ClientConfig.value(), indicateValue);
QCOMPARE(cc4ClientConfig.value(), notifyValue);