From 5ca18999a5ff02f9223ed03c7aa90b117501c471 Mon Sep 17 00:00:00 2001 From: Anthony Merlino Date: Fri, 30 Jun 2017 05:26:32 -0400 Subject: [PATCH] ieee802154: Random fixes to get beacon-enabled networking more stable --- drivers/wireless/ieee802154/mrf24j40.c | 60 ++++++--- drivers/wireless/ieee802154/mrf24j40.h | 5 + wireless/ieee802154/mac802154.c | 153 ++++++++++++++--------- wireless/ieee802154/mac802154_assoc.c | 89 +++++++++---- wireless/ieee802154/mac802154_getset.c | 84 ++++++++----- wireless/ieee802154/mac802154_internal.h | 38 +++++- wireless/ieee802154/mac802154_reset.c | 2 - 7 files changed, 297 insertions(+), 134 deletions(-) diff --git a/drivers/wireless/ieee802154/mrf24j40.c b/drivers/wireless/ieee802154/mrf24j40.c index 538d140861..92c1ade53c 100644 --- a/drivers/wireless/ieee802154/mrf24j40.c +++ b/drivers/wireless/ieee802154/mrf24j40.c @@ -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 */ diff --git a/drivers/wireless/ieee802154/mrf24j40.h b/drivers/wireless/ieee802154/mrf24j40.h index e4e4e8ba5e..915669a144 100644 --- a/drivers/wireless/ieee802154/mrf24j40.h +++ b/drivers/wireless/ieee802154/mrf24j40.h @@ -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 diff --git a/wireless/ieee802154/mac802154.c b/wireless/ieee802154/mac802154.c index 5c62aac4c4..db7a74c311 100644 --- a/wireless/ieee802154/mac802154.c +++ b/wireless/ieee802154/mac802154.c @@ -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); } diff --git a/wireless/ieee802154/mac802154_assoc.c b/wireless/ieee802154/mac802154_assoc.c index dde6575bf6..d25c2dd2d3 100644 --- a/wireless/ieee802154/mac802154_assoc.c +++ b/wireless/ieee802154/mac802154_assoc.c @@ -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 */ diff --git a/wireless/ieee802154/mac802154_getset.c b/wireless/ieee802154/mac802154_getset.c index 1a43125cb6..d6a9ddf889 100644 --- a/wireless/ieee802154/mac802154_getset.c +++ b/wireless/ieee802154/mac802154_getset.c @@ -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 diff --git a/wireless/ieee802154/mac802154_internal.h b/wireless/ieee802154/mac802154_internal.h index be3cb8ebcd..e6b067894c 100644 --- a/wireless/ieee802154/mac802154_internal.h +++ b/wireless/ieee802154/mac802154_internal.h @@ -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 */ diff --git a/wireless/ieee802154/mac802154_reset.c b/wireless/ieee802154/mac802154_reset.c index 870a4bbe1b..79ae258b7d 100644 --- a/wireless/ieee802154/mac802154_reset.c +++ b/wireless/ieee802154/mac802154_reset.c @@ -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) */