
7 changed files with 669 additions and 10 deletions
@ -0,0 +1,154 @@
|
||||
/*
|
||||
* 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 drivers_netdev_netdev2 |
||||
* @brief |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Definitions for netdev2 common IEEE 802.15.4 code |
||||
* |
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de> |
||||
*/ |
||||
#ifndef NETDEV2_IEEE802154_H_ |
||||
#define NETDEV2_IEEE802154_H_ |
||||
|
||||
#include "net/ieee802154.h" |
||||
#include "net/gnrc/nettype.h" |
||||
#include "net/netopt.h" |
||||
#include "net/netdev2.h" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/**
|
||||
* @name IEEE 802.15.4 netdev2 flags |
||||
* @brief Flags for netdev_ieee802154_t::flags |
||||
* |
||||
* The flag-space `0xff00` is available for device-specific flags. |
||||
* The flag-space `0x00ff` was chosen for global flags to be in accordance to |
||||
* the IEEE 802.15.4 MAC header flags. |
||||
* @{ |
||||
*/ |
||||
|
||||
#define NETDEV2_IEEE802154_SEND_MASK (0x0068) /**< flags to take for send packets */ |
||||
#define NETDEV2_IEEE802154_RESV1 (0x0001) /**< reserved flag */ |
||||
#define NETDEV2_IEEE802154_RAW (0x0002) /**< pass raw frame to upper layer */ |
||||
/**
|
||||
* @brief use long source addres (set) or short source address (unset) |
||||
*/ |
||||
#define NETDEV2_IEEE802154_SRC_MODE_LONG (0x0004) |
||||
#define NETDEV2_IEEE802154_SECURITY_EN (0x0008) /**< enable security */ |
||||
#define NETDEV2_IEEE802154_RESV2 (0x0010) /**< reserved flag */ |
||||
|
||||
/**
|
||||
* @brief request ACK from receiver |
||||
*/ |
||||
#define NETDEV2_IEEE802154_ACK_REQ (0x0020) |
||||
#define NETDEV2_IEEE802154_PAN_COMP (0x0040) /**< compress source PAN ID */ |
||||
#define NETDEV2_IEEE802154_RESV3 (0x0080) /**< reserved flag */ |
||||
/**
|
||||
* @} |
||||
*/ |
||||
|
||||
/**
|
||||
* @brief Extended structure to hold IEEE 802.15.4 driver state |
||||
* |
||||
* @extends netdev2_t |
||||
* |
||||
* Supposed to be extended by driver implementations. |
||||
* The extended structure should contain all variable driver state. |
||||
*/ |
||||
typedef struct { |
||||
netdev2_t netdev; /**< @ref netdev2_t base class */ |
||||
/**
|
||||
* @brief IEEE 802.15.4 specific fields |
||||
* @{ |
||||
*/ |
||||
#ifdef MODULE_GNRC |
||||
gnrc_nettype_t proto; /**< Protocol for upper layer */ |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief PAN ID in network byte order |
||||
*/ |
||||
uint16_t pan; |
||||
|
||||
/**
|
||||
* @brief Short address in network byte order |
||||
*/ |
||||
uint8_t short_addr[IEEE802154_SHORT_ADDRESS_LEN]; |
||||
|
||||
/**
|
||||
* @brief Long address in network byte order |
||||
*/ |
||||
uint8_t long_addr[IEEE802154_LONG_ADDRESS_LEN]; |
||||
uint8_t seq; /**< sequence number */ |
||||
uint8_t chan; /**< channel */ |
||||
uint16_t flags; /**< flags as defined above */ |
||||
/** @} */ |
||||
} netdev2_ieee802154_t; |
||||
|
||||
/**
|
||||
* @brief Received packet status information for IEEE 802.15.4 radios |
||||
*/ |
||||
typedef struct netdev2_radio_rx_info netdev2_ieee802154_rx_info_t; |
||||
|
||||
/**
|
||||
* @brief Fallback function for netdev2 IEEE 802.15.4 devices' _get function |
||||
* |
||||
* Supposed to be used by netdev2 drivers as default case. |
||||
* |
||||
* @param[in] dev network device descriptor |
||||
* @param[in] opt option type |
||||
* @param[out] value pointer to store the option's value in |
||||
* @param[in] max_len maximal amount of byte that fit into @p value |
||||
* |
||||
* @return number of bytes written to @p value |
||||
* @return <0 on error |
||||
*/ |
||||
int netdev2_ieee802154_get(netdev2_ieee802154_t *dev, netopt_t opt, void *value, |
||||
size_t max_len); |
||||
|
||||
/**
|
||||
* @brief Fallback function for netdev2 IEEE 802.15.4 devices' _set function |
||||
* |
||||
* Sets netdev2_ieee802154_t::pan, netdev2_ieee802154_t::short_addr, and |
||||
* netdev2_ieee802154_t::long_addr in device struct. |
||||
* Additionally @ref NETDEV2_IEEE802154_SRC_MODE_LONG, |
||||
* @ref NETDEV2_IEEE802154_RAW and, @ref NETDEV2_IEEE802154_ACK_REQ in |
||||
* netdev2_ieee802154_t::flags can be set or unset. |
||||
* |
||||
* The setting of netdev2_ieee802154_t::chan is omitted since the legality of |
||||
* its value can be very device specific and can't be checked in this function. |
||||
* Please set it in the netdev2_driver_t::set function of your driver. |
||||
* |
||||
* Be aware that this only manipulates the netdev2_ieee802154_t struct. |
||||
* Configuration to the device needs to be done in the netdev2_driver_t::set |
||||
* function of the device driver (which should call this function as a fallback |
||||
* afterwards). |
||||
* |
||||
* @param[in] dev network device descriptor |
||||
* @param[in] opt option type |
||||
* @param[in] value value to set |
||||
* @param[in] value_len the length of @p value |
||||
* |
||||
* @return number of bytes used from @p value |
||||
* @return <0 on error |
||||
*/ |
||||
int netdev2_ieee802154_set(netdev2_ieee802154_t *dev, netopt_t opt, void *value, |
||||
size_t value_len); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* NETDEV2_IEEE802154_H_ */ |
||||
/** @} */ |
@ -0,0 +1 @@
|
||||
include $(RIOTBASE)/Makefile.base |
@ -0,0 +1,243 @@
|
||||
/*
|
||||
* 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. |
||||
*/ |
||||
|
||||
/**
|
||||
* @{ |
||||
* |
||||
* @file |
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de> |
||||
*/ |
||||
|
||||
#include <assert.h> |
||||
#include <errno.h> |
||||
#include <string.h> |
||||
#include <stdbool.h> |
||||
|
||||
#include "net/eui64.h" |
||||
#include "net/ieee802154.h" |
||||
#include "net/netdev2.h" |
||||
|
||||
#include "net/netdev2/ieee802154.h" |
||||
|
||||
#define ENABLE_DEBUG (0) |
||||
#include "debug.h" |
||||
|
||||
static int _get_iid(netdev2_ieee802154_t *dev, eui64_t *value, size_t max_len) |
||||
{ |
||||
uint8_t *addr; |
||||
uint16_t addr_len; |
||||
|
||||
if (max_len < sizeof(eui64_t)) { |
||||
return -EOVERFLOW; |
||||
} |
||||
|
||||
if (dev->flags & NETDEV2_IEEE802154_SRC_MODE_LONG) { |
||||
addr_len = IEEE802154_LONG_ADDRESS_LEN; |
||||
addr = dev->long_addr; |
||||
} |
||||
else { |
||||
addr_len = IEEE802154_SHORT_ADDRESS_LEN; |
||||
addr = dev->short_addr; |
||||
} |
||||
ieee802154_get_iid(value, addr, addr_len); |
||||
|
||||
return sizeof(eui64_t); |
||||
} |
||||
|
||||
int netdev2_ieee802154_get(netdev2_ieee802154_t *dev, netopt_t opt, void *value, |
||||
size_t max_len) |
||||
{ |
||||
int res = -ENOTSUP; |
||||
|
||||
switch (opt) { |
||||
case NETOPT_ADDRESS: |
||||
if (max_len < sizeof(dev->short_addr)) { |
||||
res = -EOVERFLOW; |
||||
break; |
||||
} |
||||
memcpy(value, dev->short_addr, sizeof(dev->short_addr)); |
||||
res = sizeof(dev->short_addr); |
||||
break; |
||||
case NETOPT_ADDRESS_LONG: |
||||
if (max_len < sizeof(dev->long_addr)) { |
||||
res = -EOVERFLOW; |
||||
break; |
||||
} |
||||
memcpy(value, dev->long_addr, sizeof(dev->long_addr)); |
||||
res = sizeof(dev->long_addr); |
||||
break; |
||||
case NETOPT_ADDR_LEN: |
||||
case NETOPT_SRC_LEN: |
||||
if (max_len < sizeof(uint16_t)) { |
||||
res = -EOVERFLOW; |
||||
break; |
||||
} |
||||
if (dev->flags & NETDEV2_IEEE802154_SRC_MODE_LONG) { |
||||
*((uint16_t *)value) = IEEE802154_LONG_ADDRESS_LEN; |
||||
} |
||||
else { |
||||
*((uint16_t *)value) = IEEE802154_SHORT_ADDRESS_LEN; |
||||
} |
||||
res = sizeof(uint16_t); |
||||
break; |
||||
case NETOPT_NID: |
||||
if (max_len < sizeof(dev->pan)) { |
||||
res = -EOVERFLOW; |
||||
break; |
||||
} |
||||
*((uint16_t *)value) = dev->pan; |
||||
res = sizeof(dev->pan); |
||||
break; |
||||
case NETOPT_CHANNEL: |
||||
if (max_len < sizeof(uint16_t)) { |
||||
res = -EOVERFLOW; |
||||
break; |
||||
} |
||||
*((uint16_t *)value) = (uint16_t)dev->chan; |
||||
res = sizeof(dev->chan); |
||||
break; |
||||
case NETOPT_AUTOACK: |
||||
if (max_len < sizeof(netopt_enable_t)) { |
||||
res = -EOVERFLOW; |
||||
break; |
||||
} |
||||
if (dev->flags & NETDEV2_IEEE802154_ACK_REQ) { |
||||
*((netopt_enable_t *)value) = NETOPT_ENABLE; |
||||
} |
||||
else { |
||||
*((netopt_enable_t *)value) = NETOPT_DISABLE; |
||||
} |
||||
res = sizeof(netopt_enable_t); |
||||
break; |
||||
case NETOPT_RAWMODE: |
||||
if (max_len < sizeof(netopt_enable_t)) { |
||||
res = -EOVERFLOW; |
||||
break; |
||||
} |
||||
if (dev->flags & NETDEV2_IEEE802154_RAW) { |
||||
*((netopt_enable_t *)value) = NETOPT_ENABLE; |
||||
} |
||||
else { |
||||
*((netopt_enable_t *)value) = NETOPT_DISABLE; |
||||
} |
||||
res = sizeof(netopt_enable_t); |
||||
break; |
||||
#ifdef MODULE_GNRC |
||||
case NETOPT_PROTO: |
||||
if (max_len < sizeof(gnrc_nettype_t)) { |
||||
res = -EOVERFLOW; |
||||
break; |
||||
} |
||||
*((gnrc_nettype_t *)value) = dev->proto; |
||||
res = sizeof(gnrc_nettype_t); |
||||
break; |
||||
#endif |
||||
case NETOPT_DEVICE_TYPE: |
||||
if (max_len < sizeof(uint16_t)) { |
||||
res = -EOVERFLOW; |
||||
break; |
||||
} |
||||
*((uint16_t *)value) = NETDEV2_TYPE_IEEE802154; |
||||
res = sizeof(uint16_t); |
||||
break; |
||||
case NETOPT_IPV6_IID: |
||||
res = _get_iid(dev, value, max_len); |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
return res; |
||||
} |
||||
|
||||
int netdev2_ieee802154_set(netdev2_ieee802154_t *dev, netopt_t opt, void *value, |
||||
size_t len) |
||||
{ |
||||
int res = -ENOTSUP; |
||||
|
||||
switch (opt) { |
||||
case NETOPT_ADDRESS: |
||||
if (len > sizeof(dev->short_addr)) { |
||||
res = -EOVERFLOW; |
||||
break; |
||||
} |
||||
memset(dev->short_addr, 0, sizeof(dev->short_addr)); |
||||
memcpy(dev->short_addr, value, len); |
||||
res = sizeof(dev->short_addr); |
||||
break; |
||||
case NETOPT_ADDRESS_LONG: |
||||
if (len > sizeof(dev->long_addr)) { |
||||
res = -EOVERFLOW; |
||||
break; |
||||
} |
||||
memset(dev->long_addr, 0, sizeof(dev->long_addr)); |
||||
memcpy(dev->long_addr, value, len); |
||||
res = sizeof(dev->long_addr); |
||||
break; |
||||
case NETOPT_ADDR_LEN: |
||||
case NETOPT_SRC_LEN: |
||||
if (len > sizeof(uint16_t)) { |
||||
res = -EOVERFLOW; |
||||
break; |
||||
} |
||||
switch ((*(uint16_t *)value)) { |
||||
case IEEE802154_SHORT_ADDRESS_LEN: |
||||
dev->flags &= ~NETDEV2_IEEE802154_SRC_MODE_LONG; |
||||
break; |
||||
case IEEE802154_LONG_ADDRESS_LEN: |
||||
dev->flags |= NETDEV2_IEEE802154_SRC_MODE_LONG; |
||||
break; |
||||
default: |
||||
res = -EAFNOSUPPORT; |
||||
break; |
||||
} |
||||
res = sizeof(uint16_t); |
||||
break; |
||||
case NETOPT_NID: |
||||
if (len > sizeof(dev->pan)) { |
||||
res = -EOVERFLOW; |
||||
break; |
||||
} |
||||
dev->pan = *((uint16_t *)value); |
||||
res = sizeof(dev->pan); |
||||
break; |
||||
/* channel can be very device specific */ |
||||
case NETOPT_AUTOACK: |
||||
if ((*(bool *)value)) { |
||||
dev->flags |= NETDEV2_IEEE802154_ACK_REQ; |
||||
} |
||||
else { |
||||
dev->flags &= ~NETDEV2_IEEE802154_ACK_REQ; |
||||
} |
||||
res = sizeof(uint16_t); |
||||
break; |
||||
case NETOPT_RAWMODE: |
||||
if ((*(bool *)value)) { |
||||
dev->flags |= NETDEV2_IEEE802154_RAW; |
||||
} |
||||
else { |
||||
dev->flags &= ~NETDEV2_IEEE802154_RAW; |
||||
} |
||||
res = sizeof(uint16_t); |
||||
break; |
||||
#ifdef MODULE_GNRC |
||||
case NETOPT_PROTO: |
||||
if (len > sizeof(gnrc_nettype_t)) { |
||||
res = -EOVERFLOW; |
||||
break; |
||||
} |
||||
dev->proto = *((gnrc_nettype_t *)value); |
||||
res = sizeof(gnrc_nettype_t); |
||||
break; |
||||
#endif |
||||
default: |
||||
break; |
||||
} |
||||
return res; |
||||
} |
||||
|
||||
/** @} */ |
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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 |
||||
* @brief |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief netdev2 gnrc IEEE 802.15.4 glue code interface |
||||
* |
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de> |
||||
*/ |
||||
#ifndef GNRC_NETDEV2_IEEE802154_H_ |
||||
#define GNRC_NETDEV2_IEEE802154_H_ |
||||
|
||||
#include "net/netdev2/ieee802154.h" |
||||
#include "net/gnrc/netdev2.h" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief Initialize gnrc handler for netdev2 IEEE 802.15.4 device |
||||
* |
||||
* @param[in] gnrc_netdev2 gnrc_netdev2 struct to initialize |
||||
* @param[in] dev netdev2 device to handle |
||||
* |
||||
* @return 1 on success |
||||
* @return <=0 on error |
||||
*/ |
||||
int gnrc_netdev2_ieee802154_init(gnrc_netdev2_t *gnrc_netdev2, |
||||
netdev2_ieee802154_t *dev); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* GNRC_IEEE802154_H_ */ |
||||
/** @} */ |
@ -0,0 +1,209 @@
|
||||
/*
|
||||
* 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. |
||||
*/ |
||||
|
||||
/**
|
||||
* @{ |
||||
* |
||||
* @file |
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de> |
||||
*/ |
||||
|
||||
#include <stddef.h> |
||||
|
||||
#include "od.h" |
||||
#include "net/gnrc.h" |
||||
#include "net/ieee802154.h" |
||||
|
||||
#include "net/gnrc/netdev2/ieee802154.h" |
||||
|
||||
#define ENABLE_DEBUG (0) |
||||
#include "debug.h" |
||||
|
||||
static gnrc_pktsnip_t *_recv(gnrc_netdev2_t *gnrc_netdev2); |
||||
static int _send(gnrc_netdev2_t *gnrc_netdev2, gnrc_pktsnip_t *pkt); |
||||
|
||||
int gnrc_netdev2_ieee802154_init(gnrc_netdev2_t *gnrc_netdev2, |
||||
netdev2_ieee802154_t *dev) |
||||
{ |
||||
gnrc_netdev2->send = _send; |
||||
gnrc_netdev2->recv = _recv; |
||||
gnrc_netdev2->dev = (netdev2_t *)dev; |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static gnrc_pktsnip_t *_make_netif_hdr(uint8_t *mhr) |
||||
{ |
||||
gnrc_pktsnip_t *snip; |
||||
uint8_t src[IEEE802154_LONG_ADDRESS_LEN], dst[IEEE802154_LONG_ADDRESS_LEN]; |
||||
int src_len, dst_len; |
||||
le_uint16_t _pan_tmp; /* TODO: hand-up PAN IDs to GNRC? */ |
||||
|
||||
dst_len = ieee802154_get_dst(mhr, dst, &_pan_tmp); |
||||
src_len = ieee802154_get_src(mhr, src, &_pan_tmp); |
||||
if ((dst_len < 0) || (src_len < 0)) { |
||||
DEBUG("_make_netif_hdr: unable to get addresses\n"); |
||||
return NULL; |
||||
} |
||||
/* allocate space for header */ |
||||
snip = gnrc_netif_hdr_build(src, (size_t)src_len, dst, (size_t)dst_len); |
||||
if (snip == NULL) { |
||||
DEBUG("_make_netif_hdr: no space left in packet buffer\n"); |
||||
return NULL; |
||||
} |
||||
/* set broadcast flag for broadcast destination */ |
||||
if ((dst_len == 2) && (dst[0] == 0xff) && (dst[1] == 0xff)) { |
||||
gnrc_netif_hdr_t *hdr = snip->data; |
||||
hdr->flags |= GNRC_NETIF_HDR_FLAGS_BROADCAST; |
||||
} |
||||
return snip; |
||||
} |
||||
|
||||
static gnrc_pktsnip_t *_recv(gnrc_netdev2_t *gnrc_netdev2) |
||||
{ |
||||
netdev2_t *netdev = gnrc_netdev2->dev; |
||||
netdev2_ieee802154_rx_info_t rx_info; |
||||
netdev2_ieee802154_t *state = (netdev2_ieee802154_t *)gnrc_netdev2->dev; |
||||
gnrc_pktsnip_t *pkt = NULL; |
||||
int bytes_expected = netdev->driver->recv(netdev, NULL, 0, NULL); |
||||
|
||||
if (bytes_expected > 0) { |
||||
int nread; |
||||
|
||||
pkt = gnrc_pktbuf_add(NULL, NULL, bytes_expected, GNRC_NETTYPE_UNDEF); |
||||
if (pkt == NULL) { |
||||
DEBUG("_recv_ieee802154: cannot allocate pktsnip.\n"); |
||||
return NULL; |
||||
} |
||||
nread = netdev->driver->recv(netdev, pkt->data, bytes_expected, &rx_info); |
||||
if (nread <= 0) { |
||||
gnrc_pktbuf_release(pkt); |
||||
return NULL; |
||||
} |
||||
if (!(state->flags & NETDEV2_IEEE802154_RAW)) { |
||||
gnrc_pktsnip_t *ieee802154_hdr, *netif_hdr; |
||||
gnrc_netif_hdr_t *hdr; |
||||
#if ENABLE_DEBUG |
||||
char src_str[GNRC_NETIF_HDR_L2ADDR_MAX_LEN]; |
||||
#endif |
||||
size_t mhr_len = ieee802154_get_frame_hdr_len(pkt->data); |
||||
|
||||
if (mhr_len == 0) { |
||||
DEBUG("_recv_ieee802154: illegally formatted frame received\n"); |
||||
gnrc_pktbuf_release(pkt); |
||||
return NULL; |
||||
} |
||||
nread -= mhr_len; |
||||
/* mark IEEE 802.15.4 header */ |
||||
ieee802154_hdr = gnrc_pktbuf_mark(pkt, mhr_len, GNRC_NETTYPE_UNDEF); |
||||
if (ieee802154_hdr == NULL) { |
||||
DEBUG("_recv_ieee802154: no space left in packet buffer\n"); |
||||
gnrc_pktbuf_release(pkt); |
||||
return NULL; |
||||
} |
||||
netif_hdr = _make_netif_hdr(ieee802154_hdr->data); |
||||
if (netif_hdr == NULL) { |
||||
DEBUG("_recv_ieee802154: no space left in packet buffer\n"); |
||||
gnrc_pktbuf_release(pkt); |
||||
return NULL; |
||||
} |
||||
hdr = netif_hdr->data; |
||||
hdr->lqi = rx_info.lqi; |
||||
hdr->rssi = rx_info.rssi; |
||||
hdr->if_pid = thread_getpid(); |
||||
pkt->type = state->proto; |
||||
#if ENABLE_DEBUG |
||||
DEBUG("_recv_ieee802154: received packet from %s of length %u\n", |
||||
gnrc_netif_addr_to_str(src_str, sizeof(src_str), |
||||
gnrc_netif_hdr_get_src_addr(hdr), |
||||
hdr->src_l2addr_len), |
||||
nread); |
||||
#if defined(MODULE_OD) |
||||
od_hex_dump(pkt->data, nread, OD_WIDTH_DEFAULT); |
||||
#endif |
||||
#endif |
||||
gnrc_pktbuf_remove_snip(pkt, ieee802154_hdr); |
||||
LL_APPEND(pkt, netif_hdr); |
||||
} |
||||
|
||||
DEBUG("_recv_ieee802154: reallocating.\n"); |
||||
gnrc_pktbuf_realloc_data(pkt, nread); |
||||
} |
||||
|
||||
return pkt; |
||||
} |
||||
|
||||
static int _send(gnrc_netdev2_t *gnrc_netdev2, gnrc_pktsnip_t *pkt) |
||||
{ |
||||
netdev2_t *netdev = gnrc_netdev2->dev; |
||||
netdev2_ieee802154_t *state = (netdev2_ieee802154_t *)gnrc_netdev2->dev; |
||||
gnrc_netif_hdr_t *netif_hdr; |
||||
gnrc_pktsnip_t *vec_snip; |
||||
uint8_t *src, *dst = NULL; |
||||
int res = 0; |
||||
size_t n, src_len; |
||||
uint8_t mhr[IEEE802154_MAX_HDR_LEN]; |
||||
uint8_t flags = (uint8_t)(state->flags & NETDEV2_IEEE802154_SEND_MASK); |
||||
le_uint16_t dev_pan = byteorder_btols(byteorder_htons(state->pan)); |
||||
|
||||
flags |= IEEE802154_FCF_TYPE_DATA; |
||||
if (pkt == NULL) { |
||||
DEBUG("_send_ieee802154: pkt was NULL\n"); |
||||
return -EINVAL; |
||||
} |
||||
if (pkt->type != GNRC_NETTYPE_NETIF) { |
||||
DEBUG("_send_ieee802154: first header is not generic netif header\n"); |
||||
return -EBADMSG; |
||||
} |
||||
netif_hdr = pkt->data; |
||||
/* prepare destination address */ |
||||
if (netif_hdr->flags & /* If any of these flags is set so this is correct */ |
||||
(GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) { |
||||
flags |= IEEE802154_BCAST; |
||||
} |
||||
else { |
||||
dst = gnrc_netif_hdr_get_dst_addr(netif_hdr); |
||||
} |
||||
src_len = netif_hdr->src_l2addr_len; |
||||
if (src_len > 0) { |
||||
src = gnrc_netif_hdr_get_src_addr(netif_hdr); |
||||
} |
||||
else if (state->flags & NETDEV2_IEEE802154_SRC_MODE_LONG) { |
||||
src_len = IEEE802154_LONG_ADDRESS_LEN; |
||||
src = state->long_addr; |
||||
} |
||||
else { |
||||
src_len = IEEE802154_SHORT_ADDRESS_LEN; |
||||
src = state->short_addr; |
||||
} |
||||
/* fill MAC header, seq should be set by device */ |
||||
if ((res = ieee802154_set_frame_hdr(mhr, src, src_len, |
||||
dst, netif_hdr->dst_l2addr_len, |
||||
dev_pan, dev_pan, flags, |
||||
state->seq++)) == 0) { |
||||
DEBUG("_send_ieee802154: Error preperaring frame\n"); |
||||
return -EINVAL; |
||||
} |
||||
/* prepare packet for sending */ |
||||
vec_snip = gnrc_pktbuf_get_iovec(pkt, &n); |
||||
res = -ENOBUFS; |
||||
if (vec_snip != NULL) { |
||||
struct iovec *vector; |
||||
|
||||
pkt = vec_snip; /* reassign for later release; vec_snip is prepended to pkt */ |
||||
vector = (struct iovec *)pkt->data; |
||||
vector[0].iov_base = mhr; |
||||
vector[0].iov_len = (size_t)res; |
||||
res = netdev->driver->send(netdev, vector, n); |
||||
} |
||||
/* release old data */ |
||||
gnrc_pktbuf_release(pkt); |
||||
return res; |
||||
} |
||||
|
||||
/** @} */ |
Loading…
Reference in new issue