mirror of
https://github.com/apache/nuttx.git
synced 2026-08-23 14:38:25 +00:00
Merged in merlin17/nuttx/ieee802154 (pull request #318)
Ieee802154 Approved-by: Gregory Nutt <gnutt@nuttx.org>
This commit is contained in:
commit
53a363dd0f
5 changed files with 849 additions and 318 deletions
|
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2015-2016 Sebastien Lorquet. All rights reserved.
|
||||
* Author: Sebastien Lorquet <sebastien@lorquet.fr>
|
||||
* Author: Anthony Merlino <anthony@vergeaero.com>
|
||||
*
|
||||
* 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue