Skip to content

Commit

Permalink
Merge branch 'slipdev/api/slip-port-to-netdev' (RIOT-OS#7381) into RI…
Browse files Browse the repository at this point in the history
  • Loading branch information
miri64 committed Aug 21, 2017
2 parents 768459d + eb3c040 commit d84bc88
Show file tree
Hide file tree
Showing 21 changed files with 552 additions and 465 deletions.
2 changes: 1 addition & 1 deletion dist/tools/tunslip/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Creating a SLIP network interface
=================================

The module `gnrc_slip` (Serial line IP) enables the RIOT network stack to
The module `slipdev` (Serial line IP) enables the RIOT network stack to
communicate IP packets over the serial interface. This collection of tools
originally from Contiki [1] enables Linux to interpret this data. Though there
is a tool for such operations on Linux (`slattach`) it is only able to handle
Expand Down
4 changes: 4 additions & 0 deletions drivers/Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,10 @@ ifneq (,$(filter lsm6dsl,$(USEMODULE)))
USEMODULE += xtimer
endif

ifneq (,$(filter slipdev,$(USEMODULE)))
FEATURES_REQUIRED += periph_uart
endif

ifneq (,$(filter adc%1c,$(USEMODULE)))
FEATURES_REQUIRED += periph_gpio
FEATURES_REQUIRED += periph_i2c
Expand Down
3 changes: 2 additions & 1 deletion drivers/include/net/netdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,8 @@ enum {
NETDEV_TYPE_IEEE802154,
NETDEV_TYPE_CC110X,
NETDEV_TYPE_LORA,
NETDEV_TYPE_NRFMIN
NETDEV_TYPE_NRFMIN,
NETDEV_TYPE_SLIP,
};

/**
Expand Down
95 changes: 95 additions & 0 deletions drivers/include/slipdev.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright (C) 2015-17 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/

/**
* @defgroup drivers_slipdev SLIP network device
* @ingroup drivers_netdev
* @brief SLIP network device over @ref drivers_periph_uart
* @see [RFC 1055](https://github.com/RIOT-OS/RIOT/pull/6487)
* @{
*
* @file
* @brief SLIP device definitions
*
* @author Martine Lenders <[email protected]>
*/
#ifndef SLIPDEV_H
#define SLIPDEV_H

#include <stdint.h>

#include "cib.h"
#include "net/netdev.h"
#include "periph/uart.h"
#include "ringbuffer.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief UART buffer size used for TX and RX buffers
*
* Reduce this value if your expected traffic does not include full IPv6 MTU
* 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
* thread's message queue, but it MUST be of power of 2
*/
#ifndef SLIPDEV_PKTFIFO_SIZE
#define SLIPDEV_PKTFIFO_SIZE (8U)
#endif

/**
* @brief Configuration parameters for a slipdev
*/
typedef struct {
uart_t uart; /**< UART interface the device is connected to */
uint32_t baudrate; /**< baudrate to use with slipdev_params_t::uart */
} slipdev_params_t;

/**
* @brief Device descriptor for slipdev
*
* @extends netdev_t
*/
typedef struct {
netdev_t netdev; /**< parent class */
slipdev_params_t config; /**< configuration parameters */
ringbuffer_t inbuf; /**< 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
* byte */
} slipdev_t;

/**
* @brief Setup a slipdev device state
*
* @param[in] dev device descriptor
* @param[in] params parameters for device initialization
*/
void slipdev_setup(slipdev_t *dev, const slipdev_params_t *params);

#ifdef __cplusplus
}
#endif

#endif /* SLIPDEV_H */
/** @} */
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
MODULE = gnrc_slip

include $(RIOTBASE)/Makefile.base
220 changes: 220 additions & 0 deletions drivers/slipdev/slipdev.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
/*
* Copyright (C) 2017 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/

/**
* @{
*
* @file
* @author Martine Lenders <[email protected]>
*/

#include <errno.h>
#include <string.h>

#include "log.h"
#include "slipdev.h"

#define ENABLE_DEBUG (0)
#include "debug.h"

#define SLIP_END (0xc0U)
#define SLIP_ESC (0xdbU)
#define SLIP_END_ESC (0xdcU)
#define SLIP_ESC_ESC (0xddU)

static int _send(netdev_t *dev, const struct iovec *vector, unsigned count);
static int _recv(netdev_t *dev, void *buf, size_t len, void *info);
static int _init(netdev_t *dev);
static void _isr(netdev_t *dev);
static int _get(netdev_t *dev, netopt_t opt, void *value, size_t max_len);
static int _set(netdev_t *dev, netopt_t opt, void *value, size_t value_len);

static const netdev_driver_t slip_driver = {
.send = _send,
.recv = _recv,
.init = _init,
.isr = _isr,
.get = _get,
.set = _set,
};

void slipdev_setup(slipdev_t *dev, const slipdev_params_t *params)
{
/* set device descriptor fields */
memcpy(&dev->config, params, sizeof(dev->config));
dev->inbytes = 0U;
dev->inesc = 0U;
dev->netdev.driver = &slip_driver;
}

static inline void _add_byte_to_inbuf(slipdev_t *dev, 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;

if ((data == SLIP_END) && (dev->netdev.event_callback != NULL)) {
int idx = cib_put(&dev->pktfifo_idx);
if (idx >= 0) {
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);
}
}

