Merged in merlin17/nuttx/beacon802154 (pull request #419)

ieee80215: starts adding support for beacon-enabled networking

Approved-by: Gregory Nutt <gnutt@nuttx.org>
This commit is contained in:
Anthony Merlino 2017-06-26 00:18:46 +00:00 committed by Gregory Nutt
commit 2069a90220
18 changed files with 2137 additions and 763 deletions

View File

@ -984,8 +984,9 @@ CONFIG_WIRELESS=y
CONFIG_WIRELESS_IEEE802154=y CONFIG_WIRELESS_IEEE802154=y
CONFIG_IEEE802154_DEFAULT_EADDR=0x00fade00deadbeef CONFIG_IEEE802154_DEFAULT_EADDR=0x00fade00deadbeef
CONFIG_MAC802154_HPWORK=y CONFIG_MAC802154_HPWORK=y
CONFIG_MAC802154_NNOTIF=6
CONFIG_MAC802154_NTXDESC=3 CONFIG_MAC802154_NTXDESC=3
CONFIG_MAC802154_NNOTIF=6
CONFIG_MAC802154_NPANDESC=5
CONFIG_IEEE802154_IND_PREALLOC=20 CONFIG_IEEE802154_IND_PREALLOC=20
CONFIG_IEEE802154_IND_IRQRESERVE=10 CONFIG_IEEE802154_IND_IRQRESERVE=10
CONFIG_IEEE802154_MACDEV=y CONFIG_IEEE802154_MACDEV=y
@ -1167,10 +1168,10 @@ CONFIG_BUILTIN_PROXY_STACKSIZE=1024
CONFIG_EXAMPLES_NSH=y CONFIG_EXAMPLES_NSH=y
CONFIG_EXAMPLES_NSH_CXXINITIALIZE=y CONFIG_EXAMPLES_NSH_CXXINITIALIZE=y
# CONFIG_EXAMPLES_NULL is not set # CONFIG_EXAMPLES_NULL is not set
# CONFIG_EXAMPLES_NX is not set
# CONFIG_EXAMPLES_NXFFS is not set # CONFIG_EXAMPLES_NXFFS is not set
# CONFIG_EXAMPLES_NXHELLO is not set # CONFIG_EXAMPLES_NXHELLO is not set
# CONFIG_EXAMPLES_NXIMAGE is not set # CONFIG_EXAMPLES_NXIMAGE is not set
# CONFIG_EXAMPLES_NX is not set
# CONFIG_EXAMPLES_NXLINES is not set # CONFIG_EXAMPLES_NXLINES is not set
# CONFIG_EXAMPLES_NXTERM is not set # CONFIG_EXAMPLES_NXTERM is not set
# CONFIG_EXAMPLES_NXTEXT is not set # CONFIG_EXAMPLES_NXTEXT is not set

View File

@ -103,6 +103,24 @@
#define MRF24J40_GTS_SLOTS 2 #define MRF24J40_GTS_SLOTS 2
/* Clock configuration macros */
#define MRF24J40_SLPCLKPER_100KHZ ((1000 * 1000 * 1000)/100000) /* 10ns */
#define MRF24J40_SLPCLKPER_32KHZ ((1000 * 1000 * 1000)/32000) /* 31.25ns */
#define MRF24J40_BEACONINTERVAL_NSEC(beaconorder) \
(IEEE802154_BASE_SUPERFRAME_DURATION * (1 << beaconorder) * (16 *1000))
/* For now I am just setting the REMCNT to the maximum while staying in multiples
* of 10000 (100khz period) */
#define MRF24J40_REMCNT 60000
#define MRF24J40_REMCNT_NSEC (MRF24J40_REMCNT * 50)
#define MRF24J40_MAINCNT(bo, clkper) \
((MRF24J40_BEACONINTERVAL_NSEC(bo) - MRF24J40_REMCNT_NSEC) / \
clkper)
/* Formula for calculating default macMaxFrameWaitTime is on pg. 130 /* Formula for calculating default macMaxFrameWaitTime is on pg. 130
* *
* For PHYs other than CSS and UWB, the attribute phyMaxFrameDuration is given by: * For PHYs other than CSS and UWB, the attribute phyMaxFrameDuration is given by:
@ -146,7 +164,7 @@ struct mrf24j40_radio_s
struct ieee802154_addr_s addr; struct ieee802154_addr_s addr;
uint8_t channel; /* 11 to 26 for the 2.4 GHz band */ uint8_t chan; /* 11 to 26 for the 2.4 GHz band */
uint8_t devmode; /* device mode: device, coord, pancoord */ uint8_t devmode; /* device mode: device, coord, pancoord */
uint8_t paenabled; /* enable usage of PA */ uint8_t paenabled; /* enable usage of PA */
uint8_t rxmode; /* Reception mode: Main, no CRC, promiscuous */ uint8_t rxmode; /* Reception mode: Main, no CRC, promiscuous */
@ -163,6 +181,8 @@ struct mrf24j40_radio_s
bool csma_busy : 1; bool csma_busy : 1;
bool reschedule_csma : 1; bool reschedule_csma : 1;
bool rxenabled : 1;
struct ieee802154_txdesc_s *gts_desc[MRF24J40_GTS_SLOTS]; struct ieee802154_txdesc_s *gts_desc[MRF24J40_GTS_SLOTS];
bool gts_busy[MRF24J40_GTS_SLOTS]; bool gts_busy[MRF24J40_GTS_SLOTS];
}; };
@ -197,12 +217,12 @@ static int mrf24j40_interrupt(int irq, FAR void *context, FAR void *arg);
static void mrf24j40_dopoll_csma(FAR void *arg); static void mrf24j40_dopoll_csma(FAR void *arg);
static void mrf24j40_dopoll_gts(FAR void *arg); static void mrf24j40_dopoll_gts(FAR void *arg);
static int mrf24j40_norm_setup(FAR struct mrf24j40_radio_s *dev, static void mrf24j40_norm_setup(FAR struct mrf24j40_radio_s *dev,
FAR struct iob_s *frame, bool csma); FAR struct iob_s *frame, bool csma);
static int mrf24j40_gts_setup(FAR struct mrf24j40_radio_s *dev, uint8_t gts, static void mrf24j40_gts_setup(FAR struct mrf24j40_radio_s *dev, uint8_t gts,
FAR struct iob_s *frame); FAR struct iob_s *frame);
static int mrf24j40_setup_fifo(FAR struct mrf24j40_radio_s *dev, static void mrf24j40_setup_fifo(FAR struct mrf24j40_radio_s *dev,
FAR struct iob_s *frame, uint32_t fifo_addr); FAR const uint8_t *buf, uint8_t length, uint32_t fifo_addr);
static inline void mrf24j40_norm_trigger(FAR struct mrf24j40_radio_s *dev); static inline void mrf24j40_norm_trigger(FAR struct mrf24j40_radio_s *dev);
@ -214,6 +234,10 @@ static int mrf24j40_setsaddr(FAR struct mrf24j40_radio_s *dev,
FAR const uint8_t *saddr); FAR const uint8_t *saddr);
static int mrf24j40_seteaddr(FAR struct mrf24j40_radio_s *dev, static int mrf24j40_seteaddr(FAR struct mrf24j40_radio_s *dev,
FAR const uint8_t *eaddr); FAR const uint8_t *eaddr);
static int mrf24j40_setcoordsaddr(FAR struct mrf24j40_radio_s *dev,
FAR const uint8_t *saddr);
static int mrf24j40_setcoordeaddr(FAR struct mrf24j40_radio_s *dev,
FAR const uint8_t *eaddr);
static int mrf24j40_setdevmode(FAR struct mrf24j40_radio_s *dev, static int mrf24j40_setdevmode(FAR struct mrf24j40_radio_s *dev,
uint8_t mode); uint8_t mode);
static int mrf24j40_settxpower(FAR struct mrf24j40_radio_s *dev, static int mrf24j40_settxpower(FAR struct mrf24j40_radio_s *dev,
@ -242,6 +266,14 @@ static int mrf24j40_set_attr(FAR struct ieee802154_radio_s *radio,
static int mrf24j40_rxenable(FAR struct ieee802154_radio_s *dev, bool enable); static int mrf24j40_rxenable(FAR struct ieee802154_radio_s *dev, bool enable);
static int mrf24j40_req_rxenable(FAR struct ieee802154_radio_s *radio, static int mrf24j40_req_rxenable(FAR struct ieee802154_radio_s *radio,
FAR struct ieee802154_rxenable_req_s *req); FAR struct ieee802154_rxenable_req_s *req);
static int mrf24j40_beaconstart(FAR struct ieee802154_radio_s *radio,
FAR const struct ieee802154_superframespec_s *sfspec,
FAR struct ieee802154_beaconframe_s *beacon);
static int mrf24j40_beaconupdate(FAR struct ieee802154_radio_s *radio,
FAR struct ieee802154_beaconframe_s *beacon);
static int mrf24j40_beaconstop(FAR struct ieee802154_radio_s *radio);
static int mrf24j40_sfupdate(FAR struct ieee802154_radio_s *radio,
FAR const struct ieee802154_superframespec_s *sfspec);
/**************************************************************************** /****************************************************************************
* Private Data * Private Data
@ -423,7 +455,7 @@ static int mrf24j40_get_attr(FAR struct ieee802154_radio_s *radio,
switch (attr) switch (attr)
{ {
case IEEE802154_ATTR_MAC_EXTENDED_ADDR: case IEEE802154_ATTR_MAC_EADDR:
{ {
memcpy(&attrval->mac.eaddr[0], &dev->addr.eaddr[0], 8); memcpy(&attrval->mac.eaddr[0], &dev->addr.eaddr[0], 8);
ret = IEEE802154_STATUS_SUCCESS; ret = IEEE802154_STATUS_SUCCESS;
@ -443,6 +475,12 @@ static int mrf24j40_get_attr(FAR struct ieee802154_radio_s *radio,
ret = IEEE802154_STATUS_SUCCESS; ret = IEEE802154_STATUS_SUCCESS;
} }
break; break;
case IEEE802154_ATTR_PHY_CHAN:
{
attrval->phy.chan = dev->chan;
ret = IEEE802154_STATUS_SUCCESS;
}
default: default:
ret = IEEE802154_STATUS_UNSUPPORTED_ATTRIBUTE; ret = IEEE802154_STATUS_UNSUPPORTED_ATTRIBUTE;
@ -467,16 +505,30 @@ static int mrf24j40_set_attr(FAR struct ieee802154_radio_s *radio,
} }
break; break;
case IEEE802154_ATTR_MAC_SHORT_ADDRESS: case IEEE802154_ATTR_MAC_SADDR:
{ {
mrf24j40_setsaddr(dev, attrval->mac.saddr); mrf24j40_setsaddr(dev, attrval->mac.saddr);
ret = IEEE802154_STATUS_SUCCESS; ret = IEEE802154_STATUS_SUCCESS;
} }
break; break;
case IEEE802154_ATTR_MAC_EXTENDED_ADDR: case IEEE802154_ATTR_MAC_EADDR:
{ {
mrf24j40_seteaddr(dev, &attrval->mac.eaddr[0]); mrf24j40_seteaddr(dev, attrval->mac.eaddr);
ret = IEEE802154_STATUS_SUCCESS;
}
break;
case IEEE802154_ATTR_MAC_COORD_SADDR:
{
mrf24j40_setcoordsaddr(dev, attrval->mac.coordsaddr);
ret = IEEE802154_STATUS_SUCCESS;
}
break;
case IEEE802154_ATTR_MAC_COORD_EADDR:
{
mrf24j40_setcoordeaddr(dev, attrval->mac.coordeaddr);
ret = IEEE802154_STATUS_SUCCESS; ret = IEEE802154_STATUS_SUCCESS;
} }
break; break;
@ -503,6 +555,13 @@ static int mrf24j40_set_attr(FAR struct ieee802154_radio_s *radio,
ret = IEEE802154_STATUS_SUCCESS; ret = IEEE802154_STATUS_SUCCESS;
} }
break; break;
case IEEE802154_ATTR_PHY_CHAN:
{
mrf24j40_setchannel(dev, attrval->phy.chan);
ret = IEEE802154_STATUS_SUCCESS;
}
break;
default: default:
ret = IEEE802154_STATUS_UNSUPPORTED_ATTRIBUTE; ret = IEEE802154_STATUS_UNSUPPORTED_ATTRIBUTE;
@ -518,6 +577,185 @@ static int mrf24j40_req_rxenable(FAR struct ieee802154_radio_s *radio,
return -ENOTTY; return -ENOTTY;
} }
static int mrf24j40_beaconstart(FAR struct ieee802154_radio_s *radio,
FAR const struct ieee802154_superframespec_s *sfspec,
FAR struct ieee802154_beaconframe_s *beacon)
{
FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio;
uint32_t maincnt = 0;
uint32_t slpcal = 0;
int reg;
if (sfspec->pancoord)
{
/* Set the PANCOORD (RXMCR 0x00<3>) bit = 1to configure as PAN coordinator */
reg = mrf24j40_getreg(dev->spi, MRF24J40_RXMCR);
reg |= MRF24J40_RXMCR_PANCOORD;
mrf24j40_setreg(dev->spi, MRF24J40_RXMCR, reg);
/* Set the SLOTTED (TXMCR 0x11<5>) bit = 1 to use Slotted CSMA-CA mode */
reg = mrf24j40_getreg(dev->spi, MRF24J40_TXMCR);
reg |= MRF24J40_TXMCR_SLOTTED;
mrf24j40_setreg(dev->spi, MRF24J40_TXMCR, reg);
/* Load the beacon frame into the TXBFIFO (0x080-0x0FF). */
mrf24j40_setup_fifo(dev, beacon->bf_data, beacon->bf_len, MRF24J40_BEACON_FIFO);
/* Set the TXBMSK (TXBCON1 0x25<7>) bit = 1 to mask the beacon interrupt
* mask
*/
reg = mrf24j40_getreg(dev->spi, MRF24J40_TXBCON1);
reg |= MRF24J40_TXBCON1_TXBMSK;
mrf24j40_setreg(dev->spi, MRF24J40_TXBCON1, reg);
/* Set INTL (WAKECON 0x22<5:0>) value to 0x03. */
reg = mrf24j40_getreg(dev->spi, MRF24J40_WAKECON);
reg &= ~MRF24J40_WAKECON_INTL;
reg |= 0x03 & MRF24J40_WAKECON_INTL;
mrf24j40_setreg(dev->spi, MRF24J40_WAKECON, reg);
/* Program the CAP end slot (ESLOTG1 0x13<3:0>) value. */
reg = mrf24j40_getreg(dev->spi, MRF24J40_ESLOTG1);
reg &= ~MRF24J40_ESLOTG1_CAP;
reg |= sfspec->final_capslot & MRF24J40_ESLOTG1_CAP;
mrf24j40_setreg(dev->spi, MRF24J40_ESLOTG1, reg);
/* TODO: Add GTS related code. See pg 100 of datasheet */
/* Calibrate the Sleep Clock (SLPCLK) frequency. Refer to Section 3.15.1.2
* Sleep Clock Calibration.
*/
/* If the Sleep Clock Selection, SLPCLKSEL (0x207<7:6), is the internal
* oscillator (100 kHz), set SLPCLKDIV to a minimum value of 0x01.
*/
mrf24j40_setreg(dev->spi, MRF24J40_SLPCON1, 0x01);
/* Select the source of SLPCLK (internal 100kHz) */
mrf24j40_setreg(dev->spi, MRF24J40_RFCON7, MRF24J40_RFCON7_SEL_100KHZ);
/* Begin calibration by setting the SLPCALEN bit (SLPCAL2 0x20B<4>) to
* 1. Sixteen samples of the SLPCLK are counted and stored in the
* SLPCAL register. No need to mask, this is the only writable bit
*/
mrf24j40_setreg(dev->spi, MRF24J40_SLPCAL2, MRF24J40_SLPCAL2_SLPCALEN);
/* Calibration is complete when the SLPCALRDY bit (SLPCAL2 0x20B<7>) is
* set to 1.
*/
while (!(mrf24j40_getreg(dev->spi, MRF24J40_SLPCAL2) &
MRF24J40_SLPCAL2_SLPCALRDY))
{
usleep(1);
}
slpcal = mrf24j40_getreg(dev->spi, MRF24J40_SLPCAL0);
slpcal |= (mrf24j40_getreg(dev->spi, MRF24J40_SLPCAL1) << 8);
slpcal |= ((mrf24j40_getreg(dev->spi, MRF24J40_SLPCAL2) << 16) & 0x0F);
/* Set WAKECNT (SLPACK 0x35<6:0>) value = 0x5F to set the main oscillator
* (20 MHz) start-up timer value.
*/
mrf24j40_setreg(dev->spi, MRF24J40_SLPACK, 0x5F);
/* Program the Beacon Interval into the Main Counter, MAINCNT (0x229<1:0>,
* 0x228, 0x227, 0x226), and Remain Counter, REMCNT (0x225, 0x224),
* according to BO and SO values. Refer to Section 3.15.1.3 Sleep Mode
* Counters
*/
mrf24j40_setreg(dev->spi, MRF24J40_REMCNTL, (MRF24J40_REMCNT & 0xFF));
mrf24j40_setreg(dev->spi, MRF24J40_REMCNTH, ((MRF24J40_REMCNT >> 8) & 0xFF));
maincnt = MRF24J40_MAINCNT(sfspec->beaconorder, (slpcal * 50 / 16));
mrf24j40_setreg(dev->spi, MRF24J40_MAINCNT0, (maincnt & 0xFF));
mrf24j40_setreg(dev->spi, MRF24J40_MAINCNT1, ((maincnt >> 8) & 0xFF));
mrf24j40_setreg(dev->spi, MRF24J40_MAINCNT2, ((maincnt >> 16) & 0xFF));
mrf24j40_setreg(dev->spi, MRF24J40_MAINCNT3, ((maincnt >> 24) & 0x03));
/* Enable the SLPIF and WAKEIF flags */
reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON);
reg &= ~(MRF24J40_INTCON_SLPIE | MRF24J40_INTCON_WAKEIE);
mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg);
/* Configure the BO (ORDER 0x10<7:4>) and SO (ORDER 0x10<3:0>) values.
* After configuring BO and SO, the beacon frame will be sent immediately.
*/
mrf24j40_setreg(dev->spi, MRF24J40_ORDER,
((sfspec->beaconorder << 4) & 0xF0) | (sfspec->sforder & 0x0F));
}
else
{
return -ENOTTY;
}
return OK;
}
static int mrf24j40_beaconupdate(FAR struct ieee802154_radio_s *radio,
FAR struct ieee802154_beaconframe_s *beacon)
{
FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio;
mrf24j40_setup_fifo(dev, beacon->bf_data, beacon->bf_len, MRF24J40_BEACON_FIFO);
return OK;
}
static int mrf24j40_beaconstop(FAR struct ieee802154_radio_s *radio)
{
return -ENOTTY;
}
static int mrf24j40_sfupdate(FAR struct ieee802154_radio_s *radio,
FAR const struct ieee802154_superframespec_s *sfspec)
{
FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio;
int reg;
reg = mrf24j40_getreg(dev->spi, MRF24J40_RXMCR);
if (sfspec->pancoord)
{
reg |= MRF24J40_RXMCR_PANCOORD;
}
else
{
reg &= ~MRF24J40_RXMCR_PANCOORD;
}
mrf24j40_setreg(dev->spi, MRF24J40_RXMCR, reg);
/* Program the CAP end slot (ESLOTG1 0x13<3:0>) value. */
reg = mrf24j40_getreg(dev->spi, MRF24J40_ESLOTG1);
reg &= ~MRF24J40_ESLOTG1_CAP;
reg |= sfspec->final_capslot & MRF24J40_ESLOTG1_CAP;
mrf24j40_setreg(dev->spi, MRF24J40_ESLOTG1, reg);
/* Configure the BO (ORDER 0x10<7:4>) and SO (ORDER 0x10<3:0>) values.
* After configuring BO and SO, the beacon frame will be sent immediately.
*/
mrf24j40_setreg(dev->spi, MRF24J40_ORDER,
((sfspec->beaconorder << 4) & 0xF0) | (sfspec->sforder & 0x0F));
return OK;
}
/**************************************************************************** /****************************************************************************
* Internal Functions * Internal Functions
****************************************************************************/ ****************************************************************************/
@ -731,7 +969,7 @@ static void mrf24j40_setreg(FAR struct spi_dev_s *spi, uint32_t addr,
* Name: mrf24j40_getreg * Name: mrf24j40_getreg
* *
* Description: * Description:
* Return the value of an MRF24J40 device register * Return the value of an MRF24J40 device register*
* *
****************************************************************************/ ****************************************************************************/
@ -949,8 +1187,8 @@ static int mrf24j40_setchannel(FAR struct mrf24j40_radio_s *dev, uint8_t chan)
mrf24j40_resetrfsm(dev); mrf24j40_resetrfsm(dev);
dev->channel = chan; dev->chan = chan;
//wlinfo("%u\n", (unsigned)chan); wlinfo("%u\n", (unsigned)chan);
return OK; return OK;
} }
@ -1020,6 +1258,51 @@ static int mrf24j40_seteaddr(FAR struct mrf24j40_radio_s *dev,
return OK; return OK;
} }
/****************************************************************************
* Name: mrf24j40_setcoordsaddr
*
* Description:
* Define the coordinator short address. The following addresses are special:
* FFFEh : Broadcast
* FFFFh : Unspecified
*
****************************************************************************/
static int mrf24j40_setcoordsaddr(FAR struct mrf24j40_radio_s *dev,
FAR const uint8_t *saddr)
{
mrf24j40_setreg(dev->spi, MRF24J40_ASSOSADR0, saddr[0]);
mrf24j40_setreg(dev->spi, MRF24J40_ASSOSADR1, saddr[1]);
IEEE802154_SADDRCOPY(dev->addr.saddr, saddr);
wlinfo("%02X:%02X\n", saddr[1], saddr[0]);
return OK;
}
/****************************************************************************
* Name: mrf24j40_setcoordeaddr
*
* Description:
* Define the coordinator extended address. The following addresses are special:
* FFFFFFFFFFFFFFFFh : Unspecified
*
****************************************************************************/
static int mrf24j40_setcoordeaddr(FAR struct mrf24j40_radio_s *dev,
FAR const uint8_t *eaddr)
{
int i;
for (i = 0; i < 8; i++)
{
mrf24j40_setreg(dev->spi, MRF24J40_ASSOEADR0 + i, eaddr[i]);
dev->addr.eaddr[i] = eaddr[i];
}
return OK;
}
/**************************************************************************** /****************************************************************************
* Name: mrf24j40_setdevmode * Name: mrf24j40_setdevmode
* *
@ -1303,11 +1586,10 @@ static int mrf24j40_energydetect(FAR struct mrf24j40_radio_s *dev,
* *
****************************************************************************/ ****************************************************************************/
static int mrf24j40_norm_setup(FAR struct mrf24j40_radio_s *dev, static void mrf24j40_norm_setup(FAR struct mrf24j40_radio_s *dev,
FAR struct iob_s *frame, bool csma) FAR struct iob_s *frame, bool csma)
{ {
uint8_t reg; uint8_t reg;
int ret;
/* Enable tx int */ /* Enable tx int */
@ -1332,7 +1614,7 @@ static int mrf24j40_norm_setup(FAR struct mrf24j40_radio_s *dev,
/* Setup the FIFO */ /* Setup the FIFO */
ret = mrf24j40_setup_fifo(dev, frame, MRF24J40_TXNORM_FIFO); mrf24j40_setup_fifo(dev, frame->io_data, frame->io_len, MRF24J40_TXNORM_FIFO);
/* If the frame control field contains an acknowledgment request, set the /* If the frame control field contains an acknowledgment request, set the
* TXNACKREQ bit. See IEEE 802.15.4/2003 7.2.1.1 page 112 for info. * TXNACKREQ bit. See IEEE 802.15.4/2003 7.2.1.1 page 112 for info.
@ -1350,8 +1632,6 @@ static int mrf24j40_norm_setup(FAR struct mrf24j40_radio_s *dev,
} }
mrf24j40_setreg(dev->spi, MRF24J40_TXNCON, reg); mrf24j40_setreg(dev->spi, MRF24J40_TXNCON, reg);
return ret;
} }
/**************************************************************************** /****************************************************************************
@ -1381,10 +1661,10 @@ static inline void mrf24j40_norm_trigger(FAR struct mrf24j40_radio_s *dev)
* *
****************************************************************************/ ****************************************************************************/
static int mrf24j40_gts_setup(FAR struct mrf24j40_radio_s *dev, uint8_t fifo, static void mrf24j40_gts_setup(FAR struct mrf24j40_radio_s *dev, uint8_t fifo,
FAR struct iob_s *frame) FAR struct iob_s *frame)
{ {
return -ENOTTY;
} }
/**************************************************************************** /****************************************************************************
@ -1394,17 +1674,18 @@ static int mrf24j40_gts_setup(FAR struct mrf24j40_radio_s *dev, uint8_t fifo,
* *
****************************************************************************/ ****************************************************************************/
static int mrf24j40_setup_fifo(FAR struct mrf24j40_radio_s *dev, static void mrf24j40_setup_fifo(FAR struct mrf24j40_radio_s *dev,
FAR struct iob_s *frame, uint32_t fifo_addr) FAR const uint8_t *buf, uint8_t length,
uint32_t fifo_addr)
{ {
int ret; int hlen = 3; /* Include frame control and seq number */
int hlen = 3; /* Include frame control and seq number */ int i;
uint16_t frame_ctrl; uint16_t frame_ctrl;
/* Analyze frame control to compute header length */ /* Analyze frame control to compute header length */
frame_ctrl = frame->io_data[0]; frame_ctrl = buf[0];
frame_ctrl |= (frame->io_data[1] << 8); frame_ctrl |= (buf[1] << 8);
if ((frame_ctrl & IEEE802154_FRAMECTRL_DADDR)== IEEE802154_ADDRMODE_SHORT) if ((frame_ctrl & IEEE802154_FRAMECTRL_DADDR)== IEEE802154_ADDRMODE_SHORT)
{ {
@ -1435,16 +1716,14 @@ static int mrf24j40_setup_fifo(FAR struct mrf24j40_radio_s *dev,
/* Frame length */ /* Frame length */
mrf24j40_setreg(dev->spi, fifo_addr++, frame->io_len); mrf24j40_setreg(dev->spi, fifo_addr++, length);
/* Frame data */ /* Frame data */
for (ret = 0; ret < frame->io_len; ret++) /* this sets the correct val for ret */ for (i = 0; i < length; i++)
{ {
mrf24j40_setreg(dev->spi, fifo_addr++, frame->io_data[ret]); mrf24j40_setreg(dev->spi, fifo_addr++, buf[i]);
} }
return ret;
} }
/**************************************************************************** /****************************************************************************
@ -1599,13 +1878,30 @@ static int mrf24j40_rxenable(FAR struct ieee802154_radio_s *radio, bool enable)
FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio;
uint8_t reg; uint8_t reg;
dev->rxenabled = enable;
if (enable) if (enable)
{ {
/* Disable packet reception. See pg. 109 of datasheet */
mrf24j40_setreg(dev->spi, MRF24J40_BBREG1, MRF24J40_BBREG1_RXDECINV);
/* Enable rx int */ /* Enable rx int */
reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON);
reg &= ~MRF24J40_INTCON_RXIE; reg &= ~MRF24J40_INTCON_RXIE;
mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg);
/* Purge the RX buffer */
reg = mrf24j40_getreg(dev->spi, MRF24J40_RXFLUSH);
reg |= MRF24J40_RXFLUSH_RXFLUSH;
mrf24j40_setreg(dev->spi, MRF24J40_RXFLUSH, reg);
/* Re-enable packet reception. See pg. 109 of datasheet */
mrf24j40_setreg(dev->spi, MRF24J40_BBREG1, 0);
} }
else else
{ {
@ -1689,14 +1985,14 @@ done:
mrf24j40_setreg(dev->spi, MRF24J40_RXFLUSH, 1); mrf24j40_setreg(dev->spi, MRF24J40_RXFLUSH, 1);
/* Enable packet reception */
mrf24j40_setreg(dev->spi, MRF24J40_BBREG1, 0);
/* Only enable RX interrupt if we are to be listening when IDLE */ /* Only enable RX interrupt if we are to be listening when IDLE */
if (dev->rxonidle) if (dev->rxenabled)
{ {
/* Enable packet reception */
mrf24j40_setreg(dev->spi, MRF24J40_BBREG1, 0);
reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON);
reg &= ~MRF24J40_INTCON_RXIE; reg &= ~MRF24J40_INTCON_RXIE;
mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg);
@ -1723,7 +2019,8 @@ done:
static void mrf24j40_irqworker(FAR void *arg) static void mrf24j40_irqworker(FAR void *arg)
{ {
FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)arg; FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)arg;
uint8_t intstat, intcon; uint8_t intstat;
uint8_t reg;
DEBUGASSERT(dev); DEBUGASSERT(dev);
DEBUGASSERT(dev->spi); DEBUGASSERT(dev->spi);
@ -1735,7 +2032,6 @@ static void mrf24j40_irqworker(FAR void *arg)
/* Read and store INTSTAT - this clears the register. */ /* Read and store INTSTAT - this clears the register. */
intstat = mrf24j40_getreg(dev->spi, MRF24J40_INTSTAT); intstat = mrf24j40_getreg(dev->spi, MRF24J40_INTSTAT);
wlinfo("INT%02X\n", intstat);
/* Do work according to the pending interrupts */ /* Do work according to the pending interrupts */
@ -1749,12 +2045,12 @@ static void mrf24j40_irqworker(FAR void *arg)
/* Timers are one-shot, so disable the interrupt */ /* Timers are one-shot, so disable the interrupt */
intcon = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON);
intcon |= MRF24J40_INTCON_HSYMTMRIE; reg |= MRF24J40_INTCON_HSYMTMRIE;
mrf24j40_setreg(dev->spi, MRF24J40_INTCON, intcon); mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg);
} }
if ((intstat & MRF24J40_INTSTAT_RXIF)) if ((intstat & MRF24J40_INTSTAT_RXIF) && dev->rxenabled)
{ {
/* A packet was received, retrieve it */ /* A packet was received, retrieve it */
@ -1782,6 +2078,17 @@ static void mrf24j40_irqworker(FAR void *arg)
mrf24j40_irqwork_txgts(dev, 1); mrf24j40_irqwork_txgts(dev, 1);
} }
if ((intstat & MRF24J40_INTSTAT_SLPIF))
{
dev->radiocb->sfevent(dev->radiocb, IEEE802154_SFEVENT_ENDOFACTIVE);
/* Acknowledge the alert and put the device to sleep */
reg = mrf24j40_getreg(dev->spi, MRF24J40_SLPACK);
reg |= MRF24J40_SLPACK_SLPACK;
mrf24j40_setreg(dev->spi, MRF24J40_SLPACK, reg);
}
/* Unlock the radio device */ /* Unlock the radio device */
sem_post(&dev->exclsem); sem_post(&dev->exclsem);
@ -1878,10 +2185,16 @@ FAR struct ieee802154_radio_s *mrf24j40_init(FAR struct spi_dev_s *spi,
dev->radio.set_attr = mrf24j40_set_attr; dev->radio.set_attr = mrf24j40_set_attr;
dev->radio.rxenable = mrf24j40_rxenable; dev->radio.rxenable = mrf24j40_rxenable;
dev->radio.req_rxenable = mrf24j40_req_rxenable; dev->radio.req_rxenable = mrf24j40_req_rxenable;
dev->radio.beaconstart = mrf24j40_beaconstart;
dev->radio.beaconupdate = mrf24j40_beaconupdate;
dev->radio.beaconstop = mrf24j40_beaconstop;
dev->radio.sfupdate = mrf24j40_sfupdate;
dev->lower = lower; dev->lower = lower;
dev->spi = spi; dev->spi = spi;
dev->rxenabled = false;
mrf24j40_initialize(dev); mrf24j40_initialize(dev);
mrf24j40_setchannel(dev, 11); mrf24j40_setchannel(dev, 11);

View File

@ -118,41 +118,41 @@
#define MRF24J40_SLPCAL1 (MRF24J40_LONGREG_BASE + 0x0A) #define MRF24J40_SLPCAL1 (MRF24J40_LONGREG_BASE + 0x0A)
#define MRF24J40_SLPCAL2 (MRF24J40_LONGREG_BASE + 0x0B) #define MRF24J40_SLPCAL2 (MRF24J40_LONGREG_BASE + 0x0B)
#define MRF24J40_RFSTATE (MRF24J40_LONGREG_BASE + 0x0F) #define MRF24J40_RFSTATE (MRF24J40_LONGREG_BASE + 0x0F)
#define MRF24J40_RSSI 0x80000210 #define MRF24J40_RSSI (MRF24J40_LONGREG_BASE + 0x10)
#define MRF24J40_SLPCON0 0x80000211 #define MRF24J40_SLPCON0 (MRF24J40_LONGREG_BASE + 0x11)
#define MRF24J40_SLPCON1 0x80000220 #define MRF24J40_SLPCON1 (MRF24J40_LONGREG_BASE + 0x20)
#define MRF24J40_WAKETIMEL 0x80000222 #define MRF24J40_WAKETIMEL (MRF24J40_LONGREG_BASE + 0x22)
#define MRF24J40_WAKETIMEH 0x80000223 #define MRF24J40_WAKETIMEH (MRF24J40_LONGREG_BASE + 0x23)
#define MRF24J40_REMCNTL 0x80000224 #define MRF24J40_REMCNTL (MRF24J40_LONGREG_BASE + 0x24)
#define MRF24J40_REMCNTH 0x80000225 #define MRF24J40_REMCNTH (MRF24J40_LONGREG_BASE + 0x25)
#define MRF24J40_MAINCNT0 0x80000226 #define MRF24J40_MAINCNT0 (MRF24J40_LONGREG_BASE + 0x26)
#define MRF24J40_MAINCNT1 0x80000227 #define MRF24J40_MAINCNT1 (MRF24J40_LONGREG_BASE + 0x27)
#define MRF24J40_MAINCNT2 0x80000228 #define MRF24J40_MAINCNT2 (MRF24J40_LONGREG_BASE + 0x28)
#define MRF24J40_MAINCNT3 0x80000229 #define MRF24J40_MAINCNT3 (MRF24J40_LONGREG_BASE + 0x29)
#define MRF24J40_TESTMODE 0x8000022F #define MRF24J40_TESTMODE (MRF24J40_LONGREG_BASE + 0x2F)
#define MRF24J40_ASSOEADR0 0x80000230 #define MRF24J40_ASSOEADR0 (MRF24J40_LONGREG_BASE + 0x30)
#define MRF24J40_ASSOEADR1 0x80000231 #define MRF24J40_ASSOEADR1 (MRF24J40_LONGREG_BASE + 0x31)
#define MRF24J40_ASSOEADR2 0x80000232 #define MRF24J40_ASSOEADR2 (MRF24J40_LONGREG_BASE + 0x32)
#define MRF24J40_ASSOEADR3 0x80000233 #define MRF24J40_ASSOEADR3 (MRF24J40_LONGREG_BASE + 0x33)
#define MRF24J40_ASSOEADR4 0x80000234 #define MRF24J40_ASSOEADR4 (MRF24J40_LONGREG_BASE + 0x34)
#define MRF24J40_ASSOEADR5 0x80000235 #define MRF24J40_ASSOEADR5 (MRF24J40_LONGREG_BASE + 0x35)
#define MRF24J40_ASSOEADR6 0x80000236 #define MRF24J40_ASSOEADR6 (MRF24J40_LONGREG_BASE + 0x36)
#define MRF24J40_ASSOEADR7 0x80000237 #define MRF24J40_ASSOEADR7 (MRF24J40_LONGREG_BASE + 0x37)
#define MRF24J40_ASSOSADR0 0x80000238 #define MRF24J40_ASSOSADR0 (MRF24J40_LONGREG_BASE + 0x38)
#define MRF24J40_ASSOSADR1 0x80000239 #define MRF24J40_ASSOSADR1 (MRF24J40_LONGREG_BASE + 0x39)
#define MRF24J40_UPNONCE0 0x80000240 #define MRF24J40_UPNONCE0 (MRF24J40_LONGREG_BASE + 0x40)
#define MRF24J40_UPNONCE1 0x80000241 #define MRF24J40_UPNONCE1 (MRF24J40_LONGREG_BASE + 0x41)
#define MRF24J40_UPNONCE2 0x80000242 #define MRF24J40_UPNONCE2 (MRF24J40_LONGREG_BASE + 0x42)
#define MRF24J40_UPNONCE3 0x80000243 #define MRF24J40_UPNONCE3 (MRF24J40_LONGREG_BASE + 0x43)
#define MRF24J40_UPNONCE4 0x80000244 #define MRF24J40_UPNONCE4 (MRF24J40_LONGREG_BASE + 0x44)
#define MRF24J40_UPNONCE5 0x80000245 #define MRF24J40_UPNONCE5 (MRF24J40_LONGREG_BASE + 0x45)
#define MRF24J40_UPNONCE6 0x80000246 #define MRF24J40_UPNONCE6 (MRF24J40_LONGREG_BASE + 0x46)
#define MRF24J40_UPNONCE7 0x80000247 #define MRF24J40_UPNONCE7 (MRF24J40_LONGREG_BASE + 0x47)
#define MRF24J40_UPNONCE8 0x80000248 #define MRF24J40_UPNONCE8 (MRF24J40_LONGREG_BASE + 0x48)
#define MRF24J40_UPNONCE9 0x80000249 #define MRF24J40_UPNONCE9 (MRF24J40_LONGREG_BASE + 0x49)
#define MRF24J40_UPNONCE10 0x8000024A #define MRF24J40_UPNONCE10 (MRF24J40_LONGREG_BASE + 0x4A)
#define MRF24J40_UPNONCE11 0x8000024B #define MRF24J40_UPNONCE11 (MRF24J40_LONGREG_BASE + 0x4B)
#define MRF24J40_UPNONCE12 0x8000024C #define MRF24J40_UPNONCE12 (MRF24J40_LONGREG_BASE + 0x4C)
/* INTSTAT bits */ /* INTSTAT bits */
@ -226,4 +226,59 @@
#define MRF24J40_TXSTAT_X_SHIFT 6 #define MRF24J40_TXSTAT_X_SHIFT 6
#define MRF24J40_TXSTAT_X_MASK (3 << MRF24J40_TXSTAT_X_SHIFT) #define MRF24J40_TXSTAT_X_MASK (3 << MRF24J40_TXSTAT_X_SHIFT)
/* TXBCON1 bits */
#define MRF24J40_TXBCON1_RSSINUM 0x30
#define MRF24J40_TXBCON1_NWU_BCN 0x40
#define MRF24J40_TXBCON1_TXBMSK 0x80
/* WAKECON bits */
#define MRF24J40_WAKECON_INTL 0x3F
#define MRF24J40_WAKECON_REGWAKE 0x40
#define MRF24J40_WAKECON_IMMWAKE 0x80
/* WAKECON bits */
#define MRF24J40_WAKECON_INTL 0x3F
#define MRF24J40_WAKECON_REGWAKE 0x40
#define MRF24J40_WAKECON_IMMWAKE 0x80
/* ESLOTG1 bits */
#define MRF24J40_ESLOTG1_CAP 0x0F
#define MRF24J40_ESLOTG1_GTS1 0xF0
/* SLPCAL2 bits */
#define MRF24J40_SLPCAL2_SLPCAL 0x0F
#define MRF24J40_SLPCAL2_SLPCALEN 0x10
#define MRF24J40_SLPCAL2_SLPCALRDY 0x80
/* RFCON7 bits */
#define MRF24J40_RFCON7_SEL_32KHZ 0x40
#define MRF24J40_RFCON7_SEL_100KHZ 0x80
/* SLPACK bits */
#define MRF24J40_SLPACK_WAKECNT0_6 0x7F
#define MRF24J40_SLPACK_SLPACK 0x80
/* RXFLUSH bits */
#define MRF24J40_RXFLUSH_RXFLUSH 0x01
#define MRF24J40_RXFLUSH_BCNONLY 0x02
#define MRF24J40_RXFLUSH_DATAONLY 0x04
#define MRF24J40_RXFLUSH_CMDONLY 0x08
#define MRF24J40_RXFLUSH_WAKEPAD 0x20
#define MRF24J40_RXFLUSH_WAKEPOL 0x40
#define MRF24J40_RXFLUSH_SHIFT_RXFLUSH 0
#define MRF24J40_RXFLUSH_SHIFT_BCNONLY 1
#define MRF24J40_RXFLUSH_SHIFT_DATAONLY 2
#define MRF24J40_RXFLUSH_SHIFT_CMDONLY 3
#define MRF24J40_RXFLUSH_SHIFT_WAKEPAD 5
#define MRF24J40_RXFLUSH_SHIFT_WAKEPOL 6
#endif /* __DRIVERS_WIRELESS_IEEE802154_MRF24J40_H */ #endif /* __DRIVERS_WIRELESS_IEEE802154_MRF24J40_H */

View File

@ -60,6 +60,14 @@
/**************************************************************************** /****************************************************************************
* Pre-Processor Definitions * Pre-Processor Definitions
****************************************************************************/ ****************************************************************************/
/* Configuration ************************************************************/
#if !defined(CONFIG_MAC802154_NPANDESC) || CONFIG_MAC802154_NPANDESC <= 0
# undef CONFIG_MAC802154_NPANDESC
# define CONFIG_MAC802154_NPANDESC 5
#endif
#define MAC802154_NPANDESC CONFIG_MAC802154_NPANDESC
/* IEEE 802.15.4 address macros */ /* IEEE 802.15.4 address macros */
/* Copy a an IEEE 802.15.4 address */ /* Copy a an IEEE 802.15.4 address */
@ -97,8 +105,6 @@
#define IEEE802154_SADDR_BCAST ((uint8_t[]){0xFE,0xFF}) #define IEEE802154_SADDR_BCAST ((uint8_t[]){0xFE,0xFF})
#define IEEE802154_EADDR_UNSPEC ((uint8_t[]){0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}) #define IEEE802154_EADDR_UNSPEC ((uint8_t[]){0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF})
/* Configuration ************************************************************/
/* None at the moment */
/* IEEE 802.15.4 MAC Character Driver IOCTL Commands ************************/ /* IEEE 802.15.4 MAC Character Driver IOCTL Commands ************************/
@ -111,9 +117,9 @@
* - Response * - Response
* - Confirm * - Confirm
* *
* Of these, Request and Response primitives are sent from the next highest layer * Of these, Request and Response primitives are sent from the next highest
* to the MLME. Indication and Confirm primitives are used to notify the next * layer to the MLME. Indication and Confirm primitives are used to notify the
* highest layer of changes or actions that have taken place. * next highest layer of changes or actions that have taken place.
* *
* The MAC802154 character driver exposed here provides IOCTL hooks for all * The MAC802154 character driver exposed here provides IOCTL hooks for all
* Request and Response primitives. * Request and Response primitives.
@ -160,8 +166,53 @@
#define IEEE802154_FRAMECTRL_SHIFT_VERSION 12 /* Source addressing mode, bits 12-13 */ #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_SADDR 14 /* Source addressing mode, bits 14-15 */
/* Superframe Specification field masks, 2 bytes
* Seee IEEE 802.15.4/2011 5.2.2.1.2 page 62
*/
#define IEEE802154_SFSPEC_BEACONORDER 0x000F /* Beacon order, bits 0-3 */
#define IEEE802154_SFSPEC_SFORDER 0x00F0 /* Superframe Order, bit 4-7 */
#define IEEE802154_SFSPEC_FINCAPSLOT 0x0F00 /* Final CAP Slot, bit 8-11 */
#define IEEE802154_SFSPEC_BLE 0x1000 /* Battery Life Ext, bit 12 */
#define IEEE802154_SFSPEC_PANCOORD 0x4000 /* PAN Coordinator, bit 14 */
#define IEEE802154_SFSPEC_ASSOCPERMIT 0x8000 /* Association Permit, bit 15 */
#define IEEE802154_SFSPEC_SHIFT_BEACONORDER 0 /* Beacon order, bits 0-3 */
#define IEEE802154_SFSPEC_SHIFT_SFORDER 4 /* Superframe order, bit 4-7 */
#define IEEE802154_SFSPEC_SHIFT_FINCAPSLOT 8 /* Final CAP Slot, bit 8-11 */
#define IEEE802154_SFSPEC_SHIFT_BLE 12 /* Battery Life Ext, bit 12 */
#define IEEE802154_SFSPEC_SHIFT_PANCOORD 14 /* PAN Coordinator, bit 14 */
#define IEEE802154_SFSPEC_SHIFT_ASSOCPERMIT 15 /* Association Permit, bit 15 */
/* GTS Specification field masks, 1 byte
* Seee IEEE 802.15.4/2011 5.2.2.1.3 page 63
*/
#define IEEE802154_GTSSPEC_DESCCOUNT 0x07 /* GTS Desc. count, bits 0-2 */
#define IEEE802154_GTSSPEC_PERMIT 0x80 /* GTS Desc. count, bit 7 */
#define IEEE802154_GTSSPEC_SHIFT_DESCCOUNT 0 /* GTS Desc. count, bits 0-2 */
#define IEEE802154_GTSSPEC_SHIFT_PERMIT 7 /* GTS Desc. count, bit 7 */
/* GTS Directions field masks, 1 byte
* Seee IEEE 802.15.4/2011 5.2.2.1.3 page 63
*/
#define IEEE802154_GTSDIR_MASK 0x7F /* GTS Directions Mask, bits 0-6 */
#define IEEE802154_GTSDIR_SHIFT_MASK 0 /* GTS Directions Mask, bits 0-6 */
/* Pending address specifications field masks, 1 byte
* See IEEE 802.15.4/2011 5.2.2.1.6 page 64
*/
#define IEEE802154_PENDADDR_NSADDR 0x07 /* # of short addresses, bits 0-2 */
#define IEEE802154_PENDADDR_NEADDR 0x70 /* # of extended addresses, bits 4-6 */
#define IEEE802154_PENDADDR_SHIFT_NSADDR 0 /* # of short addresses, bits 0-2 */
#define IEEE802154_PENDADDR_SHIFT_NEADDR 4 /* # of extended addresses, bits 4-6 */
/* Capability Information Bitfield /* Capability Information Bitfield
*
*/ */
#define IEEE802154_CAPABILITY_DEVTYPE 0x02 #define IEEE802154_CAPABILITY_DEVTYPE 0x02
@ -203,7 +254,6 @@
#define IEEE802154_MAX_MPDU_UNSEC_OVERHEAD \ #define IEEE802154_MAX_MPDU_UNSEC_OVERHEAD \
(IEEE802154_MAX_UNSEC_MHR_OVERHEAD + IEEE802154_MFR_LENGTH) (IEEE802154_MAX_UNSEC_MHR_OVERHEAD + IEEE802154_MFR_LENGTH)
#define IEEE802154_MAX_SAFE_MAC_PAYLOAD_SIZE \ #define IEEE802154_MAX_SAFE_MAC_PAYLOAD_SIZE \
(IEEE802154_MAX_PHY_PACKET_SIZE - IEEE802154_MAX_MPDU_UNSEC_OVERHEAD) (IEEE802154_MAX_PHY_PACKET_SIZE - IEEE802154_MAX_MPDU_UNSEC_OVERHEAD)
@ -220,7 +270,6 @@
#define MAX_ORPHAN_ADDR 32 /* REVISIT */ #define MAX_ORPHAN_ADDR 32 /* REVISIT */
/**************************************************************************** /****************************************************************************
* Public Types * Public Types
****************************************************************************/ ****************************************************************************/
@ -265,6 +314,7 @@ enum ieee802154_status_e
IEEE802154_STATUS_TX_ACTIVE, IEEE802154_STATUS_TX_ACTIVE,
IEEE802154_STATUS_UNAVAILABLE_KEY, IEEE802154_STATUS_UNAVAILABLE_KEY,
IEEE802154_STATUS_UNSUPPORTED_ATTRIBUTE, IEEE802154_STATUS_UNSUPPORTED_ATTRIBUTE,
IEEE802154_STATUS_LIMITREACHED,
}; };
static const char *IEEE802154_STATUS_STRING[] = static const char *IEEE802154_STATUS_STRING[] =
@ -292,6 +342,7 @@ static const char *IEEE802154_STATUS_STRING[] =
"Tx active", "Tx active",
"Unavailable key", "Unavailable key",
"Unsupported attribute", "Unsupported attribute",
"Limit reached",
}; };
/* IEEE 802.15.4 PHY/MAC PIB attributes IDs */ /* IEEE 802.15.4 PHY/MAC PIB attributes IDs */
@ -300,7 +351,7 @@ enum ieee802154_attr_e
{ {
/* PHY PIB Attributes */ /* PHY PIB Attributes */
IEEE802154_ATTR_PHY_CURRENT_CHANNEL = 0x00, IEEE802154_ATTR_PHY_CHAN = 0x00,
IEEE802154_ATTR_PHY_CHANNELS_SUPPORTED, IEEE802154_ATTR_PHY_CHANNELS_SUPPORTED,
IEEE802154_ATTR_PHY_TX_POWER_TOLERANCE, IEEE802154_ATTR_PHY_TX_POWER_TOLERANCE,
IEEE802154_ATTR_PHY_TX_POWER, IEEE802154_ATTR_PHY_TX_POWER,
@ -340,7 +391,7 @@ enum ieee802154_attr_e
/* MAC PIB Attributes */ /* MAC PIB Attributes */
IEEE802154_ATTR_MAC_EXTENDED_ADDR = 0x40, IEEE802154_ATTR_MAC_EADDR = 0x40,
IEEE802154_ATTR_MAC_ACK_WAIT_DUR, IEEE802154_ATTR_MAC_ACK_WAIT_DUR,
IEEE802154_ATTR_MAC_ASSOCIATED_PANCOORD, IEEE802154_ATTR_MAC_ASSOCIATED_PANCOORD,
IEEE802154_ATTR_MAC_ASSOCIATION_PERMIT, IEEE802154_ATTR_MAC_ASSOCIATION_PERMIT,
@ -352,8 +403,8 @@ enum ieee802154_attr_e
IEEE802154_ATTR_MAC_BEACON_ORDER, IEEE802154_ATTR_MAC_BEACON_ORDER,
IEEE802154_ATTR_MAC_BEACON_TX_TIME, IEEE802154_ATTR_MAC_BEACON_TX_TIME,
IEEE802154_ATTR_MAC_BSN, IEEE802154_ATTR_MAC_BSN,
IEEE802154_ATTR_MAC_COORD_EXT_ADDR, IEEE802154_ATTR_MAC_COORD_EADDR,
IEEE802154_ATTR_MAC_COORD_SHORT_ADDR, IEEE802154_ATTR_MAC_COORD_SADDR,
IEEE802154_ATTR_MAC_DSN, IEEE802154_ATTR_MAC_DSN,
IEEE802154_ATTR_MAC_GTS_PERMIT, IEEE802154_ATTR_MAC_GTS_PERMIT,
IEEE802154_ATTR_MAC_MAX_BE, IEEE802154_ATTR_MAC_MAX_BE,
@ -369,7 +420,7 @@ enum ieee802154_attr_e
IEEE802154_ATTR_MAC_RESPONSE_WAIT_TIME, IEEE802154_ATTR_MAC_RESPONSE_WAIT_TIME,
IEEE802154_ATTR_MAC_RX_ON_WHEN_IDLE, IEEE802154_ATTR_MAC_RX_ON_WHEN_IDLE,
IEEE802154_ATTR_MAC_SECURITY_ENABLED, IEEE802154_ATTR_MAC_SECURITY_ENABLED,
IEEE802154_ATTR_MAC_SHORT_ADDRESS, IEEE802154_ATTR_MAC_SADDR,
IEEE802154_ATTR_MAC_SUPERFRAME_ORDER, IEEE802154_ATTR_MAC_SUPERFRAME_ORDER,
IEEE802154_ATTR_MAC_SYNC_SYMBOL_OFFSET, IEEE802154_ATTR_MAC_SYNC_SYMBOL_OFFSET,
IEEE802154_PIB_MAC_TIMESTAMP_SUPPORT, IEEE802154_PIB_MAC_TIMESTAMP_SUPPORT,
@ -511,31 +562,31 @@ struct ieee802154_capability_info_s
* 0=otherwise */ * 0=otherwise */
}; };
struct ieee802154_superframe_spec_s struct ieee802154_superframespec_s
{ {
uint16_t beacon_order : 4; /* Transmission interval of beacon */ uint16_t beaconorder : 4; /* Transmission interval of beacon */
uint16_t superframe_order : 4; /* Length of superframe */ uint16_t sforder : 4; /* Length of active portion of superframe */
uint16_t final_cap_slot : 4; /* Last slot utilized by CAP */ uint16_t final_capslot : 4; /* Last slot utilized by CAP */
uint16_t ble : 1; /* Battery Life Extension (BLE) */ uint16_t ble : 1; /* Battery Life Extension (BLE) */
uint16_t reserved : 1; /* Reserved bit */ uint16_t reserved : 1; /* Reserved bit */
uint16_t pan_coordinator : 1; /* 1 if beacon sent by pan coordinator */ uint16_t pancoord : 1; /* 1 if beacon sent by pan coordinator */
uint16_t assoc_permit : 1; /* 1 if coordinator is accepting associaton */ uint16_t assocpermit : 1; /* 1 if coordinator is accepting associaton */
}; };
struct ieee802154_pan_desc_s struct ieee802154_pandesc_s
{ {
/* The coordinator address of the received beacon frame */ /* The coordinator address of the received beacon frame */
struct ieee802154_addr_s coord_addr; struct ieee802154_addr_s coordaddr;
uint8_t channel; /* current channel occupied by the network */ uint8_t chan; /* current channel occupied by the network */
uint8_t channel_page; /* current channel page occupied by the network */ uint8_t chpage; /* current channel page occupied by the network */
/* The superframe specifications received in the beacon frame */ /* The superframe specifications received in the beacon frame */
struct ieee802154_superframe_spec_s superframe_spec; struct ieee802154_superframespec_s sfspec;
uint8_t gts_permit; /* 0=No GTS requests allowed uint8_t gtspermit; /* 0=No GTS requests allowed
* 1=GTS request allowed */ * 1=GTS request allowed */
uint8_t lqi; /* Link Quality Indication of the beacon */ uint8_t lqi; /* Link Quality Indication of the beacon */
uint32_t timestamp; /* Time at which the beacon frame was received uint32_t timestamp; /* Time at which the beacon frame was received
@ -574,13 +625,13 @@ union ieee802154_macattr_u
uint8_t saddr[IEEE802154_SADDRSIZE]; uint8_t saddr[IEEE802154_SADDRSIZE];
uint8_t panid[IEEE802154_PANIDSIZE]; uint8_t panid[IEEE802154_PANIDSIZE];
uint8_t coord_eaddr[IEEE802154_EADDRSIZE]; uint8_t coordeaddr[IEEE802154_EADDRSIZE];
uint8_t coord_saddr[IEEE802154_SADDRSIZE]; uint8_t coordsaddr[IEEE802154_SADDRSIZE];
enum ieee802154_devmode_e devmode; enum ieee802154_devmode_e devmode;
bool is_assoc; bool is_assoc;
bool assoc_permit; bool assocpermit;
bool auto_req; bool auto_req;
bool batt_life_ext; bool batt_life_ext;
bool gts_permit; bool gts_permit;
@ -611,7 +662,7 @@ union ieee802154_macattr_u
uint8_t beacon_order; uint8_t beacon_order;
uint32_t beacon_tx_time : 24; uint32_t beacon_tx_time : 24;
uint8_t superframe_order; uint8_t superframeorder;
uint8_t bsn; uint8_t bsn;
uint8_t dsn; uint8_t dsn;
@ -619,7 +670,7 @@ union ieee802154_macattr_u
union ieee802154_phyattr_u union ieee802154_phyattr_u
{ {
uint8_t channel; uint8_t chan;
int32_t txpwr; int32_t txpwr;
uint32_t symdur_picosec; uint32_t symdur_picosec;
/* TODO: Fill this out as we implement supported get/set commands */ /* TODO: Fill this out as we implement supported get/set commands */
@ -845,8 +896,38 @@ struct ieee802154_purge_req_s
struct ieee802154_assoc_req_s struct ieee802154_assoc_req_s
{ {
uint8_t chnum; /* Channel number to attempt association */ uint8_t chan; /* Channel number to attempt association */
uint8_t chpage; /* Channel page to attempt association */ uint8_t chpage; /* Channel page to attempt association */
/* TODO:
* This is a non-standard field. I believe there is a catch 22 in the
* standard and until I can figure it out, I'm adding this boolean to let the
* application tell the MAC whether it is trying to assocaite with a beacon
* enabled PAN or non-beacon enabled PAN. If it is beacon-enabled, the MAC
* will track the beacon first before transmitting the association. This can
* take some time depending on the beacon interval. If the PAN is non-beacon
* enabled, the association request is sent immediately via CSMA.
*
* The catch 22: The standard outlines the procedure for associating: reset
* the MAC, scan to find PAN's and pass coordinator address info to
* application, application calls associate passing address info of
* coordinator. Which sounds good. The problem is that the primitive has no
* field for determining if the PAN we are trying to join is beacon enabled
* or not. Which means we don't know whether to tranmsit immediately or try
* to track the beacon. The standard does say that ALL command frames should
* be sent during the Contention Access Period (CAP), but how could you send
* it at the rigth tiem, if you are not tracking the beacon. What's worse is
* in the association section, it says if you are tracking the beacon, to
* send the association request during the CAP. But how can you track the
* beacon if you are not associated. Normally tracking the beacon would be
* triggered by the SYNC.request primitive. But from my understanding that
* primitive is intended to be used AFTER association since it requires the
* MAC to already have a coordinator address and PAN ID so that it can track
* the beacon frames properly. Which, of course, how could the MAC have that
* info if it is not associated.
*/
bool beacon;
/* Coordinator Address with which to associate */ /* Coordinator Address with which to associate */
@ -1037,7 +1118,7 @@ struct ieee802154_beaconnotify_ind_s
/* PAN descriptor for the received beacon */ /* PAN descriptor for the received beacon */
struct ieee802154_pan_desc_s pan_desc; struct ieee802154_pandesc_s pandesc;
/* Beacon pending addresses */ /* Beacon pending addresses */
@ -1238,20 +1319,17 @@ struct ieee802154_scan_req_s
{ {
enum ieee802154_scantype_e type; enum ieee802154_scantype_e type;
uint8_t duration; uint8_t duration;
uint8_t ch_page; uint8_t chpage;
uint8_t channels[15];
uint8_t numchan;
#ifdef CONFIG_IEEE802154_SECURITY #ifdef CONFIG_IEEE802154_SECURITY
/* Security information if enabled */ /* Security information if enabled */
struct ieee802154_security_s security; struct ieee802154_security_s security;
#endif #endif
uint8_t channels[1];
}; };
#define SIZEOF_IEEE802154_SCAN_REQ_S(n) \
(sizeof(struct ieee802154_scan_req_s) + (n) - 1)
/***************************************************************************** /*****************************************************************************
* Primitive: MLME-SCAN.confirm * Primitive: MLME-SCAN.confirm
* *
@ -1264,10 +1342,12 @@ struct ieee802154_scan_conf_s
{ {
enum ieee802154_status_e status; enum ieee802154_status_e status;
enum ieee802154_scantype_e type; enum ieee802154_scantype_e type;
uint8_t ch_page; uint8_t chpage;
uint8_t num_channels; uint8_t unscanned[15];
uint8_t numunscanned;
/* TODO: Figure out how to handle missing primitive semantics. See standard. */ uint8_t numdesc;
struct ieee802154_pandesc_s pandescs[MAC802154_NPANDESC];
uint8_t edlist[MAC802154_NPANDESC];
}; };
/***************************************************************************** /*****************************************************************************
@ -1318,7 +1398,7 @@ struct ieee802154_set_req_s
struct ieee802154_start_req_s struct ieee802154_start_req_s
{ {
uint8_t panid[IEEE802154_PANIDSIZE]; uint8_t panid[IEEE802154_PANIDSIZE];
uint8_t chnum; uint8_t chan;
uint8_t chpage; uint8_t chpage;
uint32_t starttime : 24; uint32_t starttime : 24;

View File

@ -89,6 +89,18 @@ struct ieee802154_txdesc_s
/* TODO: Add slotting information for GTS transactions */ /* TODO: Add slotting information for GTS transactions */
}; };
struct ieee802154_beaconframe_s
{
uint8_t bf_data[IEEE802154_MAX_PHY_PACKET_SIZE];
uint8_t bf_len;
uint8_t bf_offset;
};
enum ieee802154_sfevent_e
{
IEEE802154_SFEVENT_ENDOFACTIVE,
};
/* IEEE802.15.4 Radio Interface Operations **********************************/ /* IEEE802.15.4 Radio Interface Operations **********************************/
struct ieee802154_radiocb_s struct ieee802154_radiocb_s
@ -99,6 +111,8 @@ struct ieee802154_radiocb_s
FAR struct ieee802154_txdesc_s *tx_desc); FAR struct ieee802154_txdesc_s *tx_desc);
CODE void (*rxframe) (FAR const struct ieee802154_radiocb_s *radiocb, CODE void (*rxframe) (FAR const struct ieee802154_radiocb_s *radiocb,
FAR struct ieee802154_data_ind_s *ind); FAR struct ieee802154_data_ind_s *ind);
CODE void (*sfevent) (FAR const struct ieee802154_radiocb_s *radiocb,
enum ieee802154_sfevent_e sfevent);
}; };
struct ieee802154_radio_s struct ieee802154_radio_s
@ -119,6 +133,14 @@ struct ieee802154_radio_s
CODE int (*rxenable) (FAR struct ieee802154_radio_s *radio, bool enable); CODE int (*rxenable) (FAR struct ieee802154_radio_s *radio, bool enable);
CODE int (*req_rxenable)(FAR struct ieee802154_radio_s *radio, CODE int (*req_rxenable)(FAR struct ieee802154_radio_s *radio,
FAR struct ieee802154_rxenable_req_s *req); FAR struct ieee802154_rxenable_req_s *req);
CODE int (*beaconstart)(FAR struct ieee802154_radio_s *radio,
FAR const struct ieee802154_superframespec_s *sfspec,
FAR struct ieee802154_beaconframe_s *beacon);
CODE int (*beaconupdate)(FAR struct ieee802154_radio_s *radio,
FAR struct ieee802154_beaconframe_s *beacon);
CODE int (*beaconstop)(FAR struct ieee802154_radio_s *radio);
CODE int (*sfupdate)(FAR struct ieee802154_radio_s *radio,
FAR const struct ieee802154_superframespec_s *sfspec);
}; };
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -73,6 +73,16 @@ config MAC802154_NNOTIF
receiver with an allocated notification structure indicating the event. The receiver with an allocated notification structure indicating the event. The
events are primitives such as Association Indication etc. events are primitives such as Association Indication etc.
config MAC802154_NPANDESC
int "Number of PAN descriptors"
default 5
---help---
Configured number of PAN descriptors Default: 5
When performing a scan to find a suitable PAN, the MAC must store
information for all unique beacons received. This is the number of unique
descriptors that can be held before the scan cancels with LIMIT_REACHED.
config IEEE802154_IND_PREALLOC config IEEE802154_IND_PREALLOC
int "Number of pre-allocated meta-data structures" int "Number of pre-allocated meta-data structures"
default 20 default 20

