summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Blasche <alexander.blasche@theqtcompany.com>2015-04-01 17:17:22 +0200
committerAlex Blasche <alexander.blasche@theqtcompany.com>2015-04-15 05:44:26 +0000
commit5be8b3d9273afcd41c6c60e6f6d2dfd5cd8b30e3 (patch)
tree08ec49c6cb04c0be06b8e3d73a384287f0946f00
parent99d62bcce229ab2807f0ea5b8a0f618b4e93c665 (diff)
Always read/write the GATT hardware even if meta data reports otherwise
It is possible that a ATT attribute is not readable or writable. Usually this is reported via descriptors or other types of meta data. However it is possible that the meta data is reporting the wrong information. Therefore we always ensure that every read and write request is forwarded to the hardware. It is up to the hardware to respond to such requests. This change keeps the device usable in cases of buggy device meta data. This only affected writeCharacteristic() calls. Change-Id: Ieb2b95f47aa51c86a8ae7c4bebed4043d7478874 Reviewed-by: Alex Blasche <alexander.blasche@theqtcompany.com> Reviewed-by: Timur Pocheptsov <Timur.Pocheptsov@digia.com>
-rw-r--r--src/bluetooth/qlowenergyservice.cpp30
-rw-r--r--src/bluetooth/qlowenergyservice_osx.mm4
-rw-r--r--tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp4
3 files changed, 23 insertions, 15 deletions
diff --git a/src/bluetooth/qlowenergyservice.cpp b/src/bluetooth/qlowenergyservice.cpp
index 21090c77..8530c8b8 100644
--- a/src/bluetooth/qlowenergyservice.cpp
+++ b/src/bluetooth/qlowenergyservice.cpp
@@ -550,17 +550,21 @@ bool QLowEnergyService::contains(const QLowEnergyCharacteristic &characteristic)
/*!
Reads the value of \a characteristic. If the operation is successful, the
\l characteristicRead() signal is emitted; otherwise the \l CharacteristicReadError
- is set.
+ is set. In general, a \a characteristic is readable, if its
+ \l QLowEnergyCharacteristic::Read property is set.
All descriptor and characteristic requests towards the same remote device are
serialised. A queue is employed when issuing multiple requests at the same time.
The queue does not eliminate duplicated read requests for the same characteristic.
A characteristic can only be read if the service is in the \l ServiceDiscovered state,
- belongs to the service and is readable. If \a characteristic is readable its
- \l QLowEnergyCharacteristic::Read property is set. If one of those conditions is
+ belongs to the service. If one of these conditions is
not true the \l QLowEnergyService::OperationError is set.
+ \note Calling this function despite \l properties() reporting a non-readable property
+ always attempts to read the characteristic's value on the hardware. If the hardware
+ returns with an error the \l CharacteristicWriteError is set.
+
\sa characteristicRead()
\since 5.5
@@ -602,9 +606,15 @@ void QLowEnergyService::readCharacteristic(
Bluetooth specification.
A characteristic can only be written if this service is in the \l ServiceDiscovered state,
- belongs to the service and is writable. If one of those conditions is
+ and belongs to the service. If one of these conditions is
not true the \l QLowEnergyService::OperationError is set.
+ \note Calling this function despite \l properties() reporting a non-writable property
+ always attempts to write to the hardware. Similarly, a \l WriteWithoutResponse
+ is sent to the hardware too although the characteristic may only support
+ \l WriteWithResponse. If the hardware returns with an error the
+ \l CharacteristicWriteError is set.
+
\sa QLowEnergyCharacteristic::properties()
*/
void QLowEnergyService::writeCharacteristic(
@@ -622,15 +632,13 @@ void QLowEnergyService::writeCharacteristic(
}
// don't write if properties don't permit it
- if (mode == WriteWithResponse
- && (characteristic.properties() & QLowEnergyCharacteristic::Write))
+ if (mode == WriteWithResponse)
{
d->controller->writeCharacteristic(characteristic.d_ptr,
characteristic.attributeHandle(),
newValue,
true);
- } else if (mode == WriteWithoutResponse
- && (characteristic.properties() & QLowEnergyCharacteristic::WriteNoResponse)) {
+ } else if (mode == WriteWithoutResponse) {
d->controller->writeCharacteristic(characteristic.d_ptr,
characteristic.attributeHandle(),
newValue,
@@ -671,8 +679,8 @@ bool QLowEnergyService::contains(const QLowEnergyDescriptor &descriptor) const
serialised. A queue is employed when issuing multiple requests at the same time.
The queue does not eliminate duplicated read requests for the same descriptor.
- A descriptor can only be written if the service is in the \l ServiceDiscovered state,
- belongs to the service and is readable. If one of those conditions is
+ A descriptor can only be written if the service is in the \l ServiceDiscovered state
+ and belongs to the service. If one of these conditions is
not true the \l QLowEnergyService::OperationError is set.
\sa descriptorRead()
@@ -708,7 +716,7 @@ void QLowEnergyService::readDescriptor(
to B, the two write request are executed in the given order.
A descriptor can only be written if this service is in the \l ServiceDiscovered state,
- belongs to the service and is writable. If one of those conditions is
+ belongs to the service. If one of these conditions is
not true the \l QLowEnergyService::OperationError is set.
*/
void QLowEnergyService::writeDescriptor(const QLowEnergyDescriptor &descriptor,
diff --git a/src/bluetooth/qlowenergyservice_osx.mm b/src/bluetooth/qlowenergyservice_osx.mm
index 51b0f53d..b5d89dd7 100644
--- a/src/bluetooth/qlowenergyservice_osx.mm
+++ b/src/bluetooth/qlowenergyservice_osx.mm
@@ -200,9 +200,9 @@ void QLowEnergyService::writeCharacteristic(const QLowEnergyCharacteristic &ch,
}
// Don't write if properties don't permit it
- if (mode == WriteWithResponse && (ch.properties() & QLowEnergyCharacteristic::Write))
+ if (mode == WriteWithResponse)
controller->writeCharacteristic(ch.d_ptr, ch.attributeHandle(), newValue, true);
- else if (mode == WriteWithoutResponse && (ch.properties() & QLowEnergyCharacteristic::WriteNoResponse))
+ else if (mode == WriteWithoutResponse)
controller->writeCharacteristic(ch.d_ptr, ch.attributeHandle(), newValue, false);
else
d_ptr->setError(QLowEnergyService::OperationError);
diff --git a/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp b/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp
index 7e96c204..5d7339a7 100644
--- a/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp
+++ b/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp
@@ -1801,8 +1801,8 @@ void tst_QLowEnergyController::tst_writeCharacteristic()
QTRY_VERIFY_WITH_TIMEOUT(!errorSpy.isEmpty(), 10000);
QCOMPARE(errorSpy[0].at(0).value<QLowEnergyService::ServiceError>(),
- QLowEnergyService::OperationError);
- QCOMPARE(service->error(), QLowEnergyService::OperationError);
+ QLowEnergyService::CharacteristicWriteError);
+ QCOMPARE(service->error(), QLowEnergyService::CharacteristicWriteError);
QCOMPARE(writeSpy.count(), 0);
QCOMPARE(dataChar.value(), QByteArray::fromHex("3f00"));