mirror of
https://github.com/apache/nuttx.git
synced 2026-05-28 11:56:10 +08:00
ieee802154: Finishes beacon association functionality
This commit is contained in:
@@ -200,6 +200,8 @@ static void mrf24j40_setreg(FAR struct spi_dev_s *spi, uint32_t addr,
|
|||||||
static uint8_t mrf24j40_getreg(FAR struct spi_dev_s *spi, uint32_t addr);
|
static uint8_t mrf24j40_getreg(FAR struct spi_dev_s *spi, uint32_t addr);
|
||||||
|
|
||||||
static int mrf24j40_resetrfsm(FAR struct mrf24j40_radio_s *dev);
|
static int mrf24j40_resetrfsm(FAR struct mrf24j40_radio_s *dev);
|
||||||
|
static void mrf24j40_setorder(FAR struct mrf24j40_radio_s *dev, uint8_t bo,
|
||||||
|
uint8_t so);
|
||||||
static int mrf24j40_pacontrol(FAR struct mrf24j40_radio_s *dev, int mode);
|
static int mrf24j40_pacontrol(FAR struct mrf24j40_radio_s *dev, int mode);
|
||||||
|
|
||||||
static int mrf24j40_setrxmode(FAR struct mrf24j40_radio_s *dev, int mode);
|
static int mrf24j40_setrxmode(FAR struct mrf24j40_radio_s *dev, int mode);
|
||||||
@@ -438,6 +440,7 @@ static int mrf24j40_reset(FAR struct ieee802154_radio_s *radio)
|
|||||||
{
|
{
|
||||||
FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio;
|
FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio;
|
||||||
struct ieee802154_cca_s cca;
|
struct ieee802154_cca_s cca;
|
||||||
|
int reg;
|
||||||
|
|
||||||
/* Software reset */
|
/* Software reset */
|
||||||
|
|
||||||
@@ -462,6 +465,27 @@ static int mrf24j40_reset(FAR struct ieee802154_radio_s *radio)
|
|||||||
|
|
||||||
mrf24j40_setreg(dev->spi, MRF24J40_FRMOFFSET, 0x15);
|
mrf24j40_setreg(dev->spi, MRF24J40_FRMOFFSET, 0x15);
|
||||||
|
|
||||||
|
/* For now, we want to always just have the frame pending bit set when
|
||||||
|
* acknowledging a Data Request command. The standard says that the coordinator
|
||||||
|
* can do this if it needs time to figure out whether it has data or not
|
||||||
|
*/
|
||||||
|
|
||||||
|
mrf24j40_setreg(dev->spi, MRF24J40_ACKTMOUT, 0x39 | MRF24J40_ACKTMOUT_DRPACK);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
dev->rxenabled = false;
|
||||||
|
|
||||||
mrf24j40_setchannel(dev, 11);
|
mrf24j40_setchannel(dev, 11);
|
||||||
mrf24j40_setpanid(dev, g_allones);
|
mrf24j40_setpanid(dev, g_allones);
|
||||||
mrf24j40_setsaddr(dev, g_allones);
|
mrf24j40_setsaddr(dev, g_allones);
|
||||||
@@ -482,15 +506,6 @@ static int mrf24j40_reset(FAR struct ieee802154_radio_s *radio)
|
|||||||
|
|
||||||
mrf24j40_pacontrol(dev, MRF24J40_PA_AUTO);
|
mrf24j40_pacontrol(dev, MRF24J40_PA_AUTO);
|
||||||
|
|
||||||
dev->rxenabled = false;
|
|
||||||
|
|
||||||
/* For now, we want to always just have the frame pending bit set when
|
|
||||||
* acknowledging a Data Request command. The standard says that the coordinator
|
|
||||||
* can do this if it needs time to figure out whether it has data or not
|
|
||||||
*/
|
|
||||||
|
|
||||||
mrf24j40_setreg(dev->spi, MRF24J40_ACKTMOUT, 0x39 | MRF24J40_ACKTMOUT_DRPACK);
|
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -623,8 +638,6 @@ static int mrf24j40_beaconstart(FAR struct ieee802154_radio_s *radio,
|
|||||||
FAR struct ieee802154_beaconframe_s *beacon)
|
FAR struct ieee802154_beaconframe_s *beacon)
|
||||||
{
|
{
|
||||||
FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio;
|
FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio;
|
||||||
uint32_t maincnt = 0;
|
|
||||||
uint32_t slpcal = 0;
|
|
||||||
int reg;
|
int reg;
|
||||||
|
|
||||||
if (sfspec->pancoord)
|
if (sfspec->pancoord)
|
||||||
@@ -669,75 +682,8 @@ static int mrf24j40_beaconstart(FAR struct ieee802154_radio_s *radio,
|
|||||||
|
|
||||||
/* TODO: Add GTS related code. See pg 100 of datasheet */
|
/* 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
|
mrf24j40_setorder(dev, sfspec->beaconorder, sfspec->sforder);
|
||||||
* 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
|
else
|
||||||
{
|
{
|
||||||
@@ -770,30 +716,18 @@ static int mrf24j40_sfupdate(FAR struct ieee802154_radio_s *radio,
|
|||||||
|
|
||||||
/* If we are operating on a beacon-enabled network, use slotted CSMA */
|
/* If we are operating on a beacon-enabled network, use slotted CSMA */
|
||||||
|
|
||||||
|
reg = mrf24j40_getreg(dev->spi, MRF24J40_TXMCR);
|
||||||
if (sfspec->beaconorder < 15)
|
if (sfspec->beaconorder < 15)
|
||||||
{
|
{
|
||||||
reg = mrf24j40_getreg(dev->spi, MRF24J40_TXMCR);
|
|
||||||
reg |= MRF24J40_TXMCR_SLOTTED;
|
reg |= MRF24J40_TXMCR_SLOTTED;
|
||||||
mrf24j40_setreg(dev->spi, MRF24J40_TXMCR, reg);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
reg = mrf24j40_getreg(dev->spi, MRF24J40_TXMCR);
|
|
||||||
reg &= ~MRF24J40_TXMCR_SLOTTED;
|
reg &= ~MRF24J40_TXMCR_SLOTTED;
|
||||||
mrf24j40_setreg(dev->spi, MRF24J40_TXMCR, reg);
|
|
||||||
}
|
}
|
||||||
|
mrf24j40_setreg(dev->spi, MRF24J40_TXMCR, reg);
|
||||||
|
|
||||||
reg = mrf24j40_getreg(dev->spi, MRF24J40_RXMCR);
|
mrf24j40_setorder(dev, sfspec->beaconorder, sfspec->sforder);
|
||||||
|
|
||||||
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. */
|
/* Program the CAP end slot (ESLOTG1 0x13<3:0>) value. */
|
||||||
|
|
||||||
@@ -802,13 +736,6 @@ static int mrf24j40_sfupdate(FAR struct ieee802154_radio_s *radio,
|
|||||||
reg |= sfspec->final_capslot & MRF24J40_ESLOTG1_CAP;
|
reg |= sfspec->final_capslot & MRF24J40_ESLOTG1_CAP;
|
||||||
mrf24j40_setreg(dev->spi, MRF24J40_ESLOTG1, reg);
|
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;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -879,10 +806,13 @@ static void mrf24j40_dopoll_csma(FAR void *arg)
|
|||||||
|
|
||||||
if (!dev->csma_busy)
|
if (!dev->csma_busy)
|
||||||
{
|
{
|
||||||
|
wlinfo("polling for frame\n");
|
||||||
len = dev->radiocb->poll(dev->radiocb, false, &dev->csma_desc);
|
len = dev->radiocb->poll(dev->radiocb, false, &dev->csma_desc);
|
||||||
|
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
{
|
{
|
||||||
|
wlinfo("frame received. frame length: %d\n", len);
|
||||||
|
|
||||||
/* Now the txdesc is in use */
|
/* Now the txdesc is in use */
|
||||||
|
|
||||||
dev->csma_busy = 1;
|
dev->csma_busy = 1;
|
||||||
@@ -892,6 +822,10 @@ static void mrf24j40_dopoll_csma(FAR void *arg)
|
|||||||
mrf24j40_norm_setup(dev, dev->csma_desc->frame, true);
|
mrf24j40_norm_setup(dev, dev->csma_desc->frame, true);
|
||||||
mrf24j40_norm_trigger(dev);
|
mrf24j40_norm_trigger(dev);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wlinfo("no frames\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sem_post(&dev->exclsem);
|
sem_post(&dev->exclsem);
|
||||||
@@ -1092,6 +1026,78 @@ static int mrf24j40_resetrfsm(FAR struct mrf24j40_radio_s *dev)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mrf24j40_setorder
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Configures the timers and sets the ORDER register
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void mrf24j40_setorder(FAR struct mrf24j40_radio_s *dev, uint8_t bo,
|
||||||
|
uint8_t so)
|
||||||
|
{
|
||||||
|
uint32_t maincnt = 0;
|
||||||
|
uint32_t slpcal = 0;
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
/* 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(bo, (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));
|
||||||
|
|
||||||
|
/* 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, ((bo << 4) & 0xF0) | (so & 0x0F));
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: mrf24j40_pacontrol
|
* Name: mrf24j40_pacontrol
|
||||||
*
|
*
|
||||||
@@ -1232,7 +1238,7 @@ static int mrf24j40_setpanid(FAR struct mrf24j40_radio_s *dev,
|
|||||||
mrf24j40_setreg(dev->spi, MRF24J40_PANIDH, panid[1]);
|
mrf24j40_setreg(dev->spi, MRF24J40_PANIDH, panid[1]);
|
||||||
|
|
||||||
IEEE802154_PANIDCOPY(dev->addr.panid, panid);
|
IEEE802154_PANIDCOPY(dev->addr.panid, panid);
|
||||||
wlinfo("%02X:%02X\n", panid[1], panid[0]);
|
wlinfo("%02X:%02X\n", panid[0], panid[1]);
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@@ -1255,7 +1261,7 @@ static int mrf24j40_setsaddr(FAR struct mrf24j40_radio_s *dev,
|
|||||||
|
|
||||||
IEEE802154_SADDRCOPY(dev->addr.saddr, saddr);
|
IEEE802154_SADDRCOPY(dev->addr.saddr, saddr);
|
||||||
|
|
||||||
wlinfo("%02X:%02X\n", saddr[1], saddr[0]);
|
wlinfo("%02X:%02X\n", saddr[0], saddr[1]);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1278,6 +1284,8 @@ static int mrf24j40_seteaddr(FAR struct mrf24j40_radio_s *dev,
|
|||||||
mrf24j40_setreg(dev->spi, MRF24J40_EADR0 + i, eaddr[i]);
|
mrf24j40_setreg(dev->spi, MRF24J40_EADR0 + i, eaddr[i]);
|
||||||
dev->addr.eaddr[i] = eaddr[i];
|
dev->addr.eaddr[i] = eaddr[i];
|
||||||
}
|
}
|
||||||
|
wlinfo("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", eaddr[0], eaddr[1],
|
||||||
|
eaddr[2], eaddr[3], eaddr[4], eaddr[5], eaddr[6], eaddr[7]);
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@@ -1300,7 +1308,7 @@ static int mrf24j40_setcoordsaddr(FAR struct mrf24j40_radio_s *dev,
|
|||||||
|
|
||||||
IEEE802154_SADDRCOPY(dev->addr.saddr, saddr);
|
IEEE802154_SADDRCOPY(dev->addr.saddr, saddr);
|
||||||
|
|
||||||
wlinfo("%02X:%02X\n", saddr[1], saddr[0]);
|
wlinfo("%02X:%02X\n", saddr[0], saddr[1]);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1324,6 +1332,8 @@ static int mrf24j40_setcoordeaddr(FAR struct mrf24j40_radio_s *dev,
|
|||||||
dev->addr.eaddr[i] = eaddr[i];
|
dev->addr.eaddr[i] = eaddr[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wlinfo("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", eaddr[0], eaddr[1],
|
||||||
|
eaddr[2], eaddr[3], eaddr[4], eaddr[5], eaddr[6], eaddr[7]);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -593,19 +593,10 @@ struct ieee802154_pandesc_s
|
|||||||
* in symbols */
|
* in symbols */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ieee802154_pend_addr_s
|
struct ieee802154_pendaddr_s
|
||||||
{
|
{
|
||||||
union
|
uint8_t nsaddr : 3; /* Number of short addresses pending */
|
||||||
{
|
uint8_t neaddr : 3; /* Number of extended addresses pending */
|
||||||
uint8_t pa_spec;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
uint8_t num_short_addr : 3; /* Number of short addresses pending */
|
|
||||||
uint8_t reserved_3 : 1; /* Reserved bit */
|
|
||||||
uint8_t num_ext_addr : 3; /* Number of extended addresses pending */
|
|
||||||
uint8_t reserved_7 : 1; /* Reserved bit */
|
|
||||||
} pa_addr;
|
|
||||||
} u;
|
|
||||||
struct ieee802154_addr_s addr[7]; /* Array of at most 7 addresses */
|
struct ieee802154_addr_s addr[7]; /* Array of at most 7 addresses */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -632,7 +623,7 @@ union ieee802154_macattr_u
|
|||||||
|
|
||||||
bool is_assoc;
|
bool is_assoc;
|
||||||
bool assocpermit;
|
bool assocpermit;
|
||||||
bool auto_req;
|
bool autoreq;
|
||||||
bool batt_life_ext;
|
bool batt_life_ext;
|
||||||
bool gts_permit;
|
bool gts_permit;
|
||||||
bool promisc_mode;
|
bool promisc_mode;
|
||||||
@@ -1112,7 +1103,7 @@ struct ieee802154_disassoc_conf_s
|
|||||||
*
|
*
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
struct ieee802154_beaconnotify_ind_s
|
struct ieee802154_beacon_ind_s
|
||||||
{
|
{
|
||||||
uint8_t bsn; /* Beacon sequence number */
|
uint8_t bsn; /* Beacon sequence number */
|
||||||
|
|
||||||
@@ -1122,20 +1113,11 @@ struct ieee802154_beaconnotify_ind_s
|
|||||||
|
|
||||||
/* Beacon pending addresses */
|
/* Beacon pending addresses */
|
||||||
|
|
||||||
struct ieee802154_pend_addr_s pend_addr;
|
struct ieee802154_pendaddr_s pendaddr;
|
||||||
|
uint8_t payloadlength; /* # of octets contained in the beacon payload */
|
||||||
uint8_t sdu_length; /* Number of octets contained in the beacon
|
uint8_t payload[IEEE802154_MAX_BEACON_PAYLOAD_LEN];
|
||||||
* payload of the received beacond frame */
|
|
||||||
|
|
||||||
/* Beacon payload */
|
|
||||||
|
|
||||||
uint8_t sdu[IEEE802154_MAX_BEACON_PAYLOAD_LEN];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SIZEOF_IEEE802154_BEACONNOTIFY_IND_S(n) \
|
|
||||||
(sizeof(struct ieee802154_beaconnotify_ind_s) \
|
|
||||||
- IEEE802154_MAX_BEACON_PAYLOAD_LEN + (n))
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* Primitive: MLME-COMM-STATUS.indication
|
* Primitive: MLME-COMM-STATUS.indication
|
||||||
*
|
*
|
||||||
@@ -1538,21 +1520,21 @@ union ieee802154_notif_u
|
|||||||
|
|
||||||
/* MLME Notifications */
|
/* MLME Notifications */
|
||||||
|
|
||||||
struct ieee802154_assoc_conf_s assocconf;
|
struct ieee802154_assoc_conf_s assocconf;
|
||||||
struct ieee802154_disassoc_conf_s disassocconf;
|
struct ieee802154_disassoc_conf_s disassocconf;
|
||||||
struct ieee802154_gts_conf_s gtsconf;
|
struct ieee802154_gts_conf_s gtsconf;
|
||||||
struct ieee802154_rxenable_conf_s rxenableconf;
|
struct ieee802154_rxenable_conf_s rxenableconf;
|
||||||
struct ieee802154_scan_conf_s scanconf;
|
struct ieee802154_scan_conf_s scanconf;
|
||||||
struct ieee802154_start_conf_s startconf;
|
struct ieee802154_start_conf_s startconf;
|
||||||
struct ieee802154_poll_conf_s pollconf;
|
struct ieee802154_poll_conf_s pollconf;
|
||||||
|
|
||||||
struct ieee802154_assoc_ind_s assocind;
|
struct ieee802154_assoc_ind_s assocind;
|
||||||
struct ieee802154_disassoc_ind_s disassocind;
|
struct ieee802154_disassoc_ind_s disassocind;
|
||||||
struct ieee802154_beaconnotify_ind_s beaconnotifyind;
|
struct ieee802154_beacon_ind_s beaconind;
|
||||||
struct ieee802154_gts_ind_s gtsind;
|
struct ieee802154_gts_ind_s gtsind;
|
||||||
struct ieee802154_orphan_ind_s orphanind;
|
struct ieee802154_orphan_ind_s orphanind;
|
||||||
struct ieee802154_commstatus_ind_s commstatusind;
|
struct ieee802154_commstatus_ind_s commstatusind;
|
||||||
struct ieee802154_syncloss_ind_s synclossind;
|
struct ieee802154_syncloss_ind_s synclossind;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ieee802154_notif_s
|
struct ieee802154_notif_s
|
||||||
|
|||||||
+270
-115
@@ -1528,51 +1528,181 @@ static void mac802154_sfevent(FAR const struct ieee802154_radiocb_s *radiocb,
|
|||||||
* 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
|
||||||
* reception of a beacon frame.
|
* reception of a beacon frame.
|
||||||
*
|
*
|
||||||
|
* Assumptions: MAC is locked
|
||||||
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void mac802154_rxbeaconframe(FAR struct ieee802154_privmac_s *priv,
|
static void mac802154_rxbeaconframe(FAR struct ieee802154_privmac_s *priv,
|
||||||
FAR struct ieee802154_data_ind_s *ind)
|
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;
|
FAR struct ieee802154_txdesc_s *respdesc;
|
||||||
uint8_t numgtsdesc;
|
FAR struct ieee802154_notif_s *notif;
|
||||||
|
FAR struct ieee802154_beacon_ind_s *beacon;
|
||||||
|
FAR struct iob_s *iob = ind->frame;
|
||||||
|
uint8_t ngtsdesc;
|
||||||
uint8_t gtsdirmask;
|
uint8_t gtsdirmask;
|
||||||
uint8_t npendsaddr;
|
bool pending_saddr = false;
|
||||||
uint8_t npendeaddr;
|
bool pending_eaddr = false;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* Even though we may not use the notification, we use a notification to
|
||||||
|
* hold all the parsed beacon information. Freeing the notification is quick,
|
||||||
|
* so it's worth saving a copy (If you were to parse all the info in locally,
|
||||||
|
* you would have to copy the data over in the case that you actually need
|
||||||
|
* to notify the next highest layer)
|
||||||
|
*/
|
||||||
|
|
||||||
|
mac802154_notif_alloc(priv, ¬if, false);
|
||||||
|
beacon = ¬if->u.beaconind;
|
||||||
|
|
||||||
|
/* Make sure there is another 2 bytes to process */
|
||||||
|
|
||||||
|
if (iob->io_len < iob->io_offset + 2)
|
||||||
|
{
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
/* Copy the coordinator address and channel info into the pan descriptor */
|
/* Copy the coordinator address and channel info into the pan descriptor */
|
||||||
|
|
||||||
memcpy(&pandesc.coordaddr, &ind->src, sizeof(struct ieee802154_addr_s));
|
memcpy(&beacon->pandesc.coordaddr, &ind->src, sizeof(struct ieee802154_addr_s));
|
||||||
pandesc.chan = priv->currscan.channels[priv->scanindex];
|
beacon->pandesc.chan = priv->currscan.channels[priv->scanindex];
|
||||||
pandesc.chpage = priv->currscan.chpage;
|
beacon->pandesc.chpage = priv->currscan.chpage;
|
||||||
pandesc.lqi = ind->lqi;
|
beacon->pandesc.lqi = ind->lqi;
|
||||||
pandesc.timestamp = ind->timestamp;
|
beacon->pandesc.timestamp = ind->timestamp;
|
||||||
|
|
||||||
/* Parse the superframe specification field */
|
/* Parse the superframe specification field */
|
||||||
|
|
||||||
pandesc.sfspec.beaconorder = IEEE802154_GETBEACONORDER(iob->io_data,
|
beacon->pandesc.sfspec.beaconorder = IEEE802154_GETBEACONORDER(iob->io_data,
|
||||||
iob->io_offset);
|
iob->io_offset);
|
||||||
|
|
||||||
|
beacon->pandesc.sfspec.sforder =
|
||||||
|
IEEE802154_GETSFORDER(iob->io_data, iob->io_offset);
|
||||||
|
|
||||||
|
beacon->pandesc.sfspec.final_capslot =
|
||||||
|
IEEE802154_GETFINCAPSLOT(iob->io_data, iob->io_offset);
|
||||||
|
|
||||||
|
beacon->pandesc.sfspec.ble =
|
||||||
|
IEEE802154_GETBLE(iob->io_data, iob->io_offset);
|
||||||
|
|
||||||
|
beacon->pandesc.sfspec.pancoord =
|
||||||
|
IEEE802154_GETPANCOORD(iob->io_data, iob->io_offset);
|
||||||
|
|
||||||
|
beacon->pandesc.sfspec.assocpermit =
|
||||||
|
IEEE802154_GETASSOCPERMIT(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;
|
iob->io_offset += 2;
|
||||||
|
|
||||||
|
/* Make sure there is another byte to process (GTS Spec) */
|
||||||
|
|
||||||
|
if (iob->io_len < iob->io_offset + 1)
|
||||||
|
{
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
/* Parse the GTS Specification field */
|
/* Parse the GTS Specification field */
|
||||||
|
|
||||||
numgtsdesc = IEEE802154_GETGTSDESCCOUNT(iob->io_data, iob->io_offset);
|
ngtsdesc = IEEE802154_GETGTSDESCCOUNT(iob->io_data, iob->io_offset);
|
||||||
pandesc.gtspermit = IEEE802154_GETGTSPERMIT(iob->io_data, iob->io_offset);
|
beacon->pandesc.gtspermit = IEEE802154_GETGTSPERMIT(iob->io_data, iob->io_offset);
|
||||||
iob->io_offset++;
|
iob->io_offset++;
|
||||||
|
|
||||||
/* We only need to parse the rest of the frame if we are not performing a
|
/* If there are any GTS descriptors, handle the GTS Dir and GTS List fields */
|
||||||
* scan
|
|
||||||
*/
|
if (ngtsdesc > 0)
|
||||||
|
{
|
||||||
|
/* Make sure there is another bytes to process (GTS Direction) */
|
||||||
|
|
||||||
|
if (iob->io_len < iob->io_offset + 1)
|
||||||
|
{
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
gtsdirmask = IEEE802154_GETGTSDIRMASK(iob->io_data, iob->io_offset);
|
||||||
|
iob->io_offset++;
|
||||||
|
|
||||||
|
/* Make sure there are enough bytes left to represent the GTS List */
|
||||||
|
|
||||||
|
if (iob->io_len < iob->io_offset + (3 * ngtsdesc))
|
||||||
|
{
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ngtsdesc; 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 */
|
||||||
|
|
||||||
|
if (iob->io_len < iob->io_offset + 1)
|
||||||
|
{
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
beacon->pendaddr.nsaddr = IEEE802154_GETNPENDSADDR(iob->io_data, iob->io_offset);
|
||||||
|
beacon->pendaddr.neaddr = IEEE802154_GETNPENDEADDR(iob->io_data, iob->io_offset);
|
||||||
|
iob->io_offset++;
|
||||||
|
|
||||||
|
/* Make sure there are enough bytes left to represent the address list */
|
||||||
|
|
||||||
|
if (iob->io_len < (iob->io_offset +
|
||||||
|
(IEEE802154_SADDRSIZE * beacon->pendaddr.nsaddr) +
|
||||||
|
(IEEE802154_EADDRSIZE * beacon->pendaddr.neaddr)))
|
||||||
|
{
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy in the pending addresses */
|
||||||
|
|
||||||
|
for (i = 0; i < beacon->pendaddr.nsaddr; i++)
|
||||||
|
{
|
||||||
|
beacon->pendaddr.addr[i].mode = IEEE802154_ADDRMODE_SHORT;
|
||||||
|
mac802154_takesaddr(iob, beacon->pendaddr.addr[i].saddr);
|
||||||
|
|
||||||
|
/* Check if the short address matches our short address */
|
||||||
|
|
||||||
|
if (IEEE802154_SADDRCMP(beacon->pendaddr.addr[i].saddr, priv->addr.saddr))
|
||||||
|
{
|
||||||
|
/* Wait to actually decide how to handle this until we parse
|
||||||
|
* the rest of the frame
|
||||||
|
*/
|
||||||
|
wlinfo("Data pending for us in coord\n");
|
||||||
|
pending_saddr = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = beacon->pendaddr.nsaddr;
|
||||||
|
i < (beacon->pendaddr.nsaddr + beacon->pendaddr.neaddr);
|
||||||
|
i++)
|
||||||
|
{
|
||||||
|
beacon->pendaddr.addr[i].mode = IEEE802154_ADDRMODE_EXTENDED;
|
||||||
|
|
||||||
|
mac802154_takeeaddr(iob, beacon->pendaddr.addr[i].eaddr);
|
||||||
|
|
||||||
|
/* If the extended address matches our extended address */
|
||||||
|
|
||||||
|
if (IEEE802154_EADDRCMP(beacon->pendaddr.addr[i].eaddr, priv->addr.eaddr))
|
||||||
|
{
|
||||||
|
/* Wait to actually decide how to handle this until we parse
|
||||||
|
* the rest of the frame
|
||||||
|
*/
|
||||||
|
wlinfo("Data pending for us in coord\n");
|
||||||
|
pending_eaddr = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If there is anything left in the frame, process it as the beacon payload */
|
||||||
|
|
||||||
|
beacon->payloadlength = iob->io_len - iob->io_offset;
|
||||||
|
|
||||||
|
if (beacon->payloadlength > 0)
|
||||||
|
{
|
||||||
|
memcpy(beacon->payload, &iob->io_data[iob->io_offset], beacon->payloadlength);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* At this point, we have extracted all relevant info from the incoming frame */
|
||||||
|
|
||||||
if (priv->curr_op == MAC802154_OP_SCAN)
|
if (priv->curr_op == MAC802154_OP_SCAN)
|
||||||
{
|
{
|
||||||
@@ -1586,19 +1716,30 @@ static void mac802154_rxbeaconframe(FAR struct ieee802154_privmac_s *priv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (memcmp(&ind->src, &priv->pandescs[i].coordaddr,
|
if (memcmp(&ind->src, &priv->pandescs[i].coordaddr,
|
||||||
sizeof(struct ieee802154_addr_s)))
|
sizeof(struct ieee802154_addr_s)) != 0)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The beacon is the same as another, so discard it */
|
/* The beacon is the same as another, so discard it */
|
||||||
|
|
||||||
return;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: There is supposed to be different logic for the scanning procedure
|
||||||
|
* based on the macAutoRequest attribute. Currently, we perform scan
|
||||||
|
* operations as if macAutoRequest is set to TRUE, without actually checking
|
||||||
|
* the value. Basically, if macAutoRequest is TRUE, we are supposed to
|
||||||
|
* round up all of the pandesc results and pass them all up via the
|
||||||
|
* SCAN.confirm primitive. If macAutoRequest is FALSE, we are supposed
|
||||||
|
* to notify the next highest layer each time a unique beacon is received
|
||||||
|
* via the BEACON.notify primitive, and pass a NULLed out list of pandesc
|
||||||
|
* when SCAN.confirm is sent.
|
||||||
|
*/
|
||||||
|
|
||||||
/* Copy the pan desc to the list of pan desc */
|
/* Copy the pan desc to the list of pan desc */
|
||||||
|
|
||||||
memcpy(&priv->pandescs[priv->npandesc], &pandesc,
|
memcpy(&priv->pandescs[priv->npandesc], &beacon->pandesc,
|
||||||
sizeof(struct ieee802154_pandesc_s));
|
sizeof(struct ieee802154_pandesc_s));
|
||||||
priv->npandesc++;
|
priv->npandesc++;
|
||||||
|
|
||||||
@@ -1607,101 +1748,116 @@ static void mac802154_rxbeaconframe(FAR struct ieee802154_privmac_s *priv,
|
|||||||
mac802154_scanfinish(priv, IEEE802154_STATUS_LIMITREACHED);
|
mac802154_scanfinish(priv, IEEE802154_STATUS_LIMITREACHED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If we are not performing a SCAN operation */
|
||||||
|
|
||||||
else
|
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. */
|
/* Check the superframe structure and update the appropriate attributes. */
|
||||||
|
|
||||||
if (memcmp(&priv->sfspec, &pandesc.sfspec,
|
if (memcmp(&priv->sfspec, &beacon->pandesc.sfspec,
|
||||||
sizeof(struct ieee802154_superframespec_s)) != 0)
|
sizeof(struct ieee802154_superframespec_s)) != 0)
|
||||||
{
|
{
|
||||||
/* Copy in the new superframe spec */
|
/* Copy in the new superframe spec */
|
||||||
|
|
||||||
memcpy(&priv->sfspec, &pandesc.sfspec,
|
memcpy(&priv->sfspec, &beacon->pandesc.sfspec,
|
||||||
sizeof(struct ieee802154_superframespec_s));
|
sizeof(struct ieee802154_superframespec_s));
|
||||||
|
|
||||||
/* Tell the radio layer about the superframe spec update */
|
/* Tell the radio layer about the superframe spec update */
|
||||||
|
|
||||||
priv->radio->sfupdate(priv->radio, &pandesc.sfspec);
|
priv->radio->sfupdate(priv->radio, &priv->sfspec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we are performing an association and there is data pending for us
|
||||||
|
* we ignore the autoRequest logic and just extract it. We also don't
|
||||||
|
* send a BEACON-NOTFIY.indication in this case, not sure if that
|
||||||
|
* is the right thing to do, can't find anything definitive in standard.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (priv->curr_op == MAC802154_OP_ASSOC && pending_eaddr)
|
||||||
|
{
|
||||||
|
priv->curr_cmd = IEEE802154_CMD_DATA_REQ;
|
||||||
|
mac802154_txdesc_alloc(priv, &respdesc, false);
|
||||||
|
mac802154_createdatareq(priv, &priv->pandesc.coordaddr,
|
||||||
|
IEEE802154_ADDRMODE_EXTENDED, respdesc);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
else if (!priv->autoreq)
|
||||||
|
{
|
||||||
|
/* If a valid beacon frame is received and macAutoRequest is set to FALSE,
|
||||||
|
* the MLME shall indicate the beacon parameters to the next higher layer
|
||||||
|
* by issuing the MLME-BEACON-NOTIFY.indication primitive. [1] pg. 38
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Unlock the MAC, notify, then lock again */
|
||||||
|
|
||||||
|
mac802154_givesem(&priv->exclsem);
|
||||||
|
mac802154_notify(priv, notif);
|
||||||
|
mac802154_takesem(&priv->exclsem, false);
|
||||||
|
return; /* Return so that we don't free the notificaiton */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* If a beacon frame is received and macAutoRequest is set to TRUE, the
|
||||||
|
* MLME shall first issue the MLME- BEACON-NOTIFY.indication primitive if
|
||||||
|
* the beacon contains any payload.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (beacon->payloadlength > 0)
|
||||||
|
{
|
||||||
|
/* Unlock the MAC, notify, then lock again */
|
||||||
|
|
||||||
|
mac802154_givesem(&priv->exclsem);
|
||||||
|
mac802154_notify(priv, notif);
|
||||||
|
mac802154_takesem(&priv->exclsem, false);
|
||||||
|
return; /* Return so that we don't free the notificaiton */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we have data pending for us, attempt to extract it. If for some
|
||||||
|
* reason we have data pending under our short address and our
|
||||||
|
* extended address, let the short address arbitrarily take precedence
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (pending_saddr | pending_eaddr)
|
||||||
|
{
|
||||||
|
mac802154_txdesc_alloc(priv, &respdesc, false);
|
||||||
|
|
||||||
|
if (pending_saddr)
|
||||||
|
{
|
||||||
|
mac802154_createdatareq(priv, &priv->pandesc.coordaddr,
|
||||||
|
IEEE802154_ADDRMODE_SHORT, respdesc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mac802154_createdatareq(priv, &priv->pandesc.coordaddr,
|
||||||
|
IEEE802154_ADDRMODE_EXTENDED, respdesc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
mac802154_notif_free_locked(priv, notif);
|
||||||
|
return;
|
||||||
|
|
||||||
|
errout:
|
||||||
|
wlwarn("Received beacon with bad format\n");
|
||||||
|
mac802154_notif_free_locked(priv, notif);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -1864,6 +2020,7 @@ MACHANDLE mac802154_create(FAR struct ieee802154_radio_s *radiodev)
|
|||||||
|
|
||||||
if (mac == NULL)
|
if (mac == NULL)
|
||||||
{
|
{
|
||||||
|
wlinfo("Failed allocation privmac structure\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1883,8 +2040,6 @@ MACHANDLE mac802154_create(FAR struct ieee802154_radio_s *radiodev)
|
|||||||
|
|
||||||
mac->radio = radiodev;
|
mac->radio = radiodev;
|
||||||
|
|
||||||
mac802154_req_reset((MACHANDLE)mac, true);
|
|
||||||
|
|
||||||
/* Initialize the Radio callbacks */
|
/* Initialize the Radio callbacks */
|
||||||
|
|
||||||
mac->radiocb.priv = mac;
|
mac->radiocb.priv = mac;
|
||||||
@@ -1904,6 +2059,8 @@ MACHANDLE mac802154_create(FAR struct ieee802154_radio_s *radiodev)
|
|||||||
ieee802154_indpool_initialize();
|
ieee802154_indpool_initialize();
|
||||||
mac802154_resetqueues(mac);
|
mac802154_resetqueues(mac);
|
||||||
|
|
||||||
|
mac802154_req_reset((MACHANDLE)mac, true);
|
||||||
|
|
||||||
/* Set the default extended address */
|
/* Set the default extended address */
|
||||||
|
|
||||||
for (i = 0; i < IEEE802154_EADDRSIZE; i++)
|
for (i = 0; i < IEEE802154_EADDRSIZE; i++)
|
||||||
@@ -1911,9 +2068,7 @@ MACHANDLE mac802154_create(FAR struct ieee802154_radio_s *radiodev)
|
|||||||
eaddr[i] = (CONFIG_IEEE802154_DEFAULT_EADDR >> (8 * i)) & 0xFF;
|
eaddr[i] = (CONFIG_IEEE802154_DEFAULT_EADDR >> (8 * i)) & 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
IEEE802154_EADDRCOPY(mac->addr.eaddr, eaddr);
|
mac802154_seteaddr(mac, eaddr);
|
||||||
mac->radio->setattr(mac->radio, IEEE802154_ATTR_MAC_EADDR,
|
|
||||||
(union ieee802154_attr_u *)&eaddr[0]);
|
|
||||||
|
|
||||||
return (MACHANDLE)mac;
|
return (MACHANDLE)mac;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ int mac802154_req_associate(MACHANDLE mac,
|
|||||||
FAR struct iob_s *iob;
|
FAR struct iob_s *iob;
|
||||||
bool rxonidle;
|
bool rxonidle;
|
||||||
int ret;
|
int ret;
|
||||||
|
int i;
|
||||||
|
|
||||||
if (req->coordaddr.mode == IEEE802154_ADDRMODE_NONE)
|
if (req->coordaddr.mode == IEEE802154_ADDRMODE_NONE)
|
||||||
{
|
{
|
||||||
@@ -248,14 +249,68 @@ int mac802154_req_associate(MACHANDLE mac,
|
|||||||
|
|
||||||
priv->cmd_desc = txdesc;
|
priv->cmd_desc = txdesc;
|
||||||
|
|
||||||
|
/* Search the list of PAN descriptors, that would have been populated by the
|
||||||
|
* latest scan procedure. If we have seen a beacon from the coordinator that
|
||||||
|
* we are about to associate with, we can check the beacon order to determine
|
||||||
|
* whether we can send the command during the CAP. If we haven't received
|
||||||
|
* a beacon frame from the desired coordinator address, we have to just
|
||||||
|
* send the frame out immediately.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (i = 0; i < priv->npandesc; i++)
|
||||||
|
{
|
||||||
|
/* Check to make sure the beacon is from the same channel as the request */
|
||||||
|
|
||||||
|
if (req->chan != priv->pandescs[i].chan)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(&req->coordaddr, &priv->pandescs[i].coordaddr,
|
||||||
|
sizeof(struct ieee802154_addr_s)) == 0)
|
||||||
|
{
|
||||||
|
wlinfo("Found matching beacon to use for settings\n");
|
||||||
|
|
||||||
|
/* We have a beacon frame from this coordinator, we can set the
|
||||||
|
* sfspec and send accordingly.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Copy in the new superframe spec */
|
||||||
|
|
||||||
|
memcpy(&priv->sfspec, &priv->pandescs[i].sfspec,
|
||||||
|
sizeof(struct ieee802154_superframespec_s));
|
||||||
|
|
||||||
|
/* Tell the radio layer about the superframe spec update */
|
||||||
|
|
||||||
|
priv->radio->sfupdate(priv->radio, &priv->pandescs[i].sfspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->sfspec.beaconorder == 15)
|
||||||
|
{
|
||||||
|
wlinfo("Transmitting assoc request\n");
|
||||||
|
|
||||||
|
/* Association Request command gets sent out immediately */
|
||||||
|
|
||||||
|
priv->radio->txdelayed(priv->radio, txdesc, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wlinfo("Queuing assoc request for CAP\n");
|
||||||
|
|
||||||
|
/* Link the transaction into the CSMA transaction list */
|
||||||
|
|
||||||
|
sq_addlast((FAR sq_entry_t *)txdesc, &priv->csma_queue);
|
||||||
|
|
||||||
|
/* Notify the radio driver that there is data available */
|
||||||
|
|
||||||
|
priv->radio->txnotify(priv->radio, false);
|
||||||
|
}
|
||||||
|
|
||||||
/* We no longer need to have the MAC layer locked. */
|
/* We no longer need to have the MAC layer locked. */
|
||||||
|
|
||||||
mac802154_givesem(&priv->exclsem);
|
mac802154_givesem(&priv->exclsem);
|
||||||
|
|
||||||
/* Association Request command gets sent out immediately */
|
|
||||||
|
|
||||||
priv->radio->txdelayed(priv->radio, txdesc, 0);
|
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -173,8 +173,8 @@ static void macnet_ind_associate(FAR struct macnet_driver_s *priv,
|
|||||||
FAR struct ieee802154_assoc_ind_s *conf);
|
FAR struct ieee802154_assoc_ind_s *conf);
|
||||||
static void macnet_ind_disassociate(FAR struct macnet_driver_s *priv,
|
static void macnet_ind_disassociate(FAR struct macnet_driver_s *priv,
|
||||||
FAR struct ieee802154_disassoc_ind_s *conf);
|
FAR struct ieee802154_disassoc_ind_s *conf);
|
||||||
static void macnet_ind_beaconnotify(FAR struct macnet_driver_s *priv,
|
static void macnet_ind_beacon(FAR struct macnet_driver_s *priv,
|
||||||
FAR struct ieee802154_beaconnotify_ind_s *conf);
|
FAR struct ieee802154_beacon_ind_s *conf);
|
||||||
static void macnet_ind_gts(FAR struct macnet_driver_s *priv,
|
static void macnet_ind_gts(FAR struct macnet_driver_s *priv,
|
||||||
FAR struct ieee802154_gts_ind_s *conf);
|
FAR struct ieee802154_gts_ind_s *conf);
|
||||||
static void macnet_ind_orphan(FAR struct macnet_driver_s *priv,
|
static void macnet_ind_orphan(FAR struct macnet_driver_s *priv,
|
||||||
@@ -589,15 +589,15 @@ static void macnet_ind_disassociate(FAR struct macnet_driver_s *priv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: macnet_ind_beaconnotify
|
* Name: macnet_ind_beacon
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Beacon notification
|
* Beacon notification
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void macnet_ind_beaconnotify(FAR struct macnet_driver_s *priv,
|
static void macnet_ind_beacon(FAR struct macnet_driver_s *priv,
|
||||||
FAR struct ieee802154_beaconnotify_ind_s *ind)
|
FAR struct ieee802154_beacon_ind_s *ind)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user