diff --git a/Makefile.dep b/Makefile.dep index 015db06ffb64081ec2749c04dcd12079d7925402..553b16894cd096884f779df20b992e23f4af7b70 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -12,6 +12,10 @@ ifneq (,$(filter nhdp,$(USEMODULE))) USEMODULE += oonf_rfc5444 endif +ifneq (,$(filter at86rf2%,$(USEMODULE))) + USEMODULE += netdev2_ieee802154 +endif + ifneq (,$(filter netdev2_ieee802154,$(USEMODULE))) USEMODULE += ieee802154 endif diff --git a/boards/fox/Makefile.dep b/boards/fox/Makefile.dep index cb47b51f4c62670889ebc544732edc2c59346e09..1a15e53a2e5a75fe39079c8976b2df2233b9ed0c 100644 --- a/boards/fox/Makefile.dep +++ b/boards/fox/Makefile.dep @@ -1,6 +1,6 @@ ifneq (,$(filter gnrc_netif_default,$(USEMODULE))) USEMODULE += at86rf231 - USEMODULE += gnrc_nomac + USEMODULE += gnrc_netdev2 endif ifneq (,$(filter saul_default,$(USEMODULE))) diff --git a/boards/iotlab-m3/Makefile.dep b/boards/iotlab-m3/Makefile.dep index 76e00fddaec989beb9f76acd91a15192b24d362e..92db731b1c93ae87c3d733eded296b8b26d754c3 100644 --- a/boards/iotlab-m3/Makefile.dep +++ b/boards/iotlab-m3/Makefile.dep @@ -1,6 +1,6 @@ ifneq (,$(filter gnrc_netif_default,$(USEMODULE))) USEMODULE += at86rf231 - USEMODULE += gnrc_nomac + USEMODULE += gnrc_netdev2 endif ifneq (,$(filter saul_default,$(USEMODULE))) diff --git a/boards/mulle/Makefile.dep b/boards/mulle/Makefile.dep index b5b923ea7633d4a78f80586088d360c9d51e8254..cc3714b7c951a8d94b02bc2200b6962411fb8b2f 100644 --- a/boards/mulle/Makefile.dep +++ b/boards/mulle/Makefile.dep @@ -1,6 +1,6 @@ ifneq (,$(filter gnrc_netif_default,$(USEMODULE))) USEMODULE += at86rf212b - USEMODULE += gnrc_nomac + USEMODULE += gnrc_netdev2 endif ifneq (,$(filter saul_default,$(USEMODULE))) diff --git a/boards/samr21-xpro/Makefile.dep b/boards/samr21-xpro/Makefile.dep index a69aeffd63ee22fdc4aa816b46356a93d76d7393..874b4f2a5e38d5c33b0b994bf2ca9b3bfa160685 100644 --- a/boards/samr21-xpro/Makefile.dep +++ b/boards/samr21-xpro/Makefile.dep @@ -1,6 +1,6 @@ ifneq (,$(filter gnrc_netif_default,$(USEMODULE))) USEMODULE += at86rf233 - USEMODULE += gnrc_nomac + USEMODULE += gnrc_netdev2 endif ifneq (,$(filter saul_default,$(USEMODULE))) diff --git a/drivers/at86rf2xx/at86rf2xx.c b/drivers/at86rf2xx/at86rf2xx.c index ec7ef6f1367e54fbec57ff0e8d7f545afb44c753..4b9159228d68eddc70f5863cff9b552f3b472d78 100644 --- a/drivers/at86rf2xx/at86rf2xx.c +++ b/drivers/at86rf2xx/at86rf2xx.c @@ -35,22 +35,13 @@ #include "debug.h" -static void _irq_handler(void *arg) +void at86rf2xx_setup(at86rf2xx_t *dev, spi_t spi, spi_speed_t spi_speed, + gpio_t cs_pin, gpio_t int_pin, gpio_t sleep_pin, + gpio_t reset_pin) { - msg_t msg; - at86rf2xx_t *dev = (at86rf2xx_t *) arg; - - /* tell driver thread about the interrupt */ - msg.type = GNRC_NETDEV_MSG_TYPE_EVENT; - msg_send(&msg, dev->mac_pid); -} - -int at86rf2xx_init(at86rf2xx_t *dev, spi_t spi, spi_speed_t spi_speed, - gpio_t cs_pin, gpio_t int_pin, - gpio_t sleep_pin, gpio_t reset_pin) -{ - dev->driver = &at86rf2xx_driver; + netdev2_t *netdev = (netdev2_t *)dev; + netdev->driver = &at86rf2xx_driver; /* initialize device descriptor */ dev->spi = spi; dev->cs_pin = cs_pin; @@ -59,32 +50,8 @@ int at86rf2xx_init(at86rf2xx_t *dev, spi_t spi, spi_speed_t spi_speed, dev->reset_pin = reset_pin; dev->idle_state = AT86RF2XX_STATE_TRX_OFF; dev->state = AT86RF2XX_STATE_SLEEP; - /* initialise SPI */ spi_init_master(dev->spi, SPI_CONF_FIRST_RISING, spi_speed); - /* initialise GPIOs */ - gpio_init(dev->cs_pin, GPIO_OUT); - gpio_set(dev->cs_pin); - gpio_init(dev->sleep_pin, GPIO_OUT); - gpio_clear(dev->sleep_pin); - gpio_init(dev->reset_pin, GPIO_OUT); - gpio_set(dev->reset_pin); - gpio_init_int(dev->int_pin, GPIO_IN, GPIO_RISING, _irq_handler, dev); - - /* make sure device is not sleeping, so we can query part number */ - at86rf2xx_assert_awake(dev); - - /* test if the SPI is set up correctly and the device is responding */ - if (at86rf2xx_reg_read(dev, AT86RF2XX_REG__PART_NUM) != - AT86RF2XX_PARTNUM) { - DEBUG("[at86rf2xx] error: unable to read correct part number\n"); - return -1; - } - - /* reset device to default values and put it into RX state */ - at86rf2xx_reset(dev); - - return 0; } void at86rf2xx_reset(at86rf2xx_t *dev) @@ -100,8 +67,8 @@ void at86rf2xx_reset(at86rf2xx_t *dev) at86rf2xx_reset_state_machine(dev); /* reset options and sequence number */ - dev->seq_nr = 0; - dev->options = 0; + dev->netdev.seq = 0; + dev->netdev.flags = 0; /* set short and long address */ #if CPUID_LEN cpuid_get(cpuid); @@ -134,15 +101,16 @@ void at86rf2xx_reset(at86rf2xx_t *dev) /* set default TX power */ at86rf2xx_set_txpower(dev, AT86RF2XX_DEFAULT_TXPOWER); /* set default options */ + at86rf2xx_set_option(dev, NETDEV2_IEEE802154_PAN_COMP, true); at86rf2xx_set_option(dev, AT86RF2XX_OPT_AUTOACK, true); at86rf2xx_set_option(dev, AT86RF2XX_OPT_CSMA, true); at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_RX_START, false); at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_RX_END, true); /* set default protocol */ #ifdef MODULE_GNRC_SIXLOWPAN - dev->proto = GNRC_NETTYPE_SIXLOWPAN; -#else - dev->proto = GNRC_NETTYPE_UNDEF; + dev->netdev.proto = GNRC_NETTYPE_SIXLOWPAN; +#elif MODULE_GNRC + dev->netdev.proto = GNRC_NETTYPE_UNDEF; #endif /* enable safe mode (protect RX FIFO until reading data starts) */ at86rf2xx_reg_write(dev, AT86RF2XX_REG__TRX_CTRL_2, @@ -219,39 +187,42 @@ void at86rf2xx_tx_prepare(at86rf2xx_t *dev) /* make sure ongoing transmissions are finished */ do { state = at86rf2xx_get_status(dev); - } - while (state == AT86RF2XX_STATE_BUSY_RX_AACK || - state == AT86RF2XX_STATE_BUSY_TX_ARET); + } while (state == AT86RF2XX_STATE_BUSY_RX_AACK || + state == AT86RF2XX_STATE_BUSY_TX_ARET); if (state != AT86RF2XX_STATE_TX_ARET_ON) { dev->idle_state = state; } at86rf2xx_set_state(dev, AT86RF2XX_STATE_TX_ARET_ON); - dev->frame_len = IEEE802154_FCS_LEN; + dev->tx_frame_len = IEEE802154_FCS_LEN; } size_t at86rf2xx_tx_load(at86rf2xx_t *dev, uint8_t *data, size_t len, size_t offset) { - dev->frame_len += (uint8_t)len; + dev->tx_frame_len += (uint8_t)len; at86rf2xx_sram_write(dev, offset + 1, data, len); return offset + len; } void at86rf2xx_tx_exec(at86rf2xx_t *dev) { + netdev2_t *netdev = (netdev2_t *)dev; + /* write frame length field in FIFO */ - at86rf2xx_sram_write(dev, 0, &(dev->frame_len), 1); + at86rf2xx_sram_write(dev, 0, &(dev->tx_frame_len), 1); /* trigger sending of pre-loaded frame */ at86rf2xx_reg_write(dev, AT86RF2XX_REG__TRX_STATE, AT86RF2XX_TRX_STATE__TX_START); - if (dev->event_cb && (dev->options & AT86RF2XX_OPT_TELL_TX_START)) { - dev->event_cb(NETDEV_EVENT_TX_STARTED, NULL); + if (netdev->event_callback && + (dev->netdev.flags & AT86RF2XX_OPT_TELL_TX_START)) { + netdev->event_callback(netdev, NETDEV2_EVENT_TX_STARTED, NULL); } } size_t at86rf2xx_rx_len(at86rf2xx_t *dev) { uint8_t phr; + at86rf2xx_fb_read(dev, &phr, 1); /* ignore MSB (refer p.80) and substract length of FCS field */ diff --git a/drivers/at86rf2xx/at86rf2xx_getset.c b/drivers/at86rf2xx/at86rf2xx_getset.c index 57578eeccc1be61e55fb89a8b7552ec6d3975d0f..4fb4ae5d97d1ca977a438862be9b049c7f26bd4a 100644 --- a/drivers/at86rf2xx/at86rf2xx_getset.c +++ b/drivers/at86rf2xx/at86rf2xx_getset.c @@ -94,22 +94,22 @@ static const uint8_t dbm_to_tx_pow[] = {0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, uint16_t at86rf2xx_get_addr_short(at86rf2xx_t *dev) { - return (dev->addr_short[0] << 8) | dev->addr_short[1]; + return (dev->netdev.short_addr[0] << 8) | dev->netdev.short_addr[1]; } void at86rf2xx_set_addr_short(at86rf2xx_t *dev, uint16_t addr) { - dev->addr_short[0] = addr >> 8; - dev->addr_short[1] = addr; + dev->netdev.short_addr[0] = (uint8_t)(addr); + dev->netdev.short_addr[1] = (uint8_t)(addr >> 8); #ifdef MODULE_SIXLOWPAN /* https://tools.ietf.org/html/rfc4944#section-12 requires the first bit to * 0 for unicast addresses */ - dev->addr_short[1] &= 0x7F; + dev->netdev.short_addr[0] &= 0x7F; #endif at86rf2xx_reg_write(dev, AT86RF2XX_REG__SHORT_ADDR_0, - dev->addr_short[0]); + dev->netdev.short_addr[1]); at86rf2xx_reg_write(dev, AT86RF2XX_REG__SHORT_ADDR_1, - dev->addr_short[1]); + dev->netdev.short_addr[0]); } uint64_t at86rf2xx_get_addr_long(at86rf2xx_t *dev) @@ -117,7 +117,7 @@ uint64_t at86rf2xx_get_addr_long(at86rf2xx_t *dev) uint64_t addr; uint8_t *ap = (uint8_t *)(&addr); for (int i = 0; i < 8; i++) { - ap[i] = dev->addr_long[7 - i]; + ap[i] = dev->netdev.long_addr[i]; } return addr; } @@ -125,26 +125,26 @@ uint64_t at86rf2xx_get_addr_long(at86rf2xx_t *dev) void at86rf2xx_set_addr_long(at86rf2xx_t *dev, uint64_t addr) { for (int i = 0; i < 8; i++) { - dev->addr_long[i] = (addr >> ((7 - i) * 8)); + dev->netdev.long_addr[i] = (uint8_t)(addr >> (i * 8)); at86rf2xx_reg_write(dev, (AT86RF2XX_REG__IEEE_ADDR_0 + i), - dev->addr_long[i]); + (addr >> ((7 - i) * 8))); } } uint8_t at86rf2xx_get_chan(at86rf2xx_t *dev) { - return dev->chan; + return dev->netdev.chan; } void at86rf2xx_set_chan(at86rf2xx_t *dev, uint8_t channel) { if ((channel < AT86RF2XX_MIN_CHANNEL) || (channel > AT86RF2XX_MAX_CHANNEL) || - (dev->chan == channel)) { + (dev->netdev.chan == channel)) { return; } - dev->chan = channel; + dev->netdev.chan = channel; at86rf2xx_configure_phy(dev); } @@ -172,15 +172,16 @@ void at86rf2xx_set_page(at86rf2xx_t *dev, uint8_t page) uint16_t at86rf2xx_get_pan(at86rf2xx_t *dev) { - return dev->pan; + return dev->netdev.pan; } void at86rf2xx_set_pan(at86rf2xx_t *dev, uint16_t pan) { - dev->pan = pan; - DEBUG("pan0: %u, pan1: %u\n", (uint8_t)pan, pan >> 8); - at86rf2xx_reg_write(dev, AT86RF2XX_REG__PAN_ID_0, (uint8_t)pan); - at86rf2xx_reg_write(dev, AT86RF2XX_REG__PAN_ID_1, (pan >> 8)); + le_uint16_t le_pan = byteorder_btols(byteorder_htons(pan)); + dev->netdev.pan = pan; + DEBUG("pan0: %u, pan1: %u\n", le_pan.u8[0], le_pan.u8[1]); + at86rf2xx_reg_write(dev, AT86RF2XX_REG__PAN_ID_0, le_pan.u8[0]); + at86rf2xx_reg_write(dev, AT86RF2XX_REG__PAN_ID_1, le_pan.u8[1]); } int16_t at86rf2xx_get_txpower(at86rf2xx_t *dev) @@ -188,7 +189,7 @@ int16_t at86rf2xx_get_txpower(at86rf2xx_t *dev) #ifdef MODULE_AT86RF212B uint8_t txpower = at86rf2xx_reg_read(dev, AT86RF2XX_REG__PHY_TX_PWR); DEBUG("txpower value: %x\n", txpower); - return _tx_pow_to_dbm_212b(dev->chan, dev->page, txpower); + return _tx_pow_to_dbm_212b(dev->netdev.chan, dev->page, txpower); #else uint8_t txpower = at86rf2xx_reg_read(dev, AT86RF2XX_REG__PHY_TX_PWR) & AT86RF2XX_PHY_TX_PWR_MASK__TX_PWR; @@ -220,11 +221,11 @@ void at86rf2xx_set_txpower(at86rf2xx_t *dev, int16_t txpower) #endif } #ifdef MODULE_AT86RF212B - if (dev->chan == 0) { + if (dev->netdev.chan == 0) { at86rf2xx_reg_write(dev, AT86RF2XX_REG__PHY_TX_PWR, dbm_to_tx_pow_868[txpower]); } - else if (dev->chan < 11) { + else if (dev->netdev.chan < 11) { at86rf2xx_reg_write(dev, AT86RF2XX_REG__PHY_TX_PWR, dbm_to_tx_pow_915[txpower]); } @@ -331,14 +332,14 @@ void at86rf2xx_set_option(at86rf2xx_t *dev, uint16_t option, bool state) /* set option field */ if (state) { - dev->options |= option; + dev->netdev.flags |= option; /* trigger option specific actions */ switch (option) { case AT86RF2XX_OPT_CSMA: DEBUG("[at86rf2xx] opt: enabling CSMA mode" \ "(4 retries, min BE: 3 max BE: 5)\n"); /* Initialize CSMA seed with hardware address */ - at86rf2xx_set_csma_seed(dev, dev->addr_long); + at86rf2xx_set_csma_seed(dev, dev->netdev.long_addr); at86rf2xx_set_csma_max_retries(dev, 4); at86rf2xx_set_csma_backoff_exp(dev, 3, 5); break; @@ -371,7 +372,7 @@ void at86rf2xx_set_option(at86rf2xx_t *dev, uint16_t option, bool state) } } else { - dev->options &= ~(option); + dev->netdev.flags &= ~(option); /* trigger option specific actions */ switch (option) { case AT86RF2XX_OPT_CSMA: @@ -386,7 +387,7 @@ void at86rf2xx_set_option(at86rf2xx_t *dev, uint16_t option, bool state) tmp &= ~(AT86RF2XX_XAH_CTRL_1__AACK_PROM_MODE); at86rf2xx_reg_write(dev, AT86RF2XX_REG__XAH_CTRL_1, tmp); /* re-enable AUTOACK only if the option is set */ - if (dev->options & AT86RF2XX_OPT_AUTOACK) { + if (dev->netdev.flags & AT86RF2XX_OPT_AUTOACK) { tmp = at86rf2xx_reg_read(dev, AT86RF2XX_REG__CSMA_SEED_1); tmp &= ~(AT86RF2XX_CSMA_SEED_1__AACK_DIS_ACK); diff --git a/drivers/at86rf2xx/at86rf2xx_internal.c b/drivers/at86rf2xx/at86rf2xx_internal.c index 3a640ea04b74bf39ecb043e4c1c196aab18ea693..11c78bd51135ea6e631704706e49a06f98564b30 100644 --- a/drivers/at86rf2xx/at86rf2xx_internal.c +++ b/drivers/at86rf2xx/at86rf2xx_internal.c @@ -173,7 +173,7 @@ void at86rf2xx_configure_phy(at86rf2xx_t *dev) /* Clear previous configuration for GC_TX_OFFS */ rf_ctrl0 &= ~AT86RF2XX_RF_CTRL_0_MASK__GC_TX_OFFS; - if (dev->chan != 0) { + if (dev->netdev.chan != 0) { /* Set sub mode bit on 915 MHz as recommended by the data sheet */ trx_ctrl2 |= AT86RF2XX_TRX_CTRL_2_MASK__SUB_MODE; } @@ -199,7 +199,7 @@ void at86rf2xx_configure_phy(at86rf2xx_t *dev) phy_cc_cca &= ~(AT86RF2XX_PHY_CC_CCA_MASK__CHANNEL); /* Update the channel register */ - phy_cc_cca |= (dev->chan & AT86RF2XX_PHY_CC_CCA_MASK__CHANNEL); + phy_cc_cca |= (dev->netdev.chan & AT86RF2XX_PHY_CC_CCA_MASK__CHANNEL); at86rf2xx_reg_write(dev, AT86RF2XX_REG__PHY_CC_CCA, phy_cc_cca); #ifdef MODULE_AT86RF212B diff --git a/drivers/at86rf2xx/at86rf2xx_netdev.c b/drivers/at86rf2xx/at86rf2xx_netdev.c index 6909a2f3da1c00aa317db6412d2834bce8ea3a2d..488ed33d25d8c43da8ecc1aadf64ea00dc32636b 100644 --- a/drivers/at86rf2xx/at86rf2xx_netdev.c +++ b/drivers/at86rf2xx/at86rf2xx_netdev.c @@ -16,13 +16,19 @@ * @author Thomas Eichinger <thomas.eichinger@fu-berlin.de> * @author Hauke Petersen <hauke.petersen@fu-berlin.de> * @author Kévin Roussel <Kevin.Roussel@inria.fr> + * @author Martine Lenders <mlenders@inf.fu-berlin.de> * * @} */ +#include <assert.h> +#include <errno.h> + #include "net/eui64.h" #include "net/ieee802154.h" -#include "net/gnrc.h" +#include "net/netdev2.h" +#include "net/netdev2/ieee802154.h" + #include "at86rf2xx.h" #include "at86rf2xx_netdev.h" #include "at86rf2xx_internal.h" @@ -33,243 +39,92 @@ #define _MAX_MHR_OVERHEAD (25) -/* TODO: generalize and move to (gnrc_)ieee802154 */ -static size_t _make_data_frame_hdr(at86rf2xx_t *dev, uint8_t *buf, - gnrc_netif_hdr_t *hdr) -{ - int pos = 0; +static int _send(netdev2_t *netdev, const struct iovec *vector, int count); +static int _recv(netdev2_t *netdev, char *buf, int len, void *info); +static int _init(netdev2_t *netdev); +static void _isr(netdev2_t *netdev); +static int _get(netdev2_t *netdev, netopt_t opt, void *val, size_t max_len); +static int _set(netdev2_t *netdev, netopt_t opt, void *val, size_t len); + +const netdev2_driver_t at86rf2xx_driver = { + .send = _send, + .recv = _recv, + .init = _init, + .isr = _isr, + .get = _get, + .set = _set, +}; - /* we are building a data frame here */ - buf[0] = IEEE802154_FCF_TYPE_DATA; - buf[1] = IEEE802154_FCF_VERS_V1; +static void _irq_handler(void *arg) +{ + netdev2_t *dev = (netdev2_t *) arg; - /* if AUTOACK is enabled, then we also expect ACKs for this packet */ - if (!(hdr->flags & GNRC_NETIF_HDR_FLAGS_BROADCAST) && - !(hdr->flags & GNRC_NETIF_HDR_FLAGS_MULTICAST) && - (dev->options & AT86RF2XX_OPT_AUTOACK)) { - buf[0] |= IEEE802154_FCF_ACK_REQ; + if (dev->event_callback) { + dev->event_callback(dev, NETDEV2_EVENT_ISR, NULL); } +} - /* fill in destination PAN ID */ - pos = 3; - buf[pos++] = (uint8_t)((dev->pan) & 0xff); - buf[pos++] = (uint8_t)((dev->pan) >> 8); - - /* fill in destination address */ - if (hdr->flags & - (GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) { - buf[1] |= IEEE802154_FCF_DST_ADDR_SHORT; - buf[pos++] = 0xff; - buf[pos++] = 0xff; - } - else if (hdr->dst_l2addr_len == 2) { - uint8_t *dst_addr = gnrc_netif_hdr_get_dst_addr(hdr); - buf[1] |= IEEE802154_FCF_DST_ADDR_SHORT; - buf[pos++] = dst_addr[1]; - buf[pos++] = dst_addr[0]; - } - else if (hdr->dst_l2addr_len == 8) { - buf[1] |= IEEE802154_FCF_DST_ADDR_LONG; - uint8_t *dst_addr = gnrc_netif_hdr_get_dst_addr(hdr); - for (int i = 7; i >= 0; i--) { - buf[pos++] = dst_addr[i]; - } - } - else { - /* unsupported address length */ - return 0; - } +static int _init(netdev2_t *netdev) +{ + at86rf2xx_t *dev = (at86rf2xx_t *)netdev; - /* fill in source PAN ID (if applicable */ - if (dev->options & AT86RF2XX_OPT_USE_SRC_PAN) { - buf[pos++] = (uint8_t)((dev->pan) & 0xff); - buf[pos++] = (uint8_t)((dev->pan) >> 8); - } else { - buf[0] |= IEEE802154_FCF_PAN_COMP; - } + /* initialise GPIOs */ + gpio_init(dev->cs_pin, GPIO_OUT); + gpio_set(dev->cs_pin); + gpio_init(dev->sleep_pin, GPIO_OUT); + gpio_clear(dev->sleep_pin); + gpio_init(dev->reset_pin, GPIO_OUT); + gpio_set(dev->reset_pin); + gpio_init_int(dev->int_pin, GPIO_IN, GPIO_RISING, _irq_handler, dev); - /* fill in source address */ - if (dev->options & AT86RF2XX_OPT_SRC_ADDR_LONG) { - buf[1] |= IEEE802154_FCF_SRC_ADDR_LONG; - memcpy(&(buf[pos]), dev->addr_long, 8); - pos += 8; - } - else { - buf[1] |= IEEE802154_FCF_SRC_ADDR_SHORT; - buf[pos++] = dev->addr_short[0]; - buf[pos++] = dev->addr_short[1]; - } + /* make sure device is not sleeping, so we can query part number */ + at86rf2xx_assert_awake(dev); - /* set sequence number */ - buf[2] = dev->seq_nr++; - /* return actual header length */ - return pos; -} + /* test if the SPI is set up correctly and the device is responding */ + if (at86rf2xx_reg_read(dev, AT86RF2XX_REG__PART_NUM) != + AT86RF2XX_PARTNUM) { + DEBUG("[at86rf2xx] error: unable to read correct part number\n"); + return -1; + } -/* TODO: generalize and move to ieee802154 */ -/* TODO: include security header implications */ -static size_t _get_frame_hdr_len(uint8_t *mhr) -{ - uint8_t tmp; - size_t len = 3; + /* reset device to default values and put it into RX state */ + at86rf2xx_reset(dev); - /* figure out address sizes */ - tmp = (mhr[1] & IEEE802154_FCF_DST_ADDR_MASK); - if (tmp == IEEE802154_FCF_DST_ADDR_SHORT) { - len += 4; - } - else if (tmp == IEEE802154_FCF_DST_ADDR_LONG) { - len += 10; - } - else if (tmp != IEEE802154_FCF_DST_ADDR_VOID) { - return 0; - } - tmp = (mhr[1] & IEEE802154_FCF_SRC_ADDR_MASK); - if (tmp == IEEE802154_FCF_SRC_ADDR_VOID) { - return len; - } - else { - if (!(mhr[0] & IEEE802154_FCF_PAN_COMP)) { - len += 2; - } - if (tmp == IEEE802154_FCF_SRC_ADDR_SHORT) { - return (len + 2); - } - else if (tmp == IEEE802154_FCF_SRC_ADDR_LONG) { - return (len + 8); - } - } return 0; } -/* TODO: generalize and move to (gnrc_)ieee802154 */ -static gnrc_pktsnip_t *_make_netif_hdr(uint8_t *mhr) -{ - uint8_t tmp; - uint8_t *addr; - uint8_t src_len, dst_len; - gnrc_pktsnip_t *snip; - gnrc_netif_hdr_t *hdr; - - /* figure out address sizes */ - tmp = mhr[1] & IEEE802154_FCF_SRC_ADDR_MASK; - if (tmp == IEEE802154_FCF_SRC_ADDR_SHORT) { - src_len = 2; - } - else if (tmp == IEEE802154_FCF_SRC_ADDR_LONG) { - src_len = 8; - } - else if (tmp == IEEE802154_FCF_SRC_ADDR_VOID) { - src_len = 0; - } - else { - return NULL; - } - tmp = mhr[1] & IEEE802154_FCF_DST_ADDR_MASK; - if (tmp == IEEE802154_FCF_DST_ADDR_SHORT) { - dst_len = 2; - } - else if (tmp == IEEE802154_FCF_DST_ADDR_LONG) { - dst_len = 8; - } - else if (tmp == IEEE802154_FCF_DST_ADDR_VOID) { - dst_len = 0; - } - else { - return NULL; - } - /* allocate space for header */ - snip = gnrc_pktbuf_add(NULL, NULL, sizeof(gnrc_netif_hdr_t) + src_len + dst_len, - GNRC_NETTYPE_NETIF); - if (snip == NULL) { - return NULL; - } - /* fill header */ - hdr = (gnrc_netif_hdr_t *)snip->data; - gnrc_netif_hdr_init(hdr, src_len, dst_len); - if (dst_len > 0) { - hdr->flags |= GNRC_NETIF_HDR_FLAGS_BROADCAST; - tmp = 5 + dst_len; - addr = gnrc_netif_hdr_get_dst_addr(hdr); - for (int i = 0; i < dst_len; i++) { - addr[i] = mhr[5 + (dst_len - i) - 1]; - if(addr[i] != 0xff) { - hdr->flags &= ~(GNRC_NETIF_HDR_FLAGS_BROADCAST); - } - } - } - else { - tmp = 3; - } - if (!(mhr[0] & IEEE802154_FCF_PAN_COMP)) { - tmp += 2; - } - if (src_len > 0) { - addr = gnrc_netif_hdr_get_src_addr(hdr); - for (int i = 0; i < src_len; i++) { - addr[i] = mhr[tmp + (src_len - i) - 1]; - } - } - return snip; -} - - -static int _send(gnrc_netdev_t *netdev, gnrc_pktsnip_t *pkt) +static int _send(netdev2_t *netdev, const struct iovec *vector, int count) { at86rf2xx_t *dev = (at86rf2xx_t *)netdev; - gnrc_pktsnip_t *snip; - uint8_t mhr[IEEE802154_MAX_HDR_LEN]; - size_t len; - - if (pkt == NULL) { - return -ENOMSG; - } - if (dev == NULL) { - gnrc_pktbuf_release(pkt); - return -ENODEV; - } - - /* create 802.15.4 header */ - len = _make_data_frame_hdr(dev, mhr, (gnrc_netif_hdr_t *)pkt->data); - if (len == 0) { - DEBUG("[at86rf2xx] error: unable to create 802.15.4 header\n"); - gnrc_pktbuf_release(pkt); - return -ENOMSG; - } - /* check if packet (header + payload + FCS) fits into FIFO */ - snip = pkt->next; - if ((gnrc_pkt_len(snip) + len + 2) > AT86RF2XX_MAX_PKT_LENGTH) { - printf("[at86rf2xx] error: packet too large (%u byte) to be send\n", - gnrc_pkt_len(snip) + len + 2); - gnrc_pktbuf_release(pkt); - return -EOVERFLOW; - } + const struct iovec *ptr = vector; + size_t len = 0; at86rf2xx_tx_prepare(dev); - /* put header into FIFO */ - len = at86rf2xx_tx_load(dev, mhr, len, 0); + /* load packet data into FIFO */ - while (snip) { - len = at86rf2xx_tx_load(dev, snip->data, snip->size, len); - snip = snip->next; + for (int i = 0; i < count; i++, ptr++) { + /* current packet data + FCS too long */ + if ((len + ptr->iov_len + 2) > AT86RF2XX_MAX_PKT_LENGTH) { + printf("[at86rf2xx] error: packet too large (%u byte) to be send\n", + (unsigned)len + 2); + return -EOVERFLOW; + } + len = at86rf2xx_tx_load(dev, ptr->iov_base, ptr->iov_len, len); } + /* send data out directly if pre-loading id disabled */ - if (!(dev->options & AT86RF2XX_OPT_PRELOADING)) { + if (!(dev->netdev.flags & AT86RF2XX_OPT_PRELOADING)) { at86rf2xx_tx_exec(dev); } - /* release packet */ - gnrc_pktbuf_release(pkt); /* return the number of bytes that were actually send out */ return (int)len; } -static void _receive_data(at86rf2xx_t *dev) +static int _recv(netdev2_t *netdev, char *buf, int len, void *info) { - uint8_t mhr[IEEE802154_MAX_HDR_LEN]; + at86rf2xx_t *dev = (at86rf2xx_t *)netdev; uint8_t phr; - size_t pkt_len, hdr_len; - gnrc_pktsnip_t *hdr, *payload = NULL; - gnrc_netif_hdr_t *netif; + size_t pkt_len; /* frame buffer protection will be unlocked as soon as at86rf2xx_fb_stop() * is called*/ @@ -281,75 +136,38 @@ static void _receive_data(at86rf2xx_t *dev) /* Ignore FCS for packet length */ pkt_len = phr - 2; - /* abort here already if no event callback is registered */ - if (!dev->event_cb) { - at86rf2xx_fb_stop(dev); - return; - } - - /* in raw mode, just read the binary dump into the packet buffer */ - if (dev->options & AT86RF2XX_OPT_RAWDUMP) { - payload = gnrc_pktbuf_add(NULL, NULL, pkt_len, GNRC_NETTYPE_UNDEF); - if (payload == NULL ) { - at86rf2xx_fb_stop(dev); - DEBUG("[at86rf2xx] error: unable to allocate RAW data\n"); - return; - } - at86rf2xx_fb_read(dev, payload->data, pkt_len); - at86rf2xx_fb_stop(dev); - dev->event_cb(NETDEV_EVENT_RX_COMPLETE, payload); - return; - } - - /* get FCF field and compute 802.15.4 header length */ - at86rf2xx_fb_read(dev, mhr, 2); - - hdr_len = _get_frame_hdr_len(mhr); - if (hdr_len == 0) { + /* just return length when buf == NULL */ + if (buf == NULL) { at86rf2xx_fb_stop(dev); - DEBUG("[at86rf2xx] error: unable parse incoming frame header\n"); - return; + return pkt_len; } - - /* read the rest of the header and parse the netif header from it */ - at86rf2xx_fb_read(dev, &(mhr[2]), hdr_len - 2); - hdr = _make_netif_hdr(mhr); - if (hdr == NULL) { + /* not enough space in buf */ + if (pkt_len > len) { at86rf2xx_fb_stop(dev); - DEBUG("[at86rf2xx] error: unable to allocate netif header\n"); - return; - } - - /* fill missing fields in netif header */ - netif = (gnrc_netif_hdr_t *)hdr->data; - netif->if_pid = dev->mac_pid; - - /* allocate payload */ - payload = gnrc_pktbuf_add(hdr, NULL, (pkt_len - hdr_len), dev->proto); - if (payload == NULL) { - at86rf2xx_fb_stop(dev); - DEBUG("[at86rf2xx] error: unable to allocate incoming payload\n"); - gnrc_pktbuf_release(hdr); - return; + return -ENOBUFS; } /* copy payload */ - at86rf2xx_fb_read(dev, payload->data, payload->size); + at86rf2xx_fb_read(dev, (uint8_t *)buf, pkt_len); /* Ignore FCS but advance fb read */ at86rf2xx_fb_read(dev, NULL, 2); - at86rf2xx_fb_read(dev, &(netif->lqi), 1); - + if (info != NULL) { + netdev2_ieee802154_rx_info_t *radio_info = info; + at86rf2xx_fb_read(dev, &(radio_info->lqi), 1); #ifndef MODULE_AT86RF231 - at86rf2xx_fb_read(dev, &(netif->rssi), 1); - at86rf2xx_fb_stop(dev); + at86rf2xx_fb_read(dev, &(radio_info->rssi), 1); + at86rf2xx_fb_stop(dev); #else - at86rf2xx_fb_stop(dev); - netif->rssi = at86rf2xx_reg_read(dev, AT86RF2XX_REG__PHY_ED_LEVEL); + at86rf2xx_fb_stop(dev); + radio_info->rssi = at86rf2xx_reg_read(dev, AT86RF2XX_REG__PHY_ED_LEVEL); #endif + } + else { + at86rf2xx_fb_stop(dev); + } - /* finish up and send data to upper layers */ - dev->event_cb(NETDEV_EVENT_RX_COMPLETE, payload); + return pkt_len; } static int _set_state(at86rf2xx_t *dev, netopt_state_t state) @@ -362,7 +180,7 @@ static int _set_state(at86rf2xx_t *dev, netopt_state_t state) at86rf2xx_set_state(dev, AT86RF2XX_STATE_RX_AACK_ON); break; case NETOPT_STATE_TX: - if (dev->options & AT86RF2XX_OPT_PRELOADING) { + if (dev->netdev.flags & AT86RF2XX_OPT_PRELOADING) { at86rf2xx_tx_exec(dev); } break; @@ -391,86 +209,16 @@ netopt_state_t _get_state(at86rf2xx_t *dev) } } -static int _get(gnrc_netdev_t *device, netopt_t opt, void *val, size_t max_len) +static int _get(netdev2_t *netdev, netopt_t opt, void *val, size_t max_len) { - at86rf2xx_t *dev = (at86rf2xx_t *) device; + at86rf2xx_t *dev = (at86rf2xx_t *) netdev; - if (device == NULL) { + if (netdev == NULL) { return -ENODEV; } /* getting these options doesn't require the transceiver to be responsive */ switch (opt) { - - case NETOPT_ADDRESS: - if (max_len < sizeof(uint16_t)) { - return -EOVERFLOW; - } - *((uint16_t *)val) = at86rf2xx_get_addr_short(dev); - return sizeof(uint16_t); - - case NETOPT_ADDRESS_LONG: - if (max_len < sizeof(uint64_t)) { - return -EOVERFLOW; - } - *((uint64_t *)val) = at86rf2xx_get_addr_long(dev); - return sizeof(uint64_t); - - case NETOPT_ADDR_LEN: - if (max_len < sizeof(uint16_t)) { - return -EOVERFLOW; - } - *((uint16_t *)val) = 2; - return sizeof(uint16_t); - - case NETOPT_SRC_LEN: - if (max_len < sizeof(uint16_t)) { - return -EOVERFLOW; - } - if (dev->options & AT86RF2XX_OPT_SRC_ADDR_LONG) { - *((uint16_t *)val) = 8; - } - else { - *((uint16_t *)val) = 2; - } - return sizeof(uint16_t); - - case NETOPT_NID: - if (max_len < sizeof(uint16_t)) { - return -EOVERFLOW; - } - *((uint16_t *)val) = dev->pan; - return sizeof(uint16_t); - - case NETOPT_IPV6_IID: - if (max_len < sizeof(eui64_t)) { - return -EOVERFLOW; - } - if (dev->options & AT86RF2XX_OPT_SRC_ADDR_LONG) { - uint64_t addr = at86rf2xx_get_addr_long(dev); - ieee802154_get_iid(val, (uint8_t *)&addr, 8); - } - else { - uint16_t addr = at86rf2xx_get_addr_short(dev); - ieee802154_get_iid(val, (uint8_t *)&addr, 2); - } - return sizeof(eui64_t); - - case NETOPT_PROTO: - if (max_len < sizeof(gnrc_nettype_t)) { - return -EOVERFLOW; - } - *((gnrc_nettype_t *)val) = dev->proto; - return sizeof(gnrc_nettype_t); - - case NETOPT_CHANNEL: - if (max_len < sizeof(uint16_t)) { - return -EOVERFLOW; - } - ((uint8_t *)val)[1] = 0; - ((uint8_t *)val)[0] = at86rf2xx_get_chan(dev); - return sizeof(uint16_t); - case NETOPT_CHANNEL_PAGE: if (max_len < sizeof(uint16_t)) { return -EOVERFLOW; @@ -490,20 +238,11 @@ static int _get(gnrc_netdev_t *device, netopt_t opt, void *val, size_t max_len) if (max_len < sizeof(netopt_state_t)) { return -EOVERFLOW; } - *((netopt_state_t*)val) = _get_state(dev); + *((netopt_state_t *)val) = _get_state(dev); return sizeof(netopt_state_t); case NETOPT_PRELOADING: - if (dev->options & AT86RF2XX_OPT_PRELOADING) { - *((netopt_enable_t *)val) = NETOPT_ENABLE; - } - else { - *((netopt_enable_t *)val) = NETOPT_DISABLE; - } - return sizeof(netopt_enable_t); - - case NETOPT_AUTOACK: - if (dev->options & AT86RF2XX_OPT_AUTOACK) { + if (dev->netdev.flags & AT86RF2XX_OPT_PRELOADING) { *((netopt_enable_t *)val) = NETOPT_ENABLE; } else { @@ -512,16 +251,7 @@ static int _get(gnrc_netdev_t *device, netopt_t opt, void *val, size_t max_len) return sizeof(netopt_enable_t); case NETOPT_PROMISCUOUSMODE: - if (dev->options & AT86RF2XX_OPT_PROMISCUOUS) { - *((netopt_enable_t *)val) = NETOPT_ENABLE; - } - else { - *((netopt_enable_t *)val) = NETOPT_DISABLE; - } - return sizeof(netopt_enable_t); - - case NETOPT_RAWMODE: - if (dev->options & AT86RF2XX_OPT_RAWDUMP) { + if (dev->netdev.flags & AT86RF2XX_OPT_PROMISCUOUS) { *((netopt_enable_t *)val) = NETOPT_ENABLE; } else { @@ -531,27 +261,27 @@ static int _get(gnrc_netdev_t *device, netopt_t opt, void *val, size_t max_len) case NETOPT_RX_START_IRQ: *((netopt_enable_t *)val) = - !!(dev->options & AT86RF2XX_OPT_TELL_RX_START); + !!(dev->netdev.flags & AT86RF2XX_OPT_TELL_RX_START); return sizeof(netopt_enable_t); case NETOPT_RX_END_IRQ: *((netopt_enable_t *)val) = - !!(dev->options & AT86RF2XX_OPT_TELL_RX_END); + !!(dev->netdev.flags & AT86RF2XX_OPT_TELL_RX_END); return sizeof(netopt_enable_t); case NETOPT_TX_START_IRQ: *((netopt_enable_t *)val) = - !!(dev->options & AT86RF2XX_OPT_TELL_TX_START); + !!(dev->netdev.flags & AT86RF2XX_OPT_TELL_TX_START); return sizeof(netopt_enable_t); case NETOPT_TX_END_IRQ: *((netopt_enable_t *)val) = - !!(dev->options & AT86RF2XX_OPT_TELL_TX_END); + !!(dev->netdev.flags & AT86RF2XX_OPT_TELL_TX_END); return sizeof(netopt_enable_t); case NETOPT_CSMA: *((netopt_enable_t *)val) = - !!(dev->options & AT86RF2XX_OPT_CSMA); + !!(dev->netdev.flags & AT86RF2XX_OPT_CSMA); return sizeof(netopt_enable_t); default: @@ -559,12 +289,18 @@ static int _get(gnrc_netdev_t *device, netopt_t opt, void *val, size_t max_len) break; } + int res; + + if (((res = netdev2_ieee802154_get((netdev2_ieee802154_t *)netdev, opt, val, + max_len)) >= 0) || (res != -ENOTSUP)) { + return res; + } uint8_t old_state = at86rf2xx_get_status(dev); - int res = 0; + res = 0; /* temporarily wake up if sleeping */ - if(old_state == AT86RF2XX_STATE_SLEEP) { + if (old_state == AT86RF2XX_STATE_SLEEP) { at86rf2xx_assert_awake(dev); } @@ -573,7 +309,8 @@ static int _get(gnrc_netdev_t *device, netopt_t opt, void *val, size_t max_len) case NETOPT_TX_POWER: if (max_len < sizeof(int16_t)) { res = -EOVERFLOW; - } else { + } + else { *((uint16_t *)val) = at86rf2xx_get_txpower(dev); res = sizeof(uint16_t); } @@ -582,7 +319,8 @@ static int _get(gnrc_netdev_t *device, netopt_t opt, void *val, size_t max_len) case NETOPT_RETRANS: if (max_len < sizeof(uint8_t)) { res = -EOVERFLOW; - } else { + } + else { *((uint8_t *)val) = at86rf2xx_get_max_retries(dev); res = sizeof(uint8_t); } @@ -601,7 +339,8 @@ static int _get(gnrc_netdev_t *device, netopt_t opt, void *val, size_t max_len) case NETOPT_CSMA_RETRIES: if (max_len < sizeof(uint8_t)) { res = -EOVERFLOW; - } else { + } + else { *((uint8_t *)val) = at86rf2xx_get_csma_max_retries(dev); res = sizeof(uint8_t); } @@ -610,7 +349,8 @@ static int _get(gnrc_netdev_t *device, netopt_t opt, void *val, size_t max_len) case NETOPT_CCA_THRESHOLD: if (max_len < sizeof(int8_t)) { res = -EOVERFLOW; - } else { + } + else { *((int8_t *)val) = at86rf2xx_get_cca_threshold(dev); res = sizeof(int8_t); } @@ -621,16 +361,16 @@ static int _get(gnrc_netdev_t *device, netopt_t opt, void *val, size_t max_len) } /* go back to sleep if were sleeping */ - if(old_state == AT86RF2XX_STATE_SLEEP) { + if (old_state == AT86RF2XX_STATE_SLEEP) { at86rf2xx_set_state(dev, AT86RF2XX_STATE_SLEEP); } return res; } -static int _set(gnrc_netdev_t *device, netopt_t opt, void *val, size_t len) +static int _set(netdev2_t *netdev, netopt_t opt, void *val, size_t len) { - at86rf2xx_t *dev = (at86rf2xx_t *) device; + at86rf2xx_t *dev = (at86rf2xx_t *) netdev; uint8_t old_state = at86rf2xx_get_status(dev); int res = 0; @@ -639,7 +379,7 @@ static int _set(gnrc_netdev_t *device, netopt_t opt, void *val, size_t len) } /* temporarily wake up if sleeping */ - if(old_state == AT86RF2XX_STATE_SLEEP) { + if (old_state == AT86RF2XX_STATE_SLEEP) { at86rf2xx_assert_awake(dev); } @@ -647,64 +387,38 @@ static int _set(gnrc_netdev_t *device, netopt_t opt, void *val, size_t len) case NETOPT_ADDRESS: if (len > sizeof(uint16_t)) { res = -EOVERFLOW; - } else { - at86rf2xx_set_addr_short(dev, *((uint16_t*)val)); - res = sizeof(uint16_t); + } + else { + at86rf2xx_set_addr_short(dev, *((uint16_t *)val)); + /* don't set res to set netdev2_ieee802154_t::short_addr */ } break; case NETOPT_ADDRESS_LONG: if (len > sizeof(uint64_t)) { res = -EOVERFLOW; - } else { - at86rf2xx_set_addr_long(dev, *((uint64_t*)val)); - res = sizeof(uint64_t); } - break; - - case NETOPT_SRC_LEN: - if (len > sizeof(uint16_t)) { - res = -EOVERFLOW; - } else { - if (*((uint16_t *)val) == 2) { - at86rf2xx_set_option(dev, AT86RF2XX_OPT_SRC_ADDR_LONG, - false); - } - else if (*((uint16_t *)val) == 8) { - at86rf2xx_set_option(dev, AT86RF2XX_OPT_SRC_ADDR_LONG, - true); - } - else { - res = -ENOTSUP; - break; - } - res = sizeof(uint16_t); + else { + at86rf2xx_set_addr_long(dev, *((uint64_t *)val)); + /* don't set res to set netdev2_ieee802154_t::long_addr */ } break; case NETOPT_NID: if (len > sizeof(uint16_t)) { res = -EOVERFLOW; - } else { - at86rf2xx_set_pan(dev, *((uint16_t *)val)); - res = sizeof(uint16_t); - } - break; - - case NETOPT_PROTO: - if (len != sizeof(gnrc_nettype_t)) { - res = -EINVAL; } else { - dev->proto = *((gnrc_nettype_t*) val); - res = sizeof(gnrc_nettype_t); + at86rf2xx_set_pan(dev, *((uint16_t *)val)); + /* don't set res to set netdev2_ieee802154_t::pan */ } break; case NETOPT_CHANNEL: if (len != sizeof(uint16_t)) { res = -EINVAL; - } else { + } + else { uint8_t chan = ((uint8_t *)val)[0]; if (chan < AT86RF2XX_MIN_CHANNEL || chan > AT86RF2XX_MAX_CHANNEL) { @@ -712,19 +426,21 @@ static int _set(gnrc_netdev_t *device, netopt_t opt, void *val, size_t len) break; } at86rf2xx_set_chan(dev, chan); - res = sizeof(uint16_t); + /* don't set res to set netdev2_ieee802154_t::chan */ } break; case NETOPT_CHANNEL_PAGE: if (len != sizeof(uint16_t)) { res = -EINVAL; - } else { + } + else { uint8_t page = ((uint8_t *)val)[0]; #ifdef MODULE_AT86RF212B if ((page != 0) && (page != 2)) { res = -ENOTSUP; - } else { + } + else { at86rf2xx_set_page(dev, page); res = sizeof(uint16_t); } @@ -732,7 +448,8 @@ static int _set(gnrc_netdev_t *device, netopt_t opt, void *val, size_t len) /* rf23x only supports page 0, no need to configure anything in the driver. */ if (page != 0) { res = -ENOTSUP; - } else { + } + else { res = sizeof(uint16_t); } #endif @@ -742,7 +459,8 @@ static int _set(gnrc_netdev_t *device, netopt_t opt, void *val, size_t len) case NETOPT_TX_POWER: if (len > sizeof(int16_t)) { res = -EOVERFLOW; - } else { + } + else { at86rf2xx_set_txpower(dev, *((int16_t *)val)); res = sizeof(uint16_t); } @@ -751,7 +469,8 @@ static int _set(gnrc_netdev_t *device, netopt_t opt, void *val, size_t len) case NETOPT_STATE: if (len > sizeof(netopt_state_t)) { res = -EOVERFLOW; - } else { + } + else { res = _set_state(dev, *((netopt_state_t *)val)); } break; @@ -759,13 +478,14 @@ static int _set(gnrc_netdev_t *device, netopt_t opt, void *val, size_t len) case NETOPT_AUTOACK: at86rf2xx_set_option(dev, AT86RF2XX_OPT_AUTOACK, ((bool *)val)[0]); - res = sizeof(netopt_enable_t); + /* don't set res to set netdev2_ieee802154_t::flags */ break; case NETOPT_RETRANS: if (len > sizeof(uint8_t)) { res = -EOVERFLOW; - } else { + } + else { at86rf2xx_set_max_retries(dev, *((uint8_t *)val)); res = sizeof(uint8_t); } @@ -783,12 +503,6 @@ static int _set(gnrc_netdev_t *device, netopt_t opt, void *val, size_t len) res = sizeof(netopt_enable_t); break; - case NETOPT_RAWMODE: - at86rf2xx_set_option(dev, AT86RF2XX_OPT_RAWDUMP, - ((bool *)val)[0]); - res = sizeof(netopt_enable_t); - break; - case NETOPT_RX_START_IRQ: at86rf2xx_set_option(dev, AT86RF2XX_OPT_TELL_RX_START, ((bool *)val)[0]); @@ -815,18 +529,20 @@ static int _set(gnrc_netdev_t *device, netopt_t opt, void *val, size_t len) case NETOPT_CSMA: at86rf2xx_set_option(dev, AT86RF2XX_OPT_CSMA, - ((bool *)val)[0]); + ((bool *)val)[0]); res = sizeof(netopt_enable_t); break; case NETOPT_CSMA_RETRIES: - if( (len > sizeof(uint8_t)) || - (*((uint8_t *)val) > 5) ) { + if ((len > sizeof(uint8_t)) || + (*((uint8_t *)val) > 5)) { res = -EOVERFLOW; - } else if( !(dev->options & AT86RF2XX_OPT_CSMA) ) { + } + else if (!(dev->netdev.flags & AT86RF2XX_OPT_CSMA)) { /* If CSMA is disabled, don't allow setting retries */ res = -ENOTSUP; - } else { + } + else { at86rf2xx_set_csma_max_retries(dev, *((uint8_t *)val)); res = sizeof(uint8_t); } @@ -835,7 +551,8 @@ static int _set(gnrc_netdev_t *device, netopt_t opt, void *val, size_t len) case NETOPT_CCA_THRESHOLD: if (len > sizeof(int8_t)) { res = -EOVERFLOW; - } else { + } + else { at86rf2xx_set_cca_threshold(dev, *((int8_t *)val)); res = sizeof(int8_t); } @@ -846,44 +563,22 @@ static int _set(gnrc_netdev_t *device, netopt_t opt, void *val, size_t len) } /* go back to sleep if were sleeping and state hasn't been changed */ - if( (old_state == AT86RF2XX_STATE_SLEEP) && - (opt != NETOPT_STATE) ) { + if ((old_state == AT86RF2XX_STATE_SLEEP) && + (opt != NETOPT_STATE)) { at86rf2xx_set_state(dev, AT86RF2XX_STATE_SLEEP); } - return res; -} - -static int _add_event_cb(gnrc_netdev_t *dev, gnrc_netdev_event_cb_t cb) -{ - if (dev == NULL) { - return -ENODEV; - } - if (dev->event_cb) { - return -ENOBUFS; - } - - dev->event_cb = cb; - return 0; -} - -static int _rem_event_cb(gnrc_netdev_t *dev, gnrc_netdev_event_cb_t cb) -{ - if (dev == NULL) { - return -ENODEV; - } - if (dev->event_cb != cb) { - return -ENOENT; + if (res == -ENOTSUP) { + res = netdev2_ieee802154_set((netdev2_ieee802154_t *)netdev, opt, + val, len); } - dev->event_cb = NULL; - return 0; + return res; } -static void _isr_event(gnrc_netdev_t *device, uint32_t event_type) +static void _isr(netdev2_t *netdev) { - (void) event_type; - at86rf2xx_t *dev = (at86rf2xx_t *) device; + at86rf2xx_t *dev = (at86rf2xx_t *) netdev; uint8_t irq_mask; uint8_t state; uint8_t trac_status; @@ -892,28 +587,29 @@ static void _isr_event(gnrc_netdev_t *device, uint32_t event_type) * lost anyway, so return immediately. */ state = at86rf2xx_get_status(dev); - if(state == AT86RF2XX_STATE_SLEEP) + if (state == AT86RF2XX_STATE_SLEEP) { return; + } /* read (consume) device status */ irq_mask = at86rf2xx_reg_read(dev, AT86RF2XX_REG__IRQ_STATUS); trac_status = at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_STATE) & - AT86RF2XX_TRX_STATE_MASK__TRAC; + AT86RF2XX_TRX_STATE_MASK__TRAC; if (irq_mask & AT86RF2XX_IRQ_STATUS_MASK__RX_START) { - dev->event_cb(NETDEV_EVENT_RX_STARTED, NULL); + netdev->event_callback(netdev, NETDEV2_EVENT_RX_STARTED, NULL); DEBUG("[at86rf2xx] EVT - RX_START\n"); } if (irq_mask & AT86RF2XX_IRQ_STATUS_MASK__TRX_END) { - if(state == AT86RF2XX_STATE_RX_AACK_ON || - state == AT86RF2XX_STATE_BUSY_RX_AACK) { + if (state == AT86RF2XX_STATE_RX_AACK_ON || + state == AT86RF2XX_STATE_BUSY_RX_AACK) { DEBUG("[at86rf2xx] EVT - RX_END\n"); - if (!(dev->options & AT86RF2XX_OPT_TELL_RX_END)) { + if (!(dev->netdev.flags & AT86RF2XX_OPT_TELL_RX_END)) { return; } - _receive_data(dev); + netdev->event_callback(netdev, NETDEV2_EVENT_RX_COMPLETE, NULL); } else if (state == AT86RF2XX_STATE_TX_ARET_ON || state == AT86RF2XX_STATE_BUSY_TX_ARET) { @@ -921,35 +617,26 @@ static void _isr_event(gnrc_netdev_t *device, uint32_t event_type) DEBUG("[at86rf2xx] EVT - TX_END\n"); DEBUG("[at86rf2xx] return to state 0x%x\n", dev->idle_state); - if (dev->event_cb && (dev->options & AT86RF2XX_OPT_TELL_TX_END)) { - switch(trac_status) { - case AT86RF2XX_TRX_STATE__TRAC_SUCCESS: - case AT86RF2XX_TRX_STATE__TRAC_SUCCESS_DATA_PENDING: - dev->event_cb(NETDEV_EVENT_TX_COMPLETE, NULL); - DEBUG("[at86rf2xx] TX SUCCESS\n"); - break; - case AT86RF2XX_TRX_STATE__TRAC_NO_ACK: - dev->event_cb(NETDEV_EVENT_TX_NOACK, NULL); - DEBUG("[at86rf2xx] TX NO_ACK\n"); - break; - case AT86RF2XX_TRX_STATE__TRAC_CHANNEL_ACCESS_FAILURE: - dev->event_cb(NETDEV_EVENT_TX_MEDIUM_BUSY, NULL); - DEBUG("[at86rf2xx] TX_CHANNEL_ACCESS_FAILURE\n"); - break; - default: - DEBUG("[at86rf2xx] Unhandled TRAC_STATUS: %d\n", - trac_status >> 5); + if (netdev->event_callback && (dev->netdev.flags & AT86RF2XX_OPT_TELL_TX_END)) { + switch (trac_status) { + case AT86RF2XX_TRX_STATE__TRAC_SUCCESS: + case AT86RF2XX_TRX_STATE__TRAC_SUCCESS_DATA_PENDING: + netdev->event_callback(netdev, NETDEV2_EVENT_TX_COMPLETE, NULL); + DEBUG("[at86rf2xx] TX SUCCESS\n"); + break; + case AT86RF2XX_TRX_STATE__TRAC_NO_ACK: + netdev->event_callback(netdev, NETDEV2_EVENT_TX_NOACK, NULL); + DEBUG("[at86rf2xx] TX NO_ACK\n"); + break; + case AT86RF2XX_TRX_STATE__TRAC_CHANNEL_ACCESS_FAILURE: + netdev->event_callback(netdev, NETDEV2_EVENT_TX_MEDIUM_BUSY, NULL); + DEBUG("[at86rf2xx] TX_CHANNEL_ACCESS_FAILURE\n"); + break; + default: + DEBUG("[at86rf2xx] Unhandled TRAC_STATUS: %d\n", + trac_status >> 5); } } } } } - -const gnrc_netdev_driver_t at86rf2xx_driver = { - .send_data = _send, - .add_event_callback = _add_event_cb, - .rem_event_callback = _rem_event_cb, - .get = _get, - .set = _set, - .isr_event = _isr_event, -}; diff --git a/drivers/at86rf2xx/include/at86rf2xx_netdev.h b/drivers/at86rf2xx/include/at86rf2xx_netdev.h index 92a1fdc9953b333a73aea61fa2bef5fcf6fb49c6..7b6e1f18a38af6a929f63002424229fa5c8d7322 100644 --- a/drivers/at86rf2xx/include/at86rf2xx_netdev.h +++ b/drivers/at86rf2xx/include/at86rf2xx_netdev.h @@ -19,7 +19,7 @@ #ifndef AT86RF2XX_NETDEV_H_ #define AT86RF2XX_NETDEV_H_ -#include "net/gnrc/netdev.h" +#include "net/netdev2.h" #ifdef __cplusplus extern "C" { @@ -28,7 +28,7 @@ extern "C" { /** * @brief Reference to the netdev device driver struct */ -extern const gnrc_netdev_driver_t at86rf2xx_driver; +extern const netdev2_driver_t at86rf2xx_driver; #ifdef __cplusplus } diff --git a/drivers/include/at86rf2xx.h b/drivers/include/at86rf2xx.h index f2e63d7cb1df0582d6d4055baa14f629ee2b93ec..ede06f710f0567f6b4f40ca3880f3fadcc278118 100644 --- a/drivers/include/at86rf2xx.h +++ b/drivers/include/at86rf2xx.h @@ -8,7 +8,7 @@ /** * @defgroup drivers_at86rf2xx AT86RF2xx based drivers - * @ingroup drivers_netdev + * @ingroup drivers_netdev_netdev2 * * This module contains drivers for radio devices in Atmel's AT86RF2xx series. * The driver is aimed to work with all devices of this series. @@ -34,7 +34,9 @@ #include "board.h" #include "periph/spi.h" #include "periph/gpio.h" -#include "net/gnrc/netdev.h" +#include "net/netdev2.h" +#include "net/netdev2/ieee802154.h" +#include "net/gnrc/nettype.h" #ifdef __cplusplus extern "C" { @@ -54,9 +56,9 @@ extern "C" { /** @} */ /** - * @brief Channel configuration - * @{ - */ + * @brief Channel configuration + * @{ + */ #ifdef MODULE_AT86RF212B /* the AT86RF212B has a sub-1GHz radio */ #define AT86RF2XX_MIN_CHANNEL (0) @@ -106,57 +108,54 @@ extern "C" { /** * @brief Internal device option flags + * + * `0x00ff` is reserved for general IEEE 802.15.4 flags + * (see @ref netdev2_ieee802154_t) + * * @{ */ -#define AT86RF2XX_OPT_AUTOACK (0x0001) /**< auto ACKs active */ -#define AT86RF2XX_OPT_CSMA (0x0002) /**< CSMA active */ -#define AT86RF2XX_OPT_PROMISCUOUS (0x0004) /**< promiscuous mode +#define AT86RF2XX_OPT_SRC_ADDR_LONG (NETDEV2_IEEE802154_SRC_MODE_LONG) /**< legacy define */ +#define AT86RF2XX_OPT_RAWDUMP (NETDEV2_IEEE802154_RAW) /**< legacy define */ +#define AT86RF2XX_OPT_AUTOACK (NETDEV2_IEEE802154_ACK_REQ) /**< legacy define */ + +#define AT86RF2XX_OPT_CSMA (0x0100) /**< CSMA active */ +#define AT86RF2XX_OPT_PROMISCUOUS (0x0200) /**< promiscuous mode * active */ -#define AT86RF2XX_OPT_PRELOADING (0x0008) /**< preloading enabled */ -#define AT86RF2XX_OPT_TELL_TX_START (0x0010) /**< notify MAC layer on TX +#define AT86RF2XX_OPT_PRELOADING (0x0400) /**< preloading enabled */ +#define AT86RF2XX_OPT_TELL_TX_START (0x0800) /**< notify MAC layer on TX * start */ -#define AT86RF2XX_OPT_TELL_TX_END (0x0020) /**< notify MAC layer on TX +#define AT86RF2XX_OPT_TELL_TX_END (0x1000) /**< notify MAC layer on TX * finished */ -#define AT86RF2XX_OPT_TELL_RX_START (0x0040) /**< notify MAC layer on RX +#define AT86RF2XX_OPT_TELL_RX_START (0x2000) /**< notify MAC layer on RX * start */ -#define AT86RF2XX_OPT_TELL_RX_END (0x0080) /**< notify MAC layer on RX +#define AT86RF2XX_OPT_TELL_RX_END (0x4000) /**< notify MAC layer on RX * finished */ -#define AT86RF2XX_OPT_RAWDUMP (0x0100) /**< pass RAW frame data to - * upper layer */ -#define AT86RF2XX_OPT_SRC_ADDR_LONG (0x0200) /**< send data using long - * source address */ -#define AT86RF2XX_OPT_USE_SRC_PAN (0x0400) /**< do not compress source - * PAN ID */ /** @} */ /** * @brief Device descriptor for AT86RF2XX radio devices + * + * @extends netdev2_ieee802154_t */ typedef struct { - /* netdev fields */ - const gnrc_netdev_driver_t *driver; /**< pointer to the devices interface */ - gnrc_netdev_event_cb_t event_cb; /**< netdev event callback */ - kernel_pid_t mac_pid; /**< the driver's thread's PID */ - /* device specific fields */ - spi_t spi; /**< used SPI device */ - gpio_t cs_pin; /**< chip select pin */ - gpio_t sleep_pin; /**< sleep pin */ - gpio_t reset_pin; /**< reset pin */ - gpio_t int_pin; /**< external interrupt pin */ - gnrc_nettype_t proto; /**< protocol the radio expects */ - uint8_t state; /**< current state of the radio */ - uint8_t seq_nr; /**< sequence number to use next */ - uint8_t frame_len; /**< length of the current TX frame */ - uint16_t pan; /**< currently used PAN ID */ - uint8_t chan; /**< currently used channel number */ + netdev2_ieee802154_t netdev; /**< netdev2 parent struct */ + /** + * @brief device specific fields + * @{ + */ + spi_t spi; /**< used SPI device */ + gpio_t cs_pin; /**< chip select pin */ + gpio_t sleep_pin; /**< sleep pin */ + gpio_t reset_pin; /**< reset pin */ + gpio_t int_pin; /**< external interrupt pin */ + uint8_t state; /**< current state of the radio */ + uint8_t tx_frame_len; /**< length of the current TX frame */ #ifdef MODULE_AT86RF212B /* Only AT86RF212B supports multiple pages (PHY modes) */ uint8_t page; /**< currently used channel page */ #endif - uint8_t addr_short[2]; /**< the radio's short address */ - uint8_t addr_long[8]; /**< the radio's long address */ - uint16_t options; /**< state of used options */ uint8_t idle_state; /**< state to return to after sending */ + /** @} */ } at86rf2xx_t; /** @@ -172,7 +171,7 @@ typedef struct at86rf2xx_params { } at86rf2xx_params_t; /** - * @brief Initialize a given AT86RF2xx device + * @brief Setup an AT86RF2xx based device state * * @param[out] dev device descriptor * @param[in] spi SPI bus the device is connected to @@ -181,13 +180,10 @@ typedef struct at86rf2xx_params { * @param[in] int_pin GPIO pin connected to the interrupt pin * @param[in] sleep_pin GPIO pin connected to the sleep pin * @param[in] reset_pin GPIO pin connected to the reset pin - * - * @return 0 on success - * @return <0 on error */ -int at86rf2xx_init(at86rf2xx_t *dev, spi_t spi, spi_speed_t spi_speed, - gpio_t cs_pin, gpio_t int_pin, - gpio_t sleep_pin, gpio_t reset_pin); +void at86rf2xx_setup(at86rf2xx_t *dev, spi_t spi, spi_speed_t spi_speed, + gpio_t cs_pin, gpio_t int_pin, gpio_t sleep_pin, + gpio_t reset_pin); /** * @brief Trigger a hardware reset and configure radio with default values diff --git a/sys/auto_init/netif/auto_init_at86rf2xx.c b/sys/auto_init/netif/auto_init_at86rf2xx.c index a80ffe3b8a354f640aea5ca84f464f5643a093e8..775d9f9b0651268e293810d7945b474ebbf23f05 100644 --- a/sys/auto_init/netif/auto_init_at86rf2xx.c +++ b/sys/auto_init/netif/auto_init_at86rf2xx.c @@ -20,7 +20,8 @@ #ifdef MODULE_AT86RF2XX #include "board.h" -#include "net/gnrc/nomac.h" +#include "net/gnrc/netdev2.h" +#include "net/gnrc/netdev2/ieee802154.h" #include "net/gnrc.h" #include "at86rf2xx.h" @@ -36,32 +37,38 @@ #define AT86RF2XX_MAC_STACKSIZE (THREAD_STACKSIZE_DEFAULT) #define AT86RF2XX_MAC_PRIO (THREAD_PRIORITY_MAIN - 4) -#define AT86RF2XX_NUM (sizeof(at86rf2xx_params)/sizeof(at86rf2xx_params[0])) +#define AT86RF2XX_NUM (sizeof(at86rf2xx_params) / sizeof(at86rf2xx_params[0])) static at86rf2xx_t at86rf2xx_devs[AT86RF2XX_NUM]; -static char _nomac_stacks[AT86RF2XX_MAC_STACKSIZE][AT86RF2XX_NUM]; +static gnrc_netdev2_t gnrc_adpt[AT86RF2XX_NUM]; +static char _at86rf2xx_stacks[AT86RF2XX_MAC_STACKSIZE][AT86RF2XX_NUM]; void auto_init_at86rf2xx(void) { for (unsigned i = 0; i < AT86RF2XX_NUM; i++) { const at86rf2xx_params_t *p = &at86rf2xx_params[i]; + int res; DEBUG("Initializing AT86RF2xx radio at SPI_%i\n", p->spi); - int res = at86rf2xx_init(&at86rf2xx_devs[i], - p->spi, - p->spi_speed, - p->cs_pin, - p->int_pin, - p->sleep_pin, - p->reset_pin); + at86rf2xx_setup(&at86rf2xx_devs[i], + p->spi, + p->spi_speed, + p->cs_pin, + p->int_pin, + p->sleep_pin, + p->reset_pin); + res = gnrc_netdev2_ieee802154_init(&gnrc_adpt[i], + (netdev2_ieee802154_t *)&at86rf2xx_devs[i]); if (res < 0) { DEBUG("Error initializing AT86RF2xx radio device!\n"); } else { - gnrc_nomac_init(_nomac_stacks[i], - AT86RF2XX_MAC_STACKSIZE, AT86RF2XX_MAC_PRIO, - "at86rfxx", (gnrc_netdev_t *)&at86rf2xx_devs[i]); + gnrc_netdev2_init(_at86rf2xx_stacks[i], + AT86RF2XX_MAC_STACKSIZE, + AT86RF2XX_MAC_PRIO, + "at86rf2xx", + &gnrc_adpt[i]); } } } diff --git a/tests/driver_at86rf2xx/Makefile b/tests/driver_at86rf2xx/Makefile index 03f6c10e65ab98d5a7338024521b2f5688f04b7e..02dc1afe96f43c12db2dca5ad5427e4e7cf3b9f3 100644 --- a/tests/driver_at86rf2xx/Makefile +++ b/tests/driver_at86rf2xx/Makefile @@ -3,12 +3,9 @@ include ../Makefile.tests_common FEATURES_REQUIRED = periph_spi periph_gpio -BOARD_INSUFFICIENT_MEMORY := nucleo-f334 stm32f0discovery weio +DISABLE_MODULE += auto_init -USEMODULE += auto_init_gnrc_netif -USEMODULE += gnrc_netif -USEMODULE += gnrc_nomac -USEMODULE += gnrc_pktdump +USEMODULE += od USEMODULE += shell USEMODULE += shell_commands USEMODULE += ps diff --git a/tests/driver_at86rf2xx/addr.c b/tests/driver_at86rf2xx/addr.c new file mode 100644 index 0000000000000000000000000000000000000000..af6b0c22611ac887a825385874b99d7331fa2d90 --- /dev/null +++ b/tests/driver_at86rf2xx/addr.c @@ -0,0 +1,31 @@ +/* + * Copyright (C) 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 <stdio.h> +#include <stdint.h> + +#include "common.h" + +void print_addr(uint8_t *addr, size_t addr_len) +{ + for (int i = 0; i < addr_len; i++) { + if (i != 0) { + printf(":"); + } + printf("%02x", (unsigned)addr[i]); + } +} + +/** @} */ diff --git a/tests/driver_at86rf2xx/cmd.c b/tests/driver_at86rf2xx/cmd.c new file mode 100644 index 0000000000000000000000000000000000000000..10d44df3f942c54cb08373c4a1c9de20128b41ad --- /dev/null +++ b/tests/driver_at86rf2xx/cmd.c @@ -0,0 +1,306 @@ +/* + * 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 <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "net/netdev2/ieee802154.h" +#include "net/ieee802154.h" + +#include "common.h" + +#include "od.h" + +#define _MAX_ADDR_LEN (8) + +static int _parse_addr(uint8_t *out, size_t out_len, const char *in); +static int send(int iface, le_uint16_t dst_pan, uint8_t *dst_addr, + size_t dst_len, char *data); + +int ifconfig_list(int idx) +{ + int res; + uint8_t array_val[_MAX_ADDR_LEN]; + netdev2_ieee802154_t *dev = (netdev2_ieee802154_t *)(&devs[idx]); + + int (*get)(netdev2_t *, netopt_t, void *, size_t) = dev->netdev.driver->get; + netopt_enable_t enable_val; + uint16_t u16_val; + + printf("Iface %3d HWaddr: ", idx); + print_addr(dev->short_addr, IEEE802154_SHORT_ADDRESS_LEN); + printf(", Long HWaddr: "); + print_addr(dev->long_addr, IEEE802154_LONG_ADDRESS_LEN); + printf(", PAN: 0x%04x", dev->pan); + + res = get((netdev2_t *)dev, NETOPT_ADDR_LEN, &u16_val, sizeof(u16_val)); + if (res < 0) { + puts("(err)"); + return 1; + } + printf("\n Address length: %u", (unsigned)u16_val); + + res = get((netdev2_t *)dev, NETOPT_SRC_LEN, &u16_val, sizeof(u16_val)); + if (res < 0) { + puts("(err)"); + return 1; + } + printf(", Source address length: %u", (unsigned)u16_val); + + res = get((netdev2_t *)dev, NETOPT_MAX_PACKET_SIZE, &u16_val, + sizeof(u16_val)); + if (res < 0) { + puts("(err)"); + return 1; + } + printf(", Max.Payload: %u", (unsigned)u16_val); + + res = get((netdev2_t *)dev, NETOPT_IPV6_IID, array_val, sizeof(array_val)); + if (res > 0) { + printf("\n IPv6 IID: "); + print_addr(array_val, res); + } + + printf("\n Channel: %u", dev->chan); + + res = get((netdev2_t *)dev, NETOPT_CHANNEL_PAGE, &u16_val, sizeof(u16_val)); + if (res < 0) { + puts("(err)"); + return 1; + } + printf(", Ch.page: %u", (unsigned)u16_val); + + res = get((netdev2_t *)dev, NETOPT_TX_POWER, &u16_val, sizeof(u16_val)); + if (res < 0) { + puts("(err)"); + return 1; + } + printf(", TXPower: %d dBm", (int)u16_val); + res = get((netdev2_t *)dev, NETOPT_IS_WIRED, &u16_val, sizeof(u16_val)); + if (res < 0) { + puts(", wireless"); + } + else { + puts(", wired"); + } + + printf(" "); + res = get((netdev2_t *)dev, NETOPT_PRELOADING, &enable_val, + sizeof(netopt_enable_t)); + if ((res > 0) && (enable_val == NETOPT_ENABLE)) { + printf(" PRELOAD"); + } + res = get((netdev2_t *)dev, NETOPT_AUTOACK, &enable_val, + sizeof(netopt_enable_t)); + if ((res > 0) && (enable_val == NETOPT_ENABLE)) { + printf(" AUTOACK"); + } + res = get((netdev2_t *)dev, NETOPT_RAWMODE, &enable_val, + sizeof(netopt_enable_t)); + if ((res > 0) && (enable_val == NETOPT_ENABLE)) { + printf(" RAW"); + } + res = get((netdev2_t *)dev, NETOPT_AUTOCCA, &enable_val, + sizeof(netopt_enable_t)); + if ((res > 0) && (enable_val == NETOPT_ENABLE)) { + printf(" AUTOCCA"); + } + res = get((netdev2_t *)dev, NETOPT_CSMA, &enable_val, + sizeof(netopt_enable_t)); + if ((res > 0) && (enable_val == NETOPT_ENABLE)) { + printf(" CSMA"); + } + puts(""); + + return 0; +} + +int ifconfig(int argc, char **argv) +{ + (void)argc; + (void)argv; + for (int i = 0; i < AT86RF2XX_NUM; i++) { + ifconfig_list(i); + } + return 0; +} + +static void txtsnd_usage(char *cmd_name) +{ + printf("usage: %s <iface> [<pan>] <addr> <text>\n", cmd_name); +} + +int txtsnd(int argc, char **argv) +{ + char *text; + uint8_t addr[_MAX_ADDR_LEN]; + int iface, idx = 2, res; + le_uint16_t pan = { 0 }; + + switch (argc) { + case 4: + break; + case 5: + res = _parse_addr((uint8_t *)&pan, sizeof(pan), argv[idx++]); + if ((res <= 0) || (res > sizeof(pan))) { + txtsnd_usage(argv[0]); + return 1; + } + pan.u16 = byteorder_swaps(pan.u16); + break; + default: + txtsnd_usage(argv[0]); + return 1; + } + + iface = atoi(argv[1]); + res = _parse_addr(addr, sizeof(addr), argv[idx++]); + if (res <= 0) { + txtsnd_usage(argv[0]); + return 1; + } + text = argv[idx++]; + return send(iface, pan, addr, (size_t)res, text); +} + +static inline int _dehex(char c, int default_) +{ + if ('0' <= c && c <= '9') { + return c - '0'; + } + else if ('A' <= c && c <= 'F') { + return c - 'A' + 10; + } + else if ('a' <= c && c <= 'f') { + return c - 'a' + 10; + } + else { + return default_; + } +} + +static int _parse_addr(uint8_t *out, size_t out_len, const char *in) +{ + const char *end_str = in; + uint8_t *out_end = out; + size_t count = 0; + int assert_cell = 1; + + if (!in || !*in) { + return 0; + } + while (end_str[1]) { + ++end_str; + } + + while (end_str >= in) { + int a = 0, b = _dehex(*end_str--, -1); + if (b < 0) { + if (assert_cell) { + return 0; + } + else { + assert_cell = 1; + continue; + } + } + assert_cell = 0; + + if (end_str >= in) { + a = _dehex(*end_str--, 0); + } + + if (++count > out_len) { + return 0; + } + *out_end++ = (a << 4) | b; + } + if (assert_cell) { + return 0; + } + /* out is reversed */ + + while (out < --out_end) { + uint8_t tmp = *out_end; + *out_end = *out; + *out++ = tmp; + } + + return count; +} + +static int send(int iface, le_uint16_t dst_pan, uint8_t *dst, size_t dst_len, + char *data) +{ + int res; + netdev2_ieee802154_t *dev; + const size_t count = 2; /* mhr + payload */ + struct iovec vector[count]; + uint8_t *src; + size_t src_len; + uint8_t mhr[IEEE802154_MAX_HDR_LEN]; + uint8_t flags; + le_uint16_t src_pan; + + if (((unsigned)iface) > (AT86RF2XX_NUM - 1)) { + printf("txtsnd: %d is not an interface\n", iface); + return 1; + } + + dev = (netdev2_ieee802154_t *)&devs[iface]; + flags = (uint8_t)(dev->flags & NETDEV2_IEEE802154_SEND_MASK); + flags |= IEEE802154_FCF_TYPE_DATA; + vector[1].iov_base = data; + vector[1].iov_len = strlen(data); + src_pan = byteorder_btols(byteorder_htons(dev->pan)); + if (dst_pan.u16 == 0) { + dst_pan = src_pan; + } + if (dev->flags & NETDEV2_IEEE802154_SRC_MODE_LONG) { + src_len = 8; + src = dev->long_addr; + } + else { + src_len = 2; + src = dev->short_addr; + } + /* fill MAC header, seq should be set by device */ + if ((res = ieee802154_set_frame_hdr(mhr, src, src_len, + dst, dst_len, + src_pan, dst_pan, + flags, dev->seq++)) < 0) { + puts("txtsnd: Error preperaring frame"); + return 1; + } + vector[0].iov_base = mhr; + vector[0].iov_len = (size_t)res; + res = dev->netdev.driver->send((netdev2_t *)dev, vector, count); + if (res < 0) { + puts("txtsnd: Error on sending"); + return 1; + } + else { + printf("txtsnd: send %u bytes to ", (unsigned)vector[1].iov_len); + print_addr(dst, dst_len); + printf(" (PAN: "); + print_addr((uint8_t *)&dst_pan, sizeof(dst_pan)); + puts(")"); + } + return 0; +} + +/** @} */ diff --git a/tests/driver_at86rf2xx/common.h b/tests/driver_at86rf2xx/common.h new file mode 100644 index 0000000000000000000000000000000000000000..8829b6e54d5b05d2247bf76306d12497adb38f4a --- /dev/null +++ b/tests/driver_at86rf2xx/common.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2016 Martine Lenders <mlenders@inf.fu-berlin.de> + * + * 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 tests + * @{ + * + * @file + * @brief Common header for at86rf2xx tests + * + * @author Martine Lenders <mlenders@inf.fu-berlin.de> + */ +#ifndef COMMON_H_ +#define COMMON_H_ + +#include <stdint.h> + +#include "at86rf2xx.h" +#include "at86rf2xx_params.h" +#include "net/netdev2.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Application-internal functions and variables for at86rf2xx tests + * @internal + * @{ + */ +#define AT86RF2XX_NUM (sizeof(at86rf2xx_params) / sizeof(at86rf2xx_params[0])) + +extern at86rf2xx_t devs[AT86RF2XX_NUM]; + +void recv(netdev2_t *dev); +int ifconfig(int argc, char **argv); +int txtsnd(int argc, char **argv); +void print_addr(uint8_t *addr, size_t addr_len); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* COMMON_H_ */ +/** @} */ diff --git a/tests/driver_at86rf2xx/main.c b/tests/driver_at86rf2xx/main.c index 1a5f12f9a7f605ac869a94159f1358e71ce9c525..1be7bfb5bbc0a9ea6763ef254bff4a242f8f2d3a 100644 --- a/tests/driver_at86rf2xx/main.c +++ b/tests/driver_at86rf2xx/main.c @@ -20,31 +20,102 @@ #include <stdio.h> +#include "net/netdev2.h" #include "shell.h" #include "shell_commands.h" -#include "net/gnrc/pktdump.h" -#include "net/gnrc.h" +#include "thread.h" +#include "xtimer.h" -/** - * @brief Maybe you are a golfer?! - */ -int main(void) +#include "common.h" + +#define _STACKSIZE (THREAD_STACKSIZE_DEFAULT + THREAD_EXTRA_STACKSIZE_PRINTF) +#define MSG_TYPE_ISR (0x3456) + +static char stack[_STACKSIZE]; +static kernel_pid_t _recv_pid; + +at86rf2xx_t devs[AT86RF2XX_NUM]; + +static const shell_command_t shell_commands[] = { + { "ifconfig", "Configure netdev2", ifconfig }, + { "txtsnd", "Send IEEE 802.15.4 packet", txtsnd }, + { NULL, NULL, NULL } +}; + +static void _event_cb(netdev2_t *dev, netdev2_event_t event, void *data) { - gnrc_netreg_entry_t dump; + (void) data; + + if (event == NETDEV2_EVENT_ISR) { + msg_t msg; + + msg.type = MSG_TYPE_ISR; + msg.content.ptr = (void *) dev; + + if (msg_send(&msg, _recv_pid) <= 0) { + puts("gnrc_netdev2: possibly lost interrupt."); + } + } + else { + switch (event) { + case NETDEV2_EVENT_RX_COMPLETE: + { + recv(dev); + break; + } + default: + puts("Unexpected event received"); + break; + } + } +} + +void *_recv_thread(void *arg) +{ + while (1) { + msg_t msg; + msg_receive(&msg); + if (msg.type == MSG_TYPE_ISR) { + netdev2_t *dev = (netdev2_t *)msg.content.ptr; + dev->driver->isr(dev); + } + else { + puts("unexpected message type"); + } + } +} + +int main(void) +{ puts("AT86RF2xx device driver test"); + xtimer_init(); + + for (unsigned i = 0; i < AT86RF2XX_NUM; i++) { + const at86rf2xx_params_t *p = &at86rf2xx_params[i]; + netdev2_t *dev = (netdev2_t *)(&devs[i]); + + printf("Initializing AT86RF2xx radio at SPI_%d\n", p->spi); + at86rf2xx_setup(&devs[i], p->spi, p->spi_speed, p->cs_pin, + p->int_pin, p->sleep_pin, p->reset_pin); + dev->event_callback = _event_cb; + dev->driver->init(dev); + } + + _recv_pid = thread_create(stack, sizeof(stack), THREAD_PRIORITY_MAIN - 1, + THREAD_CREATE_STACKTEST, _recv_thread, NULL, + "recv_thread"); - /* register the pktdump thread */ - puts("Register the packet dump thread for GNRC_NETTYPE_UNDEF packets"); - dump.pid = gnrc_pktdump_pid; - dump.demux_ctx = GNRC_NETREG_DEMUX_CTX_ALL; - gnrc_netreg_register(GNRC_NETTYPE_UNDEF, &dump); + if (_recv_pid <= KERNEL_PID_UNDEF) { + puts("Creation of receiver thread failed"); + return 1; + } /* start the shell */ puts("Initialization successful - starting the shell now"); char line_buf[SHELL_DEFAULT_BUFSIZE]; - shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); + shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); return 0; } diff --git a/tests/driver_at86rf2xx/recv.c b/tests/driver_at86rf2xx/recv.c new file mode 100644 index 0000000000000000000000000000000000000000..d351eb2574a4db0db3ad2d8633dad130b130adf9 --- /dev/null +++ b/tests/driver_at86rf2xx/recv.c @@ -0,0 +1,117 @@ +/* + * Copyright (C) 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 <stdio.h> + +#include "at86rf2xx.h" +#include "od.h" +#include "net/ieee802154.h" +#include "net/netdev2.h" + +#include "common.h" + +#define MAX_LINE (80) + +static uint8_t buffer[AT86RF2XX_MAX_PKT_LENGTH]; + +void recv(netdev2_t *dev) +{ + uint8_t src[IEEE802154_LONG_ADDRESS_LEN], dst[IEEE802154_LONG_ADDRESS_LEN]; + size_t mhr_len, data_len, src_len, dst_len; + netdev2_ieee802154_rx_info_t rx_info; + le_uint16_t src_pan, dst_pan; + + putchar('\n'); + data_len = dev->driver->recv(dev, (char *)buffer, sizeof(buffer), &rx_info); + mhr_len = ieee802154_get_frame_hdr_len(buffer); + if (mhr_len == 0) { + puts("Unexpected MHR for incoming packet"); + return; + } + dst_len = ieee802154_get_dst(buffer, dst, &dst_pan); + src_len = ieee802154_get_src(buffer, src, &src_pan); + switch (buffer[0] & IEEE802154_FCF_TYPE_MASK) { + case IEEE802154_FCF_TYPE_BEACON: + puts("BEACON"); + break; + case IEEE802154_FCF_TYPE_DATA: + puts("DATA"); + break; + case IEEE802154_FCF_TYPE_ACK: + puts("ACK"); + break; + case IEEE802154_FCF_TYPE_MACCMD: + puts("MACCMD"); + break; + default: + puts("UNKNOWN"); + break; + } + printf("Dest. PAN: 0x%04x, Dest. addr.: ", + byteorder_ntohs(byteorder_ltobs(dst_pan))); + print_addr(dst, dst_len); + printf("\nSrc. PAN: 0x%04x, Src. addr.: ", + byteorder_ntohs(byteorder_ltobs(src_pan))); + print_addr(src, src_len); + printf("\nSecurity: "); + if (buffer[0] & IEEE802154_FCF_SECURITY_EN) { + printf("1, "); + } + else { + printf("0, "); + } + printf("Frame pend.: "); + if (buffer[0] & IEEE802154_FCF_FRAME_PEND) { + printf("1, "); + } + else { + printf("0, "); + } + printf("ACK req.: "); + if (buffer[0] & IEEE802154_FCF_ACK_REQ) { + printf("1, "); + } + else { + printf("0, "); + } + printf("PAN comp.: "); + if (buffer[0] & IEEE802154_FCF_ACK_REQ) { + puts("1"); + } + else { + puts("0"); + } + printf("Version: "); + printf("%u, ", (unsigned)((buffer[1] & IEEE802154_FCF_VERS_MASK) >> 4)); + printf("Seq.: %u\n", (unsigned)ieee802154_get_seq(buffer)); + od_hex_dump(buffer + mhr_len, data_len - mhr_len, 0); + printf("txt: "); + for (int i = mhr_len; i < data_len; i++) { + if ((buffer[i] > 0x1F) && (buffer[i] < 0x80)) { + putchar((char)buffer[i]); + } + else { + putchar('?'); + } + if (((((i - mhr_len) + 1) % (MAX_LINE - sizeof("txt: "))) == 1) && + (i - mhr_len) != 0) { + printf("\n "); + } + } + printf("\n"); + printf("RSSI: %u, LQI: %u\n\n", rx_info.rssi, rx_info.lqi); +} + +/** @} */