diff options
author | Alex Blasche <alexander.blasche@theqtcompany.com> | 2015-04-01 17:17:22 +0200 |
---|---|---|
committer | Alex Blasche <alexander.blasche@theqtcompany.com> | 2015-04-15 05:44:26 +0000 |
commit | 5be8b3d9273afcd41c6c60e6f6d2dfd5cd8b30e3 (patch) | |
tree | 08ec49c6cb04c0be06b8e3d73a384287f0946f00 | |
parent | 99d62bcce229ab2807f0ea5b8a0f618b4e93c665 (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.cpp | 30 | ||||
-rw-r--r-- | src/bluetooth/qlowenergyservice_osx.mm | 4 | ||||
-rw-r--r-- | tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp | 4 |
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")); |