static int _init(netdev_t *netdev)
{
slipdev_t *dev = (slipdev_t *)netdev;

DEBUG("slipdev: initializing device %p on UART %i with baudrate %" PRIu32 "\n",
(void *)dev, dev->config.uart, dev->config.baudrate);
/* initialize buffers */
ringbuffer_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,
dev) != UART_OK) {
LOG_ERROR("slipdev: error initializing UART %i with baudrate %" PRIu32 "\n",
dev->config.uart, dev->config.baudrate);
return -ENODEV;
}
return 0;
}

static inline void _write_byte(slipdev_t *dev, uint8_t byte)
{
uart_write(dev->config.uart, &byte, 1);
}

static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count)
{
slipdev_t *dev = (slipdev_t *)netdev;
int bytes = 0;

DEBUG("slipdev: sending vector of length %u\n", count);
for (unsigned i = 0; i < count; i++) {
uint8_t *data = vector[i].iov_base;

for (unsigned j = 0; j < vector[i].iov_len; j++, data++) {
switch(*data) {
case SLIP_END:
/* escaping END byte*/
_write_byte(dev, SLIP_ESC);
_write_byte(dev, SLIP_END_ESC);
break;
case SLIP_ESC:
/* escaping ESC byte*/
_write_byte(dev, SLIP_ESC);
_write_byte(dev, SLIP_ESC_ESC);
break;
default:
_write_byte(dev, *data);
}
bytes++;
}
}
_write_byte(dev, SLIP_END);
return bytes;
}

static int _recv(netdev_t *netdev, void *buf, size_t len, void *info)
{
slipdev_t *dev = (slipdev_t *)netdev;
int res, idx = cib_peek(&dev->pktfifo_idx);

(void)info;
if (idx < 0) {
return -EFAULT;
}
if (buf == NULL) {
if (len > 0) {
/* drop packet */
cib_get(&dev->pktfifo_idx);
/* and remove data */
res = ringbuffer_remove(&dev->inbuf, len);
}
else {
res = dev->pktfifo[idx];
}
}
else if (len < dev->pktfifo[idx]) {
res = -ENOBUFS;
}
else {
size_t bytes = dev->pktfifo[cib_get(&dev->pktfifo_idx)];
bytes = ringbuffer_get(&dev->inbuf, buf, bytes);
res = bytes;
}
return res;
}

static void _isr(netdev_t *netdev)
{
DEBUG("slipdev: handling ISR event\n");
if (netdev->event_callback != NULL) {
DEBUG("slipdev: event handler set, issuing RX_COMPLETE event\n");
netdev->event_callback(netdev, NETDEV_EVENT_RX_COMPLETE);
}
}

static int _get(netdev_t *netdev, netopt_t opt, void *value, size_t max_len)
{
(void)netdev;
(void)value;
(void)max_len;
switch (opt) {
case NETOPT_IS_WIRED:
return 1;
case NETOPT_DEVICE_TYPE:
assert(max_len != sizeof(uint16_t));
*((uint16_t *)value) = NETDEV_TYPE_SLIP;
return sizeof(uint16_t);
default:
return -ENOTSUP;
}
}

static int _set(netdev_t *netdev, netopt_t opt, void *value, size_t value_len)
{
(void)netdev;
(void)opt;
(void)value;
(void)value_len;
return -ENOTSUP;
}

/** @} */
2 changes: 1 addition & 1 deletion examples/gcoap/Makefile.slip
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ USEMODULE += gnrc_rpl

# Border router requirements
# Include SLIP package for IP over Serial communication
USEMODULE += gnrc_slip
USEMODULE += slipdev
# Specify the mandatory networking modules for 6LoWPAN border router
USEMODULE += gnrc_sixlowpan_border_router_default
# Additional networking modules that can be dropped if not needed
Expand Down
10 changes: 5 additions & 5 deletions examples/gcoap/slip_params.h → examples/gcoap/slipdev_params.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@
* @author Martine Lenders <[email protected]>
*/

#ifndef SLIP_PARAMS_H
#define SLIP_PARAMS_H
#ifndef SLIPDEV_PARAMS_H
#define SLIPDEV_PARAMS_H

#include "net/gnrc/slip.h"
#include "slipdev.h"

#ifdef __cplusplus
extern "C" {
#endif

static gnrc_slip_params_t gnrc_slip_params[] = {
static slipdev_params_t slipdev_params[] = {
{
.uart = SLIP_UART,
.baudrate = SLIP_BAUDRATE,
Expand All @@ -35,5 +35,5 @@ static gnrc_slip_params_t gnrc_slip_params[] = {
#ifdef __cplusplus
}
#endif
#endif /* SLIP_PARAMS_H */
#endif /* SLIPDEV_PARAMS_H */
/** @} */
2 changes: 1 addition & 1 deletion examples/gnrc_border_router/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ endif
#CFLAGS += -DSLIP_UART=$(SLIP_UART)
#CFLAGS += -DSLIP_BAUDRATE=$(SLIP_BAUDRATE)
# Include SLIP package for IP over Serial communication
#USEMODULE += gnrc_slip
#USEMODULE += slipdev

# Include packages that pull up and auto-init the link layer.
# NOTE: 6LoWPAN will be included if IEEE802.15.4 devices are present
Expand Down
Loading

0 comments on commit d84bc88

Please sign in to comment.