ieee802154: Random fixes to get beacon-enabled networking more stable
This commit is contained in:
parent
b981ced4d4
commit
5ca18999a5
@ -147,10 +147,6 @@ struct mrf24j40_radio_s
|
||||
struct ieee802154_radio_s radio; /* The public device instance */
|
||||
FAR struct ieee802154_radiocb_s *radiocb; /* Registered callbacks */
|
||||
|
||||
/* MAC Attributes */
|
||||
|
||||
bool rxonidle : 1;
|
||||
|
||||
/* Low-level MCU-specific support */
|
||||
|
||||
FAR const struct mrf24j40_lower_s *lower;
|
||||
@ -162,6 +158,8 @@ struct mrf24j40_radio_s
|
||||
|
||||
sem_t exclsem; /* Exclusive access to this struct */
|
||||
|
||||
/* MAC Attributes */
|
||||
|
||||
struct ieee802154_addr_s addr;
|
||||
|
||||
uint8_t chan; /* 11 to 26 for the 2.4 GHz band */
|
||||
@ -183,6 +181,8 @@ struct mrf24j40_radio_s
|
||||
|
||||
bool rxenabled : 1;
|
||||
|
||||
uint8_t bsn;
|
||||
|
||||
struct ieee802154_txdesc_s *gts_desc[MRF24J40_GTS_SLOTS];
|
||||
bool gts_busy[MRF24J40_GTS_SLOTS];
|
||||
};
|
||||
@ -226,6 +226,7 @@ static void mrf24j40_setup_fifo(FAR struct mrf24j40_radio_s *dev,
|
||||
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_beacon_trigger(FAR struct mrf24j40_radio_s *dev);
|
||||
|
||||
static int mrf24j40_setchannel(FAR struct mrf24j40_radio_s *dev,
|
||||
uint8_t chan);
|
||||
@ -492,6 +493,7 @@ static int mrf24j40_reset(FAR struct ieee802154_radio_s *radio)
|
||||
mrf24j40_seteaddr(dev, g_allones);
|
||||
|
||||
dev->max_frame_waittime = MRF24J40_DEFAULT_MAX_FRAME_WAITTIME;
|
||||
dev->bsn = 0;
|
||||
|
||||
/* Default device params */
|
||||
|
||||
@ -611,14 +613,7 @@ static int mrf24j40_setattr(FAR struct ieee802154_radio_s *radio,
|
||||
}
|
||||
break;
|
||||
|
||||
case IEEE802154_ATTR_MAC_RX_ON_WHEN_IDLE:
|
||||
{
|
||||
dev->rxonidle = attrval->mac.rxonidle;
|
||||
mrf24j40_rxenable(radio, dev->rxonidle);
|
||||
ret = IEEE802154_STATUS_SUCCESS;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case IEEE802154_ATTR_PHY_CHAN:
|
||||
{
|
||||
mrf24j40_setchannel(dev, attrval->phy.chan);
|
||||
@ -658,6 +653,11 @@ static int mrf24j40_beaconstart(FAR struct ieee802154_radio_s *radio,
|
||||
|
||||
mrf24j40_setup_fifo(dev, beacon->bf_data, beacon->bf_len, MRF24J40_BEACON_FIFO);
|
||||
|
||||
/* The radio layer is responsible for setting the BSN. */
|
||||
|
||||
dev->bsn = 0;
|
||||
mrf24j40_setreg(dev->spi, MRF24J40_BEACON_FIFO + 4, dev->bsn++);
|
||||
|
||||
/* Set the TXBMSK (TXBCON1 0x25<7>) bit = 1 to mask the beacon interrupt
|
||||
* mask
|
||||
*/
|
||||
@ -682,7 +682,6 @@ static int mrf24j40_beaconstart(FAR struct ieee802154_radio_s *radio,
|
||||
|
||||
/* TODO: Add GTS related code. See pg 100 of datasheet */
|
||||
|
||||
|
||||
mrf24j40_setorder(dev, sfspec->beaconorder, sfspec->sforder);
|
||||
}
|
||||
else
|
||||
@ -699,6 +698,7 @@ static int mrf24j40_beaconupdate(FAR struct ieee802154_radio_s *radio,
|
||||
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);
|
||||
mrf24j40_beacon_trigger(dev);
|
||||
|
||||
return OK;
|
||||
}
|
||||
@ -1687,6 +1687,25 @@ static inline void mrf24j40_norm_trigger(FAR struct mrf24j40_radio_s *dev)
|
||||
mrf24j40_setreg(dev->spi, MRF24J40_TXNCON, reg);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mrf24j40_beacon_trigger
|
||||
*
|
||||
* Description:
|
||||
* Trigger the beacon TX FIFO
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline void mrf24j40_beacon_trigger(FAR struct mrf24j40_radio_s *dev)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
||||
reg = mrf24j40_getreg(dev->spi, MRF24J40_TXBCON0);
|
||||
|
||||
reg |= MRF24J40_TXBCON0_TXBTRIG;
|
||||
|
||||
mrf24j40_setreg(dev->spi, MRF24J40_TXBCON0, reg);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mrf24j40_gts_setup
|
||||
*
|
||||
@ -1991,9 +2010,6 @@ static void mrf24j40_irqwork_rx(FAR struct mrf24j40_radio_s *dev)
|
||||
|
||||
ind->frame->io_len = mrf24j40_getreg(dev->spi, addr++);
|
||||
|
||||
/* TODO: This needs to be changed. It is inefficient to do the SPI read byte
|
||||
* by byte */
|
||||
|
||||
for (index = 0; index < ind->frame->io_len; index++)
|
||||
{
|
||||
ind->frame->io_data[index] = mrf24j40_getreg(dev->spi, addr++);
|
||||
@ -2122,6 +2138,18 @@ static void mrf24j40_irqworker(FAR void *arg)
|
||||
reg |= MRF24J40_SLPACK_SLPACK;
|
||||
mrf24j40_setreg(dev->spi, MRF24J40_SLPACK, reg);
|
||||
}
|
||||
|
||||
if ((intstat & MRF24J40_INTSTAT_WAKEIF))
|
||||
{
|
||||
/* This is right before the beacon, we set the bsn here, since the MAC
|
||||
* uses the SLPIF (end of active portion of superframe). to make any
|
||||
* changes to the beacon. This assumes that any changes to the beacon
|
||||
* be in by the time that this interrupt fires.
|
||||
*/
|
||||
|
||||
mrf24j40_setreg(dev->spi, MRF24J40_BEACON_FIFO + 4, dev->bsn++);
|
||||
mrf24j40_beacon_trigger(dev);
|
||||
}
|
||||
|
||||
/* Unlock the radio device */
|
||||
|
||||
|
@ -226,6 +226,11 @@
|
||||
#define MRF24J40_TXSTAT_X_SHIFT 6
|
||||
#define MRF24J40_TXSTAT_X_MASK (3 << MRF24J40_TXSTAT_X_SHIFT)
|
||||
|
||||
/* TXBCON0 bits */
|
||||
|
||||
#define MRF24J40_TXBCON0_TXBTRIG 0x01
|
||||
#define MRF24J40_TXBCON0_TXBSECEN 0x02
|
||||
|
||||
/* TXBCON1 bits */
|
||||
|
||||
#define MRF24J40_TXBCON1_RSSINUM 0x30
|
||||
|
@ -354,9 +354,9 @@ void mac802154_createdatareq(FAR struct ieee802154_privmac_s *priv,
|
||||
|
||||
memcpy(&txdesc->destaddr, &coordaddr, sizeof(struct ieee802154_addr_s));
|
||||
|
||||
/* Copy the IOB reference to the descriptor */
|
||||
/* Save a reference of the tx descriptor */
|
||||
|
||||
txdesc->frame = iob;
|
||||
priv->cmd_desc = txdesc;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -417,9 +417,11 @@ void mac802154_updatebeacon(FAR struct ieee802154_privmac_s *priv)
|
||||
IEEE802154_SETSADDRMODE(beacon->bf_data, 0, priv->addr.mode);
|
||||
IEEE802154_SETVERSION(beacon->bf_data, 0, 1);
|
||||
|
||||
/* Copy in and increment the beacon sequence number */
|
||||
/* The beacon sequence number has to be taken care of by the radio layer, since
|
||||
* we only want to update the whole frame when more changes than just the bsn.
|
||||
*/
|
||||
|
||||
beacon->bf_data[beacon->bf_len++] = priv->bsn++;
|
||||
beacon->bf_len++;
|
||||
|
||||
IEEE802154_PANIDCOPY(&beacon->bf_data[beacon->bf_len], priv->addr.panid);
|
||||
beacon->bf_len += IEEE802154_PANIDSIZE;
|
||||
@ -580,8 +582,8 @@ void mac802154_setupindirect(FAR struct ieee802154_privmac_s *priv,
|
||||
|
||||
if (work_available(&priv->purge_work))
|
||||
{
|
||||
//work_queue(MAC802154_WORK, &priv->purge_work, mac802154_purge_worker,
|
||||
// (FAR void *)priv, ticks);
|
||||
work_queue(MAC802154_WORK, &priv->purge_work, mac802154_purge_worker,
|
||||
(FAR void *)priv, ticks);
|
||||
}
|
||||
}
|
||||
|
||||
@ -782,6 +784,8 @@ static void mac802154_txdone_worker(FAR void *arg)
|
||||
|
||||
notif =(FAR struct ieee802154_notif_s *)txdesc->conf;
|
||||
|
||||
wlinfo("tx status: %s\n", IEEE802154_STATUS_STRING[txdesc->conf->status]);
|
||||
|
||||
switch(txdesc->frametype)
|
||||
{
|
||||
case IEEE802154_FRAME_DATA:
|
||||
@ -1085,7 +1089,6 @@ static void mac802154_rxframe_worker(FAR void *arg)
|
||||
case IEEE802154_CMD_ORPHAN_NOT:
|
||||
wlinfo("Orphan notif received\n");
|
||||
break;
|
||||
break;
|
||||
|
||||
case IEEE802154_CMD_BEACON_REQ:
|
||||
wlinfo("Beacon request received\n");
|
||||
@ -1163,7 +1166,9 @@ static void mac802154_rxdataframe(FAR struct ieee802154_privmac_s *priv,
|
||||
* FIXME: Fix documentation
|
||||
*/
|
||||
|
||||
if (priv->curr_op == MAC802154_OP_POLL || priv->curr_op == MAC802154_OP_ASSOC)
|
||||
if (priv->curr_op == MAC802154_OP_POLL ||
|
||||
priv->curr_op == MAC802154_OP_ASSOC ||
|
||||
priv->curr_op == MAC802154_OP_AUTOEXTRACT)
|
||||
{
|
||||
/* If we are in promiscuous mode, we need to check if the
|
||||
* frame is even for us first. If the address is not ours,
|
||||
@ -1217,7 +1222,8 @@ static void mac802154_rxdataframe(FAR struct ieee802154_privmac_s *priv,
|
||||
}
|
||||
|
||||
/* If we've gotten this far, the frame is our extracted data. Cancel the
|
||||
* timeout */
|
||||
* timeout
|
||||
*/
|
||||
|
||||
mac802154_timercancel(priv);
|
||||
|
||||
@ -1617,6 +1623,7 @@ static void mac802154_rxbeaconframe(FAR struct ieee802154_privmac_s *priv,
|
||||
}
|
||||
|
||||
gtsdirmask = IEEE802154_GETGTSDIRMASK(iob->io_data, iob->io_offset);
|
||||
UNUSED(gtsdirmask);
|
||||
iob->io_offset++;
|
||||
|
||||
/* Make sure there are enough bytes left to represent the GTS List */
|
||||
@ -1723,7 +1730,8 @@ static void mac802154_rxbeaconframe(FAR struct ieee802154_privmac_s *priv,
|
||||
|
||||
/* The beacon is the same as another, so discard it */
|
||||
|
||||
goto done;
|
||||
mac802154_notif_free_locked(priv, notif);
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO: There is supposed to be different logic for the scanning procedure
|
||||
@ -1789,29 +1797,82 @@ static void mac802154_rxbeaconframe(FAR struct ieee802154_privmac_s *priv,
|
||||
|
||||
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)
|
||||
if (priv->autoreq || priv->curr_op == MAC802154_OP_POLL)
|
||||
{
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* 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 (priv->curr_op == MAC802154_OP_POLL)
|
||||
{
|
||||
priv->curr_cmd = IEEE802154_CMD_DATA_REQ;
|
||||
}
|
||||
else if (priv->curr_op == MAC802154_OP_NONE)
|
||||
{
|
||||
DEBUGASSERT(priv->opsem.semcount == 1);
|
||||
mac802154_takesem(&priv->opsem, false);
|
||||
priv->curr_op = MAC802154_OP_AUTOEXTRACT;
|
||||
priv->curr_cmd = IEEE802154_CMD_DATA_REQ;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* If there was a beacon payload, we used the notification, so
|
||||
* return here to make sure we don't free the notification.
|
||||
*/
|
||||
|
||||
if (beacon->payloadlength > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 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);
|
||||
@ -1819,39 +1880,9 @@ static void mac802154_rxbeaconframe(FAR struct ieee802154_privmac_s *priv,
|
||||
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;
|
||||
|
||||
@ -1973,6 +2004,8 @@ static void mac802154_timeout_expiry(int argc, wdparm_t arg, ...)
|
||||
|
||||
DEBUGASSERT(priv->timeout_worker != NULL);
|
||||
|
||||
wlinfo("timer expired\n");
|
||||
|
||||
work_queue(MAC802154_WORK, &priv->timeout_work, (worker_t)priv->timeout_worker,
|
||||
priv, 0);
|
||||
}
|
||||
|
@ -86,7 +86,6 @@ int mac802154_req_associate(MACHANDLE mac,
|
||||
(FAR struct ieee802154_privmac_s *)mac;
|
||||
FAR struct ieee802154_txdesc_s *txdesc;
|
||||
FAR struct iob_s *iob;
|
||||
bool rxonidle;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
@ -137,16 +136,7 @@ int mac802154_req_associate(MACHANDLE mac,
|
||||
priv->devmode = (req->capabilities.devtype) ?
|
||||
IEEE802154_DEVMODE_COORD : IEEE802154_DEVMODE_ENDPOINT;
|
||||
|
||||
/* Unlike other attributes, we can't simply cast this one since it is a bit
|
||||
* in a bitfield. Casting it will give us unpredicatble results. Instead
|
||||
* of creating a ieee802154_attr_u, we use a local bool. Allocating the
|
||||
* ieee802154_attr_u value would take up more room on the stack since it is
|
||||
* as large as the largest attribute type.
|
||||
*/
|
||||
|
||||
rxonidle = req->capabilities.rxonidle;
|
||||
priv->radio->setattr(priv->radio, IEEE802154_ATTR_MAC_RX_ON_WHEN_IDLE,
|
||||
(FAR const union ieee802154_attr_u *)&rxonidle);
|
||||
mac802154_setrxonidle(priv, req->capabilities.rxonidle);
|
||||
|
||||
/* Allocate an IOB to put the frame in */
|
||||
|
||||
@ -485,6 +475,7 @@ void mac802154_txdone_assocreq(FAR struct ieee802154_privmac_s *priv,
|
||||
|
||||
IEEE802154_SADDRCOPY(notif->u.assocconf.saddr, &IEEE802154_SADDR_UNSPEC);
|
||||
|
||||
|
||||
/* We are now done the operation, unlock the semaphore */
|
||||
|
||||
priv->curr_op = MAC802154_OP_NONE;
|
||||
@ -519,17 +510,33 @@ void mac802154_txdone_assocreq(FAR struct ieee802154_privmac_s *priv,
|
||||
* to respond. Setup a timeout for macResponseWaitTime so that we
|
||||
* can inform the next highest layer if the association attempt fails
|
||||
* due to NO_DATA.
|
||||
*
|
||||
* TODO: The standard defines macResponseWaitTime as:
|
||||
* The maximum time, in multiples of aBaseSuperframeDuration, a device
|
||||
* shall wait for a response command frame to be available following a
|
||||
* request command frame.
|
||||
*
|
||||
* However, on beacon-enabled networks, it seems the maximum value
|
||||
* isn't really that large of a value, AKA: assoc always fails from
|
||||
* timeout even though everything is working as expected. The definition
|
||||
* does say after we've sent a data request, which we, haven't sent
|
||||
* yet, but we do need a timeout for association in general. Not sure
|
||||
* what the correct answer is. For now, I am going to change the
|
||||
* way macResponseWaitTime is used with beacon-enabled networks and
|
||||
* make the timeout (BI * macResponseWaitTime) where BI is Beacon
|
||||
* Interval = aBaseSuperframeDuration * 2^macBeaconOrder
|
||||
*/
|
||||
|
||||
wlinfo("starting timeout timer\n");
|
||||
mac802154_timerstart(priv, (priv->resp_waittime *
|
||||
IEEE802154_BASE_SUPERFRAME_DURATION),
|
||||
mac802154_assoctimeout);
|
||||
(IEEE802154_BASE_SUPERFRAME_DURATION * (1 << priv->sfspec.beaconorder))),
|
||||
mac802154_assoctimeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Make sure the coordinator address mode is not set to none. This shouldn't
|
||||
* happen since the association request should have set the mode to short or
|
||||
* extended
|
||||
/* Make sure the coordinator address mode is not set to none. This
|
||||
* shouldn't happen since the association request should have set
|
||||
* the mode to short or extended
|
||||
*/
|
||||
|
||||
DEBUGASSERT(priv->pandesc.coordaddr.mode != IEEE802154_ADDRMODE_NONE);
|
||||
@ -634,17 +641,33 @@ void mac802154_txdone_datareq_assoc(FAR struct ieee802154_privmac_s *priv,
|
||||
|
||||
mac802154_rxenable(priv);
|
||||
|
||||
/* Start a timer, if we receive the data frame, we will cancel
|
||||
* the timer, otherwise it will expire and we will notify the
|
||||
* next highest layer of the failure.
|
||||
/* If we are on a beacon-enabled network, we already have the association
|
||||
* timeout timer scheduled. So we only need to start the timeout timer
|
||||
* if we are operating on a non-beacon enabled network.
|
||||
*
|
||||
* NOTE: This may create a bad side-effect where the receiver is on
|
||||
* for longer than it needs to be during association. Revisit if power
|
||||
* is ever an issue.
|
||||
*/
|
||||
|
||||
mac802154_timerstart(priv, priv->max_frame_waittime,
|
||||
mac802154_assoctimeout);
|
||||
if (priv->sfspec.beaconorder == 15)
|
||||
{
|
||||
|
||||
/* Start a timer, if we receive the data frame, we will cancel
|
||||
* the timer, otherwise it will expire and we will notify the
|
||||
* next highest layer of the failure.
|
||||
*/
|
||||
|
||||
wlinfo("starting timeout timer\n");
|
||||
mac802154_timerstart(priv, priv->max_frame_waittime,
|
||||
mac802154_assoctimeout);
|
||||
|
||||
}
|
||||
|
||||
/* Deallocate the data conf notification as it is no longer needed. */
|
||||
|
||||
mac802154_notif_free_locked(priv, notif);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -740,6 +763,19 @@ void mac802154_rx_assocresp(FAR struct ieee802154_privmac_s *priv,
|
||||
|
||||
if (priv->curr_op != MAC802154_OP_ASSOC)
|
||||
{
|
||||
/* This situation can occur in a beacon-enabled network if the association
|
||||
* request has timed out, but the Coordinator has already queued the
|
||||
* response. Which means the beacon would contain our address, causing us
|
||||
* to extract the response.
|
||||
*
|
||||
* TODO: What is supposed to happen in this situation. Are we supposed to
|
||||
* accept the request? Are we supposed to Disassociate with the network
|
||||
* as a convienience to the PAN Coordinator. So that it does not need
|
||||
* to waste space holding our information?
|
||||
*/
|
||||
|
||||
wlinfo("ignoring association response frame\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -793,15 +829,16 @@ void mac802154_rx_assocresp(FAR struct ieee802154_privmac_s *priv,
|
||||
|
||||
IEEE802154_SADDRCOPY(notif->u.assocconf.saddr, priv->addr.saddr);
|
||||
|
||||
/* Unlock the MAC */
|
||||
|
||||
mac802154_givesem(&priv->exclsem);
|
||||
|
||||
/* We are no longer performing the association operation */
|
||||
|
||||
priv->curr_op = MAC802154_OP_NONE;
|
||||
priv->cmd_desc = NULL;
|
||||
mac802154_givesem(&priv->opsem);
|
||||
mac802154_rxdisable(priv);
|
||||
|
||||
/* Unlock the MAC */
|
||||
|
||||
mac802154_givesem(&priv->exclsem);
|
||||
|
||||
/* Notify the next highest layer of the association status */
|
||||
|
||||
@ -842,9 +879,11 @@ static void mac802154_assoctimeout(FAR struct ieee802154_privmac_s *priv)
|
||||
mac802154_notif_alloc(priv, ¬if, false);
|
||||
|
||||
/* We are no longer performing the association operation */
|
||||
|
||||
priv->curr_op = MAC802154_OP_NONE;
|
||||
priv->cmd_desc = NULL;
|
||||
mac802154_givesem(&priv->opsem);
|
||||
mac802154_rxdisable(priv);
|
||||
|
||||
/* Release the MAC */
|
||||
|
||||
|
@ -84,29 +84,55 @@ int mac802154_req_get(MACHANDLE mac, enum ieee802154_attr_e attr,
|
||||
switch (attr)
|
||||
{
|
||||
case IEEE802154_ATTR_MAC_PANID:
|
||||
IEEE802154_PANIDCOPY(attrval->mac.panid, priv->addr.panid);
|
||||
{
|
||||
IEEE802154_PANIDCOPY(attrval->mac.panid, priv->addr.panid);
|
||||
}
|
||||
break;
|
||||
case IEEE802154_ATTR_MAC_SADDR:
|
||||
IEEE802154_SADDRCOPY(attrval->mac.saddr, priv->addr.saddr);
|
||||
break;
|
||||
case IEEE802154_ATTR_MAC_EADDR:
|
||||
IEEE802154_EADDRCOPY(attrval->mac.eaddr, priv->addr.eaddr);
|
||||
break;
|
||||
case IEEE802154_ATTR_MAC_COORD_SADDR:
|
||||
IEEE802154_SADDRCOPY(attrval->mac.coordsaddr, priv->pandesc.coordaddr.saddr);
|
||||
break;
|
||||
case IEEE802154_ATTR_MAC_COORD_EADDR:
|
||||
IEEE802154_EADDRCOPY(attrval->mac.coordeaddr, priv->pandesc.coordaddr.eaddr);
|
||||
break;
|
||||
case IEEE802154_ATTR_MAC_DEVMODE:
|
||||
attrval->mac.devmode = priv->devmode;
|
||||
break;
|
||||
default:
|
||||
/* The attribute may be handled soley in the radio driver, so pass
|
||||
* it along.
|
||||
*/
|
||||
|
||||
ret = priv->radio->getattr(priv->radio, attr, attrval);
|
||||
case IEEE802154_ATTR_MAC_SADDR:
|
||||
{
|
||||
IEEE802154_SADDRCOPY(attrval->mac.saddr, priv->addr.saddr);
|
||||
}
|
||||
break;
|
||||
|
||||
case IEEE802154_ATTR_MAC_EADDR:
|
||||
{
|
||||
IEEE802154_EADDRCOPY(attrval->mac.eaddr, priv->addr.eaddr);
|
||||
}
|
||||
break;
|
||||
|
||||
case IEEE802154_ATTR_MAC_COORD_SADDR:
|
||||
{
|
||||
IEEE802154_SADDRCOPY(attrval->mac.coordsaddr, priv->pandesc.coordaddr.saddr);
|
||||
}
|
||||
break;
|
||||
|
||||
case IEEE802154_ATTR_MAC_COORD_EADDR:
|
||||
{
|
||||
IEEE802154_EADDRCOPY(attrval->mac.coordeaddr, priv->pandesc.coordaddr.eaddr);
|
||||
}
|
||||
break;
|
||||
|
||||
case IEEE802154_ATTR_MAC_DEVMODE:
|
||||
{
|
||||
attrval->mac.devmode = priv->devmode;
|
||||
}
|
||||
break;
|
||||
|
||||
case IEEE802154_ATTR_MAC_RESPONSE_WAIT_TIME:
|
||||
{
|
||||
attrval->mac.resp_waittime = priv->resp_waittime;
|
||||
}
|
||||
break;;
|
||||
|
||||
default:
|
||||
{
|
||||
/* The attribute may be handled soley in the radio driver, so pass
|
||||
* it along.
|
||||
*/
|
||||
|
||||
ret = priv->radio->getattr(priv->radio, attr, attrval);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -133,47 +159,49 @@ int mac802154_req_set(MACHANDLE mac, enum ieee802154_attr_e attr,
|
||||
{
|
||||
FAR struct ieee802154_privmac_s *priv =
|
||||
(FAR struct ieee802154_privmac_s *)mac;
|
||||
int ret;
|
||||
int ret = IEEE802154_STATUS_SUCCESS;
|
||||
|
||||
switch (attr)
|
||||
{
|
||||
case IEEE802154_ATTR_MAC_PANID:
|
||||
{
|
||||
mac802154_setpanid(priv, attrval->mac.panid);
|
||||
ret = IEEE802154_STATUS_SUCCESS;
|
||||
}
|
||||
break;
|
||||
case IEEE802154_ATTR_MAC_SADDR:
|
||||
{
|
||||
mac802154_setsaddr(priv, attrval->mac.saddr);
|
||||
ret = IEEE802154_STATUS_SUCCESS;
|
||||
}
|
||||
break;
|
||||
case IEEE802154_ATTR_MAC_EADDR:
|
||||
{
|
||||
mac802154_seteaddr(priv, attrval->mac.eaddr);
|
||||
ret = IEEE802154_STATUS_SUCCESS;
|
||||
}
|
||||
break;
|
||||
case IEEE802154_ATTR_MAC_COORD_SADDR:
|
||||
{
|
||||
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;
|
||||
}
|
||||
break;
|
||||
case IEEE802154_ATTR_MAC_RESPONSE_WAIT_TIME:
|
||||
{
|
||||
priv->resp_waittime = attrval->mac.resp_waittime;
|
||||
}
|
||||
case IEEE802154_ATTR_MAC_RX_ON_WHEN_IDLE:
|
||||
{
|
||||
mac802154_setrxonidle(priv, attrval->mac.rxonidle);
|
||||
}
|
||||
default:
|
||||
{
|
||||
/* The attribute may be handled soley in the radio driver, so pass
|
||||
|
@ -135,7 +135,8 @@ enum mac802154_operation_e
|
||||
MAC802154_OP_NONE,
|
||||
MAC802154_OP_ASSOC,
|
||||
MAC802154_OP_POLL,
|
||||
MAC802154_OP_SCAN
|
||||
MAC802154_OP_SCAN,
|
||||
MAC802154_OP_AUTOEXTRACT,
|
||||
};
|
||||
|
||||
struct ieee802154_privmac_s; /* Forward Reference */
|
||||
@ -232,8 +233,6 @@ struct ieee802154_privmac_s
|
||||
|
||||
/*************** Fields related to beacon-enabled networks ******************/
|
||||
|
||||
uint8_t bsn; /* Seq. num added to tx beacon frame */
|
||||
|
||||
/* Holds attributes pertaining to the superframe specification */
|
||||
|
||||
struct ieee802154_superframespec_s sfspec;
|
||||
@ -357,6 +356,14 @@ struct ieee802154_privmac_s
|
||||
uint8_t maxretries : 3; /* Max # of retries allowed after tx fail */
|
||||
/* End of 8-bit bitfield. */
|
||||
|
||||
/* Start of 8-bit bitfield */
|
||||
|
||||
uint8_t rxonidle : 1; /* Receiver on when idle? */
|
||||
|
||||
/* End of 8-bit bitfield. */
|
||||
|
||||
|
||||
|
||||
/* TODO: Add Security-related MAC PIB attributes */
|
||||
};
|
||||
|
||||
@ -608,6 +615,7 @@ static inline int mac802154_timercancel(FAR struct ieee802154_privmac_s *priv)
|
||||
{
|
||||
wd_cancel(priv->timeout);
|
||||
priv->timeout_worker = NULL;
|
||||
wlinfo("timer cancelled\n");
|
||||
return OK;
|
||||
}
|
||||
|
||||
@ -702,4 +710,28 @@ static inline void mac802154_setcoordaddr(FAR struct ieee802154_privmac_s *priv,
|
||||
(FAR const union ieee802154_attr_u *)addr->saddr);
|
||||
}
|
||||
|
||||
static inline void mac802154_setrxonidle(FAR struct ieee802154_privmac_s *priv,
|
||||
bool rxonidle)
|
||||
{
|
||||
priv->rxonidle = true;
|
||||
if (priv->rxonidle)
|
||||
{
|
||||
mac802154_rxenable(priv);
|
||||
}
|
||||
else
|
||||
{
|
||||
mac802154_rxdisable(priv);
|
||||
}
|
||||
|
||||
/* Unlike other attributes, we can't simply cast this one since it is a bit
|
||||
* in a bitfield. Casting it will give us unpredicatble results. Instead
|
||||
* of creating a ieee802154_attr_u, we use a local bool. Allocating the
|
||||
* ieee802154_attr_u value would take up more room on the stack since it is
|
||||
* as large as the largest attribute type.
|
||||
*/
|
||||
|
||||
priv->radio->setattr(priv->radio, IEEE802154_ATTR_MAC_RX_ON_WHEN_IDLE,
|
||||
(FAR const union ieee802154_attr_u *)&rxonidle);
|
||||
}
|
||||
|
||||
#endif /* __WIRELESS_IEEE802154__MAC802154_INTERNAL_H */
|
||||
|
@ -95,8 +95,6 @@ int mac802154_req_reset(MACHANDLE mac, bool rst_pibattr)
|
||||
priv->sfspec.beaconorder = 15; /* Non-beacon enabled network */
|
||||
priv->sfspec.sforder = 15; /* Length of active portion of outgoing SF */
|
||||
priv->beacon_txtime = 0; /* Device never sent a beacon */
|
||||
#warning Set BSN and DSN to random values!
|
||||
priv->bsn = 0;
|
||||
priv->dsn = 0;
|
||||
priv->gtspermit = true; /* PAN Coord accepting GTS requests */
|
||||
priv->minbe = 3; /* Min value of backoff exponent (BE) */
|
||||
|
Loading…
Reference in New Issue
Block a user