Skip to content

Commit 6bae48d

Browse files
committed
Add callback for RX buffer overflow
1 parent 76a82ad commit 6bae48d

2 files changed

Lines changed: 46 additions & 14 deletions

File tree

src/NimBLEStream.cpp

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -485,9 +485,30 @@ size_t NimBLEStream::pushRx(const uint8_t* data, size_t len) {
485485
return 0;
486486
}
487487

488-
if (m_rxBuf->freeSize() < len) {
489-
NIMBLE_LOGE(LOG_TAG, "RX buffer full, dropping data");
490-
return 0;
488+
size_t freeSize = m_rxBuf->freeSize();
489+
if (len > freeSize) {
490+
const bool dropOlderData = m_rxOverflowCallback && m_rxOverflowCallback(data, len);
491+
if (!dropOlderData) {
492+
NIMBLE_LOGE(LOG_TAG, "RX buffer overflow, dropping current data");
493+
return 0;
494+
}
495+
496+
if (len >= m_rxBuf->capacity()) {
497+
m_rxBuf->drop(m_rxBuf->size());
498+
const uint8_t* tail = data + (len - m_rxBuf->capacity());
499+
size_t written = m_rxBuf->write(tail, m_rxBuf->capacity());
500+
if (written != m_rxBuf->capacity()) {
501+
NIMBLE_LOGE(LOG_TAG, "RX buffer overflow, %zu bytes dropped", m_rxBuf->capacity() - written);
502+
}
503+
return written;
504+
}
505+
506+
const size_t requiredSpace = len - freeSize;
507+
size_t dropped = m_rxBuf->drop(requiredSpace);
508+
if (dropped < requiredSpace) {
509+
NIMBLE_LOGE(LOG_TAG, "RX buffer overflow, failed to drop enough buffered data");
510+
return 0;
511+
}
491512
}
492513

493514
return m_rxBuf->write(data, len);
@@ -522,8 +543,8 @@ bool NimBLEStreamServer::begin(NimBLECharacteristic* pChr, uint32_t txBufSize, u
522543
return false;
523544
}
524545

525-
auto props = pChr->getProperties();
526-
bool canWrite = (props & NIMBLE_PROPERTY::WRITE) || (props & NIMBLE_PROPERTY::WRITE_NR);
546+
auto props = pChr->getProperties();
547+
bool canWrite = (props & NIMBLE_PROPERTY::WRITE) || (props & NIMBLE_PROPERTY::WRITE_NR);
527548
if (!canWrite && rxBufSize > 0) {
528549
NIMBLE_LOGW(LOG_TAG, "Characteristic does not support WRITE, ignoring RX buffer size");
529550
}

src/NimBLEStream.h

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
# include "nimble/nimble/include/nimble/nimble_npl.h"
2828
# endif
2929

30+
# include <functional>
3031
# include <type_traits>
3132
# include <cstdarg>
3233

@@ -61,6 +62,8 @@ class Stream : public Print {
6162

6263
class NimBLEStream : public Stream {
6364
public:
65+
typedef std::function<bool(const uint8_t* data, size_t len)> rx_overflow_callback_t;
66+
6467
NimBLEStream() = default;
6568
virtual ~NimBLEStream() { end(); }
6669

@@ -87,6 +90,13 @@ class NimBLEStream : public Stream {
8790
virtual int peek() override;
8891
virtual bool ready() const = 0;
8992

93+
/**
94+
* @brief Set a callback to be invoked when incoming data exceeds RX buffer capacity.
95+
* @param cb The callback function, which should return true to drop older buffered data and
96+
* make room for the new data, or false to drop the new data instead.
97+
*/
98+
void setRxOverflowCallback(rx_overflow_callback_t cb) { m_rxOverflowCallback = cb; }
99+
90100
operator bool() const { return ready(); }
91101

92102
using Print::write;
@@ -102,15 +112,16 @@ class NimBLEStream : public Stream {
102112
static void txDrainEventCb(struct ble_npl_event* ev);
103113
static void txDrainCalloutCb(struct ble_npl_event* ev);
104114

105-
ByteRingBuffer* m_txBuf{nullptr};
106-
ByteRingBuffer* m_rxBuf{nullptr};
107-
uint8_t m_txChunkBuf[MYNEWT_VAL(BLE_ATT_PREFERRED_MTU)];
108-
uint32_t m_txBufSize{1024};
109-
uint32_t m_rxBufSize{1024};
110-
ble_npl_event m_txDrainEvent{};
111-
ble_npl_callout m_txDrainCallout{};
112-
bool m_coInitialized{false};
113-
bool m_eventInitialized{false};
115+
ByteRingBuffer* m_txBuf{nullptr};
116+
ByteRingBuffer* m_rxBuf{nullptr};
117+
uint8_t m_txChunkBuf[MYNEWT_VAL(BLE_ATT_PREFERRED_MTU)];
118+
uint32_t m_txBufSize{1024};
119+
uint32_t m_rxBufSize{1024};
120+
ble_npl_event m_txDrainEvent{};
121+
ble_npl_callout m_txDrainCallout{};
122+
bool m_coInitialized{false};
123+
bool m_eventInitialized{false};
124+
rx_overflow_callback_t m_rxOverflowCallback{nullptr};
114125
};
115126

116127
# if MYNEWT_VAL(BLE_ROLE_PERIPHERAL)

0 commit comments

Comments
 (0)