diff --git a/src/NimBLECharacteristic.cpp b/src/NimBLECharacteristic.cpp index 1ffa2bd9..c5c25368 100644 --- a/src/NimBLECharacteristic.cpp +++ b/src/NimBLECharacteristic.cpp @@ -28,6 +28,7 @@ # include "NimBLE2904.h" # include "NimBLEDevice.h" # include "NimBLELog.h" +# include "NimBLELocalValueAttribute.h" static NimBLECharacteristicCallbacks defaultCallback; static const char* LOG_TAG = "NimBLECharacteristic"; @@ -328,13 +329,17 @@ bool NimBLECharacteristic::sendValue(const uint8_t* value, size_t length, bool i return true; } // sendValue -void NimBLECharacteristic::readEvent(NimBLEConnInfo& connInfo) { +void NimBLECharacteristic::readEvent(NimBLEConnInfo& connInfo, NimBLEReadEventArgs& args) { m_pCallbacks->onRead(this, connInfo); + m_pCallbacks->onRead(this, connInfo, args); } // readEvent -void NimBLECharacteristic::writeEvent(const uint8_t* val, uint16_t len, NimBLEConnInfo& connInfo) { - setValue(val, len); +void NimBLECharacteristic::writeEvent(const uint8_t* val, uint16_t len, NimBLEConnInfo& connInfo, NimBLEWriteEventArgs& args) { m_pCallbacks->onWrite(this, connInfo); + m_pCallbacks->onWrite(this, connInfo, args); + if(!args.isCanceled()) { + setValue(val, len); + } } // writeEvent /** @@ -381,9 +386,21 @@ std::string NimBLECharacteristic::toString() const { * @param [in] pCharacteristic The characteristic that is the source of the event. * @param [in] connInfo A reference to a NimBLEConnInfo instance containing the peer info. */ +void NimBLECharacteristicCallbacks::onRead(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo, NimBLEReadEventArgs& args) { + NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onRead: default"); +} // onRead + void NimBLECharacteristicCallbacks::onRead(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo) { NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onRead: default"); } // onRead +/** + * @brief Callback function to support a write request. + * @param [in] pCharacteristic The characteristic that is the source of the event. + * @param [in] connInfo A reference to a NimBLEConnInfo instance containing the peer info. + */ +void NimBLECharacteristicCallbacks::onWrite(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo, NimBLEWriteEventArgs& args) { + NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onWrite: default"); +} // onWrite /** * @brief Callback function to support a write request. @@ -393,7 +410,6 @@ void NimBLECharacteristicCallbacks::onRead(NimBLECharacteristic* pCharacteristic void NimBLECharacteristicCallbacks::onWrite(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo) { NIMBLE_LOGD("NimBLECharacteristicCallbacks", "onWrite: default"); } // onWrite - /** * @brief Callback function to support a Notify/Indicate Status report. * @param [in] pCharacteristic The characteristic that is the source of the event. diff --git a/src/NimBLECharacteristic.h b/src/NimBLECharacteristic.h index 789d21d7..dd2070a7 100644 --- a/src/NimBLECharacteristic.h +++ b/src/NimBLECharacteristic.h @@ -28,6 +28,7 @@ class NimBLEDescriptor; class NimBLE2904; # include "NimBLELocalValueAttribute.h" +# include "NimBLEDevice.h" # include # include @@ -226,8 +227,8 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute { friend class NimBLEService; void setService(NimBLEService* pService); - void readEvent(NimBLEConnInfo& connInfo) override; - void writeEvent(const uint8_t* val, uint16_t len, NimBLEConnInfo& connInfo) override; + void readEvent(NimBLEConnInfo& connInfo, NimBLEReadEventArgs& args) override; + void writeEvent(const uint8_t* val, uint16_t len, NimBLEConnInfo& connInfo, NimBLEWriteEventArgs& args) override; bool sendValue(const uint8_t* value, size_t length, bool is_notification = true, @@ -249,7 +250,9 @@ class NimBLECharacteristicCallbacks { public: virtual ~NimBLECharacteristicCallbacks() {} virtual void onRead(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo); + virtual void onRead(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo, NimBLEReadEventArgs& args); virtual void onWrite(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo); + virtual void onWrite(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo, NimBLEWriteEventArgs& args); virtual void onStatus(NimBLECharacteristic* pCharacteristic, int code); virtual void onSubscribe(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo, uint16_t subValue); }; diff --git a/src/NimBLEConnInfo.h b/src/NimBLEConnInfo.h index cd1e4c3e..767dcfc2 100644 --- a/src/NimBLEConnInfo.h +++ b/src/NimBLEConnInfo.h @@ -25,6 +25,7 @@ #endif #include "NimBLEAddress.h" +#include "buffer.h" /** * @brief Connection information. diff --git a/src/NimBLEDescriptor.cpp b/src/NimBLEDescriptor.cpp index 8f1bb41e..99fccc60 100644 --- a/src/NimBLEDescriptor.cpp +++ b/src/NimBLEDescriptor.cpp @@ -18,6 +18,9 @@ #include "NimBLEDescriptor.h" #if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL) +# include "NimBLELocalAttribute.h" +# include "NimBLEValueAttribute.h" +# include "NimBLELocalValueAttribute.h" # include "NimBLEService.h" # include "NimBLELog.h" @@ -120,13 +123,17 @@ std::string NimBLEDescriptor::toString() const { return res; } // toString -void NimBLEDescriptor::readEvent(NimBLEConnInfo& connInfo) { +void NimBLEDescriptor::readEvent(NimBLEConnInfo& connInfo, NimBLEReadEventArgs& args) { m_pCallbacks->onRead(this, connInfo); + m_pCallbacks->onRead(this, connInfo, args); } // readEvent -void NimBLEDescriptor::writeEvent(const uint8_t* val, uint16_t len, NimBLEConnInfo& connInfo) { - setValue(val, len); +void NimBLEDescriptor::writeEvent(const uint8_t* val, uint16_t len, NimBLEConnInfo& connInfo, NimBLEWriteEventArgs& args) { m_pCallbacks->onWrite(this, connInfo); + m_pCallbacks->onWrite(this, connInfo, args); + if(!args.isCanceled()) { + setValue(val, len); + } } // writeEvent /** @@ -134,10 +141,27 @@ void NimBLEDescriptor::writeEvent(const uint8_t* val, uint16_t len, NimBLEConnIn * @param [in] pDescriptor The descriptor that is the source of the event. * @param [in] connInfo A reference to a NimBLEConnInfo instance containing the peer info. */ -void NimBLEDescriptorCallbacks::onRead(NimBLEDescriptor* pDescriptor, NimBLEConnInfo& connInfo) { +void NimBLEDescriptorCallbacks::onRead(NimBLEDescriptor* pDescriptor, NimBLEConnInfo& connInfo, NimBLEReadEventArgs& args) { NIMBLE_LOGD("NimBLEDescriptorCallbacks", "onRead: default"); } // onRead + +/** + * @brief Callback function to support a read request. + * @param [in] pDescriptor The descriptor that is the source of the event. + * @param [in] connInfo A reference to a NimBLEConnInfo instance containing the peer info. + */ +void NimBLEDescriptorCallbacks::onRead(NimBLEDescriptor* pDescriptor, NimBLEConnInfo& connInfo) { + NIMBLE_LOGD("NimBLEDescriptorCallbacks", "onRead: default"); +} // onRead +/** + * @brief Callback function to support a write request. + * @param [in] pDescriptor The descriptor that is the source of the event. + * @param [in] connInfo A reference to a NimBLEConnInfo instance containing the peer info. + */ +void NimBLEDescriptorCallbacks::onWrite(NimBLEDescriptor* pDescriptor, NimBLEConnInfo& connInfo, NimBLEWriteEventArgs& args) { + NIMBLE_LOGD("NimBLEDescriptorCallbacks", "onWrite: default"); +} // onWrite /** * @brief Callback function to support a write request. * @param [in] pDescriptor The descriptor that is the source of the event. @@ -147,4 +171,4 @@ void NimBLEDescriptorCallbacks::onWrite(NimBLEDescriptor* pDescriptor, NimBLECon NIMBLE_LOGD("NimBLEDescriptorCallbacks", "onWrite: default"); } // onWrite -#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL) +#endif // CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL) \ No newline at end of file diff --git a/src/NimBLEDescriptor.h b/src/NimBLEDescriptor.h index b6e9b8f2..d4c5d4e4 100644 --- a/src/NimBLEDescriptor.h +++ b/src/NimBLEDescriptor.h @@ -21,7 +21,8 @@ #include "syscfg/syscfg.h" #if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL) -# include "NimBLELocalValueAttribute.h" +#include "NimBLELocalValueAttribute.h" +# include "NimBLEDevice.h" # include class NimBLECharacteristic; @@ -49,8 +50,8 @@ class NimBLEDescriptor : public NimBLELocalValueAttribute { friend class NimBLEService; void setCharacteristic(NimBLECharacteristic* pChar); - void readEvent(NimBLEConnInfo& connInfo) override; - void writeEvent(const uint8_t* val, uint16_t len, NimBLEConnInfo& connInfo) override; + void readEvent(NimBLEConnInfo& connInfo, NimBLEReadEventArgs& args) override; + void writeEvent(const uint8_t* val, uint16_t len, NimBLEConnInfo& connInfo, NimBLEWriteEventArgs& args) override; NimBLEDescriptorCallbacks* m_pCallbacks{nullptr}; NimBLECharacteristic* m_pCharacteristic{nullptr}; @@ -67,7 +68,9 @@ class NimBLEDescriptorCallbacks { public: virtual ~NimBLEDescriptorCallbacks() = default; virtual void onRead(NimBLEDescriptor* pDescriptor, NimBLEConnInfo& connInfo); + virtual void onRead(NimBLEDescriptor* pDescriptor, NimBLEConnInfo& connInfo, NimBLEReadEventArgs& args); virtual void onWrite(NimBLEDescriptor* pDescriptor, NimBLEConnInfo& connInfo); + virtual void onWrite(NimBLEDescriptor* pDescriptor, NimBLEConnInfo& connInfo, NimBLEWriteEventArgs& args); }; # include "NimBLE2904.h" diff --git a/src/NimBLEDevice.h b/src/NimBLEDevice.h index 37075009..333d20cd 100644 --- a/src/NimBLEDevice.h +++ b/src/NimBLEDevice.h @@ -15,9 +15,11 @@ * limitations under the License. */ + #ifndef NIMBLE_CPP_DEVICE_H_ #define NIMBLE_CPP_DEVICE_H_ +#include "nimconfig.h" #include "syscfg/syscfg.h" #if CONFIG_BT_NIMBLE_ENABLED # ifdef ESP_PLATFORM @@ -66,11 +68,18 @@ class NimBLEL2CAPServer; # if MYNEWT_VAL(BLE_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_ROLE_CENTRAL) class NimBLEConnInfo; + +class buffer; +class NimBLEReadEventArgs; +class NimBLEWriteEventArgs; + # endif + class NimBLEAddress; class NimBLEDeviceCallbacks; + # define BLEDevice NimBLEDevice # define BLEClient NimBLEClient # define BLERemoteService NimBLERemoteService diff --git a/src/NimBLEEventArgs.h b/src/NimBLEEventArgs.h new file mode 100644 index 00000000..adb0b5a9 --- /dev/null +++ b/src/NimBLEEventArgs.h @@ -0,0 +1,66 @@ +// +// Created by hoeflich on 30.07.2025. +// + +#ifndef NIMBLEEVENTS_H +#define NIMBLEEVENTS_H + +#if CONFIG_BT_ENABLED && (CONFIG_BT_NIMBLE_ROLE_PERIPHERAL || CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#include "buffer.h" +#include +#include + +class NimBLEReadEventArgs{ +public: + void overwriteReturnValue(const uint8_t* value, int size) { + data = new buffer(size); + std::memcpy(data->getPointer(), value, size); + } + + bool isDataOverwritten() const { return data != nullptr; } + + buffer* getData() { return data; } + + NimBLEReadEventArgs() {} + + ~NimBLEReadEventArgs() { + if(data != nullptr) + delete data; + } +private: + buffer* data = nullptr; +}; + +class NimBLEWriteEventArgs{ +public: + void Cancel(){ + canceled = true; + } + + bool isCanceled(){ + return canceled; + } + + std::string GetOldData(){ + return oldData; + } + + std::string GetNewData(){ + return newData; + } + + NimBLEWriteEventArgs(std::string oldData, std::string newData) { + this->oldData = oldData; + this->newData = newData; + } + + ~NimBLEWriteEventArgs() { + } +private: + std::string oldData; + std::string newData; + bool canceled = false; +}; + +#endif +#endif //NIMBLEEVENTS_H diff --git a/src/NimBLEHIDDevice.cpp b/src/NimBLEHIDDevice.cpp index 105ef11b..fc54745d 100644 --- a/src/NimBLEHIDDevice.cpp +++ b/src/NimBLEHIDDevice.cpp @@ -18,6 +18,7 @@ #include "NimBLEHIDDevice.h" #if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_BROADCASTER) && MYNEWT_VAL(BLE_ROLE_PERIPHERAL) +# include "NimBLEDevice.h" # include "NimBLEServer.h" # include "NimBLEService.h" # include "NimBLE2904.h" diff --git a/src/NimBLELocalValueAttribute.h b/src/NimBLELocalValueAttribute.h index 56acb729..536066ab 100644 --- a/src/NimBLELocalValueAttribute.h +++ b/src/NimBLELocalValueAttribute.h @@ -51,6 +51,7 @@ typedef enum { # include "NimBLEValueAttribute.h" # include "NimBLEAttValue.h" # include +#include "NimBLEEventArgs.h" class NimBLEConnInfo; class NimBLELocalValueAttribute : public NimBLELocalAttribute, public NimBLEValueAttribute { @@ -113,7 +114,7 @@ class NimBLELocalValueAttribute : public NimBLELocalAttribute, public NimBLEValu * @param [in] connInfo A reference to a NimBLEConnInfo instance containing the peer info. * @details This function is called by NimBLEServer when a read request is received. */ - virtual void readEvent(NimBLEConnInfo& connInfo) = 0; + virtual void readEvent(NimBLEConnInfo& connInfo, NimBLEReadEventArgs& args) = 0; /** * @brief Callback function to support a write request. @@ -122,7 +123,7 @@ class NimBLELocalValueAttribute : public NimBLELocalAttribute, public NimBLEValu * @param [in] connInfo A reference to a NimBLEConnInfo instance containing the peer info. * @details This function is called by NimBLEServer when a write request is received. */ - virtual void writeEvent(const uint8_t* val, uint16_t len, NimBLEConnInfo& connInfo) = 0; + virtual void writeEvent(const uint8_t* val, uint16_t len, NimBLEConnInfo& connInfo, NimBLEWriteEventArgs& args) = 0; /** * @brief Get a pointer to value of the attribute. diff --git a/src/NimBLEServer.cpp b/src/NimBLEServer.cpp index 5e4f381b..bbdc1a7c 100644 --- a/src/NimBLEServer.cpp +++ b/src/NimBLEServer.cpp @@ -20,6 +20,7 @@ # include "NimBLEDevice.h" # include "NimBLELog.h" +#include "NimBLEEventArgs.h" # if MYNEWT_VAL(BLE_ROLE_CENTRAL) # include "NimBLEClient.h" @@ -631,12 +632,19 @@ int NimBLEServer::handleGattEvent(uint16_t connHandle, uint16_t attrHandle, ble_ case BLE_GATT_ACCESS_OP_READ_CHR: { // Don't call readEvent if the buffer len is 0 (this is a follow up to a previous read), // or if this is an internal read (handle is NONE) + NimBLEReadEventArgs eventArgs = NimBLEReadEventArgs(); if (ctxt->om->om_len > 0 && connHandle != BLE_HS_CONN_HANDLE_NONE) { - pAtt->readEvent(peerInfo); + pAtt->readEvent(peerInfo, eventArgs); } ble_npl_hw_enter_critical(); - int rc = os_mbuf_append(ctxt->om, val.data(), val.size()); + int rc; + if(eventArgs.isDataOverwritten()) { + auto buffer = eventArgs.getData(); + rc = os_mbuf_append(ctxt->om, buffer->getPointer(), buffer->getSize()); + } else { + rc = os_mbuf_append(ctxt->om, val.data(), val.size()); + } ble_npl_hw_exit_critical(0); return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; } @@ -652,18 +660,23 @@ int NimBLEServer::handleGattEvent(uint16_t connHandle, uint16_t attrHandle, ble_ uint8_t buf[maxLen]; memcpy(buf, ctxt->om->om_data, len); + os_mbuf* next; next = SLIST_NEXT(ctxt->om, om_next); while (next != NULL) { if ((len + next->om_len) > maxLen) { return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } - memcpy(&buf[len], next->om_data, next->om_len); + memcpy(&buf[len], next->om_data, next->om_len); len += next->om_len; next = SLIST_NEXT(next, om_next); } - pAtt->writeEvent(buf, len, peerInfo); + auto oldData = std::string((char*)pAtt->getValue().data(), pAtt->getValue().length()); + auto newData = std::string((char*)buf, len); + + NimBLEWriteEventArgs eventArgs = NimBLEWriteEventArgs(oldData, newData); + pAtt->writeEvent(buf, len, peerInfo, eventArgs); return 0; } diff --git a/src/NimBLEServer.h b/src/NimBLEServer.h index 214578ab..94f15c47 100644 --- a/src/NimBLEServer.h +++ b/src/NimBLEServer.h @@ -34,6 +34,7 @@ # include # include +# include "NimBLEEventArgs.h" # define NIMBLE_ATT_REMOVE_HIDE 1 # define NIMBLE_ATT_REMOVE_DELETE 2 diff --git a/src/NimBLEService.h b/src/NimBLEService.h index 11d7c59c..03700eb6 100644 --- a/src/NimBLEService.h +++ b/src/NimBLEService.h @@ -23,7 +23,7 @@ class NimBLEService; -# include "NimBLEAttribute.h" +# include "NimBLEDevice.h" # include "NimBLEServer.h" # include "NimBLECharacteristic.h" diff --git a/src/buffer.h b/src/buffer.h new file mode 100644 index 00000000..a8530842 --- /dev/null +++ b/src/buffer.h @@ -0,0 +1,46 @@ +// +// Created by hoeflich on 30.07.2025. +// + + + +#ifndef BUFFER_H +#define BUFFER_H + +#if CONFIG_BT_ENABLED && (CONFIG_BT_NIMBLE_ROLE_PERIPHERAL || CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#include + +class buffer { + public: + + u_int8_t* getPointer() { + return data; + } + + size_t getSize() { + return size; + } + + explicit buffer(size_t size){ + if(size == 0) { + this->data = nullptr; + this->size = 0; + return; + } + + this->data = new uint8_t[size]; + this->size = size; + } + + ~buffer(){ + delete data; + } + +private: + uint8_t *data; + size_t size; +}; + +#endif + +#endif //BUFFER_H