2016-01-16 19:42:10 +01:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
2018-06-01 12:09:01 +02:00
|
|
|
* @ingroup drivers_netdev_ieee802154
|
2016-01-16 19:42:10 +01:00
|
|
|
* @{
|
|
|
|
*
|
|
|
|
* @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"
|
2017-02-15 13:07:34 +01:00
|
|
|
#include "net/netdev.h"
|
2018-07-10 18:31:09 +02:00
|
|
|
#include "random.h"
|
2016-01-16 19:42:10 +01:00
|
|
|
|
2017-02-15 13:07:34 +01:00
|
|
|
#include "net/netdev/ieee802154.h"
|
2016-01-16 19:42:10 +01:00
|
|
|
|
|
|
|
#define ENABLE_DEBUG (0)
|
|
|
|
#include "debug.h"
|
|
|
|
|
2017-02-15 13:07:34 +01:00
|
|
|
static int _get_iid(netdev_ieee802154_t *dev, eui64_t *value, size_t max_len)
|
2016-01-16 19:42:10 +01:00
|
|
|
{
|
build: fix unused parameter errors
cpu, sam0_common: fix unused parameter in periph/spi
cpu, kinetis_common: fix unused parameter in periph/spi
cpu, cc2538: fix unused param in periph/i2c
cpu, cc2538: fix unused param in periph/spi
cpu, sam3: fix unused param in periph/spi
cpu, stm32_common: fix unused param in periph/pm
cpu, stm32f3: fix unused params in periph/i2c
cpu, nrf5x_common: fix unused param in periph/gpio
cpu, nrf5x_common: fix unused param in periph/spi
cpu, lpc2387: fix unused params in periph/spi
cpu, cc2538: fix unused params in radio/netdev
cpu, cc2650: fix unused params in periph/uart
cpu, lm4f120: fix unused param in periph/spi
cpu, lm4f120: fix unused params in periph/timer
cpu, lm4f120: fix unused params in periph/uart
cpu, stm32_common: fix unused params in periph/dac
cpu, stm32l0: fix unused params in periph/i2c
cpu, msp430fxyz: fix unused params in periph/uart
cpu, mips: fix unused params
cpu, cc430: fix unused-params in periph/timer
cpu, msp430fxyz: fix unused params in periph/spi
drivers, cc2420: fix unused param
cpu, mips32r2_common: fix unused params in periph/timer
cpu, cc2538: fix unused-param in periph/i2c
cpu, mips32r2_common: fix unused-param in periph/timer
cpu, msp430fxyz: fix unused params in periph/timer
cpu, atmega_common: fix unused params in periph/spi
driver, nrfmin: fix unused params
cpu, cc2538_rf: fix unused params
driver, netdev_ieee802514: fix unused param
cpu, mip_pic32m: fix unused params
cpu, lpc2387: fix unused params in periph/pwm
tests/driver_sdcard_spi: fix unused params
cpu, sam3: fix unused param in periph/pwm
tests/driver_dynamixel: fix unused params, and style issues
cpu, cc430: fix unused param in periph/rtc
cpu, atmega_common: fix unused params in periph/i2c
2017-10-31 12:09:11 +01:00
|
|
|
(void)max_len;
|
|
|
|
|
2016-01-16 19:42:10 +01:00
|
|
|
uint8_t *addr;
|
|
|
|
uint16_t addr_len;
|
|
|
|
|
2016-04-17 14:34:23 +02:00
|
|
|
assert(max_len >= sizeof(eui64_t));
|
2016-01-16 19:42:10 +01:00
|
|
|
|
2017-02-15 13:07:34 +01:00
|
|
|
if (dev->flags & NETDEV_IEEE802154_SRC_MODE_LONG) {
|
2016-01-16 19:42:10 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2018-07-10 14:27:52 +02:00
|
|
|
void netdev_ieee802154_reset(netdev_ieee802154_t *dev)
|
|
|
|
{
|
2018-07-10 18:31:09 +02:00
|
|
|
/* Only the least significant byte of the random value is used */
|
|
|
|
dev->seq = random_uint32();
|
2018-07-10 14:27:52 +02:00
|
|
|
dev->flags = 0;
|
|
|
|
|
|
|
|
/* set default protocol */
|
|
|
|
#ifdef MODULE_GNRC_SIXLOWPAN
|
|
|
|
dev->proto = GNRC_NETTYPE_SIXLOWPAN;
|
|
|
|
#elif MODULE_GNRC
|
|
|
|
dev->proto = GNRC_NETTYPE_UNDEF;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2017-02-15 13:07:34 +01:00
|
|
|
int netdev_ieee802154_get(netdev_ieee802154_t *dev, netopt_t opt, void *value,
|
2016-01-16 19:42:10 +01:00
|
|
|
size_t max_len)
|
|
|
|
{
|
|
|
|
int res = -ENOTSUP;
|
|
|
|
|
|
|
|
switch (opt) {
|
|
|
|
case NETOPT_ADDRESS:
|
2016-04-17 14:34:23 +02:00
|
|
|
assert(max_len >= sizeof(dev->short_addr));
|
2016-01-16 19:42:10 +01:00
|
|
|
memcpy(value, dev->short_addr, sizeof(dev->short_addr));
|
|
|
|
res = sizeof(dev->short_addr);
|
|
|
|
break;
|
|
|
|
case NETOPT_ADDRESS_LONG:
|
2016-04-17 14:34:23 +02:00
|
|
|
assert(max_len >= sizeof(dev->long_addr));
|
2016-01-16 19:42:10 +01:00
|
|
|
memcpy(value, dev->long_addr, sizeof(dev->long_addr));
|
|
|
|
res = sizeof(dev->long_addr);
|
|
|
|
break;
|
|
|
|
case NETOPT_ADDR_LEN:
|
|
|
|
case NETOPT_SRC_LEN:
|
2016-04-17 14:34:23 +02:00
|
|
|
assert(max_len == sizeof(uint16_t));
|
2017-02-15 13:07:34 +01:00
|
|
|
if (dev->flags & NETDEV_IEEE802154_SRC_MODE_LONG) {
|
2016-01-16 19:42:10 +01:00
|
|
|
*((uint16_t *)value) = IEEE802154_LONG_ADDRESS_LEN;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
*((uint16_t *)value) = IEEE802154_SHORT_ADDRESS_LEN;
|
|
|
|
}
|
|
|
|
res = sizeof(uint16_t);
|
|
|
|
break;
|
|
|
|
case NETOPT_NID:
|
2016-04-17 14:34:23 +02:00
|
|
|
assert(max_len == sizeof(dev->pan));
|
2016-01-16 19:42:10 +01:00
|
|
|
*((uint16_t *)value) = dev->pan;
|
|
|
|
res = sizeof(dev->pan);
|
|
|
|
break;
|
|
|
|
case NETOPT_CHANNEL:
|
2016-04-17 14:34:23 +02:00
|
|
|
assert(max_len == sizeof(uint16_t));
|
2016-01-16 19:42:10 +01:00
|
|
|
*((uint16_t *)value) = (uint16_t)dev->chan;
|
|
|
|
res = sizeof(dev->chan);
|
|
|
|
break;
|
2016-04-12 01:04:02 +02:00
|
|
|
case NETOPT_ACK_REQ:
|
2016-04-17 14:34:23 +02:00
|
|
|
assert(max_len == sizeof(netopt_enable_t));
|
2017-02-15 13:07:34 +01:00
|
|
|
if (dev->flags & NETDEV_IEEE802154_ACK_REQ) {
|
2016-01-16 19:42:10 +01:00
|
|
|
*((netopt_enable_t *)value) = NETOPT_ENABLE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
*((netopt_enable_t *)value) = NETOPT_DISABLE;
|
|
|
|
}
|
|
|
|
res = sizeof(netopt_enable_t);
|
|
|
|
break;
|
2016-01-16 19:43:38 +01:00
|
|
|
case NETOPT_RAWMODE:
|
2016-04-17 14:34:23 +02:00
|
|
|
assert(max_len == sizeof(netopt_enable_t));
|
2017-02-15 13:07:34 +01:00
|
|
|
if (dev->flags & NETDEV_IEEE802154_RAW) {
|
2016-01-16 19:42:10 +01:00
|
|
|
*((netopt_enable_t *)value) = NETOPT_ENABLE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
*((netopt_enable_t *)value) = NETOPT_DISABLE;
|
|
|
|
}
|
|
|
|
res = sizeof(netopt_enable_t);
|
|
|
|
break;
|
2016-01-16 19:43:38 +01:00
|
|
|
#ifdef MODULE_GNRC
|
|
|
|
case NETOPT_PROTO:
|
2016-04-17 14:34:23 +02:00
|
|
|
assert(max_len == sizeof(gnrc_nettype_t));
|
2016-01-16 19:43:38 +01:00
|
|
|
*((gnrc_nettype_t *)value) = dev->proto;
|
|
|
|
res = sizeof(gnrc_nettype_t);
|
|
|
|
break;
|
|
|
|
#endif
|
2016-01-16 19:42:10 +01:00
|
|
|
case NETOPT_DEVICE_TYPE:
|
2016-04-17 14:34:23 +02:00
|
|
|
assert(max_len == sizeof(uint16_t));
|
2017-02-15 13:07:34 +01:00
|
|
|
*((uint16_t *)value) = NETDEV_TYPE_IEEE802154;
|
2016-01-16 19:42:10 +01:00
|
|
|
res = sizeof(uint16_t);
|
|
|
|
break;
|
|
|
|
case NETOPT_IPV6_IID:
|
|
|
|
res = _get_iid(dev, value, max_len);
|
|
|
|
break;
|
2016-02-11 23:06:07 +01:00
|
|
|
#ifdef MODULE_NETSTATS_L2
|
2016-02-11 22:39:34 +01:00
|
|
|
case NETOPT_STATS:
|
2016-04-17 14:34:23 +02:00
|
|
|
assert(max_len == sizeof(uintptr_t));
|
2016-04-02 00:51:19 +02:00
|
|
|
*((netstats_t **)value) = &dev->netdev.stats;
|
2016-02-11 22:39:34 +01:00
|
|
|
res = sizeof(uintptr_t);
|
|
|
|
break;
|
2017-05-16 16:28:58 +02:00
|
|
|
#endif
|
|
|
|
#ifdef MODULE_L2FILTER
|
|
|
|
case NETOPT_L2FILTER:
|
|
|
|
assert(max_len >= sizeof(l2filter_t **));
|
|
|
|
*((l2filter_t **)value) = dev->netdev.filter;
|
|
|
|
res = sizeof(l2filter_t **);
|
|
|
|
break;
|
2016-02-11 23:06:07 +01:00
|
|
|
#endif
|
2016-01-16 19:42:10 +01:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2017-08-25 07:34:03 +02:00
|
|
|
int netdev_ieee802154_set(netdev_ieee802154_t *dev, netopt_t opt, const void *value,
|
2016-01-16 19:42:10 +01:00
|
|
|
size_t len)
|
|
|
|
{
|
|
|
|
int res = -ENOTSUP;
|
|
|
|
|
|
|
|
switch (opt) {
|
2016-04-02 00:51:19 +02:00
|
|
|
case NETOPT_CHANNEL:
|
|
|
|
{
|
2016-04-17 14:34:23 +02:00
|
|
|
assert(len == sizeof(uint16_t));
|
2016-04-02 00:51:19 +02:00
|
|
|
uint16_t chan = *((uint16_t *)value);
|
|
|
|
/* real validity needs to be checked by device, since sub-GHz and
|
|
|
|
* 2.4 GHz band radios have different legal values. Here we only
|
|
|
|
* check that it fits in an 8-bit variabl*/
|
|
|
|
assert(chan <= UINT8_MAX);
|
|
|
|
dev->chan = chan;
|
|
|
|
res = sizeof(uint16_t);
|
|
|
|
break;
|
|
|
|
}
|
2016-01-16 19:42:10 +01:00
|
|
|
case NETOPT_ADDRESS:
|
2016-04-17 14:34:23 +02:00
|
|
|
assert(len <= sizeof(dev->short_addr));
|
2016-01-16 19:42:10 +01:00
|
|
|
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:
|
2016-04-17 14:34:23 +02:00
|
|
|
assert(len <= sizeof(dev->long_addr));
|
2016-01-16 19:42:10 +01:00
|
|
|
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:
|
2016-04-17 14:34:23 +02:00
|
|
|
assert(len == sizeof(uint16_t));
|
2017-03-15 16:12:24 +01:00
|
|
|
res = sizeof(uint16_t);
|
2016-01-16 19:42:10 +01:00
|
|
|
switch ((*(uint16_t *)value)) {
|
|
|
|
case IEEE802154_SHORT_ADDRESS_LEN:
|
2017-02-15 13:07:34 +01:00
|
|
|
dev->flags &= ~NETDEV_IEEE802154_SRC_MODE_LONG;
|
2016-01-16 19:42:10 +01:00
|
|
|
break;
|
|
|
|
case IEEE802154_LONG_ADDRESS_LEN:
|
2017-02-15 13:07:34 +01:00
|
|
|
dev->flags |= NETDEV_IEEE802154_SRC_MODE_LONG;
|
2016-01-16 19:42:10 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
res = -EAFNOSUPPORT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case NETOPT_NID:
|
2016-04-17 14:34:23 +02:00
|
|
|
assert(len == sizeof(dev->pan));
|
2016-01-16 19:42:10 +01:00
|
|
|
dev->pan = *((uint16_t *)value);
|
|
|
|
res = sizeof(dev->pan);
|
|
|
|
break;
|
2016-04-12 01:04:02 +02:00
|
|
|
case NETOPT_ACK_REQ:
|
2016-01-16 19:42:10 +01:00
|
|
|
if ((*(bool *)value)) {
|
2017-02-15 13:07:34 +01:00
|
|
|
dev->flags |= NETDEV_IEEE802154_ACK_REQ;
|
2016-01-16 19:42:10 +01:00
|
|
|
}
|
|
|
|
else {
|
2017-02-15 13:07:34 +01:00
|
|
|
dev->flags &= ~NETDEV_IEEE802154_ACK_REQ;
|
2016-01-16 19:42:10 +01:00
|
|
|
}
|
|
|
|
res = sizeof(uint16_t);
|
|
|
|
break;
|
|
|
|
case NETOPT_RAWMODE:
|
|
|
|
if ((*(bool *)value)) {
|
2017-02-15 13:07:34 +01:00
|
|
|
dev->flags |= NETDEV_IEEE802154_RAW;
|
2016-01-16 19:42:10 +01:00
|
|
|
}
|
|
|
|
else {
|
2017-02-15 13:07:34 +01:00
|
|
|
dev->flags &= ~NETDEV_IEEE802154_RAW;
|
2016-01-16 19:42:10 +01:00
|
|
|
}
|
|
|
|
res = sizeof(uint16_t);
|
|
|
|
break;
|
2016-01-16 19:43:38 +01:00
|
|
|
#ifdef MODULE_GNRC
|
|
|
|
case NETOPT_PROTO:
|
2016-04-17 14:34:23 +02:00
|
|
|
assert(len == sizeof(gnrc_nettype_t));
|
2016-01-16 19:43:38 +01:00
|
|
|
dev->proto = *((gnrc_nettype_t *)value);
|
|
|
|
res = sizeof(gnrc_nettype_t);
|
|
|
|
break;
|
2017-05-16 16:28:58 +02:00
|
|
|
#endif
|
|
|
|
#ifdef MODULE_L2FILTER
|
|
|
|
case NETOPT_L2FILTER:
|
|
|
|
res = l2filter_add(dev->netdev.filter, value, len);
|
|
|
|
break;
|
|
|
|
case NETOPT_L2FILTER_RM:
|
|
|
|
res = l2filter_rm(dev->netdev.filter, value, len);
|
|
|
|
break;
|
2016-01-16 19:43:38 +01:00
|
|
|
#endif
|
2016-01-16 19:42:10 +01:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @} */
|