diff --git a/drivers/wireless/ieee802154/mrf24j40.c b/drivers/wireless/ieee802154/mrf24j40.c index 263de68eebf..32da714bcad 100644 --- a/drivers/wireless/ieee802154/mrf24j40.c +++ b/drivers/wireless/ieee802154/mrf24j40.c @@ -3,6 +3,7 @@ * * Copyright (C) 2015-2016 Sebastien Lorquet. All rights reserved. * Author: Sebastien Lorquet + * Author: Anthony Merlino * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -101,10 +102,16 @@ struct mrf24j40_radio_s { - struct ieee802154_radio_s ieee; /* The public device instance */ + struct ieee802154_radio_s radio; /* The public device instance */ + + /* Reference to the bound upper layer via the phyif interface */ + + FAR const 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 */ uint16_t panid; /* PAN identifier, FFFF = not set */ uint16_t saddr; /* short address, FFFF = not set */ @@ -115,6 +122,13 @@ struct mrf24j40_radio_s 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 ieee802154_txdesc_s csma_desc; + struct ieee802154_txdesc_s gts_desc[2]; + + uint8_t tx_buf[CONFIG_IEEE802154_MTU]; }; /**************************************************************************** @@ -123,7 +137,7 @@ struct mrf24j40_radio_s /* Internal operations */ -static void mrf24j40_lock(FAR struct spi_dev_s *spi); +static void mrf24j40_spi_lock(FAR struct spi_dev_s *spi); static void mrf24j40_setreg(FAR struct spi_dev_s *spi, uint32_t addr, uint8_t val); @@ -142,48 +156,50 @@ static int mrf24j40_interrupt(int irq, FAR void *context, FAR void *arg); /* IOCTL helpers */ -static int mrf24j40_setchannel(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_setchannel(FAR struct ieee802154_radio_s *radio, uint8_t chan); -static int mrf24j40_getchannel(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_getchannel(FAR struct ieee802154_radio_s *radio, FAR uint8_t *chan); -static int mrf24j40_setpanid(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_setpanid(FAR struct ieee802154_radio_s *radio, uint16_t panid); -static int mrf24j40_getpanid(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_getpanid(FAR struct ieee802154_radio_s *radio, FAR uint16_t *panid); -static int mrf24j40_setsaddr(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_setsaddr(FAR struct ieee802154_radio_s *radio, uint16_t saddr); -static int mrf24j40_getsaddr(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_getsaddr(FAR struct ieee802154_radio_s *radio, FAR uint16_t *saddr); -static int mrf24j40_seteaddr(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_seteaddr(FAR struct ieee802154_radio_s *radio, FAR uint8_t *eaddr); -static int mrf24j40_geteaddr(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_geteaddr(FAR struct ieee802154_radio_s *radio, FAR uint8_t *eaddr); -static int mrf24j40_setpromisc(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_setpromisc(FAR struct ieee802154_radio_s *radio, bool promisc); -static int mrf24j40_getpromisc(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_getpromisc(FAR struct ieee802154_radio_s *radio, FAR bool *promisc); -static int mrf24j40_setdevmode(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_setdevmode(FAR struct ieee802154_radio_s *radio, uint8_t mode); -static int mrf24j40_getdevmode(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_getdevmode(FAR struct ieee802154_radio_s *radio, FAR uint8_t *mode); -static int mrf24j40_settxpower(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_settxpower(FAR struct ieee802154_radio_s *radio, int32_t txpwr); -static int mrf24j40_gettxpower(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_gettxpower(FAR struct ieee802154_radio_s *radio, FAR int32_t *txpwr); -static int mrf24j40_setcca(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_setcca(FAR struct ieee802154_radio_s *radio, FAR struct ieee802154_cca_s *cca); -static int mrf24j40_getcca(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_getcca(FAR struct ieee802154_radio_s *radio, FAR struct ieee802154_cca_s *cca); -static int mrf24j40_energydetect(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_energydetect(FAR struct ieee802154_radio_s *radio, FAR uint8_t *energy); /* Driver operations */ -static int mrf24j40_ioctl(FAR struct ieee802154_radio_s *ieee, int cmd, +static int mrf24j40_bind(FAR struct ieee802154_radio_s *radio, + FAR struct ieee802154_phyif_s *phyif); +static int mrf24j40_ioctl(FAR struct ieee802154_radio_s *radio, int cmd, unsigned long arg); -static int mrf24j40_rxenable(FAR struct ieee802154_radio_s *ieee, +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 *ieee, +static int mrf24j40_transmit(FAR struct ieee802154_radio_s *radio, FAR struct ieee802154_packet_s *packet); /**************************************************************************** @@ -197,10 +213,9 @@ static int mrf24j40_transmit(FAR struct ieee802154_radio_s *ieee, * using the IRQ number. See the ENC28J60 or CC3000 drivers for reference. */ -static struct mrf24j40_radio_s g_mrf24j40_devices[1]; - static const struct ieee802154_radioops_s mrf24j40_devops = { + mrf24j40_bind, mrf24j40_ioctl, mrf24j40_rxenable, mrf24j40_transmit @@ -210,15 +225,73 @@ 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) +{ + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; + + DEBUGASSERT(dev != NULL); + dev->phyif = phyif; + return OK; +} + /**************************************************************************** - * Name: mrf24j40_lock + * Function: mrf24j40_txavail + * + * Description: + * Called from the upper layer, this function is to notify the device that + * the upper layer has a pending transaction. 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 + * + ****************************************************************************/ + +static void mrf24j40_txavail(FAR struct ieee802154_radio_s *radio, bool gts) +{ + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; + uint8_t gts; + + while (sem_wait(dev->exclsem) < 0) { } + + /* If this a CSMA transaction and we have room in the CSMA fifo */ + + if (!gts && !dev->csma_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]); + + /* Setup the transmit on the device */ + + } + else + { + for(gts = 0; gts < MRF24J40_GTS_SLOTS, gts++) + { + if(!dev->gts_txdesc[i].busy) + { + ret = dev->phyif->poll_gts(dev->phyif, &radio->gts_txdesc[i], + &dev->tx_buf[0]); + + /* Setup the transmit on the device */ + + break; + } + } + } +} + +/**************************************************************************** + * Name: mrf24j40_spi_lock * * Description: * Acquire exclusive access to the shared SPI bus. * ****************************************************************************/ -static void mrf24j40_lock(FAR struct spi_dev_s *spi) +static void mrf24j40_spi_lock(FAR struct spi_dev_s *spi) { SPI_LOCK(spi, 1); SPI_SETBITS(spi, 8); @@ -227,14 +300,14 @@ static void mrf24j40_lock(FAR struct spi_dev_s *spi) } /**************************************************************************** - * Name: mrf24j40_unlock + * Name: mrf24j40_spi_unlock * * Description: * Release exclusive access to the shared SPI bus. * ****************************************************************************/ -static inline void mrf24j40_unlock(FAR struct spi_dev_s *spi) +static inline void mrf24j40_spi_unlock(FAR struct spi_dev_s *spi) { SPI_LOCK(spi,0); } @@ -484,11 +557,8 @@ static int mrf24j40_setrxmode(FAR struct mrf24j40_radio_s *dev, int mode) * ****************************************************************************/ -static int mrf24j40_setchannel(FAR struct ieee802154_radio_s *ieee, - uint8_t chan) +static int mrf24j40_setchannel(FAR struct mrf24j40_radio_s *dev, uint8_t chan) { - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; - if (chan < 11 || chan > 26) { wlerr("ERROR: Invalid chan: %d\n",chan); @@ -511,21 +581,11 @@ static int mrf24j40_setchannel(FAR struct ieee802154_radio_s *ieee, return OK; } -/**************************************************************************** - * Name: mrf24j40_getchannel - * - * Description: - * Define the current radio channel the device is operating on. - * - ****************************************************************************/ - -static int mrf24j40_getchannel(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_getchannel(FAR struct mrf24j40_radio_s *dev, FAR uint8_t *chan) { - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; - - *chan = dev->channel; - + chan = dev->channel; + return OK; } @@ -537,11 +597,9 @@ static int mrf24j40_getchannel(FAR struct ieee802154_radio_s *ieee, * ****************************************************************************/ -static int mrf24j40_setpanid(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_setpanid(FAR struct mrf24j40_radio_s *dev, uint16_t panid) { - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; - mrf24j40_setreg(dev->spi, MRF24J40_PANIDH, (uint8_t)(panid>>8)); mrf24j40_setreg(dev->spi, MRF24J40_PANIDL, (uint8_t)(panid&0xFF)); @@ -559,11 +617,9 @@ static int mrf24j40_setpanid(FAR struct ieee802154_radio_s *ieee, * ****************************************************************************/ -static int mrf24j40_getpanid(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_getpanid(FAR struct mrf24j40_radio_s *dev, FAR uint16_t *panid) { - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; - *panid = dev->panid; return OK; @@ -579,11 +635,9 @@ static int mrf24j40_getpanid(FAR struct ieee802154_radio_s *ieee, * ****************************************************************************/ -static int mrf24j40_setsaddr(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_setsaddr(FAR struct mrf24j40_radio_s *dev, uint16_t saddr) { - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; - mrf24j40_setreg(dev->spi, MRF24J40_SADRH, (uint8_t)(saddr>>8)); mrf24j40_setreg(dev->spi, MRF24J40_SADRL, (uint8_t)(saddr&0xFF)); @@ -600,11 +654,9 @@ static int mrf24j40_setsaddr(FAR struct ieee802154_radio_s *ieee, * ****************************************************************************/ -static int mrf24j40_getsaddr(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_getsaddr(FAR struct mrf24j40_radio_s *dev, FAR uint16_t *saddr) { - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; - *saddr = dev->saddr; return OK; @@ -619,10 +671,9 @@ static int mrf24j40_getsaddr(FAR struct ieee802154_radio_s *ieee, * ****************************************************************************/ -static int mrf24j40_seteaddr(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_seteaddr(FAR struct mrf24j40_radio_s *dev, FAR uint8_t *eaddr) { - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; int i; for (i = 0; i < 8; i++) @@ -642,11 +693,9 @@ static int mrf24j40_seteaddr(FAR struct ieee802154_radio_s *ieee, * ****************************************************************************/ -static int mrf24j40_geteaddr(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_geteaddr(FAR struct mrf24j40_radio_s *dev, FAR uint8_t *eaddr) { - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; - memcpy(eaddr, dev->eaddr, 8); return OK; @@ -661,11 +710,9 @@ static int mrf24j40_geteaddr(FAR struct ieee802154_radio_s *ieee, * ****************************************************************************/ -static int mrf24j40_setpromisc(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_setpromisc(FAR struct mrf24j40_radio_s *dev, bool promisc) { - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; - return mrf24j40_setrxmode(dev, promisc ? MRF24J40_RXMODE_PROMISC : MRF24J40_RXMODE_NORMAL); } @@ -678,11 +725,9 @@ static int mrf24j40_setpromisc(FAR struct ieee802154_radio_s *ieee, * ****************************************************************************/ -static int mrf24j40_getpromisc(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_getpromisc(FAR struct mrf24j40_radio_s *dev, FAR bool *promisc) { - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; - *promisc = (dev->rxmode == MRF24J40_RXMODE_PROMISC); return OK; @@ -696,10 +741,9 @@ static int mrf24j40_getpromisc(FAR struct ieee802154_radio_s *ieee, * ****************************************************************************/ -static int mrf24j40_setdevmode(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_setdevmode(FAR struct mrf24j40_radio_s *dev, uint8_t mode) { - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; int ret = OK; uint8_t reg; @@ -748,11 +792,9 @@ static int mrf24j40_setdevmode(FAR struct ieee802154_radio_s *ieee, * ****************************************************************************/ -static int mrf24j40_getdevmode(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_getdevmode(FAR struct mrf24j40_radio_s *dev, FAR uint8_t *mode) { - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; - *mode = dev->devmode; return OK; @@ -768,10 +810,9 @@ static int mrf24j40_getdevmode(FAR struct ieee802154_radio_s *ieee, * ****************************************************************************/ -static int mrf24j40_settxpower(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_settxpower(FAR struct mrf24j40_radio_s *dev, int32_t txpwr) { - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; uint8_t reg; int save_txpwr = txpwr; @@ -851,11 +892,9 @@ static int mrf24j40_settxpower(FAR struct ieee802154_radio_s *ieee, * ****************************************************************************/ -static int mrf24j40_gettxpower(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_gettxpower(FAR struct mrf24j40_radio_s *radio, FAR int32_t *txpwr) { - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; - *txpwr = dev->txpower; return OK; @@ -869,10 +908,9 @@ static int mrf24j40_gettxpower(FAR struct ieee802154_radio_s *ieee, * ****************************************************************************/ -static int mrf24j40_setcca(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_setcca(FAR struct mrf24j40_radio_s *dev, FAR struct ieee802154_cca_s *cca) { - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; uint8_t mode; if (!cca->use_ed && !cca->use_cs) @@ -914,11 +952,9 @@ static int mrf24j40_setcca(FAR struct ieee802154_radio_s *ieee, * ****************************************************************************/ -static int mrf24j40_getcca(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_getcca(FAR struct mrf24j40_radio_s *dev, FAR struct ieee802154_cca_s *cca) { - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; - memcpy(cca, &dev->cca, sizeof(struct ieee802154_cca_s)); return OK; @@ -982,82 +1018,82 @@ static int mrf24j40_regdump(FAR struct mrf24j40_radio_s *dev) * ****************************************************************************/ -static int mrf24j40_ioctl(FAR struct ieee802154_radio_s *ieee, int cmd, +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 *)ieee; + 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) switch(cmd) { case PHY802154IOC_SET_CHAN: - ret = mrf24j40_setchannel(ieee, u.channel); + ret = mrf24j40_setchannel(dev, u.channel); break; case PHY802154IOC_GET_CHAN: - ret = mrf24j40_getchannel(ieee, &u.channel); + ret = mrf24j40_getchannel(dev, &u.channel); break; case PHY802154IOC_SET_PANID: - ret = mrf24j40_setpanid(ieee, u.panid); + ret = mrf24j40_setpanid(dev, u.panid); break; case PHY802154IOC_GET_PANID: - ret = mrf24j40_getpanid(ieee, &u.panid); + ret = mrf24j40_getpanid(dev, &u.panid); break; case PHY802154IOC_SET_SADDR: - ret = mrf24j40_setsaddr(ieee, u.saddr); + ret = mrf24j40_setsaddr(dev, u.saddr); break; case PHY802154IOC_GET_SADDR: - ret = mrf24j40_getsaddr(ieee, &u.saddr); + ret = mrf24j40_getsaddr(dev, &u.saddr); break; case PHY802154IOC_SET_EADDR: - ret = mrf24j40_seteaddr(ieee, u.eaddr); + ret = mrf24j40_seteaddr(dev, u.eaddr); break; case PHY802154IOC_GET_EADDR: - ret = mrf24j40_geteaddr(ieee, u.eaddr); + ret = mrf24j40_geteaddr(dev, u.eaddr); break; case PHY802154IOC_SET_PROMISC: - ret = mrf24j40_setpromisc(ieee, u.promisc); + ret = mrf24j40_setpromisc(dev, u.promisc); break; case PHY802154IOC_GET_PROMISC: - ret = mrf24j40_getpromisc(ieee, &u.promisc); + ret = mrf24j40_getpromisc(dev, &u.promisc); break; case PHY802154IOC_SET_DEVMODE: - ret = mrf24j40_setdevmode(ieee, u.devmode); + ret = mrf24j40_setdevmode(dev, u.devmode); break; case PHY802154IOC_GET_DEVMODE: - ret = mrf24j40_getdevmode(ieee, &u.devmode); + ret = mrf24j40_getdevmode(dev, &u.devmode); break; case PHY802154IOC_SET_TXPWR: - ret = mrf24j40_settxpower(ieee, u.txpwr); + ret = mrf24j40_settxpower(dev, u.txpwr); break; case PHY802154IOC_GET_TXPWR: - ret = mrf24j40_gettxpower(ieee, &u.txpwr); + ret = mrf24j40_gettxpower(dev, &u.txpwr); break; case PHY802154IOC_SET_CCA: - ret = mrf24j40_setcca(ieee, &u.cca); + ret = mrf24j40_setcca(dev, &u.cca); break; case PHY802154IOC_GET_CCA: - ret = mrf24j40_getcca(ieee, &u.cca); + ret = mrf24j40_getcca(dev, &u.cca); break; case PHY802154IOC_ENERGYDETECT: - ret = mrf24j40_energydetect(ieee, &u.energy); + ret = mrf24j40_energydetect(dev, &u.energy); break; case 1000: @@ -1080,10 +1116,9 @@ static int mrf24j40_ioctl(FAR struct ieee802154_radio_s *ieee, int cmd, * ****************************************************************************/ -static int mrf24j40_energydetect(FAR struct ieee802154_radio_s *ieee, +static int mrf24j40_energydetect(FAR struct mrf24j40_radio_s *dev, FAR uint8_t *energy) { - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; uint8_t reg; /* Manually enable the LNA*/ @@ -1130,10 +1165,10 @@ static int mrf24j40_energydetect(FAR struct ieee802154_radio_s *ieee, * ****************************************************************************/ -static int mrf24j40_transmit(FAR struct ieee802154_radio_s *ieee, - FAR struct ieee802154_packet_s *packet) +static int mrf24j40_transmit(FAR struct ieee802154_radio_s *radio, + uint8_t *buf, uint16_t buf_len) { - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; uint32_t addr; uint8_t reg; int ret; @@ -1152,8 +1187,8 @@ static int mrf24j40_transmit(FAR struct ieee802154_radio_s *ieee, /* Analyze frame control to compute header length */ - frame_ctrl = packet->data[0]; - frame_ctrl |= packet->data[1] << 8; + frame_ctrl = buf[0]; + frame_ctrl |= (buf[1] << 8); if ((frame_ctrl & IEEE802154_FRAMECTRL_DADDR)== IEEE802154_ADDRMODE_SHORT) { @@ -1184,11 +1219,11 @@ static int mrf24j40_transmit(FAR struct ieee802154_radio_s *ieee, /* Frame length */ - mrf24j40_setreg(dev->spi, addr++, packet->len); + mrf24j40_setreg(dev->spi, addr++, buflen); /* Frame data */ - for (ret = 0; ret < packet->len; ret++) /* this sets the correct val for ret */ + for (ret = 0; ret < buflen; ret++) /* this sets the correct val for ret */ { mrf24j40_setreg(dev->spi, addr++, packet->data[ret]); } @@ -1208,9 +1243,7 @@ static int mrf24j40_transmit(FAR struct ieee802154_radio_s *ieee, mrf24j40_setreg(dev->spi, MRF24J40_TXNCON, reg); - /* Suspend calling thread until transmit is complete */ - - return sem_wait(&ieee->txsem); + return ret; } /**************************************************************************** @@ -1232,9 +1265,9 @@ static void mrf24j40_irqwork_tx(FAR struct mrf24j40_radio_s *dev) /* 1 means it failed, we want 1 to mean it worked. */ - dev->ieee.txok = (reg & MRF24J40_TXSTAT_TXNSTAT) != MRF24J40_TXSTAT_TXNSTAT; - dev->ieee.txretries = (reg & MRF24J40_TXSTAT_X_MASK) >> MRF24J40_TXSTAT_X_SHIFT; - dev->ieee.txbusy = (reg & MRF24J40_TXSTAT_CCAFAIL) == MRF24J40_TXSTAT_CCAFAIL; + 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 @@ -1248,7 +1281,8 @@ static void mrf24j40_irqwork_tx(FAR struct mrf24j40_radio_s *dev) /* Wake up the thread that triggered the transmission */ - sem_post(&dev->ieee.txsem); + sem_post(&dev->radio.txsem); + } /**************************************************************************** @@ -1259,16 +1293,16 @@ static void mrf24j40_irqwork_tx(FAR struct mrf24j40_radio_s *dev) * ****************************************************************************/ -static int mrf24j40_rxenable(FAR struct ieee802154_radio_s *ieee, bool state, +static int mrf24j40_rxenable(FAR struct ieee802154_radio_s *radio, bool state, FAR struct ieee802154_packet_s *packet) { - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)ieee; + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; uint8_t reg; if (state) { mrf24j40_pacontrol(dev, MRF24J40_PA_AUTO); - ieee->rxbuf = packet; + radio->rxbuf = packet; /* Enable rx int */ @@ -1278,7 +1312,7 @@ static int mrf24j40_rxenable(FAR struct ieee802154_radio_s *ieee, bool state, } else { - ieee->rxbuf = NULL; + radio->rxbuf = NULL; } return OK; @@ -1313,20 +1347,20 @@ static void mrf24j40_irqwork_rx(FAR struct mrf24j40_radio_s *dev) /* Read packet */ addr = MRF24J40_RXBUF_BASE; - dev->ieee.rxbuf->len = mrf24j40_getreg(dev->spi, addr++); - /* wlinfo("len %3d\n", dev->ieee.rxbuf->len); */ + dev->radio.rxbuf->len = mrf24j40_getreg(dev->spi, addr++); + /* wlinfo("len %3d\n", dev->radio.rxbuf->len); */ - for (index = 0; index < dev->ieee.rxbuf->len; index++) + for (index = 0; index < dev->radio.rxbuf->len; index++) { - dev->ieee.rxbuf->data[index] = mrf24j40_getreg(dev->spi, addr++); + dev->radio.rxbuf->data[index] = mrf24j40_getreg(dev->spi, addr++); } - dev->ieee.rxbuf->lqi = mrf24j40_getreg(dev->spi, addr++); - dev->ieee.rxbuf->rssi = mrf24j40_getreg(dev->spi, addr++); + dev->radio.rxbuf->lqi = mrf24j40_getreg(dev->spi, addr++); + dev->radio.rxbuf->rssi = mrf24j40_getreg(dev->spi, addr++); /* Reduce len by 2, we only receive frames with correct crc, no check required */ - dev->ieee.rxbuf->len -= 2; + dev->radio.rxbuf->len -= 2; /* Enable reception of next packet by flushing the fifo. * This is an MRF24J40 errata (no. 1). @@ -1338,7 +1372,7 @@ static void mrf24j40_irqwork_rx(FAR struct mrf24j40_radio_s *dev) mrf24j40_setreg(dev->spi, MRF24J40_BBREG1, 0); - sem_post(&dev->ieee.rxsem); + sem_post(&dev->radio.rxsem); } /**************************************************************************** @@ -1446,21 +1480,17 @@ static int mrf24j40_interrupt(int irq, FAR void *context, FAR void *arg) ****************************************************************************/ FAR struct ieee802154_radio_s *mrf24j40_init(FAR struct spi_dev_s *spi, - FAR const struct mrf24j40_lower_s *lower) + FAR const struct mrf24j40_lower_s *lower) { FAR struct mrf24j40_radio_s *dev; struct ieee802154_cca_s cca; -#if 0 dev = kmm_zalloc(sizeof(struct mrf24j40_radio_s)); if (dev == NULL) { return NULL; } -#else - dev = &g_mrf24j40_devices[0]; -#endif - + /* Attach irq */ if (lower->attach(lower, mrf24j40_interrupt, dev) != OK) @@ -1471,43 +1501,43 @@ FAR struct ieee802154_radio_s *mrf24j40_init(FAR struct spi_dev_s *spi, return NULL; } - dev->ieee.ops = &mrf24j40_devops; + dev->radio.ops = &mrf24j40_devops; /* Initialize semaphores */ - sem_init(&dev->ieee.rxsem, 0, 0); - sem_init(&dev->ieee.txsem, 0, 0); + sem_init(&dev->radio.rxsem, 0, 0); + sem_init(&dev->radio.txsem, 0, 0); /* These semaphores are all used for signaling and, hence, should * not have priority inheritance enabled. */ - sem_setprotocol(&dev->ieee.rxsem, SEM_PRIO_NONE); - sem_setprotocol(&dev->ieee.txsem, SEM_PRIO_NONE); + sem_setprotocol(&dev->radio.rxsem, SEM_PRIO_NONE); + sem_setprotocol(&dev->radio.txsem, SEM_PRIO_NONE); dev->lower = lower; dev->spi = spi; mrf24j40_initialize(dev); - mrf24j40_setchannel(&dev->ieee, 11); - mrf24j40_setpanid (&dev->ieee, 0xFFFF); - mrf24j40_setsaddr (&dev->ieee, 0xFFFF); - mrf24j40_seteaddr (&dev->ieee, (uint8_t*)"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"); + mrf24j40_setchannel(&dev->radio, 11); + mrf24j40_setpanid (&dev->radio, 0xFFFF); + mrf24j40_setsaddr (&dev->radio, 0xFFFF); + mrf24j40_seteaddr (&dev->radio, (uint8_t*)"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"); /* Default device params */ cca.use_ed = 1; cca.use_cs = 0; cca.edth = 0x60; /* CCA mode ED, no carrier sense, recommenced ED threshold -69 dBm */ - mrf24j40_setcca(&dev->ieee, &cca); + mrf24j40_setcca(&dev->radio, &cca); mrf24j40_setrxmode(dev, MRF24J40_RXMODE_NORMAL); - mrf24j40_settxpower(&dev->ieee, 0); /*16. Set transmitter power .*/ + mrf24j40_settxpower(&dev->radio, 0); /*16. Set transmitter power .*/ mrf24j40_pacontrol(dev, MRF24J40_PA_AUTO); - dev->lower->enable(dev->lower, true); - return &dev->ieee; + dev->lower->enable(dev->radio, true); + return &dev->radio; } diff --git a/include/nuttx/wireless/ieee802154/ieee802154_mac.h b/include/nuttx/wireless/ieee802154/ieee802154_mac.h index 6ad8158c806..838f7fcafd5 100644 --- a/include/nuttx/wireless/ieee802154/ieee802154_mac.h +++ b/include/nuttx/wireless/ieee802154/ieee802154_mac.h @@ -83,22 +83,27 @@ * Request and Response primitives. */ -#define MAC802154IOC_MLME_ASSOC_REQUEST _MAC802154IOC(0x0001) -#define MAC802154IOC_MLME_ASSOC_RESPONSE _MAC802154IOC(0x0002) -#define MAC802154IOC_MLME_DISASSOC_REQUEST _MAC802154IOC(0x0003) -#define MAC802154IOC_MLME_GET_REQUEST _MAC802154IOC(0x0004) -#define MAC802154IOC_MLME_GTS_REQUEST _MAC802154IOC(0x0005) -#define MAC802154IOC_MLME_ORPHAN_RESPONSE _MAC802154IOC(0x0006) -#define MAC802154IOC_MLME_RESET_REQUEST _MAC802154IOC(0x0007) -#define MAC802154IOC_MLME_RXENABLE_REQUEST _MAC802154IOC(0x0008) -#define MAC802154IOC_MLME_SCAN_REQUEST _MAC802154IOC(0x0009) -#define MAC802154IOC_MLME_SET_REQUEST _MAC802154IOC(0x000A) -#define MAC802154IOC_MLME_START_REQUEST _MAC802154IOC(0x000B) -#define MAC802154IOC_MLME_SYNC_REQUEST _MAC802154IOC(0x000C) -#define MAC802154IOC_MLME_POLL_REQUEST _MAC802154IOC(0x000D) -#define MAC802154IOC_MLME_DPS_REQUEST _MAC802154IOC(0x000E) -#define MAC802154IOC_MLME_SOUNDING_REQUEST _MAC802154IOC(0x000F) -#define MAC802154IOC_MLME_CALIBRATE_REQUEST _MAC802154IOC(0x0010) +#define MAC802154IOC_MCPS_REGISTER _MAC802154IOC(0x0001) + +#define MAC802154IOC_MLME_REGISER _MAC802154IOC(0x0002); +#define MAC802154IOC_MLME_ASSOC_REQUEST _MAC802154IOC(0x0003) +#define MAC802154IOC_MLME_ASSOC_RESPONSE _MAC802154IOC(0x0004) +#define MAC802154IOC_MLME_DISASSOC_REQUEST _MAC802154IOC(0x0005) +#define MAC802154IOC_MLME_GET_REQUEST _MAC802154IOC(0x0006) +#define MAC802154IOC_MLME_GTS_REQUEST _MAC802154IOC(0x0007) +#define MAC802154IOC_MLME_ORPHAN_RESPONSE _MAC802154IOC(0x0008) +#define MAC802154IOC_MLME_RESET_REQUEST _MAC802154IOC(0x0009) +#define MAC802154IOC_MLME_RXENABLE_REQUEST _MAC802154IOC(0x000A) +#define MAC802154IOC_MLME_SCAN_REQUEST _MAC802154IOC(0x000B) +#define MAC802154IOC_MLME_SET_REQUEST _MAC802154IOC(0x000C) +#define MAC802154IOC_MLME_START_REQUEST _MAC802154IOC(0x000D) +#define MAC802154IOC_MLME_SYNC_REQUEST _MAC802154IOC(0x000E) +#define MAC802154IOC_MLME_POLL_REQUEST _MAC802154IOC(0x000F) +#define MAC802154IOC_MLME_DPS_REQUEST _MAC802154IOC(0x0010) +#define MAC802154IOC_MLME_SOUNDING_REQUEST _MAC802154IOC(0x0011) +#define MAC802154IOC_MLME_CALIBRATE_REQUEST _MAC802154IOC(0x0012) + + /* IEEE 802.15.4 MAC Interface **********************************************/ @@ -141,19 +146,19 @@ #define IEEE802154_FRAMECTRL_VERSION 0x3000 /* Source addressing mode, bits 12-13 */ #define IEEE802154_FRAMECTRL_SADDR 0xC000 /* Source addressing mode, bits 14-15 */ -#define IEEE802154_FRAMECTRL_SHIFT_FTYPE 0 /* Frame type, bits 0-2 */ -#define IEEE802154_FRAMECTRL_SHIFT_SEC 3 /* Security Enabled, bit 3 */ -#define IEEE802154_FRAMECTRL_SHIFT_PEND 4 /* Frame pending, bit 4 */ -#define IEEE802154_FRAMECTRL_SHIFT_ACKREQ 5 /* Acknowledge request, bit 5 */ -#define IEEE802154_FRAMECTRL_SHIFT_PANIDCOMP 6 /* PAN ID Compression, bit 6 */ -#define IEEE802154_FRAMECTRL_SHIFT_DADDR 10 /* Dest addressing mode, bits 10-11 */ -#define IEEE802154_FRAMECTRL_SHIFT_VERSION 12 /* Source addressing mode, bits 12-13 */ -#define IEEE802154_FRAMECTRL_SHIFT_SADDR 14 /* Source addressing mode, bits 14-15 */ +#define IEEE802154_FRAMECTRL_SHIFT_FTYPE 0 /* Frame type, bits 0-2 */ +#define IEEE802154_FRAMECTRL_SHIFT_SEC 3 /* Security Enabled, bit 3 */ +#define IEEE802154_FRAMECTRL_SHIFT_PEND 4 /* Frame pending, bit 4 */ +#define IEEE802154_FRAMECTRL_SHIFT_ACKREQ 5 /* Acknowledge request, bit 5 */ +#define IEEE802154_FRAMECTRL_SHIFT_PANIDCOMP 6 /* PAN ID Compression, bit 6 */ +#define IEEE802154_FRAMECTRL_SHIFT_DADDR 10 /* Dest addressing mode, bits 10-11 */ +#define IEEE802154_FRAMECTRL_SHIFT_VERSION 12 /* Source addressing mode, bits 12-13 */ +#define IEEE802154_FRAMECTRL_SHIFT_SADDR 14 /* Source addressing mode, bits 14-15 */ /* IEEE 802.15.4 PHY constants */ #define IEEE802154_MAX_PHY_PACKET_SIZE 127 -#define IEEE802154_TURN_AROUND_TIME 12 /*symbol periods*/ +#define IEEE802154_TURN_AROUND_TIME 12 /*symbol periods*/ /* IEEE 802.15.4 MAC constants */ @@ -170,8 +175,13 @@ (IEEE802154_MAX_PHY_PACKET_SIZE - IEEE802154_MAX_BEACON_OVERHEAD) #define IEEE802154_MAX_LOST_BEACONS 4 -#define IEEE802514_MIN_MPDU_OVERHEAD 9 -#define IEEE802154_MAX_MPDU_UNSEC_OVERHEAD 25 +#define IEEE802154_MIN_MPDU_OVERHEAD 9 +#define IEEE802154_MAX_UNSEC_MHR_OVERHEAD 23 +#define IEEE802154_MFR_LENGTH 2 + +#define IEEE802154_MAX_MPDU_UNSEC_OVERHEAD \ + (IEEE802154_MAX_UNSEC_MHR_OVERHEAD + IEEE802154_MFR_LENGTH) + #define IEEE802154_MAX_SAFE_MAC_PAYLOAD_SIZE \ (IEEE802154_MAX_PHY_PACKET_SIZE - IEEE802154_MAX_MPDU_UNSEC_OVERHEAD) @@ -339,59 +349,18 @@ struct ieee802154_addr_s { /* Address mode. Short or Extended */ - enum ieee802154_addr_mode_e ia_mode; + enum ieee802154_addr_mode_e mode; - uint16_t ia_panid; /* PAN identifier, can be IEEE802154_PAN_UNSPEC */ + uint16_t panid; /* PAN identifier, can be IEEE802154_PAN_UNSPEC */ union { - uint16_t _ia_saddr; /* short address */ - uint8_t _ia_eaddr[8]; /* extended address */ - } ia_addr; - -#define ia_saddr ia_addr._ia_saddr -#define ia_eaddr ia_addr._ia_eaddr + uint16_t saddr; /* short address */ + uint8_t eaddr[8]; /* extended address */ + }; }; #define IEEE802154_ADDRSTRLEN 22 /* (2*2+1+8*2, PPPP/EEEEEEEEEEEEEEEE) */ -struct ieee802154_framecontrol_s -{ - /* Frame type - * - * Should be a value from: ieee802154_frametype_e - * - * Bits 0-1 - */ - - uint16_t frame_type : 3; - - uint16_t security_en : 1; /* Security Enabled flag, bit 3 */ - uint16_t frame_pending : 1; /* Frame Pending flag, bit 4 */ - uint16_t ack_req : 1; /* Acknowledge Request flag, bit 5 */ - uint16_t panid_comp : 1; /* PAN ID Compression flag, bit 6 */ - uint16_t reserved : 3; /* Reserved, bits 7-9 */ - - /* Destination Addressing Mode - * - * Should be a value from: ieee802154_addr_mode_e - * - * Bits 10-11 - */ - - uint16_t dest_addr_mode : 2; - - uint16_t frame_version : 2; /* Frame Version, bits 12-13 */ - - /* Source Addressing Mode - * - * Should be a value from: ieee802154_addr_mode_e - * - * Bits 14-15 - */ - - uint16_t src_addr_mode : 2; -}; - #ifdef CONFIG_IEEE802154_SECURITY struct ieee802154_security_s { @@ -444,7 +413,7 @@ struct ieee802154_frame_s struct ieee802154_data_req_s { enum ieee802154_addr_mode_e src_addr_mode; /* Source Address Mode */ - struct ieee802154_addr_s dest__addr; /* Destination Address */ + struct ieee802154_addr_s dest_addr; /* Destination Address */ /* Number of bytes contained in the MAC Service Data Unit (MSDU) * to be transmitted by the MAC sublayer enitity @@ -497,7 +466,7 @@ struct ieee802154_data_req_s }; #define SIZEOF_IEEE802154_DATA_REQ_S(n) \ - (sizeof(struct ieee802154_data_req_s) + (n)) + (sizeof(struct ieee802154_data_req_s) + (n) - 1) struct ieee802154_data_conf_s { @@ -911,17 +880,17 @@ struct ieee802154_maccb_s CODE void (*conf_disassociate)(MACHANDLE mac, int status); - /* PIvoata returned */ + /* PIB data returned */ CODE void (*conf_get)(MACHANDLE mac, int status, int attribute, FAR uint8_t *value, int valuelen); - /* GTvoanagement completed */ + /* GTS management completed */ CODE void (*conf_gts)(MACHANDLE mac, FAR uint8_t *characteristics, int status); - /* MAveset completed */ + /* MAC reset completed */ CODE void (*conf_reset)(MACHANDLE mac, int status); diff --git a/include/nuttx/wireless/ieee802154/ieee802154_radio.h b/include/nuttx/wireless/ieee802154/ieee802154_radio.h index eef94e328f4..0a38ed04022 100644 --- a/include/nuttx/wireless/ieee802154/ieee802154_radio.h +++ b/include/nuttx/wireless/ieee802154/ieee802154_radio.h @@ -157,19 +157,51 @@ struct ieee802154_netradio_s #endif /* IEEE802.15.4 Radio Interface Operations **********************************/ +struct ieee802154_trans_s +{ + uint8_t retry_count; /* The number of retries remaining */ + uint8_t msdu_handle; /* The msdu handle identifying the transaction */ + + uint16_t psdu_length; /* The length of the PSDU */ + + /* The PHY Service Data Unit (PSDU) buffer representing the frame to be + * transmitted. This must be at the end of the struct to allow the array + * to continue and make the struct "variable length". Users should allocate + * memory using the SIZEOF_MAC802154_TRANSACTION_S macro below */ + + uint8_t psdu[CONFIG_IEEE802154_MTU]; +}; struct ieee802154_radio_s; /* Forward reference */ +struct ieee802154_phyif_s +{ + CODE int (*poll_csma) (FAR struct ieee802154_phyif_s *phyif, + FAR struct ieee802154_txdesc_s *tx_desc, + uint8_t *buf); + + CODE int (*poll_gts) (FAR struct ieee802154_phyif_s *phyif, + FAR struct ieee802154_txdesc_s *tx_desc, + uint8_t *buf); + + /* Driver-specific information */ + + void * priv; +}; + 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, unsigned long arg); + CODE int (*rxenable)(FAR struct ieee802154_radio_s *dev, bool state, FAR struct ieee802154_packet_s *packet); + CODE int (*transmit)(FAR struct ieee802154_radio_s *dev, FAR struct ieee802154_packet_s *packet); - - /* TODO beacon/sf order */ }; struct ieee802154_radio_s diff --git a/wireless/ieee802154/mac802154.c b/wireless/ieee802154/mac802154.c index e8f046f2849..99e3f27d8aa 100644 --- a/wireless/ieee802154/mac802154.c +++ b/wireless/ieee802154/mac802154.c @@ -68,49 +68,191 @@ struct ieee802154_privmac_s FAR struct ieee802154_radio_s *radio; /* Contained IEEE802.15.4 radio dev */ FAR const struct ieee802154_maccb_s *cb; /* Contained MAC callbacks */ - /* MIB attributes, grouped to save memory */ - /* 0x40 */ uint8_t macAckWaitDuration : 1; /* 55 or 120(true) */ - /* 0x41 */ uint8_t macAssociationPermit : 1; - /* 0x42 */ uint8_t macAutoRequest : 1; - /* 0x43 */ uint8_t macBattLifeExt : 1; - /* 0x44 */ uint8_t macBattLifeExtPeriods : 1; /* 6 or 8(true) */ - /* 0x4E */ uint8_t macMaxCSMABackoffs : 3; /* 0-5 */ + sem_t excl_sem; /* Support exclusive access */ - /* 0x47 */ uint8_t macBeaconOrder : 4; - /* 0x54 */ uint8_t macSuperframeOrder : 4; + /* 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. */ - /* 0x4F */ uint32_t macMinBE : 2; - /* 0x4D */ uint32_t macGTSPermit : 1; - /* 0x51 */ uint32_t macPromiscuousMode : 1; - /* 0x52 */ uint32_t macRxOnWhenIdle : 1; - uint32_t macPad : 3; - /* 0x48 */ uint32_t macBeaconTxTime : 24; + FAR struct mac802154_trans_s *csma_head; + FAR struct mac802154_trans_s *csma_tail; - /* 0x45 */ uint8_t macBeaconPayload[IEEE802154_MAX_BEACON_PAYLOAD_LENGTH]; - /* 0x46 */ uint8_t macBeaconPayloadLength; - /* 0x49 */ uint8_t macBSN; - /* 0x4A */ uint8_t macCoordExtendedAddress[8]; - /* 0x4B */ uint16_t macCoordShortAddress; - /* 0x4C */ uint8_t macDSN; - /* 0x50 */ uint16_t macPANId; - /* 0x53 */ uint16_t macShortAddress; - /* 0x55 */ uint16_t macTransactionPersistenceTime; -#if 0 - /* Security MIB */ - /* 0x70 */ macACLEntryDescriptorSet - /* 0x71 */ macACLEntryDescriptorSetSize - /* 0x74 */ macDefaultSecurityMaterial - /* 0x72 */ macDefaultSecurity:1 - /* 0x75 */ macDefaultSecuritySuite:3 - /* 0x73 */ macDefaultSecurityMaterialLength:6 - /* 0x76 */ macSecurityMode:2 -#endif + struct mac802154_trans_s csma_buf[5]; + + /* 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 */ + + FAR struct mac802154_trans_s *indirect_head; + FAR struct mac802154_trans_s *indirect_tail; + + FAR struct mac802154_trans_s *active_trans; + + /* 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 coord_addr; + + /* 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_wait_dur; + + /* 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_wait_time; + + /* The maximum time (in unit periods) that a transaction is stored by a + * coordinator and indicated in its beacon. */ + + uint16_t trans_persist_time; + + /* Contents of beacon payload */ + + uint8_t beacon_payload[IEEE802154_MAX_BEACON_PAYLOAD_LENGTH]; + uint8_t beacon_payload_len; /* Length of beacon payload */ + + uint8_t batt_life_ext_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 max_retries; /* 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_wait_time; + + /* The total transmit duration (including PHY header and FCS) specified in + * symbols. [1] pg. 129 */ + + uint32_t tx_total_dur; + + struct + { + uint32_t is_assoc : 1; /* Are we associated to the PAN */ + uint32_t assoc_permit : 1; /* Are we allowing assoc. as a coord. */ + uint32_t auto_req : 1; /* Automatically send data req. if addr + * addr is in the beacon frame */ + + uint32_t batt_life_ext : 1; /* Is BLE enabled */ + uint32_t gts_permit : 1; /* Is PAN Coord. accepting GTS reqs. */ + uint32_t promiscuous_mode : 1; /* Is promiscuous mode on? */ + uint32_t ranging_supported : 1; /* Does MAC sublayer support ranging */ + uint32_t rx_when_idle : 1; /* Recvr. on during idle periods */ + uint32_t sec_enabled : 1; /* Does MAC sublayer have security en. */ + + uint32_t max_csma_backoffs : 3; /* Max num backoffs for CSMA algorithm + * before declaring ch access failure */ + + uint32_t beacon_order : 4; /* Freq. that beacon is transmitted */ + + uint32_t superframe_order : 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_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 + { + uint32_t tx_ctrl_active_dur : 17; /* Duration for which tx is permitted to + * be active */ + + 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 */ + } + + /* TODO: Add Security-related MAC PIB attributes */ + +}; + +struct mac802154_trans_s +{ + /* Supports a singly linked list */ + + FAR struct mac802154_trans_s *flink; + + uint8_t msdu_handle; + + uint8_t *mhr_buf; + uint8_t mhr_len; + + uint8_t *d_buf; + uint8_t d_len; + + sem_t sem; +}; + +struct mac802154_unsec_mhr_s +{ + uint8_t length; + union { + uint16_t frame_control; + uint8_t data[IEEE802154_MAX_UNSEC_MHR_OVERHEAD]; + }; }; /**************************************************************************** * 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_defaultmib * @@ -121,41 +263,7 @@ struct ieee802154_privmac_s static int mac802154_defaultmib(FAR struct ieee802154_privmac_s *priv) { - priv->macAckWaitDuration = 0; - priv->macAssociationPermit = 0; - priv->macAutoRequest = 1; - priv->macBattLifeExt = 0; - priv->macBattLifeExtPeriods = 0; - priv->macMaxCSMABackoffs = 4; - - priv->macBeaconOrder = 15; - priv->macSuperframeOrder = 15; - - priv->macMinBE = 3; - priv->macGTSPermit = 1; - priv->macPromiscuousMode = 0; - priv->macRxOnWhenIdle = 0; - priv->macBeaconTxTime = 0x000000; - - priv->macBeaconPayloadLength = 0; - priv->macBSN = 0; /* Shall be random */ - //priv->macCoordExtendedAddress[8]; - priv->macCoordShortAddress = 0xffff; - priv->macDSN = 0; /* Shall be random */ - priv->macPANId = 0xffff; - priv->macShortAddress = 0xffff; - priv->macTransactionPersistenceTime = 0x01f4; - -#if 0 - /* Security MIB */ - - priv->macACLEntryDescriptorSetSize = 0; - priv->macDefaultSecurity = 0; - priv->macDefaultSecuritySuite = 0; - priv->macDefaultSecurityMaterialLength = 0x15; - priv->macSecurityMode = 0; -#endif - + /* TODO: Set all MAC fields to default values */ return OK; } @@ -314,7 +422,258 @@ int mac802154_ioctl(MACHANDLE mac, int cmd, unsigned long arg) 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; - return -ENOTTY; + FAR struct mac802154_trans_s *trans; + struct mac802154_unsec_mhr_s mhr; + int ret; + + /* Start off assuming there is only the frame_control field in the MHR */ + + mhr.length = 2; + + /* Do a preliminary check to make sure the MSDU isn't too long for even the + * best case */ + + if (req->msdu_length > IEEE802154_MAX_MAC_PAYLOAD_SIZE) + { + return -EINVAL; + } + + /* Ensure we start with a clear frame control field */ + + mhr.frame_control = 0; + + /* Set the frame type to Data */ + + mhr.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 */ + + if (req->msdu_length > IEEE802154_MAX_SAFE_MAC_PAYLOAD_SIZE) + { + mhr.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 */ + + mhr.frame_ctrl |= (req->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 (req->dest_addr.mode != IEEE802154_ADDRMODE_NONE) + { + memcpy(&mhr.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); + mhr.length += 2; + } + else if (req->dest_addr.mode == IEEE802154_ADDRMODE_EXTENDED) + { + memcpy(&mhr.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); + + /* From this point on, we need exclusive access to the privmac struct */ + + ret = mac802154dev_takesem(&dev->md_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 (req->src_addr_mode != IEEE802154_ADDRMODE_NONE && + req->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(req->dest_addr.panid == priv->addr.panid) + { + mhr.frame_control |= IEEE802154_FRAMECTRL_PANIDCOMP; + } + } + + if (req->src_addr_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 (req->dest_addr.mode == IEEE802154_ADDRMODE_NONE || + (mhr.frame_control & IEEE802154_FRAMECTRL_PANIDCOMP) + { + memcpy(&mhr.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); + mhr.length += 2; + } + else if (req->src_addr_mode == IEEE802154_ADDRMODE_EXTENDED) + { + memcpy(&mhr.data[mhr.length], priv->addr.eaddr, 8); + mhr.length += 8; + } + } + + /* Set the source addr mode inside the frame contorl field */ + + mhr.frame_ctrl |= (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++; + + /* Now that we know which fields are included in the header, we can make + * sure we actually have enough room in the PSDU */ + + if (mhr.length + req->msdu_length + IEEE802154_MFR_LENGTH > + IEEE802154_MAX_PHY_PACKET_SIZE) + { + return -E2BIG; + } + + trans->mhr_buf = &mhr.data[0]; + trans->mhr_len = mhr.length; + + trans->d_buf = &req->msdu[0]; + trans->d_len = req->msdu_length; + + 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 + * 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 (req->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 (req->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] */ + + if (priv->is_coord && req->dest_addr.mode != IEEE802154_ADDRMODE_NONE) + { + /* Link the transaction into the indirect_trans list */ + + priv->indirect_tail->flink = trans; + priv->indirect_tail = trans; + } + else + { + /* Override the setting since it wasn't valid */ + + req->indirect_tx = 0; + } + } + + /* If this is a direct transmission not during a GTS */ + + if (!req->indirect_tx) + { + /* Link the transaction into the CSMA transaction list */ + + priv->csma_tail->flink = trans; + priv->csma_tail = trans; + + /* Notify the radio driver that there is data available */ + + priv->radio->tx_notify(priv->radio); + + 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, + 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; + + /* Check to see if there are any CSMA transactions waiting */ + + if (mac->csma_head) + { + /* Pop a CSMA transaction off the list */ + + trans = mac->csma_head; + mac->csma_head = mac->csma_head.flink; + + /* Setup the transmit descriptor */ + + tx_desc->psdu_handle = trans->msdu_handle; + tx_desc->psdu_length = trans->mhr_len + trans->d_len; + + /* Copy the frame into the buffer */ + + memcpy(&buf[0], trans->mhr_buf, trans->mhr_len); + memcpy(&buf[trans->mhr_len], trans->d_buf, trans->d_len); + + /* 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 txdesc->psdu_length; + } + + return 0; } /**************************************************************************** @@ -347,6 +706,29 @@ 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; + + /* Set the channel of the PHY layer */ + + /* Set the channel page of the PHY layer */ + + /* Set the macPANId */ + + /* Set either the macCoordExtendedAddress and macCoordShortAddress + * depending on the CoordAddrMode in the primitive */ + + if (req->coord_addr.mode == IEEE802154_ADDRMODE_EXTENDED) + { + + } + else if (req->coord_addr.mode == IEEE802154_ADDRMODE_EXTENDED) + { + + } + else + { + return -EINVAL; + } + return -ENOTTY; } diff --git a/wireless/ieee802154/mac802154_device.c b/wireless/ieee802154/mac802154_device.c index 18d88cf9b38..67631e7c63b 100644 --- a/wireless/ieee802154/mac802154_device.c +++ b/wireless/ieee802154/mac802154_device.c @@ -77,15 +77,33 @@ struct mac802154_devwrapper_s 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 */ }; /* This structure describes the state of one open mac driver instance */ -struct mac802154_open_s +struct mac802154dev_open_s { /* Supports a singly linked list */ - FAR struct mac802154_open_s *md_flink; + FAR struct mac802154dev_open_s *md_flink; /* The following will be true if we are closing */ @@ -96,7 +114,7 @@ struct mac802154dev_dwait_s { uint8_t mw_handle; /* The msdu handle identifying the frame */ sem_t mw_sem; /* The semaphore used to signal the completion */ - int status; /* The success/error of the transaction */ + int mw_status; /* The success/error of the transaction */ /* Supports a singly linked list */ @@ -181,7 +199,7 @@ static int mac802154dev_open(FAR struct file *filep) { FAR struct inode *inode; FAR struct mac802154_devwrapper_s *dev; - FAR struct mac802154_open_s *opriv; + FAR struct mac802154dev_open_s *opriv; int ret; DEBUGASSERT(filep != NULL && filep->f_inode != NULL); @@ -201,8 +219,8 @@ static int mac802154dev_open(FAR struct file *filep) /* Allocate a new open struct */ - opriv = (FAR struct mac802154_open_s *) - kmm_zalloc(sizeof(struct mac802154_open_s)); + opriv = (FAR struct mac802154dev_open_s *) + kmm_zalloc(sizeof(struct mac802154dev_open_s)); if (!opriv) { @@ -238,9 +256,9 @@ static int mac802154dev_close(FAR struct file *filep) { FAR struct inode *inode; FAR struct mac802154_devwrapper_s *dev; - FAR struct mac802154_open_s *opriv; - FAR struct mac802154_open_s *curr; - FAR struct mac802154_open_s *prev; + FAR struct mac802154dev_open_s *opriv; + FAR struct mac802154dev_open_s *curr; + FAR struct mac802154dev_open_s *prev; irqstate_t flags; bool closing; int ret; @@ -431,7 +449,13 @@ static ssize_t mac802154dev_write(FAR struct file *filep, /* Wait for the DATA.confirm callback to be called for our handle */ - sem_wait(&dwait.mw_sem); + 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 @@ -476,6 +500,57 @@ static int mac802154dev_ioctl(FAR struct file *filep, int cmd, switch (cmd) { +#ifndef CONFIG_DISABLE_SIGNALS + /* Command: MAC802154IOC_MLME_REGISTER, MAC802154IOC_MCPS_REGISTER + * Description: Register to receive a signal whenever there is a + * event primitive sent from the MAC layer. + * Argument: A read-only pointer to an instance of struct + * mac802154dev_notify_s + * Return: Zero (OK) on success. Minus one will be returned on + * failure with the errno value set appropriately. + */ + + case MAC802154IOC_MLME_REGISTER: + { + FAR struct mac802154dev_notify_s *notify = + (FAR struct mac802154dev_notify_s *)((uintptr_t)arg); + + if (notify) + { + /* Save the notification events */ + + dev->md_mlme_notify.mn_signo = notify->mn_signo; + dev->md_mlme_pid = getpid(); + + return OK; + } + } + break; + case MAC802154IOC_MCPS_REGISTER: + { + FAR struct mac802154dev_notify_s *notify = + (FAR struct mac802154dev_notify_s *)((uintptr_t)arg); + + if (notify) + { + /* Save the notification events */ + + dev->md_mcps_notify.mn_signo = notify->mn_signo; + dev->md_mcps_pid = getpid(); + + return OK; + } + } + break; +#endif + case MAC802154IOC_MLME_ASSOC_REQUEST: + { + FAR struct ieee802154_assoc_req_s *req = + (FAR struct ieee802154_assoc_req_s *)((uintptr_t)arg); + + + } + break; default: wlerr("ERROR: Unrecognized command %ld\n", cmd); ret = -EINVAL; @@ -501,20 +576,63 @@ void mac802154dev_conf_data(MACHANDLE mac, */ #warning Missing logic - /* Get exclusive access to the driver structure */ - - ret = mac802154dev_takesem(&dev->md_exclsem); - if (ret < 0) - { - wlerr("ERROR: mac802154dev_takesem failed: %d\n", ret); - return; - } + /* 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); /* Search to see if there is a dwait pending for this transaction */ for (prev = NULL, curr = dev->md_dwait; curr && curr->mw_handle != conf->msdu_handle; prev = curr, curr = curr->mw_flink); + + /* If a dwait is found */ + + if (curr) + { + /* Unlink the structure from the list. The struct should be allocated on + * the calling write's stack, so we don't need to worry about deallocating + * here */ + + if (prev) + { + prev->mw_flink = curr->mw_flink; + } + else + { + dev->md_dwait = curr->mw_flink; + } + + /* Copy the transmission status into the dwait struct */ + + curr->mw_status = conf->msdu_handle; + + /* Wake the thread waiting for the data transmission */ + + sem_post(&curr->mw_sem); + + /* Release the driver */ + + mac802154dev_givesem(&dev->md_exclsem); + } + + +#ifndef CONFIG_DISABLE_SIGNALS + /* Send a signal to the registered application */ + +#ifdef CONFIG_CAN_PASS_STRUCTS + /* Copy the status as the signal data to be optionally used by app */ + + union sigval value; + value.sival_int = (int)conf->status; + (void)sigqueue(dev->md_mcps_pid, dev->md_mcps_notify.mn_signo, value); +#else + (void)sigqueue(dev->md_mcps_pid, dev->md_mcps_notify.mn_signo, + value.sival_ptr); +#endif + +#endif } /****************************************************************************