diff --git a/drivers/wireless/ieee802154/Kconfig b/drivers/wireless/ieee802154/Kconfig index 93e802323df..6eba028b2a3 100644 --- a/drivers/wireless/ieee802154/Kconfig +++ b/drivers/wireless/ieee802154/Kconfig @@ -11,4 +11,10 @@ config IEEE802154_MRF24J40 ---help--- This selection enables support for the Microchip MRF24J40 device. +config IEEE802154_AT86RF233 + bool "ATMEL RF233 IEEE 802.15.4 transceiver" + default n + ---help--- + This selection enables support for the Atmel RF233 device. + endif # DRIVERS_IEEE802154 diff --git a/drivers/wireless/ieee802154/Make.defs b/drivers/wireless/ieee802154/Make.defs index b0a1406baa4..8e0924d67ff 100644 --- a/drivers/wireless/ieee802154/Make.defs +++ b/drivers/wireless/ieee802154/Make.defs @@ -45,6 +45,10 @@ ifeq ($(CONFIG_IEEE802154_MRF24J40),y) CSRCS += mrf24j40.c endif +ifeq ($(CONFIG_IEEE802154_AT86RF233),y) + CSRCS += at86rf23x.c +endif + # Include IEEE 802.15.4 build support DEPPATH += --dep-path wireless$(DELIM)ieee802154 diff --git a/drivers/wireless/ieee802154/at86rf23x.c b/drivers/wireless/ieee802154/at86rf23x.c new file mode 100644 index 00000000000..fdd2c3ad646 --- /dev/null +++ b/drivers/wireless/ieee802154/at86rf23x.c @@ -0,0 +1,1479 @@ +/**************************************************************************** + * drivers/wireless/ieee802154/at86rf23x.c + * + * Copyright (C) 2016 Matt Poppe. All rights reserved. + * Author: Matt Poppe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "at86rf23x.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +#ifndef CONFIG_SCHED_HPWORK +#error High priority work queue required in this driver +#endif + +#ifndef CONFIG_IEEE802154_at86rf23x_SPIMODE +# define CONFIG_IEEE802154_at86rf23x_SPIMODE SPIDEV_MODE0 +#endif + +#ifndef CONFIG_IEEE802154_at86rf23x_FREQUENCY +# define CONFIG_IEEE802154_at86rf23x_FREQUENCY 1000000 +#endif + +/* Definitions for the device structure */ + +#define AT86RF23X_RXMODE_NORMAL 0 +#define AT86RF23X_RXMODE_PROMISC 1 +#define AT86RF23X_RXMODE_NOCRC 2 +#define AT86RF23X_RXMODE_AUTOACK 3 + +/* Definitions for PA control on high power modules */ +#define AT86RF23X_PA_AUTO 1 +#define AT86RF23X_PA_ED 2 +#define AT86RF23X_PA_SLEEP 3 + + +/************************************************************************************ + * Private Types + ************************************************************************************/ + +/* + * AT86RF23x device instance + * + * Make sure that struct ieee802154_dev_s remains first. If not it will break the + * code + * + */ +struct at86rf23x_dev_s +{ + struct ieee802154_dev_s ieee; /* Public device instance */ + FAR struct spi_dev_s *spi; /* Saved SPI interface instance */ + struct work_s irqwork; /* Interrupt continuation work queue support */ + FAR const struct at86rf23x_lower_s *lower; /* Low-level MCU-specific support */ + uint16_t panid; /* PAN identifier, FFFF = not set */ + uint16_t saddr; /* short address, FFFF = not set */ + uint8_t eaddr[8]; /* extended address, FFFFFFFFFFFFFFFF = not set */ + uint8_t channel; /* 11 to 26 for the 2.4 GHz band */ + uint8_t devmode; /* device mode: device, coord, pancoord */ + uint8_t paenabled; /* enable usage of PA */ + uint8_t rxmode; /* Reception mode: Main, no CRC, promiscuous */ + int32_t txpower; /* TX power in mBm = dBm/100 */ + struct ieee802154_cca_s cca; /* Clear channel assessement method */ + +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Internal operations */ +static void at86rf23x_lock(FAR struct spi_dev_s *spi); +static void at86rf23x_unlock(FAR struct spi_dev_s *spi); +static void at86rf23x_setreg(FAR struct spi_dev_s *spi, uint32_t addr, uint8_t val); +static uint8_t at86rf23x_getreg(FAR struct spi_dev_s *spi, uint32_t addr); +static int at86rf23x_writeframe(FAR struct spi_dev_s *spi, uint8_t *frame, uint8_t len); +static uint8_t at86rf23x_readframe(FAR struct spi_dev_s *spi, uint8_t *frame_rx); +static int at86rf23x_setTRXstate(FAR struct at86rf23x_dev_s *dev, uint8_t state, uint8_t force); +static uint8_t at86rf23x_getTRXstate(FAR struct at86rf23x_dev_s *dev); +static int at86rf23x_resetrf(FAR struct at86rf23x_dev_s *dev); +static int at86rf23x_initialize(FAR struct at86rf23x_dev_s *dev); + +static int at86rf23x_regdump(FAR struct at86rf23x_dev_s *dev); +static void at86rf23x_irqwork_rx(FAR struct at86rf23x_dev_s *dev); +static void at86rf23x_irqwork_tx(FAR struct at86rf23x_dev_s *dev); +static void at86rf23x_irqworker(FAR void *arg); +static int at86rf23x_interrupt(int irq, FAR void *context); + +/* Driver operations */ +static int at86rf23x_setchannel (FAR struct ieee802154_dev_s *ieee, uint8_t chan); +static int at86rf23x_getchannel (FAR struct ieee802154_dev_s *ieee, FAR uint8_t *chan); +static int at86rf23x_setpanid (FAR struct ieee802154_dev_s *ieee, uint16_t panid); +static int at86rf23x_getpanid (FAR struct ieee802154_dev_s *ieee, FAR uint16_t *panid); +static int at86rf23x_setsaddr (FAR struct ieee802154_dev_s *ieee, uint16_t saddr); +static int at86rf23x_getsaddr (FAR struct ieee802154_dev_s *ieee, FAR uint16_t *saddr); +static int at86rf23x_seteaddr (FAR struct ieee802154_dev_s *ieee, FAR uint8_t *eaddr); +static int at86rf23x_geteaddr (FAR struct ieee802154_dev_s *ieee, FAR uint8_t *eaddr); +static int at86rf23x_setpromisc (FAR struct ieee802154_dev_s *ieee, bool promisc); +static int at86rf23x_getpromisc (FAR struct ieee802154_dev_s *ieee, FAR bool *promisc); +static int at86rf23x_setdevmode (FAR struct ieee802154_dev_s *ieee, uint8_t mode); +static int at86rf23x_getdevmode (FAR struct ieee802154_dev_s *ieee, FAR uint8_t *mode); +static int at86rf23x_settxpower (FAR struct ieee802154_dev_s *ieee, int32_t txpwr); +static int at86rf23x_gettxpower (FAR struct ieee802154_dev_s *ieee, FAR int32_t *txpwr); +static int at86rf23x_setcca (FAR struct ieee802154_dev_s *ieee, FAR struct ieee802154_cca_s *cca); +static int at86rf23x_getcca (FAR struct ieee802154_dev_s *ieee, FAR struct ieee802154_cca_s *cca); +static int at86rf23x_ioctl (FAR struct ieee802154_dev_s *ieee, int cmd, unsigned long arg); +static int at86rf23x_energydetect(FAR struct ieee802154_dev_s *ieee, FAR uint8_t *energy); +static int at86rf23x_rxenable (FAR struct ieee802154_dev_s *ieee, bool state, FAR struct ieee802154_packet_s *packet); +static int at86rf23x_transmit (FAR struct ieee802154_dev_s *ieee, FAR struct ieee802154_packet_s *packet); + + +/* These are pointers to ALL registered at86rf23x devices. + * This table is used during irqs to find the context + * Only one device is supported for now. + * More devices can be supported in the future by lookup them up + * using the IRQ number. See the ENC28J60 or CC3000 drivers for reference. + */ + +static struct at86rf23x_dev_s g_at86rf23x_devices[1]; + +static const struct ieee802154_devops_s at86rf23x_devops = +{ + .setchannel = at86rf23x_setchannel, + .getchannel = at86rf23x_getchannel, + .setpanid = at86rf23x_setpanid, + .getpanid = at86rf23x_getpanid, + .setsaddr = at86rf23x_setsaddr, + .getsaddr = at86rf23x_getsaddr, + .seteaddr = at86rf23x_seteaddr, + .geteaddr = at86rf23x_geteaddr, + .setpromisc = at86rf23x_setpromisc, + .getpromisc = at86rf23x_getpromisc, + .setdevmode = at86rf23x_setdevmode, + .getdevmode = at86rf23x_getdevmode, + .settxpower = at86rf23x_settxpower, + .gettxpower = at86rf23x_gettxpower, + .setcca = at86rf23x_setcca, + .getcca = at86rf23x_getcca, + .ioctl = at86rf23x_ioctl, + .energydetect = at86rf23x_energydetect, + .rxenable = at86rf23x_rxenable, + .transmit = at86rf23x_transmit +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ +#ifndef CONFIG_SPI_EXCHANGE +#error CONFIG_SPI_EXCHANGE required for this driver +#endif + +/* hardware access routines */ + +/**************************************************************************** + * Name: at86rf23x_lock + * + * Description: + * Acquire exclusive access to the shared SPI bus. + * + ****************************************************************************/ + +static void at86rf23x_lock(FAR struct spi_dev_s *spi) +{ + SPI_LOCK (spi, 1); + SPI_SETBITS (spi, 8); + SPI_SETMODE (spi, CONFIG_IEEE802154_at86rf23x_SPIMODE ); + SPI_SETFREQUENCY(spi, CONFIG_IEEE802154_at86rf23x_FREQUENCY ); + +} + +/**************************************************************************** + * Name: at86rf23x_unlock + * + * Description: + * Release exclusive access to the shared SPI bus. + * + ****************************************************************************/ + +static void at86rf23x_unlock(FAR struct spi_dev_s *spi) +{ + SPI_LOCK(spi,0); +} + +/**************************************************************************** + * Name: at86rf23x_setreg + * + * Description: + * Define the value of an at86rf23x device register + * + ****************************************************************************/ + +static void at86rf23x_setreg(FAR struct spi_dev_s *spi, uint32_t addr, uint8_t val) +{ + uint8_t reg[2]; + + reg[0] = addr; + reg[0] |= RF23X_SPI_REG_WRITE; + + reg[1] = val; + at86rf23x_lock(spi); + SPI_SELECT(spi, SPIDEV_IEEE802154, true); + SPI_SNDBLOCK(spi, reg, 2); + SPI_SELECT(spi, SPIDEV_IEEE802154, false); + at86rf23x_unlock(spi); + + vdbg("0x%02X->r[0x%02X]\n", val, addr); + +} + +/**************************************************************************** + * Name: at86rf23x_getreg + * + * Description: + * Return the value of an at86rf23x device register + * + ****************************************************************************/ +static uint8_t at86rf23x_getreg(FAR struct spi_dev_s *spi, uint32_t addr) +{ + uint8_t reg[2]; + uint8_t val[2]; + + /* Add Read mask to desired register */ + reg[0] = addr | RF23X_SPI_REG_READ; + + at86rf23x_lock (spi); + + SPI_SELECT (spi, SPIDEV_IEEE802154, true); + SPI_EXCHANGE (spi, reg, val, 2); + SPI_SELECT (spi, SPIDEV_IEEE802154, false); + + at86rf23x_unlock(spi); + + vdbg("r[0x%02X]=0x%02X\n",addr,val[1]); + + return val[1]; +} + +/**************************************************************************** + * Name: at86rf23x_setregbits + * + * Description: + * Read the current value of the register. Change only the portion + * of the register we need to change and write the value back to the + * register. + * + ****************************************************************************/ +static void at86rf23x_setregbits(FAR struct spi_dev_s *spi, + uint8_t addr, + uint8_t pos, + uint8_t mask, + uint8_t val) +{ + uint8_t reg; + + reg = at86rf23x_getreg(spi, addr); + reg = (reg & ~(mask << pos)) | (val << pos); + at86rf23x_setreg(spi, addr, reg); +} + +/**************************************************************************** + * Name: at86rf23x_getregbits + * + * Description: + * Return the value of an section of the at86rf23x device register. + * + ****************************************************************************/ +static uint8_t at86rf23x_getregbits(FAR struct spi_dev_s *spi, + uint8_t addr, + uint8_t pos, + uint8_t mask) +{ + uint8_t val; + + val = at86rf23x_getreg(spi, addr); + val = (val >> pos) & mask; + + return val; +} + +/**************************************************************************** + * Name: at86rf23x_writebuffer + * + * Description: + * Write frame to the transmit buffer of the radio. This does not + * initiate the transfer, just write to the buffer. + * + ****************************************************************************/ +static int at86rf23x_writeframe(FAR struct spi_dev_s *spi, uint8_t *frame, uint8_t len) +{ +// report_packet(frame_wr, len); + uint8_t reg = RF23X_SPI_FRAME_WRITE; + + at86rf23x_lock(spi); + + SPI_SELECT(spi, SPIDEV_IEEE802154, true); + + SPI_SNDBLOCK(spi, ®, 1); + SPI_SNDBLOCK(spi, &frame, len); + + SPI_SELECT(spi, SPIDEV_IEEE802154, false); + + at86rf23x_unlock(spi); + + return len; +} + +/**************************************************************************** + * Name: at86rf23x_readframe + * + * Description: + * Read the buffer memory of the radio. This is used when the radio + * indicates a frame has been received. + * + ****************************************************************************/ +static uint8_t at86rf23x_readframe(FAR struct spi_dev_s *spi, uint8_t *frame_rx) +{ + uint8_t len, reg; + + reg = RF23X_SPI_FRAME_READ; + + at86rf23x_lock(spi); + SPI_SELECT(spi, SPIDEV_IEEE802154, true); + + SPI_SNDBLOCK(spi, ®, 1); + SPI_RECVBLOCK(spi, &len, 1); + SPI_RECVBLOCK(spi, frame_rx, len+3); + + SPI_SELECT(spi, SPIDEV_IEEE802154, false); + at86rf23x_unlock(spi); + + return len; +} + + +/**************************************************************************** + * Name: at86rf23x_getTRXstate + * + * Description: + * Return the current status of the TRX state machine. + * + ****************************************************************************/ +static uint8_t at86rf23x_getTRXstate(FAR struct at86rf23x_dev_s *dev) +{ + return at86rf23x_getregbits(dev->spi, RF23X_TRXSTATUS_STATUS); +} + +/**************************************************************************** + * Name: at86rf23x_setTRXstate + * + * Description: + * Set the TRX state machine to the desired state. If the state machine + * cannot move to the desired state an ERROR is returned. If the transistion + * is successful an OK is returned. This is a long running function due to + * waiting for the transistion delay between states. This can be as long as + * 510us. + * + ****************************************************************************/ +static int at86rf23x_setTRXstate(FAR struct at86rf23x_dev_s *dev, uint8_t state, uint8_t force) +{ + /* Get the current state of the transceiver */ + uint8_t status = at86rf23x_getTRXstate(dev); + + int ret = OK; + + /* TODO I don't have every state included verify this will work with SLEEP */ + if((status != TRX_STATUS_TRXOFF) && + (status != TRX_STATUS_RXON) && + (status != TRX_STATUS_PLLON) && + (status != TRX_STATUS_RXAACKON) && + (status != TRX_STATUS_TXARETON) && + (status != TRX_STATUS_PON)) + { + dbg("Invalid State\n"); + return ERROR; + } + + int8_t init_status = status; + + /* Start the state change */ + switch(state) + { + case TRX_CMD_TRXOFF: + if(status == TRX_STATUS_TRXOFF) + { + break; + } + /* verify in a state that will transfer to TRX_OFF if not check if force is required */ + if( (status == TRX_STATUS_RXON) || + (status == TRX_STATUS_PLLON) || + (status == TRX_STATUS_RXAACKON) || + (status == TRX_STATUS_TXARETON)) + { + at86rf23x_setregbits(dev->spi, RF23X_TRXCMD_STATE, TRX_CMD_TRXOFF); + up_udelay(RF23X_TIME_TRANSITION_PLL_ACTIVE); + } + else if(status == TRX_STATUS_PON) + { + at86rf23x_setregbits(dev->spi, RF23X_TRXCMD_STATE, TRX_CMD_TRXOFF); + up_udelay(RF23X_TIME_P_ON_TO_TRXOFF); + } + else if(force) + { + at86rf23x_setregbits(dev->spi, RF23X_TRXCMD_STATE, TRX_CMD_FORCETRXOFF); + up_udelay(RF23X_TIME_FORCE_TRXOFF); + } + + status = at86rf23x_getregbits(dev->spi, RF23X_TRXSTATUS_STATUS); + + if(status != TRX_STATUS_TRXOFF) + { + ret = ERROR; + } + + break; + + case TRX_CMD_RX_ON: + + if(status == TRX_STATUS_RXON) + { + break; + } + + if (status == TRX_STATUS_TRXOFF) + { + at86rf23x_setregbits(dev->spi, RF23X_TRXCMD_STATE, TRX_CMD_RX_ON); + up_udelay(RF23X_TIME_TRXOFF_TO_PLL); + } + + else if((status == TRX_STATUS_RXAACKON) || + (status == TRX_STATUS_RXON) || + (status == TRX_STATUS_PLLON) || + (status == TRX_STATUS_TXARETON)) + { + at86rf23x_setregbits(dev->spi, RF23X_TRXCMD_STATE, TRX_CMD_RX_ON); + up_udelay(RF23X_TIME_TRANSITION_PLL_ACTIVE); + } + + status = at86rf23x_getregbits(dev->spi, RF23X_TRXSTATUS_STATUS); + + if(status != TRX_STATUS_RXON) + { + ret = ERROR; + } + break; + + /* transition to PLL_ON */ + case TRX_CMD_PLL_ON: + + if(status == TRX_STATUS_PLLON) + { + break; + } + + if (status == TRX_STATUS_TRXOFF) + { + at86rf23x_setregbits(dev->spi, RF23X_TRXCMD_STATE, TRX_CMD_PLL_ON); + up_udelay(RF23X_TIME_TRXOFF_TO_PLL); + } + else + { + at86rf23x_setregbits(dev->spi, RF23X_TRXCMD_STATE, TRX_CMD_PLL_ON); + up_udelay(RF23X_TIME_TRANSITION_PLL_ACTIVE); + } + + status = at86rf23x_getregbits(dev->spi, RF23X_TRXSTATUS_STATUS); + + if(status != TRX_STATUS_PLLON) + { + ret = ERROR; + } + break; + + case TRX_CMD_RX_AACK_ON: + + if(status == TRX_STATUS_RXAACKON) + { + break; + } + + if (status == TRX_STATUS_TRXOFF || status == TRX_STATUS_TXARETON) + { + at86rf23x_setregbits(dev->spi, RF23X_TRXCMD_STATE, TRX_CMD_RX_ON); + + (status == TRX_STATUS_TRXOFF) ? up_udelay(RF23X_TIME_TRXOFF_TO_PLL) : + up_udelay(RF23X_TIME_TRANSITION_PLL_ACTIVE); + } + + status = at86rf23x_getTRXstate(dev); + + if ((status == TRX_STATUS_RXON) || (status == TRX_STATUS_PLLON)) + { + at86rf23x_setregbits(dev->spi, RF23X_TRXCMD_STATE, TRX_CMD_RX_AACK_ON); + up_udelay(RF23X_TIME_TRANSITION_PLL_ACTIVE); + } + + status = at86rf23x_getregbits(dev->spi, RF23X_TRXSTATUS_STATUS); + + if(status != TRX_STATUS_RXAACKON) + { + ret = ERROR; + } + + break; + + case TRX_STATUS_TXARETON: + + if(status == TRX_STATUS_TXARETON) + { + break; + } + + if (status == TRX_STATUS_TRXOFF) + { + at86rf23x_setregbits(dev->spi, RF23X_TRXCMD_STATE, TRX_CMD_RX_ON); + up_udelay(RF23X_TIME_TRXOFF_TO_PLL); + } + + if ((status == TRX_STATUS_RXON) || (status == TRX_STATUS_PLLON)) + { + at86rf23x_setregbits(dev->spi, RF23X_TRXCMD_STATE, TRX_CMD_TX_ARET_ON); + up_udelay(RF23X_TIME_TRANSITION_PLL_ACTIVE); + } + else if (status == TRX_STATUS_RXAACKON) + { + at86rf23x_setregbits(dev->spi, RF23X_TRXCMD_STATE, TRX_CMD_RX_ON); + up_udelay(RF23X_TIME_TRANSITION_PLL_ACTIVE); + + at86rf23x_setregbits(dev->spi, RF23X_TRXCMD_STATE, TRX_CMD_TX_ARET_ON); + up_udelay(RF23X_TIME_TRANSITION_PLL_ACTIVE); + } + + status = at86rf23x_getregbits(dev->spi, RF23X_TRXSTATUS_STATUS); + + if(status != TRX_STATUS_TXARETON) + { + ret = ERROR; + } + + break; + + case TRX_STATUS_SLEEP: + at86rf23x_setregbits(dev->spi, RF23X_TRXCMD_STATE, TRX_CMD_FORCETRXOFF); + up_udelay(RF23X_TIME_CMD_FORCE_TRX_OFF); + + dev->lower->slptr(dev->lower, true); + up_udelay(RF23X_TIME_TRXOFF_TO_SLEEP); + + status = at86rf23x_getregbits(dev->spi, RF23X_TRXSTATUS_STATUS); + break; + + default: + dbg("%s \n", EINVAL_STR); + init_status = 0;/* Placed this here to keep compiler happy when not in debug */ + return -EINVAL; + + } + if(ret == ERROR) + { + dbg("State Transistion Error\n"); + } + + vdbg("Radio state change state[0x%02x]->state[0x%02x]\n", init_status, status); + + return ret; +} + +/* Publicized driver routines */ + +/**************************************************************************** + * Name: at86rf23x_setchannel + * + * Description: + * Define the current radio channel the device is operating on. + * In the 2.4 GHz, there are 16 channels, each 2 MHz wide, 5 MHz spacing: + * Chan MHz Chan MHz Chan MHz Chan MHz + * 11 2405 15 2425 19 2445 23 2465 + * 12 2410 16 2430 20 2450 24 2470 + * 13 2415 17 2435 21 2455 25 2475 + * 14 2420 18 2440 22 2460 26 2480 + * + * + ****************************************************************************/ +static int at86rf23x_setchannel(FAR struct ieee802154_dev_s *ieee, uint8_t chan) +{ + FAR struct at86rf23x_dev_s *dev = (FAR struct at86rf23x_dev_s *)ieee; + uint8_t state; + + /* Validate if chan is a valid channel */ + if(chan<11 || chan>26) + { + dbg("Invalid requested chan: %d\n",chan); + return -EINVAL; + } + + /* Validate we are in an acceptable mode to change the channel */ + state = at86rf23x_getTRXstate(dev); + + if((TRX_STATUS_SLEEP == state) || (TRX_STATUS_PON == state)) { + dbg("Radio in invalid mode [%02x] to set the channel\n", state); + return ERROR; + } + /* Set the Channel on the transceiver */ + + at86rf23x_setregbits(dev->spi, RF23X_CCA_BITS_CHANNEL, chan); + + /* Set the channel within local device */ + dev->channel = chan; + + vdbg("CHANNEL Changed to %d\n", chan); + + return OK; +} + +/**************************************************************************** + * Name: at86rf23x_getchannel + * + * Description: + * Define the current radio channel the device is operating on. + * In the 2.4 GHz, there are 16 channels, each 2 MHz wide, 5 MHz spacing: + * Chan MHz Chan MHz Chan MHz Chan MHz + * 11 2405 15 2425 19 2445 23 2465 + * 12 2410 16 2430 20 2450 24 2470 + * 13 2415 17 2435 21 2455 25 2475 + * 14 2420 18 2440 22 2460 26 2480 + * + * This section assumes that the transceiver is not in SLEEP or P_ON state. + * + * + ****************************************************************************/ +static int at86rf23x_getchannel(FAR struct ieee802154_dev_s *ieee, FAR uint8_t *chan) +{ + FAR struct at86rf23x_dev_s *dev = (FAR struct at86rf23x_dev_s *)ieee; + + /* Set the Channel on the transceiver */ + *chan = at86rf23x_getregbits(dev->spi, RF23X_CCA_BITS_CHANNEL); + + /* Set the channel within local device */ + dev->channel = *chan; + + return OK; +} + +/**************************************************************************** + * Name: at86rf23x_setpanid + * + * Description: + * Define the PAN ID for the network. + * + ****************************************************************************/ +static int at86rf23x_setpanid(FAR struct ieee802154_dev_s *ieee, uint16_t panid) +{ + FAR struct at86rf23x_dev_s *dev = (struct at86rf23x_dev_s *)ieee; + uint8_t *pan = (uint8_t *)&panid; + + at86rf23x_setreg(dev->spi, RF23X_REG_PANID0, pan[0]); + at86rf23x_setreg(dev->spi, RF23X_REG_PANID1, pan[1]); + + return OK; +} + +/**************************************************************************** + * Name: at86rf23x_getpanid + * + * Description: + * Define the PAN ID for the network. + * + ****************************************************************************/ +static int at86rf23x_getpanid(FAR struct ieee802154_dev_s *ieee, FAR uint16_t *panid) +{ + FAR struct at86rf23x_dev_s *dev = (struct at86rf23x_dev_s *)ieee; + uint8_t *pan = (uint8_t *)panid; + /* TODO: Check if we need to pay attention to endianness */ + pan[0] = at86rf23x_getreg(dev->spi, RF23X_REG_PANID0); + pan[1] = at86rf23x_getreg(dev->spi, RF23X_REG_PANID1); + + return OK; +} + +/**************************************************************************** + * Name: at86rf23x_setsaddr + * + * Description: + * Define the Short Address for the device. + * + ****************************************************************************/ +static int at86rf23x_setsaddr(FAR struct ieee802154_dev_s *ieee, uint16_t saddr) +{ + FAR struct at86rf23x_dev_s *dev = (struct at86rf23x_dev_s *)ieee; + uint8_t *addr = (uint8_t *)&saddr; + + at86rf23x_setreg(dev->spi, RF23X_REG_SADDR0, addr[0]); + at86rf23x_setreg(dev->spi, RF23X_REG_SADDR1, addr[1]); + + return OK; +} + +/**************************************************************************** + * Name: at86rf23x_getsaddr + * + * Description: + * Get the short address of the device. + * + ****************************************************************************/ +static int at86rf23x_getsaddr(FAR struct ieee802154_dev_s *ieee, FAR uint16_t *saddr) +{ + FAR struct at86rf23x_dev_s *dev = (struct at86rf23x_dev_s *)ieee; + uint8_t *addr = (uint8_t *)saddr; + /* TODO: Check if we need to pay attention to endianness */ + addr[0] = at86rf23x_getreg(dev->spi, RF23X_REG_SADDR0); + addr[1] = at86rf23x_getreg(dev->spi, RF23X_REG_SADDR1); + + return OK; +} + +/**************************************************************************** + * Name: at86rf23x_seteaddr + * + * Description: + * Set the IEEE address of the device. + * + ****************************************************************************/ +static int at86rf23x_seteaddr(FAR struct ieee802154_dev_s *ieee, FAR uint8_t *eaddr) +{ + FAR struct at86rf23x_dev_s *dev = (struct at86rf23x_dev_s *)ieee; + /* TODO: Check if we need to pay attention to endianness */ + at86rf23x_setreg(dev->spi, RF23X_REG_IEEEADDR0, eaddr[0]); + at86rf23x_setreg(dev->spi, RF23X_REG_IEEEADDR1, eaddr[1]); + at86rf23x_setreg(dev->spi, RF23X_REG_IEEEADDR2, eaddr[2]); + at86rf23x_setreg(dev->spi, RF23X_REG_IEEEADDR3, eaddr[3]); + at86rf23x_setreg(dev->spi, RF23X_REG_IEEEADDR4, eaddr[4]); + at86rf23x_setreg(dev->spi, RF23X_REG_IEEEADDR5, eaddr[5]); + at86rf23x_setreg(dev->spi, RF23X_REG_IEEEADDR6, eaddr[6]); + at86rf23x_setreg(dev->spi, RF23X_REG_IEEEADDR7, eaddr[7]); + + return OK; +} + +/**************************************************************************** + * Name: at86rf23x_geteaddr + * + * Description: + * Get the IEEE address of the device. + * + ****************************************************************************/ +static int at86rf23x_geteaddr(FAR struct ieee802154_dev_s *ieee, FAR uint8_t *eaddr) +{ + FAR struct at86rf23x_dev_s *dev = (struct at86rf23x_dev_s *)ieee; + /* TODO: Check if we need to pay attention to endianness */ + eaddr[0] = at86rf23x_getreg(dev->spi, RF23X_REG_IEEEADDR0); + eaddr[1] = at86rf23x_getreg(dev->spi, RF23X_REG_IEEEADDR1); + eaddr[2] = at86rf23x_getreg(dev->spi, RF23X_REG_IEEEADDR2); + eaddr[3] = at86rf23x_getreg(dev->spi, RF23X_REG_IEEEADDR3); + eaddr[4] = at86rf23x_getreg(dev->spi, RF23X_REG_IEEEADDR4); + eaddr[5] = at86rf23x_getreg(dev->spi, RF23X_REG_IEEEADDR5); + eaddr[6] = at86rf23x_getreg(dev->spi, RF23X_REG_IEEEADDR6); + eaddr[7] = at86rf23x_getreg(dev->spi, RF23X_REG_IEEEADDR7); + + return OK; +} + +/**************************************************************************** + * Name: at86rf23x_setpromisc + * + * Description: + * enable/disable promiscuous mode. + * + ****************************************************************************/ +static int at86rf23x_setpromisc(FAR struct ieee802154_dev_s *ieee, bool promisc) +{ + FAR struct at86rf23x_dev_s *dev = (struct at86rf23x_dev_s *)ieee; + + /* TODO: Check what mode I should be in to activate promiscuous mode: + * This is way to simple of an implementation. Many other things should be set + * and/or checked before we set the device into promiscuous mode + * */ + at86rf23x_setregbits(dev->spi, RF23X_XAHCTRL1_BITS_PROM_MODE, promisc); + + return OK; +} + +/**************************************************************************** + * Name: at86rf23x_getpromisc + * + * Description: + * Check if the device is in promiscuous mode. + * + ****************************************************************************/ +static int at86rf23x_getpromisc(FAR struct ieee802154_dev_s *ieee, FAR bool *promisc) +{ + FAR struct at86rf23x_dev_s *dev = (struct at86rf23x_dev_s *)ieee; + + *promisc = at86rf23x_getregbits(dev->spi, RF23X_XAHCTRL1_BITS_PROM_MODE); + + return OK; +} + +/**************************************************************************** + * Name: at86rf23x_setdevmode + * + * Description: + * Check if the device is in promiscuous mode. + * + ****************************************************************************/ +static int at86rf23x_setdevmode(FAR struct ieee802154_dev_s *ieee, uint8_t mode) +{ + FAR struct at86rf23x_dev_s *dev = (struct at86rf23x_dev_s *)ieee; + + /* define dev mode */ + if(mode == IEEE802154_MODE_PANCOORD) + { + at86rf23x_setregbits(dev->spi, RF23X_CSMASEED1_IAMCOORD_BITS, 0x01); + } + else if(mode == IEEE802154_MODE_COORD) + { + /* ????? */ + } + else if(mode == IEEE802154_MODE_DEVICE) + { + at86rf23x_setregbits(dev->spi, RF23X_CSMASEED1_IAMCOORD_BITS, 0x00); + } + else + { + return -EINVAL; + } + + dev->devmode = mode; + + return OK; +} + +/**************************************************************************** + * Name: at86rf23x_getdevmode + * + * Description: + * get the device mode type of the radio. + * + ****************************************************************************/ +static int at86rf23x_getdevmode (FAR struct ieee802154_dev_s *ieee, FAR uint8_t *mode) +{ + FAR struct at86rf23x_dev_s *dev = (struct at86rf23x_dev_s *)ieee; + int val; + + val = at86rf23x_getregbits(dev->spi, RF23X_CSMASEED1_IAMCOORD_BITS); + + if(val == 1) + { + mode = IEEE802154_MODE_PANCOORD; + } + else + { + mode = IEEE802154_MODE_DEVICE; + } + + return OK; +} + +/**************************************************************************** + * Name: at86rf23x_settxpower + * + * Description: + * set the tx power attenuation or amplification + * + ****************************************************************************/ +static int at86rf23x_settxpower(FAR struct ieee802154_dev_s *ieee, int32_t txpwr) +{ + FAR struct at86rf23x_dev_s *dev = (struct at86rf23x_dev_s *)ieee; + + /* TODO: this needs alot of work to make sure all chips can share this function */ + + /* Right now we only set tx power to 0 */ + at86rf23x_setreg(dev->spi, RF23X_REG_TXPWR, RF23X_TXPWR_0); + + return OK; +} + +/**************************************************************************** + * Name: at86rf23x_gettxpower + * + * Description: + * get the tx power attenuation or amplification. + * + ****************************************************************************/ +static int at86rf23x_gettxpower(FAR struct ieee802154_dev_s *ieee, FAR int32_t *txpwr) +{ + /* TODO: this needs alot of work to make sure all chips can share this function */ + FAR struct at86rf23x_dev_s *dev = (struct at86rf23x_dev_s *)ieee; + uint8_t reg; + /* TODO: this needs alot of work to make sure all chips can share this function */ + + /* Right now we only get negative values */ + reg = at86rf23x_getreg(dev->spi, RF23X_REG_TXPWR); + + switch(reg) + { + case RF23X_TXPWR_POS_4: + *txpwr = 0; + break; + case RF23X_TXPWR_POS_3_7: + *txpwr = 0; + break; + case RF23X_TXPWR_POS_3_4: + *txpwr = 0; + break; + case RF23X_TXPWR_POS_3: + *txpwr = 0; + break; + case RF23X_TXPWR_POS_2_5: + *txpwr = 0; + break; + case RF23X_TXPWR_POS_2: + *txpwr = 0; + break; + case RF23X_TXPWR_POS_1: + *txpwr = 0; + break; + case RF23X_TXPWR_0: + *txpwr = 0; + break; + case RF23X_TXPWR_NEG_1: + *txpwr = 1000; + break; + case RF23X_TXPWR_NEG_2: + *txpwr = 2000; + break; + case RF23X_TXPWR_NEG_3: + *txpwr = 3000; + break; + case RF23X_TXPWR_NEG_4: + *txpwr = 4000; + break; + case RF23X_TXPWR_NEG_6: + *txpwr = 6000; + break; + case RF23X_TXPWR_NEG_8: + *txpwr = 8000; + break; + case RF23X_TXPWR_NEG_12: + *txpwr = 12000; + break; + case RF23X_TXPWR_NEG_17: + *txpwr = 17000; + break; + } + + return OK; +} + +/**************************************************************************** + * Name: at86rf23x_setcca + * + * Description: + * Configures if energy detection is used or carrier sense. The base + * measurement is configured here as well + * + * + ****************************************************************************/ +static int at86rf23x_setcca(FAR struct ieee802154_dev_s *ieee, FAR struct ieee802154_cca_s *cca) +{ + FAR struct at86rf23x_dev_s *dev = (struct at86rf23x_dev_s *)ieee; + + /* TODO: This doesn't fit the RF233 completely come back to this */ + + if (!cca->use_ed && !cca->use_cs) + { + return -EINVAL; + } + if (cca->use_cs && cca->csth > 0x0f) + { + return -EINVAL; + } + + if (cca->use_ed) + { + at86rf23x_setregbits(dev->spi, RF23X_CCA_BITS_MODE, RF23X_CCA_MODE_ED); + } + if (cca->use_cs) + { + at86rf23x_setregbits(dev->spi, RF23X_CCA_BITS_MODE, RF23X_CCA_MODE_CS); + } + + memcpy(&dev->cca, cca, sizeof(struct ieee802154_cca_s)); + + return OK; +} + +/**************************************************************************** + * Name: at86rf23x_getcca + * + * Description: + * Get CCA for ???: TODO: need to implement + * + ****************************************************************************/ +static int at86rf23x_getcca(FAR struct ieee802154_dev_s *ieee, FAR struct ieee802154_cca_s *cca) +{ + FAR struct at86rf23x_dev_s *dev = (struct at86rf23x_dev_s *)ieee; + +#warning at86rf23x_getcca not implemented. + + UNUSED(dev); + UNUSED(cca); + + return ERROR; +} + +/**************************************************************************** + * Name: at86rf23x_ioctl + * + * Description: + * Control operations for the radio. + * + ****************************************************************************/ +static int at86rf23x_ioctl(FAR struct ieee802154_dev_s *ieee, int cmd, unsigned long arg) +{ + FAR struct at86rf23x_dev_s *dev = (FAR struct at86rf23x_dev_s *)ieee; + switch(cmd) + { + case MAC854IORDUMP: return at86rf23x_regdump(dev); + default: return -EINVAL; + } +} +/**************************************************************************** + * Name: at86rf23x_energydetect + * + * Description: + * Perform energy detection scan. TODO: Need to implement. + * + ****************************************************************************/ +static int at86rf23x_energydetect(FAR struct ieee802154_dev_s *ieee, FAR uint8_t *energy) +{ + +#warning at86rf23x_energydetect not implemented. + + /* Not yet implemented */ + + return ERROR; +} + +/**************************************************************************** + * Name: at86rf23x_initialize + * + * Description: + * Initialize the radio. + * + ****************************************************************************/ +int at86rf23x_initialize(FAR struct at86rf23x_dev_s *dev) +{ + uint8_t part; + uint8_t version; + + at86rf23x_resetrf(dev); + + part = at86rf23x_getreg(dev->spi, RF23X_REG_PART); + version = at86rf23x_getreg(dev->spi, RF23X_REG_VERSION); + + dbg("Radio part: 0x%02x version: 0x%02x found\n", part, version); + + return OK; +} + +/**************************************************************************** + * Name: at86rf23x_resetrf + * + * Description: + * Hard Reset of the radio. The reset also brings the radio into the + * TRX_OFF state. + * + ****************************************************************************/ +static int at86rf23x_resetrf(FAR struct at86rf23x_dev_s *dev) +{ + FAR const struct at86rf23x_lower_s *lower = dev->lower; + uint8_t trx_status, retry_cnt = 0; + + /* Reset the radio */ + lower->reset(lower, 0); + lower->slptr(lower, 0); + + up_udelay(RF23X_TIME_RESET); + lower->reset(lower, 1); + + + /* Dummy read of IRQ register */ + at86rf23x_getreg(dev->spi, RF23X_REG_IRQ_STATUS); + + do + { + trx_status = at86rf23x_setTRXstate(dev, TRX_CMD_TRXOFF, true); + + if (retry_cnt == RF23X_MAX_RETRY_RESET_TO_TRX_OFF) + { + dbg("Reset of transceiver failed\n"); + return ERROR; + } + + retry_cnt++; + } while (trx_status != OK); + + return OK; +} + +/**************************************************************************** + * Name: at86rf23x_rxenable + * + * Description: + * puts the radio into RX mode and brings in the buffer to handle + * RX messages. + * + ****************************************************************************/ +static int at86rf23x_rxenable(FAR struct ieee802154_dev_s *ieee, bool state, + FAR struct ieee802154_packet_s *packet) +{ + FAR struct at86rf23x_dev_s *dev = (FAR struct at86rf23x_dev_s *)ieee; + + /* Set the radio to the receive state */ + return at86rf23x_setTRXstate(dev, TRX_CMD_RX_ON, false); + + /* Enable the RX IRQ */ + + /* TODO: + * I am not sure what to do here since the at86rf23x shares the + * irq with the tx finished. Better planning needs to be done on + * my end. + */ + + /* Set buffer to receive next packet */ + ieee->rxbuf = packet; +} + +/**************************************************************************** + * Name: at86rf23x_interrupt + * + * Description: + * Actual interrupt handler ran inside privileged space. + * + ****************************************************************************/ +static int at86rf23x_interrupt(int irq, FAR void *context) +{ + + /* To support multiple devices, + * retrieve the priv structure using the irq number */ + + register FAR struct at86rf23x_dev_s *dev = &g_at86rf23x_devices[0]; + + /* In complex environments, we cannot do SPI transfers from the interrupt + * handler because semaphores are probably used to lock the SPI bus. In + * this case, we will defer processing to the worker thread. This is also + * much kinder in the use of system resources and is, therefore, probably + * a good thing to do in any event. + */ + + DEBUGASSERT(work_available(&dev->irqwork)); + + /* Notice that further GPIO interrupts are disabled until the work is + * actually performed. This is to prevent overrun of the worker thread. + * Interrupts are re-enabled in enc_irqworker() when the work is completed. + */ + dev->lower->irq(dev->lower, NULL, FALSE); + // dev->lower->enable(dev->lower, FALSE); + + return work_queue(HPWORK, &dev->irqwork, at86rf23x_irqworker, (FAR void *)dev, 0); +} + +/**************************************************************************** + * Name: at86rf23x_regdump + * + * Description: + * Dumps all the RF23X radios registers from 00 - 2F there are a few other + * registers that don't get dumped but just fore the ease of code I left + * them out. + * + ****************************************************************************/ +static int at86rf23x_regdump(FAR struct at86rf23x_dev_s *dev) +{ + uint32_t i; + char buf[4+16*3+2+1]; + + int len=0; + printf("RF23X regs:\n"); + + for (i=0;i<0x30;i++) + { + /* First row and every 15 regs */ + if ((i & 0x0f) == 0) + { + len = sprintf(buf, "%02x: ",i&0xFF); + } + + /* print the register value */ + len += sprintf(buf+len, "%02x ", at86rf23x_getreg(dev->spi, i)); + + /* at the end of each 15 regs or end of rf233s regs and actually print dbg message*/ + if ((i&15)==15 || i == 0x2f) + { + sprintf(buf+len, "\n"); + printf("%s",buf); + } + } + + /* TODO: I have a few more regs that are not consecutive. Will print later */ + + return 0; +} + +/**************************************************************************** + * Name: at86rf23x_irqworker + * + * Description: + * Actual thread to handle the irq outside of privaleged mode. + * + ****************************************************************************/ +static void at86rf23x_irqworker(FAR void *arg) +{ + FAR struct at86rf23x_dev_s *dev = (FAR struct at86rf23x_dev_s *)arg; + + uint8_t irq_status = at86rf23x_getreg(dev->spi, RF23X_REG_IRQ_STATUS); + + vdbg("IRQ: 0x%02X\n", irq_status); + + if((irq_status & (1<<3)) != 0) + { + if((irq_status & (1<<2)) != 0) + { + at86rf23x_irqwork_rx(dev); + } + else + { + at86rf23x_irqwork_tx(dev); + } + } + else + { + dbg("Unknown IRQ Status: %d\n", irq_status); + + /* Re enable the IRQ even if we don't know how to handle previous status*/ + dev->lower->irq(dev->lower, NULL, true); + } +} + +/**************************************************************************** + * Name: at86rf23x_irqwork_rx + * + * Description: + * Misc/unofficial device controls. + * + ****************************************************************************/ +static void at86rf23x_irqwork_rx(FAR struct at86rf23x_dev_s *dev) +{ + uint8_t rx_len; + + vdbg("6LOWPAN:Rx IRQ\n"); + + rx_len = at86rf23x_readframe(dev->spi, dev->ieee.rxbuf->data); + + dev->ieee.rxbuf->len = rx_len; + dev->ieee.rxbuf->lqi = 0; + dev->ieee.rxbuf->rssi = 0; + + sem_post(&dev->ieee.rxsem); + /* + * TODO: + * Not to sure yet what I should do here. I will something + * soon. + */ + + /* Re enable the IRQ */ + dev->lower->irq(dev->lower, NULL, true); +} + +/**************************************************************************** + * Name: at86rf23x_irqwork_tx + * + * Description: + * Misc/unofficial device controls. + * + ****************************************************************************/ +static void at86rf23x_irqwork_tx(FAR struct at86rf23x_dev_s *dev) +{ + vdbg("6LOWPAN:Tx IRQ\n"); + + /* + * TODO: + * There needs to be more here but for now just alert the waiting + * thread. Maybe put it back into Rx mode + * + */ + + /* Re enable the IRQ */ + dev->lower->irq(dev->lower, NULL, true); + + sem_post(&dev->ieee.txsem); + + +} + +/**************************************************************************** + * Name: at86rf23x_transmit + * + * Description: + * transmission the packet. Send the packet to the radio and initiate the + * transmit process. Then block the function till we have a successful + * transmission + * + ****************************************************************************/ +static int at86rf23x_transmit(FAR struct ieee802154_dev_s *ieee, FAR struct ieee802154_packet_s *packet) +{ + FAR struct at86rf23x_dev_s *dev = (FAR struct at86rf23x_dev_s *)ieee; + /* + * TODO: + * A plan needs to be made on when we declare the transmission successful. + * 1. If the packet is sent + * 2. If we receive an ACK. + * 3. Where do we control the retry process? + */ + + if(at86rf23x_setTRXstate(dev, TRX_CMD_PLL_ON, false)) + { + at86rf23x_writeframe(dev->spi, packet->data, packet->len); + } + else + { + dbg("Transmit could not put the radio in a Tx state\n"); + return ERROR; + } + + /* put the thread that requested transfer to a waiting state */ + sem_wait(&dev->ieee.txsem); + /*TODO Verify that I want to stay in the PLL state or if I want to roll back to RX_ON */ + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: at86rf23x_init + * + * Description: + * Return an at86rf23x device for use by other drivers. + * + ****************************************************************************/ + +FAR struct ieee802154_dev_s *at86rf23x_init(FAR struct spi_dev_s *spi, FAR const struct at86rf23x_lower_s *lower) +{ + FAR struct at86rf23x_dev_s *dev; + struct ieee802154_cca_s cca; + + dev = &g_at86rf23x_devices[0]; + /* Attach the interface, lower driver, and devops */ + dev->spi = spi; + dev->lower = lower; + dev->ieee.ops = &at86rf23x_devops; + + /* attach irq */ + if (lower->irq(lower, at86rf23x_interrupt, false) != OK) + { + return NULL; + } + + sem_init(&dev->ieee.rxsem, 0, 0); + sem_init(&dev->ieee.txsem, 0, 0); + + /*Initialize device */ + at86rf23x_initialize(dev); + + /* Configure the desired IRQs of the devices */ + at86rf23x_setreg(dev->spi, RF23X_REG_IRQ_MASK, RF23X_IRQ_MASK_DEFAULT); + + /* Turn the PLL to the on state */ + at86rf23x_setTRXstate(dev, TRX_CMD_PLL_ON, false); + + + /*SEED value of the CSMA backoff algorithm. */ + + +#ifdef RF23X_ANTENNA_DIVERSITY + + /* Use antenna diversity */ + trx_bit_write(SR_ANT_CTRL, ANTENNA_DEFAULT); + trx_bit_write(SR_PDT_THRES, THRES_ANT_DIV_ENABLE); + trx_bit_write(SR_ANT_DIV_EN, ANT_DIV_ENABLE); + trx_bit_write(SR_ANT_EXT_SW_EN, ANT_EXT_SW_ENABLE); + +#endif + +#ifdef RF23X_TIMESTAMP + + /* Enable timestamp init code goes here */ + +#endif + +#ifdef RF23X_RF_FRONTEND_CTRL + + /* Init front end control code goes here */ + +#endif + /* Set the channel of the radio */ + at86rf23x_setchannel(&dev->ieee, 12); + + /* Configure the Pan id */ + // at86rf23x_setpanid (&dev->ieee, IEEE802154_PAN_DEFAULT); + /* Configure the Short Addr */ + // at86rf23x_setsaddr (&dev->ieee, IEEE802154_SADDR_UNSPEC); + /* Configure the IEEE Addr */ +// at86rf23x_seteaddr (&dev->ieee, IEEE802154_EADDR_UNSPEC); + + /* Default device params at86rf23x defaults to energy detect only */ + cca.use_ed = 1; + cca.use_cs = 0; + cca.edth = 0x60; /* CCA mode ED, no carrier sense, recommenced ED threshold -69 dBm */ + at86rf23x_setcca(&dev->ieee, &cca); + + + + /* Put the Device to RX ON Mode */ + // at86rf23x_setTRXstate(dev, TRX_CMD_RX_ON, false ); + + + /* Enable Radio IRQ */ + lower->irq(lower, at86rf23x_interrupt, true); + + return &dev->ieee; +} + diff --git a/drivers/wireless/ieee802154/at86rf23x.h b/drivers/wireless/ieee802154/at86rf23x.h new file mode 100644 index 00000000000..51c96ced3c0 --- /dev/null +++ b/drivers/wireless/ieee802154/at86rf23x.h @@ -0,0 +1,204 @@ +/* + * at86rf23x.h + * + * Created on: Feb 24, 2016 + * Author: poppe + */ + +#ifndef APPS_EXTERNAL_IEEE_AT86RF23X_H_ +#define APPS_EXTERNAL_IEEE_AT86RF23X_H_ + +#define RF23X_SPI_REG_READ 0x80 +#define RF23X_SPI_REG_WRITE 0xC0 +#define RF23X_SPI_FRAME_WRITE 0x60 +#define RF23X_SPI_FRAME_READ 0x20 +#define RF23X_SPI_SRAM_READ 0x00 +#define RF23X_SPI_SRAM_WRITE 0x40 + +/* us Times Constants for the RF233 */ +#define RF23X_TIME_RESET_BOOT 510 +#define RF23X_TIME_FORCE_TRXOFF 100 +#define RF23X_TIME_P_ON_TO_TRXOFF 510 +#define RF23X_TIME_SLEEP_TO_TRXOFF 1200 +#define RF23X_TIME_RESET 6 +#define RF23X_TIME_ED_MEASUREMENT 140 +#define RF23X_TIME_CCA 140 +#define RF23X_TIME_PLL_LOCK 150 +#define RF23X_TIME_FTN_TUNNING 25 +#define RF23X_TIME_NOCLK_TO_WAKE 6 +#define RF23X_TIME_CMD_FORCE_TRX_OFF 1 +#define RF23X_TIME_TRXOFF_TO_PLL 180 +#define RF23X_TIME_TRANSITION_PLL_ACTIVE 1 +#define RF23X_TIME_TRXOFF_TO_SLEEP 1200 + +#define RF23X_MAX_RETRY_RESET_TO_TRX_OFF 5 + + +#define RF23X_REG_TRXSTATUS 0x01 +#define RF23X_REG_TRXSTATE 0x02 +#define RF23X_REG_TRXCTRL0 0x03 +#define RF23X_REG_TRXCTRL1 0x04 +#define RF23X_REG_TXPWR 0x05 +#define RF23X_REG_RSSI 0x06 +#define RF23X_REG_EDLEVEL 0x07 +#define RF23X_REG_CCA 0x08 +#define RF23X_REG_THRES 0x09 +#define RF23X_REG_RXCTRL 0x0a +#define RF23X_REG_SFD 0x0b +#define RF23X_REG_TRXCTRL2 0x0c +#define RF23X_REG_ANT_DIV 0x0d +#define RF23X_REG_IRQ_MASK 0x0e +#define RF23X_REG_IRQ_STATUS 0x0f +#define RF23X_REG_VREG_CTRL 0x10 +#define RF23X_REG_BATMON 0x11 +#define RF23X_REG_XOSC_CTRL 0x12 +#define RF23X_REG_CCCTRL0 0x13 +#define RF23X_REG_CCCTRL1 0x14 +#define RF23X_REG_RXSYN 0x15 +#define RF23X_REG_TRXRPC 0x16 +#define RF23X_REG_XAHCTRL1 0x17 +#define RF23X_REG_FTNCTRL 0x18 +#define RF23X_REG_XAHCTRL2 0x19 +#define RF23X_REG_PLLCF 0x1a +#define RF23X_REG_PLLDCU 0x1b +#define RF23X_REG_PART 0x1c +#define RF23X_REG_VERSION 0x1d +#define RF23X_REG_MANID0 0x1e +#define RF23X_REG_MANID1 0x1f +#define RF23X_REG_SADDR0 0x20 +#define RF23X_REG_SADDR1 0x21 +#define RF23X_REG_PANID0 0x22 +#define RF23X_REG_PANID1 0x23 +#define RF23X_REG_IEEEADDR0 0x24 +#define RF23X_REG_IEEEADDR1 0x25 +#define RF23X_REG_IEEEADDR2 0x26 +#define RF23X_REG_IEEEADDR3 0x27 +#define RF23X_REG_IEEEADDR4 0x28 +#define RF23X_REG_IEEEADDR5 0x29 +#define RF23X_REG_IEEEADDR6 0x2a +#define RF23X_REG_IEEEADDR7 0x2b +#define RF23X_REG_XAHCTRL0 0x2c +#define RF23X_REG_CSMASEED0 0x2d +#define RF23X_REG_CSMASEED1 0x2e +#define RF23X_REG_CSMABE 0x2f +#define RF23X_REG_TSTCTRLDIGI 0x36 +#define RF23X_REG_TSTAGC 0x3c +#define RF23X_REG_SDM 0x3d +#define RF23X_REG_PHYTXTIME 0x3b +#define RF23X_REG_PHYPMUVALUE 0x3b + + +#define RF23X_TRXSTATUS_POS 0 +#define RF23X_TRXSTATUS_MASK 0x1f +#define RF23X_TRXSTATUS_STATUS RF23X_REG_TRXSTATUS, RF23X_TRXSTATUS_POS, RF23X_TRXSTATUS_MASK + +#define RF23X_TRXCMD_POS 0 +#define RF23X_TRXCMD_MASK 0x1f +#define RF23X_TRXCMD_STATE RF23X_REG_TRXSTATE, RF23X_TRXCMD_POS, RF23X_TRXCMD_MASK + + +#define RF23X_TXPWR_POS_4 0x00 +#define RF23X_TXPWR_POS_3_7 0x01 +#define RF23X_TXPWR_POS_3_4 0x02 +#define RF23X_TXPWR_POS_3 0x03 +#define RF23X_TXPWR_POS_2_5 0x04 +#define RF23X_TXPWR_POS_2 0x05 +#define RF23X_TXPWR_POS_1 0x06 +#define RF23X_TXPWR_0 0x07 +#define RF23X_TXPWR_NEG_1 0x08 +#define RF23X_TXPWR_NEG_2 0x09 +#define RF23X_TXPWR_NEG_3 0x0a +#define RF23X_TXPWR_NEG_4 0x0b +#define RF23X_TXPWR_NEG_6 0x0c +#define RF23X_TXPWR_NEG_8 0x0d +#define RF23X_TXPWR_NEG_12 0x0e +#define RF23X_TXPWR_NEG_17 0x0f + +/**************************************************************************** + * CCA_STATUS + ****************************************************************************/ +#define RF23X_CCA_MODE_CS_OR_ED 0x00 +#define RF23X_CCA_MODE_ED 0x01 +#define RF23X_CCA_MODE_CS 0x02 +#define RF23X_CCA_MODE_CS_AND_ED 0x03 + +#define RF23X_CCA_CHANNEL_POS 0 +#define RF23X_CCA_CHANNEL_MASK 0x1f +#define RF23X_CCA_BITS_CHANNEL RF23X_REG_CCA, RF23X_CCA_CHANNEL_POS, RF23X_CCA_CHANNEL_MASK +#define RF23X_CCA_MODE_POS 5 +#define RF23X_CCA_MODE_MASK 0x03 +#define RF23X_CCA_BITS_MODE RF23X_REG_CCA, RF23X_CCA_MODE_POS, RF23X_CCA_MODE_MASK + + +/**************************************************************************** + * XAH CTRL 1 + ****************************************************************************/ +#define RF23X_XAHCTRL1_PROM_MODE_POS 1 +#define RF23X_XAHCTRL1_PROM_MODE_MASK 0x01 +#define RF23X_XAHCTRL1_BITS_PROM_MODE RF23X_REG_XAHCTRL1, RF23X_XAHCTRL1_PROM_MODE_POS, RF23X_XAHCTRL1_PROM_MODE_MASK + +/**************************************************************************** + * CSMA SEED 0 + ****************************************************************************/ + +/**************************************************************************** + * CSMA SEED 1 + ****************************************************************************/ +#define RF23X_CSMASEED1_IAMCOORD_POS 3 +#define RF23X_CSMASEED1_IAMCOORD_MASK 0x1 +#define RF23X_CSMASEED1_IAMCOORD_BITS RF23X_REG_CSMASEED1, RF23X_CSMASEED1_IAMCOORD_POS, RF23X_CSMASEED1_IAMCOORD_MASK + +#define RF23X_CSMASEED1_AACK_DIS_ACK_POS +#define RF23X_CSMASEED1_AACK_SET_PD_POS +#define RF23X_CSMASEED1_AACK_FVN_MODE_POS +#define RF23X_CSMASEED1_ + + +/**************************************************************************** + * TRX Status + ****************************************************************************/ +#define TRX_STATUS_PON 0x00 +#define TRX_STATUS_BUSYRX 0x01 +#define TRX_STATUS_BUSYTX 0x02 +#define TRX_STATUS_RXON 0x06 +#define TRX_STATUS_TRXOFF 0x08 +#define TRX_STATUS_PLLON 0x09 +#define TRX_STATUS_SLEEP 0x0f +#define TRX_STATUS_DEEPSLEEP 0x10 +#define TRX_STATUS_BUSYRXACK 0x11 +#define TRX_STATUS_BUSYTXARET 0x12 +#define TRX_STATUS_RXAACKON 0x16 +#define TRX_STATUS_TXARETON 0x19 +#define TRX_STATUS_STATEINTRANS 0x1f + +/**************************************************************************** + * TRX Command + ****************************************************************************/ +#define TRX_CMD_NOP 0x00 +#define TRX_CMD_TX 0x02 +#define TRX_CMD_FORCETRXOFF 0x03 +#define TRX_CMD_FORCE_PLLON 0x04 +#define TRX_CMD_RX_ON 0x06 +#define TRX_CMD_TRXOFF 0x08 +#define TRX_CMD_PLL_ON 0x09 +#define TRX_CMD_PREP_DEEPSLEEP 0x10 +#define TRX_CMD_RX_AACK_ON 0x16 +#define TRX_CMD_TX_ARET_ON 0x19 + + +/**************************************************************************** + * IRQ MASK 0x0E + ****************************************************************************/ +#define RF23X_IRQ_MASK_LOCK_PLL (1<<0) +#define RF23X_IRQ_MASK_UNLOCK_PLL (1<<1) +#define RF23X_IRQ_MASK_RX_START (1<<2) +#define RF23X_IRQ_MASK_TRX_END (1<<3) +#define RF23X_IRQ_MASK_CCA_ED_DONE (1<<4) +#define RF23X_IRQ_MASK_AMI (1<<5) +#define RF23X_IRQ_MASK_TRX_UR (1<<6) +#define RF23X_IRQ_MASK_BAT_LOW (1<<7) + +#define RF23X_IRQ_MASK_DEFAULT (RF23X_IRQ_MASK_TRX_END) + + +#endif /* APPS_EXTERNAL_IEEE_AT86RF23X_H_ */ diff --git a/drivers/wireless/ieee802154/mrf24j40.c b/drivers/wireless/ieee802154/mrf24j40.c index fa7cfd815d3..cc831fd7830 100644 --- a/drivers/wireless/ieee802154/mrf24j40.c +++ b/drivers/wireless/ieee802154/mrf24j40.c @@ -91,15 +91,53 @@ #define MRF24J40_PA_ED 2 #define MRF24J40_PA_SLEEP 3 +/* IEEE 802.15.4 frame specifics */ + +/* Security Enabled */ + +#define IEEE802154_SEC_OFF 0x00 +#define IEEE802154_SEC_ON 0x08 + +/* Flags */ + +#define IEEE802154_PEND 0x10 +#define IEEE802154_ACK_REQ 0x20 +#define IEEE802154_INTRA 0x40 + +/* Dest Addressing modes */ + +#define IEEE802154_DADDR_NONE 0x00 +#define IEEE802154_DADDR_SHORT 0x08 +#define IEEE802154_DADDR_EXT 0x0A + +/* Src Addressing modes */ + +#define IEEE802154_SADDR_NONE 0x00 +#define IEEE802154_SADDR_SHORT 0x80 +#define IEEE802154_SADDR_EXT 0xA0 + +/* Frame control field masks, 2 bytes + * Seee IEEE 802.15.4/2003 7.2.1.1 page 112 + */ + +#define IEEE802154_FC1_FTYPE 0x03 /* Frame type, bits 0-2 */ +#define IEEE802154_FC1_SEC 0x08 /* Security Enabled, bit 3 */ +#define IEEE802154_FC1_PEND 0x10 /* Frame pending, bit 4 */ +#define IEEE802154_FC1_ACKREQ 0x20 /* Acknowledge request, bit 5 */ +#define IEEE802154_FC1_INTRA 0x40 /* Intra PAN, bit 6 */ +#define IEEE802154_FC2_DADDR 0x0C /* Dest addressing mode, bits 10-11 */ +#define IEEE802154_FC2_VERSION 0x30 /* Source addressing mode, bits 12-13 */ +#define IEEE802154_FC2_SADDR 0xC0 /* Source addressing mode, bits 14-15 */ + /**************************************************************************** * Private Types ****************************************************************************/ /* A MRF24J40 device instance */ -struct mrf24j40_dev_s +struct mrf24j40_radio_s { - struct ieee802154_dev_s ieee; /* The public device instance */ + struct ieee802154_radio_s ieee; /* The public device instance */ FAR struct spi_dev_s *spi; /* Saved SPI interface instance */ struct work_s irqwork; /* Interrupt continuation work queue support */ FAR const struct mrf24j40_lower_s *lower; /* Low-level MCU-specific support */ @@ -126,39 +164,39 @@ static void mrf24j40_lock (FAR struct spi_dev_s *spi); static void mrf24j40_setreg (FAR struct spi_dev_s *spi, uint32_t addr, uint8_t val); static uint8_t mrf24j40_getreg (FAR struct spi_dev_s *spi, uint32_t addr); -static int mrf24j40_resetrfsm (FAR struct mrf24j40_dev_s *dev); -static int mrf24j40_pacontrol (FAR struct mrf24j40_dev_s *dev, int mode); -static int mrf24j40_initialize(FAR struct mrf24j40_dev_s *dev); +static int mrf24j40_resetrfsm (FAR struct mrf24j40_radio_s *dev); +static int mrf24j40_pacontrol (FAR struct mrf24j40_radio_s *dev, int mode); +static int mrf24j40_initialize(FAR struct mrf24j40_radio_s *dev); -static int mrf24j40_setrxmode (FAR struct mrf24j40_dev_s *dev, int mode); -static int mrf24j40_regdump (FAR struct mrf24j40_dev_s *dev); -static void mrf24j40_irqwork_rx(FAR struct mrf24j40_dev_s *dev); -static void mrf24j40_irqwork_tx(FAR struct mrf24j40_dev_s *dev); +static int mrf24j40_setrxmode (FAR struct mrf24j40_radio_s *dev, int mode); +static int mrf24j40_regdump (FAR struct mrf24j40_radio_s *dev); +static void mrf24j40_irqwork_rx(FAR struct mrf24j40_radio_s *dev); +static void mrf24j40_irqwork_tx(FAR struct mrf24j40_radio_s *dev); static void mrf24j40_irqworker (FAR void *arg); static int mrf24j40_interrupt (int irq, FAR void *context); /* Driver operations */ -static int mrf24j40_setchannel (FAR struct ieee802154_dev_s *ieee, uint8_t chan); -static int mrf24j40_getchannel (FAR struct ieee802154_dev_s *ieee, FAR uint8_t *chan); -static int mrf24j40_setpanid (FAR struct ieee802154_dev_s *ieee, uint16_t panid); -static int mrf24j40_getpanid (FAR struct ieee802154_dev_s *ieee, FAR uint16_t *panid); -static int mrf24j40_setsaddr (FAR struct ieee802154_dev_s *ieee, uint16_t saddr); -static int mrf24j40_getsaddr (FAR struct ieee802154_dev_s *ieee, FAR uint16_t *saddr); -static int mrf24j40_seteaddr (FAR struct ieee802154_dev_s *ieee, FAR uint8_t *eaddr); -static int mrf24j40_geteaddr (FAR struct ieee802154_dev_s *ieee, FAR uint8_t *eaddr); -static int mrf24j40_setpromisc (FAR struct ieee802154_dev_s *ieee, bool promisc); -static int mrf24j40_getpromisc (FAR struct ieee802154_dev_s *ieee, FAR bool *promisc); -static int mrf24j40_setdevmode (FAR struct ieee802154_dev_s *ieee, uint8_t mode); -static int mrf24j40_getdevmode (FAR struct ieee802154_dev_s *ieee, FAR uint8_t *mode); -static int mrf24j40_settxpower (FAR struct ieee802154_dev_s *ieee, int32_t txpwr); -static int mrf24j40_gettxpower (FAR struct ieee802154_dev_s *ieee, FAR int32_t *txpwr); -static int mrf24j40_setcca (FAR struct ieee802154_dev_s *ieee, FAR struct ieee802154_cca_s *cca); -static int mrf24j40_getcca (FAR struct ieee802154_dev_s *ieee, FAR struct ieee802154_cca_s *cca); -static int mrf24j40_ioctl (FAR struct ieee802154_dev_s *ieee, int cmd, unsigned long arg); -static int mrf24j40_energydetect(FAR struct ieee802154_dev_s *ieee, FAR uint8_t *energy); -static int mrf24j40_rxenable (FAR struct ieee802154_dev_s *ieee, bool state, FAR struct ieee802154_packet_s *packet); -static int mrf24j40_transmit (FAR struct ieee802154_dev_s *ieee, FAR struct ieee802154_packet_s *packet); +static int mrf24j40_setchannel (FAR struct ieee802154_radio_s *ieee, uint8_t chan); +static int mrf24j40_getchannel (FAR struct ieee802154_radio_s *ieee, FAR uint8_t *chan); +static int mrf24j40_setpanid (FAR struct ieee802154_radio_s *ieee, uint16_t panid); +static int mrf24j40_getpanid (FAR struct ieee802154_radio_s *ieee, FAR uint16_t *panid); +static int mrf24j40_setsaddr (FAR struct ieee802154_radio_s *ieee, uint16_t saddr); +static int mrf24j40_getsaddr (FAR struct ieee802154_radio_s *ieee, FAR uint16_t *saddr); +static int mrf24j40_seteaddr (FAR struct ieee802154_radio_s *ieee, FAR uint8_t *eaddr); +static int mrf24j40_geteaddr (FAR struct ieee802154_radio_s *ieee, FAR uint8_t *eaddr); +static int mrf24j40_setpromisc (FAR struct ieee802154_radio_s *ieee, bool promisc); +static int mrf24j40_getpromisc (FAR struct ieee802154_radio_s *ieee, FAR bool *promisc); +static int mrf24j40_setdevmode (FAR struct ieee802154_radio_s *ieee, uint8_t mode); +static int mrf24j40_getdevmode (FAR struct ieee802154_radio_s *ieee, FAR uint8_t *mode); +static int mrf24j40_settxpower (FAR struct ieee802154_radio_s *ieee, int32_t txpwr); +static int mrf24j40_gettxpower (FAR struct ieee802154_radio_s *ieee, FAR int32_t *txpwr); +static int mrf24j40_setcca (FAR struct ieee802154_radio_s *ieee, FAR struct ieee802154_cca_s *cca); +static int mrf24j40_getcca (FAR struct ieee802154_radio_s *ieee, FAR struct ieee802154_cca_s *cca); +static int mrf24j40_ioctl (FAR struct ieee802154_radio_s *ieee, int cmd, unsigned long arg); +static int mrf24j40_energydetect(FAR struct ieee802154_radio_s *ieee, FAR uint8_t *energy); +static int mrf24j40_rxenable (FAR struct ieee802154_radio_s *ieee, bool state, FAR struct ieee802154_packet_s *packet); +static int mrf24j40_transmit (FAR struct ieee802154_radio_s *ieee, FAR struct ieee802154_packet_s *packet); /* These are pointers to ALL registered MRF24J40 devices. * This table is used during irqs to find the context @@ -167,9 +205,9 @@ static int mrf24j40_transmit (FAR struct ieee802154_dev_s *ieee, FAR stru * using the IRQ number. See the ENC28J60 or CC3000 drivers for reference. */ -static struct mrf24j40_dev_s g_mrf24j40_devices[1]; +static struct mrf24j40_radio_s g_mrf24j40_devices[1]; -static const struct ieee802154_devops_s mrf24j40_devops = +static const struct ieee802154_radioops_s mrf24j40_devops = { mrf24j40_setchannel, mrf24j40_getchannel, mrf24j40_setpanid , mrf24j40_getpanid, @@ -316,7 +354,7 @@ static uint8_t mrf24j40_getreg(FAR struct spi_dev_s *spi, uint32_t addr) * ****************************************************************************/ -static int mrf24j40_resetrfsm(FAR struct mrf24j40_dev_s *dev) +static int mrf24j40_resetrfsm(FAR struct mrf24j40_radio_s *dev) { uint8_t reg; @@ -341,7 +379,7 @@ static int mrf24j40_resetrfsm(FAR struct mrf24j40_dev_s *dev) * GPIO 3: PA power enable (not required on MB) ****************************************************************************/ -static int mrf24j40_pacontrol(FAR struct mrf24j40_dev_s *dev, int mode) +static int mrf24j40_pacontrol(FAR struct mrf24j40_radio_s *dev, int mode) { if (!dev->paenabled) { @@ -383,7 +421,7 @@ static int mrf24j40_pacontrol(FAR struct mrf24j40_dev_s *dev, int mode) * ****************************************************************************/ -static int mrf24j40_initialize(FAR struct mrf24j40_dev_s *dev) +static int mrf24j40_initialize(FAR struct mrf24j40_radio_s *dev) { /* Software reset */ @@ -415,7 +453,7 @@ static int mrf24j40_initialize(FAR struct mrf24j40_dev_s *dev) * ****************************************************************************/ -static int mrf24j40_setrxmode(FAR struct mrf24j40_dev_s *dev, int mode) +static int mrf24j40_setrxmode(FAR struct mrf24j40_radio_s *dev, int mode) { uint8_t reg; if (mode < MRF24J40_RXMODE_NORMAL || mode > MRF24J40_RXMODE_NOCRC) @@ -463,10 +501,10 @@ static int mrf24j40_setrxmode(FAR struct mrf24j40_dev_s *dev, int mode) * ****************************************************************************/ -static int mrf24j40_setchannel(FAR struct ieee802154_dev_s *ieee, +static int mrf24j40_setchannel(FAR struct ieee802154_radio_s *ieee, uint8_t chan) { - FAR struct mrf24j40_dev_s *dev = (FAR struct mrf24j40_dev_s *)ieee; + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; if (chan<11 || chan>26) { @@ -498,10 +536,10 @@ static int mrf24j40_setchannel(FAR struct ieee802154_dev_s *ieee, * ****************************************************************************/ -static int mrf24j40_getchannel(FAR struct ieee802154_dev_s *ieee, +static int mrf24j40_getchannel(FAR struct ieee802154_radio_s *ieee, FAR uint8_t *chan) { - FAR struct mrf24j40_dev_s *dev = (FAR struct mrf24j40_dev_s *)ieee; + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; *chan = dev->channel; @@ -516,10 +554,10 @@ static int mrf24j40_getchannel(FAR struct ieee802154_dev_s *ieee, * ****************************************************************************/ -static int mrf24j40_setpanid(FAR struct ieee802154_dev_s *ieee, +static int mrf24j40_setpanid(FAR struct ieee802154_radio_s *ieee, uint16_t panid) { - FAR struct mrf24j40_dev_s *dev = (FAR struct mrf24j40_dev_s *)ieee; + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; mrf24j40_setreg(dev->spi, MRF24J40_PANIDH, (uint8_t)(panid>>8)); mrf24j40_setreg(dev->spi, MRF24J40_PANIDL, (uint8_t)(panid&0xFF)); @@ -538,10 +576,10 @@ static int mrf24j40_setpanid(FAR struct ieee802154_dev_s *ieee, * ****************************************************************************/ -static int mrf24j40_getpanid(FAR struct ieee802154_dev_s *ieee, +static int mrf24j40_getpanid(FAR struct ieee802154_radio_s *ieee, FAR uint16_t *panid) { - FAR struct mrf24j40_dev_s *dev = (FAR struct mrf24j40_dev_s *)ieee; + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; *panid = dev->panid; @@ -558,10 +596,10 @@ static int mrf24j40_getpanid(FAR struct ieee802154_dev_s *ieee, * ****************************************************************************/ -static int mrf24j40_setsaddr(FAR struct ieee802154_dev_s *ieee, +static int mrf24j40_setsaddr(FAR struct ieee802154_radio_s *ieee, uint16_t saddr) { - FAR struct mrf24j40_dev_s *dev = (FAR struct mrf24j40_dev_s *)ieee; + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; mrf24j40_setreg(dev->spi, MRF24J40_SADRH, (uint8_t)(saddr>>8)); mrf24j40_setreg(dev->spi, MRF24J40_SADRL, (uint8_t)(saddr&0xFF)); @@ -579,10 +617,10 @@ static int mrf24j40_setsaddr(FAR struct ieee802154_dev_s *ieee, * ****************************************************************************/ -static int mrf24j40_getsaddr(FAR struct ieee802154_dev_s *ieee, +static int mrf24j40_getsaddr(FAR struct ieee802154_radio_s *ieee, FAR uint16_t *saddr) { - FAR struct mrf24j40_dev_s *dev = (FAR struct mrf24j40_dev_s *)ieee; + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; *saddr = dev->saddr; @@ -598,10 +636,10 @@ static int mrf24j40_getsaddr(FAR struct ieee802154_dev_s *ieee, * ****************************************************************************/ -static int mrf24j40_seteaddr(FAR struct ieee802154_dev_s *ieee, +static int mrf24j40_seteaddr(FAR struct ieee802154_radio_s *ieee, FAR uint8_t *eaddr) { - FAR struct mrf24j40_dev_s *dev = (FAR struct mrf24j40_dev_s *)ieee; + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; int i; @@ -622,10 +660,10 @@ static int mrf24j40_seteaddr(FAR struct ieee802154_dev_s *ieee, * ****************************************************************************/ -static int mrf24j40_geteaddr(FAR struct ieee802154_dev_s *ieee, +static int mrf24j40_geteaddr(FAR struct ieee802154_radio_s *ieee, FAR uint8_t *eaddr) { - FAR struct mrf24j40_dev_s *dev = (FAR struct mrf24j40_dev_s *)ieee; + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; memcpy(eaddr, dev->eaddr, 8); @@ -641,10 +679,10 @@ static int mrf24j40_geteaddr(FAR struct ieee802154_dev_s *ieee, * ****************************************************************************/ -static int mrf24j40_setpromisc(FAR struct ieee802154_dev_s *ieee, +static int mrf24j40_setpromisc(FAR struct ieee802154_radio_s *ieee, bool promisc) { - FAR struct mrf24j40_dev_s *dev = (FAR struct mrf24j40_dev_s *)ieee; + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; return mrf24j40_setrxmode(dev, promisc ? MRF24J40_RXMODE_PROMISC : MRF24J40_RXMODE_NORMAL); @@ -658,10 +696,10 @@ static int mrf24j40_setpromisc(FAR struct ieee802154_dev_s *ieee, * ****************************************************************************/ -static int mrf24j40_getpromisc(FAR struct ieee802154_dev_s *ieee, +static int mrf24j40_getpromisc(FAR struct ieee802154_radio_s *ieee, FAR bool *promisc) { - FAR struct mrf24j40_dev_s *dev = (FAR struct mrf24j40_dev_s *)ieee; + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; *promisc = (dev->rxmode == MRF24J40_RXMODE_PROMISC); @@ -676,10 +714,10 @@ static int mrf24j40_getpromisc(FAR struct ieee802154_dev_s *ieee, * ****************************************************************************/ -static int mrf24j40_setdevmode(FAR struct ieee802154_dev_s *ieee, +static int mrf24j40_setdevmode(FAR struct ieee802154_radio_s *ieee, uint8_t mode) { - FAR struct mrf24j40_dev_s *dev = (FAR struct mrf24j40_dev_s *)ieee; + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; int ret = OK; uint8_t reg; @@ -728,10 +766,10 @@ static int mrf24j40_setdevmode(FAR struct ieee802154_dev_s *ieee, * ****************************************************************************/ -static int mrf24j40_getdevmode(FAR struct ieee802154_dev_s *ieee, +static int mrf24j40_getdevmode(FAR struct ieee802154_radio_s *ieee, FAR uint8_t *mode) { - FAR struct mrf24j40_dev_s *dev = (FAR struct mrf24j40_dev_s *)ieee; + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; *mode = dev->devmode; @@ -748,10 +786,10 @@ static int mrf24j40_getdevmode(FAR struct ieee802154_dev_s *ieee, * ****************************************************************************/ -static int mrf24j40_settxpower(FAR struct ieee802154_dev_s *ieee, +static int mrf24j40_settxpower(FAR struct ieee802154_radio_s *ieee, int32_t txpwr) { - FAR struct mrf24j40_dev_s *dev = (FAR struct mrf24j40_dev_s *)ieee; + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; uint8_t reg; int save_txpwr = txpwr; @@ -809,10 +847,10 @@ static int mrf24j40_settxpower(FAR struct ieee802154_dev_s *ieee, * ****************************************************************************/ -static int mrf24j40_gettxpower(FAR struct ieee802154_dev_s *ieee, +static int mrf24j40_gettxpower(FAR struct ieee802154_radio_s *ieee, FAR int32_t *txpwr) { - FAR struct mrf24j40_dev_s *dev = (FAR struct mrf24j40_dev_s *)ieee; + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; *txpwr = dev->txpower; @@ -827,10 +865,10 @@ static int mrf24j40_gettxpower(FAR struct ieee802154_dev_s *ieee, * ****************************************************************************/ -static int mrf24j40_setcca(FAR struct ieee802154_dev_s *ieee, +static int mrf24j40_setcca(FAR struct ieee802154_radio_s *ieee, FAR struct ieee802154_cca_s *cca) { - FAR struct mrf24j40_dev_s *dev = (FAR struct mrf24j40_dev_s *)ieee; + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; uint8_t mode; if (!cca->use_ed && !cca->use_cs) @@ -873,10 +911,10 @@ static int mrf24j40_setcca(FAR struct ieee802154_dev_s *ieee, * ****************************************************************************/ -static int mrf24j40_getcca(FAR struct ieee802154_dev_s *ieee, +static int mrf24j40_getcca(FAR struct ieee802154_radio_s *ieee, FAR struct ieee802154_cca_s *cca) { - FAR struct mrf24j40_dev_s *dev = (FAR struct mrf24j40_dev_s *)ieee; + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; memcpy(cca, &dev->cca, sizeof(struct ieee802154_cca_s)); @@ -891,7 +929,7 @@ static int mrf24j40_getcca(FAR struct ieee802154_dev_s *ieee, * ****************************************************************************/ -static int mrf24j40_regdump(FAR struct mrf24j40_dev_s *dev) +static int mrf24j40_regdump(FAR struct mrf24j40_radio_s *dev) { uint32_t i; char buf[4+16*3+2+1]; @@ -941,10 +979,10 @@ static int mrf24j40_regdump(FAR struct mrf24j40_dev_s *dev) * ****************************************************************************/ -static int mrf24j40_ioctl(FAR struct ieee802154_dev_s *ieee, int cmd, +static int mrf24j40_ioctl(FAR struct ieee802154_radio_s *ieee, int cmd, unsigned long arg) { - FAR struct mrf24j40_dev_s *dev = (FAR struct mrf24j40_dev_s *)ieee; + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; switch(cmd) { @@ -968,10 +1006,10 @@ static int mrf24j40_ioctl(FAR struct ieee802154_dev_s *ieee, int cmd, * ****************************************************************************/ -static int mrf24j40_energydetect(FAR struct ieee802154_dev_s *ieee, +static int mrf24j40_energydetect(FAR struct ieee802154_radio_s *ieee, FAR uint8_t *energy) { - FAR struct mrf24j40_dev_s *dev = (FAR struct mrf24j40_dev_s *)ieee; + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; uint8_t reg; /* Manually enable the LNA*/ @@ -1019,9 +1057,9 @@ static int mrf24j40_energydetect(FAR struct ieee802154_dev_s *ieee, * ****************************************************************************/ -static int mrf24j40_transmit(FAR struct ieee802154_dev_s *ieee, FAR struct ieee802154_packet_s *packet) +static int mrf24j40_transmit(FAR struct ieee802154_radio_s *ieee, FAR struct ieee802154_packet_s *packet) { - FAR struct mrf24j40_dev_s *dev = (FAR struct mrf24j40_dev_s *)ieee; + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; uint32_t addr; uint8_t reg; int ret; @@ -1030,7 +1068,7 @@ static int mrf24j40_transmit(FAR struct ieee802154_dev_s *ieee, FAR struct ieee8 mrf24j40_pacontrol(dev, MRF24J40_PA_AUTO); - addr = 0x80000000; + addr = MRF24J40_TXBUF_BASE; /* Enable tx int */ @@ -1118,22 +1156,19 @@ static int mrf24j40_transmit(FAR struct ieee802154_dev_s *ieee, FAR struct ieee8 * ****************************************************************************/ -static void mrf24j40_irqwork_tx(FAR struct mrf24j40_dev_s *dev) +static void mrf24j40_irqwork_tx(FAR struct mrf24j40_radio_s *dev) { uint8_t txstat; uint8_t reg; txstat = mrf24j40_getreg(dev->spi, MRF24J40_TXSTAT); - /* 1 means it failed, we want 1 to mean it worked. - * tx_ok = !(tmp & ~(1 << TXNSTAT)); - * retries = tmp >> 6; - * channel_busy = (tmp & (1 << CCAFAIL)); - */ + reg = mrf24j40_getreg(dev->spi, MRF24J40_TXSTAT); - //dbg("TXSTAT%02X!\n", txstat); -#warning TODO report errors - UNUSED(txstat); + /* 1 means it failed, we want 1 to mean it worked. */ + dev->ieee.txok = (reg & MRF24J40_TXSTAT_TXNSTAT) != MRF24J40_TXSTAT_TXNSTAT; + dev->ieee.txretries = (reg & MRF24J40_TXSTAT_X_MASK) >> MRF24J40_TXSTAT_X_SHIFT; + dev->ieee.txbusy = (reg & MRF24J40_TXSTAT_CCAFAIL) == MRF24J40_TXSTAT_CCAFAIL; /* Disable tx int */ @@ -1147,17 +1182,17 @@ static void mrf24j40_irqwork_tx(FAR struct mrf24j40_dev_s *dev) } /**************************************************************************** - * Name: mrf24j40_enablerx + * Name: mrf24j40_rxenable * * Description: * Enable reception of a packet. The interrupt will signal the rx semaphore. * ****************************************************************************/ -static int mrf24j40_rxenable(FAR struct ieee802154_dev_s *ieee, bool state, +static int mrf24j40_rxenable(FAR struct ieee802154_radio_s *ieee, bool state, FAR struct ieee802154_packet_s *packet) { - FAR struct mrf24j40_dev_s *dev = (FAR struct mrf24j40_dev_s *)ieee; + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; uint8_t reg; if (state) @@ -1187,7 +1222,7 @@ static int mrf24j40_rxenable(FAR struct ieee802154_dev_s *ieee, bool state, * ****************************************************************************/ -static void mrf24j40_irqwork_rx(FAR struct mrf24j40_dev_s *dev) +static void mrf24j40_irqwork_rx(FAR struct mrf24j40_radio_s *dev) { uint32_t addr; uint32_t index; @@ -1207,7 +1242,7 @@ static void mrf24j40_irqwork_rx(FAR struct mrf24j40_dev_s *dev) /* Read packet */ - addr = 0x80000300; + addr = MRF24J40_RXBUF_BASE; dev->ieee.rxbuf->len = mrf24j40_getreg(dev->spi, addr++); /*dbg("len %3d\n", dev->ieee.rxbuf->len);*/ @@ -1255,7 +1290,7 @@ static void mrf24j40_irqwork_rx(FAR struct mrf24j40_dev_s *dev) static void mrf24j40_irqworker(FAR void *arg) { - FAR struct mrf24j40_dev_s *dev = (FAR struct mrf24j40_dev_s *)arg; + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)arg; uint8_t intstat; DEBUGASSERT(dev); @@ -1310,7 +1345,7 @@ static int mrf24j40_interrupt(int irq, FAR void *context) * retrieve the priv structure using the irq number */ - register FAR struct mrf24j40_dev_s *dev = &g_mrf24j40_devices[0]; + register FAR struct mrf24j40_radio_s *dev = &g_mrf24j40_devices[0]; /* In complex environments, we cannot do SPI transfers from the interrupt * handler because semaphores are probably used to lock the SPI bus. In @@ -1342,14 +1377,14 @@ static int mrf24j40_interrupt(int irq, FAR void *context) * ****************************************************************************/ -FAR struct ieee802154_dev_s *mrf24j40_init(FAR struct spi_dev_s *spi, +FAR struct ieee802154_radio_s *mrf24j40_init(FAR struct spi_dev_s *spi, FAR const struct mrf24j40_lower_s *lower) { - FAR struct mrf24j40_dev_s *dev; + FAR struct mrf24j40_radio_s *dev; struct ieee802154_cca_s cca; #if 0 - dev = kmm_zalloc(sizeof(struct mrf24j40_dev_s)); + dev = kmm_zalloc(sizeof(struct mrf24j40_radio_s)); if (!dev) { @@ -1379,9 +1414,9 @@ FAR struct ieee802154_dev_s *mrf24j40_init(FAR struct spi_dev_s *spi, mrf24j40_initialize(dev); mrf24j40_setchannel(&dev->ieee, 11); - mrf24j40_setpanid (&dev->ieee, IEEE802154_PAN_DEFAULT); - mrf24j40_setsaddr (&dev->ieee, IEEE802154_SADDR_UNSPEC); - mrf24j40_seteaddr (&dev->ieee, IEEE802154_EADDR_UNSPEC); + mrf24j40_setpanid (&dev->ieee, 0xFFFF); + mrf24j40_setsaddr (&dev->ieee, 0xFFFF); + mrf24j40_seteaddr (&dev->ieee, (uint8_t*)"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"); /* Default device params */ diff --git a/drivers/wireless/ieee802154/mrf24j40.h b/drivers/wireless/ieee802154/mrf24j40.h index de3131e4df4..c530e61d630 100644 --- a/drivers/wireless/ieee802154/mrf24j40.h +++ b/drivers/wireless/ieee802154/mrf24j40.h @@ -97,18 +97,22 @@ #define MRF24J40_BBREG6 0x3E #define MRF24J40_CCAEDTH 0x3F -#define MRF24J40_RFCON0 0x80000200 -#define MRF24J40_RFCON1 0x80000201 -#define MRF24J40_RFCON2 0x80000202 -#define MRF24J40_RFCON3 0x80000203 -#define MRF24J40_RFCON5 0x80000205 -#define MRF24J40_RFCON6 0x80000206 -#define MRF24J40_RFCON7 0x80000207 -#define MRF24J40_RFCON8 0x80000208 -#define MRF24J40_SLPCAL0 0x80000209 -#define MRF24J40_SLPCAL1 0x8000020A -#define MRF24J40_SLPCAL2 0x8000020B -#define MRF24J40_RFSTATE 0x8000020F +#define MRF24J40_TXBUF_BASE 0x80000000 +#define MRF24J40_LONGREG_BASE 0x80000200 +#define MRF24J40_RXBUF_BASE 0x80000300 + +#define MRF24J40_RFCON0 (MRF24J40_LONGREG_BASE + 0x00) +#define MRF24J40_RFCON1 (MRF24J40_LONGREG_BASE + 0x01) +#define MRF24J40_RFCON2 (MRF24J40_LONGREG_BASE + 0x02) +#define MRF24J40_RFCON3 (MRF24J40_LONGREG_BASE + 0x03) +#define MRF24J40_RFCON5 (MRF24J40_LONGREG_BASE + 0x05) +#define MRF24J40_RFCON6 (MRF24J40_LONGREG_BASE + 0x06) +#define MRF24J40_RFCON7 (MRF24J40_LONGREG_BASE + 0x07) +#define MRF24J40_RFCON8 (MRF24J40_LONGREG_BASE + 0x08) +#define MRF24J40_SLPCAL0 (MRF24J40_LONGREG_BASE + 0x09) +#define MRF24J40_SLPCAL1 (MRF24J40_LONGREG_BASE + 0x0A) +#define MRF24J40_SLPCAL2 (MRF24J40_LONGREG_BASE + 0x0B) +#define MRF24J40_RFSTATE (MRF24J40_LONGREG_BASE + 0x0F) #define MRF24J40_RSSI 0x80000210 #define MRF24J40_SLPCON0 0x80000211 #define MRF24J40_SLPCON1 0x80000220 @@ -147,18 +151,18 @@ /* INTSTAT bits */ -#define MRF24J40_INTSTAT_SLPIF 0x80 -#define MRF24J40_INTSTAT_WAKEIF 0x40 -#define MRF24J40_INTSTAT_HSYMTMRIF 0x20 -#define MRF24J40_INTSTAT_SECIF 0x10 -#define MRF24J40_INTSTAT_RXIF 0x08 -#define MRF24J40_INTSTAT_TXG2IF 0x04 -#define MRF24J40_INTSTAT_TXG1IF 0x02 -#define MRF24J40_INTSTAT_TXNIF 0x01 +#define MRF24J40_INTSTAT_TXNIF (1 << 0) +#define MRF24J40_INTSTAT_TXG1IF (1 << 1) +#define MRF24J40_INTSTAT_TXG2IF (1 << 2) +#define MRF24J40_INTSTAT_RXIF (1 << 3) +#define MRF24J40_INTSTAT_SECIF (1 << 4) +#define MRF24J40_INTSTAT_HSYMTMRIF (1 << 5) +#define MRF24J40_INTSTAT_WAKEIF (1 << 6) +#define MRF24J40_INTSTAT_SLPIF (1 << 7) /* RXMCR bits */ -#define MRF24J40_RXMCR_PROMI 0x01 /* Enable promisc mode (rx all valid packets) */ +#define MRF24J40_RXMCR_PROMI (1 << 0) /* Enable promisc mode (rx all valid packets) */ #define MRF24J40_RXMCR_ERRPKT 0x02 /* Do not check CRC */ #define MRF24J40_RXMCR_COORD 0x04 /* Enable coordinator mode ??? DIFFERENCE ??? - not used in datasheet! */ #define MRF24J40_RXMCR_PANCOORD 0x08 /* Enable PAN coordinator mode ??? DIFFERENCE ??? */ @@ -166,7 +170,7 @@ /* TXMCR bits */ -#define MRF24J40_TXMCR_CSMABF0 0x01 +#define MRF24J40_TXMCR_CSMABF0 (1 << 0) #define MRF24J40_TXMCR_CSMABF1 0x02 #define MRF24J40_TXMCR_CSMABF2 0x04 #define MRF24J40_TXMCR_MACMINBE0 0x08 @@ -184,7 +188,7 @@ #define MRF24J40_INTCON_RXIE 0x08 #define MRF24J40_INTCON_TXG2IE 0x04 #define MRF24J40_INTCON_TXG1IE 0x02 -#define MRF24J40_INTCON_TXNIE 0x01 +#define MRF24J40_INTCON_TXNIE (1 << 0) /* BBREG1 bits */ @@ -197,10 +201,17 @@ /* TXNCON bits */ -#define MRF24J40_TXNCON_TXNTRIG 0x01 /* Trigger packet tx, automatically cleared */ +#define MRF24J40_TXNCON_TXNTRIG (1 << 0) /* Trigger packet tx, automatically cleared */ #define MRF24J40_TXNCON_TXNSECEN 0x02 /* Enable security */ #define MRF24J40_TXNCON_TXNACKREQ 0x04 /* An ACK is requested for this pkt */ #define MRF24J40_TXNCON_INDIRECT 0x08 /* Activate indirect tx bit (for coordinators) */ #define MRF24J40_TXNCON_FPSTAT 0x10 /* Status of the frame pending big in txed acks */ +/* TXSTAT bits */ + +#define MRF24J40_TXSTAT_TXNSTAT (1 << 0) +#define MRF24J40_TXSTAT_CCAFAIL (1 << 5) +#define MRF24J40_TXSTAT_X_SHIFT 6 +#define MRF24J40_TXSTAT_X_MASK (3 << MRF24J40_TXSTAT_X_SHIFT) + #endif /* __DRIVERS_IEEE802154_MRF24J40_H */ diff --git a/include/nuttx/fs/ioctl.h b/include/nuttx/fs/ioctl.h index e404057d7e6..1b0e4f9a009 100644 --- a/include/nuttx/fs/ioctl.h +++ b/include/nuttx/fs/ioctl.h @@ -83,6 +83,7 @@ #define _LOOPBASE (0x1e00) /* Loop device commands */ #define _MODEMBASE (0x1f00) /* Modem ioctl commands */ #define _I2CBASE (0x2000) /* I2C driver commands */ +#define _MAC854BASE (0x2100) /* 802.15.4 device ioctl commands */ /* boardctl commands share the same number space */ @@ -381,6 +382,12 @@ #define _I2CIOCVALID(c) (_IOC_TYPE(c)==_I2CBASE) #define _I2CIOC(nr) _IOC(_I2CBASE,nr) +/* 802.15.4 MAC driver ioctl definitions *******************************************/ +/* (see nuttx/ieee802154/ieee802154_dev.h */ + +#define _MAC854IOCVALID(c) (_IOC_TYPE(c)==_MAC854BASE) +#define _MAC854IOC(nr) _IOC(_MAC854BASE,nr) + /* boardctl() command definitions *******************************************/ #define _BOARDIOCVALID(c) (_IOC_TYPE(c)==_BOARDBASE) diff --git a/include/nuttx/wireless/ieee802154/at86rf23x.h b/include/nuttx/wireless/ieee802154/at86rf23x.h new file mode 100644 index 00000000000..974e2456e2d --- /dev/null +++ b/include/nuttx/wireless/ieee802154/at86rf23x.h @@ -0,0 +1,100 @@ +/**************************************************************************** + * include/nuttx/ieee802154/at86rf23x.h + * + * Copyright (C) 2014-2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2014-2015 Sebastien Lorquet. All rights reserved. + * Author: Sebastien Lorquet + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_IEEE802154_AT86RF23X_H +#define __INCLUDE_NUTTX_IEEE802154_AT86RF23X_H + +/* The at86rf23x provides interrupts to the MCU via a GPIO pin. The + * following structure provides an MCU-independent mechanixm for controlling + * the at86rf23x GPIO interrupt. + * + * The at86rf23x interrupt is an active low, *level* interrupt. From Datasheet: + * "Note 1: The INTEDGE polarity defaults to: + * 0 = Falling Edge. Ensure that the inter- + * rupt polarity matches the interrupt pin + * polarity of the host microcontroller. + * Note 2: The INT pin will remain high or low, + * depending on INTEDGE polarity setting, + * until INTSTAT register is read." + */ + +struct at86rf23x_lower_s +{ + int (*irq)(FAR const struct at86rf23x_lower_s *lower, xcpt_t handler, int state); + void (*slptr)(FAR const struct at86rf23x_lower_s *lower, int state); + void (*reset)(FAR const struct at86rf23x_lower_s *lower, int state); +}; + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Function: at86rf23x_init + * + * Description: + * Initialize the IEEE802.15.4 driver. The at86rf23x device is assumed to be + * in the post-reset state upon entry to this function. + * + * Parameters: + * spi - A reference to the platform's SPI driver for the at86rf23x + * lower - The MCU-specific interrupt used to control low-level MCU + * functions (i.e., at86rf23x GPIO interrupts). + * devno - If more than one at86rf23x is supported, then this is the + * zero based number that identifies the at86rf23x; + * + * Returned Value: + * OK on success; Negated errno on failure. + * + * Assumptions: + * + ****************************************************************************/ + +FAR struct ieee802154_dev_s *at86rf23x_init(FAR struct spi_dev_s *spi, FAR const struct at86rf23x_lower_s *lower); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_IEEE802154__AT86RF23X_H */ diff --git a/include/nuttx/wireless/ieee802154/ieee802154_mac.h b/include/nuttx/wireless/ieee802154/ieee802154_mac.h new file mode 100644 index 00000000000..439825391a9 --- /dev/null +++ b/include/nuttx/wireless/ieee802154/ieee802154_mac.h @@ -0,0 +1,368 @@ +/**************************************************************************** + * include/nuttx/wireless/ieee802154/ieee802154_mac.h + * + * Copyright (C) 2016 Sebastien Lorquet. All rights reserved. + * Author: Sebastien Lorquet + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_WIRELESS_IEEE802154_IEEE802154_MAC_H +#define __INCLUDE_NUTTX_WIRELESS_IEEE802154_IEEE802154_MAC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ +/* None at the moment */ + +/* IEEE 802.15.4 MAC Interface **********************************************/ + +/* Some addresses */ + +#define IEEE802154_PAN_UNSPEC (uint16_t)0xFFFF +#define IEEE802154_SADDR_UNSPEC (uint16_t)0xFFFF +#define IEEE802154_SADDR_BCAST (uint16_t)0xFFFE +#define IEEE802154_EADDR_UNSPEC (uint8_t*)"\xff\xff\xff\xff\xff\xff\xff\xff" + +/* IEEE 802.15.4 MAC status codes */ + +enum +{ + MAC802154_STATUS_OK = 0, + MAC802154_STATUS_BEACON_LOSS = 0xE0, + MAC802154_STATUS_CHANNEL_ACCESS_FAILURE, + MAC802154_STATUS_DENIED, + MAC802154_STATUS_DISABLE_TRX_FAILURE, + MAC802154_STATUS_FAILED_SECURITY_CHECK, + MAC802154_STATUS_FRAME_TOO_LONG, + MAC802154_STATUS_INVALID_GTS, + MAC802154_STATUS_INVALID_HANDLE, + MAC802154_STATUS_INVALID_PARAMETER, + MAC802154_STATUS_NO_ACK, + MAC802154_STATUS_NO_BEACON, + MAC802154_STATUS_NO_DATA, + MAC802154_STATUS_NO_SHORT_ADDRESS, + MAC802154_STATUS_OUT_OF_CAP, + MAC802154_STATUS_PAN_ID_CONFLICT, + MAC802154_STATUS_REALIGNMENT, + MAC802154_STATUS_TRANSACTION_EXPIRED, + MAC802154_STATUS_TRANSACTION_OVERFLOW, + MAC802154_STATUS_TX_ACTIVE, + MAC802154_STATUS_UNAVAILABLE_KEY, + MAC802154_STATUS_UNSUPPORTED_ATTRIBUTE +}; + +/* IEEE 802.15.4 PHY constants */ +#define MAC802154_aMaxPHYPacketSize 127 +#define MAC802154_aTurnaroundTime 12 /*symbol periods*/ + +/* IEEE 802.15.4 MAC constants */ +#define MAC802154_aBaseSlotDuration 60 +#define MAC802154_aNumSuperframeSlots 16 +#define MAC802154_aBaseSuperframeDuration (MAC802154_aBaseSlotDuration * MAC802154_aNumSuperframeSlots) +#define MAC802154_aMaxBE 5 +#define MAC802154_aMaxBeaconOverhead 75 +#define MAC802154_aMaxBeaconPayloadLength (MAC802154_aMaxPHYPacketSize - MAC802154_aMaxBeaconOverhead) +#define MAC802154_aGTSDescPersistenceTime 4 +#define MAC802154_aMaxFrameOverhead 25 +#define MAC802154_aMaxFrameResponseTime 1220 +#define MAC802154_aMaxFrameRetries 3 +#define MAC802154_aMaxLostBeacons 4 +#define MAC802154_aMaxMACFrameSize (MAC802154_aMaxPHYPacketSize - MAC802154_aMaxFrameOverhead) +#define MAC802154_aMaxSIFSFrameSize 18 +#define MAC802154_aMinCAPLength 440 +#define MAC802154_aMinLIFSPeriod 40 +#define MAC802154_aMinSIFSPeriod 12 +#define MAC802154_aResponseWaitTime (32 * MAC802154_aBaseSuperframeDuration) +#define MAC802154_aUnitBackoffPeriod 20 + + +/* IEEE 802.15.4 PHY/MAC PIB attributes IDs */ +enum +{ + MAC802154_phyCurrentChannel = 0x00, + MAC802154_phyChannelsSupported, + MAC802154_phyTransmitPower, + MAC802154_phyCCAMode, + MAC802154_macAckWaitDuration = 0x40, + MAC802154_macAssociationPermit, + MAC802154_macAutoRequest, + MAC802154_macBattLifeExt, + MAC802154_macBattLifeExtPeriods, + MAC802154_macBeaconPayload, + MAC802154_macBeaconPayloadLength, + MAC802154_macBeaconOrder, + MAC802154_macBeaconTxTime, + MAC802154_macBSN, + MAC802154_macCoordExtendedAddress, + MAC802154_macCoordShortAddress, + MAC802154_macDSN, + MAC802154_macGTSPermit, + MAC802154_macMaxCSMABackoffs, + MAC802154_macMinBE, + MAC802154_macPANId, + MAC802154_macPromiscuousMode, + MAC802154_macRxOnWhenIdle, + MAC802154_macShortAddress, + MAC802154_macSuperframeOrder, + MAC802154_macTransactionPersistenceTime, + MAC802154_macACLEntryDescriptorSet = 0x70, + MAC802154_macACLEntryDescriptorSetSize, + MAC802154_macDefaultSecurity, + MAC802154_macDefaultSecurityMaterialLength, + MAC802154_macDefaultSecurityMaterial, + MAC802154_macDefaultSecuritySuite, + MAC802154_macSecurityMode +}; + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* IEEE 802.15.4 Device address + * The addresses in ieee802154 have several formats: + * No address : [none] + * Short address + PAN id : PPPP/SSSS + * Extended address + PAN id : PPPP/LLLLLLLLLLLLLLLL + */ + +struct ieee802154_addr_s +{ + uint8_t ia_len; /* structure length, 0/2/8 */ + uint16_t ia_panid; /* PAN identifier, can be IEEE802154_PAN_UNSPEC */ + union { + uint16_t _ia_saddr; /* short address */ + uint8_t _ia_eaddr[8]; /* extended address */ + } ia_addr; +#define ia_saddr ia_addr._ia_saddr +#define ia_eaddr ia_addr._ia_eaddr +}; +#define IEEE802154_ADDRSTRLEN 22 /* (2*2+1+8*2, PPPP/EEEEEEEEEEEEEEEE) */ + +/* Operations */ + +struct ieee802154_mac_s; + +struct ieee802154_macops_s +{ + /* Requests, confirmed asynchronously via callbacks */ + + CODE int req_data (struct ieee802154_mac_s *mac, /* Transmit a data frame */ + uint8_t handle, + uint8_t *buf, + int len); + + CODE int req_purge (struct ieee802154_mac_s *mac, /* Cancel transmission of a data frame */ + uint8_t handle); + + CODE int req_associate (struct ieee802154_mac_s *mac, /* Start association with coordinator */ + uint16_t panid, + uint8_t *coordeadr); + + CODE int req_disassociate(struct ieee802154_mac_s *mac, /* Start disassociation with coordinator */ + uint8_t *eadr, + uint8_t reason); + + CODE int req_get (struct ieee802154_mac_s *mac, /* Read the PIB */ + int attribute); + + CODE int req_gts (struct ieee802154_mac_s *mac, /* Allocate or deallocate a GTS */ + uint8_t* characteristics); + + CODE int req_reset (struct ieee802154_mac_s *mac, /* MAC layer reset */ + bool setdefaults); + + CODE int req_rxenable (struct ieee802154_mac_s *mac, /* PHY receiver control */ + bool deferrable, + int ontime, + int duration); + + CODE int req_scan (struct ieee802154_mac_s *mac, /* Start a network scan */ + uint8_t type, + uint32_t channels, + int duration); + + CODE int req_set (struct ieee802154_mac_s *mac, /* Change the PIB */ + int attribute, + uint8_t *value, + int valuelen); + + CODE int req_start (struct ieee802154_mac_s *mac, + uint16_t panid, + int channel, + uint8_t bo, + uint8_t fo, + bool coord, + bool batext, + bool realign); + + CODE int req_sync (struct ieee802154_mac_s *mac, + int channel, + bool track); + + CODE int req_poll (struct ieee802154_mac_s *mac, + uint8_t *coordaddr); + + /* Synchronous Responses to Indications received via callbacks */ + + CODE int rsp_associate (struct ieee802154_mac_s *mac, /* Reply to an association request */ + uint8_t eadr, + uint16_t saddr, + int status); + + CODE int rsp_orphan (struct ieee802154_mac_s *mac, /* Orphan device management */ + uint8_t *orphanaddr, + uint16_t saddr, + bool associated); +}; + +/* Notifications */ + +struct ieee802154_maccb_s +{ + /* Asynchronous confirmations to requests */ + + CODE int conf_data (struct ieee802154_mac_s *mac, /* Data frame was received by remote device */ + uint8_t *buf, + int len); + CODE int conf_purge (struct ieee802154_mac_s *mac, /* Data frame was purged */ + uint8_t handle, + int status); + CODE int conf_associate (struct ieee802154_mac_s *mac, /* Association request completed */ + uint16_t saddr, + int status); + CODE int conf_disassociate(struct ieee802154_mac_s *mac, /* Disassociation request completed */ + int status); + CODE int conf_get (struct ieee802154_mac_s *mac, /* PIB data returned */ + int status, + int attribute, + uint8_t *value, + int valuelen); + CODE int conf_gts (struct ieee802154_mac_s *mac, /* GTS management completed */ + uint8_t *characteristics, + int status); + CODE int conf_reset (struct ieee802154_mac_s *mac, /* MAC reset completed */ + int status); + CODE int conf_rxenable (struct ieee802154_mac_s *mac, + int status); + CODE int conf_scan (struct ieee802154_mac_s *mac, + int status, + uint8_t type, + uint32_t unscanned, + int rsltsize, + uint8_t *edlist, + uint8_t *pandescs); + CODE int conf_set (struct ieee802154_mac_s *mac, + int status, int attribute); + CODE int conf_start (struct ieee802154_mac_s *mac, + int status); + CODE int conf_poll (struct ieee802154_mac_s *mac, + int status); + + /* Asynchronous event indications, replied to synchronously with responses */ + + CODE int ind_data (struct ieee802154_mac_s *mac, /* Data frame received */ + uint8_t *buf, + int len); + CODE int ind_associate (struct ieee802154_mac_s *mac, /* Association request received */ + uint16_t clipanid, + uint8_t *clieaddr); + CODE int ind_disassociate (struct ieee802154_mac_s *mac, /* Disassociation request received */ + uint8_t *eadr, + uint8_t reason); + CODE int ind_beaconnotify (struct ieee802154_mac_s *mac, /* Beacon notification */ + uint8_t *bsn, + uint_t *pandesc, + uint8_t *sdu, + int sdulen); + CODE int ind_gts (struct ieee802154_mac_s *mac, /* GTS management request received */ + uint8_t *devaddr, + uint8_t *characteristics); + CODE int ind_orphan (struct ieee802154_mac_s *mac, /* Orphan device detected */ + uint8_t *orphanaddr); + CODE int ind_commstatus (struct ieee802154_mac_s *mac, + uint16_t panid, + uint8_t *src, + uint8_t *dst, + int status); + CODE int ind_syncloss (struct ieee802154_mac_s *mac, + int reason); +}; + +struct ieee802154_radio_s; + +struct ieee802154_mac_s +{ + struct ieee802154_radio_s *radio; + struct ieee802154_macops_s ops; + struct ieee802154_maccb_s cbs; +}; + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* + * Instanciate a 802.15.4 MAC from a 802.15.4 radio device. + * To create a 802.15.4 MAC, you need to pass: + * - an instance of a radio driver in radiodev + * - a pointer to a structure that contains MAC callback routines to + * handle confirmations and indications. NULL entries indicate no callback. + * In return you get a mac structure that has pointers to MAC operations and + * responses. + * This API does not create any device accessible to userspace. If you want to + * call these APIs from userspace, you have to wrap your mac in a character + * device via mac802154_device.c . + */ +FAR struct ieee802154_mac_s * mac802154_register(FAR struct ieee802154_radio_s *radiodev, struct ieee802154_maccb_s *callbacks); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_WIRELESS_IEEE802154_MRF24J40_H */ diff --git a/include/nuttx/wireless/ieee802154/ieee802154_radio.h b/include/nuttx/wireless/ieee802154/ieee802154_radio.h index c3439feb897..06276b2870e 100644 --- a/include/nuttx/wireless/ieee802154/ieee802154_radio.h +++ b/include/nuttx/wireless/ieee802154/ieee802154_radio.h @@ -33,8 +33,8 @@ * ****************************************************************************/ -#ifndef __INCLUDE_NUTTX_WIRELESS_IEEE802154_IEEE802154_H -#define __INCLUDE_NUTTX_WIRELESS_IEEE802154_IEEE802154_H +#ifndef __INCLUDE_NUTTX_WIRELESS_IEEE802154_IEEE802154_RADIO_H +#define __INCLUDE_NUTTX_WIRELESS_IEEE802154_IEEE802154_RADIO_H /**************************************************************************** * Included Files @@ -48,70 +48,13 @@ /**************************************************************************** * Pre-Processor Definitions ****************************************************************************/ + /* Configuration ************************************************************/ -/* None at the moment */ -/* IEEE 802.15.4 MAC Interface **********************************************/ +/* IEEE 802.15.4 Radio Interface **********************************************/ -/* Frame control field masks, 2 bytes - * Seee IEEE 802.15.4/2003 7.2.1.1 page 112 - */ - -#define IEEE802154_FC1_FTYPE 0x03 /* Frame type, bits 0-2 */ -#define IEEE802154_FC1_SEC 0x08 /* Security Enabled, bit 3 */ -#define IEEE802154_FC1_PEND 0x10 /* Frame pending, bit 4 */ -#define IEEE802154_FC1_ACKREQ 0x20 /* Acknowledge request, bit 5 */ -#define IEEE802154_FC1_INTRA 0x40 /* Intra PAN, bit 6 */ -#define IEEE802154_FC2_DADDR 0x0C /* Dest addressing mode, bits 10-11 */ -#define IEEE802154_FC2_VERSION 0x30 /* Source addressing mode, bits 12-13 */ -#define IEEE802154_FC2_SADDR 0xC0 /* Source addressing mode, bits 14-15 */ - -/* Frame Type */ - -#define IEEE802154_FRAME_BEACON 0x00 -#define IEEE802154_FRAME_DATA 0x01 -#define IEEE802154_FRAME_ACK 0x02 -#define IEEE802154_FRAME_COMMAND 0x03 - -/* Security Enabled */ - -#define IEEE802154_SEC_OFF 0x00 -#define IEEE802154_SEC_ON 0x08 - -/* Flags */ - -#define IEEE802154_PEND 0x10 -#define IEEE802154_ACK_REQ 0x20 -#define IEEE802154_INTRA 0x40 - -/* Dest Addressing modes */ - -#define IEEE802154_DADDR_NONE 0x00 -#define IEEE802154_DADDR_SHORT 0x08 -#define IEEE802154_DADDR_EXT 0x0A - -/* Src Addressing modes */ - -#define IEEE802154_SADDR_NONE 0x00 -#define IEEE802154_SADDR_SHORT 0x80 -#define IEEE802154_SADDR_EXT 0xA0 - -/* Some addresses */ - -#define IEEE802154_PAN_DEFAULT (uint16_t)0xFFFF -#define IEEE802154_SADDR_UNSPEC (uint16_t)0xFFFF -#define IEEE802154_SADDR_BCAST (uint16_t)0xFFFE -#define IEEE802154_EADDR_UNSPEC (uint8_t*)"\xff\xff\xff\xff\xff\xff\xff\xff" - -#define IEEE802154_CMD_ASSOC_REQ 0x01 -#define IEEE802154_CMD_ASSOC_RSP 0x02 -#define IEEE802154_CMD_DIS_NOT 0x03 -#define IEEE802154_CMD_DATA_REQ 0x04 -#define IEEE802154_CMD_PANID_CONF_NOT 0x05 -#define IEEE802154_CMD_ORPHAN_NOT 0x06 -#define IEEE802154_CMD_BEACON_REQ 0x07 -#define IEEE802154_CMD_COORD_REALIGN 0x08 -#define IEEE802154_CMD_GTS_REQ 0x09 +/* This layer only knows radio frames. There are no 802.15.4 specific bits + * at this layer. */ /* Device modes */ @@ -135,73 +78,75 @@ struct ieee802154_cca_s { uint8_t use_ed : 1; /* CCA using ED */ uint8_t use_cs : 1; /* CCA using carrier sense */ - uint8_t edth; /* Energy detection threshold for CCA */ - uint8_t csth; /* Carrier sense threshold for CCA */ + uint8_t edth; /* Energy detection threshold for CCA */ + uint8_t csth; /* Carrier sense threshold for CCA */ }; -struct ieee802154_dev_s; +struct ieee802154_radio_s; -struct ieee802154_devops_s +struct ieee802154_radioops_s { - CODE int (*setchannel)(FAR struct ieee802154_dev_s *dev, uint8_t channel); - CODE int (*getchannel)(FAR struct ieee802154_dev_s *dev, + CODE int (*setchannel)(FAR struct ieee802154_radio_s *dev, uint8_t channel); + CODE int (*getchannel)(FAR struct ieee802154_radio_s *dev, FAR uint8_t *channel); - CODE int (*setpanid)(FAR struct ieee802154_dev_s *dev, uint16_t panid); - CODE int (*getpanid)(FAR struct ieee802154_dev_s *dev, + CODE int (*setpanid)(FAR struct ieee802154_radio_s *dev, uint16_t panid); + CODE int (*getpanid)(FAR struct ieee802154_radio_s *dev, FAR uint16_t *panid); - CODE int (*setsaddr)(FAR struct ieee802154_dev_s *dev, uint16_t saddr); - CODE int (*getsaddr)(FAR struct ieee802154_dev_s *dev, + CODE int (*setsaddr)(FAR struct ieee802154_radio_s *dev, uint16_t saddr); + CODE int (*getsaddr)(FAR struct ieee802154_radio_s *dev, FAR uint16_t *saddr); - CODE int (*seteaddr)(FAR struct ieee802154_dev_s *dev, + CODE int (*seteaddr)(FAR struct ieee802154_radio_s *dev, FAR uint8_t *laddr); - CODE int (*geteaddr)(FAR struct ieee802154_dev_s *dev, + CODE int (*geteaddr)(FAR struct ieee802154_radio_s *dev, FAR uint8_t *laddr); - CODE int (*setpromisc)(FAR struct ieee802154_dev_s *dev, bool promisc); - CODE int (*getpromisc)(FAR struct ieee802154_dev_s *dev, + CODE int (*setpromisc)(FAR struct ieee802154_radio_s *dev, bool promisc); + CODE int (*getpromisc)(FAR struct ieee802154_radio_s *dev, FAR bool *promisc); - CODE int (*setdevmode)(FAR struct ieee802154_dev_s *dev, uint8_t devmode); - CODE int (*getdevmode)(FAR struct ieee802154_dev_s *dev, + CODE int (*setdevmode)(FAR struct ieee802154_radio_s *dev, uint8_t devmode); + CODE int (*getdevmode)(FAR struct ieee802154_radio_s *dev, FAR uint8_t *devmode); - CODE int (*settxpower)(FAR struct ieee802154_dev_s *dev, + CODE int (*settxpower)(FAR struct ieee802154_radio_s *dev, int32_t txpwr); /* unit = 1 mBm = 1/100 dBm */ - CODE int (*gettxpower)(FAR struct ieee802154_dev_s *dev, + CODE int (*gettxpower)(FAR struct ieee802154_radio_s *dev, FAR int32_t *txpwr); - CODE int (*setcca)(FAR struct ieee802154_dev_s *dev, + CODE int (*setcca)(FAR struct ieee802154_radio_s *dev, FAR struct ieee802154_cca_s *cca); - CODE int (*getcca)(FAR struct ieee802154_dev_s *dev, + CODE int (*getcca)(FAR struct ieee802154_radio_s *dev, FAR struct ieee802154_cca_s *cca); - CODE int (*ioctl)(FAR struct ieee802154_dev_s *ieee, int cmd, + CODE int (*ioctl)(FAR struct ieee802154_radio_s *ieee, int cmd, unsigned long arg); - CODE int (*energydetect)(FAR struct ieee802154_dev_s *dev, + CODE int (*energydetect)(FAR struct ieee802154_radio_s *dev, FAR uint8_t *energy); - CODE int (*rxenable)(FAR struct ieee802154_dev_s *dev, bool state, + CODE int (*rxenable)(FAR struct ieee802154_radio_s *dev, bool state, FAR struct ieee802154_packet_s *packet); - CODE int (*transmit)(FAR struct ieee802154_dev_s *dev, + CODE int (*transmit)(FAR struct ieee802154_radio_s *dev, FAR struct ieee802154_packet_s *packet); /*TODO beacon/sf order*/ }; -struct ieee802154_dev_s +struct ieee802154_radio_s { - FAR const struct ieee802154_devops_s *ops; + FAR const struct ieee802154_radioops_s *ops; /* Packet reception management */ - struct ieee802154_packet_s *rxbuf; - sem_t rxsem; + struct ieee802154_packet_s *rxbuf; /* packet reception buffer, filled by rx interrupt, NULL if rx not enabled */ + sem_t rxsem; /* Semaphore posted after reception of a packet */ /* Packet transmission management */ - - sem_t txsem; + bool txok; /* Last transmission status, filled by tx interrupt */ + bool txbusy; /* Last transmission failed because channel busy */ + uint8_t txretries; /* Last transmission required this much retries */ + sem_t txsem; /* Semaphore posted after transmission of a packet */ }; #ifdef __cplusplus @@ -221,4 +166,4 @@ extern "C" } #endif -#endif /* __INCLUDE_NUTTX_WIRELESS_IEEE802154_MRF24J40_H */ +#endif /* __INCLUDE_NUTTX_WIRELESS_IEEE802154_IEEE802154_RADIO_H */ diff --git a/include/nuttx/wireless/ieee802154/mrf24j40.h b/include/nuttx/wireless/ieee802154/mrf24j40.h index 2c78faee01a..167f125b33b 100644 --- a/include/nuttx/wireless/ieee802154/mrf24j40.h +++ b/include/nuttx/wireless/ieee802154/mrf24j40.h @@ -100,7 +100,7 @@ extern "C" ****************************************************************************/ struct spi_dev_s; /* Forward reference */ -FAR struct ieee802154_dev_s *mrf24j40_init(FAR struct spi_dev_s *spi, +FAR struct ieee802154_radio_s *mrf24j40_init(FAR struct spi_dev_s *spi, FAR const struct mrf24j40_lower_s *lower); #undef EXTERN diff --git a/wireless/ieee802154/Kconfig b/wireless/ieee802154/Kconfig index 18d5a8753c3..60706d45bc1 100644 --- a/wireless/ieee802154/Kconfig +++ b/wireless/ieee802154/Kconfig @@ -12,4 +12,22 @@ config IEEE802154 if IEEE802154 +config IEEE802154_MAC + bool "Generic Media Access Control layer for 802.15.4 radios" + default n + depends on IEEE802154 + ---help--- + Enables a Media Access Controller for any IEEE802.15.4 radio + device. This in turn can be used by higher layer entities + such as 6lowpan. It is not required to use 802.15.4 radios, + but is strongly suggested to ensure exchange of valid frames. + +config IEEE802154_DEV + bool "Debug character driver for ieee802.15.4 radio interfaces" + default n + depends on IEEE802154 + ---help--- + Enables a device driver to expose ieee802.15.4 radio controls + to user space as IOCTLs. + endif # IEEE802154 diff --git a/wireless/ieee802154/Make.defs b/wireless/ieee802154/Make.defs index 9e0c66391b4..8d7251c148c 100644 --- a/wireless/ieee802154/Make.defs +++ b/wireless/ieee802154/Make.defs @@ -36,9 +36,18 @@ ifeq ($(CONFIG_IEEE802154),y) # Include IEEE 802.15.4 support +CSRCS = # Include wireless devices build support +ifeq ($(CONFIG_IEEE802154_MAC),y) +CSRCS += ieee802154/mac802154.c +endif + +ifeq ($(CONFIG_IEEE802154_DEV),y) +CSRCS += ieee802154/ieee802154_device.c +endif + DEPPATH += --dep-path wireless/ieee802154 VPATH += :wireless/ieee802154 CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)wireless$(DELIM)ieee802154} diff --git a/wireless/ieee802154/ieee802154_device.c b/wireless/ieee802154/ieee802154_device.c new file mode 100644 index 00000000000..75921a88cdd --- /dev/null +++ b/wireless/ieee802154/ieee802154_device.c @@ -0,0 +1,374 @@ +/**************************************************************************** + * drivers/ieee802154/ieee802154_device.c + * + * Copyright (C) 2014-2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2014-2015 Sebastien Lorquet. All rights reserved. + * Author: Sebastien Lorquet + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +struct ieee802154_devwrapper_s +{ + FAR struct ieee802154_radio_s *child; + sem_t devsem; /* Device access serialization semaphore */ + int opened; /* this device can only be opened once */ +}; + +/* when rx interrupt is complete, it calls sem_post(&dev->rxsem); */ +/* when tx interrupt is complete, it calls sem_post(&dev->txsem); */ + +static void ieee802154dev_semtake(FAR struct ieee802154_devwrapper_s *dev); +static int ieee802154dev_open (FAR struct file *filep); +static int ieee802154dev_close (FAR struct file *filep); +static ssize_t ieee802154dev_read (FAR struct file *filep, FAR char *buffer, size_t len); +static ssize_t ieee802154dev_write (FAR struct file *filep, FAR const char *buffer, size_t len); +static int ieee802154dev_ioctl (FAR struct file *filep, int cmd, unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations ieee802154dev_fops = +{ + ieee802154dev_open , /* open */ + ieee802154dev_close, /* close */ + ieee802154dev_read , /* read */ + ieee802154dev_write, /* write */ + 0 , /* seek */ + ieee802154dev_ioctl /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , 0 /* poll */ +#endif +}; + +/**************************************************************************** + * Name: ieee802154dev_semtake + * + * Description: + * Acquire the semaphore used for access serialization. + * + ****************************************************************************/ + +static void ieee802154dev_semtake(FAR struct ieee802154_devwrapper_s *dev) +{ + /* Take the semaphore (perhaps waiting) */ + + while (sem_wait(&dev->devsem) != 0) + { + /* The only case that an error should occur here is if + * the wait was awakened by a signal. + */ + ASSERT(errno == EINTR); + } +} + +/**************************************************************************** + * Name: ieee802154dev_semgive + * + * Description: + * Release the semaphore used for access serialization. + * + ****************************************************************************/ + +static inline void ieee802154dev_semgive(FAR struct ieee802154_devwrapper_s *dev) +{ + sem_post(&dev->devsem); +} + +/**************************************************************************** + * Name: ieee802154dev_open + * + * Description: + * Open the MRF24J40 device. + * + ****************************************************************************/ + +static int ieee802154dev_open(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct ieee802154_devwrapper_s *dev = inode->i_private; + + ieee802154dev_semtake(dev); + + if (dev->opened) + { + return -EMFILE; + } + else + { + + /* Enable interrupts (only rx for now)*/ + + //mrf24j40_setreg(dev->spi, MRF24J40_INTCON, ~(MRF24J40_INTCON_RXIE) ); + //dev->lower->enable(dev->lower, TRUE); + + dev->opened = TRUE; + } + + ieee802154dev_semgive(dev); + return OK; +} + +/**************************************************************************** + * Name: ieee802154dev_close + * + * Description: + * Close the MRF24J40 device. + * + ****************************************************************************/ + +static int ieee802154dev_close(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct ieee802154_devwrapper_s *dev = inode->i_private; + int ret = OK; + + ieee802154dev_semtake(dev); + + if(!dev->opened) + { + ret = -EIO; + } + else + { + /* Disable interrupts */ + + //mrf24j40_setreg(dev->spi, MRF24J40_INTCON, 0xFF ); + //dev->lower->enable(dev->lower, FALSE); + + dev->opened = FALSE; + } + + ieee802154dev_semgive(dev); + return ret; +} + +/**************************************************************************** + * Name: ieee802154dev_read + * + * Description: + * Return the last received packet. + * TODO: Return a packet from the receive queue. The buffer must be a pointer to a + * struct ieee802154_packet_s structure, with a correct length. + * + ****************************************************************************/ + +static ssize_t ieee802154dev_read(FAR struct file *filep, FAR char *buffer, size_t len) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct ieee802154_devwrapper_s *dev = inode->i_private; + int ret = OK; + + FAR struct ieee802154_packet_s *buf = (FAR struct ieee802154_packet_s*)buffer; + + if (lenchild->ops->rxenable(dev->child, 1, buf); +#if 0 + if (ret < 0) + { + goto done; + } +#endif + + /* if no packet is received, this will produce -EAGAIN + * The user is responsible for sleeping until sth arrives + */ +#if 0 + ret = sem_trywait(&dev->child->rxsem); +#else + ret = sem_wait(&dev->child->rxsem); +#endif + if (ret < 0) + { + ret = -errno; + goto done; + } + + /* disable read until we have process the current read */ + dev->child->ops->rxenable(dev->child, 0, NULL); + + ret = buf->len; + +done: + + return ret; +} + +/**************************************************************************** + * Name: ieee802154dev_write + * + * Description: + * Send a packet immediately. + * TODO: Put a packet in the send queue. The packet will be sent as soon as possible. + * The buffer must point to a struct ieee802154_packet_s with the correct length. + * + ****************************************************************************/ + +static ssize_t ieee802154dev_write(FAR struct file *filep, FAR const char *buffer, size_t len) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct ieee802154_devwrapper_s *dev = inode->i_private; + FAR struct ieee802154_packet_s *packet; + int ret = OK; + + /* TODO: Make this an option or have a new method of doing timeout from ioctrl */ + FAR struct timespec timeout; + + timeout.tv_sec = 1; + timeout.tv_nsec = 0; + + /* sanity checks */ + + if (lenlen > 125) /* Max len 125, 2 FCS bytes auto added by mrf*/ + { + ret = -EPERM; + // goto done; + DEBUGASSERT(0); + } + + /* Copy packet to normal device TX fifo. + * Beacons and GTS transmission will be handled via IOCTLs + */ + ret = dev->child->ops->transmit(dev->child, packet); + + if(ret != packet->len) + { + ret = -EPERM; + goto done; + } + + if(sem_timedwait(&dev->child->txsem, &timeout)) + { + dbg("Radio Device timedout on Tx\n"); + } + +done: + + /* okay, tx interrupt received. check transmission status to decide success. */ + + return ret; +} + +/**************************************************************************** + * Name: ieee802154dev_ioctl + * + * Description: + * Control the MRF24J40 device. This is where the real operations happen. + * + ****************************************************************************/ + +static int ieee802154dev_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct ieee802154_devwrapper_s *dev = inode->i_private; + FAR struct ieee802154_radio_s *child = dev->child; + int ret = OK; + + switch(cmd) + { + case MAC854IOCSCHAN : ret = child->ops->setchannel (child, (uint8_t) arg); break; + case MAC854IOCGCHAN : ret = child->ops->getchannel (child, (FAR uint8_t*) arg); break; + case MAC854IOCSPANID : ret = child->ops->setpanid (child, (uint16_t) arg); break; + case MAC854IOCGPANID : ret = child->ops->getpanid (child, (FAR uint16_t*) arg); break; + case MAC854IOCSSADDR : ret = child->ops->setsaddr (child, (uint16_t) arg); break; + case MAC854IOCGSADDR : ret = child->ops->getsaddr (child, (FAR uint16_t*) arg); break; + case MAC854IOCSEADDR : ret = child->ops->seteaddr (child, (FAR uint8_t*) arg); break; + case MAC854IOCGEADDR : ret = child->ops->geteaddr (child, (FAR uint8_t*) arg); break; + case MAC854IOCSPROMISC: ret = child->ops->setpromisc (child, (bool) arg); break; + case MAC854IOCGPROMISC: ret = child->ops->getpromisc (child, (FAR bool*) arg); break; + case MAC854IOCSDEVMODE: ret = child->ops->setdevmode (child, (uint8_t) arg); break; + case MAC854IOCGDEVMODE: ret = child->ops->getdevmode (child, (FAR uint8_t*) arg); break; + case MAC854IOCSTXP : ret = child->ops->settxpower (child, (int32_t) arg); break; + case MAC854IOCGTXP : ret = child->ops->gettxpower (child, (FAR int32_t*) arg); break; + case MAC854IOCSCCA : ret = child->ops->setcca (child, (FAR struct ieee802154_cca_s*)arg); break; + case MAC854IOCGCCA : ret = child->ops->getcca (child, (FAR struct ieee802154_cca_s*)arg); break; + case MAC854IOCGED : ret = child->ops->energydetect(child, (FAR uint8_t*) arg); break; + default : ret = child->ops->ioctl (child, cmd, arg); + } + + return ret; +} + +/**************************************************************************** + * Name: ieee802154dev_register + * + * Description: + * Register /dev/ieee%d + * + ****************************************************************************/ + +int ieee802154_register(FAR struct ieee802154_radio_s *ieee, unsigned int minor) +{ + char devname[16]; + FAR struct ieee802154_devwrapper_s *dev; + + dev = kmm_zalloc(sizeof(struct ieee802154_devwrapper_s)); + + if (!dev) + { + return -ENOMEM; + } + + dev->child = ieee; + + sem_init(&dev->devsem , 0, 1); /* Allow the device to be opened once before blocking */ + + sprintf(devname, "/dev/ieee%d", minor); + + return register_driver(devname, &ieee802154dev_fops, 0666, dev); +} + diff --git a/wireless/ieee802154/mac802154.c b/wireless/ieee802154/mac802154.c new file mode 100644 index 00000000000..ad9e1953714 --- /dev/null +++ b/wireless/ieee802154/mac802154.c @@ -0,0 +1,586 @@ +/**************************************************************************** + * wireless/ieee802154/mac802154.c + * + * Copyright (C) 2016 Sebastien Lorquet. All rights reserved. + * Author: Sebastien Lorquet + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +#include + +/* Frame Type */ + +#define IEEE802154_FRAME_BEACON 0x00 +#define IEEE802154_FRAME_DATA 0x01 +#define IEEE802154_FRAME_ACK 0x02 +#define IEEE802154_FRAME_COMMAND 0x03 + +/* MAC commands */ + +#define IEEE802154_CMD_ASSOC_REQ 0x01 +#define IEEE802154_CMD_ASSOC_RSP 0x02 +#define IEEE802154_CMD_DIS_NOT 0x03 +#define IEEE802154_CMD_DATA_REQ 0x04 +#define IEEE802154_CMD_PANID_CONF_NOT 0x05 +#define IEEE802154_CMD_ORPHAN_NOT 0x06 +#define IEEE802154_CMD_BEACON_REQ 0x07 +#define IEEE802154_CMD_COORD_REALIGN 0x08 +#define IEEE802154_CMD_GTS_REQ 0x09 + +/* private types */ +/* The privmac structure is an extension of the public ieee802154_mac_s type. + * It contains storage for the IEEE802.15.4 MIB attributes. + */ + +struct ieee802154_privmac_s +{ + struct ieee802154_mac_s pubmac; /* This MUST be the first member */ + + /* MIB attributes, grouped to save memory */ + /* 0x40 */ uint8_t macAckWaitDuration : 1; /* 55 or 120(true) */ + /* 0x41 */ uint8_t macAssociationPermit : 1; + /* 0x42 */ uint8_t macAutoRequest : 1; + /* 0x43 */ uint8_t macBattLifeExt : 1; + /* 0x44 */ uint8_t macBattLifeExtPeriods : 1; /* 6 or 8(true) */ + /* 0x4E */ uint8_t macMaxCSMABackoffs : 3; /* 0-5 */ + + /* 0x47 */ uint8_t macBeaconOrder : 4; + /* 0x54 */ uint8_t macSuperframeOrder : 4; + + /* 0x4F */ uint32_t macMinBE : 2; + /* 0x4D */ uint32_t macGTSPermit : 1; + /* 0x51 */ uint32_t macPromiscuousMode : 1; + /* 0x52 */ uint32_t macRxOnWhenIdle : 1; + uint32_t macPad : 3; + /* 0x48 */ uint32_t macBeaconTxTime : 24; + + /* 0x45 */ uint8_t macBeaconPayload[MAC802154_aMaxBeaconPayloadLength]; + /* 0x46 */ uint8_t macBeaconPayloadLength; + /* 0x49 */ uint8_t macBSN; + /* 0x4A */ uint8_t macCoordExtendedAddress[8]; + /* 0x4B */ uint16_t macCoordShortAddress; + /* 0x4C */ uint8_t macDSN; + /* 0x50 */ uint16_t macPANId; + /* 0x53 */ uint16_t macShortAddress; + /* 0x55 */ uint16_t macTransactionPersistenceTime; +#if 0 + /* Security MIB */ + /* 0x70 */ macACLEntryDescriptorSet + /* 0x71 */ macACLEntryDescriptorSetSize + /* 0x74 */ macDefaultSecurityMaterial + /* 0x72 */ macDefaultSecurity:1 + /* 0x75 */ macDefaultSecuritySuite:3 + /* 0x73 */ macDefaultSecurityMaterialLength:6 + /* 0x76 */ macSecurityMode:2 +#endif +}; + +/* forward declarations */ + +static int mac802154_reqdata (struct ieee802154_mac_s *mac, + uint8_t handle, + uint8_t *buf, + int len); + +static int mac802154_reqpurge (struct ieee802154_mac_s *mac, + uint8_t handle); + +static int mac802154_reqassociate (struct ieee802154_mac_s *mac, + uint16_t panid, + uint8_t *coordeadr); + +static int mac802154_reqdisassociate(struct ieee802154_mac_s *mac, + uint8_t *eadr, + uint8_t reason); + +static int mac802154_reqget (struct ieee802154_mac_s *mac, + int attribute); + +static int mac802154_reqgts (struct ieee802154_mac_s *mac, + uint8_t* characteristics); + +static int mac802154_reqreset (struct ieee802154_mac_s *mac, + bool setdefaults); + +static int mac802154_reqrxenable (struct ieee802154_mac_s *mac, + bool deferrable, + int ontime, + int duration); + +static int mac802154_reqscan (struct ieee802154_mac_s *mac, + uint8_t type, + uint32_t channels, + int duration); + +static int mac802154_reqset (struct ieee802154_mac_s *mac, + int attribute, + uint8_t *value, + int valuelen); + +static int mac802154_reqstart (struct ieee802154_mac_s *mac, + uint16_t panid, + int channel, + uint8_t bo, + uint8_t fo, + bool coord, + bool batext, + bool realign); + +static int mac802154_reqsync (struct ieee802154_mac_s *mac, + int channel, + bool track); + +static int mac802154_reqpoll (struct ieee802154_mac_s *mac, + uint8_t *coordaddr); + +static int mac802154_rspassociate (struct ieee802154_mac_s *mac, + uint8_t eadr, + uint16_t saddr, + int status); + +static int mac802154_rsporphan (struct ieee802154_mac_s *mac, + uint8_t *orphanaddr, + uint16_t saddr, + bool associated); + + +/* data */ +static const struct ieee802154_macops_s mac802154ops = +{ + .req_data = mac802154_reqdata + .req_purge = mac802154_reqpurge + .req_associate = mac802154_reqassociate + .req_disassociate= mac802154_reqdisassociate + .req_get = mac802154_reqget + .req_gts = mac802154_reqgts + .req_reset = mac802154_reqreset + .req_rxenable = mac802154_reqrxenable + .req_scan = mac802154_reqscan + .req_set = mac802154_reqset + .req_start = mac802154_reqstart + .req_sync = mac802154_reqsync + .req_poll = mac802154_reqpoll + .rsp_associate = mac802154_rspassociate + .rsp_orphan = mac802154_rsporphan +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mac802154_defaultmib + * + * Description: + * Set the MIB to its default values. + * + ****************************************************************************/ + +static int mac802154_defaultmib(FAR struct ieee802154_privmac_s *priv) +{ + priv->macAckWaitDuration = 0; + priv->macAssociationPermit = 0; + priv->macAutoRequest = 1; + priv->macBattLifeExt = 0; + priv->macBattLifeExtPeriods = 0; + priv->macMaxCSMABackoffs = 4; + + priv->macBeaconOrder = 15; + priv->macSuperframeOrder = 15; + + priv->macMinBE = 3; + priv->macGTSPermit = 1; + priv->macPromiscuousMode = 0; + priv->macRxOnWhenIdle = 0; + priv->macBeaconTxTime = 0x000000; + + priv->macBeaconPayloadLength = 0; + priv->macBSN = 0; /*shall be random*/ + priv->macCoordExtendedAddress[8]; + priv->macCoordShortAddress = 0xffff; + priv->macDSN = 0 /*shall be random*/; + priv->macPANId = 0xffff; + priv->macShortAddress = 0xffff; + priv->macTransactionPersistenceTime = 0x01f4; +#if 0 + /* Security MIB */ + priv->macACLEntryDescriptorSetSize = 0; + priv->macDefaultSecurity = 0; + priv->macDefaultSecuritySuite = 0; + priv->macDefaultSecurityMaterialLength = 0x15; + priv->macSecurityMode = 0; +#endif +} + +/**************************************************************************** + * Name: mac802154_applymib + * + * Description: + * Some parts of the MIB must be sent to the radio device. This routine + * calls the radio device routines to store the related parameters in the + * radio driver. It must be called each time a MIB parameter is changed. + * + ****************************************************************************/ + +static int mac802154_applymib(FAR struct ieee802154_privmac_s *priv) +{ + return OK; +} + +/**************************************************************************** + * API Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mac802154_reqdata + * + * Description: + * The MCPS-DATA.request primitive requests the transfer of a data SPDU + * (i.e., MSDU) from a local SSCS entity to a single peer SSCS entity. + * Confirmation is returned via the + * struct ieee802154_maccb_s->conf_data callback. + * + ****************************************************************************/ + +static int mac802154_reqdata(FAR struct ieee802154_mac_s *mac, + uint8_t handle, + uint8_t *buf, + int len) +{ + FAR struct ieee802154_privmac_s * priv = (FAR struct ieee802154_privmac_s *) mac; + return -ENOTTY; +} + +/**************************************************************************** + * Name: mac802154_reqpurge + * + * Description: + * The MCPS-PURGE.request primitive allows the next higher layer to purge an + * MSDU from the transaction queue. Confirmation is returned via + * the struct ieee802154_maccb_s->conf_purge callback. + * + ****************************************************************************/ + +static int mac802154_reqpurge(FAR struct ieee802154_mac_s *mac, + uint8_t handle) +{ + FAR struct ieee802154_privmac_s * priv = (FAR struct ieee802154_privmac_s *) mac; + return -ENOTTY; +} + +/**************************************************************************** + * Name: mac802154_reqassociate + * + * Description: + * The MLME-ASSOCIATE.request primitive allows a device to request an + * association with a coordinator. Confirmation is returned via the + * struct ieee802154_maccb_s->conf_associate callback. + * + ****************************************************************************/ + +static int mac802154_reqassociate(FAR struct ieee802154_mac_s *mac, + uint16_t panid, + uint8_t *coordeadr) +{ + FAR struct ieee802154_privmac_s * priv = (FAR struct ieee802154_privmac_s *) mac; + return -ENOTTY; +} + +/**************************************************************************** + * Name: mac802154_reqdisassociate + * + * Description: + * The MLME-DISASSOCIATE.request primitive is used by an associated device to + * notify the coordinator of its intent to leave the PAN. It is also used by + * the coordinator to instruct an associated device to leave the PAN. + * Confirmation is returned via the + * struct ieee802154_maccb_s->conf_disassociate callback. + * + ****************************************************************************/ + +static int mac802154_reqdisassociate(FAR struct ieee802154_mac_s *mac, + uint8_t *eadr, + uint8_t reason) +{ + FAR struct ieee802154_privmac_s * priv = (FAR struct ieee802154_privmac_s *) mac; + return -ENOTTY; +} + +/**************************************************************************** + * Name: mac802154_reqget + * + * Description: + * The MLME-GET.request primitive requests information about a given PIB + * attribute. Actual data is returned via the + * struct ieee802154_maccb_s->conf_get callback. + * + ****************************************************************************/ + +static int mac802154_reqget(FAR struct ieee802154_mac_s *mac, + int attribute) +{ + FAR struct ieee802154_privmac_s * priv = (FAR struct ieee802154_privmac_s *) mac; + return -ENOTTY; +} + +/**************************************************************************** + * Name: mac802154_reqgts + * + * Description: + * The MLME-GTS.request primitive allows a device to send a request to the PAN + * coordinator to allocate a new GTS or to deallocate an existing GTS. + * Confirmation is returned via the + * struct ieee802154_maccb_s->conf_gts callback. + * + ****************************************************************************/ + +static int mac802154_reqgts(FAR struct ieee802154_mac_s *mac, + uint8_t* characteristics) +{ + FAR struct ieee802154_privmac_s * priv = (FAR struct ieee802154_privmac_s *) mac; + return -ENOTTY; +} + +/**************************************************************************** + * Name: mac802154_reqreset + * + * Description: + * The MLME-RESET.request primitive allows the next higher layer to request + * that the MLME performs a reset operation. Confirmation is returned via + * the struct ieee802154_maccb_s->conf_reset callback. + * + ****************************************************************************/ + +static int mac802154_reqreset(FAR struct ieee802154_mac_s *mac, + bool setdefaults) +{ + FAR struct ieee802154_privmac_s * priv = (FAR struct ieee802154_privmac_s *) mac; + return -ENOTTY; +} + +/**************************************************************************** + * Name: mac802154_reqrxenable + * + * Description: + * The MLME-RX-ENABLE.request primitive allows the next higher layer to + * request that the receiver is enable for a finite period of time. + * Confirmation is returned via the + * struct ieee802154_maccb_s->conf_rxenable callback. + * + ****************************************************************************/ + +static int mac802154_reqrxenable(FAR struct ieee802154_mac_s *mac, + bool deferrable, + int ontime, + int duration) +{ + FAR struct ieee802154_privmac_s * priv = (FAR struct ieee802154_privmac_s *) mac; + return -ENOTTY; +} + +/**************************************************************************** + * Name: mac802154_reqscan + * + * Description: + * The MLME-SCAN.request primitive is used to initiate a channel scan over a + * given list of channels. A device can use a channel scan to measure the + * energy on the channel, search for the coordinator with which it associated, + * or search for all coordinators transmitting beacon frames within the POS of + * the scanning device. Scan results are returned + * via MULTIPLE calls to the struct ieee802154_maccb_s->conf_scan callback. + * This is a difference with the official 802.15.4 specification, implemented + * here to save memory. + * + ****************************************************************************/ + +static int mac802154_reqscan(FAR struct ieee802154_mac_s *mac, + uint8_t type, + uint32_t channels, + int duration) +{ + FAR struct ieee802154_privmac_s * priv = (FAR struct ieee802154_privmac_s *) mac; + return -ENOTTY; +} + +/**************************************************************************** + * Name: mac802154_reqset + * + * Description: + * The MLME-SET.request primitive attempts to write the given value to the + * indicated MAC PIB attribute. Confirmation is returned via the + * struct ieee802154_maccb_s->conf_set callback. + * + ****************************************************************************/ + +static int mac802154_reqset(FAR struct ieee802154_mac_s *mac, + int attribute, + uint8_t *value, + int valuelen) +{ + FAR struct ieee802154_privmac_s * priv = (FAR struct ieee802154_privmac_s *) mac; + return -ENOTTY; +} + +/**************************************************************************** + * Name: mac802154_reqstart + * + * Description: + * The MLME-START.request primitive makes a request for the device to start + * using a new superframe configuration. Confirmation is returned + * via the struct ieee802154_maccb_s->conf_start callback. + * + ****************************************************************************/ + +static int mac802154_reqstart(FAR struct ieee802154_mac_s *mac, + uint16_t panid, + int channel, + uint8_t bo, + uint8_t fo, + bool coord, + bool batext, + bool realign) +{ + FAR struct ieee802154_privmac_s * priv = (FAR struct ieee802154_privmac_s *) mac; + return -ENOTTY; +} + +/**************************************************************************** + * Name: mac802154_reqsync + * + * Description: + * The MLME-SYNC.request primitive requests to synchronize with the + * coordinator by acquiring and, if specified, tracking its beacons. + * Confirmation is returned via the + * struct ieee802154_maccb_s->int_commstatus callback. TOCHECK. + * + ****************************************************************************/ + +static int mac802154_reqsync(FAR struct ieee802154_mac_s *mac, + int channel, + bool track) +{ + FAR struct ieee802154_privmac_s * priv = (FAR struct ieee802154_privmac_s *) mac; + return -ENOTTY; +} + +/**************************************************************************** + * Name: mac802154_reqpoll + * + * Description: + * The MLME-POLL.request primitive prompts the device to request data from the + * coordinator. Confirmation is returned via the + * struct ieee802154_maccb_s->conf_poll callback, followed by a + * struct ieee802154_maccb_s->ind_data callback. + * + ****************************************************************************/ + +static int mac802154_reqpoll(FAR struct ieee802154_mac_s *mac, + uint8_t *coordaddr) +{ + FAR struct ieee802154_privmac_s * priv = (FAR struct ieee802154_privmac_s *) mac; + return -ENOTTY; +} + +/**************************************************************************** + * Name: mac802154_rspassociate + * + * Description: + * The MLME-ASSOCIATE.response primitive is used to initiate a response to an + * MLME-ASSOCIATE.indication primitive. + * + ****************************************************************************/ + +static int mac802154_rspassociate(FAR struct ieee802154_mac_s *mac, + uint8_t eadr, + uint16_t saddr, + int status) +{ + FAR struct ieee802154_privmac_s * priv = (FAR struct ieee802154_privmac_s *) mac; + return -ENOTTY; +} + +/**************************************************************************** + * Name: mac802154_rsporphan + * + * Description: + * The MLME-ORPHAN.response primitive allows the next higher layer of a + * coordinator to respond to the MLME-ORPHAN.indication primitive. + * + ****************************************************************************/ + +static int mac802154_rsporphan(FAR struct ieee802154_mac_s *mac, + uint8_t *orphanaddr, + uint16_t saddr, + bool associated) +{ + FAR struct ieee802154_privmac_s * priv = (FAR struct ieee802154_privmac_s *) mac; + return -ENOTTY; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mac802154_register + * + * Description: + * Create a 802.15.4 MAC device from a 802.15.4 compatible radio device. + * + ****************************************************************************/ + +FAR struct ieee802154_mac_s * mac802154_register(FAR struct ieee802154_radio_s *radiodev, unsigned int minor) +{ + FAR struct ieee802154_privmac_s *mac; + + /* allocate object */ + mac = (FAR struct ieee802154_privmac_s *)kmm_zalloc(sizeof(struct ieee802154_privmac_s)); + if(!mac) + { + return NULL; + } + + /* init fields */ + mac->pubmac.radio = radiodev; + mac->pubmac.ops = mac802154ops; + mac802154_defaultmib(mac); + mac802154_applymib(mac); + return &mac->pubmac; +} +