Skip to content
Snippets Groups Projects
Unverified Commit 2f4a7e28 authored by Koen Zandberg's avatar Koen Zandberg Committed by GitHub
Browse files

Merge pull request #8268 from miri64/slipdev/enh/simplify-byte-unstuffing

slipdev: simplify and solidify byte-unstuffing
parents 87e3f10e c61a3431
No related branches found
No related tags found
No related merge requests found
...@@ -246,6 +246,7 @@ ifneq (,$(filter si70%,$(USEMODULE))) ...@@ -246,6 +246,7 @@ ifneq (,$(filter si70%,$(USEMODULE)))
endif endif
ifneq (,$(filter slipdev,$(USEMODULE))) ifneq (,$(filter slipdev,$(USEMODULE)))
USEMODULE += tsrb
FEATURES_REQUIRED += periph_uart FEATURES_REQUIRED += periph_uart
endif endif
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#include "cib.h" #include "cib.h"
#include "net/netdev.h" #include "net/netdev.h"
#include "periph/uart.h" #include "periph/uart.h"
#include "ringbuffer.h" #include "tsrb.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
...@@ -36,20 +36,12 @@ extern "C" { ...@@ -36,20 +36,12 @@ extern "C" {
* @brief UART buffer size used for TX and RX buffers * @brief UART buffer size used for TX and RX buffers
* *
* Reduce this value if your expected traffic does not include full IPv6 MTU * Reduce this value if your expected traffic does not include full IPv6 MTU
* sized packets * sized packets.
*/
#ifndef SLIPDEV_BUFSIZE
#define SLIPDEV_BUFSIZE (1500U)
#endif
/**
* @brief Packet FIFO size
* *
* @note For GNRC it is recommended to have it the same size as the link-layer * @pre Needs to be power of two and `<= INT_MAX`
* thread's message queue, but it MUST be of power of 2
*/ */
#ifndef SLIPDEV_PKTFIFO_SIZE #ifndef SLIPDEV_BUFSIZE
#define SLIPDEV_PKTFIFO_SIZE (8U) #define SLIPDEV_BUFSIZE (2048U)
#endif #endif
/** /**
...@@ -68,13 +60,8 @@ typedef struct { ...@@ -68,13 +60,8 @@ typedef struct {
typedef struct { typedef struct {
netdev_t netdev; /**< parent class */ netdev_t netdev; /**< parent class */
slipdev_params_t config; /**< configuration parameters */ slipdev_params_t config; /**< configuration parameters */
ringbuffer_t inbuf; /**< RX buffer */ tsrb_t inbuf; /**< RX buffer */
char rxmem[SLIPDEV_BUFSIZE]; /**< memory used by RX buffer */ char rxmem[SLIPDEV_BUFSIZE]; /**< memory used by RX buffer */
uint16_t pktfifo[SLIPDEV_PKTFIFO_SIZE]; /**< FIFO of sizes of fully received
* packets */
cib_t pktfifo_idx; /**< CIB for slipdev_t::pktfifo */
uint16_t inbytes; /**< the number of bytes received of
* a currently incoming packet */
uint16_t inesc; /**< device previously received an escape uint16_t inesc; /**< device previously received an escape
* byte */ * byte */
} slipdev_t; } slipdev_t;
......
...@@ -48,53 +48,17 @@ void slipdev_setup(slipdev_t *dev, const slipdev_params_t *params) ...@@ -48,53 +48,17 @@ void slipdev_setup(slipdev_t *dev, const slipdev_params_t *params)
{ {
/* set device descriptor fields */ /* set device descriptor fields */
memcpy(&dev->config, params, sizeof(dev->config)); memcpy(&dev->config, params, sizeof(dev->config));
dev->inbytes = 0U;
dev->inesc = 0U; dev->inesc = 0U;
dev->netdev.driver = &slip_driver; dev->netdev.driver = &slip_driver;
} }
static inline void _add_byte_to_inbuf(slipdev_t *dev, uint8_t byte) static void _slip_rx_cb(void *arg, uint8_t byte)
{
if (ringbuffer_add_one(&dev->inbuf, byte) < 0) {
dev->inbytes++;
}
}
static void _slip_rx_cb(void *arg, uint8_t data)
{ {
slipdev_t *dev = arg; slipdev_t *dev = arg;
if ((data == SLIP_END) && (dev->netdev.event_callback != NULL)) { tsrb_add_one(&dev->inbuf, byte);
int idx = cib_put(&dev->pktfifo_idx); if ((byte == SLIP_END) && (dev->netdev.event_callback != NULL)) {
if (idx >= 0) { dev->netdev.event_callback((netdev_t *)dev, NETDEV_EVENT_ISR);
dev->netdev.event_callback((netdev_t *)dev, NETDEV_EVENT_ISR);
dev->pktfifo[idx] = dev->inbytes;
}
else {
/* can't handover packet => dropping it */
ringbuffer_remove(&dev->inbuf, dev->inbytes);
}
dev->inbytes = 0;
}
else if (dev->inesc) {
dev->inesc = 0U;
uint8_t actual = (data == SLIP_END_ESC) ? SLIP_END :
((data == SLIP_ESC_ESC) ? SLIP_ESC : 0);
switch (data) {
case SLIP_END_ESC:
case SLIP_ESC_ESC:
_add_byte_to_inbuf(dev, actual);
break;
default:
break;
}
}
else if (data == SLIP_ESC) {
dev->inesc = 1U;
}
else {
_add_byte_to_inbuf(dev, data);
} }
} }
...@@ -105,8 +69,7 @@ static int _init(netdev_t *netdev) ...@@ -105,8 +69,7 @@ static int _init(netdev_t *netdev)
DEBUG("slipdev: initializing device %p on UART %i with baudrate %" PRIu32 "\n", DEBUG("slipdev: initializing device %p on UART %i with baudrate %" PRIu32 "\n",
(void *)dev, dev->config.uart, dev->config.baudrate); (void *)dev, dev->config.uart, dev->config.baudrate);
/* initialize buffers */ /* initialize buffers */
ringbuffer_init(&dev->inbuf, dev->rxmem, sizeof(dev->rxmem)); tsrb_init(&dev->inbuf, dev->rxmem, sizeof(dev->rxmem));
cib_init(&dev->pktfifo_idx, SLIPDEV_PKTFIFO_SIZE);
if (uart_init(dev->config.uart, dev->config.baudrate, _slip_rx_cb, if (uart_init(dev->config.uart, dev->config.baudrate, _slip_rx_cb,
dev) != UART_OK) { dev) != UART_OK) {
LOG_ERROR("slipdev: error initializing UART %i with baudrate %" PRIu32 "\n", LOG_ERROR("slipdev: error initializing UART %i with baudrate %" PRIu32 "\n",
...@@ -155,30 +118,69 @@ static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count) ...@@ -155,30 +118,69 @@ static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count)
static int _recv(netdev_t *netdev, void *buf, size_t len, void *info) static int _recv(netdev_t *netdev, void *buf, size_t len, void *info)
{ {
slipdev_t *dev = (slipdev_t *)netdev; slipdev_t *dev = (slipdev_t *)netdev;
int res, idx = cib_peek(&dev->pktfifo_idx); int res = 0;
(void)info; (void)info;
if (idx < 0) {
return -EFAULT;
}
if (buf == NULL) { if (buf == NULL) {
if (len > 0) { if (len > 0) {
/* drop packet */ /* remove data */
cib_get(&dev->pktfifo_idx); for (; len > 0; len--) {
/* and remove data */ int byte = tsrb_get_one(&dev->inbuf);
res = ringbuffer_remove(&dev->inbuf, len); if ((byte == (int)SLIP_END) || (byte < 0)) {
} /* end early if end of packet or ringbuffer is reached;
else { * len might be larger than the actual packet */
res = dev->pktfifo[idx]; break;
}
}
} else {
/* the user was warned not to use a buffer size > `INT_MAX` ;-) */
res = (int)tsrb_avail(&dev->inbuf);
} }
} }
else if (len < dev->pktfifo[idx]) {
res = -ENOBUFS;
}
else { else {
size_t bytes = dev->pktfifo[cib_get(&dev->pktfifo_idx)]; int byte;
bytes = ringbuffer_get(&dev->inbuf, buf, bytes); uint8_t *ptr = buf;
res = bytes;
do {
if ((byte = tsrb_get_one(&dev->inbuf)) < 0) {
/* something went wrong, return error */
return -EIO;
}
switch (byte) {
case SLIP_END:
break;
case SLIP_ESC:
dev->inesc = 1;
break;
case SLIP_END_ESC:
if (dev->inesc) {
*(ptr++) = SLIP_END;
res++;
dev->inesc = 0;
break;
}
/* falls through intentionally to default when !dev->inesc */
case SLIP_ESC_ESC:
if (dev->inesc) {
*(ptr++) = SLIP_ESC;
res++;
dev->inesc = 0;
break;
}
/* falls through intentionally to default when !dev->inesc */
default:
*(ptr++) = (uint8_t)byte;
res++;
break;
}
if ((unsigned)res > len) {
while (byte != SLIP_END) {
/* clear out unreceived packet */
byte = tsrb_get_one(&dev->inbuf);
}
return -ENOBUFS;
}
} while (byte != SLIP_END);
} }
return res; return res;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment