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

slip: port to be used with netdev

This commit is contained in:
Martine Lenders 2017-07-18 14:39:03 +02:00
parent 9368b1deb6
commit b74ee8869b
21 changed files with 554 additions and 465 deletions

View File

@ -377,10 +377,6 @@ ifneq (,$(filter gnrc_pktdump,$(USEMODULE)))
USEMODULE += od
endif
ifneq (,$(filter gnrc_slip,$(USEMODULE)))
FEATURES_REQUIRED += periph_uart
endif
ifneq (,$(filter od,$(USEMODULE)))
USEMODULE += fmt
endif

View File

@ -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

View File

@ -246,6 +246,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

View File

@ -213,7 +213,8 @@ enum {
NETDEV_TYPE_IEEE802154,
NETDEV_TYPE_CC110X,
NETDEV_TYPE_LORA,
NETDEV_TYPE_NRFMIN
NETDEV_TYPE_NRFMIN,
NETDEV_TYPE_SLIP,
};
/**

95
drivers/include/slipdev.h Normal file
View File

@ -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 <m.lenders@fu-berlin.de>
*/
#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 */
/** @} */

View File

@ -1,3 +1 @@
MODULE = gnrc_slip
include $(RIOTBASE)/Makefile.base

222
drivers/slipdev/slipdev.c Normal file
View File

@ -0,0 +1,222 @@
/*
* 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 <mlenders@inf.fu-berlin.de>
*/
#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, const 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, const void *value,
size_t value_len)
{
(void)netdev;
(void)opt;
(void)value;
(void)value_len;
return -ENOTSUP;
}
/** @} */

View File

@ -48,7 +48,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

View File

@ -16,16 +16,16 @@
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
*/
#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,
@ -35,5 +35,5 @@ static gnrc_slip_params_t gnrc_slip_params[] = {
#ifdef __cplusplus
}
#endif
#endif /* SLIP_PARAMS_H */
#endif /* SLIPDEV_PARAMS_H */
/** @} */

View File

@ -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

View File

