diff --git a/src/NimBLECharacteristic.cpp b/src/NimBLECharacteristic.cpp index 343d4071..2965bb4b 100644 --- a/src/NimBLECharacteristic.cpp +++ b/src/NimBLECharacteristic.cpp @@ -434,9 +434,30 @@ void NimBLECharacteristic::readEvent(NimBLEConnInfo& connInfo) { */ void NimBLECharacteristic::writeEvent(const uint8_t* val, uint16_t len, NimBLEConnInfo& connInfo) { setValue(val, len); + m_writeError = 0; m_pCallbacks->onWrite(this, connInfo); } // writeEvent +/** + * @brief Set the ATT error code to return for the current write operation. + * @param [in] attError The ATT error code; 0 accepts the write. Use the + * Bluetooth-spec vendor-specific range 0x80-0x9F for application errors. + * Call this from your NimBLECharacteristicCallbacks::onWrite() implementation + * to reject the write; the stack will then send an ATT Error Response instead + * of a success response. Ignored for Write Commands (no response exists). + */ +void NimBLECharacteristic::setWriteError(uint8_t attError) { + m_writeError = attError; +} // setWriteError + +/** + * @brief Get the write error code set by the onWrite callback. + * @return The ATT error code for the current write operation, 0 if none was set. + */ +int NimBLECharacteristic::getWriteError() const { + return m_writeError; +} // getWriteError + /** * @brief Set the callback handlers for this characteristic. * @param [in] pCallbacks An instance of a NimBLECharacteristicCallbacks class\n diff --git a/src/NimBLECharacteristic.h b/src/NimBLECharacteristic.h index e3c70b63..d2c13b0e 100644 --- a/src/NimBLECharacteristic.h +++ b/src/NimBLECharacteristic.h @@ -76,6 +76,22 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute { NimBLECharacteristicCallbacks* getCallbacks() const; + /** + * @brief Set the ATT error code to return for the current write operation. + * @param [in] attError The ATT error code; 0 accepts the write. Use the + * Bluetooth-spec vendor-specific range 0x80-0x9F for application errors. + * Call this from your NimBLECharacteristicCallbacks::onWrite() implementation + * to reject the write; the stack will then send an ATT Error Response instead + * of a success response. Ignored for Write Commands (no response exists). + */ + void setWriteError(uint8_t attError); + + /** + * @brief Get the write error code set by the onWrite callback. + * @return The ATT error code for the current write operation, 0 if none was set. + */ + int getWriteError() const; + /*********************** Template Functions ************************/ # if __cplusplus < 201703L @@ -305,6 +321,7 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute { NimBLEService* m_pService{nullptr}; std::vector m_vDescriptors{}; mutable SubPeerArray m_subPeers{}; + int m_writeError = 0; }; // NimBLECharacteristic /** diff --git a/src/NimBLEServer.cpp b/src/NimBLEServer.cpp index 1cab58ed..469ed484 100644 --- a/src/NimBLEServer.cpp +++ b/src/NimBLEServer.cpp @@ -18,6 +18,7 @@ #include "NimBLEServer.h" #if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL) +# include "NimBLECharacteristic.h" # include "NimBLEDevice.h" # include "NimBLELog.h" @@ -774,7 +775,8 @@ int NimBLEServer::handleGattEvent(uint16_t connHandle, uint16_t attrHandle, ble_ } pAtt->writeEvent(buf, len, peerInfo); - return 0; + // Only characteristics carry the write error slot; descriptor writes keep succeeding. + return ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR ? static_cast(pAtt)->getWriteError() : 0; } default: