Merged in merlin17/nuttx/ieee802154 (pull request #321)
wireless/ieee802154: Lots of small fixes to eliminate build issues. Approved-by: Gregory Nutt <gnutt@nuttx.org>
This commit is contained in:
commit
ea224e8ddb
@ -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); */
|
||||
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/wireless/ieee802154/ieee802154_radio.h>
|
||||
@ -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)
|
||||
{
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
@ -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 */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user