Browse Source

sys/net/gnrc: added XBee-to-GNRC glue code

pr/spi.typo
Hauke Petersen 6 years ago
parent
commit
61378430e2
  1. 52
      sys/include/net/gnrc/netdev2/xbee_adpt.h
  2. 182
      sys/net/gnrc/link_layer/netdev2/gnrc_netdev2_xbee.c

52
sys/include/net/gnrc/netdev2/xbee_adpt.h

@ -0,0 +1,52 @@
/*
* Copyright (C) 2016 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.
*/
/**
* @addtogroup net_gnrc
* @{
*
* @file
* @brief GNRC to XBee netdev2 glue code interface
*
* Although the XBee devices are IEEE802.15.4 transceivers, use their own
* proprietary format for communicating between the host CPU and the device over
* UART. The XBee device driver expects the data to send to be given in this
* format, hence we need to introduce an XBee specific adaption layer that
* translates between GNRC and the XBee proprietary header format.
*
* For this custom header format, we can not make use of the existing adaption
* layers for other IEEE802.15.4 devices.
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*/
#ifndef GNRC_NETDEV2_XBEE_ADPT_H_
#define GNRC_NETDEV2_XBEE_ADPT_H_
#include "xbee.h"
#include "net/gnrc/netdev2.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initialize GNRC handler for netdev2 XBee devices
*
* @param[out] gnrc_netdev2 gnrc_netdev2 struct to initialize
* @param[in] dev XBee device to handle
*/
void gnrc_netdev2_xbee_init(gnrc_netdev2_t *gnrc_netdev2, xbee_t *dev);
#ifdef __cplusplus
}
#endif
#endif /* GNRC_NETDEV2_XBEE_ADPT_H_ */
/** @} */

182
sys/net/gnrc/link_layer/netdev2/gnrc_netdev2_xbee.c

