From 5be8b3d9273afcd41c6c60e6f6d2dfd5cd8b30e3 Mon Sep 17 00:00:00 2001 From: Alex Blasche Date: Wed, 1 Apr 2015 17:17:22 +0200 Subject: 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 Reviewed-by: Timur Pocheptsov --- src/bluetooth/qlowenergyservice.cpp | 30 +++++++++++++++++++----------- src/bluetooth/qlowenergyservice_osx.mm | 4 ++-- 2 files changed, 21 insertions(+), 13 deletions(-) (limited to 'src') 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); -- cgit v1.2.3