/* * 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 */ #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; } /** @} */