View File

@ -0,0 +1,8 @@
This will eventually hold some general documentation for the IEEE 802.15.4
MAC implementation.
NOTE: Throughout the code, excerpts from the standard are quoted as to make
the code thoroughly readable. I have tried, to always put a reference [1] and
page number. Below is the references that correspond with the reference number
[1]

View File

@ -59,6 +59,7 @@
#include "mac802154_notif.h" #include "mac802154_notif.h"
#include "mac802154_internal.h" #include "mac802154_internal.h"
#include "mac802154_assoc.h" #include "mac802154_assoc.h"
#include "mac802154_scan.h"
#include "mac802154_data.h" #include "mac802154_data.h"
#include "mac802154_poll.h" #include "mac802154_poll.h"
@ -86,10 +87,8 @@ static void mac802154_rxframe(FAR const struct ieee802154_radiocb_s *radiocb,
FAR struct ieee802154_data_ind_s *ind); FAR struct ieee802154_data_ind_s *ind);
static void mac802154_rxframe_worker(FAR void *arg); static void mac802154_rxframe_worker(FAR void *arg);
static void mac802154_rx_datareq(FAR struct ieee802154_privmac_s *priv, static void mac802154_sfevent(FAR const struct ieee802154_radiocb_s *radiocb,
FAR struct ieee802154_data_ind_s *ind); enum ieee802154_sfevent_e sfevent);
static void mac802154_rx_dataframe(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_data_ind_s *ind);
static void mac802154_purge_worker(FAR void *arg); static void mac802154_purge_worker(FAR void *arg);
@ -100,6 +99,13 @@ static void mac802154_timeout_expiry(int argc, wdparm_t arg, ...);
static uint32_t mac802154_symtoticks(FAR struct ieee802154_privmac_s *priv, static uint32_t mac802154_symtoticks(FAR struct ieee802154_privmac_s *priv,
uint32_t symbols); uint32_t symbols);
static void mac802154_rxdatareq(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_data_ind_s *ind);
static void mac802154_rxdataframe(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_data_ind_s *ind);
static void mac802154_rxbeaconframe(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_data_ind_s *ind);
/**************************************************************************** /****************************************************************************
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
@ -353,6 +359,163 @@ void mac802154_createdatareq(FAR struct ieee802154_privmac_s *priv,
txdesc->frame = iob; txdesc->frame = iob;
} }
/****************************************************************************
* Name: mac802154_updatebeacon
*
* Description:
* This function is called in the following scenarios:
* - The MAC receives a START.request primitive
* - Upon receiving the IEEE802154_SFEVENT_ENDOFACTIVE event from the
* radio layer, the MAC checks the bf_update flag and if set calls this
* function. The bf_update flag is set when various attributes that
* effect the beacon are updated.
*
* Internal function used by various parts of the MAC layer. This function
* uses the various MAC attributes to update the beacon frame. It loads the
* inactive beacon frame structure and then notifies the radio layer of the
* new frame. the provided tx descriptor in the indirect list and manages the
* scheduling for purging the transaction if it does not get extracted in
* time.
*
* Assumptions:
* Called with the MAC locked
*
****************************************************************************/
void mac802154_updatebeacon(FAR struct ieee802154_privmac_s *priv)
{
FAR struct ieee802154_txdesc_s *txdesc;
uint8_t pendaddrspec_ind;
uint8_t pendeaddr = 0;
uint8_t pendsaddr = 0;
/* Switch the buffer */
priv->bf_ind = !priv->bf_ind;
/* Get a local reference to the beacon frame */
FAR struct ieee802154_beaconframe_s *beacon = &priv->beaconframe[priv->bf_ind];
/* Clear the frame control fields */
beacon->bf_data[0] = 0;
beacon->bf_data[1] = 0;
beacon->bf_len = 2;
IEEE802154_SETFTYPE(beacon->bf_data, 0, IEEE802154_FRAME_BEACON);
/* Check if there is a broadcast message pending, if there is, we must set
* the frame pending bit to 1.
*/
/* TODO: handle broadcast frame */
DEBUGASSERT(priv->addr.mode != IEEE802154_ADDRMODE_NONE);
IEEE802154_SETDADDRMODE(beacon->bf_data, 0, IEEE802154_ADDRMODE_NONE);
IEEE802154_SETSADDRMODE(beacon->bf_data, 0, priv->addr.mode);
IEEE802154_SETVERSION(beacon->bf_data, 0, 1);
/* Copy in and increment the beacon sequence number */
beacon->bf_data[beacon->bf_len++] = priv->bsn++;
IEEE802154_PANIDCOPY(&beacon->bf_data[beacon->bf_len], priv->addr.panid);
beacon->bf_len += IEEE802154_PANIDSIZE;
if (priv->addr.mode == IEEE802154_ADDRMODE_SHORT)
{
IEEE802154_SADDRCOPY(&beacon->bf_data[beacon->bf_len], priv->addr.saddr);
beacon->bf_len += IEEE802154_SADDRSIZE;
}
else
{
IEEE802154_EADDRCOPY(&beacon->bf_data[beacon->bf_len], priv->addr.eaddr);
beacon->bf_len += IEEE802154_EADDRSIZE;
}
/* Clear the superframe specification, then set the appropriate bits */
beacon->bf_data[beacon->bf_len] = 0;
beacon->bf_data[beacon->bf_len + 1] = 0;
IEEE802154_SETBEACONORDER(beacon->bf_data, beacon->bf_len,
priv->sfspec.beaconorder);
IEEE802154_SETSFORDER(beacon->bf_data, beacon->bf_len,
priv->sfspec.sforder);
IEEE802154_SETFINCAPSLOT(beacon->bf_data, beacon->bf_len,
priv->sfspec.final_capslot);
if (priv->sfspec.ble)
{
IEEE802154_SETBLE(beacon->bf_data, beacon->bf_len);
}
if (priv->sfspec.pancoord)
{
IEEE802154_SETPANCOORD(beacon->bf_data, beacon->bf_len);
}
if (priv->sfspec.assocpermit)
{
IEEE802154_SETASSOCPERMIT(beacon->bf_data, beacon->bf_len);
}
beacon->bf_len += 2;
/* TODO: Handle GTS properly, for now, we just set the descriptor count to
* zero and specify that we do not permit GTS requests */
beacon->bf_data[beacon->bf_len++] = 0;
/* TODO: Add GTS List here */
/* Skip the pending address specification field for now */
pendaddrspec_ind = beacon->bf_len++;
txdesc = (FAR struct ieee802154_txdesc_s *)sq_peek(&priv->indirect_queue);
while(txdesc != NULL)
{
if (txdesc->destaddr.mode == IEEE802154_ADDRMODE_SHORT)
{
pendsaddr++;
IEEE802154_SADDRCOPY(&beacon->bf_data[beacon->bf_len], txdesc->destaddr.saddr);
beacon->bf_len += IEEE802154_SADDRSIZE;
}
else if (txdesc->destaddr.mode == IEEE802154_ADDRMODE_EXTENDED)
{
pendeaddr++;
IEEE802154_EADDRCOPY(&beacon->bf_data[beacon->bf_len], txdesc->destaddr.eaddr);
beacon->bf_len += IEEE802154_EADDRSIZE;
}
/* Check if we are up to 7 addresses yet */
if ((pendsaddr + pendeaddr) == 7)
{
break;
}
/* Get the next pending indirect transation */
txdesc = (FAR struct ieee802154_txdesc_s *)sq_next((FAR sq_entry_t *)txdesc);
}
/* At this point, we know how many of each transaction we have, we can setup
* the Pending Address Specification field
*/
beacon->bf_data[pendaddrspec_ind] = (pendsaddr & 0x07) | ((pendeaddr << 4) & 0x70);
/* Copy in the beacon payload */
memcpy(&beacon->bf_data[beacon->bf_len], priv->beaconpayload,
priv->beaconpayloadlength);
beacon->bf_len += priv->beaconpayloadlength;
priv->beaconupdate = false;
}
/**************************************************************************** /****************************************************************************
* Name: mac802154_setupindirect * Name: mac802154_setupindirect
* *
@ -386,10 +549,10 @@ void mac802154_setupindirect(FAR struct ieee802154_privmac_s *priv,
* aBaseSuperframeDuration. [1] pg. 129 * aBaseSuperframeDuration. [1] pg. 129
*/ */
if (priv->beaconorder < 15) if (priv->sfspec.beaconorder < 15)
{ {
symbols = priv->trans_persisttime * symbols = priv->trans_persisttime *
(IEEE802154_BASE_SUPERFRAME_DURATION * (1 << priv->beaconorder)); (IEEE802154_BASE_SUPERFRAME_DURATION * (1 << priv->sfspec.beaconorder));
} }
else else
{ {
@ -400,6 +563,13 @@ void mac802154_setupindirect(FAR struct ieee802154_privmac_s *priv,
txdesc->purge_time = clock_systimer() + ticks; txdesc->purge_time = clock_systimer() + ticks;
/* Make sure the beacon gets updated */
if (priv->sfspec.beaconorder < 15)
{
priv->beaconupdate = true;
}
/* Check to see if the purge indirect timer is scheduled. If it is, when the /* Check to see if the purge indirect timer is scheduled. If it is, when the
* timer fires, it will schedule the next purge timer event. Inherently, the * timer fires, it will schedule the next purge timer event. Inherently, the
* queue will be in order of which transaction needs to be purged next. * queue will be in order of which transaction needs to be purged next.
@ -469,6 +639,7 @@ static void mac802154_purge_worker(FAR void *arg)
((FAR struct mac802154_notif_s *)txdesc->conf)->flink = priv->notif_free; ((FAR struct mac802154_notif_s *)txdesc->conf)->flink = priv->notif_free;
priv->notif_free = ((FAR struct mac802154_notif_s *)txdesc->conf); priv->notif_free = ((FAR struct mac802154_notif_s *)txdesc->conf);
mac802154_txdesc_free(priv, txdesc); mac802154_txdesc_free(priv, txdesc);
priv->beaconupdate = true;
wlinfo("Indirect TX purged"); wlinfo("Indirect TX purged");
} }
@ -888,7 +1059,7 @@ static void mac802154_rxframe_worker(FAR void *arg)
{ {
case IEEE802154_FRAME_DATA: case IEEE802154_FRAME_DATA:
{ {
mac802154_rx_dataframe(priv, ind); mac802154_rxdataframe(priv, ind);
} }
break; break;
@ -904,33 +1075,43 @@ static void mac802154_rxframe_worker(FAR void *arg)
switch (cmdtype) switch (cmdtype)
{ {
case IEEE802154_CMD_ASSOC_REQ: case IEEE802154_CMD_ASSOC_REQ:
wlinfo("Assoc request received\n");
mac802154_rx_assocreq(priv, ind); mac802154_rx_assocreq(priv, ind);
break; break;
case IEEE802154_CMD_ASSOC_RESP: case IEEE802154_CMD_ASSOC_RESP:
wlinfo("Assoc response received\n");
mac802154_rx_assocresp(priv, ind); mac802154_rx_assocresp(priv, ind);
break; break;
case IEEE802154_CMD_DISASSOC_NOT: case IEEE802154_CMD_DISASSOC_NOT:
wlinfo("Disassoc notif received\n");
break; break;
case IEEE802154_CMD_DATA_REQ: case IEEE802154_CMD_DATA_REQ:
mac802154_rx_datareq(priv, ind); wlinfo("Data request received\n");
mac802154_rxdatareq(priv, ind);
break; break;
case IEEE802154_CMD_PANID_CONF_NOT: case IEEE802154_CMD_PANID_CONF_NOT:
wlinfo("PAN ID Conflict notif received\n");
break; break;
case IEEE802154_CMD_ORPHAN_NOT: case IEEE802154_CMD_ORPHAN_NOT:
wlinfo("Orphan notif received\n");
break;
break; break;
case IEEE802154_CMD_BEACON_REQ: case IEEE802154_CMD_BEACON_REQ:
wlinfo("Beacon request received\n");
break; break;
case IEEE802154_CMD_COORD_REALIGN: case IEEE802154_CMD_COORD_REALIGN:
wlinfo("Coord realign received\n");
break; break;
case IEEE802154_CMD_GTS_REQ: case IEEE802154_CMD_GTS_REQ:
wlinfo("GTS request received\n");
break; break;
} }
@ -942,15 +1123,9 @@ static void mac802154_rxframe_worker(FAR void *arg)
case IEEE802154_FRAME_BEACON: case IEEE802154_FRAME_BEACON:
{ {
/* TODO: Add logic here to handle extracting association response from wlinfo("Beacon frame received\n");
* coordinator if beacon tracking was enabled during the Association mac802154_rxbeaconframe(priv, ind);
* operation. ieee802154_ind_free(ind);
*
* mac802154_txdesc_alloc(priv, &respdec, false);
* mac802154_createdatareq(priv, &req->coordaddr,
* IEEE802154_ADDRMODE_EXTENDED, respdesc);
* sq_addlast((FAR sq_entry_t *)respdesc, &priv->csma_queue);
*/
} }
break; break;
@ -969,7 +1144,7 @@ static void mac802154_rxframe_worker(FAR void *arg)
} }
/**************************************************************************** /****************************************************************************
* Name: mac802154_rx_dataframe * Name: mac802154_rxdataframe
* *
* Description: * Description:
* Function called from the generic RX Frame worker to parse and handle the * Function called from the generic RX Frame worker to parse and handle the
@ -977,8 +1152,8 @@ static void mac802154_rxframe_worker(FAR void *arg)
* *
****************************************************************************/ ****************************************************************************/
static void mac802154_rx_dataframe(FAR struct ieee802154_privmac_s *priv, static void mac802154_rxdataframe(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_data_ind_s *ind) FAR struct ieee802154_data_ind_s *ind)
{ {
FAR struct ieee802154_notif_s *notif; FAR struct ieee802154_notif_s *notif;
@ -1158,7 +1333,7 @@ notify_without_lock:
} }
/**************************************************************************** /****************************************************************************
* Name: mac802154_rx_datareq * Name: mac802154_rxdatareq
* *
* Description: * Description:
* Function called from the generic RX Frame worker to parse and handle the * Function called from the generic RX Frame worker to parse and handle the
@ -1166,7 +1341,7 @@ notify_without_lock:
* *
****************************************************************************/ ****************************************************************************/
static void mac802154_rx_datareq(FAR struct ieee802154_privmac_s *priv, static void mac802154_rxdatareq(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_data_ind_s *ind) FAR struct ieee802154_data_ind_s *ind)
{ {
FAR struct ieee802154_txdesc_s *txdesc; FAR struct ieee802154_txdesc_s *txdesc;
@ -1189,12 +1364,7 @@ static void mac802154_rx_datareq(FAR struct ieee802154_privmac_s *priv,
txdesc = (FAR struct ieee802154_txdesc_s *)sq_peek(&priv->indirect_queue); txdesc = (FAR struct ieee802154_txdesc_s *)sq_peek(&priv->indirect_queue);
if (txdesc == NULL) while(txdesc != NULL)
{
goto no_data;
}
do
{ {
if (txdesc->destaddr.mode == ind->src.mode) if (txdesc->destaddr.mode == ind->src.mode)
{ {
@ -1209,7 +1379,9 @@ static void mac802154_rx_datareq(FAR struct ieee802154_privmac_s *priv,
/* The addresses match, send the transaction immediately */ /* The addresses match, send the transaction immediately */
priv->radio->txdelayed(priv->radio, txdesc, 0); priv->radio->txdelayed(priv->radio, txdesc, 0);
break; priv->beaconupdate = true;
mac802154_givesem(&priv->exclsem);
return;
} }
} }
else if (txdesc->destaddr.mode == IEEE802154_ADDRMODE_EXTENDED) else if (txdesc->destaddr.mode == IEEE802154_ADDRMODE_EXTENDED)
@ -1224,7 +1396,9 @@ static void mac802154_rx_datareq(FAR struct ieee802154_privmac_s *priv,
/* The addresses match, send the transaction immediately */ /* The addresses match, send the transaction immediately */
priv->radio->txdelayed(priv->radio, txdesc, 0); priv->radio->txdelayed(priv->radio, txdesc, 0);
break; priv->beaconupdate = true;
mac802154_givesem(&priv->exclsem);
return;
} }
} }
else else
@ -1234,18 +1408,7 @@ static void mac802154_rx_datareq(FAR struct ieee802154_privmac_s *priv,
} }
txdesc = (FAR struct ieee802154_txdesc_s *)sq_next((FAR sq_entry_t *)txdesc); txdesc = (FAR struct ieee802154_txdesc_s *)sq_next((FAR sq_entry_t *)txdesc);
if (txdesc == NULL)
{
goto no_data;
}
} }
while (1);
mac802154_givesem(&priv->exclsem);
return;
no_data:
/* If there is no data frame pending for the requesting device, the coordinator /* If there is no data frame pending for the requesting device, the coordinator
* shall send a data frame without requesting acknowledgment to the device * shall send a data frame without requesting acknowledgment to the device
@ -1345,6 +1508,217 @@ no_data:
priv->radio->txdelayed(priv->radio, txdesc, 0); priv->radio->txdelayed(priv->radio, txdesc, 0);
} }
static void mac802154_sfevent(FAR const struct ieee802154_radiocb_s *radiocb,
enum ieee802154_sfevent_e sfevent)
{
FAR struct mac802154_radiocb_s *cb =
(FAR struct mac802154_radiocb_s *)radiocb;
FAR struct ieee802154_privmac_s *priv;
DEBUGASSERT(cb != NULL && cb->priv != NULL);
priv = cb->priv;
/* Get exclusive access to the driver structure. We don't care about any
* signals so if we see one, just go back to trying to get access again.
*/
mac802154_takesem(&priv->exclsem, false);
/* Check if there is any reason to update the beacon */
if (priv->beaconupdate)
{
mac802154_updatebeacon(priv);
priv->radio->beaconupdate(priv->radio, &priv->beaconframe[priv->bf_ind]);
}
mac802154_givesem(&priv->exclsem);
}
/****************************************************************************
* Name: mac802154_rxbeaconframe
*
* Description:
* Function called from the generic RX Frame worker to parse and handle the
* reception of a beacon frame.
*
****************************************************************************/
static void mac802154_rxbeaconframe(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_data_ind_s *ind)
{
FAR struct iob_s *iob = ind->frame;
struct ieee802154_pandesc_s pandesc;
FAR struct ieee802154_txdesc_s *respdesc;
uint8_t numgtsdesc;
uint8_t gtsdirmask;
uint8_t npendsaddr;
uint8_t npendeaddr;
int i;
/* Copy the coordinator address and channel info into the pan descriptor */
memcpy(&pandesc.coordaddr, &ind->src, sizeof(struct ieee802154_addr_s));
pandesc.chan = priv->currscan.channels[priv->scanindex];
pandesc.chpage = priv->currscan.chpage;
pandesc.lqi = ind->lqi;
pandesc.timestamp = ind->timestamp;
/* Parse the superframe specification field */
pandesc.sfspec.beaconorder = IEEE802154_GETBEACONORDER(iob->io_data,
iob->io_offset);
pandesc.sfspec.sforder = IEEE802154_GETSFORDER(iob->io_data, iob->io_offset);
pandesc.sfspec.final_capslot = IEEE802154_GETFINCAPSLOT(iob->io_data,
iob->io_offset);
pandesc.sfspec.ble = IEEE802154_GETBLE(iob->io_data, iob->io_offset);
pandesc.sfspec.pancoord = IEEE802154_GETPANCOORD(iob->io_data, iob->io_offset);
pandesc.sfspec.assocpermit = IEEE802154_GETASSOCPERMIT(iob->io_data,
iob->io_offset);
iob->io_offset += 2;
/* Parse the GTS Specification field */
numgtsdesc = IEEE802154_GETGTSDESCCOUNT(iob->io_data, iob->io_offset);
pandesc.gtspermit = IEEE802154_GETGTSPERMIT(iob->io_data, iob->io_offset);
iob->io_offset++;
/* We only need to parse the rest of the frame if we are not performing a
* scan
*/
if (priv->curr_op == MAC802154_OP_SCAN)
{
/* Check to see if we already have a frame from this coordinator */
for (i = 0; i < priv->npandesc; i++)
{
if (priv->currscan.channels[priv->scanindex] != priv->pandescs[i].chan)
{
continue;
}
if (memcmp(&ind->src, &priv->pandescs[i].coordaddr,
sizeof(struct ieee802154_addr_s)))
{
continue;
}
/* The beacon is the same as another, so discard it */
return;
}
/* Copy the pan desc to the list of pan desc */
memcpy(&priv->pandescs[priv->npandesc], &pandesc,
sizeof(struct ieee802154_pandesc_s));
priv->npandesc++;
if (priv->npandesc == MAC802154_NPANDESC)
{
mac802154_scanfinish(priv, IEEE802154_STATUS_LIMITREACHED);
}
}
else
{
/* If there are any GTS descriptors, handle the GTS Directions and
* GTS List fields
*/
if (numgtsdesc > 0)
{
gtsdirmask = IEEE802154_GETGTSDIRMASK(iob->io_data, iob->io_offset);
iob->io_offset++;
for (i = 0; i < numgtsdesc; i++)
{
/* For now we just discard the data by skipping over it */
iob->io_offset += 3;
}
}
/* Pending address fields. Min 1 byte, the Pending Address Specification */
npendsaddr = IEEE802154_GETNPENDSADDR(iob->io_data, iob->io_offset);
npendeaddr = IEEE802154_GETNPENDEADDR(iob->io_data, iob->io_offset);
iob->io_offset++;
/* The pending address field tells us whether or not there is any data
* pending for us.
*/
for (i = 0; i < npendsaddr; i++)
{
/* If the short address matches our short address */
if (IEEE802154_SADDRCMP(&iob->io_data[iob->io_offset], priv->addr.saddr))
{
/* TODO: Handle data pending in coordinator for us */
}
iob->io_offset += IEEE802154_SADDRSIZE;
}
for (i = 0; i < npendeaddr; i++)
{
/* If the extended address matches our extended address */
if (IEEE802154_EADDRCMP(&iob->io_data[iob->io_offset], priv->addr.eaddr))
{
/* If we are associating, polling, or if macAutoRequest is TRUE,
* extract the data.
*/
if ((priv->autoreq) || (priv->curr_op == MAC802154_OP_ASSOC) ||
(priv->curr_op == MAC802154_OP_POLL))
{
mac802154_txdesc_alloc(priv, &respdesc, false);
mac802154_createdatareq(priv, &priv->pandesc.coordaddr,
IEEE802154_ADDRMODE_EXTENDED, respdesc);
if (priv->curr_op == MAC802154_OP_ASSOC ||
priv->curr_op == MAC802154_OP_POLL)
{
priv->curr_cmd = IEEE802154_CMD_DATA_REQ;
}
/* Link the transaction into the CSMA transaction list */
sq_addlast((FAR sq_entry_t *)respdesc, &priv->csma_queue);
/* Notify the radio driver that there is data available */
priv->radio->txnotify(priv->radio, false);
}
}
iob->io_offset += IEEE802154_EADDRSIZE;
}
/* TODO: Process incoming beacon payload
* If there is anything left in the frame, process it as the beacon payload
*/
/* Check the superframe structure and update the appropriate attributes. */
if (memcmp(&priv->sfspec, &pandesc.sfspec,
sizeof(struct ieee802154_superframespec_s)) != 0)
{
/* Copy in the new superframe spec */
memcpy(&priv->sfspec, &pandesc.sfspec,
sizeof(struct ieee802154_superframespec_s));
/* Tell the radio layer about the superframe spec update */
priv->radio->sfupdate(priv->radio, &pandesc.sfspec);
}
}
}
/**************************************************************************** /****************************************************************************
* Name: mac802154_symtoticks * Name: mac802154_symtoticks
* *
@ -1534,6 +1908,7 @@ MACHANDLE mac802154_create(FAR struct ieee802154_radio_s *radiodev)
radiocb->poll = mac802154_radiopoll; radiocb->poll = mac802154_radiopoll;
radiocb->txdone = mac802154_txdone; radiocb->txdone = mac802154_txdone;
radiocb->rxframe = mac802154_rxframe; radiocb->rxframe = mac802154_rxframe;
radiocb->sfevent = mac802154_sfevent;
/* Bind our callback structure */ /* Bind our callback structure */
@ -1552,7 +1927,7 @@ MACHANDLE mac802154_create(FAR struct ieee802154_radio_s *radiodev)
} }
IEEE802154_EADDRCOPY(mac->addr.eaddr, eaddr); IEEE802154_EADDRCOPY(mac->addr.eaddr, eaddr);
mac->radio->set_attr(mac->radio, IEEE802154_ATTR_MAC_EXTENDED_ADDR, mac->radio->set_attr(mac->radio, IEEE802154_ATTR_MAC_EADDR,
(union ieee802154_attr_u *)&eaddr[0]); (union ieee802154_attr_u *)&eaddr[0]);
return (MACHANDLE)mac; return (MACHANDLE)mac;