@ -0,0 +1,182 @@
/*
* Copyright (C) 2016 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
* @{
*
* @file
* @brief GNRC to netdev adapter for XBee devices
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*
* @}
*/
#include "assert.h"
#include "xbee.h"
#include "net/gnrc.h"
#include "net/gnrc/netdev2/xbee_adpt.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
#define BCAST (GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)
static gnrc_pktsnip_t *xbee_adpt_recv(gnrc_netdev2_t *gnrc_netdev2)
{
netdev2_t *dev = gnrc_netdev2->dev;
int pktlen;
int xhdr_len;
gnrc_pktsnip_t *payload;
gnrc_pktsnip_t *netif_snip;
gnrc_pktsnip_t *xhdr_snip;
gnrc_netif_hdr_t *netif;
xbee_l2hdr_t l2hdr;
assert(dev);
/* see how much data there is to process */
pktlen = dev->driver->recv(dev, NULL, 0, NULL);
if (pktlen <= 0) {
DEBUG("[xbee-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, XBEE_DEFAULT_PROTOCOL);
if (payload == NULL) {
DEBUG("[xbee-gnrc] recv: unable to allocate space in the pktbuf\n");
/* tell the driver to drop the packet */
dev->driver->recv(dev, NULL, 1, NULL);
return NULL;
}
/* copy the complete including the XBee header into the packet buffer */
dev->driver->recv(dev, payload->data, pktlen, NULL);
/* try to parse the L2 header data from the XBee header */
xhdr_len = xbee_parse_hdr((xbee_t *)dev, (uint8_t *)payload->data, &l2hdr);
if (xhdr_len < 0) {
DEBUG("[xbee-gnrc] recv: unable to parse XBee header\n");
gnrc_pktbuf_release(payload);
return NULL;
}
/* crop the XBee header from the payload */
xhdr_snip = gnrc_pktbuf_mark(payload, xhdr_len, GNRC_NETTYPE_UNDEF);
if (xhdr_snip == NULL) {
DEBUG("[xbee-gnrc] recv: unable to mark XBee header snip\n");
gnrc_pktbuf_release(payload);
return NULL;
}
gnrc_pktbuf_remove_snip(payload, xhdr_snip);
/* create a netif hdr from the obtained data */
netif_snip = gnrc_netif_hdr_build(l2hdr.src_addr, l2hdr.addr_len,
l2hdr.dst_addr, l2hdr.addr_len);
if (netif_snip == NULL) {
DEBUG("[xbee-gnrc] recv: unable to allocate netif header\n");
gnrc_pktbuf_release(payload);
return NULL;
}
netif = (gnrc_netif_hdr_t *)netif_snip->data;
netif->if_pid = gnrc_netdev2->pid;
netif->rssi = l2hdr.rssi;
if (l2hdr.bcast) {
netif->flags = GNRC_NETIF_HDR_FLAGS_BROADCAST;
}
DEBUG("[xbee-gnrc] recv: successfully parsed packet\n");
/* and append the netif header */
LL_APPEND(payload, netif_snip);
return payload;
}
static int xbee_adpt_send(gnrc_netdev2_t *dev, gnrc_pktsnip_t *pkt)
{
int res;
size_t size;
size_t count;
gnrc_pktsnip_t *vec;
gnrc_netif_hdr_t *hdr;
uint8_t xhdr[XBEE_MAX_TXHDR_LENGTH];
/* check device descriptor and packet */
assert(dev && pkt);
/* get the payload size and the dst address details */
size = gnrc_pkt_len(pkt->next);
DEBUG("[xbee-gnrc] send: payload of packet is %i\n", (int)size);
hdr = (gnrc_netif_hdr_t *)pkt->data;
if (hdr->flags & BCAST) {
uint16_t addr = 0xffff;
res = xbee_build_hdr((xbee_t *)dev, xhdr, size, &addr, 2);
DEBUG("[xbee-gnrc] send: preparing to send broadcast\n");
}
else {
uint8_t *addr = gnrc_netif_hdr_get_dst_addr(hdr);
res = xbee_build_hdr((xbee_t *)dev, xhdr, size, addr, hdr->dst_l2addr_len);
if (res < 0) {
if (res == -EOVERFLOW) {
DEBUG("[xbee-gnrc] send: payload length exceeds max limit\n");
}
else if (res == -ENOMSG) {
DEBUG("[xbee-gnrc] send: invalid destination l2 address\n");
}
return res;
}
if (hdr->dst_l2addr_len == IEEE802154_SHORT_ADDRESS_LEN) {
DEBUG("[xbee-gnrc] send: preparing to send unicast to %02x:%02x\n",
(int)addr[0], (int)addr[1]);
}
else {
DEBUG("[xbee-gnrc] send: preparing to send unicast to "
"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
(int)addr[0], (int)addr[1], (int)addr[2], (int)addr[3],
(int)addr[4], (int)addr[5], (int)addr[6], (int)addr[7]);
}
}
/* now let's extract the iovector and send out the stuff */
vec = gnrc_pktbuf_get_iovec(pkt, &count);
if (vec != NULL) {
pkt = vec;
struct iovec *vector = (struct iovec *)pkt->data;
vector[0].iov_base = xhdr;
vector[0].iov_len = res;
#ifdef MODULE_NETSTATS_L2
if (hdr->flags & BCAST) {
dev->dev->stats.tx_mcast_count++;
}
else {
dev->dev->stats.tx_unicast_count++;
}
#endif
DEBUG("[xbee-gnrc] send: triggering the drivers send function\n");
res = dev->dev->driver->send(dev->dev, vector, count);
}
else {
DEBUG("[xbee-gnrc] send: unable to create iovec\n");
}
gnrc_pktbuf_release(pkt);
return res;
}
void gnrc_netdev2_xbee_init(gnrc_netdev2_t *gnrc_netdev2, xbee_t *dev)
{
assert(gnrc_netdev2 && dev);
gnrc_netdev2->send = xbee_adpt_send;
gnrc_netdev2->recv = xbee_adpt_recv;
gnrc_netdev2->dev = (netdev2_t *)dev;
}
Loading…
Cancel
Save