/* * Copyright (C) 2016-17 Freie Universität Berlin * 2018 Otto-von-Guericke-Universität Magdeburg * * 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_netif * @{ * * @file * * @author Martine Lenders * @author Hauke Petersen * @author Marian Buschsieweke * * Adapted from @ref gnrc_xbee.c with only minor modifications. So all credit * goes to Martine Lenders and to * Hauke Petersen . * * @} */ #include "assert.h" #include "net/gnrc.h" #include "luid.h" #include "cc1xxx_common.h" #define ENABLE_DEBUG 0 #include "debug.h" #define BCAST (GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST) static gnrc_pktsnip_t *cc1xxx_adpt_recv(gnrc_netif_t *netif) { netdev_t *dev = netif->dev; cc1xxx_rx_info_t rx_info; int pktlen; gnrc_pktsnip_t *payload; gnrc_pktsnip_t *hdr; gnrc_netif_hdr_t *netif_hdr; cc1xxx_l2hdr_t l2hdr; assert(dev); /* see how much data there is to process */ pktlen = dev->driver->recv(dev, NULL, 0, &rx_info); if (pktlen <= 0) { DEBUG("[cc1xxx-gnrc] recv: no data available to process\n"); return NULL; } /* allocate space for the packet in the pktbuf */ payload = gnrc_pktbuf_add(NULL, NULL, pktlen, CC1XXX_DEFAULT_PROTOCOL); if (payload == NULL) { DEBUG("[cc1xxx-gnrc] recv: unable to allocate space in the pktbuf\n"); /* tell the driver to drop the packet */ dev->driver->recv(dev, NULL, pktlen, NULL); return NULL; } /* copy the complete including the CC1XXX header into the packet buffer */ dev->driver->recv(dev, payload->data, pktlen, NULL); /* The first two bytes are the layer 2 header */ l2hdr.dest_addr = ((uint8_t *)payload->data)[0]; l2hdr.src_addr = ((uint8_t *)payload->data)[1]; /* crop the layer 2 header from the payload */ hdr = gnrc_pktbuf_mark(payload, sizeof(cc1xxx_l2hdr_t), GNRC_NETTYPE_UNDEF); if (hdr == NULL) { DEBUG("[cc1xxx-gnrc] recv: unable to mark cc1xxx header snip\n"); gnrc_pktbuf_release(payload); return NULL; } gnrc_pktbuf_remove_snip(payload, hdr); /* create a netif hdr from the obtained data */ hdr = gnrc_netif_hdr_build(&l2hdr.src_addr, CC1XXX_ADDR_SIZE, &l2hdr.dest_addr, CC1XXX_ADDR_SIZE); if (hdr == NULL) { DEBUG("[cc1xxx-gnrc] recv: unable to allocate netif header\n"); gnrc_pktbuf_release(payload); return NULL; } netif_hdr = (gnrc_netif_hdr_t *)hdr->data; gnrc_netif_hdr_set_netif(netif_hdr, netif); netif_hdr->rssi = rx_info.rssi; netif_hdr->lqi = rx_info.lqi; if (l2hdr.dest_addr == CC1XXX_BCAST_ADDR) { netif_hdr->flags = GNRC_NETIF_HDR_FLAGS_BROADCAST; } DEBUG("[cc1xxx-gnrc] recv: successfully parsed packet\n"); /* and append the netif header */ payload = gnrc_pkt_append(payload, hdr); #ifdef MODULE_NETSTATS_L2 netif->stats.rx_count++; netif->stats.rx_bytes += pktlen; #endif return payload; } static int cc1xxx_adpt_send(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt) { int res; size_t size; cc1xxx_t *cc1xxx_dev = (cc1xxx_t *)netif->dev; gnrc_netif_hdr_t *netif_hdr; cc1xxx_l2hdr_t l2hdr; /* check device descriptor and packet */ assert(netif && pkt); /* get the payload size and the dst address details */ size = gnrc_pkt_len(pkt->next); DEBUG("[cc1xxx-gnrc] send: payload of packet is %i\n", (int)size); netif_hdr = (gnrc_netif_hdr_t *)pkt->data; l2hdr.src_addr = cc1xxx_dev->addr; if (netif_hdr->flags & BCAST) { l2hdr.dest_addr = CC1XXX_BCAST_ADDR; DEBUG("[cc1xxx-gnrc] send: preparing to send broadcast\n"); #ifdef MODULE_NETSTATS_L2 netif->stats.tx_mcast_count++; #endif } else { /* check that destination address is valid */ assert(netif_hdr->dst_l2addr_len > 0); uint8_t *addr = gnrc_netif_hdr_get_dst_addr(netif_hdr); l2hdr.dest_addr = addr[0]; DEBUG("[cc1xxx-gnrc] send: preparing to send unicast %02x --> %02x\n", (int)l2hdr.src_addr, (int)l2hdr.dest_addr); #ifdef MODULE_NETSTATS_L2 netif->stats.tx_unicast_count++; #endif } /* now let's send out the stuff */ iolist_t iolist = { .iol_next = (iolist_t *)pkt->next, .iol_base = &l2hdr, .iol_len = sizeof(l2hdr), }; DEBUG("[cc1xxx-gnrc] send: triggering the drivers send function\n"); res = netif->dev->driver->send(netif->dev, &iolist); gnrc_pktbuf_release(pkt); return res; } static const gnrc_netif_ops_t cc1xxx_netif_ops = { .init = gnrc_netif_default_init, .send = cc1xxx_adpt_send, .recv = cc1xxx_adpt_recv, .get = gnrc_netif_get_from_netdev, .set = gnrc_netif_set_from_netdev, }; int gnrc_netif_cc1xxx_create(gnrc_netif_t *netif, char *stack, int stacksize, char priority, char *name, netdev_t *dev) { return gnrc_netif_create(netif, stack, stacksize, priority, name, dev, &cc1xxx_netif_ops); } void __attribute__((weak)) cc1xxx_eui_get(const netdev_t *netdev, uint8_t *eui) { (void)netdev; do { luid_get(eui, 1); } while (*eui == CC1XXX_BCAST_ADDR); }