View File

@ -58,7 +58,7 @@
* Private Function Prototypes * Private Function Prototypes
****************************************************************************/ ****************************************************************************/
static void mac802154_timeout_assoc(FAR struct ieee802154_privmac_s *priv); static void mac802154_assoctimeout(FAR struct ieee802154_privmac_s *priv);
/**************************************************************************** /****************************************************************************
* Public MAC Functions * Public MAC Functions
@ -120,22 +120,18 @@ int mac802154_req_associate(MACHANDLE mac,
/* Set the channel and channel page of the PHY layer */ /* Set the channel and channel page of the PHY layer */
priv->radio->set_attr(priv->radio, IEEE802154_ATTR_PHY_CURRENT_CHANNEL, mac802154_setchannel(priv, req->chan);
(FAR const union ieee802154_attr_u *)&req->chnum); mac802154_setchpage(priv, req->chpage);
priv->radio->set_attr(priv->radio, IEEE802154_ATTR_PHY_CURRENT_PAGE,
(FAR const union ieee802154_attr_u *)&req->chpage);
/* Set the coordinator address attributes */ /* Set the coordinator address attributes */
memcpy(&priv->coordaddr, &req->coordaddr, sizeof(struct ieee802154_addr_s)); mac802154_setcoordaddr(priv, &req->coordaddr);
/* TODO: Need to send coordinator address to radio layer */
/* Copy the coordinator PAN ID to our PAN ID */ /* Copy the coordinator PAN ID to our PAN ID */
IEEE802154_PANIDCOPY(priv->addr.panid, req->coordaddr.panid); mac802154_setpanid(priv, req->coordaddr.panid);
priv->radio->set_attr(priv->radio, IEEE802154_ATTR_MAC_PANID,
(FAR const union ieee802154_attr_u *)req->coordaddr.panid);
/* Copy in the capabilities information bitfield */ /* Copy in the capabilities information bitfield */
@ -181,7 +177,7 @@ int mac802154_req_associate(MACHANDLE mac,
IEEE802154_SETACKREQ(iob->io_data, 0); IEEE802154_SETACKREQ(iob->io_data, 0);
IEEE802154_SETFTYPE(iob->io_data, 0, IEEE802154_FRAME_COMMAND); IEEE802154_SETFTYPE(iob->io_data, 0, IEEE802154_FRAME_COMMAND);
IEEE802154_SETDADDRMODE(iob->io_data, 0, priv->coordaddr.mode); IEEE802154_SETDADDRMODE(iob->io_data, 0, priv->pandesc.coordaddr.mode);
IEEE802154_SETSADDRMODE(iob->io_data, 0, IEEE802154_ADDRMODE_EXTENDED); IEEE802154_SETSADDRMODE(iob->io_data, 0, IEEE802154_ADDRMODE_EXTENDED);
iob->io_len = 2; iob->io_len = 2;
@ -197,20 +193,20 @@ int mac802154_req_associate(MACHANDLE mac,
* PAN to which to associate. [1] pg. 68 * PAN to which to associate. [1] pg. 68
*/ */
mac802154_putpanid(iob, priv->coordaddr.panid); mac802154_putpanid(iob, priv->pandesc.coordaddr.panid);
/* The Destination Address field shall contain the address from the beacon /* The Destination Address field shall contain the address from the beacon
* frame that was transmitted by the coordinator to which the association * frame that was transmitted by the coordinator to which the association
* request command is being sent. [1] pg. 68 * request command is being sent. [1] pg. 68
*/ */
if (priv->coordaddr.mode == IEEE802154_ADDRMODE_SHORT) if (priv->pandesc.coordaddr.mode == IEEE802154_ADDRMODE_SHORT)
{ {
mac802154_putsaddr(iob, priv->coordaddr.saddr); mac802154_putsaddr(iob, priv->pandesc.coordaddr.saddr);
} }
else if (priv->coordaddr.mode == IEEE802154_ADDRMODE_EXTENDED) else if (priv->pandesc.coordaddr.mode == IEEE802154_ADDRMODE_EXTENDED)
{ {
mac802154_puteaddr(iob, priv->coordaddr.eaddr); mac802154_puteaddr(iob, priv->pandesc.coordaddr.eaddr);
} }
/* The Source PAN Identifier field shall contain the broadcast PAN identifier.*/ /* The Source PAN Identifier field shall contain the broadcast PAN identifier.*/
@ -258,7 +254,7 @@ int mac802154_req_associate(MACHANDLE mac,
mac802154_givesem(&priv->exclsem); mac802154_givesem(&priv->exclsem);
/* Association Request commands get sent out immediately */ /* Association Request command gets sent out immediately */
priv->radio->txdelayed(priv->radio, txdesc, 0); priv->radio->txdelayed(priv->radio, txdesc, 0);
@ -464,7 +460,7 @@ void mac802154_txdone_assocreq(FAR struct ieee802154_privmac_s *priv,
* the coordinator after macResponseWaitTime. [1] pg. 34 * the coordinator after macResponseWaitTime. [1] pg. 34
*/ */
if (priv->trackingbeacon) if (priv->sfspec.beaconorder < 15)
{ {
/* We are tracking the beacon, so we should see our address in the /* We are tracking the beacon, so we should see our address in the
* beacon frame within macResponseWaitTime if the coordinator is going * beacon frame within macResponseWaitTime if the coordinator is going
@ -475,7 +471,7 @@ void mac802154_txdone_assocreq(FAR struct ieee802154_privmac_s *priv,
mac802154_timerstart(priv, (priv->resp_waittime * mac802154_timerstart(priv, (priv->resp_waittime *
IEEE802154_BASE_SUPERFRAME_DURATION), IEEE802154_BASE_SUPERFRAME_DURATION),
mac802154_timeout_assoc); mac802154_assoctimeout);
} }
else else
{ {
@ -484,7 +480,7 @@ void mac802154_txdone_assocreq(FAR struct ieee802154_privmac_s *priv,
* extended * extended
*/ */
DEBUGASSERT(priv->coordaddr.mode != IEEE802154_ADDRMODE_NONE); DEBUGASSERT(priv->pandesc.coordaddr.mode != IEEE802154_ADDRMODE_NONE);
/* Send the Data Request MAC command after macResponseWaitTime to /* Send the Data Request MAC command after macResponseWaitTime to
* extract the data from the coordinator. * extract the data from the coordinator.
@ -492,7 +488,7 @@ void mac802154_txdone_assocreq(FAR struct ieee802154_privmac_s *priv,
mac802154_txdesc_alloc(priv, &respdesc, false); mac802154_txdesc_alloc(priv, &respdesc, false);
mac802154_createdatareq(priv, &priv->coordaddr, mac802154_createdatareq(priv, &priv->pandesc.coordaddr,
IEEE802154_ADDRMODE_EXTENDED, respdesc); IEEE802154_ADDRMODE_EXTENDED, respdesc);
priv->curr_cmd = IEEE802154_CMD_DATA_REQ; priv->curr_cmd = IEEE802154_CMD_DATA_REQ;
@ -589,7 +585,7 @@ void mac802154_txdone_datareq_assoc(FAR struct ieee802154_privmac_s *priv,
* the corresponding data frame from the coordinator. [1] pg.43 * the corresponding data frame from the coordinator. [1] pg.43
*/ */
priv->radio->rxenable(priv->radio, true); mac802154_rxenable(priv);
/* Start a timer, if we receive the data frame, we will cancel /* Start a timer, if we receive the data frame, we will cancel
* the timer, otherwise it will expire and we will notify the * the timer, otherwise it will expire and we will notify the
@ -597,7 +593,7 @@ void mac802154_txdone_datareq_assoc(FAR struct ieee802154_privmac_s *priv,
*/ */
mac802154_timerstart(priv, priv->max_frame_waittime, mac802154_timerstart(priv, priv->max_frame_waittime,
mac802154_timeout_assoc); mac802154_assoctimeout);
/* We can deallocate the data conf notification as it is no longer /* We can deallocate the data conf notification as it is no longer
* needed. We can't use the public function here since we already * needed. We can't use the public function here since we already
@ -724,7 +720,7 @@ void mac802154_rx_assocresp(FAR struct ieee802154_privmac_s *priv,
/* Inform the radio of the address change */ /* Inform the radio of the address change */
priv->radio->set_attr(priv->radio, IEEE802154_ATTR_MAC_SHORT_ADDRESS, priv->radio->set_attr(priv->radio, IEEE802154_ATTR_MAC_SADDR,
(FAR union ieee802154_attr_u *)priv->addr.saddr); (FAR union ieee802154_attr_u *)priv->addr.saddr);
/* A Short Address field value equal to 0xfffe shall indicate that the device /* A Short Address field value equal to 0xfffe shall indicate that the device
@ -775,7 +771,7 @@ void mac802154_rx_assocresp(FAR struct ieee802154_privmac_s *priv,
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
* Name: mac802154_timeout_assoc * Name: mac802154_assoctimeout
* *
* Description: * Description:
* Function registered with MAC timer that gets called via the work queue to * Function registered with MAC timer that gets called via the work queue to
@ -783,7 +779,7 @@ void mac802154_rx_assocresp(FAR struct ieee802154_privmac_s *priv,
* *
****************************************************************************/ ****************************************************************************/
static void mac802154_timeout_assoc(FAR struct ieee802154_privmac_s *priv) static void mac802154_assoctimeout(FAR struct ieee802154_privmac_s *priv)
{ {
FAR struct ieee802154_notif_s *notif; FAR struct ieee802154_notif_s *notif;
@ -805,7 +801,7 @@ static void mac802154_timeout_assoc(FAR struct ieee802154_privmac_s *priv)
/* We are no longer performing the association operation */ /* We are no longer performing the association operation */
priv->curr_op = MAC802154_OP_NONE; priv->curr_op = MAC802154_OP_NONE;
priv->cmd_desc = NULL; priv->cmd_desc = NULL;
mac802154_givesem(&priv->opsem); mac802154_givesem(&priv->opsem);
/* Release the MAC */ /* Release the MAC */

View File

@ -86,10 +86,10 @@ int mac802154_req_get(MACHANDLE mac, enum ieee802154_attr_e attr,
case IEEE802154_ATTR_MAC_PANID: case IEEE802154_ATTR_MAC_PANID:
IEEE802154_PANIDCOPY(attrval->mac.panid, priv->addr.panid); IEEE802154_PANIDCOPY(attrval->mac.panid, priv->addr.panid);
break; break;
case IEEE802154_ATTR_MAC_SHORT_ADDRESS: case IEEE802154_ATTR_MAC_SADDR:
IEEE802154_SADDRCOPY(attrval->mac.saddr, priv->addr.saddr); IEEE802154_SADDRCOPY(attrval->mac.saddr, priv->addr.saddr);
break; break;
case IEEE802154_ATTR_MAC_EXTENDED_ADDR: case IEEE802154_ATTR_MAC_EADDR:
IEEE802154_EADDRCOPY(attrval->mac.eaddr, priv->addr.eaddr); IEEE802154_EADDRCOPY(attrval->mac.eaddr, priv->addr.eaddr);
break; break;
case IEEE802154_ATTR_MAC_DEVMODE: case IEEE802154_ATTR_MAC_DEVMODE:
@ -100,7 +100,7 @@ int mac802154_req_get(MACHANDLE mac, enum ieee802154_attr_e attr,
* it along. * it along.
*/ */
ret = priv->radio->set_attr(priv->radio, attr, attrval); ret = priv->radio->get_attr(priv->radio, attr, attrval);
break; break;
} }
@ -133,36 +133,38 @@ int mac802154_req_set(MACHANDLE mac, enum ieee802154_attr_e attr,
{ {
case IEEE802154_ATTR_MAC_PANID: case IEEE802154_ATTR_MAC_PANID:
{ {
IEEE802154_PANIDCOPY(priv->addr.panid, attrval->mac.panid); mac802154_setpanid(priv, attrval->mac.panid);
/* Tell the radio about the attribute */
priv->radio->set_attr(priv->radio, attr, attrval);
ret = IEEE802154_STATUS_SUCCESS; ret = IEEE802154_STATUS_SUCCESS;
} }
break; break;
case IEEE802154_ATTR_MAC_SHORT_ADDRESS: case IEEE802154_ATTR_MAC_SADDR:
{ {
IEEE802154_SADDRCOPY(priv->addr.saddr, attrval->mac.saddr); mac802154_setsaddr(priv, attrval->mac.saddr);
/* Tell the radio about the attribute */
priv->radio->set_attr(priv->radio, attr, attrval);
ret = IEEE802154_STATUS_SUCCESS; ret = IEEE802154_STATUS_SUCCESS;
} }
break; break;
case IEEE802154_ATTR_MAC_EXTENDED_ADDR: case IEEE802154_ATTR_MAC_EADDR:
{ {
/* Set the MAC copy of the address in the table */ mac802154_seteaddr(priv, attrval->mac.eaddr);
ret = IEEE802154_STATUS_SUCCESS;
IEEE802154_EADDRCOPY(priv->addr.eaddr, attrval->mac.eaddr); }
break;
/* Tell the radio about the attribute */ case IEEE802154_ATTR_MAC_COORD_SADDR:
{
priv->radio->set_attr(priv->radio, attr, attrval); mac802154_setcoordsaddr(priv, attrval->mac.coordsaddr);
ret = IEEE802154_STATUS_SUCCESS;
}
break;
case IEEE802154_ATTR_MAC_COORD_EADDR:
{
mac802154_setcoordeaddr(priv, attrval->mac.coordeaddr);
ret = IEEE802154_STATUS_SUCCESS;
}
break;
case IEEE802154_ATTR_MAC_ASSOCIATION_PERMIT:
{
priv->sfspec.assocpermit = attrval->mac.assocpermit;
priv->beaconupdate = true;
ret = IEEE802154_STATUS_SUCCESS; ret = IEEE802154_STATUS_SUCCESS;
} }
break; break;

File diff suppressed because it is too large Load Diff

View File

@ -735,14 +735,14 @@ static int lo_ioctl(FAR struct net_driver_s *dev, int cmd,
IEEE802154_PANIDCOPY(g_panid, setreq->attrval.mac.panid); IEEE802154_PANIDCOPY(g_panid, setreq->attrval.mac.panid);
break; break;
case IEEE802154_ATTR_MAC_EXTENDED_ADDR: case IEEE802154_ATTR_MAC_EADDR:
IEEE802154_EADDRCOPY(g_eaddr, setreq->attrval.mac.eaddr); IEEE802154_EADDRCOPY(g_eaddr, setreq->attrval.mac.eaddr);
#ifdef CONFIG_NET_6LOWPAN_EXTENDEDADDR #ifdef CONFIG_NET_6LOWPAN_EXTENDEDADDR
lo_addr2ip(dev); lo_addr2ip(dev);
#endif #endif
break; break;
case IEEE802154_ATTR_MAC_SHORT_ADDRESS: case IEEE802154_ATTR_MAC_SADDR:
IEEE802154_SADDRCOPY(g_saddr, setreq->attrval.mac.saddr); IEEE802154_SADDRCOPY(g_saddr, setreq->attrval.mac.saddr);
#ifndef CONFIG_NET_6LOWPAN_EXTENDEDADDR #ifndef CONFIG_NET_6LOWPAN_EXTENDEDADDR
lo_addr2ip(dev); lo_addr2ip(dev);
@ -765,11 +765,11 @@ static int lo_ioctl(FAR struct net_driver_s *dev, int cmd,
IEEE802154_PANIDCOPY(getreq->attrval.mac.panid, g_panid); IEEE802154_PANIDCOPY(getreq->attrval.mac.panid, g_panid);
break; break;
case IEEE802154_ATTR_MAC_EXTENDED_ADDR: case IEEE802154_ATTR_MAC_EADDR:
IEEE802154_EADDRCOPY(getreq->attrval.mac.eaddr, g_eaddr); IEEE802154_EADDRCOPY(getreq->attrval.mac.eaddr, g_eaddr);
break; break;
case IEEE802154_ATTR_MAC_SHORT_ADDRESS: case IEEE802154_ATTR_MAC_SADDR:
IEEE802154_SADDRCOPY(getreq->attrval.mac.saddr, g_saddr); IEEE802154_SADDRCOPY(getreq->attrval.mac.saddr, g_saddr);
break; break;

View File

@ -248,7 +248,7 @@ static int macnet_advertise(FAR struct net_driver_s *dev)
/* Get the eaddr from the MAC */ /* Get the eaddr from the MAC */
memcpy(arg.ifr_name, dev->d_ifname, IFNAMSIZ); memcpy(arg.ifr_name, dev->d_ifname, IFNAMSIZ);
arg.u.getreq.attr = IEEE802154_ATTR_MAC_EXTENDED_ADDR; arg.u.getreq.attr = IEEE802154_ATTR_MAC_EADDR;
ret = dev->d_ioctl(dev, MAC802154IOC_MLME_GET_REQUEST, ret = dev->d_ioctl(dev, MAC802154IOC_MLME_GET_REQUEST,
(unsigned long)((uintptr_t)&arg)); (unsigned long)((uintptr_t)&arg));
if (ret < 0) if (ret < 0)
@ -283,7 +283,7 @@ static int macnet_advertise(FAR struct net_driver_s *dev)
/* Get the saddr from the MAC */ /* Get the saddr from the MAC */
memcpy(arg.ifr_name, dev->d_ifname, IFNAMSIZ); memcpy(arg.ifr_name, dev->d_ifname, IFNAMSIZ);
arg.u.getreq.attr = IEEE802154_ATTR_MAC_SHORT_ADDRESS; arg.u.getreq.attr = IEEE802154_ATTR_MAC_SADDR;
ret = dev->d_ioctl(dev, MAC802154IOC_MLME_GET_REQUEST, ret = dev->d_ioctl(dev, MAC802154IOC_MLME_GET_REQUEST,
(unsigned long)((uintptr_t)&arg)); (unsigned long)((uintptr_t)&arg));
if (ret < 0) if (ret < 0)

View File

@ -60,7 +60,7 @@
* Private Function Prototypes * Private Function Prototypes
****************************************************************************/ ****************************************************************************/
static void mac802154_timeout_poll(FAR struct ieee802154_privmac_s *priv); static void mac802154_polltimeout(FAR struct ieee802154_privmac_s *priv);
/**************************************************************************** /****************************************************************************
* Public MAC Functions * Public MAC Functions
@ -235,7 +235,7 @@ void mac802154_txdone_datareq_poll(FAR struct ieee802154_privmac_s *priv,
* the corresponding data frame from the coordinator. [1] pg.43 * the corresponding data frame from the coordinator. [1] pg.43
*/ */
priv->radio->rxenable(priv->radio, true); mac802154_rxenable(priv);
/* Start a timer, if we receive the data frame, we will cancel /* Start a timer, if we receive the data frame, we will cancel
* the timer, otherwise it will expire and we will notify the * the timer, otherwise it will expire and we will notify the
@ -243,7 +243,7 @@ void mac802154_txdone_datareq_poll(FAR struct ieee802154_privmac_s *priv,
*/ */
mac802154_timerstart(priv, priv->max_frame_waittime, mac802154_timerstart(priv, priv->max_frame_waittime,
mac802154_timeout_poll); mac802154_polltimeout);
/* We can deallocate the data conf notification as it is no longer /* We can deallocate the data conf notification as it is no longer
* needed. We can't use the public function here since we already * needed. We can't use the public function here since we already
@ -256,7 +256,7 @@ void mac802154_txdone_datareq_poll(FAR struct ieee802154_privmac_s *priv,
} }
/**************************************************************************** /****************************************************************************
* Name: mac802154_timeout_poll * Name: mac802154_polltimeout
* *
* Description: * Description:
* Function registered with MAC timer that gets called via the work queue to * Function registered with MAC timer that gets called via the work queue to
@ -264,7 +264,7 @@ void mac802154_txdone_datareq_poll(FAR struct ieee802154_privmac_s *priv,
* *
****************************************************************************/ ****************************************************************************/
void mac802154_timeout_poll(FAR struct ieee802154_privmac_s *priv) void mac802154_polltimeout(FAR struct ieee802154_privmac_s *priv)
{ {
FAR struct ieee802154_notif_s *notif; FAR struct ieee802154_notif_s *notif;

View File

@ -86,15 +86,15 @@ int mac802154_req_reset(MACHANDLE mac, bool rst_pibattr)
if (rst_pibattr) if (rst_pibattr)
{ {
priv->isassoc = false; /* Not associated with a PAN */ priv->isassoc = false; /* Not associated with a PAN */
priv->trackingbeacon = false; /* Not tracking beacon by default */ priv->trackingbeacon = false; /* Not tracking beacon by default */
priv->assocpermit = false; /* Device (if coord) not accepting ssociation */ priv->sfspec.assocpermit = false; /* Device (if coord) not accepting ssociation */
priv->autoreq = true; /* Auto send data req if addr. in beacon */ priv->autoreq = true; /* Auto send data req if addr. in beacon */
priv->battlifeext = false; /* BLE disabled */ priv->sfspec.ble = false; /* BLE disabled */
priv->beacon_payload_len = 0; /* Beacon payload NULL */ priv->beaconpayloadlength = 0; /* Beacon payload NULL */
priv->beaconorder = 15; /* Non-beacon enabled network */ priv->sfspec.beaconorder = 15; /* Non-beacon enabled network */
priv->superframeorder = 15; /* Length of active portion of outgoing SF */ priv->sfspec.sforder = 15; /* Length of active portion of outgoing SF */
priv->beacon_txtime = 0; /* Device never sent a beacon */ priv->beacon_txtime = 0; /* Device never sent a beacon */
#warning Set BSN and DSN to random values! #warning Set BSN and DSN to random values!
priv->bsn = 0; priv->bsn = 0;
priv->dsn = 0; priv->dsn = 0;
@ -113,10 +113,10 @@ int mac802154_req_reset(MACHANDLE mac, bool rst_pibattr)
/* Reset the Coordinator address */ /* Reset the Coordinator address */
priv->coordaddr.mode = IEEE802154_ADDRMODE_NONE; priv->pandesc.coordaddr.mode = IEEE802154_ADDRMODE_NONE;
IEEE802154_PANIDCOPY(priv->coordaddr.panid, &IEEE802154_PANID_UNSPEC); IEEE802154_PANIDCOPY(priv->pandesc.coordaddr.panid, &IEEE802154_PANID_UNSPEC);
IEEE802154_SADDRCOPY(priv->coordaddr.saddr, &IEEE802154_SADDR_UNSPEC); IEEE802154_SADDRCOPY(priv->pandesc.coordaddr.saddr, &IEEE802154_SADDR_UNSPEC);
IEEE802154_EADDRCOPY(priv->coordaddr.eaddr, &IEEE802154_EADDR_UNSPEC); IEEE802154_EADDRCOPY(priv->pandesc.coordaddr.eaddr, &IEEE802154_EADDR_UNSPEC);
/* Reset the device's address */ /* Reset the device's address */

View File

@ -51,9 +51,17 @@
#include <string.h> #include <string.h>
#include "mac802154.h" #include "mac802154.h"
#include "mac802154_internal.h"
#include "mac802154_scan.h"
#include <nuttx/wireless/ieee802154/ieee802154_mac.h> #include <nuttx/wireless/ieee802154/ieee802154_mac.h>
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static void mac802154_scantimeout(FAR struct ieee802154_privmac_s *priv);
/**************************************************************************** /****************************************************************************
* Public MAC Functions * Public MAC Functions
****************************************************************************/ ****************************************************************************/
@ -77,6 +85,200 @@ int mac802154_req_scan(MACHANDLE mac, FAR struct ieee802154_scan_req_s *req)
{ {
FAR struct ieee802154_privmac_s *priv = FAR struct ieee802154_privmac_s *priv =
(FAR struct ieee802154_privmac_s *)mac; (FAR struct ieee802154_privmac_s *)mac;
return -ENOTTY; int ret;
if (req->duration > 15 || req->numchan < 0 || req->numchan > 15)
{
ret = -EINVAL;
goto errout;
}
/* Need to get access to the ops semaphore since operations are serial. This
* must be done before locking the MAC so that we don't hold the MAC
*/
ret = mac802154_takesem(&priv->opsem, true);
if (ret < 0)
{
ret = -EINTR;
goto errout;
}
priv->curr_op = MAC802154_OP_SCAN;
/* Get exclusive access to the MAC */
ret = mac802154_takesem(&priv->exclsem, true);
if (ret < 0)
{
mac802154_givesem(&priv->opsem);
ret = -EINTR;
goto errout;
}
/* Copy the request so we have a reference */
memcpy(&priv->currscan, req, sizeof(struct ieee802154_scan_req_s));
priv->scanindex = 0;
priv->npandesc = 0;
switch (req->type)
{
case IEEE802154_SCANTYPE_PASSIVE:
{
/* Set the channel to the first channel in the list */
mac802154_setchannel(priv, req->channels[priv->scanindex]);
mac802154_setchpage(priv, req->chpage);
/* Before commencing an active or passive scan, the MAC sublayer shall
* store the value of macPANId and then set it to 0xffff for the
* duration of the scan. This enables the receive filter to accept all
* beacons rather than just the beacons from its current PAN, as
* described in 5.1.6.2. On completion of the scan, the MAC sublayer
* shall restore the value of macPANId to the value stored before the
* scan began. [1] pg. 24
*/
IEEE802154_PANIDCOPY(priv->panidbeforescan, priv->addr.panid);
mac802154_setpanid(priv, (const uint8_t *)&IEEE802154_PANID_UNSPEC);
/* ...after switching to the channel for a passive scan, the device
* shall enable its receiver for at most
* [aBaseSuperframeDuration × (2 * n + 1)],
* where n is the value of the ScanDuration parameter. [1] pg. 25
*/
mac802154_rxenable(priv);
priv->scansymdur = IEEE802154_BASE_SUPERFRAME_DURATION *
((1 << req->duration) + 1);
mac802154_timerstart(priv, priv->scansymdur, mac802154_scantimeout);
}
break;
case IEEE802154_SCANTYPE_ACTIVE:
{
ret = -ENOTTY;
goto errout_with_sem;
}
break;
case IEEE802154_SCANTYPE_ED:
{
ret = -ENOTTY;
goto errout_with_sem;
}
break;
case IEEE802154_SCANTYPE_ORPHAN:
{
ret = -ENOTTY;
goto errout_with_sem;
}
break;
default:
{
ret = -EINVAL;
goto errout_with_sem;
}
break;
}
mac802154_givesem(&priv->exclsem);
return OK;
errout_with_sem:
mac802154_givesem(&priv->exclsem);
mac802154_givesem(&priv->opsem);
errout:
return ret;
} }
/****************************************************************************
* Internal MAC Functions
****************************************************************************/
void mac802154_scanfinish(FAR struct ieee802154_privmac_s *priv,
enum ieee802154_status_e status)
{
FAR struct ieee802154_notif_s * notif;
mac802154_takesem(&priv->exclsem, false);
mac802154_notif_alloc(priv, &notif, false);
priv->curr_op = MAC802154_OP_NONE;
mac802154_givesem(&priv->opsem);
notif->notiftype = IEEE802154_NOTIFY_CONF_SCAN;
notif->u.scanconf.type = priv->currscan.type;
notif->u.scanconf.chpage = priv->currscan.chpage;
/* Copy in the channels that did not get scanned */
if (priv->scanindex != priv->currscan.numchan)
{
notif->u.scanconf.numunscanned = priv->currscan.numchan - priv->scanindex;
memcpy(notif->u.scanconf.unscanned, &priv->currscan.channels[priv->scanindex],
notif->u.scanconf.numunscanned);
}
notif->u.scanconf.numdesc = priv->npandesc;
memcpy(notif->u.scanconf.pandescs, priv->pandescs,
sizeof(struct ieee802154_pandesc_s) * priv->npandesc);
notif->u.scanconf.status = status;
/* Reset the PAN ID to the setting before the scan started */
mac802154_setpanid(priv, priv->panidbeforescan);
mac802154_givesem(&priv->exclsem);
mac802154_notify(priv, notif);
}
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: mac802154_scantimeout
*
* Description:
* Function registered with MAC timer that gets called via the work queue to
* handle a timeout for performing a scan operation.
*
****************************************************************************/
static void mac802154_scantimeout(FAR struct ieee802154_privmac_s *priv)
{
DEBUGASSERT(priv->curr_op == MAC802154_OP_SCAN);
/* If we got here it means we are done scanning that channel */
mac802154_rxdisable(priv);
priv->scanindex++;
/* Check to see if this was the last channel to scan */
if (priv->scanindex == priv->currscan.numchan)
{
if (priv->npandesc > 0)
{
mac802154_scanfinish(priv, IEEE802154_STATUS_SUCCESS);
}
else
{
mac802154_scanfinish(priv, IEEE802154_STATUS_NO_BEACON);
}
return;
}
mac802154_setchannel(priv, priv->currscan.channels[priv->scanindex]);
/* ...after switching to the channel for a passive scan, the device
* shall enable its receiver for at most
* [aBaseSuperframeDuration × (2 * n + 1)],
* where n is the value of the ScanDuration parameter. [1] pg. 25
*/
mac802154_rxenable(priv);
mac802154_timerstart(priv, priv->scansymdur, mac802154_scantimeout);
}

View File

@ -0,0 +1,66 @@
/****************************************************************************
* wireless/ieee802154/mac802154_scan.h
*
* Copyright (C) 2017 Verge Inc. All rights reserved.
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
*
* Author: Anthony Merlino <anthony@vergeaero.com>
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* The naming and comments for various fields are taken directly
* from the IEEE 802.15.4 2011 standard.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __WIRELESS_IEEE802154__MAC802154_SCAN_H
#define __WIRELESS_IEEE802154__MAC802154_SCAN_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <stdbool.h>
#include <nuttx/wireless/ieee802154/ieee802154_mac.h>
#include <nuttx/wireless/ieee802154/ieee802154_radio.h>
/****************************************************************************
* Function Prototypes
****************************************************************************/
struct ieee802154_privmac_s; /* Forward Reference */
void mac802154_scanfinish(FAR struct ieee802154_privmac_s *priv,
enum ieee802154_status_e status);
#endif /* __WIRELESS_IEEE802154__MAC802154_SCAN_H */

View File

@ -97,17 +97,28 @@ int mac802154_req_start(MACHANDLE mac, FAR struct ieee802154_start_req_s *req)
/* Set the PANID attribute */ /* Set the PANID attribute */
IEEE802154_PANIDCOPY(priv->addr.panid, req->panid); mac802154_setpanid(priv, req->panid);
priv->radio->set_attr(priv->radio, IEEE802154_ATTR_MAC_PANID,
(FAR const union ieee802154_attr_u *)req->panid);
/* Set the radio attributes */ /* Tell the radio layer to set the channel number and channel page */
priv->radio->set_attr(priv->radio, IEEE802154_ATTR_PHY_CURRENT_CHANNEL,
(FAR const union ieee802154_attr_u *)&req->chnum);
priv->radio->set_attr(priv->radio, IEEE802154_ATTR_PHY_CHAN,
(FAR const union ieee802154_attr_u *)&req->chan);
priv->radio->set_attr(priv->radio, IEEE802154_ATTR_PHY_CURRENT_PAGE, priv->radio->set_attr(priv->radio, IEEE802154_ATTR_PHY_CURRENT_PAGE,
(FAR const union ieee802154_attr_u *)&req->chpage); (FAR const union ieee802154_attr_u *)&req->chpage);
/* The address used in the Source Address field of the beacon frame shall
* contain the value of macExtendedAddress if macShortAddress is equal to
* 0xfffe or macShortAddress otherwise. [1] pg. 32
*/
if (IEEE802154_SADDRCMP(priv->addr.saddr, &IEEE802154_SADDR_BCAST))
{
priv->addr.mode = IEEE802154_ADDRMODE_EXTENDED;
}
else
{
priv->addr.mode = IEEE802154_ADDRMODE_SHORT;
}
/* Set the beacon order */ /* Set the beacon order */
@ -117,11 +128,11 @@ int mac802154_req_start(MACHANDLE mac, FAR struct ieee802154_start_req_s *req)
goto errout; goto errout;
} }
priv->beaconorder = req->beaconorder; priv->sfspec.beaconorder = req->beaconorder;
/* The value of macSuperframeOrder shall be ignored if macBeaconOrder = 15. pg. 19 */ /* The value of macSuperframeOrder shall be ignored if macBeaconOrder = 15. pg. 19 */
if (priv->beaconorder < 15) if (priv->sfspec.beaconorder < 15)
{ {
/* Set the superframe order */ /* Set the superframe order */
@ -131,7 +142,7 @@ int mac802154_req_start(MACHANDLE mac, FAR struct ieee802154_start_req_s *req)
goto errout; goto errout;
} }
priv->superframeorder = req->superframeorder; priv->sfspec.sforder = req->superframeorder;
} }
if (req->pancoord) if (req->pancoord)
@ -143,18 +154,44 @@ int mac802154_req_start(MACHANDLE mac, FAR struct ieee802154_start_req_s *req)
priv->devmode = IEEE802154_DEVMODE_COORD; priv->devmode = IEEE802154_DEVMODE_COORD;
} }
/* If the BeaconOrder parameter is less than 15, the MLME sets macBattLifeExt to priv->sfspec.pancoord = req->pancoord;
* the value of the BatteryLifeExtension parameter. If the BeaconOrder parameter
* equals 15, the value of the BatteryLifeExtension parameter is ignored.
* [1] pg. 106
*/
if (priv->beaconorder < 15) if (priv->sfspec.beaconorder < 15)
{ {
priv->battlifeext = req->battlifeext; /* If the BeaconOrder parameter is less than 15, the MLME sets macBattLifeExt to
* the value of the BatteryLifeExtension parameter. If the BeaconOrder parameter
* equals 15, the value of the BatteryLifeExtension parameter is ignored.
* [1] pg. 106
*/
/* TODO: Finish starting beacon enabled network */ priv->sfspec.ble = req->battlifeext;
return -ENOTTY;
/* For now we just set the CAP Slot to 15 */
priv->sfspec.final_capslot = 15;
/* If the PAN coordinator parameter is set to TRUE, the MLME ignores the
* StartTime parameter and begins beacon transmissions immediately.
*/
if (req->pancoord)
{
/* Update the beacon frame to start sending */
mac802154_updatebeacon(priv);
/* Tell the radio to start transmitting beacon frames */
priv->radio->beaconstart(priv->radio, &priv->sfspec,
&priv->beaconframe[priv->bf_ind]);
}
else
{
/* TODO: Finish non-PAN coordinator delayed start */
ret = -ENOTTY;
goto errout;
}
} }
mac802154_givesem(&priv->exclsem); mac802154_givesem(&priv->exclsem);