mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
100 lines
2.6 KiB
C
100 lines
2.6 KiB
C
|
/*
|
||
|
* 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;
|
||
|
}
|
||
|
/** @} */
|