diff --git a/configs/clicker2-stm32/mrf24j40-radio/defconfig b/configs/clicker2-stm32/mrf24j40-radio/defconfig index b258d177c3..2455c08c41 100644 --- a/configs/clicker2-stm32/mrf24j40-radio/defconfig +++ b/configs/clicker2-stm32/mrf24j40-radio/defconfig @@ -125,7 +125,6 @@ CONFIG_ARCH_CORTEXM4=y # CONFIG_ARCH_CORTEXR7F is not set CONFIG_ARCH_FAMILY="armv7-m" CONFIG_ARCH_CHIP="stm32" -# CONFIG_ARCH_TOOLCHAIN_IAR is not set # CONFIG_ARMV7M_USEBASEPRI is not set CONFIG_ARCH_HAVE_CMNVECTOR=y # CONFIG_ARMV7M_CMNVECTOR is not set @@ -534,6 +533,7 @@ CONFIG_STM32_USART3_SERIALDRIVER=y # # USB Device Configuration # +# CONFIG_ARCH_TOOLCHAIN_IAR is not set CONFIG_ARCH_TOOLCHAIN_GNU=y # @@ -979,6 +979,7 @@ CONFIG_IOB_NCHAINS=0 # CONFIG_WIRELESS=y CONFIG_WIRELESS_IEEE802154=y +CONFIG_IEEE802154_DEFAULT_EADDR=0x00fade00deadbeef CONFIG_IEEE802154_MAC_DEV=y CONFIG_MAC802154_HPWORK=y CONFIG_IEEE802154_NTXDESC=3 @@ -1109,7 +1110,6 @@ CONFIG_LIB_SENDFILE_BUFSIZE=512 # # CONFIG_C99_BOOL8 is not set CONFIG_HAVE_CXX=y -CONFIG_HAVE_CXXINITIALIZE=y # CONFIG_CXX_NEWLONG is not set # @@ -1340,6 +1340,7 @@ CONFIG_NSH_ARCHINIT=y # Platform-specific Support # # CONFIG_PLATFORM_CONFIGDATA is not set +CONFIG_HAVE_CXXINITIALIZE=y # # System Libraries and NSH Add-Ons diff --git a/drivers/wireless/ieee802154/mrf24j40.c b/drivers/wireless/ieee802154/mrf24j40.c index 903b843c9c..90fd913334 100644 --- a/drivers/wireless/ieee802154/mrf24j40.c +++ b/drivers/wireless/ieee802154/mrf24j40.c @@ -103,6 +103,22 @@ #define MRF24J40_GTS_SLOTS 2 +/* + * Formula for calculating default macMaxFrameWaitTime is on pg. 130 + * + * For PHYs other than CSS and UWB, the attribute phyMaxFrameDuration is given by: + * + * phyMaxFrameDuration = phySHRDuration + + * ceiling([aMaxPHYPacketSize + 1] x phySymbolsPerOctet) + * + * where ceiling() is a function that returns the smallest integer value greater + * than or equal to its argument value. [1] pg. 158 +*/ + +#define MRF24J40_DEFAULT_MAX_FRAME_WAITTIME 1824 + +#define MRF24J40_SYMBOL_DURATION_PS 16000000 + /**************************************************************************** * Private Types ****************************************************************************/ @@ -123,27 +139,32 @@ struct mrf24j40_radio_s FAR const struct mrf24j40_lower_s *lower; FAR struct spi_dev_s *spi; /* Saved SPI interface instance */ - struct work_s irqwork; /* For deferring interrupt work to work queue */ - struct work_s pollwork; /* For deferring poll work to the work queue */ - sem_t exclsem; /* Exclusive access to this struct */ + struct work_s irqwork; /* For deferring interrupt work to work queue */ + struct work_s csma_pollwork; /* For deferring poll work to the work queue */ + struct work_s gts_pollwork; /* For deferring poll work to the work queue */ + + sem_t exclsem; /* Exclusive access to this struct */ struct ieee802154_addr_s addr; - 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 */ + 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 */ - /* Buffer Allocations */ + /* MAC PIB attributes */ + uint32_t max_frame_waittime; + + struct ieee802154_txdesc_s *txdelayed_desc; struct ieee802154_txdesc_s *csma_desc; - FAR struct iob_s *csma_frame; - bool csma_busy; + bool txdelayed_busy : 1; + bool csma_busy : 1; + bool reschedule_csma : 1; struct ieee802154_txdesc_s *gts_desc[MRF24J40_GTS_SLOTS]; - FAR struct iob_s *gts_frame[MRF24J40_GTS_SLOTS]; bool gts_busy[MRF24J40_GTS_SLOTS]; }; @@ -177,13 +198,15 @@ static int mrf24j40_interrupt(int irq, FAR void *context, FAR void *arg); static void mrf24j40_dopoll_csma(FAR void *arg); static void mrf24j40_dopoll_gts(FAR void *arg); -static int mrf24j40_csma_setup(FAR struct mrf24j40_radio_s *dev, - FAR struct iob_s *frame); +static int mrf24j40_norm_setup(FAR struct mrf24j40_radio_s *dev, + FAR struct iob_s *frame, bool csma); static int mrf24j40_gts_setup(FAR struct mrf24j40_radio_s *dev, uint8_t gts, FAR struct iob_s *frame); static int mrf24j40_setup_fifo(FAR struct mrf24j40_radio_s *dev, FAR struct iob_s *frame, uint32_t fifo_addr); +static inline void mrf24j40_norm_trigger(FAR struct mrf24j40_radio_s *dev); + static int mrf24j40_setchannel(FAR struct mrf24j40_radio_s *dev, uint8_t chan); static int mrf24j40_getchannel(FAR struct mrf24j40_radio_s *dev, @@ -214,41 +237,31 @@ static int mrf24j40_getcca(FAR struct mrf24j40_radio_s *dev, FAR struct ieee802154_cca_s *cca); static int mrf24j40_energydetect(FAR struct mrf24j40_radio_s *dev, FAR uint8_t *energy); -static int mrf24j40_rxenable(FAR struct mrf24j40_radio_s *dev, bool enable); +static void mrf24j40_mactimer(FAR struct mrf24j40_radio_s *dev, int numsymbols); /* Driver operations */ static int mrf24j40_bind(FAR struct ieee802154_radio_s *radio, FAR struct ieee802154_radiocb_s *radiocb); -static int mrf24j40_txnotify_csma(FAR struct ieee802154_radio_s *radio); -static int mrf24j40_txnotify_gts(FAR struct ieee802154_radio_s *radio); +static int mrf24j40_txnotify(FAR struct ieee802154_radio_s *radio, bool gts); +static int mrf24j40_txdelayed(FAR struct ieee802154_radio_s *radio, + FAR struct ieee802154_txdesc_s *txdesc, + uint32_t symboldelay); +static int mrf24j40_reset_attrs(FAR struct ieee802154_radio_s *radio); static int mrf24j40_get_attr(FAR struct ieee802154_radio_s *radio, - enum ieee802154_pib_attr_e pib_attr, + enum ieee802154_attr_e attr, FAR union ieee802154_attr_u *attrval); -static int mrf24j40_set_attr(FAR struct ieee802154_radio_s *radio, - enum ieee802154_pib_attr_e pib_attr, +static int mrf24j40_set_attr(FAR struct ieee802154_radio_s *radio, + enum ieee802154_attr_e attr, FAR const union ieee802154_attr_u *attrval); +static int mrf24j40_rxenable(FAR struct ieee802154_radio_s *dev, bool enable); +static int mrf24j40_req_rxenable(FAR struct ieee802154_radio_s *radio, + FAR struct ieee802154_rxenable_req_s *req); /**************************************************************************** * Private Data ****************************************************************************/ -/* These are pointers to ALL registered MRF24J40 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 const struct ieee802154_radioops_s mrf24j40_devops = -{ - mrf24j40_bind, - mrf24j40_txnotify_csma, - mrf24j40_txnotify_gts, - mrf24j40_get_attr, - mrf24j40_set_attr -}; - /**************************************************************************** * Radio Interface Functions ****************************************************************************/ @@ -264,7 +277,7 @@ static int mrf24j40_bind(FAR struct ieee802154_radio_s *radio, } /**************************************************************************** - * Function: mrf24j40_txnotify_csma + * Function: mrf24j40_txnotify * * Description: * Driver callback invoked when new TX data is available. This is a @@ -281,32 +294,49 @@ static int mrf24j40_bind(FAR struct ieee802154_radio_s *radio, * ****************************************************************************/ -static int mrf24j40_txnotify_csma(FAR struct ieee802154_radio_s *radio) +static int mrf24j40_txnotify(FAR struct ieee802154_radio_s *radio, bool gts) { FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; - /* Is our single work structure available? It may not be if there are - * pending interrupt actions and we will have to ignore the Tx - * availability action. - */ - - if (work_available(&dev->pollwork)) + if (gts) { - /* Schedule to serialize the poll on the worker thread. */ + /* Is our single work structure available? It may not be if there are + * pending interrupt actions and we will have to ignore the Tx + * availability action. + */ - work_queue(HPWORK, &dev->pollwork, mrf24j40_dopoll_csma, dev, 0); + if (work_available(&dev->gts_pollwork)) + { + /* Schedule to serialize the poll on the worker thread. */ + + work_queue(HPWORK, &dev->gts_pollwork, mrf24j40_dopoll_gts, dev, 0); + } + } + else + { + /* Is our single work structure available? It may not be if there are + * pending interrupt actions and we will have to ignore the Tx + * availability action. + */ + + if (work_available(&dev->csma_pollwork)) + { + /* Schedule to serialize the poll on the worker thread. */ + + work_queue(HPWORK, &dev->csma_pollwork, mrf24j40_dopoll_csma, dev, 0); + } } return OK; } /**************************************************************************** - * Function: mrf24j40_txnotify_gts + * Function: mrf24j40_txdelayed * * Description: - * Driver callback invoked when new TX data is available. This is a - * stimulus perform an out-of-cycle poll and, thereby, reduce the TX - * latency. + * Transmit a packet without regard to supeframe structure after a certain + * number of symbols. This function is used to send Data Request responses. + * It can also be used to send data immediately if the delay is set to 0. * * Parameters: * radio - Reference to the radio driver state structure @@ -318,40 +348,109 @@ static int mrf24j40_txnotify_csma(FAR struct ieee802154_radio_s *radio) * ****************************************************************************/ -static int mrf24j40_txnotify_gts(FAR struct ieee802154_radio_s *radio) +static int mrf24j40_txdelayed(FAR struct ieee802154_radio_s *radio, + FAR struct ieee802154_txdesc_s *txdesc, + uint32_t symboldelay) { FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; + uint8_t reg; + + /* Get exclusive access to the radio device */ - /* Is our single work structure available? It may not be if there are - * pending interrupt actions and we will have to ignore the Tx - * availability action. + if (sem_wait(&dev->exclsem) != 0) + { + return -EINTR; + } + + /* There should never be more than one of these transactions at once. */ + + DEBUGASSERT(!dev->txdelayed_busy); + + dev->txdelayed_desc = txdesc; + dev->txdelayed_busy = true; + + /* Disable the TX norm interrupt and clear it */ + + reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); + reg |= MRF24J40_INTCON_TXNIE; + mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); + + /* If after disabling the interrupt, the irqworker is not scheduled, there + * are no interrupts to worry about. However, if there is work scheduled, + * we need to process it before going any further. */ - if (work_available(&dev->pollwork)) + if (!work_available(&dev->irqwork)) { - /* Schedule to serialize the poll on the worker thread. */ + work_cancel(HPWORK, &dev->irqwork); + sem_post(&dev->exclsem); + mrf24j40_irqworker((FAR void *)dev); - work_queue(HPWORK, &dev->pollwork, mrf24j40_dopoll_gts, dev, 0); + /* Get exclusive access to the radio device */ + + if (sem_wait(&dev->exclsem) != 0) + { + return -EINTR; + } } + if (dev->csma_busy) + { + dev->reschedule_csma = true; + } + + mrf24j40_norm_setup(dev, txdesc->frame, false); + + if (symboldelay == 0) + { + mrf24j40_norm_trigger(dev); + } + else + { + mrf24j40_mactimer(dev, symboldelay); + } + + sem_post(&dev->exclsem); + return OK; } -static int mrf24j40_get_attr(FAR struct ieee802154_radio_s *radio, - enum ieee802154_pib_attr_e pib_attr, - FAR union ieee802154_attr_u *attrval) +static int mrf24j40_reset_attrs(FAR struct ieee802154_radio_s *radio) +{ + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; + + dev->max_frame_waittime = MRF24J40_DEFAULT_MAX_FRAME_WAITTIME; + + return OK; +} + +static int mrf24j40_get_attr(FAR struct ieee802154_radio_s *radio, + enum ieee802154_attr_e attr, + FAR union ieee802154_attr_u *attrval) { FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; int ret; - switch (pib_attr) + switch (attr) { - case IEEE802154_PIB_MAC_EXTENDED_ADDR: + case IEEE802154_ATTR_MAC_EXTENDED_ADDR: { memcpy(&attrval->mac.eaddr[0], &dev->addr.eaddr[0], 8); ret = IEEE802154_STATUS_SUCCESS; } break; + case IEEE802154_ATTR_MAC_MAX_FRAME_WAITTIME: + { + attrval->mac.max_frame_waittime = dev->max_frame_waittime; + ret = IEEE802154_STATUS_SUCCESS; + } + break; + case IEEE802154_ATTR_PHY_SYMBOL_DURATION: + { + attrval->phy.symdur_picosec = MRF24J40_SYMBOL_DURATION_PS; + ret = IEEE802154_STATUS_SUCCESS; + } + break; default: ret = IEEE802154_STATUS_UNSUPPORTED_ATTRIBUTE; } @@ -359,21 +458,33 @@ static int mrf24j40_get_attr(FAR struct ieee802154_radio_s *radio, } static int mrf24j40_set_attr(FAR struct ieee802154_radio_s *radio, - enum ieee802154_pib_attr_e pib_attr, + enum ieee802154_attr_e attr, FAR const union ieee802154_attr_u *attrval) { FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; int ret; - switch (pib_attr) + switch (attr) { - case IEEE802154_PIB_MAC_EXTENDED_ADDR: + case IEEE802154_ATTR_MAC_PANID: + { + mrf24j40_setpanid(dev, attrval->mac.panid); + ret = IEEE802154_STATUS_SUCCESS; + } + break; + case IEEE802154_ATTR_MAC_SHORT_ADDRESS: + { + mrf24j40_setsaddr(dev, attrval->mac.saddr); + ret = IEEE802154_STATUS_SUCCESS; + } + break; + case IEEE802154_ATTR_MAC_EXTENDED_ADDR: { mrf24j40_seteaddr(dev, &attrval->mac.eaddr[0]); ret = IEEE802154_STATUS_SUCCESS; } break; - case IEEE802154_PIB_MAC_PROMISCUOUS_MODE: + case IEEE802154_ATTR_MAC_PROMISCUOUS_MODE: { if (attrval->mac.promisc_mode) { @@ -387,22 +498,59 @@ static int mrf24j40_set_attr(FAR struct ieee802154_radio_s *radio, ret = IEEE802154_STATUS_SUCCESS; } break; - case IEEE802154_PIB_MAC_RX_ON_WHEN_IDLE: + case IEEE802154_ATTR_MAC_RX_ON_WHEN_IDLE: { dev->rxonidle = attrval->mac.rxonidle; - mrf24j40_rxenable(dev, dev->rxonidle); + mrf24j40_rxenable(radio, dev->rxonidle); + ret = IEEE802154_STATUS_SUCCESS; } break; default: ret = IEEE802154_STATUS_UNSUPPORTED_ATTRIBUTE; + break; } + return ret; } +static int mrf24j40_req_rxenable(FAR struct ieee802154_radio_s *radio, + FAR struct ieee802154_rxenable_req_s *req) +{ + return -ENOTTY; +} + /**************************************************************************** * Internal Functions ****************************************************************************/ +static void mrf24j40_mactimer(FAR struct mrf24j40_radio_s *dev, int numsymbols) +{ + uint16_t nhalfsym; + uint8_t reg; + + nhalfsym = (numsymbols << 1); + + /* Disable the interrupt, clear the timer count */ + + reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); + reg |= MRF24J40_INTCON_HSYMTMRIE; + mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); + + mrf24j40_setreg(dev->spi, MRF24J40_HSYMTMRL, 0x00); + mrf24j40_setreg(dev->spi, MRF24J40_HSYMTMRH, 0x00); + + reg &= ~MRF24J40_INTCON_HSYMTMRIE; + mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); + + /* Set the timer count and enable interrupts */ + + reg = (nhalfsym & 0xFF); + mrf24j40_setreg(dev->spi, MRF24J40_HSYMTMRL, reg); + + reg = (nhalfsym >> 8) & 0xFF; + mrf24j40_setreg(dev->spi, MRF24J40_HSYMTMRH, reg); +} + /**************************************************************************** * Function: mrf24j40_dopoll_csma * @@ -411,7 +559,7 @@ static int mrf24j40_set_attr(FAR struct ieee802154_radio_s *radio, * This is done: * * 1. After completion of a transmission (mrf24j40_txdone_csma), - * 2. When new TX data is available (mrf24j40_txnotify_csma), and + * 2. When new TX data is available (mrf24j40_txnotify), and * 3. After a TX timeout to restart the sending process * (mrf24j40_txtimeout_csma). * @@ -438,10 +586,8 @@ static void mrf24j40_dopoll_csma(FAR void *arg) if (!dev->csma_busy) { - /* need to somehow allow for a handle to be passed */ - - len = dev->radiocb->poll_csma(dev->radiocb, &dev->csma_desc, - &dev->csma_frame); + len = dev->radiocb->poll(dev->radiocb, false, &dev->csma_desc); + if (len > 0) { /* Now the txdesc is in use */ @@ -450,7 +596,8 @@ static void mrf24j40_dopoll_csma(FAR void *arg) /* Setup the transaction on the device in the CSMA FIFO */ - mrf24j40_csma_setup(dev, dev->csma_frame); + mrf24j40_norm_setup(dev, dev->csma_desc->frame, true); + mrf24j40_norm_trigger(dev); } } @@ -465,7 +612,7 @@ static void mrf24j40_dopoll_csma(FAR void *arg) * This is done: * * 1. After completion of a transmission (mrf24j40_txdone_gts), - * 2. When new TX data is available (mrf24j40_txnotify_gts), and + * 2. When new TX data is available (mrf24j40_txnotify), and * 3. After a TX timeout to restart the sending process * (mrf24j40_txtimeout_gts). * @@ -493,8 +640,8 @@ static void mrf24j40_dopoll_gts(FAR void *arg) { if (!dev->gts_busy[gts]) { - len = dev->radiocb->poll_gts(dev->radiocb, &dev->gts_desc[gts], - &dev->gts_frame[0]); + len = dev->radiocb->poll(dev->radiocb, true, &dev->gts_desc[gts]); + if (len > 0) { /* Now the txdesc is in use */ @@ -503,7 +650,7 @@ static void mrf24j40_dopoll_gts(FAR void *arg) /* Setup the transaction on the device in the open GTS FIFO */ - mrf24j40_gts_setup(dev, gts, dev->gts_frame[0]); + mrf24j40_gts_setup(dev, gts, dev->gts_desc[gts]->frame); } } } @@ -1258,15 +1405,15 @@ static int mrf24j40_energydetect(FAR struct mrf24j40_radio_s *dev, } /**************************************************************************** - * Name: mrf24j40_csma_setup + * Name: mrf24j40_norm_setup * * Description: - * Setup a CSMA transaction in the normal TX FIFO + * Setup a transaction in the normal TX FIFO * ****************************************************************************/ -static int mrf24j40_csma_setup(FAR struct mrf24j40_radio_s *dev, - FAR struct iob_s *frame) +static int mrf24j40_norm_setup(FAR struct mrf24j40_radio_s *dev, + FAR struct iob_s *frame, bool csma) { uint8_t reg; int ret; @@ -1277,27 +1424,64 @@ static int mrf24j40_csma_setup(FAR struct mrf24j40_radio_s *dev, reg &= ~MRF24J40_INTCON_TXNIE; mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); + /* Enable/Disable CSMA mode */ + + reg = mrf24j40_getreg(dev->spi, MRF24J40_TXMCR); + + if (csma) + { + reg &= ~MRF24J40_TXMCR_NOCSMA; + } + else + { + reg |= MRF24J40_TXMCR_NOCSMA; + } + + mrf24j40_setreg(dev->spi, MRF24J40_TXMCR, reg); + /* Setup the FIFO */ ret = mrf24j40_setup_fifo(dev, frame, MRF24J40_TXNORM_FIFO); - /* If the frame control field contains - * an acknowledgment request, set the TXNACKREQ bit. - * See IEEE 802.15.4/2003 7.2.1.1 page 112 for info. + /* If the frame control field contains an acknowledgment request, set the + * TXNACKREQ bit. See IEEE 802.15.4/2003 7.2.1.1 page 112 for info. */ - reg = MRF24J40_TXNCON_TXNTRIG; + reg = mrf24j40_getreg(dev->spi, MRF24J40_TXNCON); + if (frame->io_data[0] & IEEE802154_FRAMECTRL_ACKREQ) { reg |= MRF24J40_TXNCON_TXNACKREQ; } - - /* Trigger packet emission */ + else + { + reg &= ~MRF24J40_TXNCON_TXNACKREQ; + } mrf24j40_setreg(dev->spi, MRF24J40_TXNCON, reg); + return ret; } +/**************************************************************************** + * Name: mrf24j40_norm_trigger + * + * Description: + * Trigger the normal TX FIFO + * + ****************************************************************************/ + +static inline void mrf24j40_norm_trigger(FAR struct mrf24j40_radio_s *dev) +{ + uint8_t reg; + + reg = mrf24j40_getreg(dev->spi, MRF24J40_TXNCON); + + reg |= MRF24J40_TXNCON_TXNTRIG; + + mrf24j40_setreg(dev->spi, MRF24J40_TXNCON, reg); +} + /**************************************************************************** * Name: mrf24j40_gts_setup * @@ -1382,35 +1566,87 @@ static int mrf24j40_setup_fifo(FAR struct mrf24j40_radio_s *dev, static void mrf24j40_irqwork_txnorm(FAR struct mrf24j40_radio_s *dev) { - uint8_t txstat; + uint8_t reg; + enum ieee802154_status_e status; + bool framepending; /* Disable tx int */ - txstat = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); - txstat |= MRF24J40_INTCON_TXNIE; - mrf24j40_setreg(dev->spi, MRF24J40_INTCON, txstat); + reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); + reg |= MRF24J40_INTCON_TXNIE; + mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); /* Get the status from the device and copy the status into the tx desc. * The status for the normal FIFO is represented with bit TXNSTAT where * 0=success, 1= failure. */ - txstat = mrf24j40_getreg(dev->spi, MRF24J40_TXSTAT); - dev->csma_desc->conf->status = txstat & MRF24J40_TXSTAT_TXNSTAT; + reg = mrf24j40_getreg(dev->spi, MRF24J40_TXSTAT); - /* Inform the next layer of the transmission success/failure */ + /* TXNSTAT = 0: Transmission was successful + * TXNSTAT = 1: Transmission failed, retry count exceeded + */ - dev->radiocb->txdone(dev->radiocb, dev->csma_desc); + if (reg & MRF24J40_TXSTAT_TXNSTAT) + { + /* The number of retries of the most recent transmission is contained in the + * TXNRETRY (TXSTAT 0x24<7:6>) bits. The CCAFAIL (TXSTAT 0x24<5>) bit = 1 + * indicates if the failed transmission was due to the channel busy + * (CSMA-CA timed out). + */ + + if (reg & MRF24J40_TXSTAT_CCAFAIL) + { + status = IEEE802154_STATUS_CHANNEL_ACCESS_FAILURE; + } + else + { + status = IEEE802154_STATUS_NO_ACK; + } + } + else + { + status = IEEE802154_STATUS_SUCCESS; + } + + framepending = (mrf24j40_getreg(dev->spi, MRF24J40_TXNCON) & + MRF24J40_TXNCON_FPSTAT); - /* We are now done with the transaction */ + if (dev->txdelayed_busy) + { + /* Inform the next layer of the transmission success/failure */ - dev->csma_busy = 0; + dev->txdelayed_desc->conf->status = status; + dev->txdelayed_desc->framepending = framepending; + dev->radiocb->txdone(dev->radiocb, dev->txdelayed_desc); - /* Free the IOB */ + dev->txdelayed_busy = false; - iob_free(dev->csma_frame); + if (dev->reschedule_csma) + { + mrf24j40_norm_setup(dev, dev->csma_desc->frame, true); + mrf24j40_norm_trigger(dev); + dev->reschedule_csma = false; + } + } + else + { + /* Inform the next layer of the transmission success/failure */ - mrf24j40_dopoll_csma(dev); + dev->csma_desc->conf->status = status; + dev->csma_desc->framepending = framepending; + dev->radiocb->txdone(dev->radiocb, dev->csma_desc); + + /* We are now done with the transaction */ + + dev->csma_busy = 0; + + /* Must unlock the radio before calling poll */ + + sem_post(&dev->exclsem); + mrf24j40_dopoll_csma(dev); + while (sem_wait(&dev->exclsem) != 0) { } + } } /**************************************************************************** @@ -1456,10 +1692,6 @@ static void mrf24j40_irqwork_txgts(FAR struct mrf24j40_radio_s *dev, dev->gts_busy[gts]= 0; - /* Free the IOB */ - - iob_free(dev->gts_frame[gts]); - mrf24j40_dopoll_gts(dev); } @@ -1471,8 +1703,9 @@ static void mrf24j40_irqwork_txgts(FAR struct mrf24j40_radio_s *dev, * ****************************************************************************/ -static int mrf24j40_rxenable(FAR struct mrf24j40_radio_s *dev, bool enable) +static int mrf24j40_rxenable(FAR struct ieee802154_radio_s *radio, bool enable) { + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; uint8_t reg; if (enable) @@ -1510,6 +1743,8 @@ static void mrf24j40_irqwork_rx(FAR struct mrf24j40_radio_s *dev) uint32_t index; uint8_t reg; + wlinfo("RX interrupt\n"); + /* Disable rx int */ reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); @@ -1525,7 +1760,7 @@ static void mrf24j40_irqwork_rx(FAR struct mrf24j40_radio_s *dev) ind = ieee802154_ind_allocate(); if (ind == NULL) { - wlerr("ERROR: Unable to allocate data_ind. Discarding frame"); + wlerr("ERROR: Unable to allocate data_ind. Discarding frame\n"); goto done; } @@ -1533,7 +1768,7 @@ static void mrf24j40_irqwork_rx(FAR struct mrf24j40_radio_s *dev) addr = MRF24J40_RXBUF_BASE; - ind->frame->io_len= mrf24j40_getreg(dev->spi, addr++); + ind->frame->io_len = mrf24j40_getreg(dev->spi, addr++); /* TODO: This needs to be changed. It is inefficient to do the SPI read byte * by byte */ @@ -1597,18 +1832,37 @@ done: static void mrf24j40_irqworker(FAR void *arg) { FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)arg; - uint8_t intstat; + uint8_t intstat, intcon; DEBUGASSERT(dev); DEBUGASSERT(dev->spi); + /* Get exclusive access to the driver */ + + while (sem_wait(&dev->exclsem) != 0) { } + /* Read and store INTSTAT - this clears the register. */ intstat = mrf24j40_getreg(dev->spi, MRF24J40_INTSTAT); - //wlinfo("INT%02X\n", intstat); + wlinfo("INT%02X\n", intstat); /* Do work according to the pending interrupts */ + if ((intstat & MRF24J40_INTSTAT_HSYMTMRIF)) + { + /* As of now the only use for the MAC timer is for delayed transactions. + * Therefore, all we do here is trigger the TX norm FIFO + */ + + mrf24j40_norm_trigger(dev); + + /* Timers are one-shot, so disable the interrupt */ + + intcon = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); + intcon |= MRF24J40_INTCON_HSYMTMRIE; + mrf24j40_setreg(dev->spi, MRF24J40_INTCON, intcon); + } + if ((intstat & MRF24J40_INTSTAT_RXIF)) { /* A packet was received, retrieve it */ @@ -1636,6 +1890,10 @@ static void mrf24j40_irqworker(FAR void *arg) mrf24j40_irqwork_txgts(dev, 1); } + + /* Unlock the radio device */ + + sem_post(&dev->exclsem); /* Re-enable GPIO interrupts */ @@ -1721,7 +1979,14 @@ FAR struct ieee802154_radio_s *mrf24j40_init(FAR struct spi_dev_s *spi, sem_init(&dev->exclsem, 0, 1); - dev->radio.ops = &mrf24j40_devops; + dev->radio.bind = mrf24j40_bind; + dev->radio.txnotify = mrf24j40_txnotify; + dev->radio.txdelayed = mrf24j40_txdelayed; + dev->radio.reset_attrs = mrf24j40_reset_attrs; + dev->radio.get_attr = mrf24j40_get_attr; + dev->radio.set_attr = mrf24j40_set_attr; + dev->radio.rxenable = mrf24j40_rxenable; + dev->radio.req_rxenable = mrf24j40_req_rxenable; dev->lower = lower; dev->spi = spi; @@ -1746,6 +2011,13 @@ FAR struct ieee802154_radio_s *mrf24j40_init(FAR struct spi_dev_s *spi, mrf24j40_pacontrol(dev, MRF24J40_PA_AUTO); + /* For now, we want to always just have the frame pending bit set when + * acknowledging a Data Request command. The standard says that the coordinator + * can do this if it needs time to figure out whether it has data or not + */ + + mrf24j40_setreg(dev->spi, MRF24J40_ACKTMOUT, 0x39 | MRF24J40_ACKTMOUT_DRPACK); + dev->lower->enable(dev->lower, true); return &dev->radio; } diff --git a/drivers/wireless/ieee802154/mrf24j40.h b/drivers/wireless/ieee802154/mrf24j40.h index f9a8a35a5d..397b9f4e39 100644 --- a/drivers/wireless/ieee802154/mrf24j40.h +++ b/drivers/wireless/ieee802154/mrf24j40.h @@ -184,6 +184,11 @@ #define MRF24J40_TXMCR_BATLIFEXT 0x40 #define MRF24J40_TXMCR_NOCSMA 0x80 +/* ACKTMOUT bits */ + +#define MRF24J40_ACKTMOUT_MAWD 0xEF +#define MRF24J40_ACKTMOUT_DRPACK 0x80 + /* INTCON bits */ #define MRF24J40_INTCON_SLPIE 0x80 diff --git a/include/nuttx/wireless/ieee802154/ieee802154_mac.h b/include/nuttx/wireless/ieee802154/ieee802154_mac.h index 5f28cfa0c7..ac51825c9a 100644 --- a/include/nuttx/wireless/ieee802154/ieee802154_mac.h +++ b/include/nuttx/wireless/ieee802154/ieee802154_mac.h @@ -201,7 +201,11 @@ enum ieee802154_status_e { IEEE802154_STATUS_SUCCESS = 0, - IEEE802154_STATUS_BEACON_LOSS = 0xE0, + IEEE802154_STATUS_FAILURE, /* This value is not outlined in the standard. It + * is a catch-all for any failures that are not + * outlined in the standard + */ + IEEE802154_STATUS_BEACON_LOSS, IEEE802154_STATUS_CHANNEL_ACCESS_FAILURE, IEEE802154_STATUS_DENIED, IEEE802154_STATUS_DISABLE_TRX_FAILURE, @@ -222,93 +226,119 @@ enum ieee802154_status_e IEEE802154_STATUS_TX_ACTIVE, IEEE802154_STATUS_UNAVAILABLE_KEY, IEEE802154_STATUS_UNSUPPORTED_ATTRIBUTE, - IEEE802154_STATUS_FAILED /* This value is not outlined in the standard. It is - * a catch-all for any failures that are not outlined - * in the standard */ +}; + +static const char *IEEE802154_STATUS_STRING[] = +{ + "Success", + "Failure", + "Beacon loss", + "Channel access failure", + "Denied", + "Disable TRX failure", + "Failed security check", + "Frame too long", + "Invalid GTS", + "Invalid handle", + "Invalid parameter", + "No ack", + "No beacon", + "No data", + "No short address", + "Out of cap", + "PAN ID conflict", + "Realignment", + "Transaction expired", + "Transaction overflow", + "Tx active", + "Unavailable key", + "Unsupported attribute", }; /* IEEE 802.15.4 PHY/MAC PIB attributes IDs */ -enum ieee802154_pib_attr_e +enum ieee802154_attr_e { /* PHY PIB Attributes */ - IEEE802154_PIB_PHY_CURRENT_CHANNEL = 0x00, - IEEE802154_PIB_PHY_CHANNELS_SUPPORTED, - IEEE802154_PIB_PHY_TX_POWER_TOLERANCE, - IEEE802154_PIB_PHY_TX_POWER, - IEEE802154_PIB_PHY_CCA_MODE, - IEEE802154_PIB_PHY_CURRENT_PAGE, - IEEE802154_PIB_PHY_MAX_FRAME_DURATION, - IEEE802154_PIB_PHY_SHR_DURATION, - IEEE802154_PIB_PHY_SYM_PER_OCTET, - IEEE802154_PIB_PHY_PREAMBLE_SYM_LEN, - IEEE802154_PIB_PHY_UWB_DATARATES_SUP, - IEEE802154_PIB_PHY_CSS_LOW_DATARATE_SUP, - IEEE802154_PIB_PHY_UWB_COU_PULSES_SUP, - IEEE802154_PIB_PHY_UWB_CS_PULSES_SUP, - IEEE802154_PIB_PHY_UWB_LCP_PULSES_SUP, - IEEE802154_PIB_PHY_UWB_CURR_PULSE_SHAPE, - IEEE802154_PIB_PHY_UWB_COU_PULSE, - IEEE802154_PIB_PHY_UWB_CS_PULSE, - IEEE802154_PIB_PHY_UWB_LCP_WEIGHT1, - IEEE802154_PIB_PHY_UWB_LCP_WEIGHT2, - IEEE802154_PIB_PHY_UWB_LCP_WEIGHT3, - IEEE802154_PIB_PHY_UWB_LCP_WEIGHT4, - IEEE802154_PIB_PHY_UWB_LCP_DELAY2, - IEEE802154_PIB_PHY_UWB_LCP_DELAY3, - IEEE802154_PIB_PHY_UWB_LCP_DELAY4, - IEEE802154_PIB_PHY_RANGING, - IEEE802154_PIB_PHY_RANGING_CRYSTAL_OFFSET, - IEEE802154_PIB_PHY_RANGING_DPS, - IEEE802154_PIB_PHY_CURRENT_CODE, - IEEE802154_PIB_PHY_NATIVE_PRF, - IEEE802154_PIB_PHY_UWB_SCAN_BINS_PER_CHAN, - IEEE802154_PIB_PHY_UWB_INS_PREAMBLE_INTERVAL, - IEEE802154_PIB_PHY_UWB_TX_RMARKER, - IEEE802154_PIB_PHY_UWB_RX_RMARKER, - IEEE802154_PIB_PHY_RFRAME_PROC_TIME, - IEEE802154_PIB_PHY_CCA_DURATION, + IEEE802154_ATTR_PHY_CURRENT_CHANNEL = 0x00, + IEEE802154_ATTR_PHY_CHANNELS_SUPPORTED, + IEEE802154_ATTR_PHY_TX_POWER_TOLERANCE, + IEEE802154_ATTR_PHY_TX_POWER, + IEEE802154_ATTR_PHY_CCA_MODE, + IEEE802154_ATTR_PHY_CURRENT_PAGE, + IEEE802154_ATTR_PHY_MAX_FRAME_DURATION, + IEEE802154_ATTR_PHY_SHR_DURATION, + IEEE802154_ATTR_PHY_SYM_PER_OCTET, + IEEE802154_ATTR_PHY_PREAMBLE_SYM_LEN, + IEEE802154_ATTR_PHY_UWB_DATARATES_SUP, + IEEE802154_ATTR_PHY_CSS_LOW_DATARATE_SUP, + IEEE802154_ATTR_PHY_UWB_COU_PULSES_SUP, + IEEE802154_ATTR_PHY_UWB_CS_PULSES_SUP, + IEEE802154_ATTR_PHY_UWB_LCP_PULSES_SUP, + IEEE802154_ATTR_PHY_UWB_CURR_PULSE_SHAPE, + IEEE802154_ATTR_PHY_UWB_COU_PULSE, + IEEE802154_ATTR_PHY_UWB_CS_PULSE, + IEEE802154_ATTR_PHY_UWB_LCP_WEIGHT1, + IEEE802154_ATTR_PHY_UWB_LCP_WEIGHT2, + IEEE802154_ATTR_PHY_UWB_LCP_WEIGHT3, + IEEE802154_ATTR_PHY_UWB_LCP_WEIGHT4, + IEEE802154_ATTR_PHY_UWB_LCP_DELAY2, + IEEE802154_ATTR_PHY_UWB_LCP_DELAY3, + IEEE802154_ATTR_PHY_UWB_LCP_DELAY4, + IEEE802154_ATTR_PHY_RANGING, + IEEE802154_ATTR_PHY_RANGING_CRYSTAL_OFFSET, + IEEE802154_ATTR_PHY_RANGING_DPS, + IEEE802154_ATTR_PHY_CURRENT_CODE, + IEEE802154_ATTR_PHY_NATIVE_PRF, + IEEE802154_ATTR_PHY_UWB_SCAN_BINS_PER_CHAN, + IEEE802154_ATTR_PHY_UWB_INS_PREAMBLE_INTERVAL, + IEEE802154_ATTR_PHY_UWB_TX_RMARKER, + IEEE802154_ATTR_PHY_UWB_RX_RMARKER, + IEEE802154_ATTR_PHY_RFRAME_PROC_TIME, + IEEE802154_ATTR_PHY_CCA_DURATION, + IEEE802154_ATTR_PHY_SYMBOL_DURATION, /* Non-standard attribute */ /* MAC PIB Attributes */ - IEEE802154_PIB_MAC_EXTENDED_ADDR = 0x40, - IEEE802154_PIB_MAC_ACK_WAIT_DUR, - IEEE802154_PIB_MAC_ASSOCIATED_PANCOORD, - IEEE802154_PIB_MAC_ASSOCIATION_PERMIT, - IEEE802154_PIB_MAC_AUTO_REQUEST, - IEEE802154_PIB_MAC_BATT_LIFE_EXT, - IEEE802154_PIB_MAC_BATT_LIFE_EXT_PERIODS, - IEEE802154_PIB_MAC_BEACON_PAYLOAD, - IEEE802154_PIB_MAC_BEACON_PAYLOAD_LEN, - IEEE802154_PIB_MAC_BEACON_ORDER, - IEEE802154_PIB_MAC_BEACON_TX_TIME, - IEEE802154_PIB_MAC_BSN, - IEEE802154_PIB_MAC_COORD_EXT_ADDR, - IEEE802154_PIB_MAC_COORD_SHORT_ADDR, - IEEE802154_PIB_MAC_DSN, - IEEE802154_PIB_MAC_GTS_PERMIT, - IEEE802154_PIB_MAC_MAX_BE, - IEEE802154_PIB_MAC_MAX_CSMA_BACKOFFS, - IEEE802154_PIB_MAC_FRAME_TOTAL_WAIT_TIME, - IEEE802154_PIB_MAC_MAX_FRAME_RETRIES, - IEEE802154_PIB_MAC_MIN_BE, - IEEE802154_PIB_MAC_LIFS_PERIOD, - IEEE802154_PIB_MAC_SIFS_PERIOD, - IEEE802154_PIB_MAC_PANID, - IEEE802154_PIB_MAC_PROMISCUOUS_MODE, - IEEE802154_PIB_MAC_RANGING_SUPPORT, - IEEE802154_PIB_MAC_RESPONSE_WAIT_TIME, - IEEE802154_PIB_MAC_RX_ON_WHEN_IDLE, - IEEE802154_PIB_MAC_SECURITY_ENABLED, - IEEE802154_PIB_MAC_SHORT_ADDRESS, - IEEE802154_PIB_MAC_SUPERFRAME_ORDER, - IEEE802154_PIB_MAC_SYNC_SYMBOL_OFFSET, + IEEE802154_ATTR_MAC_EXTENDED_ADDR = 0x40, + IEEE802154_ATTR_MAC_ACK_WAIT_DUR, + IEEE802154_ATTR_MAC_ASSOCIATED_PANCOORD, + IEEE802154_ATTR_MAC_ASSOCIATION_PERMIT, + IEEE802154_ATTR_MAC_AUTO_REQUEST, + IEEE802154_ATTR_MAC_BATT_LIFE_EXT, + IEEE802154_ATTR_MAC_BATT_LIFE_EXT_PERIODS, + IEEE802154_ATTR_MAC_BEACON_PAYLOAD, + IEEE802154_ATTR_MAC_BEACON_PAYLOAD_LEN, + IEEE802154_ATTR_MAC_BEACON_ORDER, + IEEE802154_ATTR_MAC_BEACON_TX_TIME, + IEEE802154_ATTR_MAC_BSN, + IEEE802154_ATTR_MAC_COORD_EXT_ADDR, + IEEE802154_ATTR_MAC_COORD_SHORT_ADDR, + IEEE802154_ATTR_MAC_DSN, + IEEE802154_ATTR_MAC_GTS_PERMIT, + IEEE802154_ATTR_MAC_MAX_BE, + IEEE802154_ATTR_MAC_MAX_CSMA_BACKOFFS, + IEEE802154_ATTR_MAC_MAX_FRAME_WAITTIME, + IEEE802154_ATTR_MAC_MAX_FRAME_RETRIES, + IEEE802154_ATTR_MAC_MIN_BE, + IEEE802154_ATTR_MAC_LIFS_PERIOD, + IEEE802154_ATTR_MAC_SIFS_PERIOD, + IEEE802154_ATTR_MAC_PANID, + IEEE802154_ATTR_MAC_PROMISCUOUS_MODE, + IEEE802154_ATTR_MAC_RANGING_SUPPORT, + IEEE802154_ATTR_MAC_RESPONSE_WAIT_TIME, + IEEE802154_ATTR_MAC_RX_ON_WHEN_IDLE, + IEEE802154_ATTR_MAC_SECURITY_ENABLED, + IEEE802154_ATTR_MAC_SHORT_ADDRESS, + IEEE802154_ATTR_MAC_SUPERFRAME_ORDER, + IEEE802154_ATTR_MAC_SYNC_SYMBOL_OFFSET, IEEE802154_PIB_MAC_TIMESTAMP_SUPPORT, IEEE802154_PIB_MAC_TRANSACTION_PERSIST_TIME, IEEE802154_PIB_MAC_TX_CTRL_ACTIVE_DUR, IEEE802154_PIB_MAC_TX_CTRL_PAUSE_DUR, IEEE802154_PIB_MAC_TX_TOTAL_DUR, + IEEE802154_ATTR_MAC_DEVMODE, /* Non-standard */ /* MAC Security Attributes */ @@ -336,6 +366,7 @@ enum ieee802154_frametype_e }; /* MAC command IDs */ +/* TODO: Change terminology to be "current primitive" */ enum ieee802154_cmdid_e { @@ -352,7 +383,7 @@ enum ieee802154_cmdid_e enum ieee802154_devmode_e { - IEEE802154_DEVMODE_ENDPOINT, + IEEE802154_DEVMODE_ENDPOINT = 0x00, IEEE802154_DEVMODE_COORD, IEEE802154_DEVMODE_PANCOORD }; @@ -371,6 +402,10 @@ enum ieee802154_addrmode_e IEEE802154_ADDRMODE_NONE = 0, IEEE802154_ADDRMODE_SHORT = 2, IEEE802154_ADDRMODE_EXTENDED + + /* TODO: Add a IEEE802154_ADDRMODE_ANY setting for structs where both the + * extended and short addresses are safe to use. + */ }; struct ieee802154_addr_s @@ -502,6 +537,8 @@ union ieee802154_macattr_u uint8_t coord_eaddr[IEEE802154_EADDR_LEN]; uint16_t coord_saddr; + enum ieee802154_devmode_e devmode; + bool is_assoc; bool assoc_permit; bool auto_req; @@ -509,7 +546,7 @@ union ieee802154_macattr_u bool gts_permit; bool promisc_mode; bool rng_support; - bool resp_wait_time; + bool resp_waittime; bool rxonidle; bool sec_enabled; bool timestamp_support; @@ -519,7 +556,7 @@ union ieee802154_macattr_u uint8_t max_csma_backoffs : 3; uint8_t max_be : 4; uint8_t min_be : 4; - uint32_t max_frame_wait_time; + uint32_t max_frame_waittime; uint8_t max_retries; uint8_t lifs_period; uint8_t sifs_period; @@ -529,7 +566,7 @@ union ieee802154_macattr_u uint32_t tx_ctrl_pause_dur; uint32_t tx_total_dur; - uint8_t beacon_payload[IEEE802154_PIB_MAC_BEACON_PAYLOAD_LEN]; + uint8_t beacon_payload[IEEE802154_ATTR_MAC_BEACON_PAYLOAD_LEN]; uint8_t beacon_payload_len; uint8_t beacon_order; uint32_t beacon_tx_time : 24; @@ -543,7 +580,8 @@ union ieee802154_macattr_u union ieee802154_phyattr_u { uint8_t channel; - int32_t txpwr + int32_t txpwr; + uint32_t symdur_picosec; /* TODO: Fill this out as we implement supported get/set commands */ }; @@ -577,8 +615,8 @@ enum ieee802154_scantype_e struct ieee802154_frame_meta_s { - enum ieee802154_addrmode_e src_addrmode; /* Source Address Mode */ - struct ieee802154_addr_s dest_addr; /* Destination Address */ + enum ieee802154_addrmode_e srcaddr_mode; /* Source Address Mode */ + struct ieee802154_addr_s destaddr; /* Destination Address */ uint8_t msdu_handle; /* Handle assoc. with MSDU */ @@ -797,7 +835,7 @@ struct ieee802154_assoc_ind_s { /* Address of device requesting association. Always in extended mode */ - struct ieee802154_addr_s dev_addr; + uint8_t devaddr[IEEE802154_EADDR_LEN]; /* Capabilities of associating device */ @@ -822,7 +860,11 @@ struct ieee802154_assoc_resp_s { /* Address of device requesting association. Always in extended mode */ - struct ieee802154_addr_s dev_addr; + uint8_t devaddr[8]; + + /* Address assigned to the device. 0xFFFF if failure */ + + uint16_t assocsaddr; /* Status of association attempt */ @@ -851,7 +893,7 @@ struct ieee802154_assoc_conf_s * unsuccessful. */ - struct ieee802154_addr_s dev_addr; + uint16_t saddr; /* Status of association attempt */ @@ -1185,7 +1227,7 @@ struct ieee802154_scan_conf_s uint8_t ch_page; uint8_t num_channels; -#warning Figure out how to handle missing primitive semantics. See standard. + /* TODO: Figure out how to handle missing primitive semantics. See standard. */ }; /***************************************************************************** @@ -1198,7 +1240,7 @@ struct ieee802154_scan_conf_s struct ieee802154_get_req_s { - enum ieee802154_pib_attr_e pib_attr; + enum ieee802154_attr_e attr; union ieee802154_attr_u attrval; }; @@ -1218,7 +1260,7 @@ struct ieee802154_get_req_s struct ieee802154_set_req_s { - enum ieee802154_pib_attr_e pib_attr; + enum ieee802154_attr_e attr; union ieee802154_attr_u attrval; }; @@ -1318,7 +1360,7 @@ struct ieee802154_syncloss_ind_s struct ieee802154_poll_req_s { - struct ieee802154_addr_s coord_addr; + struct ieee802154_addr_s coordaddr; #ifdef CONFIG_IEEE802154_SECURITY /* Security information if enabled */ @@ -1396,13 +1438,16 @@ union ieee802154_notif_u struct ieee802154_notif_s { /* Must be first member so that we can interchange between the actual - *notification and this extended struct. + * notification and this extended struct. */ union ieee802154_notif_u u; enum ieee802154_notify_e notiftype; - /* Support a singly linked list */ + /* Support a singly linked list. For use by receivers. The MAC has it's own + * extended struct type with another forward link that the MAC uses internally + * to handle allocation and freeing. + */ FAR struct ieee802154_notif_s *flink; }; diff --git a/include/nuttx/wireless/ieee802154/ieee802154_radio.h b/include/nuttx/wireless/ieee802154/ieee802154_radio.h index e0ff8b664f..7e9cd14653 100644 --- a/include/nuttx/wireless/ieee802154/ieee802154_radio.h +++ b/include/nuttx/wireless/ieee802154/ieee802154_radio.h @@ -66,6 +66,14 @@ struct ieee802154_txdesc_s FAR struct ieee802154_txdesc_s *flink; + /* Destination Address */ + + struct ieee802154_addr_s destaddr; /* Only used for indirect transactions */ + + /* Pointer to the frame IOB */ + + FAR struct iob_s *frame; + /* Pointer to the data confirmation structure to be populated upon * success/failure of the transmission. */ @@ -74,6 +82,9 @@ struct ieee802154_txdesc_s enum ieee802154_frametype_e frametype; /* Frame type. Used by MAC layer to * control how tx done is handled */ + bool framepending; /* Did the ACK have the frame pending bit + * bit set */ + uint32_t purge_time; /* Time to purge transaction */ /* TODO: Add slotting information for GTS transactions */ }; @@ -82,37 +93,32 @@ struct ieee802154_txdesc_s struct ieee802154_radiocb_s { - CODE int (*poll_csma) (FAR const struct ieee802154_radiocb_s *radiocb, - FAR struct ieee802154_txdesc_s **tx_desc, - FAR struct iob_s **frame); - CODE int (*poll_gts) (FAR const struct ieee802154_radiocb_s *radiocb, - FAR struct ieee802154_txdesc_s **tx_desc, - FAR struct iob_s **frame); + CODE int (*poll) (FAR const struct ieee802154_radiocb_s *radiocb, + bool gts, FAR struct ieee802154_txdesc_s **tx_desc); CODE void (*txdone) (FAR const struct ieee802154_radiocb_s *radiocb, - FAR const struct ieee802154_txdesc_s *tx_desc); + FAR struct ieee802154_txdesc_s *tx_desc); CODE void (*rxframe) (FAR const struct ieee802154_radiocb_s *radiocb, FAR struct ieee802154_data_ind_s *ind); }; -struct ieee802154_radio_s; /* Forward reference */ - -struct ieee802154_radioops_s +struct ieee802154_radio_s { CODE int (*bind) (FAR struct ieee802154_radio_s *radio, FAR struct ieee802154_radiocb_s *radiocb); - CODE int (*txnotify_csma)(FAR struct ieee802154_radio_s *radio); - CODE int (*txnotify_gts)(FAR struct ieee802154_radio_s *radio); + CODE int (*txnotify)(FAR struct ieee802154_radio_s *radio, bool gts); + CODE int (*txdelayed)(FAR struct ieee802154_radio_s *radio, + FAR struct ieee802154_txdesc_s *txdesc, + uint32_t symboldelay); + CODE int (*reset_attrs) (FAR struct ieee802154_radio_s *radio); CODE int (*get_attr) (FAR struct ieee802154_radio_s *radio, - enum ieee802154_pib_attr_e pib_attr, + enum ieee802154_attr_e , FAR union ieee802154_attr_u *attrval); CODE int (*set_attr) (FAR struct ieee802154_radio_s *radio, - enum ieee802154_pib_attr_e pib_attr, + enum ieee802154_attr_e , FAR const union ieee802154_attr_u *attrval); -}; - -struct ieee802154_radio_s -{ - FAR const struct ieee802154_radioops_s *ops; + CODE int (*rxenable) (FAR struct ieee802154_radio_s *radio, bool enable); + CODE int (*req_rxenable)(FAR struct ieee802154_radio_s *radio, + FAR struct ieee802154_rxenable_req_s *req); }; #ifdef __cplusplus diff --git a/net/sixlowpan/sixlowpan_framer.c b/net/sixlowpan/sixlowpan_framer.c index 2d8d54480a..c67ae2768b 100644 --- a/net/sixlowpan/sixlowpan_framer.c +++ b/net/sixlowpan/sixlowpan_framer.c @@ -163,7 +163,7 @@ int sixlowpan_meta_data(FAR struct ieee802154_driver_s *ieee, /* Source address mode */ - meta->src_addrmode = pktmeta->sextended != 0? + meta->srcaddr_mode = pktmeta->sextended != 0? IEEE802154_ADDRMODE_EXTENDED : IEEE802154_ADDRMODE_SHORT; @@ -197,25 +197,25 @@ int sixlowpan_meta_data(FAR struct ieee802154_driver_s *ieee, { /* Broadcast requires short address mode. */ - meta->dest_addr.mode = IEEE802154_ADDRMODE_SHORT; - meta->dest_addr.saddr = 0; + meta->destaddr.mode = IEEE802154_ADDRMODE_SHORT; + meta->destaddr.saddr = 0; } else if (pktmeta->dextended != 0) { /* Extended destination address mode */ - meta->dest_addr.mode = IEEE802154_ADDRMODE_EXTENDED; - sixlowpan_eaddrcopy(&meta->dest_addr.eaddr, pktmeta->dest.eaddr.u8); + meta->destaddr.mode = IEEE802154_ADDRMODE_EXTENDED; + sixlowpan_eaddrcopy(&meta->destaddr.eaddr, pktmeta->dest.eaddr.u8); } else { /* Short destination address mode */ - meta->dest_addr.mode = IEEE802154_ADDRMODE_SHORT; - sixlowpan_saddrcopy(&meta->dest_addr.saddr, pktmeta->dest.saddr.u8); + meta->destaddr.mode = IEEE802154_ADDRMODE_SHORT; + sixlowpan_saddrcopy(&meta->destaddr.saddr, pktmeta->dest.saddr.u8); } - meta->dest_addr.panid = pktmeta->dpanid; + meta->destaddr.panid = pktmeta->dpanid; /* Handle associated with MSDU. Will increment once per packet, not * necesarily per frame: The same MSDU handle will be used for each diff --git a/net/sixlowpan/sixlowpan_utils.c b/net/sixlowpan/sixlowpan_utils.c index 75da3ed556..822127f7f7 100644 --- a/net/sixlowpan/sixlowpan_utils.c +++ b/net/sixlowpan/sixlowpan_utils.c @@ -195,7 +195,7 @@ int sixlowpan_src_panid(FAR struct ieee802154_driver_s *ieee, int ret; memcpy(arg.ifr_name, ieee->i_dev.d_ifname, IFNAMSIZ); - arg.u.getreq.pib_attr = IEEE802154_PIB_MAC_PANID; + arg.u.getreq.attr = IEEE802154_ATTR_MAC_PANID; ret = dev->d_ioctl(dev, MAC802154IOC_MLME_GET_REQUEST, (unsigned long)((uintptr_t)&arg)); if (ret < 0) diff --git a/wireless/ieee802154/Kconfig b/wireless/ieee802154/Kconfig index 9e12f8b1bb..7ffe2654f4 100644 --- a/wireless/ieee802154/Kconfig +++ b/wireless/ieee802154/Kconfig @@ -15,6 +15,12 @@ menuconfig WIRELESS_IEEE802154 if WIRELESS_IEEE802154 +config IEEE802154_DEFAULT_EADDR + hex "IEEE 802.15.4 Default Extended Address" + default 0x00fade00deadbeef + ---help--- + Set the default extended address to be used by MAC networks on init + config IEEE802154_MAC_DEV bool "Character driver for IEEE 802.15.4 MAC layer" default n diff --git a/wireless/ieee802154/Make.defs b/wireless/ieee802154/Make.defs index eedec934eb..da1b1bc05e 100644 --- a/wireless/ieee802154/Make.defs +++ b/wireless/ieee802154/Make.defs @@ -37,7 +37,12 @@ ifeq ($(CONFIG_WIRELESS_IEEE802154),y) # Include IEEE 802.15.4 support -CSRCS += mac802154.c mac802154_indalloc.c +CSRCS += mac802154.c mac802154_indalloc.c mac802154_assoc.c mac802154_disassoc.c +CSRCS += mac802154_bind.c mac802154_data.c mac802154_get_mhrlen.c +CSRCS += mac802154_getset.c mac802154_gts.c mac802154_ioctl.c +CSRCS += mac802154_notif.c mac802154_orphan.c mac802154_poll.c mac802154_purge.c +CSRCS += mac802154_reset.c mac802154_rxenable.c mac802154_scan.c mac802154_start.c +CSRCS += mac802154_sync.c # Include wireless devices build support diff --git a/wireless/ieee802154/mac802154.c b/wireless/ieee802154/mac802154.c index c57891f83c..51395e531b 100644 --- a/wireless/ieee802154/mac802154.c +++ b/wireless/ieee802154/mac802154.c @@ -2,8 +2,11 @@ * wireless/ieee802154/mac802154.c * * Copyright (C) 2016 Sebastien Lorquet. All rights reserved. + * Copyright (C) 2017 Gregory Nutt. All rights reserved. * Copyright (C) 2017 Verge Inc. All rights reserved. + * * Author: Sebastien Lorquet + * Author: Gregory Nutt * Author: Anthony Merlino * * Redistribution and use in source and binary forms, with or without @@ -53,347 +56,54 @@ #include #include "mac802154.h" +#include "mac802154_notif.h" +#include "mac802154_internal.h" +#include "mac802154_assoc.h" +#include "mac802154_data.h" +#include "mac802154_poll.h" #include #include -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ -/* Configuration ************************************************************/ -/* If processing is not done at the interrupt level, then work queue support - * is required. - */ - -#if !defined(CONFIG_SCHED_WORKQUEUE) -# error Work queue support is required in this configuration (CONFIG_SCHED_WORKQUEUE) -#else - - /* Use the low priority work queue if possible */ - -# if defined(CONFIG_MAC802154_HPWORK) -# define MAC802154_WORK HPWORK -# elif defined(CONFIG_MAC802154_LPWORK) -# define MAC802154_WORK LPWORK -# else -# error Neither CONFIG_MAC802154_HPWORK nor CONFIG_MAC802154_LPWORK defined -# endif -#endif - -#if !defined(CONFIG_MAC802154_NNOTIF) || CONFIG_MAC802154_NNOTIF <= 0 -# undef CONFIG_MAC802154_NNOTIF -# define CONFIG_MAC802154_NNOTIF 6 -#endif - -#if !defined(CONFIG_MAC802154_NTXDESC) || CONFIG_MAC802154_NTXDESC <= 0 -# undef CONFIG_MAC802154_NTXDESC -# define CONFIG_MAC802154_NTXDESC 3 -#endif - -#if CONFIG_MAC802154_NTXDESC > CONFIG_MAC802154_NNOTIF -#error CONFIG_MAC802154_NNOTIF must be greater than CONFIG_MAC802154_NTXDESC -#endif - -/**************************************************************************** - * Private Types - ****************************************************************************/ - -struct mac802154_txtrans_s -{ - /* Supports a singly linked list */ - - FAR struct mac802154_txtrans_s *flink; - FAR struct iob_s *frame; - uint8_t handle; - enum ieee802154_frametype_e frametype; - sem_t sem; -}; - -struct mac802154_unsec_mhr_s -{ - uint8_t length; - union - { - uint16_t frame_control; - uint8_t data[IEEE802154_MAX_UNSEC_MHR_OVERHEAD]; - } u; -}; - -struct mac802154_radiocb_s -{ - struct ieee802154_radiocb_s cb; - FAR struct ieee802154_privmac_s *priv; -}; - -/* The privmac structure holds the internal state of the MAC and is the - * underlying represention of the opaque MACHANDLE. It contains storage for - * the IEEE802.15.4 MIB attributes. - */ - -struct ieee802154_privmac_s -{ - FAR struct ieee802154_radio_s *radio; /* Contained IEEE802.15.4 radio dev */ - FAR const struct mac802154_maccb_s *cb; /* Contained MAC callbacks */ - FAR struct mac802154_radiocb_s radiocb; /* Interface to bind to radio */ - - sem_t exclsem; /* Support exclusive access */ - - /* Support a single transaction dedicated to commands. As of now I see no - * condition where you need to have more than one command frame simultaneously - */ - - struct - { - sem_t sem; /* Exclusive use of the cmdtrans */ - enum ieee802154_cmdid_e type; /* Type of cmd in the cmdtrans */ - struct mac802154_txtrans_s trans; /* Dedicated txframe for cmds */ - - /* Has the command been successfully sent. This is to help protect - * against an odd edge case that may or may not ever happen. The condition - * occurs when you receive a seemingly appropriate response to the command - * yet the command was never actually sent. - */ - - bool txdone; - } cmd; - - /* Pre-allocated notifications to be passed to the registered callback. These - * need to be freed by the application using mac802154_xxxxnotif_free when - * the callee layer is finished with it's use. - */ - - FAR struct ieee802154_notif_s *notif_free; - struct ieee802154_notif_s notif_alloc[CONFIG_MAC802154_NNOTIF]; - sq_queue_t notif_queue; - - FAR struct ieee802154_txdesc_s *txdesc_free; - struct ieee802154_txdesc_s txdesc_alloc[CONFIG_IEEE802154_NTXDESC]; - sq_queue_t txdesc_queue; - sq_queue_t txdone_queue; - - /* Work structures for offloading aynchronous work */ - - struct work_s tx_work; - struct work_s rx_work; - - /* Support a singly linked list of transactions that will be sent using the - * CSMA algorithm. On a non-beacon enabled PAN, these transactions will be - * sent whenever. On a beacon-enabled PAN, these transactions will be sent - * during the CAP of the Coordinator's superframe. - */ - - sq_queue_t csma_queue; - - /* Support a singly linked list of transactions that will be sent indirectly. - * This list should only be used by a MAC acting as a coordinator. These - * transactions will stay here until the data is extracted by the destination - * device sending a Data Request MAC command or if too much time passes. This - * list should also be used to populate the address list of the outgoing - * beacon frame. - */ - - sq_queue_t indirect_queue; - - /* Support a singly linked list of frames received */ - - sq_queue_t dataind_queue; - - /* MAC PIB attributes, grouped to save memory */ - - /* Holds all address information (Extended, Short, and PAN ID) for the MAC. */ - - struct ieee802154_addr_s addr; - - /* Holds all address information (Extended, Short) for Coordinator */ - - struct ieee802154_addr_s coordaddr; - - /* The maximum number of symbols to wait for an acknowledgement frame to - * arrive following a transmitted data frame. [1] pg. 126 - * - * NOTE: This may be able to be a 16-bit or even an 8-bit number. I wasn't - * sure at the time what the range of reasonable values was. - */ - - uint32_t ack_waitdur; - - /* The maximum time to wait either for a frame intended as a response to a - * data request frame or for a broadcast frame following a beacon with the - * Frame Pending field set to one. [1] pg. 127 - * - * NOTE: This may be able to be a 16-bit or even an 8-bit number. I wasn't - * sure at the time what the range of reasonable values was. - */ - - uint32_t max_frame_waittime; - - /* The maximum time (in unit periods) that a transaction is stored by a - * coordinator and indicated in its beacon. - */ - - uint16_t trans_persisttime; - - /* Contents of beacon payload */ - - uint8_t beacon_payload[IEEE802154_MAX_BEACON_PAYLOAD_LEN]; - uint8_t beacon_payload_len; /* Length of beacon payload */ - - uint8_t battlifeext_periods; /* # of backoff periods during which rx is - * enabled after the IFS following beacon */ - - uint8_t bsn; /* Seq. num added to tx beacon frame */ - uint8_t dsn; /* Seq. num added to tx data or MAC frame */ - uint8_t maxretries; /* Max # of retries alloed after tx failure */ - - /* The maximum time, in multiples of aBaseSuperframeDuration, a device shall - * wait for a response command frame to be available following a request - * command frame. [1] 128. - */ - - uint8_t resp_waittime; - - /* The total transmit duration (including PHY header and FCS) specified in - * symbols. [1] pg. 129. - */ - - uint32_t tx_totaldur; - - /* Start of 32-bit bitfield */ - - uint32_t isassoc : 1; /* Are we associated to the PAN */ - uint32_t assocpermit : 1; /* Are we allowing assoc. as a coord. */ - uint32_t autoreq : 1; /* Automatically send data req. if addr - * addr is in the beacon frame */ - - uint32_t battlifeext : 1; /* Is BLE enabled */ - uint32_t gtspermit : 1; /* Is PAN Coord. accepting GTS reqs. */ - uint32_t promisc : 1; /* Is promiscuous mode on? */ - uint32_t rngsupport : 1; /* Does MAC sublayer support ranging */ - uint32_t sec_enabled : 1; /* Does MAC sublayer have security en. */ - uint32_t timestamp_support : 1; /* Does MAC layer supports timestamping */ - - uint32_t max_csmabackoffs : 3; /* Max num backoffs for CSMA algorithm - * before declaring ch access failure */ - - uint32_t beaconorder : 4; /* Freq. that beacon is transmitted */ - - uint32_t superframeorder : 4; /* Length of active portion of outgoing - * superframe, including the beacon */ - - /* The offset, measured is symbols, between the symbol boundary at which the - * MLME captures the timestamp of each transmitted and received frame, and - * the onset of the first symbol past the SFD, namely the first symbol of - * the frames [1] pg. 129. - */ - - uint32_t sync_symboffset : 12; - - /* End of 32-bit bitfield */ - - /* Start of 32-bit bitfield */ - - uint32_t beacon_txtime : 24; /* Time of last beacon transmit */ - uint32_t minbe : 4; /* Min value of backoff exponent (BE) */ - uint32_t maxbe : 4; /* Max value of backoff exponent (BE) */ - - /* End of 32-bit bitfield */ - - /* Start of 32-bit bitfield */ - - uint32_t txctrl_activedur : 17; /* Duration for which tx is permitted to - * be active */ - uint32_t txctrl_pausedur : 1; /* Duration after tx before another tx is - * permitted. 0=2000, 1= 10000 */ - - /* What type of device is this node acting as */ - - enum ieee802154_devmode_e devmode : 2; - - bool csma_tryagain : 1; - bool gts_tryagain : 1; - - /* 10-bits remaining */ - - /* End of 32-bit bitfield. */ - - /* TODO: Add Security-related MAC PIB attributes */ -}; - /**************************************************************************** * Private Function Prototypes ****************************************************************************/ -/* Internal Functions */ - -static inline int mac802154_takesem(sem_t *sem); -#define mac802154_givesem(s) sem_post(s); +/* Data structure pools and allocation helpers */ static void mac802154_resetqueues(FAR struct ieee802154_privmac_s *priv); -static void mac802154_notifpool_init(FAR struct ieee802154_privmac_s *priv); -static FAR struct ieee802154_notif_s * - mac802154_notif_alloc(FAR struct ieee802154_privmac_s *priv); - -static int mac802154_defaultmib(FAR struct ieee802154_privmac_s *priv); -static int mac802154_applymib(FAR struct ieee802154_privmac_s *priv); - -static void mac802154_txdone_worker(FAR void *arg); -static void mac802154_rxframe_worker(FAR void *arg); - -static void mac802154_cmd_txdone(FAR struct ieee802154_privmac_s *priv, - FAR struct ieee802154_txdesc_s *txdesc); /* IEEE 802.15.4 PHY Interface OPs */ -static int mac802154_poll_csma(FAR const struct ieee802154_radiocb_s *radiocb, - FAR struct ieee802154_txdesc_s **tx_desc, - FAR struct iob_s **frame); - -static int mac802154_poll_gts(FAR const struct ieee802154_radiocb_s *radiocb, - FAR struct ieee802154_txdesc_s **tx_desc, - FAR struct iob_s **frame); +static int mac802154_poll(FAR const struct ieee802154_radiocb_s *radiocb, + bool gts, FAR struct ieee802154_txdesc_s **tx_desc); static void mac802154_txdone(FAR const struct ieee802154_radiocb_s *radiocb, - FAR const struct ieee802154_txdesc_s *tx_desc); + FAR struct ieee802154_txdesc_s *tx_desc); +static void mac802154_txdone_worker(FAR void *arg); static void mac802154_rxframe(FAR const struct ieee802154_radiocb_s *radiocb, FAR struct ieee802154_data_ind_s *ind); +static void mac802154_rxframe_worker(FAR void *arg); -/**************************************************************************** - * Private Data - ****************************************************************************/ +static void mac802154_rx_datareq(FAR struct ieee802154_privmac_s *priv, + FAR struct ieee802154_data_ind_s *ind); +static void mac802154_rx_dataframe(FAR struct ieee802154_privmac_s *priv, + FAR struct ieee802154_data_ind_s *ind); -/* Map between ieee802154_addrmode_e enum and actual address length */ +static void mac802154_purge_worker(FAR void *arg); -static const uint8_t mac802154_addr_length[4] = {0, 0, 2, 8}; +/* Watchdog Timeout Functions */ + +static void mac802154_timeout_expiry(int argc, uint32_t arg, ...); + +static uint32_t mac802154_symtoticks(FAR struct ieee802154_privmac_s *priv, + uint32_t symbols); /**************************************************************************** * Private Functions ****************************************************************************/ -/**************************************************************************** - * Name: mac802154_semtake - * - * Description: - * Acquire the semaphore used for access serialization. - * - ****************************************************************************/ - -static inline int mac802154_takesem(sem_t *sem) -{ - /* Take a count from the semaphore, possibly waiting */ - - if (sem_wait(sem) < 0) - { - /* EINTR is the only error that we expect */ - - int errcode = get_errno(); - DEBUGASSERT(errcode == EINTR); - return -errcode; - } - - return OK; -} - /**************************************************************************** * Name: mac802154_resetqueues * @@ -409,303 +119,294 @@ static void mac802154_resetqueues(FAR struct ieee802154_privmac_s *priv) sq_init(&priv->txdone_queue); sq_init(&priv->csma_queue); + sq_init(&priv->gts_queue); sq_init(&priv->indirect_queue); sq_init(&priv->dataind_queue); - sq_init(&priv->notif_queue); + /* Initialize the tx descriptor allocation pool */ + sq_init(&priv->txdesc_queue); - - for (i = 0; i < CONFIG_MAC802154_NNOTIF; i++) - { - sq_addlast((FAR sq_entry_t *)&priv->notif_alloc[i], &priv->notif_queue); - } - for (i = 0; i < CONFIG_MAC802154_NTXDESC; i++) { - sq_addlast((FAR sq_entry_t *)&priv->txdesc_alloc[i], &priv->txdesc_queue); + sq_addlast((FAR sq_entry_t *)&priv->txdesc_pool[i], &priv->txdesc_queue); } + sem_init(&priv->txdesc_sem, 0, CONFIG_MAC802154_NTXDESC); + + /* Initialize the notifcation allocation pool */ mac802154_notifpool_init(priv); } /**************************************************************************** - * Name: mac802154_notifpool_init + * Name: mac802154_txdesc_pool * * Description: - * This function initializes the notification structure pool. It allows the - * MAC to pass notifications and for the callee to free them when they are - * done using them, saving copying the data when passing. - * - ****************************************************************************/ - -static void mac802154_notifpool_init(FAR struct ieee802154_privmac_s *priv) -{ - FAR struct ieee802154_notif_s *pool = priv->notif_alloc; - int remaining = CONFIG_MAC802154_NNOTIF; - - priv->notif_free = NULL; - while (remaining > 0) - { - FAR struct ieee802154_notif_s *notif = pool; - - /* Add the next meta data structure from the pool to the list of - * general structures. - */ - - notif->flink = priv->notif_free; - priv->notif_free = notif; - - /* Set up for the next structure from the pool */ - - pool++; - remaining--; - } -} - -/**************************************************************************** - * Name: mac802154_notif_alloc - * - * Description: - * This function allocates a free notification structure from the free list - * to be used for passing to the registered notify callback. The callee software - * is responsible for freeing the notification structure after it is done using - * it via mac802154_notif_free. + * This function allocates a tx descriptor and the dependent notification (data + * confirmation) from the free list. The notification and tx descriptor will + * be freed seperately, both by the MAC layer either directly, or through + * mac802154_notif_free in the case of the notification. * * Assumptions: * priv MAC struct is locked when calling. * + * Notes: + * If any of the semaphore waits inside this function get interrupted, the + * function will release the MAC layer. If this function returns -EINTR, the + * calling code should NOT release the MAC semaphore. + * ****************************************************************************/ -static FAR struct ieee802154_notif_s * - mac802154_notif_alloc(FAR struct ieee802154_privmac_s *priv) + +int mac802154_txdesc_alloc(FAR struct ieee802154_privmac_s *priv, + FAR struct ieee802154_txdesc_s **txdesc, + bool allow_interrupt) { + int ret; FAR struct ieee802154_notif_s *notif; - if (priv->notif_free == NULL) + /* Try and take a count from the semaphore. If this succeeds, we have + * "reserved" the structure, but still need to unlink it from the free list. + * The MAC is already locked, so there shouldn't be any other conflicting calls + */ + + ret = sem_trywait(&priv->txdesc_sem); + + if (ret == OK) { - return NULL; + *txdesc = (FAR struct ieee802154_txdesc_s *)sq_remfirst(&priv->txdesc_queue); } - - notif = priv->notif_free; - priv->notif_free = notif->flink; - - return notif; -} - -/**************************************************************************** - * Name: mac802154_defaultmib - * - * Description: - * Set the MIB to its default values. - * - ****************************************************************************/ - -static int mac802154_defaultmib(FAR struct ieee802154_privmac_s *priv) -{ - priv->isassoc = false; /* Not associated with a PAN */ - priv->assocpermit = false; /* Device (if coord) not accepting association */ - priv->autoreq = true; /* Auto send data req if addr. in beacon */ - priv->battlifeext = false; /* BLE disabled */ - priv->beacon_payload_len = 0; /* Beacon payload NULL */ - priv->beaconorder = 15; /* Non-beacon enabled network */ - priv->superframeorder = 15; /* Length of active portion of outgoing SF */ - priv->beacon_txtime = 0; /* Device never sent a beacon */ -#warning Set BSN and DSN to random values! - priv->bsn = 0; - priv->dsn = 0; - priv->gtspermit = true; /* PAN Coord accepting GTS requests */ - priv->minbe = 3; /* Min value of backoff exponent (BE) */ - priv->maxbe = 5; /* Max value of backoff exponent (BE) */ - priv->max_csmabackoffs = 4; /* Max # of backoffs before failure */ - priv->maxretries = 3; /* Max # of retries allowed after failure */ - priv->promisc = false; /* Device not in promiscuous mode */ - priv->rngsupport = false; /* Ranging not yet supported */ - priv->resp_waittime = 32; /* 32 SF durations */ - priv->sec_enabled = false; /* Security disabled by default */ - priv->tx_totaldur = 0; /* 0 transmit duration */ - - priv->trans_persisttime = 0x01F4; - - /* Reset the Coordinator address */ - - priv->coordaddr.mode = IEEE802154_ADDRMODE_NONE; - priv->coordaddr.saddr = IEEE802154_SADDR_UNSPEC; - memcpy(&priv->coordaddr.eaddr[0], IEEE802154_EADDR_UNSPEC, - IEEE802154_EADDR_LEN); - - /* Reset the device's address */ - - priv->addr.mode = IEEE802154_ADDRMODE_NONE; - priv->addr.panid = IEEE802154_PAN_UNSPEC; - priv->addr.saddr = IEEE802154_SADDR_UNSPEC; - memcpy(&priv->addr.eaddr[0], IEEE802154_EADDR_UNSPEC, IEEE802154_EADDR_LEN); - - - /* These attributes are effected and determined based on the PHY. Need to - * figure out how to "share" attributes between the radio driver and this - * MAC layer - * - * macAckWaitDuration - * macBattLifeExtPeriods - * macMaxFrameTotalWaitTime - * macLIFSPeriod - * macSIFSPeriod - * macSyncSymbolOffset - * macTimestampSupported - * macTxControlActiveDuration - * macTxControlPauseDuration - * macRxOnWhenIdle - */ - - return OK; -} - -/**************************************************************************** - * 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; -} - -/**************************************************************************** - * Name: mac802154_poll_csma - * - * Description: - * Called from the radio driver through the callback struct. This function is - * called when the radio has room for another CSMA transaction. If the MAC - * layer has a CSMA transaction, it copies it into the supplied buffer and - * returns the length. A descriptor is also populated with the transaction. - * - ****************************************************************************/ - -static int mac802154_poll_csma(FAR const struct ieee802154_radiocb_s *radiocb, - FAR struct ieee802154_txdesc_s **txdesc, - FAR struct iob_s **frame) -{ - FAR struct mac802154_radiocb_s *cb = - (FAR struct mac802154_radiocb_s *)radiocb; - FAR struct ieee802154_privmac_s *priv; - FAR struct mac802154_txtrans_s *trans; - FAR struct ieee802154_txdesc_s *desc; - FAR struct ieee802154_notif_s *notif; - - DEBUGASSERT(cb != NULL && cb->priv != NULL); - priv = cb->priv; - - /* Get exclusive access to the driver structure. We don't care about any - * signals so if we see one, just go back to trying to get access again. - */ - - while (mac802154_takesem(&priv->exclsem) != 0); - - /* Check to see if there are any CSMA transactions waiting */ - - trans = (FAR struct mac802154_txtrans_s *)sq_remfirst(&priv->csma_queue); - mac802154_givesem(&priv->exclsem); - - if (trans != NULL) + else { - /* Allocate a Tx descriptor to pass */ + /* Unlock MAC so that other work can be done to free a notification */ - desc = (FAR struct ieee802154_txdesc_s *)sq_remfirst(&priv->txdesc_queue); - if (desc == NULL) + mac802154_givesem(&priv->exclsem); + + /* Take a count from the tx desc semaphore, waiting if necessary. We + * only return from here with an error if we are allowing interruptions + * and we received a signal */ + + ret = mac802154_takesem(&priv->txdesc_sem, allow_interrupt); + if (ret < 0) { - wlerr("ERROR: Failed to allocate ieee802154_txdesc_s"); - goto errout; + /* MAC is already released */ + + return -EINTR; } - /* Allocate a notif struct (ie data confirmation struct) to pass with - * the tx descriptor. - */ + /* If we've taken a count from the semaphore, we have "reserved" the struct + * but now we need to pop it off of the free list. We need to re-lock the + * MAC in order to ensure this happens correctly. + */ - notif = mac802154_notif_alloc(priv); - if (notif == NULL) + ret = mac802154_takesem(&priv->exclsem, allow_interrupt); + if (ret < 0) { - wlerr("ERROR: Failed to allocate ieee802154_notif_s"); - - /* Free the tx descriptor */ - - sq_addlast((FAR sq_entry_t *)desc, &priv->txdesc_queue); - goto errout; + mac802154_givesem(&priv->txdesc_sem); + return -EINTR; } - desc->conf = (FAR struct ieee802154_data_conf_s *)notif; - desc->conf->handle = trans->handle; - desc->frametype = trans->frametype; - - *frame = trans->frame; - *txdesc = desc; - - /* Now that we've passed off the data, notify the waiting thread. - * NOTE: The transaction was allocated on the waiting thread's stack so - * it will be automatically deallocated when that thread awakens and - * returns. */ - - sem_post(&trans->sem); - return (trans->frame->io_len); + /* We can now safely unlink the next free structure from the free list */ + + *txdesc = (FAR struct ieee802154_txdesc_s *)sq_remfirst(&priv->txdesc_queue); } - -errout: - /* Need to set flag to tell MAC to retry notifying radio layer about transmit - * since we couldn't allocate the required data structures at this time. + + /* We have now successfully allocated the tx descriptor. Now we need to allocate + * the notification for the data confirmation that gets passed along with the + * tx descriptor. These are allocated together, but not freed together. */ - priv->csma_tryagain = true; - mac802154_givesem(&priv->exclsem); - return 0; + ret = mac802154_notif_alloc(priv, ¬if, allow_interrupt); + if (ret < 0) + { + /* The mac802154_notif_alloc function follows the same rules as this + * function. If it returns -EINTR, the MAC layer is already released + */ + + /* We need to free the txdesc */ + + mac802154_txdesc_free(priv, *txdesc); + return -EINTR; + } + + (*txdesc)->conf = ¬if->u.dataconf; + + return OK; } /**************************************************************************** - * Name: mac802154_poll_gts + * Name: mac802154_setupindirect + * + * Description: + * Internal function used by various parts of the MAC layer. This function + * places the provided tx descriptor in the indirect list and manages the + * scheduling for purging the transaction if it does not get extracted in + * time. + * + * Assumptions: + * Called with the MAC locked + * + ****************************************************************************/ + +void mac802154_setupindirect(FAR struct ieee802154_privmac_s *priv, + FAR struct ieee802154_txdesc_s *txdesc) +{ + uint32_t ticks; + uint32_t symbols; + + /* Link the tx descriptor into the list */ + + sq_addlast((FAR sq_entry_t *)txdesc, &priv->indirect_queue); + + /* Update the timestamp for purging the transaction */ + + /* The maximum time (in unit periods) that a transaction is stored by a + * coordinator and indicated in its beacon. The unit period is governed by + * macBeaconOrder, BO, as follows: For 0 ≤ BO ≤ 14, the unit period will be + * aBaseSuperframeDuration × 2 BO . For BO = 15, the unit period will be + * aBaseSuperframeDuration. [1] pg. 129 + */ + + if (priv->beaconorder < 15) + { + symbols = priv->trans_persisttime * + (IEEE802154_BASE_SUPERFRAME_DURATION * (1 << priv->beaconorder)); + } + else + { + symbols = priv->trans_persisttime * IEEE802154_BASE_SUPERFRAME_DURATION; + } + + ticks = mac802154_symtoticks(priv, symbols); + + txdesc->purge_time = clock_systimer() + ticks; + + /* Check to see if the purge indirect timer is scheduled. If it is, when the + * timer fires, it will schedule the next purge timer event. Inherently, the + * queue will be in order of which transaction needs to be purged next. + * + * If the purge indirect timer has not been scheduled, schedule it for when + * this transaction should expire. + */ + + if (work_available(&priv->purge_work)) + { + //work_queue(MAC802154_WORK, &priv->purge_work, mac802154_purge_worker, + // (FAR void *)priv, ticks); + } +} + +/**************************************************************************** + * Name: mac802154_purge_worker + * + * Description: + * Worker function scheduled in order to purge expired indirect transactions. + * The first element in the list should always be removed. The list is searched + * and transactions are removed until a transaction has not yet expired. Then + * if there are any remaining transactions, the work function is rescheduled + * for the next expiring transaction. + * + ****************************************************************************/ + +static void mac802154_purge_worker(FAR void *arg) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)arg; + FAR struct ieee802154_txdesc_s *txdesc; + + /* Get exclusive access to the driver structure. We don't care about any + * signals so don't allow interruptions + */ + + mac802154_takesem(&priv->exclsem, false); + + while (1) + { + /* Pop transactions off indirect queue until the transaction timeout has not + * passed. + */ + + txdesc = (FAR struct ieee802154_txdesc_s *)sq_peek(&priv->indirect_queue); + + if (txdesc == NULL) + { + break; + } + + /* Should probably check a little ahead and remove the transaction if it is within + * a certain number of clock ticks away. There is no since in scheduling the + * timer to expire in only a few ticks. + */ + + if (clock_systimer() >= txdesc->purge_time) + { + /* Unlink the transaction */ + + sq_remfirst(&priv->indirect_queue); + + /* Free the IOB, the notification, and the tx descriptor */ + + iob_free(txdesc->frame); + ((FAR struct mac802154_notif_s *)txdesc->conf)->flink = priv->notif_free; + priv->notif_free = ((FAR struct mac802154_notif_s *)txdesc->conf); + mac802154_txdesc_free(priv, txdesc); + + wlinfo("Indirect TX purged"); + } + else + { + /* Reschedule the transaction for the next timeout */ + + work_queue(MAC802154_WORK, &priv->purge_work, mac802154_purge_worker, + (FAR void *)priv, txdesc->purge_time - clock_systimer()); + break; + } + } +} + +/**************************************************************************** + * Name: mac802154_poll * * Description: * Called from the radio driver through the callback struct. This function is - * called when the radio has room for another GTS transaction. If the MAC - * layer has a GTS transaction, it copies it into the supplied buffer and + * called when the radio has room for another transaction. If the MAC + * layer has a transaction, it copies it into the supplied buffer and * returns the length. A descriptor is also populated with the transaction. * ****************************************************************************/ -static int mac802154_poll_gts(FAR const struct ieee802154_radiocb_s *radiocb, - FAR struct ieee802154_txdesc_s **tx_desc, - FAR struct iob_s **frame) +static int mac802154_poll(FAR const struct ieee802154_radiocb_s *radiocb, + bool gts, FAR struct ieee802154_txdesc_s **txdesc) { FAR struct mac802154_radiocb_s *cb = (FAR struct mac802154_radiocb_s *)radiocb; FAR struct ieee802154_privmac_s *priv; - FAR struct mac802154_txtrans_s *trans; - FAR struct ieee802154_txdesc_s *desc; - int ret = 0; DEBUGASSERT(cb != NULL && cb->priv != NULL); priv = cb->priv; - /* Get exclusive access to the driver structure. We don't care about any - * signals so if we see one, just go back to trying to get access again. - */ + /* Get exclusive access to the driver structure. Ignore any EINTR signals */ - while (mac802154_takesem(&priv->exclsem) != 0); + mac802154_takesem(&priv->exclsem, false); -#warning Missing logic. + if (gts) + { + /* Check to see if there are any GTS transactions waiting */ + + *txdesc = (FAR struct ieee802154_txdesc_s *)sq_remfirst(&priv->gts_queue); + } + else + { + /* Check to see if there are any CSMA transactions waiting */ + + *txdesc = (FAR struct ieee802154_txdesc_s *)sq_remfirst(&priv->csma_queue); + } mac802154_givesem(&priv->exclsem); - return 0; - -errout: - /* Need to set flag to tell MAC to retry notifying radio layer about transmit - * since we couldn't allocate the required data structures at this time. - */ - - priv->gts_tryagain = true; - mac802154_givesem(&priv->exclsem); + if (*txdesc != NULL) + { + return (*txdesc)->frame->io_len; + } + return 0; } @@ -723,7 +424,7 @@ errout: ****************************************************************************/ static void mac802154_txdone(FAR const struct ieee802154_radiocb_s *radiocb, - FAR const struct ieee802154_txdesc_s *txdesc) + FAR struct ieee802154_txdesc_s *txdesc) { FAR struct mac802154_radiocb_s *cb = (FAR struct mac802154_radiocb_s *)radiocb; @@ -733,10 +434,10 @@ static void mac802154_txdone(FAR const struct ieee802154_radiocb_s *radiocb, priv = cb->priv; /* Get exclusive access to the driver structure. We don't care about any - * signals so if we see one, just go back to trying to get access again. + * signals so don't allow interruptions */ - while (mac802154_takesem(&priv->exclsem) != 0); + mac802154_takesem(&priv->exclsem, false); sq_addlast((FAR sq_entry_t *)txdesc, &priv->txdone_queue); @@ -766,16 +467,14 @@ static void mac802154_txdone_worker(FAR void *arg) FAR struct ieee802154_privmac_s *priv = (FAR struct ieee802154_privmac_s *)arg; FAR struct ieee802154_txdesc_s *txdesc; - FAR struct ieee802154_data_conf_s *conf; FAR struct ieee802154_notif_s *notif; - enum ieee802154_frametype_e frametype; - int count; + FAR struct mac802154_notif_s *privnotif; /* Get exclusive access to the driver structure. We don't care about any - * signals so if we see one, just go back to trying to get access again. + * signals so don't allow interruptions */ - while (mac802154_takesem(&priv->exclsem) != 0); + mac802154_takesem(&priv->exclsem, false); while (1) { @@ -786,112 +485,104 @@ static void mac802154_txdone_worker(FAR void *arg) break; } - count++; - - /* Once we get the frametype and data confirmation struct, we can free - * the tx descriptor. + /* Cast the data_conf to a notification. We get both the private and public + * notification structure to make it easier to use. */ - conf = txdesc->conf; - frametype = txdesc->frametype; - sq_addlast((FAR sq_entry_t *)txdesc, &priv->txdesc_queue); + privnotif = (FAR struct mac802154_notif_s *)txdesc->conf; + notif = &privnotif->pub; - /* Cast the data_conf to a notification */ - - notif = (FAR struct ieee802154_notif_s *)conf; - - switch(frametype) + switch(txdesc->frametype) { case IEEE802154_FRAME_DATA: { notif->notiftype = IEEE802154_NOTIFY_CONF_DATA; - /* Release the MAC then call the callback */ - + /* Release the MAC, call the callback, get exclusive access again */ mac802154_givesem(&priv->exclsem); priv->cb->notify(priv->cb, notif); + mac802154_takesem(&priv->exclsem, false); } break; - case IEEE802154_FRAME_COMMAND: { - mac802154_cmd_txdone(priv, txdesc); + switch (priv->curr_cmd) + { + case IEEE802154_CMD_ASSOC_REQ: + mac802154_txdone_assocreq(priv, txdesc); + break; + case IEEE802154_CMD_ASSOC_RESP: + break; + case IEEE802154_CMD_DISASSOC_NOT: + break; + case IEEE802154_CMD_DATA_REQ: + /* Data requests can be sent for 3 different reasons. + * + * 1. On a beacon-enabled PAN, this command shall be sent + * by a device when macAutoRequest is equal to TRUE and + * a beacon frame indicating that data are pending for + * that device is received from its coordinator. + * 2. when instructed to do so by the next higher layer on + * reception of the MLME-POLL.request primitive. + * 3. a device may send this command to the coordinator + * macResponseWaitTime after the acknowledgment to an + * association request command. + */ - /* We can deallocate the data conf notification as it is no longer - * needed. We don't use the public function here since we already - * have the MAC locked. Additionally, we are already handling the - * tx_tryagain here, so we wouldn't want to handle it twice. - */ - - notif->flink = priv->notif_free; - priv->notif_free = notif; - mac802154_givesem(&priv->exclsem); + switch (priv->curr_op) + { + case MAC802154_OP_ASSOC: + mac802154_txdone_datareq_assoc(priv, txdesc); + break; + case MAC802154_OP_POLL: + mac802154_txdone_datareq_poll(priv, txdesc); + break; + default: + break; + } + break; + case IEEE802154_CMD_PANID_CONF_NOT: + break; + case IEEE802154_CMD_ORPHAN_NOT: + break; + case IEEE802154_CMD_BEACON_REQ: + break; + case IEEE802154_CMD_COORD_REALIGN: + break; + case IEEE802154_CMD_GTS_REQ: + break; + default: + /* We can deallocate the data conf notification as it is no + * longer needed. We can't use the public function here + * since we already have the MAC locked. + */ + + privnotif->flink = priv->notif_free; + priv->notif_free = privnotif; + break; + } } break; - default: { - mac802154_givesem(&priv->exclsem); + /* We can deallocate the data conf notification as it is no longer + * needed. We can't use the public function here since we already + * have the MAC locked. + */ + + privnotif->flink = priv->notif_free; + priv->notif_free = privnotif; } break; - } + + /* Free the IOB and the tx descriptor */ + + iob_free(txdesc->frame); + mac802154_txdesc_free(priv, txdesc); } - /* If we've freed a tx descriptor or notification structure and a previous - * attempt at passing data to the radio layer failed due to insufficient - * available structures, try again now that we've freed some resources */ - - if (count > 0 && priv->csma_tryagain) - { - priv->csma_tryagain = false; - priv->radio->ops->txnotify_csma(priv->radio); - } - - if (count > 0 && priv->gts_tryagain) - { - priv->gts_tryagain = false; - priv->radio->ops->txnotify_gts(priv->radio); - } -} - -/**************************************************************************** - * Name: mac802154_cmd_txdone - * - * Description: - * Called from mac802154_txdone_worker, this is a helper function for - * handling command frames that have either successfully sent or failed. - * - ****************************************************************************/ - -static void mac802154_cmd_txdone(FAR struct ieee802154_privmac_s *priv, - FAR struct ieee802154_txdesc_s *txdesc) -{ - - /* Check to see what type of command it was. All information about the command - * will still be valid because it is protected by a semaphore. - */ - - switch (priv->cmd.type) - { - case IEEE802154_CMD_ASSOC_REQ: - if(txdesc->conf->status != IEEE802154_STATUS_SUCCESS) - { - /* if the association request command cannot be sent due to a - * channel access failure, the MAC sublayer shall notify the next - * higher layer. [1] pg. 33 - */ - - - } - else - { - priv->cmd.txdone = true; - } - break; - default: - break; - } + mac802154_givesem(&priv->exclsem); } /**************************************************************************** @@ -922,12 +613,14 @@ static void mac802154_rxframe(FAR const struct ieee802154_radiocb_s *radiocb, * signals so if we see one, just go back to trying to get access again. */ - while (mac802154_takesem(&priv->exclsem) != 0); + mac802154_takesem(&priv->exclsem, false); /* Push the iob onto the tail of the frame list for processing */ sq_addlast((FAR sq_entry_t *)ind, &priv->dataind_queue); + wlinfo("frame received\n"); + mac802154_givesem(&priv->exclsem); /* Schedule work with the work queue to process the completion further */ @@ -966,22 +659,21 @@ static void mac802154_rxframe_worker(FAR void *arg) * signals so if we see one, just go back to trying to get access again. */ - while (mac802154_takesem(&priv->exclsem) != 0); + mac802154_takesem(&priv->exclsem, false); - /* Push the iob onto the tail of the frame list for processing */ + /* Pop the iob from the head of the frame list for processing */ ind = (FAR struct ieee802154_data_ind_s *)sq_remfirst(&priv->dataind_queue); - if (ind == NULL) - { - mac802154_givesem(&priv->exclsem); - break; - } - /* Once we pop off the indication, we don't need to keep the mac locked */ mac802154_givesem(&priv->exclsem); + if (ind == NULL) + { + return; + } + /* Get a local copy of the frame to make it easier to access */ frame = ind->frame; @@ -1014,19 +706,19 @@ static void mac802154_rxframe_worker(FAR void *arg) { /* Get the destination PAN ID */ - ind->dest.panid = frame->io_data[frame->io_offset]; + memcpy(&ind->dest.panid, &frame->io_data[frame->io_offset], 2); frame->io_offset += 2; if (ind->dest.mode == IEEE802154_ADDRMODE_SHORT) { - ind->dest.saddr = frame->io_data[frame->io_offset]; + memcpy(&ind->dest.saddr, &frame->io_data[frame->io_offset], 2); frame->io_offset += 2; } else if (ind->dest.mode == IEEE802154_ADDRMODE_EXTENDED) { memcpy(&ind->dest.eaddr[0], &frame->io_data[frame->io_offset], IEEE802154_EADDR_LEN); - frame->io_offset += 8; + frame->io_offset += IEEE802154_EADDR_LEN; } } @@ -1036,24 +728,21 @@ static void mac802154_rxframe_worker(FAR void *arg) * is set, get the PAN ID from the header. */ - if (!panid_comp) + if (panid_comp) { - ind->src.panid = frame->io_data[frame->io_offset]; + /* The source PAN ID is equal to the destination PAN ID */ + + ind->src.panid = ind->dest.panid; + } + else + { + memcpy(&ind->src.panid, &frame->io_data[frame->io_offset], 2); frame->io_offset += 2; } - /* If the source address is included, and the PAN ID compression field - * is set, the source PAN ID is the same as the destination PAN ID - */ - - else - { - ind->src.panid = ind->dest.panid; - } - if (ind->src.mode == IEEE802154_ADDRMODE_SHORT) { - ind->src.saddr = frame->io_data[frame->io_offset]; + memcpy(&ind->src.saddr, &frame->io_data[frame->io_offset], 2); frame->io_offset += 2; } else if (ind->src.mode == IEEE802154_ADDRMODE_EXTENDED) @@ -1067,45 +756,567 @@ static void mac802154_rxframe_worker(FAR void *arg) ftype = (*frame_ctrl & IEEE802154_FRAMECTRL_FTYPE) >> IEEE802154_FRAMECTRL_SHIFT_FTYPE; - if (ftype == IEEE802154_FRAME_DATA) + switch (ftype) { - /* If there is a registered MCPS callback receiver registered, send - * the frame, otherwise, throw it out. - */ - - if (priv->cb->rxframe != NULL) + case IEEE802154_FRAME_DATA: { - priv->cb->rxframe(priv->cb, ind); + mac802154_rx_dataframe(priv, ind); } - else + break; + + case IEEE802154_FRAME_COMMAND: { + /* Get the command type. The command type is always the first + * field after the MHR. Consu;me the byte by increasing offset so that + * subsequent functions can start from the byte after the command ID. + */ + + uint8_t cmdtype = frame->io_data[frame->io_offset++]; + + switch (cmdtype) + { + case IEEE802154_CMD_ASSOC_REQ: + mac802154_rx_assocreq(priv, ind); + break; + case IEEE802154_CMD_ASSOC_RESP: + mac802154_rx_assocresp(priv, ind); + break; + case IEEE802154_CMD_DISASSOC_NOT: + break; + case IEEE802154_CMD_DATA_REQ: + mac802154_rx_datareq(priv, ind); + break; + case IEEE802154_CMD_PANID_CONF_NOT: + break; + case IEEE802154_CMD_ORPHAN_NOT: + break; + case IEEE802154_CMD_BEACON_REQ: + break; + case IEEE802154_CMD_COORD_REALIGN: + break; + case IEEE802154_CMD_GTS_REQ: + break; + } + /* Free the data indication struct from the pool */ ieee802154_ind_free(ind); } - } - else if (ftype == IEEE802154_FRAME_COMMAND) - { + break; - } - else if (ftype == IEEE802154_FRAME_BEACON) - { + case IEEE802154_FRAME_BEACON: + { + /* TODO: Add logic here to handle extracting association response from + * coordinator if beacon tracking was enabled during the Association + * operation. + * + * txdesc = mac802154_assoc_getresp(priv); + * sq_addlast((FAR sq_entry_t *)txdesc, &priv->csma_queue); + */ + } + break; + case IEEE802154_FRAME_ACK: + { + /* The radio layer is responsible for handling all ACKs and retries. + * If for some reason an ACK gets here, just throw it out. + */ + + wlinfo("ACK received\n"); + ieee802154_ind_free(ind); + } + break; + } + } +} + +/**************************************************************************** + * Name: mac802154_rx_dataframe + * + * Description: + * Function called from the generic RX Frame worker to parse and handle the + * reception of a data frame. + * + ****************************************************************************/ + +static void mac802154_rx_dataframe(FAR struct ieee802154_privmac_s *priv, + FAR struct ieee802154_data_ind_s *ind) +{ + FAR struct ieee802154_notif_s *notif; + + /* Get exclusive access to the MAC */ + + mac802154_takesem(&priv->exclsem, false); + + /* If we are currently performing a POLL operation and we've + * received a data response, use the addressing information + * to determine if it is extracted data. If the addressing info + * matches, notify the next highest layer using POLL.confirm + * primitive. If the addressing information does not match, + * handle the transaction like any other data transaction. + * + * Note: We can't receive frames without addressing information + * unless we are the PAN coordinator. And in that situation, we + * wouldn't be performing a POLL operation. Meaning: + * + * If the current operation is POLL, we aren't the PAN coordinator + * so the incoming frame CAN'T + * + * FIXME: Fix documentation + */ + + if (priv->curr_op == MAC802154_OP_POLL || priv->curr_op == MAC802154_OP_ASSOC) + { + /* If we are in promiscuous mode, we need to check if the + * frame is even for us first. If the address is not ours, + * then handle the frame like a normal transaction. + */ + + if (priv->promisc) + { + if (ind->dest.panid != priv->addr.panid) + { + goto notify_with_lock; + } + + if (ind->dest.mode == IEEE802154_ADDRMODE_SHORT && + ind->dest.saddr != priv->addr.saddr) + { + goto notify_with_lock; + } + else if (ind->dest.mode == IEEE802154_ADDRMODE_EXTENDED && + (memcmp(&ind->dest.eaddr[0], &priv->addr.eaddr[0], + IEEE802154_EADDR_LEN) != 0)) + { + goto notify_with_lock; + } + else + { + goto notify_with_lock; + } + } + + /* If this was our extracted data, the source addressing field can only + * be NONE if we are trying to extract data from the PAN coordinator. + * A PAN coordinator shouldn't be sending us a frame if it wasn't + * our extracted data. Therefore just assume if the address mode is set + * to NONE, we process it as our extracted frame + */ + + if (ind->src.mode != priv->cmd_desc->destaddr.mode) + { + goto notify_with_lock; + } + + if (ind->src.mode == IEEE802154_ADDRMODE_SHORT && + ind->src.saddr != priv->cmd_desc->destaddr.saddr) + { + goto notify_with_lock; + } + else if (ind->src.mode == IEEE802154_ADDRMODE_EXTENDED && + (memcmp(&ind->src.eaddr[0], &priv->cmd_desc->destaddr.eaddr[0], + IEEE802154_EADDR_LEN) != 0)) + { + goto notify_with_lock; + } + + /* If we've gotten this far, the frame is our extracted data. Cancel the + * timeout */ + + mac802154_timercancel(priv); + + /* If a frame is received from the coordinator with a zero length payload + * or if the frame is a MAC command frame, the MLME will issue the + * MLME-POLL.confirm primitive with a status of NO_DATA. [1] pg. 111 + */ + + mac802154_notif_alloc(priv, ¬if, false); + + if (priv->curr_op == MAC802154_OP_POLL) + { + notif->notiftype = IEEE802154_NOTIFY_CONF_POLL; + + if (ind->frame->io_offset == ind->frame->io_len) + { + ieee802154_ind_free(ind); + notif->u.pollconf.status = IEEE802154_STATUS_NO_DATA; + } + else + { + notif->u.pollconf.status = IEEE802154_STATUS_SUCCESS; + } + } + else if (priv->curr_op == MAC802154_OP_ASSOC) + { + /* If we ever receive a data frame back as a response to the + * association request, we assume it means there wasn't any data. + */ + + notif->notiftype = IEEE802154_NOTIFY_CONF_ASSOC; + notif->u.assocconf.status = IEEE802154_STATUS_NO_DATA; + } + + /* We are no longer performing the association operation */ + + priv->curr_op = MAC802154_OP_NONE; + priv->cmd_desc = NULL; + mac802154_givesem(&priv->op_sem); + + /* Release the MAC */ + + mac802154_givesem(&priv->exclsem); + + priv->cb->notify(priv->cb, notif); + + /* If there was data, pass it along */ + + if (ind->frame->io_len > ind->frame->io_offset) + { + goto notify_without_lock; + } + } + else + { +notify_with_lock: + + mac802154_givesem(&priv->exclsem); + +notify_without_lock: + + /* If there is a registered MCPS callback receiver registered, + * send the frame, otherwise, throw it out. + */ + + if (priv->cb->rxframe != NULL) + { + priv->cb->rxframe(priv->cb, ind); } else { - /* The radio layer is responsible for handling all ACKs and retries. If for - * some reason an ACK gets here, just throw it out. - */ + /* Free the data indication struct from the pool */ + + ieee802154_ind_free(ind); } } } +/**************************************************************************** + * Name: mac802154_rx_datareq + * + * Description: + * Function called from the generic RX Frame worker to parse and handle the + * reception of an Data Request MAC command frame. + * + ****************************************************************************/ + +static void mac802154_rx_datareq(FAR struct ieee802154_privmac_s *priv, + FAR struct ieee802154_data_ind_s *ind) +{ + FAR struct ieee802154_txdesc_s *txdesc; + FAR struct iob_s *iob; + uint16_t *frame_ctrl; + + /* Get exclusive access to the MAC */ + + mac802154_takesem(&priv->exclsem, false); + + /* Search the list of indirect transactions to see if there are any waiting + * for the requesting device. + */ + + /* TODO: I believe there is an issue here. If there is for some reason a + * outgoing data frame to a device who is currently requesting association, + * we will send the data frame as a response to an association request. We + * need to check for this condition. + */ + + txdesc = (FAR struct ieee802154_txdesc_s *)sq_peek(&priv->indirect_queue); + + if (txdesc == NULL) + { + goto no_data; + } + + do + { + if (txdesc->destaddr.mode == ind->src.mode) + { + if (txdesc->destaddr.mode == IEEE802154_ADDRMODE_SHORT) + { + if (txdesc->destaddr.saddr == ind->src.saddr) + { + /* Remove the transaction from the queue */ + + sq_rem((FAR sq_entry_t *)txdesc, &priv->indirect_queue); + + /* The addresses match, send the transaction immediately */ + + priv->radio->txdelayed(priv->radio, txdesc, 0); + break; + } + } + else if (txdesc->destaddr.mode == IEEE802154_ADDRMODE_EXTENDED) + { + if (memcmp(&txdesc->destaddr.eaddr[0], &ind->src.eaddr[0], + sizeof(IEEE802154_EADDR_LEN)) == 0) + { + /* Remove the transaction from the queue */ + + sq_rem((FAR sq_entry_t *)txdesc, &priv->indirect_queue); + + /* The addresses match, send the transaction immediately */ + + priv->radio->txdelayed(priv->radio, txdesc, 0); + break; + } + } + else + { + DEBUGASSERT(false); + } + } + + txdesc = (FAR struct ieee802154_txdesc_s *)sq_next((FAR sq_entry_t *)txdesc); + + if (txdesc == NULL) + { + goto no_data; + } + } + while (1); + + mac802154_givesem(&priv->exclsem); + return; + +no_data: + + /* If there is no data frame pending for the requesting device, the coordinator + * shall send a data frame without requesting acknowledgment to the device + * containing a zero length payload, indicating that no data are present, using + * one of the mechanisms described in this subclause. [1] pg. 43 + */ + + /* Allocate an IOB to put the frame in */ + + iob = iob_alloc(false); + DEBUGASSERT(iob != NULL); + + iob->io_flink = NULL; + iob->io_len = 0; + iob->io_offset = 0; + iob->io_pktlen = 0; + + iob->io_len += 2; + + /* Cast the first two bytes of the IOB to a uint16_t frame control field */ + + frame_ctrl = (FAR uint16_t *)&iob->io_data[0]; + + /* Ensure we start with a clear frame control field */ + + *frame_ctrl = 0; + + /* Set the frame type to Data */ + + *frame_ctrl |= IEEE802154_FRAME_DATA << IEEE802154_FRAMECTRL_SHIFT_FTYPE; + + /* Each time a data or a MAC command frame is generated, the MAC sublayer + * shall copy the value of macDSN into the Sequence Number field of the MHR + * of the outgoing frame and then increment it by one. [1] pg. 40. + */ + + iob->io_data[iob->io_len++] = priv->dsn++; + + /* Use the source address information from the received data request to + * respond. + */ + + *((uint16_t *)&iob->io_data[iob->io_len]) = ind->src.panid; + iob->io_len += 2; + + if (ind->src.mode == IEEE802154_ADDRMODE_SHORT) + { + memcpy(&iob->io_data[iob->io_len], &ind->src.saddr, 2); + iob->io_len += 2; + } + else if (ind->src.mode == IEEE802154_ADDRMODE_EXTENDED) + { + memcpy(&iob->io_data[iob->io_len], &ind->src.eaddr, IEEE802154_EADDR_LEN); + iob->io_len += IEEE802154_EADDR_LEN; + } + else + { + DEBUGASSERT(false); + } + + /* Set the destination addr mode inside the frame control field */ + + *frame_ctrl |= (ind->src.mode << IEEE802154_FRAMECTRL_SHIFT_DADDR); + + /* Check if the source PAN ID of the incoming request is the same as ours. */ + + if (ind->src.panid == priv->addr.panid) + { + *frame_ctrl |= IEEE802154_FRAMECTRL_PANIDCOMP; + } + else + { + /* Copy in our PAN ID */ + + memcpy(&iob->io_data[iob->io_len], &priv->addr.panid, 2); + iob->io_len += 2; + } + + /* Copy in our address using the mode that the device used to address us */ + + if (ind->dest.mode == IEEE802154_ADDRMODE_SHORT) + { + memcpy(&iob->io_data[iob->io_len], &priv->addr.saddr, 2); + iob->io_len += 2; + + *frame_ctrl |= (IEEE802154_ADDRMODE_SHORT << IEEE802154_FRAMECTRL_SHIFT_SADDR); + } + else + { + memcpy(&iob->io_data[iob->io_len], &ind->dest.eaddr, IEEE802154_EADDR_LEN); + iob->io_len += IEEE802154_EADDR_LEN; + *frame_ctrl |= (IEEE802154_ADDRMODE_EXTENDED << IEEE802154_FRAMECTRL_SHIFT_SADDR); + } + + /* Allocate the txdesc, waiting if necessary, allow interruptions */ + + mac802154_txdesc_alloc(priv, &txdesc, false); + + txdesc->frame = iob; + txdesc->frametype = IEEE802154_FRAME_DATA; + + mac802154_givesem(&priv->exclsem); + + priv->radio->txdelayed(priv->radio, txdesc, 0); +} + +/**************************************************************************** + * Name: mac802154_symtoticks + * + * Description: + * Helper function for converting symbols to system clock ticks + * + * Assumptions: + * priv MAC struct is locked when calling. + * + ****************************************************************************/ + +static uint32_t mac802154_symtoticks(FAR struct ieee802154_privmac_s *priv, + uint32_t symbols) +{ + union ieee802154_attr_u attrval; + uint32_t ret; + + /* First, get the symbol duration from the radio layer. Symbol duration is + * returned in picoseconds to ensure precision is kept when multiplying to + * get overall times. + */ + + priv->radio->get_attr(priv->radio, IEEE802154_ATTR_PHY_SYMBOL_DURATION, + &attrval); + + /* After this step, ret represents microseconds */ + + ret = ((uint64_t)attrval.phy.symdur_picosec * symbols) / (1000 * 1000); + + /* This method should only be used for things that can be late. For instance, + * it's always okay to wait a little longer before disabling your receiver. + * Therefore, we force the tick count to round up. + */ + + if (ret % USEC_PER_TICK == 0) + { + ret = ret/USEC_PER_TICK; + } + else + { + ret = ret/USEC_PER_TICK; + ret++; + } + + return ret; +} + +/**************************************************************************** + * Name: mac802154_timerstart + * + * Description: + * Helper function wrapping the watchdog timer interface. Helps isolate + * different operations from having to worry about work queues and watchdog + * timers. + * + * Assumptions: + * priv MAC struct is locked when calling. + * + ****************************************************************************/ + +int mac802154_timerstart(FAR struct ieee802154_privmac_s *priv, + uint32_t numsymbols, mac802154_worker_t worker) +{ + /* TODO: Add check to make sure timer is not already being used. I'd like to + * design this so that it absolutely never happens */ + + /* Convert the number of symbols to the number of CPU ticks */ + + uint32_t ticks = mac802154_symtoticks(priv, numsymbols); + + /* Save the function pointer to call if the timeout expires */ + + priv->timeout_worker = worker; + + /* Start the watchdog */ + + wd_start(priv->timeout, (int32_t)ticks, mac802154_timeout_expiry, 1, (uint32_t)priv); + + return OK; +} + +/**************************************************************************** + * Function: mac802154_timeout_expiry + * + * Description: + * The watchdog timed out. Called from the timer interrupt handler. + * + * Parameters: + * argc - The number of available arguments + * arg - The first argument + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by the watchdog logic. + * + ****************************************************************************/ + +static void mac802154_timeout_expiry(int argc, uint32_t arg, ...) +{ + FAR struct ieee802154_privmac_s *priv = (FAR struct ieee802154_privmac_s *)arg; + + /* There should never be a case where the timeout is used twice at the same + * time. */ + + DEBUGASSERT(work_available(&priv->timeout_work)); + + /* Check to make sure the function pointer is still valid */ + + DEBUGASSERT(priv->timeout_worker != NULL); + + work_queue(MAC802154_WORK, &priv->timeout_work, (worker_t)priv->timeout_worker, + priv, 0); +} + /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** + * Name: mac802154_create * * Description: @@ -1133,6 +1344,8 @@ MACHANDLE mac802154_create(FAR struct ieee802154_radio_s *radiodev) { FAR struct ieee802154_privmac_s *mac; FAR struct ieee802154_radiocb_s *radiocb; + uint8_t eaddr[IEEE802154_EADDR_LEN]; + int i; /* Allocate object */ @@ -1148,1147 +1361,48 @@ MACHANDLE mac802154_create(FAR struct ieee802154_radio_s *radiodev) sem_init(&mac->exclsem, 0, 1); - /* Allow exlusive access to the dedicated command transaction */ + /* Allow exclusive access to the dedicated command transaction */ - sem_init(&mac->cmd.sem, 0, 1); + sem_init(&mac->op_sem, 0, 1); - /* Setup the signaling semaphore for the dedicated command transaction */ + /* Setup watchdog for extraction timeout */ - sem_init(&mac->cmd.trans.sem, 0, 0); - sem_setprotocol(&mac->cmd.trans.sem, SEM_PRIO_NONE); + mac->timeout = wd_create(); /* Initialize fields */ mac->radio = radiodev; - mac802154_defaultmib(mac); - mac802154_applymib(mac); + mac802154_req_reset((MACHANDLE)mac, true); /* Initialize the Radio callbacks */ mac->radiocb.priv = mac; - radiocb = &mac->radiocb.cb; - radiocb->poll_csma = mac802154_poll_csma; - radiocb->poll_gts = mac802154_poll_gts; - radiocb->txdone = mac802154_txdone; - radiocb->rxframe = mac802154_rxframe; + radiocb = &mac->radiocb.cb; + radiocb->poll = mac802154_poll; + radiocb->txdone = mac802154_txdone; + radiocb->rxframe = mac802154_rxframe; /* Bind our callback structure */ - radiodev->ops->bind(radiodev, &mac->radiocb.cb); + radiodev->bind(radiodev, &mac->radiocb.cb); /* Initialize our various data pools */ ieee802154_indpool_initialize(); mac802154_resetqueues(mac); + + /* Set the default extended address */ + + for (i = 0; i < IEEE802154_EADDR_LEN; i++) + { + eaddr[i] = (CONFIG_IEEE802154_DEFAULT_EADDR >> (8 * i)) & 0xFF; + } + + memcpy(&mac->addr.eaddr, &eaddr[0], IEEE802154_EADDR_LEN); + mac->radio->set_attr(mac->radio, IEEE802154_ATTR_MAC_EXTENDED_ADDR, + (union ieee802154_attr_u *)&eaddr[0]); return (MACHANDLE)mac; } - -/**************************************************************************** - * Name: mac802154_bind - * - * Description: - * Bind the MAC callback table to the MAC state. - * - * Parameters: - * mac - Reference to the MAC driver state structure - * cb - MAC callback operations - * - * Returned Value: - * OK on success; Negated errno on failure. - * - ****************************************************************************/ - -int mac802154_bind(MACHANDLE mac, FAR const struct mac802154_maccb_s *cb) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - - priv->cb = cb; - return OK; -} - -/**************************************************************************** - * Name: mac802154_ioctl - * - * Description: - * Handle MAC and radio IOCTL commands directed to the MAC. - * - * Parameters: - * mac - Reference to the MAC driver state structure - * cmd - The IOCTL command - * arg - The argument for the IOCTL command - * - * Returned Value: - * OK on success; Negated errno on failure. - * - ****************************************************************************/ - -int mac802154_ioctl(MACHANDLE mac, int cmd, unsigned long arg) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - int ret = -EINVAL; - - FAR union ieee802154_macarg_u *macarg = - (FAR union ieee802154_macarg_u *)((uintptr_t)arg); - - DEBUGASSERT(priv != NULL); - - /* Check for IOCTLs aimed at the IEEE802.15.4 MAC layer */ - - if (_MAC802154IOCVALID(cmd)) - { - /* Handle the MAC IOCTL command */ - - switch (cmd) - { - case MAC802154IOC_MLME_ASSOC_REQUEST: - { - ret = mac802154_req_associate(mac, &macarg->assocreq); - } - break; - case MAC802154IOC_MLME_ASSOC_RESPONSE: - { - ret = mac802154_resp_associate(mac, &macarg->assocresp); - } - break; - case MAC802154IOC_MLME_DISASSOC_REQUEST: - { - ret = mac802154_req_disassociate(mac, &macarg->disassocreq); - } - break; - case MAC802154IOC_MLME_GET_REQUEST: - { - ret = mac802154_req_get(mac, macarg->getreq.pib_attr, - &macarg->getreq.attrval); - } - break; - case MAC802154IOC_MLME_GTS_REQUEST: - { - ret = mac802154_req_gts(mac, &macarg->gtsreq); - } - break; - case MAC802154IOC_MLME_ORPHAN_RESPONSE: - { - ret = mac802154_resp_orphan(mac, &macarg->orphanresp); - } - break; - case MAC802154IOC_MLME_RESET_REQUEST: - { - ret = mac802154_req_reset(mac, macarg->resetreq.rst_pibattr); - } - break; - case MAC802154IOC_MLME_RXENABLE_REQUEST: - { - ret = mac802154_req_rxenable(mac, &macarg->rxenabreq); - } - break; - case MAC802154IOC_MLME_SCAN_REQUEST: - { - ret = mac802154_req_scan(mac, &macarg->scanreq); - } - break; - case MAC802154IOC_MLME_SET_REQUEST: - { - ret = mac802154_req_set(mac, macarg->setreq.pib_attr, - &macarg->setreq.attrval); - } - break; - case MAC802154IOC_MLME_START_REQUEST: - { - ret = mac802154_req_start(mac, &macarg->startreq); - } - break; - case MAC802154IOC_MLME_SYNC_REQUEST: - { - ret = mac802154_req_sync(mac, &macarg->syncreq); - } - break; - case MAC802154IOC_MLME_POLL_REQUEST: - { - ret = mac802154_req_poll(mac, &macarg->pollreq); - } - break; - default: - wlerr("ERROR: Unrecognized cmd: %d\n", cmd); - ret = -ENOTTY; - break; - } - } - return ret; -} - -/**************************************************************************** - * MAC Interface Operations - ****************************************************************************/ - -/**************************************************************************** - * Name: mac802154_get_mhrlen - * - * Description: - * Calculate the MAC header length given the frame meta-data. - * - ****************************************************************************/ - -int mac802154_get_mhrlen(MACHANDLE mac, - FAR const struct ieee802154_frame_meta_s *meta) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - int ret = 3; /* Always frame control (2 bytes) and seq. num (1 byte) */ - - /* Check to make sure both the dest address and the source address are not set - * to NONE */ - - if (meta->dest_addr.mode == IEEE802154_ADDRMODE_NONE && - meta->src_addrmode == IEEE802154_ADDRMODE_NONE) - { - return -EINVAL; - } - - /* The source address can only be set to NONE if the device is the PAN coord */ - - if (meta->src_addrmode == IEEE802154_ADDRMODE_NONE && - priv->devmode != IEEE802154_DEVMODE_PANCOORD) - { - return -EINVAL; - } - - /* Add the destination address length */ - - ret += mac802154_addr_length[meta->dest_addr.mode]; - - /* Add the source address length */ - - ret += mac802154_addr_length[ meta->src_addrmode]; - - /* If both destination and source addressing information is present, the MAC - * sublayer shall compare the destination and source PAN identifiers. - * [1] pg. 41. - */ - - if (meta->src_addrmode != IEEE802154_ADDRMODE_NONE && - meta->dest_addr.mode != IEEE802154_ADDRMODE_NONE) - { - /* If the PAN identifiers are identical, the PAN ID Compression field - * shall be set to one, and the source PAN identifier shall be omitted - * from the transmitted frame. [1] pg. 41. - */ - - if (meta->dest_addr.panid == priv->addr.panid) - { - ret += 2; /* 2 bytes for destination PAN ID */ - return ret; - } - } - - /* If we are here, PAN ID compression is off, so include the dest and source - * PAN ID if the respective address is included - */ - - if (meta->src_addrmode != IEEE802154_ADDRMODE_NONE) - { - ret += 2; /* 2 bytes for source PAN ID */ - } - - if (meta->dest_addr.mode != IEEE802154_ADDRMODE_NONE) - { - ret += 2; /* 2 bytes for destination PAN ID */ - } - - return ret; -} - -/**************************************************************************** - * Name: mac802154_req_data - * - * 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 mac802154_maccb_s->conf_data callback. - * - ****************************************************************************/ - -int mac802154_req_data(MACHANDLE mac, - FAR const struct ieee802154_frame_meta_s *meta, - FAR struct iob_s *frame) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - FAR struct mac802154_txtrans_s trans; - uint16_t *frame_ctrl; - uint8_t mhr_len = 3; /* Start assuming frame control and seq. num */ - int ret; - - /* Check the required frame size */ - - if (frame->io_len > IEEE802154_MAX_PHY_PACKET_SIZE) - { - return -E2BIG; - } - - /* Cast the first two bytes of the IOB to a uint16_t frame control field */ - - frame_ctrl = (FAR uint16_t *)&frame->io_data[0]; - - /* Ensure we start with a clear frame control field */ - - *frame_ctrl = 0; - - /* Set the frame type to Data */ - - *frame_ctrl |= IEEE802154_FRAME_DATA << IEEE802154_FRAMECTRL_SHIFT_FTYPE; - - /* If the msduLength is greater than aMaxMACSafePayloadSize, the MAC - * sublayer will set the Frame Version to one. [1] pg. 118. - */ - - if ((frame->io_len - frame->io_offset) > IEEE802154_MAX_SAFE_MAC_PAYLOAD_SIZE) - { - *frame_ctrl |= IEEE802154_FRAMECTRL_VERSION; - } - - /* If the TXOptions parameter specifies that an acknowledged transmission - * is required, the AR field will be set appropriately, as described in - * 5.1.6.4 [1] pg. 118. - */ - - *frame_ctrl |= (meta->msdu_flags.ack_tx << IEEE802154_FRAMECTRL_SHIFT_ACKREQ); - - /* If the destination address is present, copy the PAN ID and one of the - * addresses, depending on mode, into the MHR. - */ - - if (meta->dest_addr.mode != IEEE802154_ADDRMODE_NONE) - { - memcpy(&frame->io_data[mhr_len], &meta->dest_addr.panid, 2); - mhr_len += 2; - - if (meta->dest_addr.mode == IEEE802154_ADDRMODE_SHORT) - { - memcpy(&frame->io_data[mhr_len], &meta->dest_addr.saddr, 2); - mhr_len += 2; - } - else if (meta->dest_addr.mode == IEEE802154_ADDRMODE_EXTENDED) - { - memcpy(&frame->io_data[mhr_len], &meta->dest_addr.eaddr, - IEEE802154_EADDR_LEN); - - mhr_len += IEEE802154_EADDR_LEN; - } - } - - /* Set the destination addr mode inside the frame control field */ - - *frame_ctrl |= (meta->dest_addr.mode << IEEE802154_FRAMECTRL_SHIFT_DADDR); - - /* From this point on, we need exclusive access to the privmac struct */ - - ret = mac802154_takesem(&priv->exclsem); - if (ret < 0) - { - wlerr("ERROR: mac802154_takesem failed: %d\n", ret); - return ret; - } - - /* If both destination and source addressing information is present, the MAC - * sublayer shall compare the destination and source PAN identifiers. - * [1] pg. 41. - */ - - if (meta->src_addrmode != IEEE802154_ADDRMODE_NONE && - meta->dest_addr.mode != IEEE802154_ADDRMODE_NONE) - { - /* If the PAN identifiers are identical, the PAN ID Compression field - * shall be set to one, and the source PAN identifier shall be omitted - * from the transmitted frame. [1] pg. 41. - */ - - if (meta->dest_addr.panid == priv->addr.panid) - { - *frame_ctrl |= IEEE802154_FRAMECTRL_PANIDCOMP; - } - } - - if (meta->src_addrmode != IEEE802154_ADDRMODE_NONE) - { - /* If the destination address is not included, or if PAN ID Compression - * is off, we need to include the Source PAN ID. - */ - - if ((meta->dest_addr.mode == IEEE802154_ADDRMODE_NONE) || - (!(*frame_ctrl & IEEE802154_FRAMECTRL_PANIDCOMP))) - { - memcpy(&frame->io_data[mhr_len], &priv->addr.panid, 2); - mhr_len += 2; - } - - if (meta->src_addrmode == IEEE802154_ADDRMODE_SHORT) - { - memcpy(&frame->io_data[mhr_len], &priv->addr.saddr, 2); - mhr_len += 2; - } - else if (meta->src_addrmode == IEEE802154_ADDRMODE_EXTENDED) - { - memcpy(&frame->io_data[mhr_len], &priv->addr.eaddr, - IEEE802154_EADDR_LEN); - - mhr_len += IEEE802154_EADDR_LEN; - } - } - - /* Set the source addr mode inside the frame control field */ - - *frame_ctrl |= (meta->src_addrmode << IEEE802154_FRAMECTRL_SHIFT_SADDR); - - /* Each time a data or a MAC command frame is generated, the MAC sublayer - * shall copy the value of macDSN into the Sequence Number field of the MHR - * of the outgoing frame and then increment it by one. [1] pg. 40. - */ - - frame->io_data[2] = priv->dsn++; - - /* The MAC header we just created must never have exceeded where the app - * data starts. This should never happen since the offset should have - * been set via the same logic to calculate the header length as the logic - * here that created the header - */ - - DEBUGASSERT(mhr_len == frame->io_offset); - - frame->io_offset = 0; /* Set the offset to 0 to include the header */ - - /* Setup our transaction */ - - trans.handle = meta->msdu_handle; - trans.frametype = IEEE802154_FRAME_DATA; - trans.frame = frame; - sem_init(&trans.sem, 0, 0); - sem_setprotocol(&trans.sem, SEM_PRIO_NONE); - - /* If the TxOptions parameter specifies that a GTS transmission is required, - * the MAC sublayer will determine whether it has a valid GTS as described - * 5.1.7.3. If a valid GTS could not be found, the MAC sublayer will discard - * the MSDU. If a valid GTS was found, the MAC sublayer will defer, if - * necessary, until the GTS. If the TxOptions parameter specifies that a GTS - * transmission is not required, the MAC sublayer will transmit the MSDU using - * either slotted CSMA-CA in the CAP for a beacon-enabled PAN or unslotted - * CSMA-CA for a nonbeacon-enabled PAN. Specifying a GTS transmission in the - * TxOptions parameter overrides an indirect transmission request. - * [1] pg. 118. - */ - - if (meta->msdu_flags.gts_tx) - { - /* TODO: Support GTS transmission. This should just change where we link - * the transaction. Instead of going in the CSMA transaction list, it - * should be linked to the GTS' transaction list. We'll need to check if - * the GTS is valid, and then find the GTS, before linking. Note, we also - * don't have to try and kick-off any transmission here. - */ - - return -ENOTSUP; - } - else - { - /* If the TxOptions parameter specifies that an indirect transmission is - * required and this primitive is received by the MAC sublayer of a - * coordinator, the data frame is sent using indirect transmission, as - * described in 5.1.5 and 5.1.6.3. [1] - */ - - if (meta->msdu_flags.indirect_tx) - { - /* If the TxOptions parameter specifies that an indirect transmission - * is required and if the device receiving this primitive is not a - * coordinator, the destination address is not present, or the - * TxOptions parameter also specifies a GTS transmission, the indirect - * transmission option will be ignored. [1] - * - * NOTE: We don't just ignore the parameter. Instead, we throw an - * error, since this really shouldn't be happening. - */ - - if (priv->devmode == IEEE802154_DEVMODE_PANCOORD && - meta->dest_addr.mode != IEEE802154_ADDRMODE_NONE) - { - /* Link the transaction into the indirect_trans list */ - - } - else - { - return -EINVAL; - } - } - else - { - /* Link the transaction into the CSMA transaction list */ - - sq_addlast((FAR sq_entry_t *)&trans, &priv->csma_queue); - - /* We no longer need to have the MAC layer locked. */ - - mac802154_givesem(&priv->exclsem); - - /* Notify the radio driver that there is data available */ - - priv->radio->ops->txnotify_csma(priv->radio); - - ret = sem_wait(&trans.sem); - if (ret < 0) - { - return -EINTR; - } - } - } - - sem_destroy(&trans.sem); - return OK; -} - -/**************************************************************************** - * Name: mac802154_req_purge - * - * 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 mac802154_maccb_s->conf_purge callback. - * - * NOTE: The standard specifies that confirmation should be indicated via - * the asynchronous MLME-PURGE.confirm primitve. However, in our - * implementation we synchronously return the status from the request. - * Therefore, we merge the functionality of the MLME-PURGE.request and - * MLME-PURGE.confirm primitives together. - * - ****************************************************************************/ - -int mac802154_req_purge(MACHANDLE mac, uint8_t msdu_handle) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - return -ENOTTY; -} - -/**************************************************************************** - * Name: mac802154_req_associate - * - * Description: - * The MLME-ASSOCIATE.request primitive allows a device to request an - * association with a coordinator. Confirmation is returned via the - * struct mac802154_maccb_s->conf_associate callback. - * - ****************************************************************************/ - -int mac802154_req_associate(MACHANDLE mac, - FAR struct ieee802154_assoc_req_s *req) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - FAR struct mac802154_txtrans_s trans; - FAR struct iob_s *iob; - FAR uint16_t *u16; - bool rxonidle; - int ret; - - /* On receipt of the MLME-ASSOCIATE.request primitive, the MLME of an - * unassociated device first updates the appropriate PHY and MAC PIB - * attributes, as described in 5.1.3.1, and then generates an association - * request command, as defined in 5.3.1 [1] pg.80 - */ - - /* Get exlusive access to the shared command transaction. This must happen - * before getting exclusive access to the MAC struct or else there could be - * a lockup condition. This would occur if another thread is using the cmdtrans - * but needs access to the MAC in order to unlock it. - */ - - if (sem_wait(&priv->cmd.sem) < 0) - { - /* EINTR is the only error that we expect */ - - int errcode = get_errno(); - DEBUGASSERT(errcode == EINTR); - return -errcode; - } - - /* Get exclusive access to the MAC */ - - ret = mac802154_takesem(&priv->exclsem); - if (ret < 0) - { - wlerr("ERROR: mac802154_takesem failed: %d\n", ret); - return ret; - } - - /* Set the channel and channel page of the PHY layer */ - - priv->radio->ops->set_attr(priv->radio, IEEE802154_PIB_PHY_CURRENT_CHANNEL, - (FAR const union ieee802154_attr_u *)&req->chnum); - - priv->radio->ops->set_attr(priv->radio, IEEE802154_PIB_PHY_CURRENT_PAGE, - (FAR const union ieee802154_attr_u *)&req->chpage); - - /* Set the PANID attribute */ - - priv->addr.panid = req->coordaddr.panid; - priv->coordaddr.panid = req->coordaddr.panid; - priv->radio->ops->set_attr(priv->radio, IEEE802154_PIB_MAC_PANID, - (FAR const union ieee802154_attr_u *)&req->coordaddr.panid); - - /* Set the coordinator address attributes */ - - priv->coordaddr.mode = req->coordaddr.mode; - - if (priv->coordaddr.mode == IEEE802154_ADDRMODE_SHORT) - { - priv->coordaddr.saddr = req->coordaddr.saddr; - memcpy(&priv->coordaddr.eaddr[0], IEEE802154_EADDR_UNSPEC, - IEEE802154_EADDR_LEN); - } - else if (priv->coordaddr.mode == IEEE802154_ADDRMODE_EXTENDED) - { - priv->coordaddr.saddr = IEEE802154_SADDR_UNSPEC; - memcpy(&priv->coordaddr.eaddr[0], &req->coordaddr.eaddr[0], - IEEE802154_EADDR_LEN); - } - else - { - ret = -EINVAL; - goto errout; - } - - /* Copy in the capabilities information bitfield */ - - priv->devmode = (req->capabilities.devtype) ? - IEEE802154_DEVMODE_COORD : IEEE802154_DEVMODE_ENDPOINT; - - /* Unlike other attributes, we can't simply cast this one since it is a bit - * in a bitfield. Casting it will give us unpredicatble results. Instead - * of creating a ieee802154_attr_u, we use a local bool. Allocating the - * ieee802154_attr_u value would take up more room on the stack since it is - * as large as the largest attribute type. - */ - - rxonidle = req->capabilities.rxonidle; - priv->radio->ops->set_attr(priv->radio, IEEE802154_PIB_MAC_RX_ON_WHEN_IDLE, - (FAR const union ieee802154_attr_u *)&rxonidle); - - /* Allocate an IOB to put the frame in */ - - iob = iob_alloc(false); - DEBUGASSERT(iob != NULL); - - iob->io_flink = NULL; - iob->io_len = 0; - iob->io_offset = 0; - iob->io_pktlen = 0; - - /* Get a uin16_t reference to the first two bytes. ie frame control field */ - - u16 = (FAR uint16_t *)&iob->io_data[0]; - - *u16 = (IEEE802154_FRAME_COMMAND << IEEE802154_FRAMECTRL_SHIFT_FTYPE); - *u16 |= IEEE802154_FRAMECTRL_ACKREQ; - *u16 |= (priv->coordaddr.mode << IEEE802154_FRAMECTRL_SHIFT_DADDR); - *u16 |= (IEEE802154_ADDRMODE_EXTENDED << IEEE802154_FRAMECTRL_SHIFT_SADDR); - - iob->io_len = 2; - - /* Each time a data or a MAC command frame is generated, the MAC sublayer - * shall copy the value of macDSN into the Sequence Number field of the MHR - * of the outgoing frame and then increment it by one. [1] pg. 40. - */ - - iob->io_data[iob->io_len++] = priv->dsn++; - - /* The Destination PAN Identifier field shall contain the identifier of the - * PAN to which to associate. [1] pg. 68 - */ - - memcpy(&iob->io_data[iob->io_len], &priv->coordaddr.panid, 2); - - /* The Destination Address field shall contain the address from the beacon - * frame that was transmitted by the coordinator to which the association - * request command is being sent. [1] pg. 68 - */ - - if (priv->coordaddr.mode == IEEE802154_ADDRMODE_SHORT) - { - memcpy(&iob->io_data[iob->io_len], &priv->coordaddr.saddr, 2); - iob->io_len += 2; - } - else if (priv->coordaddr.mode == IEEE802154_ADDRMODE_EXTENDED) - { - memcpy(&iob->io_data[iob->io_len], &priv->coordaddr.eaddr[0], - IEEE802154_EADDR_LEN); - iob->io_len += IEEE802154_EADDR_LEN; - } - - /* The Source PAN Identifier field shall contain the broadcast PAN identifier.*/ - - u16 = (uint16_t *)&iob->io_data[iob->io_len]; - *u16 = IEEE802154_SADDR_BCAST; - iob->io_len += 2; - - /* The Source Address field shall contain the value of macExtendedAddress. */ - - memcpy(&iob->io_data[iob->io_len], &priv->addr.eaddr[0], - IEEE802154_EADDR_LEN); - iob->io_len += IEEE802154_EADDR_LEN; - - /* Copy in the Command Frame Identifier */ - - iob->io_data[iob->io_len++] = IEEE802154_CMD_ASSOC_REQ; - - /* Copy in the capability information bits */ - - iob->io_data[iob->io_len] = 0; - iob->io_data[iob->io_len] |= (req->capabilities.devtype << - IEEE802154_CAPABILITY_SHIFT_DEVTYPE); - iob->io_data[iob->io_len] |= (req->capabilities.powersource << - IEEE802154_CAPABILITY_SHIFT_PWRSRC); - iob->io_data[iob->io_len] |= (req->capabilities.rxonidle << - IEEE802154_CAPABILITY_SHIFT_RXONIDLE); - iob->io_data[iob->io_len] |= (req->capabilities.security << - IEEE802154_CAPABILITY_SHIFT_SECURITY); - iob->io_data[iob->io_len] |= (req->capabilities.allocaddr << - IEEE802154_CAPABILITY_SHIFT_ALLOCADDR); - - iob->io_len++; - - /* Copy reference to the frame into the shared command transaction */ - - priv->cmd.trans.frame = iob; - priv->cmd.trans.frametype = IEEE802154_FRAME_COMMAND; - priv->cmd.type = IEEE802154_CMD_ASSOC_REQ; - - /* Link the transaction into the CSMA transaction list */ - - sq_addlast((FAR sq_entry_t *)&trans, &priv->csma_queue); - - /* We no longer need to have the MAC layer locked. */ - - mac802154_givesem(&priv->exclsem); - - /* TODO: Need to setup a timeout here so that we can return an error to the - * user if the device never receives a response. - */ - - /* Notify the radio driver that there is data available */ - - priv->radio->ops->txnotify_csma(priv->radio); - - /* Wait for the transaction to be passed to the radio layer */ - - ret = sem_wait(&priv->cmd.trans.sem); - if (ret < 0) - { - return -EINTR; - } - - return OK; - -errout: - mac802154_givesem(&priv->exclsem); - return ret; -} - -/**************************************************************************** - * Name: mac802154_req_disassociate - * - * 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 mac802154_maccb_s->conf_disassociate callback. - * - ****************************************************************************/ - -int mac802154_req_disassociate(MACHANDLE mac, - FAR struct ieee802154_disassoc_req_s *req) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - return -ENOTTY; -} - -/**************************************************************************** - * Name: mac802154_req_gts - * - * 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 mac802154_maccb_s->conf_gts callback. - * - ****************************************************************************/ - -int mac802154_req_gts(MACHANDLE mac, FAR struct ieee802154_gts_req_s *req) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - return -ENOTTY; -} - -/**************************************************************************** - * Name: mac802154_req_reset - * - * Description: - * The MLME-RESET.request primitive allows the next higher layer to request - * that the MLME performs a reset operation. - * - * NOTE: The standard specifies that confirmation should be provided via - * via the asynchronous MLME-RESET.confirm primitve. However, in our - * implementation we synchronously return the value immediately. Therefore, - * we merge the functionality of the MLME-RESET.request and MLME-RESET.confirm - * primitives together. - * - * Input Parameters: - * mac - Handle to the MAC layer instance - * rst_pibattr - Whether or not to reset the MAC PIB attributes to defaults - * - ****************************************************************************/ - -int mac802154_req_reset(MACHANDLE mac, bool rst_pibattr) -{ - FAR struct ieee802154_privmac_s * priv = - (FAR struct ieee802154_privmac_s *) mac; - return -ENOTTY; -} - -/**************************************************************************** - * Name: mac802154_req_rxenable - * - * 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 mac802154_maccb_s->conf_rxenable callback. - * - ****************************************************************************/ - -int mac802154_req_rxenable(MACHANDLE mac, - FAR struct ieee802154_rxenable_req_s *req) -{ - FAR struct ieee802154_privmac_s * priv = - (FAR struct ieee802154_privmac_s *)mac; - return -ENOTTY; -} - -/**************************************************************************** - * Name: mac802154_req_scan - * - * 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 mac802154_maccb_s->conf_scan callback. - * This is a difference with the official 802.15.4 specification, implemented - * here to save memory. - * - ****************************************************************************/ - -int mac802154_req_scan(MACHANDLE mac, FAR struct ieee802154_scan_req_s *req) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - return -ENOTTY; -} - -/**************************************************************************** - * Name: mac802154_req_get - * - * Description: - * The MLME-GET.request primitive requests information about a given PIB - * attribute. - * - * NOTE: The standard specifies that the attribute value should be returned - * via the asynchronous MLME-GET.confirm primitve. However, in our - * implementation, we synchronously return the value immediately.Therefore, we - * merge the functionality of the MLME-GET.request and MLME-GET.confirm - * primitives together. - * - ****************************************************************************/ - -int mac802154_req_get(MACHANDLE mac, enum ieee802154_pib_attr_e pib_attr, - FAR union ieee802154_attr_u *attrval) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - return -ENOTTY; -} - -/**************************************************************************** - * Name: mac802154_req_set - * - * Description: - * The MLME-SET.request primitive attempts to write the given value to the - * indicated MAC PIB attribute. - * - * NOTE: The standard specifies that confirmation should be indicated via - * the asynchronous MLME-SET.confirm primitve. However, in our implementation - * we synchronously return the status from the request. Therefore, we do merge - * the functionality of the MLME-SET.request and MLME-SET.confirm primitives - * together. - * - ****************************************************************************/ - -int mac802154_req_set(MACHANDLE mac, enum ieee802154_pib_attr_e pib_attr, - FAR const union ieee802154_attr_u *attrval) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - int ret; - - switch (pib_attr) - { - case IEEE802154_PIB_MAC_EXTENDED_ADDR: - { - /* Set the MAC copy of the address in the table */ - - memcpy(&priv->addr.eaddr[0], &attrval->mac.eaddr[0], - IEEE802154_EADDR_LEN); - - /* Tell the radio about the attribute */ - - priv->radio->ops->set_attr(priv->radio, pib_attr, attrval); - - ret = IEEE802154_STATUS_SUCCESS; - } - break; - default: - { - /* The attribute may be handled soley in the radio driver, so pass - * it along. - */ - - ret = priv->radio->ops->set_attr(priv->radio, pib_attr, attrval); - } - break; - } - return ret; -} - -/**************************************************************************** - * Name: mac802154_req_start - * - * 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 mac802154_maccb_s->conf_start callback. - * - ****************************************************************************/ - -int mac802154_req_start(MACHANDLE mac, FAR struct ieee802154_start_req_s *req) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - int ret; - - /* Get exclusive access to the MAC */ - - ret = mac802154_takesem(&priv->exclsem); - if (ret < 0) - { - wlerr("ERROR: mac802154_takesem failed: %d\n", ret); - return ret; - } - - /* When the CoordRealignment parameter is set to TRUE, the coordinator - * attempts to transmit a coordinator realignment command frame as described - * in 5.1.2.3.2. If the transmission of the coordinator realignment command - * fails due to a channel access failure, the MLME will not make any changes - * to the superframe configuration. (i.e., no PIB attributes will be changed). - * If the coordinator realignment command is successfully transmitted, the - * MLME updates the PIB attributes BeaconOrder, SuperframeOrder, PANId, - * ChannelPage, and ChannelNumber parameters. [1] pg. 106 - */ - - if (req->coordrealign) - { - /* TODO: Finish the realignment functionality */ - - return -ENOTTY; - } - - /* Set the PANID attribute */ - - priv->addr.panid = req->panid; - priv->radio->ops->set_attr(priv->radio, IEEE802154_PIB_MAC_PANID, - (FAR const union ieee802154_attr_u *)&req->panid); - - /* Set the radio attributes */ - priv->radio->ops->set_attr(priv->radio, IEEE802154_PIB_PHY_CURRENT_CHANNEL, - (FAR const union ieee802154_attr_u *)&req->chnum); - - priv->radio->ops->set_attr(priv->radio, IEEE802154_PIB_PHY_CURRENT_PAGE, - (FAR const union ieee802154_attr_u *)&req->chpage); - - /* Set the superframe order */ - - if(req->superframeorder > 15) - { - ret = -EINVAL; - goto errout; - } - - priv->superframeorder = req->superframeorder; - - /* Set the beacon order */ - - if(req->beaconorder > 15) - { - ret = -EINVAL; - goto errout; - } - - priv->beaconorder = req->beaconorder; - - if (req->pancoord) - { - priv->devmode = IEEE802154_DEVMODE_PANCOORD; - } - else - { - priv->devmode = IEEE802154_DEVMODE_COORD; - } - - /* If the BeaconOrder parameter is less than 15, the MLME sets macBattLifeExt to - * the value of the BatteryLifeExtension parameter. If the BeaconOrder parameter - * equals 15, the value of the BatteryLifeExtension parameter is ignored. - * [1] pg. 106 - */ - - if (priv->beaconorder < 15) - { - priv->battlifeext = req->battlifeext; - - /* TODO: Finish starting beacon enabled network */ - return -ENOTTY; - } - - mac802154_givesem(&priv->exclsem); - - return OK; - -errout: - mac802154_givesem(&priv->exclsem); - return ret; -} - -/**************************************************************************** - * Name: mac802154_req_sync - * - * 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 mac802154_maccb_s->int_commstatus callback. TOCHECK. - * - ****************************************************************************/ - -int mac802154_req_sync(MACHANDLE mac, FAR struct ieee802154_sync_req_s *req) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - return -ENOTTY; -} - -/**************************************************************************** - * Name: mac802154_req_poll - * - * Description: - * The MLME-POLL.request primitive prompts the device to request data from - * the coordinator. Confirmation is returned via the - * struct mac802154_maccb_s->conf_poll callback, followed by a - * struct mac802154_maccb_s->ind_data callback. - * - ****************************************************************************/ - -int mac802154_req_poll(MACHANDLE mac, FAR struct ieee802154_poll_req_s *req) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - return -ENOTTY; -} - -/**************************************************************************** - * Name: mac802154_resp_associate - * - * Description: - * The MLME-ASSOCIATE.response primitive is used to initiate a response to - * an MLME-ASSOCIATE.indication primitive. - * - ****************************************************************************/ - -int mac802154_resp_associate(MACHANDLE mac, - FAR struct ieee802154_assoc_resp_s *resp) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - return -ENOTTY; -} - -/**************************************************************************** - * Name: mac802154_resp_orphan - * - * Description: - * The MLME-ORPHAN.response primitive allows the next higher layer of a - * coordinator to respond to the MLME-ORPHAN.indication primitive. - * - ****************************************************************************/ - -int mac802154_resp_orphan(MACHANDLE mac, - FAR struct ieee802154_orphan_resp_s *resp) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - return -ENOTTY; -} - -/**************************************************************************** - * Name: mac802154_notif_free - * - * Description: - * When the MAC calls the registered callback, it passes a reference - * to a mac802154_notify_s structure. This structure needs to be freed - * after the callback handler is done using it. - * - ****************************************************************************/ - -int mac802154_notif_free(MACHANDLE mac, - FAR struct ieee802154_notif_s *notif) -{ - FAR struct ieee802154_privmac_s *priv = - (FAR struct ieee802154_privmac_s *)mac; - - /* Get exclusive access to the MAC */ - - while(mac802154_takesem(&priv->exclsem) < 0); - - notif->flink = priv->notif_free; - priv->notif_free = notif; - - mac802154_givesem(&priv->exclsem); - - if (priv->csma_tryagain) - { - priv->csma_tryagain = false; - priv->radio->ops->txnotify_csma(priv->radio); - } - - if (priv->gts_tryagain) - { - priv->gts_tryagain = false; - priv->radio->ops->txnotify_gts(priv->radio); - } - - return -ENOTTY; -} diff --git a/wireless/ieee802154/mac802154.h b/wireless/ieee802154/mac802154.h index 2e8110f755..8eb104d5d3 100644 --- a/wireless/ieee802154/mac802154.h +++ b/wireless/ieee802154/mac802154.h @@ -58,8 +58,6 @@ * Public Data Types ****************************************************************************/ - - /* Callback operations to notify the next highest layer of various asynchronous * events, usually triggered by some previous request or response invoked by the * upper layer. @@ -273,7 +271,7 @@ int mac802154_req_scan(MACHANDLE mac, FAR struct ieee802154_scan_req_s *req); * ****************************************************************************/ -int mac802154_req_get(MACHANDLE mac, enum ieee802154_pib_attr_e pib_attr, +int mac802154_req_get(MACHANDLE mac, enum ieee802154_attr_e , FAR union ieee802154_attr_u *attrval); /**************************************************************************** @@ -291,7 +289,7 @@ int mac802154_req_get(MACHANDLE mac, enum ieee802154_pib_attr_e pib_attr, * ****************************************************************************/ -int mac802154_req_set(MACHANDLE mac, enum ieee802154_pib_attr_e pib_attr, +int mac802154_req_set(MACHANDLE mac, enum ieee802154_attr_e , FAR const union ieee802154_attr_u *attrval); /**************************************************************************** diff --git a/wireless/ieee802154/mac802154_assoc.c b/wireless/ieee802154/mac802154_assoc.c new file mode 100644 index 0000000000..0e4eee7238 --- /dev/null +++ b/wireless/ieee802154/mac802154_assoc.c @@ -0,0 +1,949 @@ +/**************************************************************************** + * wireless/ieee802154/mac802154_assoc.c + * + * Copyright (C) 2017 Verge Inc. All rights reserved. + * Author: Anthony Merlino + * + * 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 "mac802154.h" +#include "mac802154_internal.h" +#include "mac802154_assoc.h" + +#include + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void mac802154_timeout_assoc(FAR struct ieee802154_privmac_s *priv); +static FAR struct ieee802154_txdesc_s * + mac802154_assoc_getresp(FAR struct ieee802154_privmac_s *priv); + +/**************************************************************************** + * Public MAC Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mac802154_req_associate + * + * Description: + * The MLME-ASSOCIATE.request primitive allows a device to request an + * association with a coordinator. Confirmation is returned via the + * struct mac802154_maccb_s->conf_associate callback. + * + * On receipt of the MLME-ASSOCIATE.request primitive, the MLME of an + * unassociated device first updates the appropriate PHY and MAC PIB + * attributes, as described in 5.1.3.1, and then generates an association + * request command, as defined in 5.3.1 [1] pg.80 + * + ****************************************************************************/ + +int mac802154_req_associate(MACHANDLE mac, + FAR struct ieee802154_assoc_req_s *req) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + FAR struct ieee802154_txdesc_s *txdesc; + FAR struct iob_s *iob; + FAR uint16_t *u16; + bool rxonidle; + int ret; + + /* Get exlusive access to the operation sempaphore. This must happen before + * getting exclusive access to the MAC struct or else there could be a lockup + * condition. This would occur if another thread is using the cmdtrans but + * needs access to the MAC in order to unlock it. + */ + + ret = mac802154_takesem(&priv->op_sem, true); + if (ret < 0) + { + return ret; + } + + priv->curr_op = MAC802154_OP_ASSOC; + priv->curr_cmd = IEEE802154_CMD_ASSOC_REQ; + + /* Get exclusive access to the MAC */ + + ret = mac802154_takesem(&priv->exclsem, true); + if (ret < 0) + { + mac802154_givesem(&priv->op_sem); + return ret; + } + + /* Set the channel and channel page of the PHY layer */ + + priv->radio->set_attr(priv->radio, IEEE802154_ATTR_PHY_CURRENT_CHANNEL, + (FAR const union ieee802154_attr_u *)&req->chnum); + + priv->radio->set_attr(priv->radio, IEEE802154_ATTR_PHY_CURRENT_PAGE, + (FAR const union ieee802154_attr_u *)&req->chpage); + + /* Set the PANID attribute */ + + priv->addr.panid = req->coordaddr.panid; + priv->coordaddr.panid = req->coordaddr.panid; + priv->radio->set_attr(priv->radio, IEEE802154_ATTR_MAC_PANID, + (FAR const union ieee802154_attr_u *)&req->coordaddr.panid); + + /* Set the coordinator address attributes */ + + priv->coordaddr.mode = req->coordaddr.mode; + + if (priv->coordaddr.mode == IEEE802154_ADDRMODE_SHORT) + { + priv->coordaddr.saddr = req->coordaddr.saddr; + memcpy(&priv->coordaddr.eaddr[0], IEEE802154_EADDR_UNSPEC, + IEEE802154_EADDR_LEN); + } + else if (priv->coordaddr.mode == IEEE802154_ADDRMODE_EXTENDED) + { + priv->coordaddr.saddr = IEEE802154_SADDR_UNSPEC; + memcpy(&priv->coordaddr.eaddr[0], &req->coordaddr.eaddr[0], + IEEE802154_EADDR_LEN); + } + else + { + ret = -EINVAL; + goto errout; + } + + /* Copy in the capabilities information bitfield */ + + priv->devmode = (req->capabilities.devtype) ? + IEEE802154_DEVMODE_COORD : IEEE802154_DEVMODE_ENDPOINT; + + /* Unlike other attributes, we can't simply cast this one since it is a bit + * in a bitfield. Casting it will give us unpredicatble results. Instead + * of creating a ieee802154_attr_u, we use a local bool. Allocating the + * ieee802154_attr_u value would take up more room on the stack since it is + * as large as the largest attribute type. + */ + + rxonidle = req->capabilities.rxonidle; + priv->radio->set_attr(priv->radio, IEEE802154_ATTR_MAC_RX_ON_WHEN_IDLE, + (FAR const union ieee802154_attr_u *)&rxonidle); + + /* Allocate an IOB to put the frame in */ + + iob = iob_alloc(false); + DEBUGASSERT(iob != NULL); + + iob->io_flink = NULL; + iob->io_len = 0; + iob->io_offset = 0; + iob->io_pktlen = 0; + + /* Allocate the txdesc, waiting if necessary */ + + ret = mac802154_txdesc_alloc(priv, &txdesc, true); + if (ret < 0) + { + iob_free(iob); + mac802154_givesem(&priv->exclsem); + mac802154_givesem(&priv->op_sem); + return ret; + } + + /* Get a uin16_t reference to the first two bytes. ie frame control field */ + + u16 = (FAR uint16_t *)&iob->io_data[0]; + + *u16 = (IEEE802154_FRAME_COMMAND << IEEE802154_FRAMECTRL_SHIFT_FTYPE); + *u16 |= IEEE802154_FRAMECTRL_ACKREQ; + *u16 |= (priv->coordaddr.mode << IEEE802154_FRAMECTRL_SHIFT_DADDR); + *u16 |= (IEEE802154_ADDRMODE_EXTENDED << IEEE802154_FRAMECTRL_SHIFT_SADDR); + + iob->io_len = 2; + + /* Each time a data or a MAC command frame is generated, the MAC sublayer + * shall copy the value of macDSN into the Sequence Number field of the MHR + * of the outgoing frame and then increment it by one. [1] pg. 40. + */ + + iob->io_data[iob->io_len++] = priv->dsn++; + + /* The Destination PAN Identifier field shall contain the identifier of the + * PAN to which to associate. [1] pg. 68 + */ + + memcpy(&iob->io_data[iob->io_len], &priv->coordaddr.panid, 2); + iob->io_len += 2; + + /* The Destination Address field shall contain the address from the beacon + * frame that was transmitted by the coordinator to which the association + * request command is being sent. [1] pg. 68 + */ + + if (priv->coordaddr.mode == IEEE802154_ADDRMODE_SHORT) + { + memcpy(&iob->io_data[iob->io_len], &priv->coordaddr.saddr, 2); + iob->io_len += 2; + } + else if (priv->coordaddr.mode == IEEE802154_ADDRMODE_EXTENDED) + { + memcpy(&iob->io_data[iob->io_len], &priv->coordaddr.eaddr[0], + IEEE802154_EADDR_LEN); + iob->io_len += IEEE802154_EADDR_LEN; + } + + /* The Source PAN Identifier field shall contain the broadcast PAN identifier.*/ + + u16 = (uint16_t *)&iob->io_data[iob->io_len]; + *u16 = IEEE802154_SADDR_BCAST; + iob->io_len += 2; + + /* The Source Address field shall contain the value of macExtendedAddress. */ + + memcpy(&iob->io_data[iob->io_len], &priv->addr.eaddr[0], + IEEE802154_EADDR_LEN); + iob->io_len += IEEE802154_EADDR_LEN; + + /* Copy in the Command Frame Identifier */ + + iob->io_data[iob->io_len++] = IEEE802154_CMD_ASSOC_REQ; + + /* Copy in the capability information bits */ + + iob->io_data[iob->io_len] = 0; + iob->io_data[iob->io_len] |= (req->capabilities.devtype << + IEEE802154_CAPABILITY_SHIFT_DEVTYPE); + iob->io_data[iob->io_len] |= (req->capabilities.powersource << + IEEE802154_CAPABILITY_SHIFT_PWRSRC); + iob->io_data[iob->io_len] |= (req->capabilities.rxonidle << + IEEE802154_CAPABILITY_SHIFT_RXONIDLE); + iob->io_data[iob->io_len] |= (req->capabilities.security << + IEEE802154_CAPABILITY_SHIFT_SECURITY); + iob->io_data[iob->io_len] |= (req->capabilities.allocaddr << + IEEE802154_CAPABILITY_SHIFT_ALLOCADDR); + + iob->io_len++; + + txdesc->frame = iob; + txdesc->frametype = IEEE802154_FRAME_COMMAND; + + /* Save a copy of the destination addressing infromation into the tx descriptor. + * We only do this for commands to help with handling their progession. + */ + + memcpy(&txdesc->destaddr, &req->coordaddr, sizeof(struct ieee802154_addr_s)); + + /* Save a reference of the tx descriptor */ + + priv->cmd_desc = txdesc; + + /* We no longer need to have the MAC layer locked. */ + + mac802154_givesem(&priv->exclsem); + + /* Association Request commands get sent out immediately */ + + priv->radio->txdelayed(priv->radio, txdesc, 0); + + return OK; + +errout: + mac802154_givesem(&priv->exclsem); + return ret; +} + +/**************************************************************************** + * Name: mac802154_resp_associate + * + * Description: + * The MLME-ASSOCIATE.response primitive is used to initiate a response to + * an MLME-ASSOCIATE.indication primitive. + * + ****************************************************************************/ + +int mac802154_resp_associate(MACHANDLE mac, + FAR struct ieee802154_assoc_resp_s *resp) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + FAR struct ieee802154_txdesc_s *txdesc; + FAR struct iob_s *iob; + FAR uint16_t *u16; + int ret; + + /* Allocate an IOB to put the frame in */ + + iob = iob_alloc(false); + DEBUGASSERT(iob != NULL); + + iob->io_flink = NULL; + iob->io_len = 0; + iob->io_offset = 0; + iob->io_pktlen = 0; + + /* Get a uin16_t reference to the first two bytes. ie frame control field */ + + u16 = (FAR uint16_t *)&iob->io_data[0]; + + /* The Destination Addressing Mode and Source Addressing Mode fields shall + * each be set to indicate extended addressing. + * + * The Frame Pending field shall be set to zero and ignored upon reception, + * and the AR field shall be set to one. + * + * The PAN ID Compression field shall be set to one. [1] pg. 69 + */ + + *u16 = (IEEE802154_FRAME_COMMAND << IEEE802154_FRAMECTRL_SHIFT_FTYPE); + *u16 |= IEEE802154_FRAMECTRL_ACKREQ; + *u16 |= IEEE802154_FRAMECTRL_PANIDCOMP; + *u16 |= (IEEE802154_ADDRMODE_EXTENDED << IEEE802154_FRAMECTRL_SHIFT_DADDR); + *u16 |= (IEEE802154_ADDRMODE_EXTENDED << IEEE802154_FRAMECTRL_SHIFT_SADDR); + + iob->io_len = 2; + + /* Each time a data or a MAC command frame is generated, the MAC sublayer + * shall copy the value of macDSN into the Sequence Number field of the MHR + * of the outgoing frame and then increment it by one. [1] pg. 40. + */ + + iob->io_data[iob->io_len++] = priv->dsn++; + + /* In accordance with this value of the PAN ID Compression field, the + * Destination PAN Identifier field shall contain the value of macPANId, while + * the Source PAN Identifier field shall be omitted. [1] pg. 69 + */ + + memcpy(&iob->io_data[iob->io_len], &priv->addr.panid, 2); + iob->io_len += 2; + + /* The Destination Address field shall contain the extended address of the + * device requesting association. [1] pg. 69 */ + + memcpy(&iob->io_data[iob->io_len], &resp->devaddr[0], IEEE802154_EADDR_LEN); + iob->io_len += IEEE802154_EADDR_LEN; + + /* The Source Address field shall contain the value of macExtendedAddress. */ + + memcpy(&iob->io_data[iob->io_len], &priv->addr.eaddr[0], IEEE802154_EADDR_LEN); + iob->io_len += IEEE802154_EADDR_LEN; + + /* Copy in the Command Frame Identifier */ + + iob->io_data[iob->io_len++] = IEEE802154_CMD_ASSOC_RESP; + + /* Copy in the assigned short address */ + + memcpy(&iob->io_data[iob->io_len], &resp->assocsaddr, 2); + iob->io_len += 2; + + /* Copy in the association status */ + + iob->io_data[iob->io_len++] = resp->status; + + /* Get exclusive access to the MAC */ + + ret = mac802154_takesem(&priv->exclsem, true); + if (ret < 0) + { + iob_free(iob); + return ret; + } + + /* Allocate the txdesc, waiting if necessary */ + + ret = mac802154_txdesc_alloc(priv, &txdesc, true); + if (ret < 0) + { + iob_free(iob); + mac802154_givesem(&priv->exclsem); + return ret; + } + + txdesc->frame = iob; + txdesc->frametype = IEEE802154_FRAME_COMMAND; + + txdesc->destaddr.panid = priv->addr.panid; + txdesc->destaddr.mode = IEEE802154_ADDRMODE_EXTENDED; + memcpy(&txdesc->destaddr.eaddr[0], &resp->devaddr[0], IEEE802154_EADDR_LEN); + + mac802154_setupindirect(priv, txdesc); + + mac802154_givesem(&priv->exclsem); + + return OK; +} + +/**************************************************************************** + * Internal MAC Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mac802154_txdone_assocreq + * + * Description: + * Handle the completion (success/failure) of transmitting an association + * request command. + * + * Assumptions: + * Called with the MAC locked. + * + ****************************************************************************/ + +void mac802154_txdone_assocreq(FAR struct ieee802154_privmac_s *priv, + FAR struct ieee802154_txdesc_s *txdesc) +{ + enum ieee802154_status_e status; + FAR struct mac802154_notif_s *privnotif = + (FAR struct mac802154_notif_s *)txdesc->conf; + FAR struct ieee802154_notif_s *notif = &privnotif->pub; + FAR struct ieee802154_txdesc_s *respdesc; + + if(txdesc->conf->status != IEEE802154_STATUS_SUCCESS) + { + /* if the association request command cannot be sent due to a + * channel access failure, the MAC sublayer shall notify the next + * higher layer. [1] pg. 33 + */ + + /* We can actually high-jack the data conf notification since it + * is allocated as an ieee80215_notif_s anyway. Before we overwrite + * any data though, we need to get the status from the data + * confirmation as that is the method we use to get the reason + * why the tx failed from the radio layer. + */ + + status = txdesc->conf->status; + notif->notiftype = IEEE802154_NOTIFY_CONF_ASSOC; + + notif->u.assocconf.status = status; + + /* The short device address allocated by the coordinator on + * successful association. This parameter will be equal to 0xffff + * if the association attempt was unsuccessful. [1] pg. 81 + */ + + notif->u.assocconf.saddr = IEEE802154_SADDR_UNSPEC; + + /* We are now done the operation, unlock the semaphore */ + + priv->curr_op = MAC802154_OP_NONE; + priv->cmd_desc = NULL; + mac802154_givesem(&priv->op_sem); + + /* Release the MAC, call the callback, get exclusive access again */ + + mac802154_givesem(&priv->exclsem); + priv->cb->notify(priv->cb, notif); + mac802154_takesem(&priv->exclsem, false); + } + else + { + /* On receipt of the acknowledgment to the association request + * command, the device shall wait for at most macResponseWaitTime + * for the coordinator to make its association decision; the PIB + * attribute macResponseWaitTime is a network-topology-dependent + * parameter and may be set to match the specific requirements of + * the network that a device is trying to join. If the device is + * tracking the beacon, it shall attempt to extract the association + * response command from the coordinator whenever it is indicated in + * the beacon frame. If the device is not tracking the beacon, it + * shall attempt to extract the association response command from + * the coordinator after macResponseWaitTime. [1] pg. 34 + */ + + if (priv->trackingbeacon) + { + /* We are tracking the beacon, so we should see our address in the + * beacon frame within macResponseWaitTime if the coordinator is going + * to respond. Setup a timeout for macResponseWaitTime so that we + * can inform the next highest layer if the association attempt fails + * due to NO_DATA. + */ + + mac802154_timerstart(priv, + priv->resp_waittime*IEEE802154_BASE_SUPERFRAME_DURATION, + mac802154_timeout_assoc); + } + else + { + /* Send the Data Request MAC command after macResponseWaitTime to + * extract the data from the coordinator. + */ + + respdesc = mac802154_assoc_getresp(priv); + priv->radio->txdelayed(priv->radio, respdesc, + (priv->resp_waittime*IEEE802154_BASE_SUPERFRAME_DURATION)); + } + + /* We can deallocate the data conf notification as it is no longer + * needed. We can't use the public function here since we already + * have the MAC locked. + */ + + privnotif->flink = priv->notif_free; + priv->notif_free = privnotif; + } +} + +/**************************************************************************** + * Name: mac802154_txdone_datareq_assoc + * + * Description: + * Handle the completion (success/failure) of transmitting a data request + * command in an effort to extract the association response from the + * coordinator. + * + * Assumptions: + * Called with the MAC locked. + * + ****************************************************************************/ + +void mac802154_txdone_datareq_assoc(FAR struct ieee802154_privmac_s *priv, + FAR struct ieee802154_txdesc_s *txdesc) +{ + enum ieee802154_status_e status; + FAR struct mac802154_notif_s *privnotif = + (FAR struct mac802154_notif_s *)txdesc->conf; + FAR struct ieee802154_notif_s *notif = &privnotif->pub; + + /* If the data request failed to be sent, notify the next layer + * that the association has failed. + * OR + * On receipt of the Ack frame with the Frame Pending field set + * to zero, the device shall conclude that there are no data + * pending at the coordinator. [1] pg. 43 + */ + + if (notif->u.dataconf.status != IEEE802154_STATUS_SUCCESS || + txdesc->framepending == 0) + { + if (notif->u.dataconf.status != IEEE802154_STATUS_SUCCESS) + { + status = notif->u.dataconf.status; + } + else + { + /* If the device does not extract an association response + * command frame from the coordinator within macResponseWaitTime, + * the MLME shall issue the MLME-ASSOCIATE.confirm primitive, + * as described in 6.2.2.4, with a status of NO_DATA, and the + * association attempt shall be deemed a failure. [1] pg. 34 + */ + + status = IEEE802154_STATUS_NO_DATA; + } + + notif->notiftype = IEEE802154_NOTIFY_CONF_ASSOC; + notif->u.assocconf.status = status; + + /* The short device address allocated by the coordinator on + * successful association. This parameter will be equal to 0xffff + * if the association attempt was unsuccessful. [1] pg. 81 + */ + + notif->u.assocconf.saddr = IEEE802154_SADDR_UNSPEC; + + /* We are now done the operation, and can release the command */ + + priv->curr_op = MAC802154_OP_NONE; + priv->cmd_desc = NULL; + mac802154_givesem(&priv->op_sem); + + /* Release the MAC, call the callback, get exclusive access again */ + + mac802154_givesem(&priv->exclsem); + priv->cb->notify(priv->cb, notif); + mac802154_takesem(&priv->exclsem, false); + } + else + { + /* On receipt of the acknowledgment frame with the Frame + * Pending field set to one, a device shall enable its + * receiver for at most macMaxFrameTotalWaitTime to receive + * the corresponding data frame from the coordinator. [1] pg.43 + */ + + priv->radio->rxenable(priv->radio, true); + + /* Start a timer, if we receive the data frame, we will cancel + * the timer, otherwise it will expire and we will notify the + * next highest layer of the failure. + */ + + mac802154_timerstart(priv, priv->max_frame_waittime, + mac802154_timeout_assoc); + + /* We can deallocate the data conf notification as it is no longer + * needed. We can't use the public function here since we already + * have the MAC locked. + */ + + privnotif->flink = priv->notif_free; + priv->notif_free = privnotif; + mac802154_givesem(&priv->notif_sem); + } +} + +/**************************************************************************** + * Name: mac802154_rx_assocreq + * + * Description: + * Function called from the generic RX Frame worker to parse and handle the + * reception of an Association Request MAC command frame. + * + ****************************************************************************/ + +void mac802154_rx_assocreq(FAR struct ieee802154_privmac_s *priv, + FAR struct ieee802154_data_ind_s *ind) +{ + FAR struct iob_s *frame = ind->frame; + FAR struct ieee802154_notif_s *notif; + uint8_t cap; + + /* Get exclusive access to the MAC */ + + mac802154_takesem(&priv->exclsem, false); + + /* Allocate a notification to pass to the next highest layer */ + + mac802154_notif_alloc(priv, ¬if, false); + notif->notiftype = IEEE802154_NOTIFY_IND_ASSOC; + + /* Association Requests should always be sent from a device with source + * addressing mode set to extended mode. Throw out any request received + * without addressing set to extended + */ + + if (ind->src.mode != IEEE802154_ADDRMODE_EXTENDED) + { + goto errout_with_sem; + } + + /* Copy the extended address of the requesting device */ + + memcpy(¬if->u.assocind.devaddr[0], &ind->src.eaddr[0], + sizeof(struct ieee802154_addr_s)); + + /* Copy in the capability information from the frame to the notification */ + + cap = frame->io_data[frame->io_offset++]; + notif->u.assocind.capabilities.devtype = + (cap >> IEEE802154_CAPABILITY_SHIFT_DEVTYPE) & 0x01; + notif->u.assocind.capabilities.powersource = + (cap >> IEEE802154_CAPABILITY_SHIFT_PWRSRC) & 0x01; + notif->u.assocind.capabilities.rxonidle = + (cap >> IEEE802154_CAPABILITY_SHIFT_RXONIDLE) & 0x01; + notif->u.assocind.capabilities.security = + (cap >> IEEE802154_CAPABILITY_SHIFT_SECURITY) & 0x01; + notif->u.assocind.capabilities.allocaddr = + (cap >> IEEE802154_CAPABILITY_SHIFT_ALLOCADDR) & 0x01; + +#ifdef CONFIG_IEEE802154_SECURITY +#error Missing security logic +#endif + + /* Unlock the MAC */ + + mac802154_givesem(&priv->exclsem); + + /* Notify the next highest layer of the association status */ + + priv->cb->notify(priv->cb, notif); + + return; + +errout_with_sem: + mac802154_givesem(&priv->exclsem); + return; +} + +/**************************************************************************** + * Name: mac802154_rx_assocresp + * + * Description: + * Function called from the generic RX Frame worker to parse and handle the + * reception of an Association Response MAC command frame. + * + ****************************************************************************/ + +void mac802154_rx_assocresp(FAR struct ieee802154_privmac_s *priv, + FAR struct ieee802154_data_ind_s *ind) +{ + FAR struct iob_s *frame = ind->frame; + FAR struct ieee802154_notif_s *notif; + + /* Check if we are performing an Association operation, if not, we will just + * ignore the frame. + */ + + if (priv->curr_op != MAC802154_OP_ASSOC) + { + return; + } + + /* Cancel the timeout used if we didn't get a response */ + + mac802154_timercancel(priv); + + /* Get exclusive access to the MAC */ + + mac802154_takesem(&priv->exclsem, false); + + /* Allocate a notification to pass to the next highest layer */ + + mac802154_notif_alloc(priv, ¬if, false); + notif->notiftype = IEEE802154_NOTIFY_CONF_ASSOC; + + /* Parse the short address from the response */ + + priv->addr.saddr = (uint16_t)(frame->io_data[frame->io_offset]); + frame->io_offset += 2; + + /* Inform the radio of the address change */ + + priv->radio->set_attr(priv->radio, IEEE802154_ATTR_MAC_SHORT_ADDRESS, + (FAR union ieee802154_attr_u *)&priv->addr.saddr); + + /* A Short Address field value equal to 0xfffe shall indicate that the device + * has been successfully associated with a PAN but has not been allocated a + * short address. In this case, the device shall communicate on the PAN using + * only its extended address. [1] pg. 70 + */ + + if (priv->addr.saddr == IEEE802154_SADDR_BCAST) + { + /* TODO: Figure out if this is sufficient */ + + priv->addr.mode = IEEE802154_ADDRMODE_SHORT; + } + + /* Parse the status from the response */ + + notif->u.assocconf.status = frame->io_data[frame->io_offset++]; + + if (notif->u.assocconf.status == IEEE802154_STATUS_SUCCESS) + { + priv->isassoc = true; + } + else + { + priv->isassoc = false; + } + + notif->u.assocconf.saddr = priv->addr.saddr; + + /* Unlock the MAC */ + + mac802154_givesem(&priv->exclsem); + + /* We are no longer performing the association operation */ + + priv->curr_op = MAC802154_OP_NONE; + priv->cmd_desc = NULL; + mac802154_givesem(&priv->op_sem); + + /* Notify the next highest layer of the association status */ + + priv->cb->notify(priv->cb, notif); +} + +/**************************************************************************** + * Private Function + ****************************************************************************/ + +/**************************************************************************** + * Name: mac802154_timeout_assoc + * + * Description: + * Function registered with MAC timer that gets called via the work queue to + * handle a timeout for extracting the Association Response from the Coordinator. + * + ****************************************************************************/ + +static void mac802154_timeout_assoc(FAR struct ieee802154_privmac_s *priv) +{ + FAR struct ieee802154_notif_s *notif; + + DEBUGASSERT(priv->curr_op == MAC802154_OP_ASSOC); + + /* If the device does not extract an association response command + * frame from the coordinator within macResponseWaitTime, the MLME + * shall issue the MLME-ASSOCIATE.confirm primitive, as described + * in 6.2.2.4, with a status of NO_DATA, and the association attempt + * shall be deemed a failure. [1] pg. 33 + */ + + /* Allocate a notification struct to pass to the next highest layer. + * Don't allow EINTR to interrupt. + */ + + mac802154_takesem(&priv->exclsem, false); + mac802154_notif_alloc(priv, ¬if, false); + + /* We are no longer performing the association operation */ + priv->curr_op = MAC802154_OP_NONE; + priv->cmd_desc = NULL; + mac802154_givesem(&priv->op_sem); + + /* Release the MAC */ + + mac802154_givesem(&priv->exclsem); + + notif->notiftype = IEEE802154_NOTIFY_CONF_ASSOC; + notif->u.assocconf.status = IEEE802154_STATUS_NO_DATA; + notif->u.assocconf.saddr = IEEE802154_SADDR_UNSPEC; + + priv->cb->notify(priv->cb, notif); +} + +/**************************************************************************** + * Name: mac802154_assoc_getresp + * + * Description: + * Send a data request to the coordinator to extract the association response. + * + * Assumptions: + * MAC is locked when called. + * + * TODO: Can this be used for general data extraction? + * + ****************************************************************************/ + +static FAR struct ieee802154_txdesc_s * + mac802154_assoc_getresp(FAR struct ieee802154_privmac_s *priv) +{ + FAR struct iob_s *iob; + FAR struct ieee802154_txdesc_s *txdesc; + FAR uint16_t *u16; + + /* Allocate an IOB to put the frame in */ + + iob = iob_alloc(false); + DEBUGASSERT(iob != NULL); + + iob->io_flink = NULL; + iob->io_len = 0; + iob->io_offset = 0; + iob->io_pktlen = 0; + + /* Allocate a tx descriptor */ + + mac802154_txdesc_alloc(priv, &txdesc, false); + + priv->curr_cmd = IEEE802154_CMD_DATA_REQ; + + /* Get a uin16_t reference to the first two bytes. ie frame control field */ + + u16 = (FAR uint16_t *)&iob->io_data[0]; + + *u16 = (IEEE802154_FRAME_COMMAND << IEEE802154_FRAMECTRL_SHIFT_FTYPE); + *u16 |= IEEE802154_FRAMECTRL_ACKREQ; + *u16 |= (priv->coordaddr.mode << IEEE802154_FRAMECTRL_SHIFT_DADDR); + *u16 |= (IEEE802154_ADDRMODE_EXTENDED << IEEE802154_FRAMECTRL_SHIFT_SADDR); + + /* If the Destination Addressing Mode field is set to indicate that + * destination addressing information is not present, the PAN ID Compression + * field shall be set to zero and the source PAN identifier shall contain the + * value of macPANId. Otherwise, the PAN ID Compression field shall be set to + * one. In this case and in accordance with the PAN ID Compression field, the + * Destination PAN Identifier field shall contain the value of macPANId, while + * the Source PAN Identifier field shall be omitted. [1] pg. 72 + * + * The destination address for a data request to extract an assoication request + * should never be set to none. So we always set the PAN ID compression field + */ + + DEBUGASSERT(priv->coordaddr.mode != IEEE802154_ADDRMODE_NONE); + + *u16 |= IEEE802154_FRAMECTRL_PANIDCOMP; + + iob->io_len = 2; + + /* Each time a data or a MAC command frame is generated, the MAC sublayer + * shall copy the value of macDSN into the Sequence Number field of the + * MHR of the outgoing frame and then increment it by one. [1] pg. 40. + */ + + iob->io_data[iob->io_len++] = priv->dsn++; + + /* The Destination PAN Identifier field shall contain the identifier of + * the PAN to which to associate. [1] pg. 68 + */ + + memcpy(&iob->io_data[iob->io_len], &priv->coordaddr.panid, 2); + iob->io_len += 2; + + /* The Destination Address field shall contain the address from the + * beacon frame that was transmitted by the coordinator to which the + * association request command is being sent. [1] pg. 68 + */ + + if (priv->coordaddr.mode == IEEE802154_ADDRMODE_SHORT) + { + memcpy(&iob->io_data[iob->io_len], &priv->coordaddr.saddr, 2); + iob->io_len += 2; + } + else if (priv->coordaddr.mode == IEEE802154_ADDRMODE_EXTENDED) + { + memcpy(&iob->io_data[iob->io_len], &priv->coordaddr.eaddr[0], + IEEE802154_EADDR_LEN); + iob->io_len += IEEE802154_EADDR_LEN; + } + + /* The Source Address field shall contain the value of macExtendedAddress. */ + + memcpy(&iob->io_data[iob->io_len], &priv->addr.eaddr[0], + IEEE802154_EADDR_LEN); + iob->io_len += IEEE802154_EADDR_LEN; + + /* Copy in the Command Frame Identifier */ + + iob->io_data[iob->io_len++] = IEEE802154_CMD_DATA_REQ; + + /* Copy the IOB reference to the descriptor */ + + txdesc->frame = iob; + + return txdesc; +} diff --git a/wireless/ieee802154/mac802154_assoc.h b/wireless/ieee802154/mac802154_assoc.h new file mode 100644 index 0000000000..e1e7d1d352 --- /dev/null +++ b/wireless/ieee802154/mac802154_assoc.h @@ -0,0 +1,75 @@ +/**************************************************************************** + * wireless/ieee802154/mac802154_assoc.h + * + * Copyright (C) 2017 Verge Inc. All rights reserved. + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * + * Author: Anthony Merlino + * Author: Gregory Nutt + * + * The naming and comments for various fields are taken directly + * from the IEEE 802.15.4 2011 standard. + * + * 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 __WIRELESS_IEEE802154__MAC802154_ASSOC_H +#define __WIRELESS_IEEE802154__MAC802154_ASSOC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +/**************************************************************************** + * Function Prototypes + ****************************************************************************/ + +struct ieee802154_privmac_s; /* Forward Reference */ + +void mac802154_txdone_assocreq(FAR struct ieee802154_privmac_s *priv, + FAR struct ieee802154_txdesc_s *txdesc); + +void mac802154_txdone_datareq_assoc(FAR struct ieee802154_privmac_s *priv, + FAR struct ieee802154_txdesc_s *txdesc); + +void mac802154_rx_assocreq(FAR struct ieee802154_privmac_s *priv, + FAR struct ieee802154_data_ind_s *ind); + +void mac802154_rx_assocresp(FAR struct ieee802154_privmac_s *priv, + FAR struct ieee802154_data_ind_s *ind); + +#endif /* __WIRELESS_IEEE802154__MAC802154_ASSOC_H */ \ No newline at end of file diff --git a/wireless/ieee802154/mac802154_bind.c b/wireless/ieee802154/mac802154_bind.c new file mode 100644 index 0000000000..c173aef477 --- /dev/null +++ b/wireless/ieee802154/mac802154_bind.c @@ -0,0 +1,80 @@ +/**************************************************************************** + * wireless/ieee802154/mac802154_bind.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2017 Verge Inc. All rights reserved. + * + * Author: Gregory Nutt + * Author: Anthony Merlino + * + * 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 "mac802154.h" +#include "mac802154_internal.h" + +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mac802154_bind + * + * Description: + * Bind the MAC callback table to the MAC state. + * + * Parameters: + * mac - Reference to the MAC driver state structure + * cb - MAC callback operations + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +int mac802154_bind(MACHANDLE mac, FAR const struct mac802154_maccb_s *cb) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + + priv->cb = cb; + return OK; +} + diff --git a/wireless/ieee802154/mac802154_data.c b/wireless/ieee802154/mac802154_data.c new file mode 100644 index 0000000000..fb89d1858d --- /dev/null +++ b/wireless/ieee802154/mac802154_data.c @@ -0,0 +1,331 @@ +/**************************************************************************** + * wireless/ieee802154/mac802154_data.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2017 Verge Inc. All rights reserved. + * + * Author: Gregory Nutt + * Author: Anthony Merlino + * + * 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 "mac802154.h" +#include "mac802154_internal.h" +#include "mac802154_data.h" + +#include + +/**************************************************************************** + * Public MAC Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mac802154_req_data + * + * 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 mac802154_maccb_s->conf_data callback. + * + ****************************************************************************/ + +int mac802154_req_data(MACHANDLE mac, + FAR const struct ieee802154_frame_meta_s *meta, + FAR struct iob_s *frame) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + FAR struct ieee802154_txdesc_s *txdesc; + uint16_t *frame_ctrl; + uint8_t mhr_len = 3; /* Start assuming frame control and seq. num */ + int ret; + + /* Check the required frame size */ + + if (frame->io_len > IEEE802154_MAX_PHY_PACKET_SIZE) + { + return -E2BIG; + } + + /* Cast the first two bytes of the IOB to a uint16_t frame control field */ + + frame_ctrl = (FAR uint16_t *)&frame->io_data[0]; + + /* Ensure we start with a clear frame control field */ + + *frame_ctrl = 0; + + /* Set the frame type to Data */ + + *frame_ctrl |= IEEE802154_FRAME_DATA << IEEE802154_FRAMECTRL_SHIFT_FTYPE; + + /* If the msduLength is greater than aMaxMACSafePayloadSize, the MAC + * sublayer will set the Frame Version to one. [1] pg. 118. + */ + + if ((frame->io_len - frame->io_offset) > IEEE802154_MAX_SAFE_MAC_PAYLOAD_SIZE) + { + *frame_ctrl |= IEEE802154_FRAMECTRL_VERSION; + } + + /* If the TXOptions parameter specifies that an acknowledged transmission + * is required, the AR field will be set appropriately, as described in + * 5.1.6.4 [1] pg. 118. + */ + + *frame_ctrl |= (meta->msdu_flags.ack_tx << IEEE802154_FRAMECTRL_SHIFT_ACKREQ); + + /* If the destination address is present, copy the PAN ID and one of the + * addresses, depending on mode, into the MHR. + */ + + if (meta->destaddr.mode != IEEE802154_ADDRMODE_NONE) + { + memcpy(&frame->io_data[mhr_len], &meta->destaddr.panid, 2); + mhr_len += 2; + + if (meta->destaddr.mode == IEEE802154_ADDRMODE_SHORT) + { + memcpy(&frame->io_data[mhr_len], &meta->destaddr.saddr, 2); + mhr_len += 2; + } + else if (meta->destaddr.mode == IEEE802154_ADDRMODE_EXTENDED) + { + memcpy(&frame->io_data[mhr_len], &meta->destaddr.eaddr, + IEEE802154_EADDR_LEN); + + mhr_len += IEEE802154_EADDR_LEN; + } + } + + /* Set the destination addr mode inside the frame control field */ + + *frame_ctrl |= (meta->destaddr.mode << IEEE802154_FRAMECTRL_SHIFT_DADDR); + + /* From this point on, we need exclusive access to the privmac struct */ + + ret = mac802154_takesem(&priv->exclsem, true); + if (ret < 0) + { + return ret; + } + + /* If both destination and source addressing information is present, the MAC + * sublayer shall compare the destination and source PAN identifiers. + * [1] pg. 41. + */ + + if (meta->srcaddr_mode != IEEE802154_ADDRMODE_NONE && + meta->destaddr.mode != IEEE802154_ADDRMODE_NONE) + { + /* If the PAN identifiers are identical, the PAN ID Compression field + * shall be set to one, and the source PAN identifier shall be omitted + * from the transmitted frame. [1] pg. 41. + */ + + if (meta->destaddr.panid == priv->addr.panid) + { + *frame_ctrl |= IEEE802154_FRAMECTRL_PANIDCOMP; + } + } + + if (meta->srcaddr_mode != IEEE802154_ADDRMODE_NONE) + { + /* If the destination address is not included, or if PAN ID Compression + * is off, we need to include the Source PAN ID. + */ + + if ((meta->destaddr.mode == IEEE802154_ADDRMODE_NONE) || + (!(*frame_ctrl & IEEE802154_FRAMECTRL_PANIDCOMP))) + { + memcpy(&frame->io_data[mhr_len], &priv->addr.panid, 2); + mhr_len += 2; + } + + if (meta->srcaddr_mode == IEEE802154_ADDRMODE_SHORT) + { + memcpy(&frame->io_data[mhr_len], &priv->addr.saddr, 2); + mhr_len += 2; + } + else if (meta->srcaddr_mode == IEEE802154_ADDRMODE_EXTENDED) + { + memcpy(&frame->io_data[mhr_len], &priv->addr.eaddr, + IEEE802154_EADDR_LEN); + + mhr_len += IEEE802154_EADDR_LEN; + } + } + else + { + /* If this device is not the PAN coordinator, it shouldn't be sending + * frames with a source address mode of NONE + */ + + if (priv->devmode != IEEE802154_DEVMODE_PANCOORD) + { + return -EINVAL; + } + } + + /* Set the source addr mode inside the frame control field */ + + *frame_ctrl |= (meta->srcaddr_mode << IEEE802154_FRAMECTRL_SHIFT_SADDR); + + /* Each time a data or a MAC command frame is generated, the MAC sublayer + * shall copy the value of macDSN into the Sequence Number field of the MHR + * of the outgoing frame and then increment it by one. [1] pg. 40. + */ + + frame->io_data[2] = priv->dsn++; + + /* The MAC header we just created must never have exceeded where the app + * data starts. This should never happen since the offset should have + * been set via the same logic to calculate the header length as the logic + * here that created the header + */ + + DEBUGASSERT(mhr_len == frame->io_offset); + + frame->io_offset = 0; /* Set the offset to 0 to include the header */ + + /* Allocate the txdesc, waiting if necessary, allow interruptions */ + + ret = mac802154_txdesc_alloc(priv, &txdesc, true); + if (ret < 0) + { + return ret; + } + + txdesc->conf->handle = meta->msdu_handle; + txdesc->frame = frame; + txdesc->frametype = IEEE802154_FRAME_DATA; + + /* If the TxOptions parameter specifies that a GTS transmission is required, + * the MAC sublayer will determine whether it has a valid GTS as described + * 5.1.7.3. If a valid GTS could not be found, the MAC sublayer will discard + * the MSDU. If a valid GTS was found, the MAC sublayer will defer, if + * necessary, until the GTS. If the TxOptions parameter specifies that a GTS + * transmission is not required, the MAC sublayer will transmit the MSDU using + * either slotted CSMA-CA in the CAP for a beacon-enabled PAN or unslotted + * CSMA-CA for a nonbeacon-enabled PAN. Specifying a GTS transmission in the + * TxOptions parameter overrides an indirect transmission request. + * [1] pg. 118. + */ + + if (meta->msdu_flags.gts_tx) + { + /* TODO: Support GTS transmission. This should just change where we link + * the transaction. Instead of going in the CSMA transaction list, it + * should be linked to the GTS' transaction list. We'll need to check if + * the GTS is valid, and then find the GTS, before linking. Note, we also + * don't have to try and kick-off any transmission here. + */ + + /* We no longer need to have the MAC layer locked. */ + + mac802154_givesem(&priv->exclsem); + + return -ENOTSUP; + } + else + { + /* If the TxOptions parameter specifies that an indirect transmission is + * required and this primitive is received by the MAC sublayer of a + * coordinator, the data frame is sent using indirect transmission, as + * described in 5.1.5 and 5.1.6.3. [1] + */ + + if (meta->msdu_flags.indirect_tx) + { + /* If the TxOptions parameter specifies that an indirect transmission + * is required and if the device receiving this primitive is not a + * coordinator, the destination address is not present, or the + * TxOptions parameter also specifies a GTS transmission, the indirect + * transmission option will be ignored. [1] + * + * NOTE: We don't just ignore the parameter. Instead, we throw an + * error, since this really shouldn't be happening. + */ + + if (priv->devmode >= IEEE802154_DEVMODE_COORD && + meta->destaddr.mode != IEEE802154_ADDRMODE_NONE) + { + /* Copy in a reference to the destination address to assist in + * searching when data is requested. + */ + + memcpy(&txdesc->destaddr, &meta->destaddr, + sizeof(struct ieee802154_addr_s)); + mac802154_setupindirect(priv, txdesc); + mac802154_givesem(&priv->exclsem); + } + else + { + mac802154_givesem(&priv->exclsem); + return -EINVAL; + } + } + else + { + /* Link the transaction into the CSMA transaction list */ + + sq_addlast((FAR sq_entry_t *)txdesc, &priv->csma_queue); + + /* We no longer need to have the MAC layer locked. */ + + mac802154_givesem(&priv->exclsem); + + /* Notify the radio driver that there is data available */ + + priv->radio->txnotify(priv->radio, false); + } + } + + return OK; +} + +/**************************************************************************** + * Internal MAC Functions + ****************************************************************************/ diff --git a/wireless/ieee802154/mac802154_data.h b/wireless/ieee802154/mac802154_data.h new file mode 100644 index 0000000000..c1514a6e14 --- /dev/null +++ b/wireless/ieee802154/mac802154_data.h @@ -0,0 +1,64 @@ +/**************************************************************************** + * wireless/ieee802154/mac802154_data.h + * + * Copyright (C) 2017 Verge Inc. All rights reserved. + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * + * Author: Anthony Merlino + * Author: Gregory Nutt + * + * The naming and comments for various fields are taken directly + * from the IEEE 802.15.4 2011 standard. + * + * 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 __WIRELESS_IEEE802154__MAC802154_DATA_H +#define __WIRELESS_IEEE802154__MAC802154_DATA_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Function Prototypes + ****************************************************************************/ + +#endif /* __WIRELESS_IEEE802154__MAC802154_DATA_H */ \ No newline at end of file diff --git a/wireless/ieee802154/mac802154_device.c b/wireless/ieee802154/mac802154_device.c index a41ff240bf..85a52c0051 100644 --- a/wireless/ieee802154/mac802154_device.c +++ b/wireless/ieee802154/mac802154_device.c @@ -600,6 +600,7 @@ static ssize_t mac802154dev_write(FAR struct file *filep, ret = mac802154_req_data(dev->md_mac, &tx->meta, iob); if (ret < 0) { + iob_free(iob); wlerr("ERROR: req_data failed %d\n", ret); return ret; } @@ -616,7 +617,7 @@ static ssize_t mac802154dev_write(FAR struct file *filep, ****************************************************************************/ static int mac802154dev_ioctl(FAR struct file *filep, int cmd, - unsigned long arg) + unsigned long arg) { FAR struct inode *inode; FAR struct mac802154_chardevice_s *dev; @@ -697,7 +698,6 @@ static int mac802154dev_ioctl(FAR struct file *filep, int cmd, /* Free the notification */ mac802154_notif_free(dev->md_mac, notif); - ret = OK; break; } diff --git a/wireless/ieee802154/mac802154_disassoc.c b/wireless/ieee802154/mac802154_disassoc.c new file mode 100644 index 0000000000..ab5a745068 --- /dev/null +++ b/wireless/ieee802154/mac802154_disassoc.c @@ -0,0 +1,79 @@ +/**************************************************************************** + * wireless/ieee802154/mac802154_disassoc.c + * + * Copyright (C) 2016 Sebastien Lorquet. All rights reserved. + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2017 Verge Inc. All rights reserved. + * + * Author: Sebastien Lorquet + * Author: Gregory Nutt + * Author: Anthony Merlino + * + * 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 "mac802154.h" + +#include + +/**************************************************************************** + * Public MAC Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mac802154_req_disassociate + * + * 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 mac802154_maccb_s->conf_disassociate callback. + * + ****************************************************************************/ + +int mac802154_req_disassociate(MACHANDLE mac, + FAR struct ieee802154_disassoc_req_s *req) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + return -ENOTTY; +} \ No newline at end of file diff --git a/wireless/ieee802154/mac802154_get_mhrlen.c b/wireless/ieee802154/mac802154_get_mhrlen.c new file mode 100644 index 0000000000..608acd8067 --- /dev/null +++ b/wireless/ieee802154/mac802154_get_mhrlen.c @@ -0,0 +1,135 @@ +/**************************************************************************** + * wireless/ieee802154/mac802154_get_mhrlen.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2017 Verge Inc. All rights reserved. + * + * Author: Gregory Nutt + * Author: Anthony Merlino + * + * 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 "mac802154.h" +#include "mac802154_internal.h" + +#include + +/**************************************************************************** + * Public MAC Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mac802154_get_mhrlen + * + * Description: + * Calculate the MAC header length given the frame meta-data. + * + ****************************************************************************/ + +int mac802154_get_mhrlen(MACHANDLE mac, + FAR const struct ieee802154_frame_meta_s *meta) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + int ret = 3; /* Always frame control (2 bytes) and seq. num (1 byte) */ + + /* Check to make sure both the dest address and the source address are not set + * to NONE */ + + if (meta->destaddr.mode == IEEE802154_ADDRMODE_NONE && + meta->srcaddr_mode == IEEE802154_ADDRMODE_NONE) + { + return -EINVAL; + } + + /* The source address can only be set to NONE if the device is the PAN coord */ + + if (meta->srcaddr_mode == IEEE802154_ADDRMODE_NONE && + priv->devmode != IEEE802154_DEVMODE_PANCOORD) + { + return -EINVAL; + } + + /* Add the destination address length */ + + ret += mac802154_addr_length[meta->destaddr.mode]; + + /* Add the source address length */ + + ret += mac802154_addr_length[ meta->srcaddr_mode]; + + /* If both destination and source addressing information is present, the MAC + * sublayer shall compare the destination and source PAN identifiers. + * [1] pg. 41. + */ + + if (meta->srcaddr_mode != IEEE802154_ADDRMODE_NONE && + meta->destaddr.mode != IEEE802154_ADDRMODE_NONE) + { + /* If the PAN identifiers are identical, the PAN ID Compression field + * shall be set to one, and the source PAN identifier shall be omitted + * from the transmitted frame. [1] pg. 41. + */ + + if (meta->destaddr.panid == priv->addr.panid) + { + ret += 2; /* 2 bytes for destination PAN ID */ + return ret; + } + } + + /* If we are here, PAN ID compression is off, so include the dest and source + * PAN ID if the respective address is included + */ + + if (meta->srcaddr_mode != IEEE802154_ADDRMODE_NONE) + { + ret += 2; /* 2 bytes for source PAN ID */ + } + + if (meta->destaddr.mode != IEEE802154_ADDRMODE_NONE) + { + ret += 2; /* 2 bytes for destination PAN ID */ + } + + return ret; +} diff --git a/wireless/ieee802154/mac802154_getset.c b/wireless/ieee802154/mac802154_getset.c new file mode 100644 index 0000000000..f32559b9ab --- /dev/null +++ b/wireless/ieee802154/mac802154_getset.c @@ -0,0 +1,181 @@ +/**************************************************************************** + * wireless/ieee802154/mac802154_getset.c + * + * Copyright (C) 2016 Sebastien Lorquet. All rights reserved. + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2017 Verge Inc. All rights reserved. + * + * Author: Sebastien Lorquet + * Author: Gregory Nutt + * Author: Anthony Merlino + * + * 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 "mac802154.h" +#include "mac802154_internal.h" + +#include + +/**************************************************************************** + * Public MAC Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mac802154_req_get + * + * Description: + * The MLME-GET.request primitive requests information about a given PIB + * attribute. + * + * NOTE: The standard specifies that the attribute value should be returned + * via the asynchronous MLME-GET.confirm primitve. However, in our + * implementation, we synchronously return the value immediately.Therefore, we + * merge the functionality of the MLME-GET.request and MLME-GET.confirm + * primitives together. + * + ****************************************************************************/ + +int mac802154_req_get(MACHANDLE mac, enum ieee802154_attr_e attr, + FAR union ieee802154_attr_u *attrval) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + int ret = IEEE802154_STATUS_SUCCESS; + + switch (attr) + { + case IEEE802154_ATTR_MAC_PANID: + attrval->mac.panid = priv->addr.panid; + break; + case IEEE802154_ATTR_MAC_SHORT_ADDRESS: + attrval->mac.saddr = priv->addr.saddr; + break; + case IEEE802154_ATTR_MAC_EXTENDED_ADDR: + memcpy(&attrval->mac.eaddr[0], &priv->addr.eaddr[0], IEEE802154_EADDR_LEN); + break; + case IEEE802154_ATTR_MAC_DEVMODE: + attrval->mac.devmode = priv->devmode; + break; + default: + /* The attribute may be handled soley in the radio driver, so pass + * it along. + */ + + ret = priv->radio->set_attr(priv->radio, attr, attrval); + break; + } + + return ret; +} + +/**************************************************************************** + * Name: mac802154_req_set + * + * Description: + * The MLME-SET.request primitive attempts to write the given value to the + * indicated MAC PIB attribute. + * + * NOTE: The standard specifies that confirmation should be indicated via + * the asynchronous MLME-SET.confirm primitve. However, in our implementation + * we synchronously return the status from the request. Therefore, we do merge + * the functionality of the MLME-SET.request and MLME-SET.confirm primitives + * together. + * + ****************************************************************************/ + +int mac802154_req_set(MACHANDLE mac, enum ieee802154_attr_e attr, + FAR const union ieee802154_attr_u *attrval) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + int ret; + + switch (attr) + { + case IEEE802154_ATTR_MAC_PANID: + { + priv->addr.panid = attrval->mac.panid; + + /* Tell the radio about the attribute */ + + priv->radio->set_attr(priv->radio, attr, attrval); + + ret = IEEE802154_STATUS_SUCCESS; + } + break; + case IEEE802154_ATTR_MAC_SHORT_ADDRESS: + { + priv->addr.saddr = attrval->mac.saddr; + + /* Tell the radio about the attribute */ + + priv->radio->set_attr(priv->radio, attr, attrval); + + ret = IEEE802154_STATUS_SUCCESS; + } + break; + case IEEE802154_ATTR_MAC_EXTENDED_ADDR: + { + /* Set the MAC copy of the address in the table */ + + memcpy(&priv->addr.eaddr[0], &attrval->mac.eaddr[0], + IEEE802154_EADDR_LEN); + + /* Tell the radio about the attribute */ + + priv->radio->set_attr(priv->radio, attr, attrval); + + ret = IEEE802154_STATUS_SUCCESS; + } + break; + default: + { + /* The attribute may be handled soley in the radio driver, so pass + * it along. + */ + + ret = priv->radio->set_attr(priv->radio, attr, attrval); + } + break; + } + return ret; +} \ No newline at end of file diff --git a/wireless/ieee802154/mac802154_gts.c b/wireless/ieee802154/mac802154_gts.c new file mode 100644 index 0000000000..e24e409f81 --- /dev/null +++ b/wireless/ieee802154/mac802154_gts.c @@ -0,0 +1,72 @@ +/**************************************************************************** + * wireless/ieee802154/mac802154_gts.c + * + * Copyright (C) 2017 Verge Inc. All rights reserved. + * Author: Anthony Merlino + * + * 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 "mac802154.h" + +#include + +/**************************************************************************** + * Public MAC Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mac802154_req_gts + * + * 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 mac802154_maccb_s->conf_gts callback. + * + ****************************************************************************/ + +int mac802154_req_gts(MACHANDLE mac, FAR struct ieee802154_gts_req_s *req) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + return -ENOTTY; +} \ No newline at end of file diff --git a/wireless/ieee802154/mac802154_internal.h b/wireless/ieee802154/mac802154_internal.h new file mode 100644 index 0000000000..0e49c4654d --- /dev/null +++ b/wireless/ieee802154/mac802154_internal.h @@ -0,0 +1,405 @@ +/**************************************************************************** + * wireless/ieee802154/mac802154_internal.h + * + * Copyright (C) 2016 Sebastien Lorquet. All rights reserved. + * Copyright (C) 2017 Verge Inc. All rights reserved. + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * + * Author: Sebastien Lorquet + * Author: Anthony Merlino + * + * The naming and comments for various fields are taken directly + * from the IEEE 802.15.4 2011 standard. + * + * 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 __WIRELESS_IEEE802154__MAC802154_INTERNAL_H +#define __WIRELESS_IEEE802154__MAC802154_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "mac802154_notif.h" + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* If processing is not done at the interrupt level, then work queue support + * is required. + */ + +#if !defined(CONFIG_SCHED_WORKQUEUE) +# error Work queue support is required in this configuration (CONFIG_SCHED_WORKQUEUE) +#else + + /* Use the low priority work queue if possible */ + +# if defined(CONFIG_MAC802154_HPWORK) +# define MAC802154_WORK HPWORK +# elif defined(CONFIG_MAC802154_LPWORK) +# define MAC802154_WORK LPWORK +# else +# error Neither CONFIG_MAC802154_HPWORK nor CONFIG_MAC802154_LPWORK defined +# endif +#endif + +#if !defined(CONFIG_MAC802154_NNOTIF) || CONFIG_MAC802154_NNOTIF <= 0 +# undef CONFIG_MAC802154_NNOTIF +# define CONFIG_MAC802154_NNOTIF 6 +#endif + +#if !defined(CONFIG_MAC802154_NTXDESC) || CONFIG_MAC802154_NTXDESC <= 0 +# undef CONFIG_MAC802154_NTXDESC +# define CONFIG_MAC802154_NTXDESC 3 +#endif + +#if CONFIG_MAC802154_NTXDESC > CONFIG_MAC802154_NNOTIF +#error CONFIG_MAC802154_NNOTIF must be greater than CONFIG_MAC802154_NTXDESC +#endif + +#if !defined(CONFIG_IEEE802154_DEFAULT_EADDR) +#define CONFIG_IEEE802154_DEFAULT_EADDR 0xFFFFFFFFFFFFFFFF +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Map between ieee802154_addrmode_e enum and actual address length */ + +static const uint8_t mac802154_addr_length[4] = {0, 0, 2, 8}; + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct mac802154_radiocb_s +{ + struct ieee802154_radiocb_s cb; + FAR struct ieee802154_privmac_s *priv; +}; + +/* Enumeration for representing what operation the MAC layer is currently doing. + * There can only be one command being handled at any given time, but certain + * operations such as association requires more than one command to be sent. + * Therefore, the need to track not only what command is currently active, but + * also, what overall operation the command is apart of is necessary. + */ + +enum mac802154_operation_e +{ + MAC802154_OP_NONE, + MAC802154_OP_ASSOC, + MAC802154_OP_POLL +}; + +struct ieee802154_privmac_s; /* Forward Reference */ +typedef void (*mac802154_worker_t)(FAR struct ieee802154_privmac_s *priv); + +/* The privmac structure holds the internal state of the MAC and is the + * underlying represention of the opaque MACHANDLE. It contains storage for + * the IEEE802.15.4 MIB attributes. + */ + +struct ieee802154_privmac_s +{ + FAR struct ieee802154_radio_s *radio; /* Contained IEEE802.15.4 radio dev */ + FAR const struct mac802154_maccb_s *cb; /* Contained MAC callbacks */ + FAR struct mac802154_radiocb_s radiocb; /* Interface to bind to radio */ + + sem_t exclsem; /* Support exclusive access */ + + /* Only support a single command at any given time. As of now I see no + * condition where you need to have more than one command frame simultaneously + */ + + sem_t op_sem; /* Exclusive operations */ + enum mac802154_operation_e curr_op; /* The current overall operation */ + enum ieee802154_cmdid_e curr_cmd; /* Type of the current cmd */ + FAR struct ieee802154_txdesc_s *cmd_desc; /* TX descriptor for current cmd */ + + /* Pre-allocated notifications to be passed to the registered callback. These + * need to be freed by the application using mac802154_xxxxnotif_free when + * the callee layer is finished with it's use. + */ + + FAR struct mac802154_notif_s *notif_free; + struct mac802154_notif_s notif_pool[CONFIG_MAC802154_NNOTIF]; + sem_t notif_sem; + + struct ieee802154_txdesc_s txdesc_pool[CONFIG_IEEE802154_NTXDESC]; + sem_t txdesc_sem; + sq_queue_t txdesc_queue; + sq_queue_t txdone_queue; + + + /* Support a singly linked list of transactions that will be sent using the + * CSMA algorithm. On a non-beacon enabled PAN, these transactions will be + * sent whenever. On a beacon-enabled PAN, these transactions will be sent + * during the CAP of the Coordinator's superframe. + */ + + sq_queue_t csma_queue; + sq_queue_t gts_queue; + + /* Support a singly linked list of transactions that will be sent indirectly. + * This list should only be used by a MAC acting as a coordinator. These + * transactions will stay here until the data is extracted by the destination + * device sending a Data Request MAC command or if too much time passes. This + * list should also be used to populate the address list of the outgoing + * beacon frame. + */ + + sq_queue_t indirect_queue; + + /* Support a singly linked list of frames received */ + + sq_queue_t dataind_queue; + + /* Work structures for offloading aynchronous work */ + + struct work_s tx_work; + struct work_s rx_work; + + struct work_s timeout_work; + WDOG_ID timeout; /* Timeout watchdog */ + mac802154_worker_t timeout_worker; + + struct work_s purge_work; + + /* MAC PIB attributes, grouped to save memory */ + + /* Holds all address information (Extended, Short, and PAN ID) for the MAC. */ + + struct ieee802154_addr_s addr; + + /* Holds all address information (Extended, Short) for Coordinator */ + + struct ieee802154_addr_s coordaddr; + + /* The maximum number of symbols to wait for an acknowledgement frame to + * arrive following a transmitted data frame. [1] pg. 126 + * + * NOTE: This may be able to be a 16-bit or even an 8-bit number. I wasn't + * sure at the time what the range of reasonable values was. + */ + + uint32_t ack_waitdur; + + /* The maximum time to wait either for a frame intended as a response to a + * data request frame or for a broadcast frame following a beacon with the + * Frame Pending field set to one. [1] pg. 127 + * + * NOTE: This may be able to be a 16-bit or even an 8-bit number. I wasn't + * sure at the time what the range of reasonable values was. + */ + + uint32_t max_frame_waittime; + + /* The maximum time (in unit periods) that a transaction is stored by a + * coordinator and indicated in its beacon. + */ + + uint16_t trans_persisttime; + + /* Contents of beacon payload */ + + uint8_t beacon_payload[IEEE802154_MAX_BEACON_PAYLOAD_LEN]; + uint8_t beacon_payload_len; /* Length of beacon payload */ + + uint8_t battlifeext_periods; /* # of backoff periods during which rx is + * enabled after the IFS following beacon */ + + uint8_t bsn; /* Seq. num added to tx beacon frame */ + uint8_t dsn; /* Seq. num added to tx data or MAC frame */ + uint8_t maxretries; /* Max # of retries alloed after tx failure */ + + /* The maximum time, in multiples of aBaseSuperframeDuration, a device shall + * wait for a response command frame to be available following a request + * command frame. [1] 128. + */ + + uint8_t resp_waittime; + + /* The total transmit duration (including PHY header and FCS) specified in + * symbols. [1] pg. 129. + */ + + uint32_t tx_totaldur; + + /* Start of 32-bit bitfield */ + + uint32_t trackingbeacon : 1; /* Are we tracking the beacon */ + uint32_t isassoc : 1; /* Are we associated to the PAN */ + uint32_t assocpermit : 1; /* Are we allowing assoc. as a coord. */ + uint32_t autoreq : 1; /* Automatically send data req. if addr + * addr is in the beacon frame */ + + uint32_t battlifeext : 1; /* Is BLE enabled */ + uint32_t gtspermit : 1; /* Is PAN Coord. accepting GTS reqs. */ + uint32_t promisc : 1; /* Is promiscuous mode on? */ + uint32_t rngsupport : 1; /* Does MAC sublayer support ranging */ + uint32_t sec_enabled : 1; /* Does MAC sublayer have security en. */ + uint32_t timestamp_support : 1; /* Does MAC layer supports timestamping */ + + /* 2 available bits */ + + uint32_t beaconorder : 4; /* Freq. that beacon is transmitted */ + + uint32_t superframeorder : 4; /* Length of active portion of outgoing + * superframe, including the beacon */ + + /* The offset, measured is symbols, between the symbol boundary at which the + * MLME captures the timestamp of each transmitted and received frame, and + * the onset of the first symbol past the SFD, namely the first symbol of + * the frames [1] pg. 129. + */ + + uint32_t sync_symboffset : 12; + + /* End of 32-bit bitfield */ + + /* Start of 32-bit bitfield */ + + uint32_t beacon_txtime : 24; /* Time of last beacon transmit */ + uint32_t minbe : 4; /* Min value of backoff exponent (BE) */ + uint32_t maxbe : 4; /* Max value of backoff exponent (BE) */ + + /* End of 32-bit bitfield */ + + /* Start of 32-bit bitfield */ + + uint32_t txctrl_activedur : 17; /* Duration for which tx is permitted to + * be active */ + uint32_t txctrl_pausedur : 1; /* Duration after tx before another tx is + * permitted. 0=2000, 1= 10000 */ + + /* What type of device is this node acting as */ + + enum ieee802154_devmode_e devmode : 2; + + uint32_t max_csmabackoffs : 3; /* Max num backoffs for CSMA algorithm + * before declaring ch access failure */ + + /* 9-bits remaining */ + + /* End of 32-bit bitfield. */ + + /* TODO: Add Security-related MAC PIB attributes */ +}; + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +#define mac802154_givesem(s) sem_post(s); + +static inline int mac802154_takesem(sem_t *sem, bool allowinterrupt) +{ + int ret; + do + { + /* Take a count from the semaphore, possibly waiting */ + + ret = sem_wait(sem); + if (ret < 0) + { + /* EINTR is the only error that we expect */ + + DEBUGASSERT(get_errno() == EINTR); + + if (allowinterrupt) + { + return -EINTR; + } + } + } + while (ret != OK); + + return OK; +} + +static inline void mac802154_txdesc_free(FAR struct ieee802154_privmac_s *priv, + FAR struct ieee802154_txdesc_s *txdesc) +{ + sq_addlast((FAR sq_entry_t *)txdesc, &priv->txdesc_queue); + mac802154_givesem(&priv->txdesc_sem); +} + +/**************************************************************************** + * Name: mac802154_timercancel + * + * Description: + * Cancel timer and remove reference to callback function + * + * Assumptions: + * priv MAC struct is locked when calling. + * + ****************************************************************************/ + +static inline int mac802154_timercancel(FAR struct ieee802154_privmac_s *priv) +{ + wd_cancel(priv->timeout); + priv->timeout_worker = NULL; + return OK; +} + +/**************************************************************************** + * Function Prototypes + ****************************************************************************/ + + +int mac802154_txdesc_alloc(FAR struct ieee802154_privmac_s *priv, + FAR struct ieee802154_txdesc_s **txdesc, + bool allow_interrupt); + +int mac802154_timerstart(FAR struct ieee802154_privmac_s *priv, + uint32_t numsymbols, mac802154_worker_t); + +void mac802154_setupindirect(FAR struct ieee802154_privmac_s *priv, + FAR struct ieee802154_txdesc_s *txdesc); + +#endif /* __WIRELESS_IEEE802154__MAC802154_INTERNAL_H */ diff --git a/wireless/ieee802154/mac802154_ioctl.c b/wireless/ieee802154/mac802154_ioctl.c new file mode 100644 index 0000000000..35093f6936 --- /dev/null +++ b/wireless/ieee802154/mac802154_ioctl.c @@ -0,0 +1,169 @@ +/**************************************************************************** + * wireless/ieee802154/mac802154_ioctl.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2017 Verge Inc. All rights reserved. + * + * Author: Gregory Nutt + * Author: Anthony Merlino + * + * 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 "mac802154.h" + +#include + +/**************************************************************************** + * Public MAC Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mac802154_ioctl + * + * Description: + * Handle MAC and radio IOCTL commands directed to the MAC. + * + * Parameters: + * mac - Reference to the MAC driver state structure + * cmd - The IOCTL command + * arg - The argument for the IOCTL command + * + * Returned Value: + * OK on success; Negated errno on failure. + * + ****************************************************************************/ + +int mac802154_ioctl(MACHANDLE mac, int cmd, unsigned long arg) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + int ret = -EINVAL; + + FAR union ieee802154_macarg_u *macarg = + (FAR union ieee802154_macarg_u *)((uintptr_t)arg); + + DEBUGASSERT(priv != NULL); + + /* Check for IOCTLs aimed at the IEEE802.15.4 MAC layer */ + + if (_MAC802154IOCVALID(cmd)) + { + /* Handle the MAC IOCTL command */ + + switch (cmd) + { + case MAC802154IOC_MLME_ASSOC_REQUEST: + { + ret = mac802154_req_associate(mac, &macarg->assocreq); + } + break; + case MAC802154IOC_MLME_ASSOC_RESPONSE: + { + ret = mac802154_resp_associate(mac, &macarg->assocresp); + } + break; + case MAC802154IOC_MLME_DISASSOC_REQUEST: + { + ret = mac802154_req_disassociate(mac, &macarg->disassocreq); + } + break; + case MAC802154IOC_MLME_GET_REQUEST: + { + ret = mac802154_req_get(mac, macarg->getreq.attr, + &macarg->getreq.attrval); + } + break; + case MAC802154IOC_MLME_GTS_REQUEST: + { + ret = mac802154_req_gts(mac, &macarg->gtsreq); + } + break; + case MAC802154IOC_MLME_ORPHAN_RESPONSE: + { + ret = mac802154_resp_orphan(mac, &macarg->orphanresp); + } + break; + case MAC802154IOC_MLME_RESET_REQUEST: + { + ret = mac802154_req_reset(mac, macarg->resetreq.rst_pibattr); + } + break; + case MAC802154IOC_MLME_RXENABLE_REQUEST: + { + ret = mac802154_req_rxenable(mac, &macarg->rxenabreq); + } + break; + case MAC802154IOC_MLME_SCAN_REQUEST: + { + ret = mac802154_req_scan(mac, &macarg->scanreq); + } + break; + case MAC802154IOC_MLME_SET_REQUEST: + { + ret = mac802154_req_set(mac, macarg->setreq.attr, + &macarg->setreq.attrval); + } + break; + case MAC802154IOC_MLME_START_REQUEST: + { + ret = mac802154_req_start(mac, &macarg->startreq); + } + break; + case MAC802154IOC_MLME_SYNC_REQUEST: + { + ret = mac802154_req_sync(mac, &macarg->syncreq); + } + break; + case MAC802154IOC_MLME_POLL_REQUEST: + { + ret = mac802154_req_poll(mac, &macarg->pollreq); + } + break; + default: + wlerr("ERROR: Unrecognized cmd: %d\n", cmd); + ret = -ENOTTY; + break; + } + } + return ret; +} + diff --git a/wireless/ieee802154/mac802154_notif.c b/wireless/ieee802154/mac802154_notif.c new file mode 100644 index 0000000000..314e6bf5f3 --- /dev/null +++ b/wireless/ieee802154/mac802154_notif.c @@ -0,0 +1,208 @@ +/**************************************************************************** + * wireless/ieee802154/mac802154_notif.c + * + * Copyright (C) 2016 Sebastien Lorquet. All rights reserved. + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2017 Verge Inc. All rights reserved. + * + * Author: Sebastien Lorquet + * Author: Gregory Nutt + * Author: Anthony Merlino + * + * 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 "mac802154.h" +#include "mac802154_internal.h" + +#include + +/**************************************************************************** + * Public MAC Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mac802154_notif_free + * + * Description: + * When the MAC calls the registered callback, it passes a reference + * to a mac802154_notify_s structure. This structure needs to be freed + * after the callback handler is done using it. + * + ****************************************************************************/ + +int mac802154_notif_free(MACHANDLE mac, + FAR struct ieee802154_notif_s *notif) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + FAR struct mac802154_notif_s *privnotif = (FAR struct mac802154_notif_s *)notif; + + /* Get exclusive access to the MAC */ + + mac802154_takesem(&priv->exclsem, false); + + privnotif->flink = priv->notif_free; + priv->notif_free = privnotif; + mac802154_givesem(&priv->notif_sem); + + mac802154_givesem(&priv->exclsem); + + return -ENOTTY; +} + +/**************************************************************************** + * Internal MAC Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mac802154_notifpool_init + * + * Description: + * This function initializes the notification structure pool. It allows the + * MAC to pass notifications and for the callee to free them when they are + * done using them, saving copying the data when passing. + * + ****************************************************************************/ + +void mac802154_notifpool_init(FAR struct ieee802154_privmac_s *priv) +{ + FAR struct mac802154_notif_s *pool = priv->notif_pool; + int remaining = CONFIG_MAC802154_NNOTIF; + + priv->notif_free = NULL; + while (remaining > 0) + { + FAR struct mac802154_notif_s *notif = pool; + + /* Add the next meta data structure from the pool to the list of + * general structures. + */ + + notif->flink = priv->notif_free; + priv->notif_free = notif; + + /* Set up for the next structure from the pool */ + + pool++; + remaining--; + } + sem_init(&priv->notif_sem, 0, CONFIG_MAC802154_NNOTIF); +} + +/**************************************************************************** + * Name: mac802154_notif_alloc + * + * Description: + * This function allocates a free notification structure from the free list + * to be used for passing to the registered notify callback. The callee software + * is responsible for freeing the notification structure after it is done using + * it via mac802154_notif_free. + * + * Assumptions: + * priv MAC struct is locked when calling. + * + * Notes: + * If any of the semaphore waits inside this function get interrupted, the + * function will release the MAC layer. If this function returns -EINTR, the + * calling code should NOT release the MAC semaphore. + * + ****************************************************************************/ + +int mac802154_notif_alloc(FAR struct ieee802154_privmac_s *priv, + FAR struct ieee802154_notif_s **notif, + bool allow_interrupt) +{ + int ret; + FAR struct mac802154_notif_s *privnotif; + + /* Try and take a count from the semaphore. If this succeeds, we have + * "reserved" the structure, but still need to unlink it from the free list. + * The MAC is already locked, so there shouldn't be any other conflicting calls + */ + + ret = sem_trywait(&priv->notif_sem); + + if (ret == OK) + { + privnotif = priv->notif_free; + priv->notif_free = privnotif->flink; + } + else + { + /* Unlock MAC so that other work can be done to free a notification */ + + mac802154_givesem(&priv->exclsem); + + /* Take a count from the notification semaphore, waiting if necessary. We + * only return from here with an error if we are allowing interruptions + * and we received a signal */ + + ret = mac802154_takesem(&priv->notif_sem, allow_interrupt); + if (ret < 0) + { + /* MAC sem is already released */ + + return -EINTR; + } + + /* If we've taken a count from the semaphore, we have "reserved" the struct + * but now we need to pop it off of the free list. We need to re-lock the + * MAC in order to ensure this happens correctly. + */ + + ret = mac802154_takesem(&priv->exclsem, allow_interrupt); + if (ret < 0) + { + mac802154_givesem(&priv->notif_sem); + return -EINTR; + } + + /* We can now safely unlink the next free structure from the free list */ + + privnotif = priv->notif_free; + priv->notif_free = privnotif->flink; + } + + *notif = (FAR struct ieee802154_notif_s *)privnotif; + + return OK; +} \ No newline at end of file diff --git a/wireless/ieee802154/mac802154_notif.h b/wireless/ieee802154/mac802154_notif.h new file mode 100644 index 0000000000..3cf088163d --- /dev/null +++ b/wireless/ieee802154/mac802154_notif.h @@ -0,0 +1,82 @@ +/**************************************************************************** + * wireless/ieee802154/mac802154_notif.h + * + * Copyright (C) 2017 Verge Inc. All rights reserved. + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * + * Author: Anthony Merlino + * Author: Gregory Nutt + * + * The naming and comments for various fields are taken directly + * from the IEEE 802.15.4 2011 standard. + * + * 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 __WIRELESS_IEEE802154__MAC802154_NOTIF_H +#define __WIRELESS_IEEE802154__MAC802154_NOTIF_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Extend the public ieee802154_notif_s to include a private forward link to + * support a list to handle allocation + */ + +struct mac802154_notif_s +{ + struct ieee802154_notif_s pub; + FAR struct mac802154_notif_s *flink; +}; + +/**************************************************************************** + * Function Prototypes + ****************************************************************************/ + +struct ieee802154_privmac_s; /* Forward Reference */ + +void mac802154_notifpool_init(FAR struct ieee802154_privmac_s *priv); + +int mac802154_notif_alloc(FAR struct ieee802154_privmac_s *priv, + FAR struct ieee802154_notif_s **notif, + bool allow_interrupt); + +#endif /* __WIRELESS_IEEE802154__MAC802154_NOTIF_H */ \ No newline at end of file diff --git a/wireless/ieee802154/mac802154_orphan.c b/wireless/ieee802154/mac802154_orphan.c new file mode 100644 index 0000000000..9e4a80d4f2 --- /dev/null +++ b/wireless/ieee802154/mac802154_orphan.c @@ -0,0 +1,71 @@ +/**************************************************************************** + * wireless/ieee802154/mac802154_orphan.c + * + * Copyright (C) 2017 Verge Inc. All rights reserved. + * Author: Anthony Merlino + * + * 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 "mac802154.h" + +#include + +/**************************************************************************** + * Public MAC Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mac802154_resp_orphan + * + * Description: + * The MLME-ORPHAN.response primitive allows the next higher layer of a + * coordinator to respond to the MLME-ORPHAN.indication primitive. + * + ****************************************************************************/ + +int mac802154_resp_orphan(MACHANDLE mac, + FAR struct ieee802154_orphan_resp_s *resp) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + return -ENOTTY; +} diff --git a/wireless/ieee802154/mac802154_poll.c b/wireless/ieee802154/mac802154_poll.c new file mode 100644 index 0000000000..58b6217211 --- /dev/null +++ b/wireless/ieee802154/mac802154_poll.c @@ -0,0 +1,376 @@ +/**************************************************************************** + * wireless/ieee802154/mac802154_poll.c + * + * Copyright (C) 2016 Sebastien Lorquet. All rights reserved. + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2017 Verge Inc. All rights reserved. + * + * Author: Sebastien Lorquet + * Author: Gregory Nutt + * Author: Anthony Merlino + * + * 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 "mac802154.h" +#include "mac802154_internal.h" + +#include +#include + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void mac802154_timeout_poll(FAR struct ieee802154_privmac_s *priv); + +/**************************************************************************** + * Public MAC Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mac802154_req_poll + * + * Description: + * The MLME-POLL.request primitive prompts the device to request data from + * the coordinator. Confirmation is returned via the + * struct mac802154_maccb_s->conf_poll callback, followed by a + * struct mac802154_maccb_s->ind_data callback. + * + ****************************************************************************/ + +int mac802154_req_poll(MACHANDLE mac, FAR struct ieee802154_poll_req_s *req) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + FAR struct iob_s *iob; + FAR struct ieee802154_txdesc_s *txdesc; + FAR uint16_t *frame_ctrl; + int ret; + + /* On receipt of the MLME-POLL.request primitive, the MLME requests data from + * the coordinator, as described in 5.1.6.3. If the poll is directed to the + * PAN coordinator, the data request command may be generated without any + * destination address information present. Otherwise, the data request + * command is always generated with the destination address information in the + * CoordPANId and CoordAddress parameters. + */ + + /* Get exlusive access to the operation sempaphore. This must happen before + * getting exclusive access to the MAC struct or else there could be a lockup + * condition. This would occur if another thread is using the cmdtrans but + * needs access to the MAC in order to unlock it. + */ + + ret = mac802154_takesem(&priv->op_sem, true); + if (ret < 0) + { + return ret; + } + + priv->curr_op = MAC802154_OP_POLL; + priv->curr_cmd = IEEE802154_CMD_DATA_REQ; + + /* Get exclusive access to the MAC */ + + ret = mac802154_takesem(&priv->exclsem, true); + if (ret < 0) + { + mac802154_givesem(&priv->op_sem); + return ret; + } + + /* Allocate an IOB to put the frame in */ + + iob = iob_alloc(false); + DEBUGASSERT(iob != NULL); + + iob->io_flink = NULL; + iob->io_len = 0; + iob->io_offset = 0; + iob->io_pktlen = 0; + + /* Allocate the txdesc, waiting if necessary */ + + ret = mac802154_txdesc_alloc(priv, &txdesc, true); + if (ret < 0) + { + iob_free(iob); + mac802154_givesem(&priv->exclsem); + mac802154_givesem(&priv->op_sem); + return ret; + } + + /* Get a uin16_t reference to the first two bytes. ie frame control field */ + + frame_ctrl = (FAR uint16_t *)&iob->io_data[0]; + iob->io_len = 2; + + *frame_ctrl = (IEEE802154_FRAME_COMMAND << IEEE802154_FRAMECTRL_SHIFT_FTYPE); + *frame_ctrl |= IEEE802154_FRAMECTRL_ACKREQ; + + /* Each time a data or a MAC command frame is generated, the MAC sublayer + * shall copy the value of macDSN into the Sequence Number field of the + * MHR of the outgoing frame and then increment it by one. [1] pg. 40. + */ + + iob->io_data[iob->io_len++] = priv->dsn++; + + /* If the destination address is present, copy the PAN ID and one of the + * addresses, depending on mode, into the MHR. + */ + + if (req->coordaddr.mode != IEEE802154_ADDRMODE_NONE) + { + memcpy(&iob->io_data[iob->io_len], &req->coordaddr.panid, 2); + iob->io_len += 2; + + if (req->coordaddr.mode == IEEE802154_ADDRMODE_SHORT) + { + memcpy(&iob->io_data[iob->io_len], &req->coordaddr.saddr, 2); + iob->io_len += 2; + } + else if (req->coordaddr.mode == IEEE802154_ADDRMODE_EXTENDED) + { + memcpy(&iob->io_data[iob->io_len], &req->coordaddr.eaddr, + IEEE802154_EADDR_LEN); + iob->io_len += IEEE802154_EADDR_LEN; + } + } + + *frame_ctrl |= (req->coordaddr.mode << IEEE802154_FRAMECTRL_SHIFT_DADDR); + + + + /* If the PAN identifiers are identical, the PAN ID Compression field + * shall be set to one, and the source PAN identifier shall be omitted + * from the transmitted frame. [1] pg. 41. + */ + + if (req->coordaddr.mode != IEEE802154_ADDRMODE_NONE && + req->coordaddr.panid == priv->addr.panid) + { + *frame_ctrl |= IEEE802154_FRAMECTRL_PANIDCOMP; + } + else + { + memcpy(&iob->io_data[iob->io_len], &priv->addr.panid, 2); + iob->io_len += 2; + } + + /* The Source Addressing Mode field shall be set according to the value of + * macShortAddress. If macShortAddress is less than 0xfffe, short addressing + * shall be used. Extended addressing shall be used otherwise. + */ + + if (priv->addr.saddr == IEEE802154_SADDR_BCAST) + { + *frame_ctrl |= (IEEE802154_ADDRMODE_EXTENDED << IEEE802154_FRAMECTRL_SHIFT_SADDR); + memcpy(&iob->io_data[iob->io_len], &priv->addr.eaddr[0], IEEE802154_EADDR_LEN); + iob->io_len += IEEE802154_EADDR_LEN; + } + else + { + *frame_ctrl |= (IEEE802154_ADDRMODE_SHORT << IEEE802154_FRAMECTRL_SHIFT_SADDR); + memcpy(&iob->io_data[iob->io_len], &priv->addr.saddr, 2); + iob->io_len += 2; + } + + /* Copy in the Command Frame Identifier */ + + iob->io_data[iob->io_len++] = IEEE802154_CMD_DATA_REQ; + + /* Copy the IOB reference to the descriptor */ + + txdesc->frame = iob; + txdesc->frametype = IEEE802154_FRAME_COMMAND; + + /* Save a copy of the destination addressing infromation into the tx descriptor. + * We only do this for commands to help with handling their progession. + */ + + memcpy(&txdesc->destaddr, &req->coordaddr, sizeof(struct ieee802154_addr_s)); + + /* Save a reference of the tx descriptor */ + + priv->cmd_desc = txdesc; + + /* Link the transaction into the CSMA transaction list */ + + sq_addlast((FAR sq_entry_t *)txdesc, &priv->csma_queue); + + /* We no longer need to have the MAC layer locked. */ + + mac802154_givesem(&priv->exclsem); + + /* Notify the radio driver that there is data available */ + + priv->radio->txnotify(priv->radio, false); + + return OK; +} + +/**************************************************************************** + * Internal MAC Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mac802154_txdone_datareq_poll + * + * Description: + * Handle the completion (success/failure) of transmitting a data request + * command in an effort to extract data from the coordinator triggered by + * a POLL.request from the next highest layer + * + * Assumptions: + * Called with the MAC locked. + * + ****************************************************************************/ + +void mac802154_txdone_datareq_poll(FAR struct ieee802154_privmac_s *priv, + FAR struct ieee802154_txdesc_s *txdesc) +{ + enum ieee802154_status_e status; + FAR struct mac802154_notif_s *privnotif = + (FAR struct mac802154_notif_s *)txdesc->conf; + FAR struct ieee802154_notif_s *notif = &privnotif->pub; + + /* If the data request failed to be sent, notify the next layer + * that the poll has failed. + * OR + * On receipt of the Ack frame with the Frame Pending field set + * to zero, the device shall conclude that there are no data + * pending at the coordinator. [1] pg. 43 + */ + + if (notif->u.dataconf.status != IEEE802154_STATUS_SUCCESS || + txdesc->framepending == 0) + { + if (notif->u.dataconf.status != IEEE802154_STATUS_SUCCESS) + { + status = notif->u.dataconf.status; + } + else + { + status = IEEE802154_STATUS_NO_DATA; + } + + notif->notiftype = IEEE802154_NOTIFY_CONF_POLL; + notif->u.pollconf.status = status; + + /* We are now done the operation, and can release the command */ + + priv->curr_op = MAC802154_OP_NONE; + priv->cmd_desc = NULL; + mac802154_givesem(&priv->op_sem); + + /* Release the MAC, call the callback, get exclusive access again */ + + mac802154_givesem(&priv->exclsem); + priv->cb->notify(priv->cb, notif); + mac802154_takesem(&priv->exclsem, false); + } + else + { + /* On receipt of the acknowledgment frame with the Frame + * Pending field set to one, a device shall enable its + * receiver for at most macMaxFrameTotalWaitTime to receive + * the corresponding data frame from the coordinator. [1] pg.43 + */ + + priv->radio->rxenable(priv->radio, true); + + /* Start a timer, if we receive the data frame, we will cancel + * the timer, otherwise it will expire and we will notify the + * next highest layer of the failure. + */ + + mac802154_timerstart(priv, priv->max_frame_waittime, + mac802154_timeout_poll); + + /* We can deallocate the data conf notification as it is no longer + * needed. We can't use the public function here since we already + * have the MAC locked. + */ + + privnotif->flink = priv->notif_free; + priv->notif_free = privnotif; + } +} + +/**************************************************************************** + * Name: mac802154_timeout_poll + * + * Description: + * Function registered with MAC timer that gets called via the work queue to + * handle a timeout for extracting a response from the Coordinator. + * + ****************************************************************************/ + +static void mac802154_timeout_poll(FAR struct ieee802154_privmac_s *priv) +{ + FAR struct ieee802154_notif_s *notif; + + DEBUGASSERT(priv->curr_op == MAC802154_OP_POLL); + + /* Allocate a notification struct to pass to the next highest layer. + * Don't allow EINTR to interrupt. + */ + + mac802154_takesem(&priv->exclsem, false); + mac802154_notif_alloc(priv, ¬if, false); + + /* We are no longer performing the association operation */ + priv->curr_op = MAC802154_OP_NONE; + priv->cmd_desc = NULL; + mac802154_givesem(&priv->op_sem); + + /* Release the MAC */ + + mac802154_givesem(&priv->exclsem); + + notif->notiftype = IEEE802154_NOTIFY_CONF_POLL; + notif->u.pollconf.status = IEEE802154_STATUS_NO_DATA; + + priv->cb->notify(priv->cb, notif); +} \ No newline at end of file diff --git a/wireless/ieee802154/mac802154_poll.h b/wireless/ieee802154/mac802154_poll.h new file mode 100644 index 0000000000..ceb393023c --- /dev/null +++ b/wireless/ieee802154/mac802154_poll.h @@ -0,0 +1,66 @@ +/**************************************************************************** + * wireless/ieee802154/mac802154_poll.h + * + * Copyright (C) 2017 Verge Inc. All rights reserved. + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * + * Author: Anthony Merlino + * Author: Gregory Nutt + * + * The naming and comments for various fields are taken directly + * from the IEEE 802.15.4 2011 standard. + * + * 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 __WIRELESS_IEEE802154__MAC802154_POLL_H +#define __WIRELESS_IEEE802154__MAC802154_POLL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +/**************************************************************************** + * Function Prototypes + ****************************************************************************/ + +struct ieee802154_privmac_s; /* Forward Reference */ + +void mac802154_txdone_datareq_poll(FAR struct ieee802154_privmac_s *priv, + FAR struct ieee802154_txdesc_s *txdesc); + +#endif /* __WIRELESS_IEEE802154__MAC802154_POLL_H */ \ No newline at end of file diff --git a/wireless/ieee802154/mac802154_purge.c b/wireless/ieee802154/mac802154_purge.c new file mode 100644 index 0000000000..8249cb5678 --- /dev/null +++ b/wireless/ieee802154/mac802154_purge.c @@ -0,0 +1,83 @@ +/**************************************************************************** + * wireless/ieee802154/mac802154_purge.c + * + * Copyright (C) 2016 Sebastien Lorquet. All rights reserved. + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2017 Verge Inc. All rights reserved. + * + * Author: Sebastien Lorquet + * Author: Gregory Nutt + * Author: Anthony Merlino + * + * 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 "mac802154.h" + +#include + +/**************************************************************************** + * Public MAC Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mac802154_req_purge + * + * 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 mac802154_maccb_s->conf_purge callback. + * + * NOTE: The standard specifies that confirmation should be indicated via + * the asynchronous MLME-PURGE.confirm primitve. However, in our + * implementation we synchronously return the status from the request. + * Therefore, we merge the functionality of the MLME-PURGE.request and + * MLME-PURGE.confirm primitives together. + * + ****************************************************************************/ + +int mac802154_req_purge(MACHANDLE mac, uint8_t msdu_handle) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + return -ENOTTY; +} + diff --git a/wireless/ieee802154/mac802154_reset.c b/wireless/ieee802154/mac802154_reset.c new file mode 100644 index 0000000000..c1115d01db --- /dev/null +++ b/wireless/ieee802154/mac802154_reset.c @@ -0,0 +1,159 @@ +/**************************************************************************** + * wireless/ieee802154/mac802154_reset.c + * + * Copyright (C) 2016 Sebastien Lorquet. All rights reserved. + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2017 Verge Inc. All rights reserved. + * + * Author: Sebastien Lorquet + * Author: Gregory Nutt + * Author: Anthony Merlino + * + * 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 "mac802154.h" +#include "mac802154_internal.h" + +#include + +/**************************************************************************** + * Public MAC Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mac802154_req_reset + * + * Description: + * The MLME-RESET.request primitive allows the next higher layer to request + * that the MLME performs a reset operation. + * + * NOTE: The standard specifies that confirmation should be provided via + * via the asynchronous MLME-RESET.confirm primitve. However, in our + * implementation we synchronously return the value immediately. Therefore, + * we merge the functionality of the MLME-RESET.request and MLME-RESET.confirm + * primitives together. + * + * Input Parameters: + * mac - Handle to the MAC layer instance + * rst_pibattr - Whether or not to reset the MAC PIB attributes to defaults + * + ****************************************************************************/ + +int mac802154_req_reset(MACHANDLE mac, bool rst_pibattr) +{ + FAR struct ieee802154_privmac_s * priv = + (FAR struct ieee802154_privmac_s *) mac; + union ieee802154_attr_u attr; + + if (rst_pibattr) + { + priv->isassoc = false; /* Not associated with a PAN */ + priv->trackingbeacon = false; /* Not tracking beacon by default */ + priv->assocpermit = false; /* Device (if coord) not accepting ssociation */ + priv->autoreq = true; /* Auto send data req if addr. in beacon */ + priv->battlifeext = false; /* BLE disabled */ + priv->beacon_payload_len = 0; /* Beacon payload NULL */ + priv->beaconorder = 15; /* Non-beacon enabled network */ + priv->superframeorder = 15; /* Length of active portion of outgoing SF */ + priv->beacon_txtime = 0; /* Device never sent a beacon */ +#warning Set BSN and DSN to random values! + priv->bsn = 0; + priv->dsn = 0; + priv->gtspermit = true; /* PAN Coord accepting GTS requests */ + priv->minbe = 3; /* Min value of backoff exponent (BE) */ + priv->maxbe = 5; /* Max value of backoff exponent (BE) */ + priv->max_csmabackoffs = 4; /* Max # of backoffs before failure */ + priv->maxretries = 3; /* Max # of retries allowed after failure */ + priv->promisc = false; /* Device not in promiscuous mode */ + priv->rngsupport = false; /* Ranging not yet supported */ + priv->resp_waittime = 32; /* 32 SF durations */ + priv->sec_enabled = false; /* Security disabled by default */ + priv->tx_totaldur = 0; /* 0 transmit duration */ + + priv->trans_persisttime = 0x01F4; + + /* Reset the Coordinator address */ + + priv->coordaddr.mode = IEEE802154_ADDRMODE_NONE; + priv->coordaddr.saddr = IEEE802154_SADDR_UNSPEC; + memcpy(&priv->coordaddr.eaddr[0], IEEE802154_EADDR_UNSPEC, + IEEE802154_EADDR_LEN); + + /* Reset the device's address */ + + priv->addr.mode = IEEE802154_ADDRMODE_NONE; + priv->addr.panid = IEEE802154_PAN_UNSPEC; + priv->addr.saddr = IEEE802154_SADDR_UNSPEC; + memcpy(&priv->addr.eaddr[0], IEEE802154_EADDR_UNSPEC, IEEE802154_EADDR_LEN); + + priv->radio->reset_attrs(priv->radio); + + /* The radio is in control of certain attributes, but we keep a mirror + * for easy access. Copy in the radio's values now that they've been + * reset. + */ + + priv->radio->get_attr(priv->radio, IEEE802154_ATTR_MAC_MAX_FRAME_WAITTIME, + &attr); + priv->max_frame_waittime = attr.mac.max_frame_waittime; + + /* These attributes are effected and determined based on the PHY. Need to + * figure out how to "share" attributes between the radio driver and this + * MAC layer + * + * macAckWaitDuration + * macBattLifeExtPeriods + * macMaxFrameTotalWaitTime + * macLIFSPeriod + * macSIFSPeriod + * macSyncSymbolOffset + * macTimestampSupported + * macTxControlActiveDuration + * macTxControlPauseDuration + * macRxOnWhenIdle + */ + } + + return OK; +} + + diff --git a/wireless/ieee802154/mac802154_rxenable.c b/wireless/ieee802154/mac802154_rxenable.c new file mode 100644 index 0000000000..683d130e75 --- /dev/null +++ b/wireless/ieee802154/mac802154_rxenable.c @@ -0,0 +1,78 @@ +/**************************************************************************** + * wireless/ieee802154/mac802154_rxenable.c + * + * Copyright (C) 2016 Sebastien Lorquet. All rights reserved. + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2017 Verge Inc. All rights reserved. + * + * Author: Sebastien Lorquet + * Author: Gregory Nutt + * Author: Anthony Merlino + * + * 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 "mac802154.h" + +#include + +/**************************************************************************** + * Public MAC Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mac802154_req_rxenable + * + * 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 mac802154_maccb_s->conf_rxenable callback. + * + ****************************************************************************/ + +int mac802154_req_rxenable(MACHANDLE mac, + FAR struct ieee802154_rxenable_req_s *req) +{ + FAR struct ieee802154_privmac_s * priv = + (FAR struct ieee802154_privmac_s *)mac; + return -ENOTTY; +} \ No newline at end of file diff --git a/wireless/ieee802154/mac802154_scan.c b/wireless/ieee802154/mac802154_scan.c new file mode 100644 index 0000000000..1ba9932288 --- /dev/null +++ b/wireless/ieee802154/mac802154_scan.c @@ -0,0 +1,82 @@ +/**************************************************************************** + * wireless/ieee802154/mac80215_scan.c + * + * Copyright (C) 2016 Sebastien Lorquet. All rights reserved. + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2017 Verge Inc. All rights reserved. + * + * Author: Sebastien Lorquet + * Author: Gregory Nutt + * Author: Anthony Merlino + * + * 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 "mac802154.h" + +#include + +/**************************************************************************** + * Public MAC Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mac802154_req_scan + * + * 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 mac802154_maccb_s->conf_scan callback. + * This is a difference with the official 802.15.4 specification, implemented + * here to save memory. + * + ****************************************************************************/ + +int mac802154_req_scan(MACHANDLE mac, FAR struct ieee802154_scan_req_s *req) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + return -ENOTTY; +} + diff --git a/wireless/ieee802154/mac802154_start.c b/wireless/ieee802154/mac802154_start.c new file mode 100644 index 0000000000..6b0c051717 --- /dev/null +++ b/wireless/ieee802154/mac802154_start.c @@ -0,0 +1,167 @@ +/**************************************************************************** + * wireless/ieee802154/mac802154_start.c + * + * Copyright (C) 2017 Verge Inc. All rights reserved. + * Author: Anthony Merlino + * + * 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 "mac802154.h" +#include "mac802154_internal.h" + +#include + +/**************************************************************************** + * Public MAC Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mac802154_req_start + * + * 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 mac802154_maccb_s->conf_start callback. + * + ****************************************************************************/ + +int mac802154_req_start(MACHANDLE mac, FAR struct ieee802154_start_req_s *req) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + int ret; + + /* Get exclusive access to the MAC */ + + ret = mac802154_takesem(&priv->exclsem, true); + if (ret < 0) + { + return ret; + } + + /* When the CoordRealignment parameter is set to TRUE, the coordinator + * attempts to transmit a coordinator realignment command frame as described + * in 5.1.2.3.2. If the transmission of the coordinator realignment command + * fails due to a channel access failure, the MLME will not make any changes + * to the superframe configuration. (i.e., no PIB attributes will be changed). + * If the coordinator realignment command is successfully transmitted, the + * MLME updates the PIB attributes BeaconOrder, SuperframeOrder, PANId, + * ChannelPage, and ChannelNumber parameters. [1] pg. 106 + */ + + if (req->coordrealign) + { + /* TODO: Finish the realignment functionality */ + + return -ENOTTY; + } + + /* Set the PANID attribute */ + + priv->addr.panid = req->panid; + priv->radio->set_attr(priv->radio, IEEE802154_ATTR_MAC_PANID, + (FAR const union ieee802154_attr_u *)&req->panid); + + /* Set the radio attributes */ + priv->radio->set_attr(priv->radio, IEEE802154_ATTR_PHY_CURRENT_CHANNEL, + (FAR const union ieee802154_attr_u *)&req->chnum); + + priv->radio->set_attr(priv->radio, IEEE802154_ATTR_PHY_CURRENT_PAGE, + (FAR const union ieee802154_attr_u *)&req->chpage); + + + /* Set the beacon order */ + + if(req->beaconorder > 15) + { + ret = -EINVAL; + goto errout; + } + + priv->beaconorder = req->beaconorder; + + /* The value of macSuperframeOrder shall be ignored if macBeaconOrder = 15. pg. 19 */ + + if (priv->beaconorder < 15) + { + /* Set the superframe order */ + + if(req->superframeorder > 15) + { + ret = -EINVAL; + goto errout; + } + + priv->superframeorder = req->superframeorder; + } + + if (req->pancoord) + { + priv->devmode = IEEE802154_DEVMODE_PANCOORD; + } + else + { + priv->devmode = IEEE802154_DEVMODE_COORD; + } + + /* If the BeaconOrder parameter is less than 15, the MLME sets macBattLifeExt to + * the value of the BatteryLifeExtension parameter. If the BeaconOrder parameter + * equals 15, the value of the BatteryLifeExtension parameter is ignored. + * [1] pg. 106 + */ + + if (priv->beaconorder < 15) + { + priv->battlifeext = req->battlifeext; + + /* TODO: Finish starting beacon enabled network */ + return -ENOTTY; + } + + mac802154_givesem(&priv->exclsem); + + return OK; + +errout: + mac802154_givesem(&priv->exclsem); + return ret; +} \ No newline at end of file diff --git a/wireless/ieee802154/mac802154_sync.c b/wireless/ieee802154/mac802154_sync.c new file mode 100644 index 0000000000..fed5e452de --- /dev/null +++ b/wireless/ieee802154/mac802154_sync.c @@ -0,0 +1,78 @@ +/**************************************************************************** + * wireless/ieee802154/mac802154_sync.c + * + * Copyright (C) 2016 Sebastien Lorquet. All rights reserved. + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2017 Verge Inc. All rights reserved. + * + * Author: Sebastien Lorquet + * Author: Gregory Nutt + * Author: Anthony Merlino + * + * 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 "mac802154.h" + +#include + +/**************************************************************************** + * Public MAC Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mac802154_req_sync + * + * 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 mac802154_maccb_s->int_commstatus callback. TOCHECK. + * + ****************************************************************************/ + +int mac802154_req_sync(MACHANDLE mac, FAR struct ieee802154_sync_req_s *req) +{ + FAR struct ieee802154_privmac_s *priv = + (FAR struct ieee802154_privmac_s *)mac; + return -ENOTTY; +} +