From 2ddfc385e9532463342dfc2c9adb570a21874113 Mon Sep 17 00:00:00 2001 From: lianggao Date: Fri, 13 Jan 2017 22:07:08 +0800 Subject: [PATCH] Jira 794 Inconsistent writeInt() result with different Peripherals, git 385 Root cause: - As a Central, the write() operation can produce two different commands to a Peripheral depending on the Characteristic. - One command is a simple write without aknowledgement from Peripheral and the other requires a complete handshake for each write operation. - Root cause of the issue was that the function, BLECharacteristicImp::write(), did not check the characteristic property to determine if the caller requires a response. It just treats all calls do not require a response. Feature added: - For write with respond from Peripheral, it is now a blocking call (it also satisfied Arduino's request). Modifications: 1. libraries/CurieBLE/src/internal/BLECallbacks.cpp: - ble_on_write_no_rsp_complete: CB to process Peripheral Response to complete a write operation. 2. libraries/CurieBLE/src/internal/BLECallbacks.h: - Function definition added. 3. libraries/CurieBLE/src/internal/BLECharacteristicImp.cpp: - In function write(), check the characteristic property to determine whether the call requires a response. - Added a flag to signal the waiting on Peripheral Response for a write operation. - Write with response is now a blocking call. 4. BLECharacteristicImp.h: - Prototyping. --- .../CurieBLE/src/internal/BLECallbacks.cpp | 5 +++ .../CurieBLE/src/internal/BLECallbacks.h | 3 ++ .../src/internal/BLECharacteristicImp.cpp | 39 +++++++++++++++---- .../src/internal/BLECharacteristicImp.h | 5 +++ 4 files changed, 45 insertions(+), 7 deletions(-) diff --git a/libraries/CurieBLE/src/internal/BLECallbacks.cpp b/libraries/CurieBLE/src/internal/BLECallbacks.cpp index b6234750..568c54f8 100644 --- a/libraries/CurieBLE/src/internal/BLECallbacks.cpp +++ b/libraries/CurieBLE/src/internal/BLECallbacks.cpp @@ -223,4 +223,9 @@ void ble_central_device_found(const bt_addr_le_t *addr, ad, len); } +void ble_on_write_no_rsp_complete(struct bt_conn *conn, uint8_t err, + const void *data) +{ + BLECharacteristicImp::writeResponseReceived(conn, err, data); +} diff --git a/libraries/CurieBLE/src/internal/BLECallbacks.h b/libraries/CurieBLE/src/internal/BLECallbacks.h index 882c134a..213bd794 100644 --- a/libraries/CurieBLE/src/internal/BLECallbacks.h +++ b/libraries/CurieBLE/src/internal/BLECallbacks.h @@ -74,5 +74,8 @@ uint8_t profile_service_read_rsp_process(bt_conn_t *conn, const void *data, uint16_t length); +void ble_on_write_no_rsp_complete(struct bt_conn *conn, uint8_t err, + const void *data); + #endif diff --git a/libraries/CurieBLE/src/internal/BLECharacteristicImp.cpp b/libraries/CurieBLE/src/internal/BLECharacteristicImp.cpp index a5a60c57..91c46a8a 100644 --- a/libraries/CurieBLE/src/internal/BLECharacteristicImp.cpp +++ b/libraries/CurieBLE/src/internal/BLECharacteristicImp.cpp @@ -27,6 +27,7 @@ bt_uuid_16_t BLECharacteristicImp::_gatt_chrc_uuid = {BT_UUID_TYPE_16, BT_UUID_GATT_CHRC_VAL}; bt_uuid_16_t BLECharacteristicImp::_gatt_ccc_uuid = {BT_UUID_TYPE_16, BT_UUID_GATT_CCC_VAL}; +volatile bool BLECharacteristicImp::_gattc_writing = false; BLECharacteristicImp::BLECharacteristicImp(const bt_uuid_t* uuid, unsigned char properties, @@ -637,13 +638,20 @@ bool BLECharacteristicImp::read() return _reading; } +void BLECharacteristicImp::writeResponseReceived(struct bt_conn *conn, + uint8_t err, + const void *data) +{ + _gattc_writing = false; +} + bool BLECharacteristicImp::write(const unsigned char value[], uint16_t length) { int retval = 0; bt_conn_t* conn = NULL; - if (true == BLEUtils::isLocalBLE(_ble_device)) + if (true == BLEUtils::isLocalBLE(_ble_device) || true == _gattc_writing) { // GATT server can't write return false; @@ -655,12 +663,29 @@ bool BLECharacteristicImp::write(const unsigned char value[], return false; } - // Send read request - retval = bt_gatt_write_without_response(conn, - _value_handle, - value, - length, - false); + // Send write request + if (_gatt_chrc.properties | BT_GATT_CHRC_WRITE_WITHOUT_RESP) + { + retval = bt_gatt_write_without_response(conn, + _value_handle, + value, + length, + false); + } + else if (_gatt_chrc.properties | BT_GATT_CHRC_WRITE) + { + _gattc_writing = true; + retval = bt_gatt_write(conn, + _value_handle, + 0, + value, + length, + ble_on_write_no_rsp_complete); + while (_gattc_writing) + { + delay(2); + } + } bt_conn_unref(conn); return (0 == retval); } diff --git a/libraries/CurieBLE/src/internal/BLECharacteristicImp.h b/libraries/CurieBLE/src/internal/BLECharacteristicImp.h index c6cee5ab..1066992c 100644 --- a/libraries/CurieBLE/src/internal/BLECharacteristicImp.h +++ b/libraries/CurieBLE/src/internal/BLECharacteristicImp.h @@ -168,6 +168,10 @@ class BLECharacteristicImp: public BLEAttribute{ */ bool write(const unsigned char value[], uint16_t length); + + static void writeResponseReceived(struct bt_conn *conn, + uint8_t err, + const void *data); int descriptorCount() const; uint8_t discoverResponseProc(bt_conn_t *conn, @@ -325,6 +329,7 @@ class BLECharacteristicImp: public BLEAttribute{ bool _subscribed; bool _reading; + static volatile bool _gattc_writing; bt_gatt_read_params_t _read_params; // GATT read parameter typedef LinkNode BLEDescriptorLinkNodeHeader;