From 9ad3b375e59c673749d70dfc7cecc59802c9e4c7 Mon Sep 17 00:00:00 2001 From: Anthony Merlino Date: Tue, 18 Apr 2017 15:34:13 -0400 Subject: [PATCH] wireless/ieee802154: Lots of small fixes to eliminate build issues. Generally cleans things up and fixes lots of small issues preventing a successful build. Does not completely build, but there are significantly less errors --- drivers/wireless/ieee802154/mrf24j40.c | 345 +++++++++++++----- .../wireless/ieee802154/ieee802154_mac.h | 27 +- .../wireless/ieee802154/ieee802154_radio.h | 12 +- wireless/ieee802154/mac802154.c | 129 ++++--- wireless/ieee802154/mac802154_device.c | 138 ++++--- 5 files changed, 418 insertions(+), 233 deletions(-) diff --git a/drivers/wireless/ieee802154/mrf24j40.c b/drivers/wireless/ieee802154/mrf24j40.c index 2cb3300e5a..655871eb94 100644 --- a/drivers/wireless/ieee802154/mrf24j40.c +++ b/drivers/wireless/ieee802154/mrf24j40.c @@ -94,10 +94,19 @@ #define MRF24J40_PA_ED 2 #define MRF24J40_PA_SLEEP 3 +#define MRF24J40_GTS_SLOTS 2 + /**************************************************************************** * Private Types ****************************************************************************/ +struct mrf24j40_txdesc_s +{ + struct ieee802154_txdesc_s pub; + + uint8_t busy : 1; /* Is this txdesc being used */ +}; + /* A MRF24J40 device instance */ struct mrf24j40_radio_s @@ -106,36 +115,33 @@ struct mrf24j40_radio_s /* Reference to the bound upper layer via the phyif interface */ - FAR const struct ieee802154_phyif_s *phyif; + FAR struct ieee802154_phyif_s *phyif; - FAR struct spi_dev_s *spi; /* Saved SPI interface instance */ - struct work_s irqwork; /* Interrupt continuation work queue support */ - FAR const struct mrf24j40_lower_s *lower; /* Low-level MCU-specific support */ - sem_t excl_sem; /* Exclusive access to this struct */ + /* Low-level MCU-specific support */ - uint16_t panid; /* PAN identifier, FFFF = not set */ - uint16_t saddr; /* short address, FFFF = not set */ - uint8_t eaddr[8]; /* extended address, FFFFFFFFFFFFFFFF = not set */ - uint8_t channel; /* 11 to 26 for the 2.4 GHz band */ - uint8_t devmode; /* device mode: device, coord, pancoord */ - uint8_t paenabled; /* enable usage of PA */ - uint8_t rxmode; /* Reception mode: Main, no CRC, promiscuous */ - int32_t txpower; /* TX power in mBm = dBm/100 */ - struct ieee802154_cca_s cca; /* Clear channel assessement method */ + 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 */ + + uint16_t panid; /* PAN identifier, FFFF = not set */ + uint16_t saddr; /* short address, FFFF = not set */ + uint8_t eaddr[8]; /* extended address, FFFFFFFFFFFFFFFF = not set */ + uint8_t channel; /* 11 to 26 for the 2.4 GHz band */ + uint8_t devmode; /* device mode: device, coord, pancoord */ + uint8_t paenabled; /* enable usage of PA */ + uint8_t rxmode; /* Reception mode: Main, no CRC, promiscuous */ + int32_t txpower; /* TX power in mBm = dBm/100 */ + struct ieee802154_cca_s cca; /* Clear channel assessement method */ /* Buffer Allocations */ struct mrf24j40_txdesc_s csma_desc; - struct mrf24j40_txdesc_s gts_desc[2]; + struct mrf24j40_txdesc_s gts_desc[MRF24J40_GTS_SLOTS]; - uint8_t tx_buf[CONFIG_IEEE802154_MTU]; -}; - -struct mrf24j40_txdesc_s -{ - struct ieee802154_txdesc_s ieee_desc; - - uint8_t busy : 1; /* Is this txdesc being used */ + uint8_t tx_buf[IEEE802154_MAX_PHY_PACKET_SIZE]; }; /**************************************************************************** @@ -161,41 +167,49 @@ static void mrf24j40_irqwork_tx(FAR struct mrf24j40_radio_s *dev); static void mrf24j40_irqworker(FAR void *arg); static int mrf24j40_interrupt(int irq, FAR void *context, 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, + uint8_t *buf, uint16_t buf_len); +static int mrf24j40_gts_setup(FAR struct mrf24j40_radio_s *dev, uint8_t gts, + uint8_t *buf, uint16_t buf_len); + /* IOCTL helpers */ -static int mrf24j40_setchannel(FAR struct ieee802154_radio_s *radio, +static int mrf24j40_setchannel(FAR struct mrf24j40_radio_s *radio, uint8_t chan); -static int mrf24j40_getchannel(FAR struct ieee802154_radio_s *radio, +static int mrf24j40_getchannel(FAR struct mrf24j40_radio_s *radio, FAR uint8_t *chan); -static int mrf24j40_setpanid(FAR struct ieee802154_radio_s *radio, +static int mrf24j40_setpanid(FAR struct mrf24j40_radio_s *radio, uint16_t panid); -static int mrf24j40_getpanid(FAR struct ieee802154_radio_s *radio, +static int mrf24j40_getpanid(FAR struct mrf24j40_radio_s *radio, FAR uint16_t *panid); -static int mrf24j40_setsaddr(FAR struct ieee802154_radio_s *radio, +static int mrf24j40_setsaddr(FAR struct mrf24j40_radio_s *radio, uint16_t saddr); -static int mrf24j40_getsaddr(FAR struct ieee802154_radio_s *radio, +static int mrf24j40_getsaddr(FAR struct mrf24j40_radio_s *radio, FAR uint16_t *saddr); -static int mrf24j40_seteaddr(FAR struct ieee802154_radio_s *radio, +static int mrf24j40_seteaddr(FAR struct mrf24j40_radio_s *radio, FAR uint8_t *eaddr); -static int mrf24j40_geteaddr(FAR struct ieee802154_radio_s *radio, +static int mrf24j40_geteaddr(FAR struct mrf24j40_radio_s *radio, FAR uint8_t *eaddr); -static int mrf24j40_setpromisc(FAR struct ieee802154_radio_s *radio, +static int mrf24j40_setpromisc(FAR struct mrf24j40_radio_s *radio, bool promisc); -static int mrf24j40_getpromisc(FAR struct ieee802154_radio_s *radio, +static int mrf24j40_getpromisc(FAR struct mrf24j40_radio_s *radio, FAR bool *promisc); -static int mrf24j40_setdevmode(FAR struct ieee802154_radio_s *radio, +static int mrf24j40_setdevmode(FAR struct mrf24j40_radio_s *radio, uint8_t mode); -static int mrf24j40_getdevmode(FAR struct ieee802154_radio_s *radio, +static int mrf24j40_getdevmode(FAR struct mrf24j40_radio_s *radio, FAR uint8_t *mode); -static int mrf24j40_settxpower(FAR struct ieee802154_radio_s *radio, +static int mrf24j40_settxpower(FAR struct mrf24j40_radio_s *radio, int32_t txpwr); -static int mrf24j40_gettxpower(FAR struct ieee802154_radio_s *radio, +static int mrf24j40_gettxpower(FAR struct mrf24j40_radio_s *radio, FAR int32_t *txpwr); -static int mrf24j40_setcca(FAR struct ieee802154_radio_s *radio, +static int mrf24j40_setcca(FAR struct mrf24j40_radio_s *radio, FAR struct ieee802154_cca_s *cca); -static int mrf24j40_getcca(FAR struct ieee802154_radio_s *radio, +static int mrf24j40_getcca(FAR struct mrf24j40_radio_s *radio, FAR struct ieee802154_cca_s *cca); -static int mrf24j40_energydetect(FAR struct ieee802154_radio_s *radio, +static int mrf24j40_energydetect(FAR struct mrf24j40_radio_s *radio, FAR uint8_t *energy); /* Driver operations */ @@ -207,7 +221,9 @@ static int mrf24j40_ioctl(FAR struct ieee802154_radio_s *radio, int cmd, static int mrf24j40_rxenable(FAR struct ieee802154_radio_s *radio, bool state, FAR struct ieee802154_packet_s *packet); static int mrf24j40_transmit(FAR struct ieee802154_radio_s *radio, - FAR struct ieee802154_packet_s *packet); + uint8_t *buf, uint16_t buf_len); +static int mrf24j40_txnotify_csma(FAR struct ieee802154_radio_s *radio); +static int mrf24j40_txnotify_gts(FAR struct ieee802154_radio_s *radio); /**************************************************************************** * Private Data @@ -233,8 +249,8 @@ static const struct ieee802154_radioops_s mrf24j40_devops = * Private Functions ****************************************************************************/ -static void mrf24j40_bind(FAR struct ieee802154_radio_s *radio, - FAR struct ieee802154_phyif_s *phyif) +static int mrf24j40_bind(FAR struct ieee802154_radio_s *radio, + FAR struct ieee802154_phyif_s *phyif) { FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; @@ -243,6 +259,43 @@ static void mrf24j40_bind(FAR struct ieee802154_radio_s *radio, return OK; } +/**************************************************************************** + * Function: mrf24j40_txnotify_csma + * + * 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. + * + * Parameters: + * radio - Reference to the radio driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static int mrf24j40_txnotify_csma(FAR struct ieee802154_radio_s *radio) +{ + 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)) + { + /* Schedule to serialize the poll on the worker thread. */ + + work_queue(HPWORK, &dev->pollwork, mrf24j40_dopoll_csma, dev, 0); + } + + return OK; +} + /**************************************************************************** * Function: mrf24j40_dopoll_csma * @@ -250,8 +303,10 @@ static void mrf24j40_bind(FAR struct ieee802154_radio_s *radio, * This function is called in order to preform an out-of-sequence TX poll. * This is done: * - * 1. After completion of a CSMA transmission - * 2. When the upper layer calls txnotify_csma + * 1. After completion of a transmission (mrf24j40_txdone_csma), + * 2. When new TX data is available (mrf24j40_txnotify_csma), and + * 3. After a TX timeout to restart the sending process + * (mrf24j40_txtimeout_csma). * * Parameters: * radio - Reference to the radio driver state structure @@ -263,40 +318,41 @@ static void mrf24j40_bind(FAR struct ieee802154_radio_s *radio, * ****************************************************************************/ -static void mrf24j40_dopoll_csma(FAR struct ieee802154_radio_s *radio) +static void mrf24j40_dopoll_csma(FAR void *arg) { - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)arg; + int ret = 0; /* Need to get exlusive access to the device so that we can use the copy * buffer. */ - while (sem_wait(&dev->exclsem) < 0) { } + while (sem_wait(&dev->exclsem) != 0) { } /* If this a CSMA transaction and we have room in the CSMA fifo */ - if (!dev->csma_txdesc.busy) + if (!dev->csma_desc.busy) { /* need to somehow allow for a handle to be passed */ - ret = dev->phyif->poll_csma(dev->phyif, &radio->csma_txdesc, - &dev->tx_buf[0]); + ret = dev->phyif->ops->poll_csma(dev->phyif, + &dev->csma_desc.pub, + &dev->tx_buf[0]); if (ret > 0) { /* Now the txdesc is in use */ - dev->cmsa_desc.busy = 1; + dev->csma_desc.busy = 1; /* Setup the transaction on the device in the CSMA FIFO */ - mrf24j40_csma_setup(radio, &dev->tx_buf[0], - dev->gts_desc[i].psdu_length); + mrf24j40_csma_setup(dev, &dev->tx_buf[0], + dev->csma_desc.pub.psdu_length); } /* Setup the transmit on the device */ - break; } sem_post(&dev->exclsem); @@ -306,44 +362,95 @@ static void mrf24j40_dopoll_csma(FAR struct ieee802154_radio_s *radio) * Function: mrf24j40_txnotify_gts * * Description: - * Called from the upper layer, this function is to notify the device that - * the upper layer has a pending transaction for one of it's GTS'. This - * function checks to see if there is availability for the corresponding - * transaction type. If there is, the function will call to the MAC layer - * to get the transaction and then start the transmission + * 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. + * + * Parameters: + * radio - Reference to the radio driver state structure + * + * Returned Value: + * None + * + * Assumptions: * ****************************************************************************/ -static void mrf24j40_txnotify_gts(FAR struct ieee802154_radio_s *radio) +static int mrf24j40_txnotify_gts(FAR struct ieee802154_radio_s *radio) { 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)) + { + /* Schedule to serialize the poll on the worker thread. */ + + work_queue(HPWORK, &dev->pollwork, mrf24j40_dopoll_gts, dev, 0); + } + + return OK; +} + +/**************************************************************************** + * Function: mrf24j40_dopoll_gts + * + * Description: + * This function is called in order to preform an out-of-sequence TX poll. + * This is done: + * + * 1. After completion of a transmission (mrf24j40_txdone_gts), + * 2. When new TX data is available (mrf24j40_txnotify_gts), and + * 3. After a TX timeout to restart the sending process + * (mrf24j40_txtimeout_gts). + * + * Parameters: + * arg - Reference to the radio driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * + ****************************************************************************/ + +static void mrf24j40_dopoll_gts(FAR void *arg) +{ + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)arg; + int gts = 0; + int ret = 0; + /* Need to get exclusive access to the device so that we can use the copy * buffer. */ - while (sem_wait(dev->exclsem) < 0) { } + while (sem_wait(&dev->exclsem) != 0) { } - for (gts = 0; gts < MRF24J40_GTS_SLOTS, gts++) + for (gts = 0; gts < MRF24J40_GTS_SLOTS; gts++) { - if (!dev->gts_txdesc[i].busy) + if (!dev->gts_desc[gts].busy) { - ret = dev->phyif->poll_gts(dev->phyif, &radio->gts_txdesc[i], - &dev->tx_buf[0]); + ret = dev->phyif->ops->poll_gts(dev->phyif, &dev->gts_desc[gts].pub, + &dev->tx_buf[0]); if (ret > 0) { /* Now the txdesc is in use */ - dev->gts_txdesc[i].busy = 1; + dev->gts_desc[gts].busy = 1; /* Setup the transaction on the device in the open GTS FIFO */ - mrf24j40_gts_setup(radio, i, &dev->tx_buf[0], - dev->gts_desc[i].psdu_length); + mrf24j40_gts_setup(dev, gts, &dev->tx_buf[0], + dev->gts_desc[gts].pub.psdu_length); } } } + + sem_post(&dev->exclsem); } /**************************************************************************** @@ -409,11 +516,11 @@ static void mrf24j40_setreg(FAR struct spi_dev_s *spi, uint32_t addr, buf[len++] = val; - mrf24j40_lock(spi); + mrf24j40_spi_lock(spi); SPI_SELECT(spi, SPIDEV_IEEE802154, true); SPI_SNDBLOCK(spi, buf, len); SPI_SELECT(spi, SPIDEV_IEEE802154, false); - mrf24j40_unlock(spi); + mrf24j40_spi_unlock(spi); } /**************************************************************************** @@ -453,11 +560,11 @@ static uint8_t mrf24j40_getreg(FAR struct spi_dev_s *spi, uint32_t addr) buf[len++] = 0xFF; /* dummy */ - mrf24j40_lock (spi); + mrf24j40_spi_lock (spi); SPI_SELECT (spi, SPIDEV_IEEE802154, true); SPI_EXCHANGE (spi, buf, rx, len); SPI_SELECT (spi, SPIDEV_IEEE802154, false); - mrf24j40_unlock(spi); + mrf24j40_spi_unlock(spi); /* wlinfo("r[%04X]=%02X\n", addr, rx[len - 1]); */ return rx[len - 1]; @@ -644,10 +751,18 @@ static int mrf24j40_setchannel(FAR struct mrf24j40_radio_s *dev, uint8_t chan) return OK; } +/**************************************************************************** + * Name: mrf24j40_getchannel + * + * Description: + * Get the channel the device is operating on. + * + ****************************************************************************/ + static int mrf24j40_getchannel(FAR struct mrf24j40_radio_s *dev, FAR uint8_t *chan) { - chan = dev->channel; + *chan = dev->channel; return OK; } @@ -955,7 +1070,7 @@ static int mrf24j40_settxpower(FAR struct mrf24j40_radio_s *dev, * ****************************************************************************/ -static int mrf24j40_gettxpower(FAR struct mrf24j40_radio_s *radio, +static int mrf24j40_gettxpower(FAR struct mrf24j40_radio_s *dev, FAR int32_t *txpwr) { *txpwr = dev->txpower; @@ -1085,78 +1200,78 @@ static int mrf24j40_ioctl(FAR struct ieee802154_radio_s *radio, int cmd, unsigned long arg) { FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; - - FAR union ieee802154_radioarg_u *u; = - (FAR union ieee802154_radioarg_u *)((uintptr_t)arg) + FAR union ieee802154_radioarg_u *u = + (FAR union ieee802154_radioarg_u *)((uintptr_t)arg); + int ret; switch(cmd) { case PHY802154IOC_SET_CHAN: - ret = mrf24j40_setchannel(dev, u.channel); + ret = mrf24j40_setchannel(dev, u->channel); break; case PHY802154IOC_GET_CHAN: - ret = mrf24j40_getchannel(dev, &u.channel); + ret = mrf24j40_getchannel(dev, &u->channel); break; case PHY802154IOC_SET_PANID: - ret = mrf24j40_setpanid(dev, u.panid); + ret = mrf24j40_setpanid(dev, u->panid); break; case PHY802154IOC_GET_PANID: - ret = mrf24j40_getpanid(dev, &u.panid); + ret = mrf24j40_getpanid(dev, &u->panid); break; case PHY802154IOC_SET_SADDR: - ret = mrf24j40_setsaddr(dev, u.saddr); + ret = mrf24j40_setsaddr(dev, u->saddr); break; case PHY802154IOC_GET_SADDR: - ret = mrf24j40_getsaddr(dev, &u.saddr); + ret = mrf24j40_getsaddr(dev, &u->saddr); break; case PHY802154IOC_SET_EADDR: - ret = mrf24j40_seteaddr(dev, u.eaddr); + ret = mrf24j40_seteaddr(dev, u->eaddr); break; case PHY802154IOC_GET_EADDR: - ret = mrf24j40_geteaddr(dev, u.eaddr); + ret = mrf24j40_geteaddr(dev, u->eaddr); break; case PHY802154IOC_SET_PROMISC: - ret = mrf24j40_setpromisc(dev, u.promisc); + ret = mrf24j40_setpromisc(dev, u->promisc); break; case PHY802154IOC_GET_PROMISC: - ret = mrf24j40_getpromisc(dev, &u.promisc); + ret = mrf24j40_getpromisc(dev, &u->promisc); break; case PHY802154IOC_SET_DEVMODE: - ret = mrf24j40_setdevmode(dev, u.devmode); + ret = mrf24j40_setdevmode(dev, u->devmode); break; case PHY802154IOC_GET_DEVMODE: - ret = mrf24j40_getdevmode(dev, &u.devmode); + ret = mrf24j40_getdevmode(dev, &u->devmode); break; case PHY802154IOC_SET_TXPWR: - ret = mrf24j40_settxpower(dev, u.txpwr); + ret = mrf24j40_settxpower(dev, u->txpwr); break; case PHY802154IOC_GET_TXPWR: - ret = mrf24j40_gettxpower(dev, &u.txpwr); + ret = mrf24j40_gettxpower(dev, &u->txpwr); break; case PHY802154IOC_SET_CCA: - ret = mrf24j40_setcca(dev, &u.cca); + ret = mrf24j40_setcca(dev, &u->cca); break; case PHY802154IOC_GET_CCA: - ret = mrf24j40_getcca(dev, &u.cca); + ret = mrf24j40_getcca(dev, &u->cca); break; case PHY802154IOC_ENERGYDETECT: - ret = mrf24j40_energydetect(dev, &u.energy); + ret = mrf24j40_energydetect(dev, &u->energy); break; case 1000: @@ -1169,6 +1284,8 @@ static int mrf24j40_ioctl(FAR struct ieee802154_radio_s *radio, int cmd, default: return -ENOTTY; } + + return ret; } /**************************************************************************** @@ -1282,13 +1399,13 @@ static int mrf24j40_transmit(FAR struct ieee802154_radio_s *radio, /* Frame length */ - mrf24j40_setreg(dev->spi, addr++, buflen); + mrf24j40_setreg(dev->spi, addr++, buf_len); /* Frame data */ - for (ret = 0; ret < buflen; ret++) /* this sets the correct val for ret */ + for (ret = 0; ret < buf_len; ret++) /* this sets the correct val for ret */ { - mrf24j40_setreg(dev->spi, addr++, packet->data[ret]); + mrf24j40_setreg(dev->spi, addr++, buf[ret]); } /* If the frame control field contains @@ -1309,6 +1426,34 @@ static int mrf24j40_transmit(FAR struct ieee802154_radio_s *radio, return ret; } +/**************************************************************************** + * Name: mrf24j40_csma_setup + * + * Description: + * Setup a CSMA transaction in the normal TX FIFO + * + ****************************************************************************/ + +static int mrf24j40_csma_setup(FAR struct mrf24j40_radio_s *dev, + uint8_t *buf, uint16_t buf_len) +{ + return -ENOTTY; +} + +/**************************************************************************** + * Name: mrf24j40_gts_setup + * + * Description: + * Setup a GTS transaction in one of the GTS FIFOs + * + ****************************************************************************/ + +static int mrf24j40_gts_setup(FAR struct mrf24j40_radio_s *dev, uint8_t fifo, + uint8_t *buf, uint16_t buf_len) +{ + return -ENOTTY; +} + /**************************************************************************** * Name: mrf24j40_irqwork_tx * @@ -1328,9 +1473,11 @@ static void mrf24j40_irqwork_tx(FAR struct mrf24j40_radio_s *dev) /* 1 means it failed, we want 1 to mean it worked. */ + /* dev->radio.txok = (reg & MRF24J40_TXSTAT_TXNSTAT) != MRF24J40_TXSTAT_TXNSTAT; dev->radio.txretries = (reg & MRF24J40_TXSTAT_X_MASK) >> MRF24J40_TXSTAT_X_SHIFT; dev->radio.txbusy = (reg & MRF24J40_TXSTAT_CCAFAIL) == MRF24J40_TXSTAT_CCAFAIL; + */ //wlinfo("TXSTAT%02X!\n", txstat); #warning TODO report errors @@ -1344,7 +1491,7 @@ static void mrf24j40_irqwork_tx(FAR struct mrf24j40_radio_s *dev) /* Wake up the thread that triggered the transmission */ - sem_post(&dev->radio.txsem); + /* sem_post(&dev->radio.txsem); */ } diff --git a/include/nuttx/wireless/ieee802154/ieee802154_mac.h b/include/nuttx/wireless/ieee802154/ieee802154_mac.h index 76880ebf29..800436de78 100644 --- a/include/nuttx/wireless/ieee802154/ieee802154_mac.h +++ b/include/nuttx/wireless/ieee802154/ieee802154_mac.h @@ -85,7 +85,7 @@ #define MAC802154IOC_MCPS_REGISTER _MAC802154IOC(0x0001) -#define MAC802154IOC_MLME_REGISER _MAC802154IOC(0x0002); +#define MAC802154IOC_MLME_REGISTER _MAC802154IOC(0x0002) #define MAC802154IOC_MLME_ASSOC_REQUEST _MAC802154IOC(0x0003) #define MAC802154IOC_MLME_ASSOC_RESPONSE _MAC802154IOC(0x0004) #define MAC802154IOC_MLME_DISASSOC_REQUEST _MAC802154IOC(0x0005) @@ -103,8 +103,6 @@ #define MAC802154IOC_MLME_SOUNDING_REQUEST _MAC802154IOC(0x0011) #define MAC802154IOC_MLME_CALIBRATE_REQUEST _MAC802154IOC(0x0012) - - /* IEEE 802.15.4 MAC Interface **********************************************/ /* Frame Type */ @@ -351,12 +349,9 @@ struct ieee802154_addr_s enum ieee802154_addr_mode_e mode; - uint16_t panid; /* PAN identifier, can be IEEE802154_PAN_UNSPEC */ - union - { - uint16_t saddr; /* short address */ - uint8_t eaddr[8]; /* extended address */ - } u; + uint16_t panid; /* PAN identifier, can be IEEE802154_PAN_UNSPEC */ + uint16_t saddr; /* short address */ + uint8_t eaddr[8]; /* extended address */ }; #define IEEE802154_ADDRSTRLEN 22 /* (2*2+1+8*2, PPPP/EEEEEEEEEEEEEEEE) */ @@ -397,19 +392,6 @@ enum ieee802154_ranging_e IEEE802154_PHY_HEADER_ONLY }; -struct ieee802154_frame_s -{ - struct ieee802154_framecontrol_s frame_control; - uint8_t seq_num; - struct ieee802154_addr_s dest_addr; - struct ieee802154_addr_s src_addr; -#ifdef CONFIG_IEEE802154_SECURITY - struct ieee802154_auxsec_s aux_sec_hdr; -#endif - void *payload; - uint16_t fcs; -}; - struct ieee802154_data_req_s { enum ieee802154_addr_mode_e src_addr_mode; /* Source Address Mode */ @@ -464,7 +446,6 @@ struct ieee802154_data_req_s uint8_t msdu[1]; }; - #define SIZEOF_IEEE802154_DATA_REQ_S(n) \ (sizeof(struct ieee802154_data_req_s) + (n) - 1) diff --git a/include/nuttx/wireless/ieee802154/ieee802154_radio.h b/include/nuttx/wireless/ieee802154/ieee802154_radio.h index d48b0d4e12..638760f356 100644 --- a/include/nuttx/wireless/ieee802154/ieee802154_radio.h +++ b/include/nuttx/wireless/ieee802154/ieee802154_radio.h @@ -190,14 +190,14 @@ struct ieee802154_radio_s; /* Forward reference */ struct ieee802154_radioops_s { - CODE int (*bind) (FAR struct ieee802154_radio_s *dev, - FAR const struct ieee802154_phyif_s *phyif); - CODE int (*ioctl)(FAR struct ieee802154_radio_s *ieee, int cmd, + CODE int (*bind) (FAR struct ieee802154_radio_s *radio, + FAR struct ieee802154_phyif_s *phyif); + CODE int (*ioctl)(FAR struct ieee802154_radio_s *radio, int cmd, unsigned long arg); - CODE int (*rxenable)(FAR struct ieee802154_radio_s *dev, bool state, + CODE int (*rxenable)(FAR struct ieee802154_radio_s *radio, bool state, FAR struct ieee802154_packet_s *packet); - CODE int (*txnotify_csma)(FAR struct ieee802154_radio_s *dev); - CODE int (*txnotify_gts)(FAR struct ieee802154_radio_s *dev); + CODE int (*txnotify_csma)(FAR struct ieee802154_radio_s *radio); + CODE int (*txnotify_gts)(FAR struct ieee802154_radio_s *radio); }; struct ieee802154_radio_s diff --git a/wireless/ieee802154/mac802154.c b/wireless/ieee802154/mac802154.c index ee057dcec1..671e67b6e2 100644 --- a/wireless/ieee802154/mac802154.c +++ b/wireless/ieee802154/mac802154.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -96,7 +97,7 @@ struct ieee802154_privmac_s FAR const struct ieee802154_maccb_s *cb; /* Contained MAC callbacks */ FAR struct ieee802154_phyif_s phyif; /* Interface to bind to radio */ - sem_t excl_sem; /* Support exclusive access */ + sem_t exclsem; /* Support exclusive access */ /* 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 @@ -207,14 +208,14 @@ struct ieee802154_privmac_s */ uint32_t sync_symb_offset : 12; - } + }; struct { uint32_t beacon_tx_time : 24; /* Time of last beacon transmit */ uint32_t min_be : 4; /* Min value of backoff exponent (BE) */ uint32_t max_be : 4; /* Max value of backoff exponent (BE) */ - } + }; struct { @@ -223,11 +224,33 @@ struct ieee802154_privmac_s uint32_t tx_ctrl_pause_dur : 1; /* Duration after tx before another tx is * permitted. 0=2000, 1= 10000 */ uint32_t timestamp_support : 1; /* Does MAC layer supports timestamping */ - } + uint32_t is_coord : 1; /* Is this device acting as coordinator */ + }; /* TODO: Add Security-related MAC PIB attributes */ }; +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static inline int mac802154_takesem(sem_t *sem); +#define mac802154_givesem(s) sem_post(s); + +/* Internal Functions */ + +static int mac802154_defaultmib(FAR struct ieee802154_privmac_s *priv); +static int mac802154_applymib(FAR struct ieee802154_privmac_s *priv); + +/* IEEE 802.15.4 PHY Interface OPs */ + +static int mac802154_poll_csma(FAR struct ieee802154_phyif_s *phyif, + FAR struct ieee802154_txdesc_s *tx_desc, + uint8_t *buf); + +static int mac802154_poll_gts(FAR struct ieee802154_phyif_s *phyif, + FAR struct ieee802154_txdesc_s *tx_desc, + uint8_t *buf); /**************************************************************************** * Private Data @@ -350,7 +373,7 @@ MACHANDLE mac802154_create(FAR struct ieee802154_radio_s *radiodev) /* Bind our PHY interface to the radio */ - radiodev->ops->bind(radiodev, mac->phyif); + radiodev->ops->bind(radiodev, &mac->phyif); return (MACHANDLE)mac; } @@ -444,7 +467,7 @@ int mac802154_req_data(MACHANDLE mac, FAR struct ieee802154_data_req_s *req) { FAR struct ieee802154_privmac_s *priv = (FAR struct ieee802154_privmac_s *)mac; - FAR struct mac802154_trans_s *trans; + FAR struct mac802154_trans_s trans; struct mac802154_unsec_mhr_s mhr; int ret; @@ -462,11 +485,12 @@ int mac802154_req_data(MACHANDLE mac, FAR struct ieee802154_data_req_s *req) /* Ensure we start with a clear frame control field */ - mhr.frame_control = 0; + mhr.u.frame_control = 0; /* Set the frame type to Data */ - mhr.frame_control |= IEEE802154_FRAME_DATA << IEEE802154_FRAMECTRL_SHIFT_FTYPE; + mhr.u.frame_control |= 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. @@ -474,7 +498,7 @@ int mac802154_req_data(MACHANDLE mac, FAR struct ieee802154_data_req_s *req) if (req->msdu_length > IEEE802154_MAX_SAFE_MAC_PAYLOAD_SIZE) { - mhr.frame_ctrl |= IEEE802154_FRAMECTRL_VERSION; + mhr.u.frame_control |= IEEE802154_FRAMECTRL_VERSION; } /* If the TXOptions parameter specifies that an acknowledged transmission is @@ -482,7 +506,8 @@ int mac802154_req_data(MACHANDLE mac, FAR struct ieee802154_data_req_s *req) * 5.1.6.4 [1] pg. 118. */ - mhr.frame_ctrl |= (req->msdu_flags.ack_tx << IEEE802154_FRAMECTRL_SHIFT_ACKREQ); + mhr.u.frame_control |= (req->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 . @@ -490,28 +515,29 @@ int mac802154_req_data(MACHANDLE mac, FAR struct ieee802154_data_req_s *req) if (req->dest_addr.mode != IEEE802154_ADDRMODE_NONE) { - memcpy(&mhr.data[mhr.length], req->dest_addr.panid, 2); + memcpy(&mhr.u.data[mhr.length], &req->dest_addr.panid, 2); mhr.length += 2; if (req->dest_addr.mode == IEEE802154_ADDRMODE_SHORT) { - memcpy(&mhr.data[mhr.length], req->dest_addr.saddr, 2); + memcpy(&mhr.u.data[mhr.length], &req->dest_addr.saddr, 2); mhr.length += 2; } else if (req->dest_addr.mode == IEEE802154_ADDRMODE_EXTENDED) { - memcpy(&mhr.data[mhr.length], req->dest_addr.eaddr, 8); + memcpy(&mhr.u.data[mhr.length], &req->dest_addr.eaddr, 8); mhr.length += 8; } } /* Set the destination addr mode inside the frame contorl field */ - mhr.frame_ctrl |= (req->dest_addr.mode << IEEE802154_FRAMECTRL_SHIFT_DADDR); + mhr.u.frame_control |= (req->dest_addr.mode << + IEEE802154_FRAMECTRL_SHIFT_DADDR); /* From this point on, we need exclusive access to the privmac struct */ - ret = mac802154dev_takesem(&dev->md_exclsem); + ret = mac802154_takesem(&priv->exclsem); if (ret < 0) { wlerr("ERROR: mac802154_takesem failed: %d\n", ret); @@ -533,7 +559,7 @@ int mac802154_req_data(MACHANDLE mac, FAR struct ieee802154_data_req_s *req) if (req->dest_addr.panid == priv->addr.panid) { - mhr.frame_control |= IEEE802154_FRAMECTRL_PANIDCOMP; + mhr.u.frame_control |= IEEE802154_FRAMECTRL_PANIDCOMP; } } @@ -543,35 +569,36 @@ int mac802154_req_data(MACHANDLE mac, FAR struct ieee802154_data_req_s *req) * is off, we need to include the Source PAN ID. */ - if (req->dest_addr.mode == IEEE802154_ADDRMODE_NONE || - (mhr.frame_control & IEEE802154_FRAMECTRL_PANIDCOMP) + if ((req->dest_addr.mode == IEEE802154_ADDRMODE_NONE) || + (mhr.u.frame_control & IEEE802154_FRAMECTRL_PANIDCOMP)) { - memcpy(&mhr.data[mhr.length], priv->addr.panid, 2); + memcpy(&mhr.u.data[mhr.length], &priv->addr.panid, 2); mhr.length += 2; } if (req->src_addr_mode == IEEE802154_ADDRMODE_SHORT) { - memcpy(&mhr.data[mhr.length], priv->addr.saddr, 2); + memcpy(&mhr.u.data[mhr.length], &priv->addr.saddr, 2); mhr.length += 2; } else if (req->src_addr_mode == IEEE802154_ADDRMODE_EXTENDED) { - memcpy(&mhr.data[mhr.length], priv->addr.eaddr, 8); + memcpy(&mhr.u.data[mhr.length], &priv->addr.eaddr, 8); mhr.length += 8; } } /* Set the source addr mode inside the frame control field */ - mhr.frame_ctrl |= (req->src_addr_mode << IEEE802154_FRAMECTRL_SHIFT_SADDR); + mhr.u.frame_control |= (req->src_addr_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. */ - mhr.data[mhr.length++] = priv.dsn++; + mhr.u.data[mhr.length++] = priv->dsn++; /* Now that we know which fields are included in the header, we can make * sure we actually have enough room in the PSDU. @@ -583,13 +610,13 @@ int mac802154_req_data(MACHANDLE mac, FAR struct ieee802154_data_req_s *req) return -E2BIG; } - trans->mhr_buf = &mhr.data[0]; - trans->mhr_len = mhr.length; + trans.mhr_buf = &mhr.u.data[0]; + trans.mhr_len = mhr.length; - trans->d_buf = &req->msdu[0]; - trans->d_len = req->msdu_length; + trans.d_buf = &req->msdu[0]; + trans.d_len = req->msdu_length; - trans->msdu_handle = req->msdu_handle; + trans.msdu_handle = req->msdu_handle; /* If the TxOptions parameter specifies that a GTS transmission is required, * the MAC sublayer will determine whether it has a valid GTS as described @@ -635,14 +662,14 @@ int mac802154_req_data(MACHANDLE mac, FAR struct ieee802154_data_req_s *req) { /* Link the transaction into the indirect_trans list */ - priv->indirect_tail->flink = trans; - priv->indirect_tail = trans; + priv->indirect_tail->flink = &trans; + priv->indirect_tail = &trans; } else { /* Override the setting since it wasn't valid */ - req->msgu_flags.indirect_tx = 0; + req->msdu_flags.indirect_tx = 0; } } @@ -652,40 +679,50 @@ int mac802154_req_data(MACHANDLE mac, FAR struct ieee802154_data_req_s *req) { /* Link the transaction into the CSMA transaction list */ - priv->csma_tail->flink = trans; - priv->csma_tail = trans; + priv->csma_tail->flink = &trans; + priv->csma_tail = &trans; + + /* 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->tx_notify(priv->radio); + priv->radio->ops->txnotify_csma(priv->radio); - sem_wait(&trans->sem); + sem_wait(&trans.sem); } } return OK; } - /* Called from interrupt level or worker thread with interrupts disabled */ -static uint16_t mac802154_poll_csma(FAR struct ieee802154_phyif_s *phyif, +static int mac802154_poll_csma(FAR struct ieee802154_phyif_s *phyif, FAR struct ieee802154_txdesc_s *tx_desc, uint8_t *buf) { FAR struct ieee802154_privmac_s *priv = (FAR struct ieee802154_privmac_s *)&phyif->priv; - FAR struct mac802154_trans_s *trans; + int ret = 0; + + DEBUGASSERT(priv != 0); + + /* 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 */ - if (mac->csma_head) + if (priv->csma_head) { /* Pop a CSMA transaction off the list */ - trans = mac->csma_head; - mac->csma_head = mac->csma_head.flink; + trans = priv->csma_head; + priv->csma_head = priv->csma_head->flink; /* Setup the transmit descriptor */ @@ -703,15 +740,17 @@ static uint16_t mac802154_poll_csma(FAR struct ieee802154_phyif_s *phyif, * returns. */ - sem_post(trans->sem); + sem_post(&trans->sem); - return txdesc->psdu_length; + ret = tx_desc->psdu_length; } - return 0; + mac802154_givesem(&priv->exclsem); + + return ret; } -static uint16_t mac802154_poll_gts(FAR struct ieee802154_phyif_s *phyif, +static int mac802154_poll_gts(FAR struct ieee802154_phyif_s *phyif, FAR struct ieee802154_txdesc_s *tx_desc, uint8_t *buf) { diff --git a/wireless/ieee802154/mac802154_device.c b/wireless/ieee802154/mac802154_device.c index b35049e9ac..8e9250a218 100644 --- a/wireless/ieee802154/mac802154_device.c +++ b/wireless/ieee802154/mac802154_device.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -66,31 +67,6 @@ * Private Types ****************************************************************************/ -struct mac802154_devwrapper_s -{ - MACHANDLE md_mac; /* Saved binding to the mac layer */ - sem_t md_exclsem; /* Exclusive device access */ - - /* The following is a singly linked list of open references to the - * MAC device. - */ - - FAR struct mac802154_open_s *md_open; - FAR struct mac802154dev_dwait_s *md_dwait; - -#ifndef CONFIG_DISABLE_SIGNALS - /* MCPS Service notification information */ - - struct mac802154dev_notify_s md_mcps_notify; - pid_t md_mcps_pid; - - /* MLME Service notification information */ - - struct mac802154dev_notify_s md_mlme_notify; - pid_t md_mlme_pid; -#endif -}; - struct mac802154dev_notify_s { uint8_t mn_signo; /* Signal number to use in the notification */ @@ -120,6 +96,31 @@ struct mac802154dev_dwait_s FAR struct mac802154dev_dwait_s *mw_flink; }; +struct mac802154_devwrapper_s +{ + MACHANDLE md_mac; /* Saved binding to the mac layer */ + sem_t md_exclsem; /* Exclusive device access */ + + /* The following is a singly linked list of open references to the + * MAC device. + */ + + FAR struct mac802154dev_open_s *md_open; + FAR struct mac802154dev_dwait_s *md_dwait; + +#ifndef CONFIG_DISABLE_SIGNALS + /* MCPS Service notification information */ + + struct mac802154dev_notify_s md_mcps_notify; + pid_t md_mcps_pid; + + /* MLME Service notification information */ + + struct mac802154dev_notify_s md_mlme_notify; + pid_t md_mlme_pid; +#endif +}; + /**************************************************************************** * Private Function Prototypes ****************************************************************************/ @@ -358,7 +359,8 @@ static ssize_t mac802154dev_read(FAR struct file *filep, FAR char *buffer, * packet. */ - if (len < sizeof(struct ieee802154_frame_s)) + if ((len >= SIZEOF_IEEE802154_DATA_REQ_S(1)) && + (len <= SIZEOF_IEEE802154_DATA_REQ_S(IEEE802154_MAX_MAC_PAYLOAD_SIZE))) { wlerr("ERROR: buffer too small: %lu\n", (unsigned long)len); return -EINVAL; @@ -394,7 +396,6 @@ static ssize_t mac802154dev_write(FAR struct file *filep, FAR struct inode *inode; FAR struct mac802154_devwrapper_s *dev; FAR struct ieee802154_data_req_s *req; - FAR struct ieee802154_frame_s *frame; struct mac802154dev_dwait_s dwait; int ret; @@ -404,64 +405,82 @@ static ssize_t mac802154dev_write(FAR struct file *filep, dev = (FAR struct mac802154_devwrapper_s *)inode->i_private; /* Check to make sure that the buffer is big enough to hold at least one - * packet. - */ + * packet. */ - if (len < sizeof(struct ieee802154_frame_s)) + if ((len >= SIZEOF_IEEE802154_DATA_REQ_S(1)) && + (len <= SIZEOF_IEEE802154_DATA_REQ_S(IEEE802154_MAX_MAC_PAYLOAD_SIZE))) { - wlerr("ERROR: buffer too small: %lu\n", (unsigned long)len); + wlerr("ERROR: buffer isn't an ieee802154_data_req_s: %lu\n", + (unsigned long)len); + return -EINVAL; } DEBUGASSERT(buffer != NULL); - frame = (FAR struct ieee802154_frame_s *)buffer; + req = (FAR struct ieee802154_data_req_s *)buffer; - /* Get exclusive access to the driver structure */ + /* If this is a blocking operation, we need to setup a wait struct so we + * can unblock when the packet transmission has finished. If this is a + * non-blocking write, we pass off the data and then move along. Technically + * we stil have to wait for the transaction to get put into the buffer, but we + * won't wait for the transaction to actually finish. */ - ret = mac802154dev_takesem(&dev->md_exclsem); - if (ret < 0) + if (!(filep->f_oflags & O_NONBLOCK)) { - wlerr("ERROR: mac802154dev_takesem failed: %d\n", ret); - return ret; - } + /* Get exclusive access to the driver structure */ - /* Setup the wait struct */ + ret = mac802154dev_takesem(&dev->md_exclsem); + if (ret < 0) + { + wlerr("ERROR: mac802154dev_takesem failed: %d\n", ret); + return ret; + } - dwait.mw_handle = req->msdu_handle; + /* Setup the wait struct */ - /* Link the wait struct */ + dwait.mw_handle = req->msdu_handle; - dwait.mw_flink = dev->md_dwait; - dev->md_dwait = &dwait; + /* Link the wait struct */ + dwait.mw_flink = dev->md_dwait; + dev->md_dwait = &dwait; + + mac802154dev_givesem(&dev->md_exclsem); + + } + /* Pass the request to the MAC layer */ ret = mac802154_req_data(dev->md_mac, req); - mac802154dev_givesem(&dev->md_exclsem); - if (ret < 0) { wlerr("ERROR: req_data failed %d\n", ret); return ret; } - /* Wait for the DATA.confirm callback to be called for our handle */ - if (sem_wait(dwait.mw_sem) < 0) + if (!(filep->f_oflags & O_NONBLOCK)) { - /* This should only happen if the wait was canceled by an signal */ + /* Wait for the DATA.confirm callback to be called for our handle */ - DEBUGASSERT(errno == EINTR); - return -EINTR; + if (sem_wait(&dwait.mw_sem) < 0) + { + /* This should only happen if the wait was canceled by an signal */ + + DEBUGASSERT(errno == EINTR); + return -EINTR; + } + + /* The unlinking of the wait struct happens inside the callback. This + * is more efficient since it will already have to find the struct in + * the list in order to perform the sem_post. + */ + + return dwait.mw_status; } - /* The unlinking of the wait struct happens inside the callback. This - * is more efficient since it will already have to find the struct in - * the list in order to perform the sem_post. - */ - - return dwait.status; + return OK; } /**************************************************************************** @@ -477,7 +496,6 @@ static int mac802154dev_ioctl(FAR struct file *filep, int cmd, { FAR struct inode *inode; FAR struct mac802154_devwrapper_s *dev; - MACHANDLE mac; int ret; DEBUGASSERT(filep != NULL && filep->f_priv != NULL && @@ -564,10 +582,10 @@ static int mac802154dev_ioctl(FAR struct file *filep, int cmd, void mac802154dev_conf_data(MACHANDLE mac, FAR struct ieee802154_data_conf_s *conf) { - FAR struct mac802154_devwrapper_s *dev; + FAR struct mac802154_devwrapper_s *dev = + (FAR struct mac802154_devwrapper_s *)mac; FAR struct mac802154dev_dwait_s *curr; FAR struct mac802154dev_dwait_s *prev; - int ret; /* Get the dev from the callback context. This should have been set when * the char driver was registered. @@ -579,7 +597,7 @@ void mac802154dev_conf_data(MACHANDLE mac, /* 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(mac802154dev_takesem(&dev->md_exclsem) != OK); + while (mac802154dev_takesem(&dev->md_exclsem) != 0); /* Search to see if there is a dwait pending for this transaction */