@ -210,7 +210,7 @@ INCLUDES += -I$(CURDIR)
CFLAGS += -DSLIP_UART=$(SLIP_UART)
CFLAGS += -DSLIP_BAUDRATE=$(SLIP_BAUDRATE)
# Include SLIP package for IP over Serial communication
USEMODULE += gnrc_slip
USEMODULE += slipdev
```

View File

@ -200,9 +200,9 @@ void auto_init(void)
auto_init_ethos();
#endif
#ifdef MODULE_GNRC_SLIP
extern void auto_init_slip(void);
auto_init_slip();
#ifdef MODULE_SLIPDEV
extern void auto_init_slipdev(void);
auto_init_slipdev();
#endif
#ifdef MODULE_CC110X

View File

@ -1,68 +0,0 @@
/*
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
*
* 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.
*
*/
/**
* @ingroup auto_init_gnrc_netif
* @{
*
* @file
* @brief Auto initialization for XBee network interfaces
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
*/
#ifdef MODULE_GNRC_SLIP
#include "log.h"
#include "board.h"
#include "net/gnrc/netdev.h"
#include "net/gnrc.h"
#include "net/gnrc/slip.h"
#include "slip_params.h"
#define SLIP_NUM (sizeof(gnrc_slip_params)/sizeof(gnrc_slip_params_t))
static gnrc_slip_dev_t slip_devs[SLIP_NUM];
/**
* @brief Define stack parameters for the MAC layer thread
* @{
*/
#define SLIP_STACKSIZE (THREAD_STACKSIZE_DEFAULT)
#ifndef SLIP_PRIO
#define SLIP_PRIO (GNRC_NETDEV_MAC_PRIO)
#endif
/**
* @brief Stacks for the MAC layer threads
*/
static char _slip_stacks[SLIP_NUM][SLIP_STACKSIZE];
void auto_init_slip(void)
{
for (unsigned i = 0; i < SLIP_NUM; i++) {
const gnrc_slip_params_t *p = &gnrc_slip_params[i];
LOG_DEBUG("[auto_init_netif] initializing slip #%u\n", i);
kernel_pid_t res = gnrc_slip_init(&slip_devs[i], p->uart, p->baudrate,
_slip_stacks[i], SLIP_STACKSIZE,
SLIP_PRIO);
if (res <= KERNEL_PID_UNDEF) {
LOG_ERROR("[auto_init_netif] error initializing slip #%u\n", i);
}
}
}
#else
typedef int dont_be_pedantic;
#endif /* MODULE_GNRC_SLIP */
/** @} */

View File

@ -0,0 +1,69 @@
/*
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
*
* 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.
*
*/
/**
* @ingroup auto_init_gnrc_netif
* @{
*
* @file
* @brief Auto initialization for XBee network interfaces
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
*/
#ifdef MODULE_SLIPDEV
#include "log.h"
#include "board.h"
#include "net/gnrc/netdev.h"
#include "net/gnrc/netdev/raw.h"
#include "net/gnrc.h"
#include "slipdev.h"
#include "slipdev_params.h"
#define SLIPDEV_NUM (sizeof(slipdev_params)/sizeof(slipdev_params_t))
/**
* @brief Define stack parameters for the MAC layer thread
* @{
*/
#define SLIPDEV_STACKSIZE (THREAD_STACKSIZE_DEFAULT)
#ifndef SLIPDEV_PRIO
#define SLIPDEV_PRIO (GNRC_NETDEV_MAC_PRIO)
#endif
static slipdev_t slipdevs[SLIPDEV_NUM];
static gnrc_netdev_t gnrc_adpt[SLIPDEV_NUM];
static char _slipdev_stacks[SLIPDEV_NUM][SLIPDEV_STACKSIZE];
void auto_init_slipdev(void)
{
for (unsigned i = 0; i < SLIPDEV_NUM; i++) {
const slipdev_params_t *p = &slipdev_params[i];
LOG_DEBUG("[auto_init_netif] initializing slip #%u\n", i);
slipdev_setup(&slipdevs[i], p);
kernel_pid_t res = gnrc_netdev_raw_init(&gnrc_adpt[i],
(netdev_t *)&slipdevs[i]);
if (res < 0) {
LOG_ERROR("[auto_init_netif] error initializing slipdev #%u\n", i);
}
else {
gnrc_netdev_init(_slipdev_stacks[i], SLIPDEV_STACKSIZE,
SLIPDEV_PRIO, "slipdev", &gnrc_adpt[i]);
}
}
}
#else
typedef int dont_be_pedantic;
#endif /* MODULE_SLIPDEV */
/** @} */

View File

@ -0,0 +1,43 @@
/*
* 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.
*/
/**
* @ingroup net_gnrc_netdev
* @{
*
* @file
* @brief netdev gnrc raw (i.e. pure L3) glue code interface
*
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
*/
#ifndef NET_GNRC_NETDEV_RAW_H
#define NET_GNRC_NETDEV_RAW_H
#include "net/gnrc/netdev.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initialize gnrc handler for netdev raw L3 devices
*
* @param[in] gnrc_netdev gnrc_netdev struct to initialize
* @param[in] dev network device to handle
*
* @return 1 on success
* @return <=0 on error
*/
int gnrc_netdev_raw_init(gnrc_netdev_t *gnrc_netdev, netdev_t *dev);
#ifdef __cplusplus
}
#endif
#endif /* NET_GNRC_NETDEV_RAW_H */
/** @} */

View File

@ -1,92 +0,0 @@
/*
* Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de>
*
* 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 net_gnrc_slip SLIP
* @ingroup net_gnrc
* @brief Provides a SLIP interface over UART utilizing
* @ref drivers_periph_uart.
* @see <a href="https://www.ietf.org/rfc/rfc1055">RFC 1055</a>
* @{
*
* @file
* @brief SLIP interface defintion
*
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*/
#ifndef NET_GNRC_SLIP_H
#define NET_GNRC_SLIP_H
#include <inttypes.h>
#include "net/gnrc.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 GNRC_SLIP_BUFSIZE
#define GNRC_SLIP_BUFSIZE (1500U)
#endif
/**
* @brief Device descriptor for SLIP devices
*/
typedef struct {
uart_t uart; /**< the UART interface */
ringbuffer_t in_buf; /**< RX buffer */
ringbuffer_t out_buf; /**< TX buffer */
char rx_mem[GNRC_SLIP_BUFSIZE]; /**< memory used by RX buffer */
uint32_t in_bytes; /**< the number of bytes received of a
* currently incoming packet */
uint16_t in_esc; /**< receiver is in escape mode */
kernel_pid_t slip_pid; /**< PID of the device thread */
} gnrc_slip_dev_t;
/**
* @brief auto_init struct holding SLIP initalization params
*/
typedef struct xbee_params {
uart_t uart; /**< UART interfaced the device is connected to */
uint32_t baudrate; /**< baudrate to use */
} gnrc_slip_params_t;
/**
* @brief Initializes a new @ref net_gnrc_slip control thread for UART device
* @p uart
*
* @param[in] dev un-initialized SLIP device descriptor
* @param[in] uart UART device to use
* @param[in] baudrate baudrate to use
* @param[in] stack stack memory to use for the SLIP devices thread
* @param[in] stack_size size of @p stack
* @param[in] priority priority for the newly created thread
*
* @return PID of SLIP thread on success
* @return -EFAULT, if slip thread could not be created
* @return -ENODEV, if gnrc_slip_dev_t::uart of @p dev was no valid UART
*/
kernel_pid_t gnrc_slip_init(gnrc_slip_dev_t *dev, uart_t uart, uint32_t baudrate,
char *stack, size_t stack_size, char priority);
#ifdef __cplusplus
}
#endif
#endif /* NET_GNRC_SLIP_H */
/** @} */

View File

@ -118,9 +118,6 @@ endif
ifneq (,$(filter gnrc_sixlowpan_netif,$(USEMODULE)))
DIRS += network_layer/sixlowpan/netif
endif
ifneq (,$(filter gnrc_slip,$(USEMODULE)))
DIRS += link_layer/slip
endif
ifneq (,$(filter gnrc_sock,$(USEMODULE)))
DIRS += sock
endif

View File

@ -0,0 +1,99 @@
/*
* 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 <mlenders@inf.fu-berlin.de>
*/
#include "net/gnrc/netdev/raw.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
#define IP_VERSION_MASK (0xf0)
#define IP_VERSION4 (0x40)
#define IP_VERSION6 (0x60)
static gnrc_pktsnip_t *_recv(gnrc_netdev_t *gnrc_netdev)
{
netdev_t *dev = gnrc_netdev->dev;
int bytes_expected = dev->driver->recv(dev, NULL, 0, NULL);
gnrc_pktsnip_t *pkt = NULL;
if (bytes_expected > 0) {
int nread;
pkt = gnrc_pktbuf_add(NULL, NULL, bytes_expected, GNRC_NETTYPE_UNDEF);
if (!pkt) {
DEBUG("gnrc_netdev_raw: cannot allocate pktsnip.\n");
/* drop packet */
dev->driver->recv(dev, NULL, bytes_expected, NULL);
return pkt;
}
nread = dev->driver->recv(dev, pkt->data, bytes_expected, NULL);
if (nread <= 0) {
DEBUG("gnrc_netdev_raw: read error.\n");
gnrc_pktbuf_release(pkt);
return NULL;
}
if (nread < bytes_expected) {
/* we've got less then the expected packet size,
* so free the unused space.*/
DEBUG("gnrc_netdev_raw: reallocating.\n");
gnrc_pktbuf_realloc_data(pkt, nread);
}
switch (((uint8_t *)pkt->data)[0] & IP_VERSION_MASK) {
#ifdef MODULE_GNRC_IPV6
case IP_VERSION6:
pkt->type = GNRC_NETTYPE_IPV6;
break;
#endif
default:
/* leave UNDEF */
break;
}
}
return pkt;
}
static int _send(gnrc_netdev_t *gnrc_netdev, gnrc_pktsnip_t *pkt)
{
gnrc_pktsnip_t *vector;
int res = -ENOBUFS;
size_t n;
if (pkt->type == GNRC_NETTYPE_NETIF) {
/* we don't need the netif snip: remove it */
pkt = gnrc_pktbuf_remove_snip(pkt, pkt);
}
vector = gnrc_pktbuf_get_iovec(pkt, &n);
if (vector != NULL) {
struct iovec *v = (struct iovec *)vector->data;
netdev_t *dev = gnrc_netdev->dev;
#ifdef MODULE_NETSTATS_L2
gnrc_netdev->dev->stats.tx_unicast_count++;
#endif
res = dev->driver->send(dev, v, n);
}
return res;
}
int gnrc_netdev_raw_init(gnrc_netdev_t *gnrc_netdev, netdev_t *dev)
{
gnrc_netdev->send = _send;
gnrc_netdev->recv = _recv;
gnrc_netdev->dev = dev;
return 0;
}
/** @} */

View File

@ -1,277 +0,0 @@
/*
* Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de>
*
* 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.
*/
/**
* @ingroup net_gnrc_slip
* @{
*
* @file
* @brief SLIP device implementation
*
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*
* @}
*/
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "kernel_types.h"
#include "msg.h"
#include "net/gnrc.h"
#include "periph/uart.h"
#include "od.h"
#include "ringbuffer.h"
#include "thread.h"
#include "net/ipv6/hdr.h"
#include "net/gnrc/slip.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
#define _SLIP_END ('\xc0')
#define _SLIP_ESC ('\xdb')
#define _SLIP_END_ESC ('\xdc')
#define _SLIP_ESC_ESC ('\xdd')
#define _SLIP_MSG_TYPE (0xc1dc) /* chosen randomly */
#define _SLIP_NAME "SLIP"
#define _SLIP_MSG_QUEUE_SIZE (8U)
#define _SLIP_DEV(arg) ((gnrc_slip_dev_t *)arg)
/* UART callbacks */
static void _slip_rx_cb(void *arg, uint8_t data)
{
if (data == (uint8_t)_SLIP_END) {
msg_t msg;
msg.type = _SLIP_MSG_TYPE;
msg.content.value = _SLIP_DEV(arg)->in_bytes;
msg_send_int(&msg, _SLIP_DEV(arg)->slip_pid);
_SLIP_DEV(arg)->in_bytes = 0;
}
else if (_SLIP_DEV(arg)->in_esc) {
_SLIP_DEV(arg)->in_esc = 0;
switch (data) {
case ((uint8_t)_SLIP_END_ESC):
if (ringbuffer_add_one(&_SLIP_DEV(arg)->in_buf, _SLIP_END) < 0) {
_SLIP_DEV(arg)->in_bytes++;
}
break;
case ((uint8_t)_SLIP_ESC_ESC):
if (ringbuffer_add_one(&_SLIP_DEV(arg)->in_buf, _SLIP_ESC) < 0) {
_SLIP_DEV(arg)->in_bytes++;
}
break;
default:
break;
}
}
else if (data == (uint8_t)_SLIP_ESC) {
_SLIP_DEV(arg)->in_esc = 1;
}
else {
if (ringbuffer_add_one(&_SLIP_DEV(arg)->in_buf, data) < 0) {
_SLIP_DEV(arg)->in_bytes++;
}
}
}
/* SLIP receive handler */
static void _slip_receive(gnrc_slip_dev_t *dev, size_t bytes)
{
gnrc_pktsnip_t *pkt, *hdr;
hdr = gnrc_netif_hdr_build(NULL, 0, NULL, 0);
if (hdr == NULL) {
DEBUG("slip: no space left in packet buffer\n");
return;
}
((gnrc_netif_hdr_t *)(hdr->data))->if_pid = thread_getpid();
pkt = gnrc_pktbuf_add(hdr, NULL, bytes, GNRC_NETTYPE_UNDEF);
if (pkt == NULL) {
DEBUG("slip: no space left in packet buffer\n");
gnrc_pktbuf_release(hdr);
return;
}
if (ringbuffer_get(&dev->in_buf, pkt->data, bytes) != bytes) {
DEBUG("slip: could not read %u bytes from ringbuffer\n", (unsigned)bytes);
gnrc_pktbuf_release(pkt);
return;
}
#if ENABLE_DEBUG && defined(MODULE_OD)
else {
DEBUG("slip: received data\n");
od_hex_dump(pkt->data, bytes, OD_WIDTH_DEFAULT);
}
#endif
#ifdef MODULE_GNRC_IPV6
if ((pkt->size >= sizeof(ipv6_hdr_t)) && ipv6_hdr_is(pkt->data)) {
pkt->type = GNRC_NETTYPE_IPV6;
}
#endif
if (gnrc_netapi_dispatch_receive(pkt->type, GNRC_NETREG_DEMUX_CTX_ALL, pkt) == 0) {
DEBUG("slip: unable to forward packet of type %i\n", pkt->type);
gnrc_pktbuf_release(pkt);
}
}
static inline void _slip_send_char(gnrc_slip_dev_t *dev, char c)
{
uart_write(dev->uart, (uint8_t *)&c, 1);
}
/* SLIP send handler */
static void _slip_send(gnrc_slip_dev_t *dev, gnrc_pktsnip_t *pkt)
{
gnrc_pktsnip_t *ptr;
ptr = pkt->next; /* ignore gnrc_netif_hdr_t, we don't need it */
while (ptr != NULL) {
DEBUG("slip: send pktsnip of length %u over UART_%d\n", (unsigned)ptr->size, dev->uart);
char *data = ptr->data;
for (size_t i = 0; i < ptr->size; i++) {
switch (data[i]) {
case _SLIP_END:
DEBUG("slip: encountered END byte on send: stuff with ESC\n");
_slip_send_char(dev, _SLIP_ESC);
_slip_send_char(dev, _SLIP_END_ESC);
break;
case _SLIP_ESC:
DEBUG("slip: encountered ESC byte on send: stuff with ESC\n");
_slip_send_char(dev, _SLIP_ESC);
_slip_send_char(dev, _SLIP_ESC_ESC);
break;
default:
_slip_send_char(dev, data[i]);
break;
}
}
ptr = ptr->next;
}
_slip_send_char(dev, _SLIP_END);
gnrc_pktbuf_release(pkt);
}
static inline int _slip_get(gnrc_netapi_opt_t *opt)
{
switch (opt->opt) {
case NETOPT_IS_WIRED:
return 1;
default:
return -ENOTSUP;
}
}
static void *_slip(void *args)
{
gnrc_slip_dev_t *dev = _SLIP_DEV(args);
msg_t msg, reply, msg_q[_SLIP_MSG_QUEUE_SIZE];
msg_init_queue(msg_q, _SLIP_MSG_QUEUE_SIZE);
dev->slip_pid = thread_getpid();
gnrc_netif_add(dev->slip_pid);
DEBUG("slip: SLIP runs on UART_%d\n", dev->uart);
while (1) {
DEBUG("slip: waiting for incoming messages\n");
msg_receive(&msg);
switch (msg.type) {
case _SLIP_MSG_TYPE:
DEBUG("slip: incoming message of size %" PRIu32 " from UART_%d in buffer\n",
msg.content.value, dev->uart);
_slip_receive(dev, (size_t)msg.content.value);
break;
case GNRC_NETAPI_MSG_TYPE_SND:
DEBUG("slip: GNRC_NETAPI_MSG_TYPE_SND received\n");
_slip_send(dev, msg.content.ptr);
break;
case GNRC_NETAPI_MSG_TYPE_GET:
DEBUG("slip: GNRC_NETAPI_MSG_TYPE_GET received\n");
reply.type = GNRC_NETAPI_MSG_TYPE_ACK;
reply.content.value = (uint32_t)_slip_get(msg.content.ptr);
msg_reply(&msg, &reply);
break;
case GNRC_NETAPI_MSG_TYPE_SET:
DEBUG("slip: GNRC_NETAPI_MSG_TYPE_SET received\n");
reply.type = GNRC_NETAPI_MSG_TYPE_ACK;
reply.content.value = (uint32_t)(-ENOTSUP);
DEBUG("slip: I don't support this but have to reply.\n");
msg_reply(&msg, &reply);
break;
}
}
/* should be never reached */
return NULL;
}
kernel_pid_t gnrc_slip_init(gnrc_slip_dev_t *dev, uart_t uart, uint32_t baudrate,
char *stack, size_t stack_size, char priority)
{
kernel_pid_t pid;
/* reset device descriptor fields */
dev->uart = uart;
dev->in_bytes = 0;
dev->in_esc = 0;
dev->slip_pid = KERNEL_PID_UNDEF;
/* initialize buffers */
ringbuffer_init(&dev->in_buf, dev->rx_mem, sizeof(dev->rx_mem));
/* initialize UART */
DEBUG("slip: initialize UART_%d with baudrate %" PRIu32 "\n", uart,
baudrate);
if (uart_init(uart, baudrate, _slip_rx_cb, dev) != UART_OK) {
DEBUG("slip: error initializing UART_%i with baudrate %" PRIu32 "\n",
uart, baudrate);
return -ENODEV;
}
/* start SLIP thread */
DEBUG("slip: starting SLIP thread\n");
pid = thread_create(stack, stack_size, priority, THREAD_CREATE_STACKTEST,
_slip, dev, _SLIP_NAME);
if (pid < 0) {
DEBUG("slip: unable to create SLIP thread\n");
return -EFAULT;
}
return pid;
}

View File

@ -10,7 +10,9 @@ BOARD_BLACKLIST += mips-malta
USEMODULE += auto_init_gnrc_netif
USEMODULE += gnrc
USEMODULE += gnrc_pktdump
USEMODULE += gnrc_slip
USEMODULE += gnrc_netdev
USEMODULE += gnrc_txtsnd
USEMODULE += slipdev
USEMODULE += shell
USEMODULE += shell_commands

View File

@ -16,16 +16,16 @@
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
*/
#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,
@ -35,5 +35,5 @@ static gnrc_slip_params_t gnrc_slip_params[] = {
#ifdef __cplusplus
}
#endif
#endif /* SLIP_PARAMS_H */
#endif /* SLIPDEV_PARAMS_H */
/** @} */