1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

slipdev: internally expose byte stuffing functionality

This commit is contained in:
Martine Lenders 2018-11-25 15:59:38 +01:00 committed by Martine Lenders
parent 79e80d4fec
commit f11940973c
No known key found for this signature in database
GPG Key ID: CCD317364F63286F
2 changed files with 105 additions and 50 deletions

View File

@ -19,12 +19,18 @@
#ifndef SLIPDEV_INTERNAL_H
#define SLIPDEV_INTERNAL_H
#include <stddef.h>
#include <stdint.h>
#include "periph/uart.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name SLIP marker bytes
* @see [RFC 1055](https://tools.ietf.org/html/rfc1055)
* @{
*/
#define SLIPDEV_END (0xc0U)
@ -33,6 +39,43 @@ extern "C" {
#define SLIPDEV_ESC_ESC (0xddU)
/** @} */
/**
* @brief Writes one byte to UART
*
* @param[in] uart The UART device to write to.
* @param[in] byte The byte to write to @p uart.
*/
static inline void slipdev_write_byte(uart_t uart, uint8_t byte)
{
uart_write(uart, &byte, 1U);
}
/**
* @brief Write multiple bytes SLIP-escaped to UART
*
* @param[in] uart The UART device to write to.
* @param[in] data The bytes to write SLIP-escaped to @p uart.
* @param[in] len Number of bytes in @p data.
*/
void slipdev_write_bytes(uart_t uart, const uint8_t *data, size_t len);
/**
* @brief Unstuffs a (SLIP-escaped) byte.
*
* @param[out] buf The buffer to write to. It must at least be able to
* receive 1 byte.
* @param[in] byte The byte to unstuff.
* @param[in,out] escaped When set to `false` on in, @p byte will be read as
* though it was not escaped, when set to `true` it
* will be read as though it was escaped. On out it
* will be `false` unless @p byte was `SLIPDEV_ESC`.
*
* @return 0, when @p byte did not resolve to an actual byte
* @return 1, when @p byte resolves to an actual byte (or @p escaped was set to
* true on in and resolves to a byte that was previously escaped).
*/
unsigned slipdev_unstuff_readbyte(uint8_t *buf, uint8_t byte, bool *escaped);
#ifdef __cplusplus
}
#endif

View File

@ -14,6 +14,7 @@
*/
#include <errno.h>
#include <stdbool.h>
#include <string.h>
#include "log.h"
@ -50,9 +51,59 @@ static int _init(netdev_t *netdev)
return 0;
}
static inline void _write_byte(slipdev_t *dev, uint8_t byte)
void slipdev_write_bytes(uart_t uart, const uint8_t *data, size_t len)
{
uart_write(dev->config.uart, &byte, 1);
for (unsigned j = 0; j < len; j++, data++) {
switch (*data) {
case SLIPDEV_END:
/* escaping END byte*/
slipdev_write_byte(uart, SLIPDEV_ESC);
slipdev_write_byte(uart, SLIPDEV_END_ESC);
break;
case SLIPDEV_ESC:
/* escaping ESC byte*/
slipdev_write_byte(uart, SLIPDEV_ESC);
slipdev_write_byte(uart, SLIPDEV_ESC_ESC);
break;
default:
slipdev_write_byte(uart, *data);
}
}
}
static unsigned _copy_byte(uint8_t *buf, uint8_t byte, bool *escaped)
{
*buf = byte;
*escaped = false;
return 1U;
}
unsigned slipdev_unstuff_readbyte(uint8_t *buf, uint8_t byte, bool *escaped)
{
unsigned res = 0U;
switch (byte) {
case SLIPDEV_ESC:
*escaped = true;
/* Intentionally falls through */
case SLIPDEV_END:
break;
case SLIPDEV_END_ESC:
if (*escaped) {
return _copy_byte(buf, SLIPDEV_END, escaped);
}
/* Intentionally falls through */
/* to default when !(*escaped) */
case SLIPDEV_ESC_ESC:
if (*escaped) {
return _copy_byte(buf, SLIPDEV_ESC, escaped);
}
/* Intentionally falls through */
/* to default when !(*escaped) */
default:
return _copy_byte(buf, byte, escaped);
}
return res;
}
static int _send(netdev_t *netdev, const iolist_t *iolist)
@ -63,26 +114,10 @@ static int _send(netdev_t *netdev, const iolist_t *iolist)
DEBUG("slipdev: sending iolist\n");
for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
uint8_t *data = iol->iol_base;
for (unsigned j = 0; j < iol->iol_len; j++, data++) {
switch(*data) {
case SLIPDEV_END:
/* escaping END byte*/
_write_byte(dev, SLIPDEV_ESC);
_write_byte(dev, SLIPDEV_END_ESC);
break;
case SLIPDEV_ESC:
/* escaping ESC byte*/
_write_byte(dev, SLIPDEV_ESC);
_write_byte(dev, SLIPDEV_ESC_ESC);
break;
default:
_write_byte(dev, *data);
}
bytes++;
}
slipdev_write_bytes(dev->config.uart, data, iol->iol_len);
bytes += iol->iol_len;
}
_write_byte(dev, SLIPDEV_END);
slipdev_write_byte(dev->config.uart, SLIPDEV_END);
return bytes;
}
@ -110,42 +145,19 @@ static int _recv(netdev_t *netdev, void *buf, size_t len, void *info)
}
else {
int byte;
bool escaped = false;
uint8_t *ptr = buf;
do {
int tmp;
if ((byte = tsrb_get_one(&dev->inbuf)) < 0) {
/* something went wrong, return error */
return -EIO;
}
switch (byte) {
case SLIPDEV_END:
break;
case SLIPDEV_ESC:
dev->inesc = 1;
break;
case SLIPDEV_END_ESC:
if (dev->inesc) {
*(ptr++) = SLIPDEV_END;
res++;
dev->inesc = 0;
break;
}
/* Intentionally falls through */
/* to default when !dev->inesc */
case SLIPDEV_ESC_ESC:
if (dev->inesc) {
*(ptr++) = SLIPDEV_ESC;
res++;
dev->inesc = 0;
break;
}
/* Intentionally falls through */
/* to default when !dev->inesc */
default:
*(ptr++) = (uint8_t)byte;
res++;
break;
}
tmp = slipdev_unstuff_readbyte(ptr, byte, &escaped);
ptr += tmp;
res += tmp;
if ((unsigned)res > len) {
while (byte != SLIPDEV_END) {
/* clear out unreceived packet */