Merged in antmerlino/nuttx/sixlowpan-mac802154 (pull request #526)

ieee802154: Simplifies notify() and rxframe() calls to a single notify() call. dataind's and all other "notifs" are now "primitives" which aligns with standard terminology

* mac802154: Adds missing breaks from case statement

* sixlowpan: Fixes bad logic where ACK is not requested if address is not a broadcast

* ieee802154: Simplification of "notifs" and "datainds" to generic primitives passed via a single notify call to the layer above the MAC

* Directories.mk should reference CONFIG_WIRELESS instead of CONFIG_DRIVERS_WIRELESS

* xbee_netdev: Network must be locked when calling sixlowpan_input

* sixlowpan: Reassembly buffer can't be freed if provided by radio driver

* sixlowpan: Don't free IOB if there is an error processing it as the MAC will try to pass it along to another receiver

* ieee802154: Adds basic logging to ieee802154_primitive.c

* Minor fixes after rebase

* xbee: Adds AT query timeout to retry if XBee doesn't respond to request

* same70-xplained: Adds Xbee support. Makes mikroBus slot Kconfig 'choice'

* mac802154: Removes unused function declaration

* drivers/mrf24j40: Fixes compilation error using . operator rather than -> operator

* mac802154_device: Changes a few mac802154_primtive_free's to ieee802154_primitive_free() and changes notif to primitive in a couple places.

* mac802154: Adds promiscous mode logic to bypass parsing of incoming frames. MAC char device also checks for promiscous mode and passes whole frames including header and FCS to the application if promiscous mode is enabled.

* sixlowpan: Fixes logic to correctly check if packet is large enough to include header.  This would cause packets to be considered too small when they are sufficiently sized.

* sixlowpan: Fixes forwarding logic to use forwarding device rather than received device to look up destination link layer address

* net/ipforward: Fixes typo that caused build error when IP forwarding was enabled with CONFIG_NET_ICMPv6_NEIGHBOR enabled as well.

* configs/same70-xplained: Simple spelling fix

Approved-by: Gregory Nutt <gnutt@nuttx.org>
This commit is contained in:
Anthony Merlino 2017-11-01 20:15:21 +00:00 committed by Gregory Nutt
parent 5c2e740ce3
commit 14fb37c995
42 changed files with 1388 additions and 2449 deletions

View File

@ -98,7 +98,7 @@ int board_app_initialize(uintptr_t arg)
if (ret < 0)
{
syslog(LOG_ERR, "ERROR: stm32_bringup() failed: %d\n", ret);
return ret
return ret;
}
#endif

View File

@ -22,19 +22,44 @@ config SAME70XPLAINED_MB2_SPI
default n
choice
prompt "Bee mikroBUS"
depends on SAME70XPLAINED_CLICKSHIELD && IEEE802154_MRF24J40
default SAME70XPLAINED_MB1_BEE
prompt "mikroBUS1 Click"
depends on SAME70XPLAINED_CLICKSHIELD
default SAME70XPLAINED_MB1_NONE
config SAME70XPLAINED_MB1_NONE
bool "None"
config SAME70XPLAINED_MB1_BEE
bool "MRF24J40 Bee in mikroBUS1"
depends on IEEE802154_MRF24J40
select SAME70XPLAINED_MB1_SPI
config SAME70XPLAINED_MB1_XBEE
bool "XBee in mikroBUS1"
depends on IEEE802154_XBEE
select SAME70XPLAINED_MB1_SPI
endchoice # mikroBUS1 Click
choice
prompt "mikroBUS2 Click"
depends on SAME70XPLAINED_CLICKSHIELD
default SAME70XPLAINED_MB2_NONE
config SAME70XPLAINED_MB2_NONE
bool "None"
config SAME70XPLAINED_MB2_BEE
bool "MRF24J40 Bee in mikroBUS2"
depends on IEEE802154_MRF24J40
select SAME70XPLAINED_MB2_SPI
endchoice # Bee mikroBUS
config SAME70XPLAINED_MB2_XBEE
bool "XBee in mikroBUS2"
depends on IEEE802154_XBEE
select SAME70XPLAINED_MB2_SPI
endchoice # mikroBUS2 Click
config SAME70XPLAINED_HSMCI0_AUTOMOUNT
bool "HSMCI0 automounter"

View File

@ -98,4 +98,8 @@ ifeq ($(CONFIG_IEEE802154_MRF24J40),y)
CSRCS += sam_mrf24j40.c
endif
ifeq ($(CONFIG_IEEE802154_XBEE),y)
CSRCS += sam_xbee.c
endif
include $(TOPDIR)/configs/Board.mk

View File

@ -170,6 +170,18 @@ void sam_spi0select(uint32_t devid, bool selected)
break;
#endif
#ifdef CONFIG_IEEE802154_XBEE
case SPIDEV_IEEE802154(0):
/* Set the GPIO low to select and high to de-select */
#if defined(CONFIG_SAME70XPLAINED_MB1_XBEE)
sam_gpiowrite(CLICK_MB1_CS, !selected);
#elif defined(CONFIG_SAME70XPLAINED_MB2_XBEE)
sam_gpiowrite(CLICK_MB2_CS, !selected);
#endif
break;
#endif
default:
break;
}

View File

@ -76,7 +76,7 @@ struct sam_priv_s
uint32_t attncfg;
uint32_t rstcfg;
uint8_t irq;
uint8_t spidev;
uint8_t csno;
};
/****************************************************************************
@ -92,11 +92,12 @@ struct sam_priv_s
* irq_enable - Enable or disable the GPIO interrupt
*/
static int sam_reset(FAR const struct xbee_lower_s *lower);
static void sam_reset(FAR const struct xbee_lower_s *lower);
static int sam_attach_irq(FAR const struct xbee_lower_s *lower,
xcpt_t handler, FAR void *arg);
static void sam_enable_irq(FAR const struct xbee_lower_s *lower,
bool state);
static bool sam_poll_attn(FAR const struct xbee_lower_s *lower);
static int sam_xbee_devsetup(FAR struct sam_priv_s *priv);
/****************************************************************************
@ -116,9 +117,11 @@ static int sam_xbee_devsetup(FAR struct sam_priv_s *priv);
#ifdef CONFIG_SAME70XPLAINED_MB1_XBEE
static struct sam_priv_s g_xbee_mb1_priv =
{
.dev.reset = sam_reset,
.dev.attach = sam_attach_irq,
.dev.enable = sam_enable_irq,
.intcfg = CLICK_MB1_INTR,
.dev.poll = sam_poll_attn,
.attncfg = CLICK_MB1_INTR,
.rstcfg = CLICK_MB1_RESET,
.irq = IRQ_MB1,
.csno = MB1_CSNO,
@ -128,12 +131,14 @@ static struct sam_priv_s g_xbee_mb1_priv =
#ifdef CONFIG_SAME70XPLAINED_MB2_XBEE
static struct sam_priv_s g_xbee_mb2_priv =
{
.dev.reset = sam_reset,
.dev.attach = sam_attach_irq,
.dev.enable = sam_enable_irq,
.intcfg = CLICK_MB2_INTR,
.dev.poll = sam_poll_attn,
.attncfg = CLICK_MB2_INTR,
.rstcfg = CLICK_MB2_RESET,
.irq = IRQ_MB2,
.spidev = MB2_CSNO,
.csno = MB2_CSNO,
};
#endif
@ -141,7 +146,7 @@ static struct sam_priv_s g_xbee_mb2_priv =
* Private Functions
****************************************************************************/
static int sam_reset(FAR const struct xbee_lower_s *lower)
static void sam_reset(FAR const struct xbee_lower_s *lower)
{
FAR struct sam_priv_s *priv = (FAR struct sam_priv_s *)lower;
@ -149,14 +154,11 @@ static int sam_reset(FAR const struct xbee_lower_s *lower)
/* Reset pulse */
sam_gpiowrite(priv->rstcfg, true);
sam_gpiowrite(priv->rstcfg, false);
up_udelay(1);
sam_gpiowrite(priv->rstcfg, true);
/* Wait minimum 1.5 ms to allow Xbee a proper boot-up sequence */
/* TODO: Update time according to datasheet */
nxsig_usleep(1500);
return OK;
up_mdelay(100);
}
static int sam_attach_irq(FAR const struct xbee_lower_s *lower,
@ -214,6 +216,13 @@ static void sam_enable_irq(FAR const struct xbee_lower_s *lower,
leave_critical_section(flags);
}
static bool sam_poll_attn(FAR const struct xbee_lower_s *lower)
{
FAR struct sam_priv_s *priv = (FAR struct sam_priv_s *)lower;
return !sam_gpioread(priv->attncfg);
}
/****************************************************************************
* Name: sam_xbee_devsetup
*
@ -286,7 +295,7 @@ int sam_xbee_initialize(void)
int ret;
#ifdef CONFIG_SAME70XPLAINED_MB1_XBEE
wlinfo("Configuring BEE in mikroBUS1\n");
wlinfo("Configuring XBee in mikroBUS1\n");
ret = sam_xbee_devsetup(&g_xbee_mb1_priv);
if (ret < 0)

View File

@ -655,5 +655,21 @@ int sam_at24config(void);
int sam_mrf24j40_initialize(void);
#endif
/****************************************************************************
* Name: stm32_xbee_initialize
*
* Description:
* Initialize the XBee device.
*
* Returned Value:
* Zero is returned on success. Otherwise, a negated errno value is
* returned to indicate the nature of the failure.
*
****************************************************************************/
#ifdef HAVE_XBEE
int sam_xbee_initialize(void);
#endif
#endif /* __ASSEMBLY__ */
#endif /* __CONFIGS_SAME70_XPLAINED_SRC_SAME70_XPLAINED_H */

View File

@ -117,7 +117,6 @@ static void mrf24j40_irqwork_txnorm(FAR struct mrf24j40_radio_s *dev)
MRF24J40_TXNCON_FPSTAT);
if (dev->txdelayed_busy)
{
/* Inform the next layer of the transmission success/failure */
@ -213,6 +212,7 @@ static void mrf24j40_irqwork_txgts(FAR struct mrf24j40_radio_s *dev,
static void mrf24j40_irqwork_rx(FAR struct mrf24j40_radio_s *dev)
{
FAR struct ieee802154_primitive_s *primitive;
FAR struct ieee802154_data_ind_s *ind;
uint32_t addr;
uint32_t index;
@ -232,13 +232,24 @@ static void mrf24j40_irqwork_rx(FAR struct mrf24j40_radio_s *dev)
/* Allocate a data_ind to put the frame in */
ind = ieee802154_ind_allocate();
primitive = ieee802154_primitive_allocate();
ind = (FAR struct ieee802154_data_ind_s *)primitive;
if (ind == NULL)
{
wlerr("ERROR: Unable to allocate data_ind. Discarding frame\n");
goto done;
}
primitive->type = IEEE802154_PRIMITIVE_IND_DATA;
/* Allocate an IOB to put the frame into */
ind->frame = iob_alloc(false);
ind->frame->io_flink = NULL;
ind->frame->io_len = 0;
ind->frame->io_pktlen = 0;
ind->frame->io_offset = 0;
/* Read packet */
addr = MRF24J40_RXBUF_BASE;

View File

@ -11,24 +11,6 @@ config IEEE802154_XBEE_FREQUENCY
---help---
SPI SLCK frequency in Hz
config XBEE_NETDEV_RECVRPRIO
int "Priority of frame receiver registerd with the MAC layer"
default 1
---help---
When the MAC layer receives an incoming data frame, it passes the frame
to registered receivers, in order of receiver priority, until one of the
receivers claim the frame.
An example case would be when 6LoWPAN and the MAC character driver are
enabled. Both have receivers registered with the MAC. The 6LoWPAN layer
should get assigned a higher priority than the character driver. In this
case, the 6LoWPAN receiver will receive the frame first. If the frame is
a 6LoWPAN frame, it will claim the frame and the MAC will not pass the
frame to any additional receivers. If it does not claim the frame, the
MAC layer will call the next highest priority receiver, in this case,
the MAC character driver (which should always be lowest priority since
it is a "catch-all" type receiver).
choice
prompt "Work queue"
default XBEE_NETDEV_LPWORK if SCHED_LPWORK
@ -57,21 +39,22 @@ config XBEE_NETDEV_LPWORK
endchoice # Work queue
config XBEE_NNOTIF
int "Number or notification structures"
default 3
config XBEE_NETDEV_RECVRPRIO
int "Priority of frame receiver registerd with the MAC layer"
default 1
---help---
Configured number of notification strucures Default: 3
When the MAC layer receives an incoming data frame, it passes the frame
to registered receivers, in order of receiver priority, until one of the
receivers claim the frame.
When various MAC management events occur, the MAC notifies the registered
receiver with an allocated notification structure indicating the event. The
events are primitives such as Association Indication etc.
config XBEE_LOCK_VERBOSE
bool "Verbose logging related to XBee driver lock management"
default n
depends on DEBUG_WIRELESS_INFO
---help---
Enable verbose logging of XBee lock management. Default: false
An example case would be when 6LoWPAN and the MAC character driver are
enabled. Both have receivers registered with the MAC. The 6LoWPAN layer
should get assigned a higher priority than the character driver. In this
case, the 6LoWPAN receiver will receive the frame first. If the frame is
a 6LoWPAN frame, it will claim the frame and the MAC will not pass the
frame to any additional receivers. If it does not claim the frame, the
MAC layer will call the next highest priority receiver, in this case,
the MAC character driver (which should always be lowest priority since
it is a "catch-all" type receiver).
endif # IEEE802154_XBEE

View File

@ -37,7 +37,7 @@ ifeq ($(CONFIG_IEEE802154_XBEE),y)
# Include XBee files into the build
CSRCS += xbee_dataind.c xbee_ioctl.c xbee_mac.c xbee_netdev.c xbee_notif.c xbee.c
CSRCS += xbee_ioctl.c xbee_mac.c xbee_netdev.c xbee.c
# Include XBee build support

View File

@ -60,6 +60,8 @@
* Pre-processor Definitions
****************************************************************************/
#define XBEE_ATQUERY_TIMEOUT 100
/****************************************************************************
* Private Types
****************************************************************************/
@ -79,6 +81,10 @@ static void xbee_process_txstatus(FAR struct xbee_priv_s *priv, uint8_t frameid,
static void xbee_process_rxframe(FAR struct xbee_priv_s *priv,
FAR struct iob_s *frame,
enum ieee802154_addrmode_e addrmode);
static void xbee_notify(FAR struct xbee_priv_s *priv,
FAR struct ieee802154_primitive_s *primitive);
static void xbee_notify_worker(FAR void *arg);
static void xbee_atquery_timeout(int argc, uint32_t arg, ...);
/****************************************************************************
* Private Data
@ -355,6 +361,17 @@ static void xbee_attnworker(FAR void *arg)
{
xbee_process_apiframes(priv, iobhead);
}
/* If an interrupt occured while the worker was running, it was not
* scheduled since there is a good chance this function has already handled
* it as part of the previous ATTN assertion. Therefore, if the ATTN
* line is asserted again reschedule the work.
*/
if (priv->attn_latched)
{
work_queue(HPWORK, &priv->attnwork, xbee_attnworker, (FAR void *)priv, 0);
}
}
/****************************************************************************
@ -480,7 +497,7 @@ static bool xbee_verify_checksum(FAR const struct iob_s *iob)
static void xbee_process_apiframes(FAR struct xbee_priv_s *priv,
FAR struct iob_s *framelist)
{
FAR struct ieee802154_notif_s *notif;
FAR struct ieee802154_primitive_s *primitive;
FAR struct iob_s *frame;
FAR struct iob_s *nextframe;
FAR char *command;
@ -515,7 +532,7 @@ static void xbee_process_apiframes(FAR struct xbee_priv_s *priv,
command = (FAR char *)&frame->io_data[frame->io_offset];
frame->io_offset += 2;
wlinfo("AT Repsonse Recevied: %.*s\n", 2, command);
wlinfo("AT Response Received: %.*s\n", 2, command);
/* Make sure the command status is OK=0 */
@ -532,8 +549,6 @@ static void xbee_process_apiframes(FAR struct xbee_priv_s *priv,
{
priv->addr.panid[1] = frame->io_data[frame->io_offset++];
priv->addr.panid[0] = frame->io_data[frame->io_offset++];
xbee_notify_respwaiter(priv, XBEE_RESP_AT_NETWORKID);
}
else if (memcmp(command, "SH", 2) == 0)
{
@ -541,8 +556,6 @@ static void xbee_process_apiframes(FAR struct xbee_priv_s *priv,
priv->addr.eaddr[6] = frame->io_data[frame->io_offset++];
priv->addr.eaddr[5] = frame->io_data[frame->io_offset++];
priv->addr.eaddr[4] = frame->io_data[frame->io_offset++];
xbee_notify_respwaiter(priv, XBEE_RESP_AT_SERIALHIGH);
}
else if (memcmp(command, "SL", 2) == 0)
{
@ -550,27 +563,20 @@ static void xbee_process_apiframes(FAR struct xbee_priv_s *priv,
priv->addr.eaddr[2] = frame->io_data[frame->io_offset++];
priv->addr.eaddr[1] = frame->io_data[frame->io_offset++];
priv->addr.eaddr[0] = frame->io_data[frame->io_offset++];
xbee_notify_respwaiter(priv, XBEE_RESP_AT_SERIALLOW);
}
else if (memcmp(command, "MY", 2) == 0)
{
priv->addr.saddr[1] = frame->io_data[frame->io_offset++];
priv->addr.saddr[0] = frame->io_data[frame->io_offset++];
xbee_notify_respwaiter(priv, XBEE_RESP_AT_SOURCEADDR);
}
else if (memcmp(command, "CH", 2) == 0)
{
priv->chan = frame->io_data[frame->io_offset++];
xbee_notify_respwaiter(priv, XBEE_RESP_AT_CHAN);
}
else if (memcmp(command, "VR", 2) == 0)
{
priv->firmwareversion = frame->io_data[frame->io_offset++] << 8;
priv->firmwareversion |= frame->io_data[frame->io_offset++];
xbee_notify_respwaiter(priv, XBEE_RESP_AT_FIRMWAREVERSION);
}
else if (memcmp(command, "AI", 2) == 0)
{
@ -584,22 +590,19 @@ static void xbee_process_apiframes(FAR struct xbee_priv_s *priv,
{
wd_cancel(priv->assocwd);
xbee_lock(priv, false);
xbee_notif_alloc(priv, &notif, false);
xbee_unlock(priv);
notif->notiftype = IEEE802154_NOTIFY_CONF_ASSOC;
primitive = ieee802154_primitive_allocate();
primitive->type = IEEE802154_PRIMITIVE_CONF_ASSOC;
if (frame->io_data[frame->io_offset] == 0)
{
notif->u.assocconf.status = IEEE802154_STATUS_SUCCESS;
primitive->u.assocconf.status = IEEE802154_STATUS_SUCCESS;
}
else
{
notif->u.assocconf.status = IEEE802154_STATUS_FAILURE;
primitive->u.assocconf.status = IEEE802154_STATUS_FAILURE;
}
xbee_notify(priv, notif);
xbee_notify(priv, primitive);
}
}
else if (memcmp(command, "A1", 2) == 0)
@ -626,6 +629,15 @@ static void xbee_process_apiframes(FAR struct xbee_priv_s *priv,
{
wlwarn("Unhandled AT Response: %.*s\n", 2, command);
}
/* If this is the command we are querying for */
if ((priv->querycmd[0] == *command) &&
(priv->querycmd[1] == *(command + 1)))
{
priv->querydone = true;
nxsem_post(&priv->atresp_sem);
}
}
}
break;
@ -633,11 +645,13 @@ static void xbee_process_apiframes(FAR struct xbee_priv_s *priv,
{
xbee_process_txstatus(priv, frame->io_data[frame->io_offset],
frame->io_data[frame->io_offset + 1]);
nxsem_post(&priv->txdone_sem);
}
break;
case XBEE_APIFRAME_RX_EADDR:
{
nextframe = frame->io_flink;
frame->io_flink = NULL;
xbee_process_rxframe(priv, frame, IEEE802154_ADDRMODE_EXTENDED);
frame = nextframe;
@ -650,6 +664,7 @@ static void xbee_process_apiframes(FAR struct xbee_priv_s *priv,
case XBEE_APIFRAME_RX_SADDR:
{
nextframe = frame->io_flink;
frame->io_flink = NULL;
xbee_process_rxframe(priv, frame, IEEE802154_ADDRMODE_SHORT);
frame = nextframe;
@ -670,7 +685,15 @@ static void xbee_process_apiframes(FAR struct xbee_priv_s *priv,
break;
}
/* IOB free logic assumes that a valid io_flink entry in the IOB that
* is being freed indicates that the IOB is a part of an IOB chain. Since
* that is not the case here and we are just using the io_flink field
* as a way of managing a list of independent frames, we set the io_flink
* to NULL prior to freeing it.
*/
nextframe = frame->io_flink;
frame->io_flink = NULL;
iob_free(frame);
frame = nextframe;
}
@ -688,13 +711,15 @@ static void xbee_process_rxframe(FAR struct xbee_priv_s *priv,
FAR struct iob_s *frame,
enum ieee802154_addrmode_e addrmode)
{
FAR struct ieee802154_primitive_s *primitive;
FAR struct ieee802154_data_ind_s *dataind;
FAR struct xbee_maccb_s *cb;
int ret;
xbee_lock(priv, false);
xbee_dataind_alloc(priv, &dataind, false);
xbee_unlock(priv);
DEBUGASSERT(frame != NULL);
primitive = ieee802154_primitive_allocate();
dataind = &primitive->u.dataind;
primitive->type = IEEE802154_PRIMITIVE_IND_DATA;
dataind->frame = frame;
@ -742,34 +767,7 @@ static void xbee_process_rxframe(FAR struct xbee_priv_s *priv,
frame->io_len--; /* Remove the checksum */
/* If there are registered MCPS callback receivers registered,
* then forward the frame in priority order. If there are no
* registered receivers or if none of the receivers accept the
* data frame then drop the frame.
*/
for (cb = priv->cb; cb != NULL; cb = cb->flink)
{
/* Does this MAC client want frames? */
if (cb->rxframe != NULL)
{
/* Yes.. Offer this frame to the receiver */
ret = cb->rxframe(cb, dataind);
if (ret >= 0)
{
/* The receiver accepted and disposed of the frame and
* its metadata. We are done.
*/
return;
}
}
}
xbee_dataind_free((XBEEHANDLE)priv, dataind);
iob_free(frame);
xbee_notify(priv, primitive);
}
/****************************************************************************
@ -784,34 +782,188 @@ static void xbee_process_rxframe(FAR struct xbee_priv_s *priv,
static void xbee_process_txstatus(FAR struct xbee_priv_s *priv, uint8_t frameid,
uint8_t status)
{
FAR struct ieee802154_notif_s *notif;
FAR struct ieee802154_primitive_s *primitive;
xbee_lock(priv, false);
xbee_notif_alloc(priv, &notif, false);
xbee_unlock(priv);
primitive = ieee802154_primitive_allocate();
notif->notiftype = IEEE802154_NOTIFY_CONF_DATA;
primitive->type = IEEE802154_PRIMITIVE_CONF_DATA;
switch (status)
{
case 0x00:
notif->u.dataconf.status = IEEE802154_STATUS_SUCCESS;
primitive->u.dataconf.status = IEEE802154_STATUS_SUCCESS;
break;
case 0x01:
case 0x21:
notif->u.dataconf.status = IEEE802154_STATUS_NO_ACK;
primitive->u.dataconf.status = IEEE802154_STATUS_NO_ACK;
break;
case 0x02:
notif->u.dataconf.status = IEEE802154_STATUS_CHANNEL_ACCESS_FAILURE;
primitive->u.dataconf.status = IEEE802154_STATUS_CHANNEL_ACCESS_FAILURE;
break;
default:
notif->u.dataconf.status = IEEE802154_STATUS_FAILURE;
primitive->u.dataconf.status = IEEE802154_STATUS_FAILURE;
break;
}
wlinfo("TX done. Frame ID: %d Status: 0x%02X\n", frameid, status);
xbee_notify(priv, notif);
xbee_notify(priv, primitive);
}
/****************************************************************************
* Name: xbee_notify
*
* Description:
* Queue the primitive in the queue and queue work on the LPWORK
* queue if is not already scheduled.
*
* Assumptions:
* Called with the MAC locked
*
****************************************************************************/
static void xbee_notify(FAR struct xbee_priv_s *priv,
FAR struct ieee802154_primitive_s *primitive)
{
while (nxsem_wait(&priv->primitive_sem) < 0);
sq_addlast((FAR sq_entry_t *)primitive, &priv->primitive_queue);
nxsem_post(&priv->primitive_sem);
if (work_available(&priv->notifwork))
{
work_queue(LPWORK, &priv->notifwork, xbee_notify_worker,
(FAR void *)priv, 0);
}
}
/****************************************************************************
* Name: xbee_notify_worker
*
* Description:
* Pop each primitive off the queue and call the registered
* callbacks. There is special logic for handling ieee802154_data_ind_s.
*
****************************************************************************/
static void xbee_notify_worker(FAR void *arg)
{
FAR struct xbee_priv_s *priv = (FAR struct xbee_priv_s *)arg;
FAR struct xbee_maccb_s *cb;
FAR struct ieee802154_primitive_s *primitive;
int ret;
DEBUGASSERT(priv != NULL);
while (nxsem_wait(&priv->primitive_sem) < 0);
primitive =
(FAR struct ieee802154_primitive_s *)sq_remfirst(&priv->primitive_queue);
nxsem_post(&priv->primitive_sem);
while (primitive != NULL)
{
/* Data indications are a special case since the frame can only be passed to
* one place. The return value of the notify call is used to accept or reject
* the primitive. In the case of the data indication, there can only be one
* accept. Callbacks are stored in order of there receiver priority ordered
* when the callbacks are bound in mac802154_bind().
*/
if (primitive->type == IEEE802154_PRIMITIVE_IND_DATA)
{
bool dispose = true;
primitive->nclients = 1;
for (cb = priv->cb; cb != NULL; cb = cb->flink)
{
if (cb->notify != NULL)
{
ret = cb->notify(cb, primitive);
if (ret >= 0)
{
/* The receiver accepted and disposed of the frame and it's
* meta-data. We are done.
*/
dispose = false;
break;
}
}
}
if (dispose)
{
iob_free(primitive->u.dataind.frame);
ieee802154_primitive_free(primitive);
}
}
else
{
/* Set the number of clients count so that the primitive resources will be
* preserved until all clients are finished with it.
*/
primitive->nclients = priv->nclients;
/* Try to notify every registered MAC client */
for (cb = priv->cb; cb != NULL; cb = cb->flink)
{
if (cb->notify != NULL)
{
ret = cb->notify(cb, primitive);
if (ret < 0)
{
ieee802154_primitive_free(primitive);
}
}
else
{
ieee802154_primitive_free(primitive);
}
}
}
/* Get the next primitive then loop */
while (nxsem_wait(&priv->primitive_sem) < 0);
primitive =
(FAR struct ieee802154_primitive_s *)sq_remfirst(&priv->primitive_queue);
nxsem_post(&priv->primitive_sem);
}
}
/****************************************************************************
* Name: xbee_atquery_timeout
*
* Description:
* This function runs when an AT Query has timed out waiting for a response
* from the XBee module. This really should never happen, but if it does,
* handle it gracefully by retrying the query.
*
* Parameters:
* argc - The number of available arguments
* arg - The first argument
*
* Returned Value:
* None
*
* Assumptions:
*
****************************************************************************/
static void xbee_atquery_timeout(int argc, uint32_t arg, ...)
{
FAR struct xbee_priv_s *priv = (FAR struct xbee_priv_s *)arg;
DEBUGASSERT(priv != NULL);
wlwarn("AT Query timeout\n");
/* Wake the pending query thread so it can retry */
nxsem_post(&priv->atresp_sem);
}
/****************************************************************************
@ -860,26 +1012,28 @@ XBEEHANDLE xbee_init(FAR struct spi_dev_s *spi,
return NULL;
}
/* Allow exclusive access to the struct */
nxsem_init(&priv->exclsem, 0, 1);
/* Initialize the data indication and notifcation allocation pools */
xbee_notifpool_init(priv);
xbee_dataindpool_init(priv);
sq_init(&priv->waiter_queue);
priv->assocwd = wd_create();
priv->lower = lower;
priv->spi = spi;
nxsem_init(&priv->primitive_sem, 0, 1);
nxsem_init(&priv->atquery_sem, 0, 1);
nxsem_init(&priv->tx_sem, 0, 1);
nxsem_init(&priv->txdone_sem, 0, 0);
nxsem_setprotocol(&priv->txdone_sem, SEM_PRIO_NONE);
ieee802154_primitivepool_initialize();
sq_init(&priv->primitive_queue);
priv->assocwd = wd_create();
priv->atquery_wd = wd_create();
priv->frameid = 0; /* Frame ID should never be 0, but it is incremented
* in xbee_next_frameid before being used so it will be 1 */
priv->querycmd[0] = 0;
priv->querycmd[1] = 0;
/* Reset the XBee */
/* Reset the XBee radio */
priv->lower->reset(priv->lower);
@ -892,7 +1046,7 @@ XBEEHANDLE xbee_init(FAR struct spi_dev_s *spi,
* when a valid SPI frame is received.
*/
xbee_at_query(priv, "VR");
xbee_send_atquery(priv, "VR");
return (XBEEHANDLE)priv;
}
@ -1097,17 +1251,82 @@ void xbee_send_apiframe(FAR struct xbee_priv_s *priv,
}
/****************************************************************************
* Name: xbee_at_query
* Name: xbee_atquery
*
* Description:
* Helper function to query a AT Command value.
* Sends AT Query and waits for response from device
*
****************************************************************************/
void xbee_at_query(FAR struct xbee_priv_s *priv, FAR const char *atcommand)
int xbee_atquery(FAR struct xbee_priv_s *priv, FAR const char *atcommand)
{
int ret;
/* Only allow one query at a time */
ret = nxsem_wait(&priv->atquery_sem);
if (ret < 0)
{
DEBUGASSERT(ret == -EINTR);
return ret;
}
priv->querydone = false;
/* We reinitialize this every time, in case something gets out of phase with
* the timeout and the received response.
*/
nxsem_init(&priv->atresp_sem, 0, 0);
nxsem_setprotocol(&priv->atresp_sem, SEM_PRIO_NONE);
do
{
/* Setup a timeout */
(void)wd_start(priv->atquery_wd, XBEE_ATQUERY_TIMEOUT, xbee_atquery_timeout,
1, (wdparm_t)priv);
/* Send the query */
priv->querycmd[0] = *atcommand;
priv->querycmd[1] = *(atcommand + 1);
xbee_send_atquery(priv, atcommand);
/* Wait for the response to be received */
ret = nxsem_wait(&priv->atresp_sem);
if (ret < 0)
{
DEBUGASSERT(ret == -EINTR);
wd_cancel(priv->atquery_wd);
priv->querycmd[0] = 0;
priv->querycmd[1] = 0;
nxsem_post(&priv->atquery_sem);
return ret;
}
}
while (!priv->querydone);
nxsem_post(&priv->atquery_sem);
return OK;
}
/****************************************************************************
* Name: xbee_send_atquery
*
* Description:
* Helper function to send the AT query to the XBee
*
****************************************************************************/
void xbee_send_atquery(FAR struct xbee_priv_s *priv, FAR const char *atcommand)
{
uint8_t frame[8];
wlinfo("AT Query: %c%c\n", *atcommand, *(atcommand + 1));
frame[0] = XBEE_STARTBYTE;
frame[1] = 0;
frame[2] = 4;
@ -1121,145 +1340,6 @@ void xbee_at_query(FAR struct xbee_priv_s *priv, FAR const char *atcommand)
xbee_send_apiframe(priv, frame, 8);
}
/****************************************************************************
* Name: xbee_query_firmwareversion
*
* Description:
* Sends API frame with AT command request in order to get the firmware version
* from the device.
*
****************************************************************************/
void xbee_query_firmwareversion(FAR struct xbee_priv_s *priv)
{
struct xbee_respwaiter_s respwaiter;
respwaiter.resp_id = XBEE_RESP_AT_FIRMWAREVERSION;
nxsem_init(&respwaiter.sem, 0, 0);
nxsem_setprotocol(&respwaiter.sem, SEM_PRIO_NONE);
xbee_register_respwaiter(priv, &respwaiter);
xbee_at_query(priv, "VR");
nxsem_wait(&respwaiter.sem);
xbee_unregister_respwaiter(priv, &respwaiter);
nxsem_destroy(&respwaiter.sem);
}
/****************************************************************************
* Name: xbee_query_panid
*
* Description:
* Sends API frame with AT command request in order to get the PAN ID
* (Network ID) from the device.
*
****************************************************************************/
void xbee_query_panid(FAR struct xbee_priv_s *priv)
{
struct xbee_respwaiter_s respwaiter;
respwaiter.resp_id = XBEE_RESP_AT_NETWORKID;
nxsem_init(&respwaiter.sem, 0, 0);
nxsem_setprotocol(&respwaiter.sem, SEM_PRIO_NONE);
xbee_register_respwaiter(priv, &respwaiter);
xbee_at_query(priv, "ID");
nxsem_wait(&respwaiter.sem);
xbee_unregister_respwaiter(priv, &respwaiter);
nxsem_destroy(&respwaiter.sem);
}
/****************************************************************************
* Name: xbee_query_eaddr
*
* Description:
* Sends API frame with AT command request in order to get the IEEE 802.15.4
* Extended Address. (Serial Number) from the device.
*
****************************************************************************/
void xbee_query_eaddr(FAR struct xbee_priv_s *priv)
{
struct xbee_respwaiter_s respwaiter;
respwaiter.resp_id = XBEE_RESP_AT_SERIALHIGH;
nxsem_init(&respwaiter.sem, 0, 0);
nxsem_setprotocol(&respwaiter.sem, SEM_PRIO_NONE);
xbee_register_respwaiter(priv, &respwaiter);
xbee_at_query(priv, "SH");
nxsem_wait(&respwaiter.sem);
respwaiter.resp_id = XBEE_RESP_AT_SERIALLOW;
xbee_at_query(priv, "SL");
nxsem_wait(&respwaiter.sem);
xbee_unregister_respwaiter(priv, &respwaiter);
nxsem_destroy(&respwaiter.sem);
}
/****************************************************************************
* Name: xbee_query_saddr
*
* Description:
* Sends API frame with AT command request in order to get the
* Short Address. (Source Address (MY)) from the device.
*
****************************************************************************/
void xbee_query_saddr(FAR struct xbee_priv_s *priv)
{
struct xbee_respwaiter_s respwaiter;
respwaiter.resp_id = XBEE_RESP_AT_SOURCEADDR;
nxsem_init(&respwaiter.sem, 0, 0);
nxsem_setprotocol(&respwaiter.sem, SEM_PRIO_NONE);
xbee_register_respwaiter(priv, &respwaiter);
xbee_at_query(priv, "MY");
nxsem_wait(&respwaiter.sem);
xbee_unregister_respwaiter(priv, &respwaiter);
nxsem_destroy(&respwaiter.sem);
}
/****************************************************************************
* Name: xbee_query_chan
*
* Description:
* Sends API frame with AT command request in order to get the RF Channel
* (Operating Channel) from the device.
*
****************************************************************************/
void xbee_query_chan(FAR struct xbee_priv_s *priv)
{
struct xbee_respwaiter_s respwaiter;
respwaiter.resp_id = XBEE_RESP_AT_CHAN;
nxsem_init(&respwaiter.sem, 0, 0);
nxsem_setprotocol(&respwaiter.sem, SEM_PRIO_NONE);
xbee_register_respwaiter(priv, &respwaiter);
xbee_at_query(priv, "CH");
nxsem_wait(&respwaiter.sem);
xbee_unregister_respwaiter(priv, &respwaiter);
nxsem_destroy(&respwaiter.sem);
}
/****************************************************************************
* Name: xbee_set_panid
*
@ -1470,8 +1550,8 @@ void xbee_regdump(FAR struct xbee_priv_s *priv)
wlinfo("XBee Firmware Version: %04x\n", priv->firmwareversion);
xbee_at_query(priv, "CE");
xbee_at_query(priv, "A1");
xbee_at_query(priv, "A2");
xbee_at_query(priv, "SP");
xbee_send_atquery(priv, "CE");
xbee_send_atquery(priv, "A1");
xbee_send_atquery(priv, "A2");
xbee_send_atquery(priv, "SP");
}

View File

@ -49,19 +49,17 @@
#include <nuttx/wqueue.h>
#include <nuttx/spi/spi.h>
#include <nuttx/wireless/ieee802154/ieee802154_mac.h>
#include <nuttx/wireless/ieee802154/xbee.h>
#include "xbee_notif.h"
#include "xbee_dataind.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Configuration *************************************************************/
#ifndef CONFIG_SCHED_HPWORK
# error High priority work queue required in this driver
#if !defined(CONFIG_SCHED_HPWORK) || !defined(CONFIG_SCHED_LPWORK)
# error Both Low and High priority work queues are required for this driver
#endif
#ifndef CONFIG_IEEE802154_XBEE_FREQUENCY
@ -72,16 +70,6 @@
# error CONFIG_SPI_EXCHANGE required for this driver
#endif
#if !defined(CONFIG_XBEE_NNOTIF) || CONFIG_XBEE_NNOTIF <= 0
# undef CONFIG_XBEE_NNOTIF
# define CONFIG_XBEE_NNOTIF 6
#endif
#if !defined(CONFIG_XBEE_NDATAIND) || CONFIG_XBEE_NDATAIND <= 0
# undef CONFIG_XBEE_NDATAIND
# define CONFIG_XBEE_NDATAIND 8
#endif
#define XBEE_APIFRAME_MODEMSTATUS 0x8A
#define XBEE_APIFRAME_ATCOMMMAND 0x08
#define XBEE_APIFRAME_ATCOMMMANDQUEUED 0x09
@ -166,22 +154,29 @@ struct xbee_priv_s
FAR const struct xbee_lower_s *lower;
FAR struct spi_dev_s *spi; /* Saved SPI interface instance */
FAR struct xbee_maccb_s *cb; /* Head of a list of XBee MAC callbacks */
/* Fields related to interface with next layer */
FAR struct xbee_maccb_s *cb; /* Head of a list of XBee MAC callbacks */
uint8_t nclients; /* Number of registered callbacks */
FAR struct iob_s *rx_apiframes; /* List of incoming API frames to process */
struct work_s notifwork; /* For deferring notifications to LPWORK queue*/
struct work_s attnwork; /* For deferring interrupt work to work queue */
sem_t exclsem; /* Exclusive access to this struct */
volatile bool attn_latched; /* Latched state of ATTN */
sem_t primitive_sem; /* Exclusive access to the primitive queue */
sq_queue_t primitive_queue; /* Queue of primitives to pass via notify()
* callback to registered receivers */
WDOG_ID assocwd; /* Association watchdog */
struct work_s assocwork; /* For polling for association status */
volatile bool attn_latched; /* Latched state of ATTN */
sq_queue_t waiter_queue; /* List of response waiters */
sq_queue_t tx_queue; /* List of pending TX requests */
sem_t atquery_sem; /* Only allow one AT query at a time */
sem_t atresp_sem; /* For signaling pending AT response received */
char querycmd[2]; /* Stores the pending AT Query command */
bool querydone; /* Used to tell waiting thread query is done*/
WDOG_ID atquery_wd; /* Support AT Query timeout and retry */
uint8_t frameid; /* For differentiating AT request/response */
sem_t tx_sem; /* Support a single pending transmit */
sem_t txdone_sem; /* For signalling tx is completed */
/******************* Fields related to Xbee radio ***************************/
uint16_t firmwareversion;
@ -190,32 +185,8 @@ struct xbee_priv_s
/* Holds all address information (Extended, Short, and PAN ID) for the MAC. */
struct ieee802154_addr_s addr;
struct ieee802154_pandesc_s pandesc;
/******************* Fields related to notifications ************************/
/* Pre-allocated notifications to be passed to the registered callback. These
* need to be freed by the application using xbee_xxxxnotif_free when
* the callee layer is finished with it's use.
*/
FAR struct xbee_notif_s *notif_free;
struct xbee_notif_s notif_pool[CONFIG_XBEE_NNOTIF];
sem_t notif_sem;
uint8_t nclients;
/******************* Fields related to data indications *********************/
/* Pre-allocated notifications to be passed to the registered callback. These
* need to be freed by the application using xbee_dataind_free when
* the callee layer is finished with it's use.
*/
FAR struct xbee_dataind_s *dataind_free;
struct xbee_dataind_s dataind_pool[CONFIG_XBEE_NDATAIND];
sem_t dataind_sem;
/****************** Uncategorized MAC PIB attributes ***********************/
/* What type of device is this node acting as */
@ -235,123 +206,6 @@ struct xbee_priv_s
* Inline Functions
****************************************************************************/
#define xbee_givesem(s) nxsem_post(s)
static inline int xbee_takesem(sem_t *sem, bool allowinterrupt)
{
int ret;
do
{
/* Take a count from the semaphore, possibly waiting */
ret = nxsem_wait(sem);
if (ret < 0)
{
/* EINTR is the only error that we expect */
DEBUGASSERT(ret == -EINTR);
if (allowinterrupt)
{
return ret;
}
}
}
while (ret == -EINTR);
return ret;
}
#ifdef CONFIG_XBEE_LOCK_VERBOSE
#define xbee_unlock(dev) \
xbee_givesem(&dev->exclsem); \
wlinfo("MAC unlocked\n");
#else
#define xbee_unlock(dev) \
xbee_givesem(&dev->exclsem);
#endif
#define xbee_lock(dev, allowinterrupt) \
xbee_lockpriv(dev, allowinterrupt, __FUNCTION__)
static inline int xbee_lockpriv(FAR struct xbee_priv_s *dev,
bool allowinterrupt, FAR const char *funcname)
{
int ret;
#ifdef CONFIG_XBEE_LOCK_VERBOSE
wlinfo("Locking MAC: %s\n", funcname);
#endif
ret = xbee_takesem(&dev->exclsem, allowinterrupt);
if (ret < 0)
{
wlwarn("Failed to lock MAC\n");
}
else
{
#ifdef CONFIG_XBEE_LOCK_VERBOSE
wlinfo("MAC locked\n");
#endif
}
return ret;
}
/****************************************************************************
* Name: xbee_register_respwaiter
*
* Description:
* Register a respone waiter
*
****************************************************************************/
static inline void xbee_register_respwaiter(FAR struct xbee_priv_s *priv,
FAR struct xbee_respwaiter_s *waiter)
{
sq_addlast((sq_entry_t *)waiter, &priv->waiter_queue);
}
/****************************************************************************
* Name: xbee_unregister_respwaiter
*
* Description:
* Unregister a respone waiter
*
****************************************************************************/
static inline void xbee_unregister_respwaiter(FAR struct xbee_priv_s *priv,
FAR struct xbee_respwaiter_s *waiter)
{
sq_rem((sq_entry_t *)waiter, &priv->waiter_queue);
}
/****************************************************************************
* Name: xbee_notify_respwaiter
*
* Description:
* Check to see if there are any respwaiters waiting for this response type.
* If so, signal them.
*
****************************************************************************/
static inline void xbee_notify_respwaiter(FAR struct xbee_priv_s *priv,
enum xbee_response_e resp_id)
{
FAR struct xbee_respwaiter_s *waiter;
waiter = (FAR struct xbee_respwaiter_s *)sq_peek(&priv->waiter_queue);
while (waiter != NULL)
{
if (waiter->resp_id == resp_id)
{
nxsem_post(&waiter->sem);
}
waiter = (FAR struct xbee_respwaiter_s *)sq_next((FAR sq_entry_t *)waiter);
}
}
/****************************************************************************
* Name: xbee_next_frameid
*
@ -418,14 +272,24 @@ void xbee_send_apiframe(FAR struct xbee_priv_s *priv,
FAR const uint8_t *frame, uint16_t framelen);
/****************************************************************************
* Name: xbee_at_query
* Name: xbee_atquery
*
* Description:
* Helper function to query a AT Command value.
* Sends AT Query and waits for response from device
*
****************************************************************************/
void xbee_at_query(FAR struct xbee_priv_s *priv, FAR const char *atcommand);
int xbee_atquery(FAR struct xbee_priv_s *priv, FAR const char *atcommand);
/****************************************************************************
* Name: xbee_send_atquery
*
* Description:
* Helper function to send the AT query to the XBee
*
****************************************************************************/
void xbee_send_atquery(FAR struct xbee_priv_s *priv, FAR const char *atcommand);
/****************************************************************************
* Name: xbee_query_firmwareversion
@ -436,7 +300,7 @@ void xbee_at_query(FAR struct xbee_priv_s *priv, FAR const char *atcommand);
*
****************************************************************************/
void xbee_query_firmwareversion(FAR struct xbee_priv_s *priv);
#define xbee_query_firmwareversion(priv) xbee_atquery(priv, "VR")
/****************************************************************************
* Name: xbee_query_panid
@ -447,7 +311,7 @@ void xbee_query_firmwareversion(FAR struct xbee_priv_s *priv);
*
****************************************************************************/
void xbee_query_panid(FAR struct xbee_priv_s *priv);
#define xbee_query_panid(priv) xbee_atquery(priv, "ID")
/****************************************************************************
* Name: xbee_query_eaddr
@ -458,7 +322,8 @@ void xbee_query_panid(FAR struct xbee_priv_s *priv);
*
****************************************************************************/
void xbee_query_eaddr(FAR struct xbee_priv_s *priv);
#define xbee_query_eaddr(priv) xbee_atquery(priv, "SH"); \
xbee_atquery(priv, "SL")
/****************************************************************************
* Name: xbee_query_saddr
@ -469,7 +334,7 @@ void xbee_query_eaddr(FAR struct xbee_priv_s *priv);
*
****************************************************************************/
void xbee_query_saddr(FAR struct xbee_priv_s *priv);
#define xbee_query_saddr(priv) xbee_atquery(priv, "MY")
/****************************************************************************
* Name: xbee_query_chan
@ -480,7 +345,7 @@ void xbee_query_saddr(FAR struct xbee_priv_s *priv);
*
****************************************************************************/
void xbee_query_chan(FAR struct xbee_priv_s *priv);
#define xbee_query_chan(priv) xbee_atquery(priv, "CH")
/****************************************************************************
* Name: xbee_query_assoc
@ -491,7 +356,7 @@ void xbee_query_chan(FAR struct xbee_priv_s *priv);
*
****************************************************************************/
void xbee_query_assoc(FAR struct xbee_priv_s *priv);
#define xbee_query_assoc(priv) xbee_atquery(priv "AI")
/****************************************************************************
* Name: xbee_set_panid

View File

@ -1,203 +0,0 @@
/****************************************************************************
* drivers/wireless/ieee802154/xbee/xbee_dataind.c
*
* Copyright (C) 2017 Verge Inc. All rights reserved.
* Author: Anthony Merlino <anthony@vergeaero.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <string.h>
#include <nuttx/semaphore.h>
#include <nuttx/wireless/ieee802154/ieee802154_mac.h>
#include <nuttx/wireless/ieee802154/xbee.h>
#include "xbee.h"
#include "xbee_mac.h"
#include "xbee_notif.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: xbee_dataind_free
*
* Description:
* When the XBee driver calls the registered rxframe function, it passes a
* reference to a ieee802154_data_ind_s structure. This structure needs to be
* freed after the handler is done using it.
*
****************************************************************************/
void xbee_dataind_free(XBEEHANDLE xbee, FAR struct ieee802154_data_ind_s *dataind)
{
FAR struct xbee_priv_s *priv = (FAR struct xbee_priv_s *)xbee;
FAR struct xbee_dataind_s *privind = (FAR struct xbee_dataind_s *)dataind;
xbee_lock(priv, false);
privind->flink = priv->dataind_free;
priv->dataind_free = privind;
xbee_givesem(&priv->dataind_sem);
xbee_unlock(priv);
}
/****************************************************************************
* Name: xbee_datatindpool_init
*
* Description:
* This function initializes the data indication structure pool. It allows the
* XBee driver to pass received frames with meta data to the callee, where they
* can free them when the calle is done using them, saving copying the data
* when passing.
*
****************************************************************************/
void xbee_dataindpool_init(FAR struct xbee_priv_s *priv)
{
FAR struct xbee_dataind_s *pool = priv->dataind_pool;
int remaining = CONFIG_XBEE_NDATAIND;
priv->dataind_free = NULL;
while (remaining > 0)
{
FAR struct xbee_dataind_s *dataind = pool;
/* Add the next meta data structure from the pool to the list of
* general structures.
*/
dataind->flink = priv->dataind_free;
priv->dataind_free = dataind;
/* Set up for the next structure from the pool */
pool++;
remaining--;
}
nxsem_init(&priv->dataind_sem, 0, CONFIG_XBEE_NDATAIND);
}
/****************************************************************************
* Name: xbee_dataind_alloc
*
* Description:
* This function allocates a free data indication structure from the free list
* to be used for passing to the registered rxframe callback. The callee software
* is responsible for freeing the data indication structure after it is done using
* it via xbee_data_ind_sfree.
*
* Assumptions:
* priv XBee struct is locked when calling.
*
* Notes:
* If any of the semaphore waits inside this function get interrupted, the
* function will release the MAC layer. If this function returns -EINTR, the
* calling code should NOT release the MAC semaphore.
*
****************************************************************************/
int xbee_dataind_alloc(FAR struct xbee_priv_s *priv,
FAR struct ieee802154_data_ind_s **dataind,
bool allow_interrupt)
{
int ret;
FAR struct xbee_dataind_s *privind;
/* Try and take a count from the semaphore. If this succeeds, we have
* "reserved" the structure, but still need to unlink it from the free list.
* The MAC is already locked, so there shouldn't be any other conflicting calls
*/
ret = nxsem_trywait(&priv->dataind_sem);
if (ret == OK)
{
privind = priv->dataind_free;
priv->dataind_free = privind->flink;
}
else
{
wlinfo("waiting for dataind to be free\n");
/* Unlock XBee driver so that other work can be done to free a data indication */
xbee_unlock(priv);
/* Take a count from the indication semaphore, waiting if necessary. We
* only return from here with an error if we are allowing interruptions
* and we received a signal */
ret = xbee_takesem(&priv->dataind_sem, allow_interrupt);
if (ret < 0)
{
/* MAC sem is already released */
return -EINTR;
}
/* If we've taken a count from the semaphore, we have "reserved" the struct
* but now we need to pop it off of the free list. We need to re-lock the
* MAC in order to ensure this happens correctly.
*/
ret = xbee_lock(priv, allow_interrupt);
if (ret < 0)
{
xbee_givesem(&priv->dataind_sem);
return -EINTR;
}
/* We can now safely unlink the next free structure from the free list */
privind = priv->dataind_free;
priv->dataind_free = privind->flink;
wlinfo("dataind allocated\n");
}
*dataind = (FAR struct ieee802154_data_ind_s *)privind;
return OK;
}

View File

@ -1,77 +0,0 @@
/****************************************************************************
* drivers/wireless/ieee802154/xbee/xbee_dataind.h
*
* Copyright (C) 2017 Verge Inc. All rights reserved.
*
* Author: Anthony Merlino <anthony@vergeaero.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __DRIVERS_WIRELESS_IEEE802154_XBEE_DATAIND_H
#define __DRIVERS_WIRELESS_IEEE802154_XBEE_DATAIND_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <stdbool.h>
#include <nuttx/wireless/ieee802154/ieee802154_mac.h>
/****************************************************************************
* Private Types
****************************************************************************/
/* Extend the public ieee802154_data_ind_s to include a private forward link to
* support a list to handle allocation
*/
struct xbee_dataind_s
{
struct ieee802154_data_ind_s pub; /* Publically visible structure */
FAR struct xbee_dataind_s *flink; /* Supports a singly linked list */
};
/****************************************************************************
* Function Prototypes
****************************************************************************/
struct xbee_priv_s; /* Forward Reference */
void xbee_dataindpool_init(FAR struct xbee_priv_s *priv);
int xbee_dataind_alloc(FAR struct xbee_priv_s *priv,
FAR struct ieee802154_data_ind_s **dataind,
bool allow_interrupt);
#endif /* __DRIVERS_WIRELESS_IEEE802154_XBEE_DATAIND_H */

View File

@ -128,7 +128,7 @@ static void xbee_assoctimer(int argc, uint32_t arg, ...)
* Description:
* Poll the device for the assosciation status. This function is indirectly
* scheduled rom xbee_req_associate in order to poll the device for association
* progress.
* progress.
*
* Parameters:
* arg - The reference to the driver structure (cast to void*)
@ -144,7 +144,7 @@ static void xbee_assocworker(FAR void *arg)
{
FAR struct xbee_priv_s *priv = (FAR struct xbee_priv_s *)arg;
xbee_at_query(priv, "AI");
xbee_send_atquery(priv, "AI");
(void)wd_start(priv->assocwd, XBEE_ASSOC_POLLDELAY, xbee_assoctimer, 1, (wdparm_t)arg);
}
@ -268,6 +268,10 @@ int xbee_req_data(XBEEHANDLE xbee,
int prevoffs = frame->io_offset;
#endif
/* Support one pending transmit at a time */
while (nxsem_wait(&priv->tx_sem) < 0);
/* Figure out how much room we need to place the API frame header */
if (meta->destaddr.mode == IEEE802154_ADDRMODE_EXTENDED)
@ -326,6 +330,11 @@ int xbee_req_data(XBEEHANDLE xbee,
xbee_send_apiframe(priv, &frame->io_data[frame->io_offset],
(frame->io_len - frame->io_offset));
/* Wait for a transmit status to be received. Does not necessarily mean success */
while (nxsem_wait(&priv->txdone_sem) < 0);
nxsem_post(&priv->tx_sem);
iob_free(frame);
return OK;
}

View File

@ -70,12 +70,18 @@ struct xbee_maccb_s
FAR struct xbee_maccb_s *flink; /* Implements a singly linked list */
uint8_t prio; /* RX frame callback priority */
/* Callback methods */
/* Callback for various MLME or MCPS service events. Return value represents
* whether the callback accepts the primitive. >= 0 means the callback has
* accepted the primitive and is responsible for calling
* ieee802154_primitive_free(). In the case of DATA.indication primitive, only
* one callback can accept the frame. The callbacks are stored in order of
* receiver priority defined by the 'prio' field above. All other
* notifications are offered to all callbacks and all can accept and free
* separately since the primitive will not be freed until the nclients count
* reaches 0. */
CODE void (*notify)(FAR struct xbee_maccb_s *maccb,
FAR struct ieee802154_notif_s *notif);
CODE int (*rxframe)(FAR struct xbee_maccb_s *maccb,
FAR struct ieee802154_data_ind_s *ind);
CODE int (*notify)(FAR struct xbee_maccb_s *maccb,
FAR struct ieee802154_primitive_s *primitive);
};
/****************************************************************************
@ -235,28 +241,4 @@ int xbee_req_associate(XBEEHANDLE xbee, FAR struct ieee802154_assoc_req_s *req);
int xbee_req_reset(XBEEHANDLE xbee, bool resetattr);
/****************************************************************************
* Name: xbee_notif_free
*
* Description:
* When the XBee driver calls the registered callback, it passes a reference
* to a ieee802154_notif_s structure. This structure needs to be freed
* after the callback handler is done using it.
*
****************************************************************************/
void xbee_notif_free(XBEEHANDLE mac, FAR struct ieee802154_notif_s *notif);
/****************************************************************************
* Name: xbee_dataind_free
*
* Description:
* When the XBee driver calls the registered callback, it passes a reference
* to a ieee802154_data_ind_s structure. This structure needs to be freed
* after the callback handler is done using it.
*
****************************************************************************/
void xbee_dataind_free(XBEEHANDLE mac, FAR struct ieee802154_data_ind_s *dataind);
#endif /* __DRIVERS_WIRELESS_IEEE802154_XBEE_MAC_H */

View File

@ -140,12 +140,12 @@ struct xbeenet_driver_s
{
/* This holds the information visible to the NuttX network */
struct radio_driver_s xd_dev; /* Interface understood by the network */
/* Cast compatible with struct xbeenet_driver_s */
struct radio_driver_s xd_dev; /* Interface understood by the network
* Cast compatible with struct xbeenet_driver_s */
/* For internal use by this driver */
sem_t xd_exclsem; /* Exclusive access to struct */
sem_t xd_exclsem; /* Exclusive access to struct */
struct xbeenet_callback_s xd_cb; /* Callback information */
XBEEHANDLE xd_mac; /* Contained XBee MAC interface */
bool xd_bifup; /* true:ifup false:ifdown */
@ -154,11 +154,10 @@ struct xbeenet_driver_s
/* Hold a list of events */
bool xd_enableevents : 1; /* Are events enabled? */
bool xd_eventpending : 1; /* Is there a get event using the semaphore? */
sem_t xd_eventsem; /* Signaling semaphore for waiting get event */
FAR struct ieee802154_notif_s *xd_eventhead;
FAR struct ieee802154_notif_s *xd_eventtail;
bool xd_enableevents : 1; /* Are events enabled? */
bool xd_eventpending : 1; /* Is there a get event using the semaphore? */
sem_t xd_eventsem; /* Signaling semaphore for waiting get event */
sq_queue_t primitive_queue; /* For holding primitives to pass along */
#ifndef CONFIG_DISABLE_SIGNALS
/* MAC Service notification information */
@ -178,23 +177,13 @@ struct xbeenet_driver_s
static int xbeenet_set_ipaddress(FAR struct net_driver_s *dev);
static inline void xbeenet_netmask(FAR struct net_driver_s *dev);
static inline void xbeenet_pushevent(FAR struct xbeenet_driver_s *priv,
FAR struct ieee802154_notif_s *notif);
static inline FAR struct ieee802154_notif_s *
xbeenet_popevent(FAR struct xbeenet_driver_s *priv);
/* IEE802.15.4 MAC callback functions ***************************************/
static void xbeenet_notify(FAR struct xbee_maccb_s *maccb,
FAR struct ieee802154_notif_s *notif);
static int xbeenet_rxframe(FAR struct xbee_maccb_s *maccb,
static int xbeenet_notify(FAR struct xbee_maccb_s *maccb,
FAR struct ieee802154_primitive_s *primitive);
static int xbeenet_rxframe(FAR struct xbeenet_driver_s *maccb,
FAR struct ieee802154_data_ind_s *ind);
/* Asynchronous event indications, replied to synchronously with responses.
* (none are implemented).
*/
/* Network interface support ************************************************/
/* Common TX logic */
@ -390,63 +379,6 @@ static inline void xbeenet_netmask(FAR struct net_driver_s *dev)
#endif
}
/****************************************************************************
* Name: xbeenet_pushevent
*
* Description:
* Push event onto the event queue
*
* Assumptions:
* Called with the device struct locked.
*
****************************************************************************/
static inline void xbeenet_pushevent(FAR struct xbeenet_driver_s *priv,
FAR struct ieee802154_notif_s *notif)
{
notif->flink = NULL;
if (!priv->xd_eventhead)
{
priv->xd_eventhead = notif;
priv->xd_eventtail = notif;
}
else
{
priv->xd_eventtail->flink = notif;
priv->xd_eventtail = notif;
}
}
/****************************************************************************
* Name: xbeenet_popevent
*
* Description:
* Pop an event off of the event queue
*
* Assumptions:
* Called with the device struct locked.
*
****************************************************************************/
static inline FAR struct ieee802154_notif_s *
xbeenet_popevent(FAR struct xbeenet_driver_s *priv)
{
FAR struct ieee802154_notif_s *notif = priv->xd_eventhead;
if (notif)
{
priv->xd_eventhead = notif->flink;
if (!priv->xd_eventhead)
{
priv->xd_eventhead = NULL;
}
notif->flink = NULL;
}
return notif;
}
/****************************************************************************
* Name: xbeenet_notify
*
@ -454,8 +386,8 @@ static inline FAR struct ieee802154_notif_s *
*
****************************************************************************/
static void xbeenet_notify(FAR struct xbee_maccb_s *maccb,
FAR struct ieee802154_notif_s *notif)
static int xbeenet_notify(FAR struct xbee_maccb_s *maccb,
FAR struct ieee802154_primitive_s *primitive)
{
FAR struct xbeenet_callback_s *cb =
(FAR struct xbeenet_callback_s *)maccb;
@ -464,20 +396,28 @@ static void xbeenet_notify(FAR struct xbee_maccb_s *maccb,
DEBUGASSERT(cb != NULL && cb->mc_priv != NULL);
priv = cb->mc_priv;
/* Get exclusive access to the driver structure. We don't care about any
* signals so if we see one, just go back to trying to get access again */
/* Handle the special case for data indications or "incoming frames" */
while (nxsem_wait(&priv->xd_exclsem) < 0);
if (primitive->type == IEEE802154_PRIMITIVE_IND_DATA)
{
return xbeenet_rxframe(priv, &primitive->u.dataind);
}
/* If there is a registered notification receiver, queue the event and signal
/* If there is a registered primitive receiver, queue the event and signal
* the receiver. Events should be popped from the queue from the application
* at a reasonable rate in order for the MAC layer to be able to allocate new
* notifications.
* primitives.
*/
if (priv->xd_enableevents)
{
xbeenet_pushevent(priv, notif);
/* Get exclusive access to the driver structure. We don't care about any
* signals so if we see one, just go back to trying to get access again
*/
while (nxsem_wait(&priv->xd_exclsem) < 0);
sq_addlast((FAR sq_entry_t *)primitive, &priv->primitive_queue);
/* Check if there is a read waiting for data */
@ -494,26 +434,25 @@ static void xbeenet_notify(FAR struct xbee_maccb_s *maccb,
{
#ifdef CONFIG_CAN_PASS_STRUCTS
union sigval value;
value.sival_int = (int)notif->notiftype;
value.sival_int = (int)primitive->type;
(void)nxsig_queue(priv->xd_notify_pid, priv->xd_notify_signo,
value);
#else
(void)nxsig_queue(priv->xd_notify_pid, priv->xd_notify_signo,
(FAR void *)notif->notiftype);
(FAR void *)primitive->type);
#endif
}
#endif
}
else
{
/* Just free the event if the driver is closed and there isn't a registered
* signal number.
*/
xbee_notif_free(priv->xd_mac, notif);
nxsem_post(&priv->xd_exclsem);
return OK;
}
nxsem_post(&priv->xd_exclsem);
/* By returning a negative value, we let the MAC know that we don't want the
* primitive and it will free it for us
*/
return -1;
}
/****************************************************************************
@ -529,18 +468,12 @@ static void xbeenet_notify(FAR struct xbee_maccb_s *maccb,
*
****************************************************************************/
static int xbeenet_rxframe(FAR struct xbee_maccb_s *maccb,
static int xbeenet_rxframe(FAR struct xbeenet_driver_s *priv,
FAR struct ieee802154_data_ind_s *ind)
{
FAR struct xbeenet_callback_s *cb =
(FAR struct xbeenet_callback_s *)maccb;
FAR struct xbeenet_driver_s *priv;
FAR struct iob_s *iob;
int ret;
DEBUGASSERT(cb != NULL && cb->mc_priv != NULL);
priv = cb->mc_priv;
/* Ignore the frame if the network is not up */
if (!priv->xd_bifup)
@ -558,6 +491,8 @@ static int xbeenet_rxframe(FAR struct xbee_maccb_s *maccb,
ind->frame = NULL;
net_lock();
/* Transfer the frame to the network logic */
#ifdef CONFIG_NET_IEEE802154
@ -595,9 +530,11 @@ static int xbeenet_rxframe(FAR struct xbee_maccb_s *maccb,
}
}
if (ret < 0)
#endif
{
net_unlock();
ind->frame = iob;
return ret;
}
@ -607,11 +544,13 @@ static int xbeenet_rxframe(FAR struct xbee_maccb_s *maccb,
NETDEV_RXPACKETS(&priv->xd_dev.r_dev);
NETDEV_RXIPV6(&priv->xd_dev.r_dev);
net_unlock();
/* sixlowpan_input() will free the IOB, but we must free the struct
* ieee802154_data_ind_s container here.
* ieee802154_primitive_s container here.
*/
xbee_dataind_free(priv->xd_mac, ind);
ieee802154_primitive_free((FAR struct ieee802154_primitive_s *)ind);
return OK;
}
@ -1134,25 +1073,27 @@ static int xbeenet_ioctl(FAR struct net_driver_s *dev, int cmd,
#endif
case MAC802154IOC_GET_EVENT:
{
FAR struct ieee802154_notif_s *notif;
FAR struct ieee802154_primitive_s *primitive;
while (1)
{
/* Try popping an event off the queue */
notif = xbeenet_popevent(priv);
primitive = (FAR struct ieee802154_primitive_s *)
sq_remfirst(&priv->primitive_queue);
/* If there was an event to pop off, copy it into the user
* data and free it from the MAC layer's memory.
*/
if (notif != NULL)
if (primitive != NULL)
{
memcpy(&netmac->u, notif, sizeof(struct ieee802154_notif_s));
memcpy(&netmac->u, primitive,
sizeof(struct ieee802154_primitive_s));
/* Free the notification */
/* Free the primitive */
xbee_notif_free(priv->xd_mac, notif);
ieee802154_primitive_free(primitive);
ret = OK;
break;
}
@ -1478,8 +1419,7 @@ int xbee_netdev_register(XBEEHANDLE xbee)
nxsem_init(&priv->xd_eventsem, 0, 0);
nxsem_setprotocol(&priv->xd_eventsem, SEM_PRIO_NONE);
priv->xd_eventhead = NULL;
priv->xd_eventtail = NULL;
sq_init(&priv->primitive_queue);
priv->xd_enableevents = false;
priv->xd_notify_registered = false;
@ -1492,7 +1432,6 @@ int xbee_netdev_register(XBEEHANDLE xbee)
maccb->flink = NULL;
maccb->prio = CONFIG_XBEE_NETDEV_RECVRPRIO;
maccb->notify = xbeenet_notify;
maccb->rxframe = xbeenet_rxframe;
/* Bind the callback structure */

View File

@ -1,284 +0,0 @@
/****************************************************************************
* drivers/wireless/ieee802154/xbee/xbee_notif.c
*
* Copyright (C) 2017 Verge Inc. All rights reserved.
* Author: Anthony Merlino <anthony@vergeaero.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <string.h>
#include "xbee.h"
#include "xbee_mac.h"
#include "xbee_notif.h"
#include <nuttx/semaphore.h>
#include <nuttx/wireless/ieee802154/ieee802154_mac.h>
#include <nuttx/wireless/ieee802154/xbee.h>
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: xbee_notif_free
*
* Description:
* When the XBee driver calls the registered callback, it passes a reference
* to a ieee802154_notif_s structure. This structure needs to be freed
* after the callback handler is done using it.
*
****************************************************************************/
void xbee_notif_free(XBEEHANDLE xbee, FAR struct ieee802154_notif_s *notif)
{
FAR struct xbee_priv_s *priv = (FAR struct xbee_priv_s *)xbee;
/* Lock the MAC */
xbee_lock(priv, false);
/* Call the internal helper function to free the notification */
xbee_notif_free_locked(priv, notif);
/* Unlock the MAC */
xbee_unlock(priv)
}
/****************************************************************************
* Internal MAC Functions
****************************************************************************/
/****************************************************************************
* Name: xbee_notifpool_init
*
* Description:
* This function initializes the notification structure pool. It allows the
* XBee driver to pass notifications and for the callee to free them when they
* are done using them, saving copying the data when passing.
*
****************************************************************************/
void xbee_notifpool_init(FAR struct xbee_priv_s *priv)
{
FAR struct xbee_notif_s *pool = priv->notif_pool;
int remaining = CONFIG_XBEE_NNOTIF;
priv->notif_free = NULL;
while (remaining > 0)
{
FAR struct xbee_notif_s *notif = pool;
/* Add the next meta data structure from the pool to the list of
* general structures.
*/
notif->flink = priv->notif_free;
priv->notif_free = notif;
/* Set up for the next structure from the pool */
pool++;
remaining--;
}
nxsem_init(&priv->notif_sem, 0, CONFIG_XBEE_NNOTIF);
}
/****************************************************************************
* Name: xbee_notif_alloc
*
* Description:
* This function allocates a free notification structure from the free list
* to be used for passing to the registered notify callback. The callee software
* is responsible for freeing the notification structure after it is done using
* it via xbee_notif_free.
*
* Assumptions:
* priv XBee struct is locked when calling.
*
* Notes:
* If any of the semaphore waits inside this function get interrupted, the
* function will release the MAC layer. If this function returns -EINTR, the
* calling code should NOT release the MAC semaphore.
*
****************************************************************************/
int xbee_notif_alloc(FAR struct xbee_priv_s *priv,
FAR struct ieee802154_notif_s **notif,
bool allow_interrupt)
{
int ret;
FAR struct xbee_notif_s *privnotif;
/* Try and take a count from the semaphore. If this succeeds, we have
* "reserved" the structure, but still need to unlink it from the free list.
* The MAC is already locked, so there shouldn't be any other conflicting calls
*/
ret = nxsem_trywait(&priv->notif_sem);
if (ret == OK)
{
privnotif = priv->notif_free;
priv->notif_free = privnotif->flink;
privnotif->nclients = 0;
}
else
{
/* Unlock XBee driver so that other work can be done to free a notification */
xbee_unlock(priv)
/* Take a count from the notification semaphore, waiting if necessary. We
* only return from here with an error if we are allowing interruptions
* and we received a signal */
ret = xbee_takesem(&priv->notif_sem, allow_interrupt);
if (ret < 0)
{
/* MAC sem is already released */
return -EINTR;
}
/* If we've taken a count from the semaphore, we have "reserved" the struct
* but now we need to pop it off of the free list. We need to re-lock the
* MAC in order to ensure this happens correctly.
*/
ret = xbee_lock(priv, allow_interrupt);
if (ret < 0)
{
xbee_givesem(&priv->notif_sem);
return -EINTR;
}
/* We can now safely unlink the next free structure from the free list */
privnotif = priv->notif_free;
priv->notif_free = privnotif->flink;
privnotif->nclients = 0;
}
*notif = (FAR struct ieee802154_notif_s *)privnotif;
return OK;
}
/****************************************************************************
* Name: xbee_notif_free_locked
*
* Description:
* When the XBee driver calls the registered callback, it passes a reference
* to a ieee802154_notif_s structure. This structure needs to be freed
* after the callback handler is done using it.
*
* Internal version that already has XBee driver locked
*
****************************************************************************/
void xbee_notif_free_locked(FAR struct xbee_priv_s * priv,
FAR struct ieee802154_notif_s *notif)
{
FAR struct xbee_notif_s *privnotif =
(FAR struct xbee_notif_s *)notif;
/* We know how many clients have registered for notifications. Each must
* call xbee_notif_free() before we can release the notification
* resource.
*/
if (privnotif->nclients < 2)
{
/* This is the free from the last notification */
privnotif->flink = priv->notif_free;
priv->notif_free = privnotif;
privnotif->nclients = 0;
xbee_givesem(&priv->notif_sem);
}
else
{
/* More calls are expected. Decrement the count of expected calls
* and preserve the notification resources.
*/
privnotif->nclients--;
}
}
/****************************************************************************
* Name: xbee_notify
*
* Description:
* Notify every register XBee MAC client.
*
****************************************************************************/
void xbee_notify(FAR struct xbee_priv_s *priv,
FAR struct ieee802154_notif_s *notif)
{
FAR struct xbee_maccb_s *cb;
FAR struct xbee_notif_s *privnotif = (FAR struct xbee_notif_s *)notif;
/* Set the notification count so that the notification resources will be
* preserved until the final notification.
*/
privnotif->nclients = priv->nclients;
/* Try to notify every registered XBee MAC client */
for (cb = priv->cb; cb != NULL; cb = cb->flink)
{
/* Does this client want notifications? */
if (cb->notify != NULL)
{
/* Yes.. Notify */
cb->notify(cb, notif);
}
}
}

View File

@ -1,84 +0,0 @@
/****************************************************************************
* drivers/wireless/ieee802154/xbee/xbee_notif.h
*
* Copyright (C) 2017 Verge Inc. All rights reserved.
*
* Author: Anthony Merlino <anthony@vergeaero.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __DRIVERS_WIRELESS_IEEE802154_XBEE_NOTIF_H
#define __DRIVERS_WIRELESS_IEEE802154_XBEE_NOTIF_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <stdbool.h>
#include <nuttx/wireless/ieee802154/ieee802154_mac.h>
/****************************************************************************
* Private Types
****************************************************************************/
/* Extend the public ieee802154_notif_s to include a private forward link to
* support a list to handle allocation
*/
struct xbee_notif_s
{
struct ieee802154_notif_s pub; /* Publically visible structure */
FAR struct xbee_notif_s *flink; /* Supports a singly linked list */
uint8_t nclients;
};
/****************************************************************************
* Function Prototypes
****************************************************************************/
struct xbee_priv_s; /* Forward Reference */
void xbee_notifpool_init(FAR struct xbee_priv_s *priv);
int xbee_notif_alloc(FAR struct xbee_priv_s *priv,
FAR struct ieee802154_notif_s **notif,
bool allow_interrupt);
void xbee_notify(FAR struct xbee_priv_s *priv,
FAR struct ieee802154_notif_s *notif);
void xbee_notif_free_locked(FAR struct xbee_priv_s * priv,
FAR struct ieee802154_notif_s *notif);
#endif /* __DRIVERS_WIRELESS_IEEE802154_XBEE_NOTIF_H */

View File

@ -66,7 +66,7 @@ struct mac802154dev_txframe_s
struct mac802154dev_rxframe_s
{
struct ieee802154_data_ind_s meta;
uint8_t payload[IEEE802154_MAX_MAC_PAYLOAD_SIZE];
uint8_t payload[IEEE802154_MAX_PHY_PACKET_SIZE];
uint16_t length;
};

View File

@ -756,6 +756,10 @@ struct ieee802154_frame_meta_s
struct ieee802154_data_conf_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
uint8_t handle; /* Handle assoc. with MSDU */
/* The time, in symbols, at which the data were transmitted */
@ -806,7 +810,9 @@ struct ieee802154_data_conf_s
struct ieee802154_data_ind_s
{
FAR struct ieee802154_data_ind_s *flink;
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
FAR struct iob_s *frame;
@ -883,6 +889,10 @@ struct ieee802154_data_ind_s
struct ieee802154_purge_req_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
uint8_t msdu_handle; /* Handle assoc. with MSDU */
};
@ -896,6 +906,10 @@ struct ieee802154_purge_req_s
struct ieee802154_assoc_req_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
uint8_t chan; /* Channel number to attempt association */
uint8_t chpage; /* Channel page to attempt association */
@ -954,6 +968,10 @@ struct ieee802154_assoc_req_s
struct ieee802154_assoc_ind_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
/* Address of device requesting association. Always in extended mode */
uint8_t devaddr[IEEE802154_EADDRSIZE];
@ -979,6 +997,10 @@ struct ieee802154_assoc_ind_s
struct ieee802154_assoc_resp_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
/* Address of device requesting association. Always in extended mode */
uint8_t devaddr[IEEE802154_EADDRSIZE];
@ -1009,6 +1031,10 @@ struct ieee802154_assoc_resp_s
struct ieee802154_assoc_conf_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
/* Associated device address ALWAYS passed in short address mode. The
* address will be IEEE802154_SADDR_UNSPEC if association was
* unsuccessful.
@ -1039,6 +1065,10 @@ struct ieee802154_assoc_conf_s
struct ieee802154_disassoc_req_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
/* Address of device to send disassociation notification */
struct ieee802154_addr_s dev_addr;
@ -1066,6 +1096,10 @@ struct ieee802154_disassoc_req_s
struct ieee802154_disassoc_ind_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
/* Address of device requesting disassociation. Always extended mode */
struct ieee802154_addr_s dev_addr;
@ -1091,6 +1125,10 @@ struct ieee802154_disassoc_ind_s
struct ieee802154_disassoc_conf_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
/* Status of the disassociation attempt */
enum ieee802154_status_e status;
@ -1114,6 +1152,10 @@ struct ieee802154_disassoc_conf_s
struct ieee802154_beacon_ind_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
uint8_t bsn; /* Beacon sequence number */
/* PAN descriptor for the received beacon */
@ -1137,6 +1179,10 @@ struct ieee802154_beacon_ind_s
struct ieee802154_commstatus_ind_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
struct ieee802154_addr_s src_addr;
struct ieee802154_addr_s dest_addr;
enum ieee802154_status_e status;
@ -1160,6 +1206,10 @@ struct ieee802154_commstatus_ind_s
struct ieee802154_gts_req_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
struct ieee802154_gts_info_s gts_info;
#ifdef CONFIG_IEEE802154_SECURITY
@ -1180,6 +1230,10 @@ struct ieee802154_gts_req_s
struct ieee802154_gts_conf_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
struct ieee802154_gts_info_s gts_info;
enum ieee802154_status_e status;
};
@ -1195,6 +1249,10 @@ struct ieee802154_gts_conf_s
struct ieee802154_gts_ind_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
uint16_t dev_addr;
struct ieee802154_gts_info_s gts_info;
@ -1216,6 +1274,10 @@ struct ieee802154_gts_ind_s
struct ieee802154_orphan_ind_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
uint8_t orphan_addr[8];
#ifdef CONFIG_IEEE802154_SECURITY
@ -1236,6 +1298,10 @@ struct ieee802154_orphan_ind_s
struct ieee802154_orphan_resp_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
uint8_t orphan_addr[8];
#ifdef CONFIG_IEEE802154_SECURITY
@ -1256,6 +1322,10 @@ struct ieee802154_orphan_resp_s
struct ieee802154_reset_req_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
bool resetattr;
};
@ -1270,6 +1340,10 @@ struct ieee802154_reset_req_s
struct ieee802154_rxenable_req_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
/* Number of symbols measured from the start of the superframe before the
* receiver is to be enabled or disabled.
*/
@ -1295,6 +1369,10 @@ struct ieee802154_rxenable_req_s
struct ieee802154_rxenable_conf_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
enum ieee802154_status_e status;
};
@ -1308,6 +1386,10 @@ struct ieee802154_rxenable_conf_s
struct ieee802154_scan_req_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
enum ieee802154_scantype_e type;
uint8_t duration;
uint8_t chpage;
@ -1331,6 +1413,10 @@ struct ieee802154_scan_req_s
struct ieee802154_scan_conf_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
enum ieee802154_status_e status;
enum ieee802154_scantype_e type;
uint8_t chpage;
@ -1351,6 +1437,10 @@ struct ieee802154_scan_conf_s
struct ieee802154_get_req_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
enum ieee802154_attr_e attr;
union ieee802154_attr_u attrval;
};
@ -1371,6 +1461,10 @@ struct ieee802154_get_req_s
struct ieee802154_set_req_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
enum ieee802154_attr_e attr;
union ieee802154_attr_u attrval;
};
@ -1388,6 +1482,10 @@ struct ieee802154_set_req_s
struct ieee802154_start_req_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
uint8_t panid[IEEE802154_PANIDSIZE];
uint8_t chan;
uint8_t chpage;
@ -1420,6 +1518,10 @@ struct ieee802154_start_req_s
struct ieee802154_start_conf_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
enum ieee802154_status_e status;
};
@ -1434,6 +1536,10 @@ struct ieee802154_start_conf_s
struct ieee802154_sync_req_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
uint8_t ch_num;
uint8_t ch_page;
bool track_beacon;
@ -1449,6 +1555,10 @@ struct ieee802154_sync_req_s
struct ieee802154_syncloss_ind_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
enum ieee802154_status_e loss_reason;
uint16_t pan_id;
uint8_t ch_num;
@ -1471,6 +1581,10 @@ struct ieee802154_syncloss_ind_s
struct ieee802154_poll_req_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
struct ieee802154_addr_s coordaddr;
#ifdef CONFIG_IEEE802154_SECURITY
@ -1490,44 +1604,50 @@ struct ieee802154_poll_req_s
struct ieee802154_poll_conf_s
{
/* Each primitive must have a forward-link to a primitive to support lists */
FAR struct ieee802154_primitive_s *flink;
enum ieee802154_status_e status;
};
/* MAC Service Notifications */
/* MAC Service Primitives */
enum ieee802154_notify_e
enum ieee802154_primitive_e
{
/* MCPS Notifications */
IEEE802154_NOTIFY_CONF_DATA = 0x00,
IEEE802154_PRIMITIVE_CONF_DATA = 0x00,
IEEE802154_PRIMITIVE_IND_DATA,
/* MLME Notifications */
IEEE802154_NOTIFY_CONF_ASSOC,
IEEE802154_NOTIFY_CONF_DISASSOC,
IEEE802154_NOTIFY_CONF_GTS,
IEEE802154_NOTIFY_CONF_RESET,
IEEE802154_NOTIFY_CONF_RXENABLE,
IEEE802154_NOTIFY_CONF_SCAN,
IEEE802154_NOTIFY_CONF_START,
IEEE802154_NOTIFY_CONF_POLL,
IEEE802154_PRIMITIVE_CONF_ASSOC,
IEEE802154_PRIMITIVE_CONF_DISASSOC,
IEEE802154_PRIMITIVE_CONF_GTS,
IEEE802154_PRIMITIVE_CONF_RESET,
IEEE802154_PRIMITIVE_CONF_RXENABLE,
IEEE802154_PRIMITIVE_CONF_SCAN,
IEEE802154_PRIMITIVE_CONF_START,
IEEE802154_PRIMITIVE_CONF_POLL,
IEEE802154_NOTIFY_IND_ASSOC,
IEEE802154_NOTIFY_IND_DISASSOC,
IEEE802154_NOTIFY_IND_BEACONNOTIFY,
IEEE802154_NOTIFY_IND_GTS,
IEEE802154_NOTIFY_IND_ORPHAN,
IEEE802154_NOTIFY_IND_COMMSTATUS,
IEEE802154_NOTIFY_IND_SYNCLOSS
IEEE802154_PRIMITIVE_IND_ASSOC,
IEEE802154_PRIMITIVE_IND_DISASSOC,
IEEE802154_PRIMITIVE_IND_BEACONNOTIFY,
IEEE802154_PRIMITIVE_IND_GTS,
IEEE802154_PRIMITIVE_IND_ORPHAN,
IEEE802154_PRIMITIVE_IND_COMMSTATUS,
IEEE802154_PRIMITIVE_IND_SYNCLOSS
};
union ieee802154_notif_u
union ieee802154_primitive_u
{
/* MCPS Notifications */
/* MCPS Primitives */
struct ieee802154_data_conf_s dataconf;
struct ieee802154_data_conf_s dataconf;
struct ieee802154_data_ind_s dataind;
/* MLME Notifications */
/* MLME Primitives */
struct ieee802154_assoc_conf_s assocconf;
struct ieee802154_disassoc_conf_s disassocconf;
@ -1544,23 +1664,23 @@ union ieee802154_notif_u
struct ieee802154_orphan_ind_s orphanind;
struct ieee802154_commstatus_ind_s commstatusind;
struct ieee802154_syncloss_ind_s synclossind;
/* Foward link contained as first entry of all primitives */
FAR struct ieee802154_primitive_s *flink;
};
struct ieee802154_notif_s
struct ieee802154_primitive_s
{
/* Must be first member so that we can interchange between the actual
* notification and this extended struct.
* primitive and this extended struct. Note, all frames also have the first
* entry as a forward link to a primitive so that primitives can be contained
* in lists.
*/
union ieee802154_notif_u u;
enum ieee802154_notify_e notiftype;
/* Support a singly linked list. For use by receivers. The MAC has it's own
* extended struct type with another forward link that the MAC uses internally
* to handle allocation and freeing.
*/
FAR struct ieee802154_notif_s *flink;
union ieee802154_primitive_u u;
enum ieee802154_primitive_e type;
int nclients; /* Number of clients to call ieee802154_primitive_free before freed */
};
/* A pointer to this structure is passed as the argument of each IOCTL
@ -1587,7 +1707,7 @@ union ieee802154_macarg_u
/* To be determined */ /* MAC802154IOC_MLME_CALIBRATE_REQUEST */
uint8_t signo; /* MAC802154IOC_NOTIFY_REGISTER */
struct ieee802154_notif_s notif; /* MAC802154IOC_GET_EVENT */
struct ieee802154_primitive_s primitive; /* MAC802154IOC_GET_EVENT */
bool enable; /* MAC802154IOC_ENABLE_EVENTS */
};
@ -1690,10 +1810,12 @@ int mac802154dev_register(MACHANDLE mac, int minor);
int mac802154netdev_register(MACHANDLE mac);
/****************************************************************************
* Name: ieee802154_indpool_initialize
* Name: ieee802154_primitivepool_initialize
*
* Description:
* This function initializes the meta-data allocator. This function must
* This function initializes the primitive allocator. Primitives are defined
* in the standard and are used to pass information between the MAC layer and
* the next highest layer. They are a data type abstraction. This function must
* be called early in the initialization sequence before any radios
* begin operation.
*
@ -1705,54 +1827,53 @@ int mac802154netdev_register(MACHANDLE mac);
*
****************************************************************************/
void ieee802154_indpool_initialize(void);
void ieee802154_primitivepool_initialize(void);
/****************************************************************************
* Name: ieee802154_ind_allocate
* Name: ieee802154_primitive_allocate
*
* Description:
* The ieee802154_ind_allocate function will get a free meta-data
* structure for use by the IEEE 802.15.4 MAC.
* The ieee802154_primitive_allocate function will get a free primitive
* structure from the pool, for use with the IEEE 802.15.4 MAC.
*
* Interrupt handling logic will first attempt to allocate from the
* g_indfree list. If that list is empty, it will attempt to allocate
* from its reserve, g_indfree_irq. If that list is empty, then the
* g_primfree list. If that list is empty, it will attempt to allocate
* from its reserve, g_primfree_irq. If that list is empty, then the
* allocation fails (NULL is returned).
*
* Non-interrupt handler logic will attempt to allocate from g_indfree
* list. If that the list is empty, then the meta-data structure will be
* Non-interrupt handler logic will attempt to allocate from g_primfree
* list. If that the list is empty, then the primitive structure will be
* allocated from the dynamic memory pool.
*
* Inputs:
* None
*
* Return Value:
* A reference to the allocated msg structure. All user fields in this
* A reference to the allocated primitive structure. All user fields in this
* structure have been zeroed. On a failure to allocate, NULL is
* returned.
*
****************************************************************************/
FAR struct ieee802154_data_ind_s *ieee802154_ind_allocate(void);
FAR struct ieee802154_primitive_s *ieee802154_primitive_allocate(void);
/****************************************************************************
* Name: ieee802154_ind_free
* Name: ieee802154_primitive_free
*
* Description:
* The ieee802154_ind_free function will return a meta-data structure to
* the free pool of messages if it was a pre-allocated meta-data
* structure. If the meta-data structure was allocated dynamically it will
* be deallocated.
* The ieee802154_primitive_free function will return a primitive structure to
* the free pool if it was a pre-allocated primitive structure. If the primitive
* was allocated dynamically it will be deallocated.
*
* Inputs:
* ind - meta-data structure to free
* prim - primitive structure to free
*
* Return Value:
* None
*
****************************************************************************/
void ieee802154_ind_free(FAR struct ieee802154_data_ind_s *ind);
void ieee802154_primitive_free(FAR struct ieee802154_primitive_s *prim);
#undef EXTERN
#ifdef __cplusplus

View File

@ -171,8 +171,8 @@ static inline bool ipfwd_addrchk(FAR struct forward_s *fwd)
else
#endif
{
#if !defined(CONFIG_NET_ICMPv6_NEIGHBOR)
FAR struct ipv6_hdr_s *ipv4 = (FAR struct ipv6_hdr_s *)fwd->f_iob->io_data;
#if defined(CONFIG_NET_ICMPv6_NEIGHBOR)
FAR struct ipv6_hdr_s *ipv6 = (FAR struct ipv6_hdr_s *)fwd->f_iob->io_data;
return (neighbor_findentry(ipv6->destipaddr) != NULL);
#else
return true;

View File

@ -182,7 +182,7 @@ int sixlowpan_meta_data(FAR struct radio_driver_s *radio,
rcvrnull = sixlowpan_saddrnull(pktmeta->dest.nm_addr);
}
if (rcvrnull)
if (!rcvrnull)
{
meta->flags.ackreq = TRUE;
}

View File

@ -88,7 +88,7 @@ void sixlowpan_icmpv6_send(FAR struct net_driver_s *dev,
/* Double check */
DEBUGASSERT(dev != NULL && dev->d_len > 0);
DEBUGASSERT(dev != NULL && dev->d_len > 0 && fwddev != NULL);
ninfo("d_len %u\n", dev->d_len);
@ -118,7 +118,7 @@ void sixlowpan_icmpv6_send(FAR struct net_driver_s *dev,
* assumes an encoding of the MAC address in the IPv6 address.
*/
ret = sixlowpan_destaddrfromip((FAR struct radio_driver_s *)dev,
ret = sixlowpan_destaddrfromip((FAR struct radio_driver_s *)fwddev,
ipv6icmpv6->ipv6.destipaddr, &destmac);
if (ret < 0)
{

View File

@ -438,6 +438,7 @@ static int sixlowpan_frame_process(FAR struct radio_driver_s *radio,
DEBUGASSERT(radio->r_dev.d_buf != NULL);
reass = (FAR struct sixlowpan_reassbuf_s *)radio->r_dev.d_buf;
reass->rb_pool = REASS_POOL_RADIO;
bptr = reass->rb_buf;
break;
}
@ -735,9 +736,16 @@ int sixlowpan_input(FAR struct radio_driver_s *radio,
ret = sixlowpan_frame_process(radio, metadata, iob);
/* Free the IOB the held the consumed frame */
/* If the frame was a valid 6LoWPAN frame, free the IOB the held the
* consumed frame. Otherwise, the frame must stay allocated since the
* MAC layer will try and pass it to another receiver to see if that
* receiver wants it.
*/
iob_free(iob);
if (ret >= 0)
{
iob_free(iob);
}
/* Was the frame successfully processed? Is the packet in d_buf fully
* reassembled?
@ -826,9 +834,9 @@ int sixlowpan_input(FAR struct radio_driver_s *radio,
}
}
if (hdrlen < radio->r_dev.d_len)
if (hdrlen > radio->r_dev.d_len)
{
nwarn("WARNING: Packet to small: Have %u need >%u\n",
nwarn("WARNING: Packet too small: Have %u need >%u\n",
radio->r_dev.d_len, hdrlen);
ret = -ENOBUFS;
goto drop;

View File

@ -122,6 +122,7 @@
#define REASS_POOL_PREALLOCATED 0
#define REASS_POOL_DYNAMIC 1
#define REASS_POOL_RADIO 2
/* Debug ********************************************************************/

View File

@ -439,7 +439,7 @@ void sixlowpan_reass_free(FAR struct sixlowpan_reassbuf_s *reass)
reass->rb_flink = g_free_reass;
g_free_reass = reass;
}
else
else if (reass->rb_pool == REASS_POOL_DYNAMIC)
{
#ifdef CONFIG_NET_6LOWPAN_REASS_STATIC
DEBUGPANIC();
@ -451,4 +451,8 @@ void sixlowpan_reass_free(FAR struct sixlowpan_reassbuf_s *reass)
sched_kfree(reass);
#endif
}
/* If the reassembly buffer structure was provided by the driver, nothing
* needs to be freed.
*/
}

View File

@ -929,7 +929,7 @@ void sixlowpan_tcp_send(FAR struct net_driver_s *dev,
sixlowpan_dumpbuffer("Outgoing TCP packet",
(FAR const uint8_t *)ipv6, dev->d_len);
if (dev != NULL && dev->d_len > 0)
if (dev != NULL && dev->d_len > 0 && fwddev != NULL)
{
FAR struct ipv6tcp_hdr_s *ipv6hdr;
@ -961,7 +961,7 @@ void sixlowpan_tcp_send(FAR struct net_driver_s *dev,
* assumes an encoding of the MAC address in the IPv6 address.
*/
ret = sixlowpan_destaddrfromip((FAR struct radio_driver_s *)dev,
ret = sixlowpan_destaddrfromip((FAR struct radio_driver_s *)fwddev,
ipv6hdr->ipv6.destipaddr, &destmac);
if (ret < 0)
{

View File

@ -441,11 +441,11 @@ void sixlowpan_udp_send(FAR struct net_driver_s *dev,
/* Double check */
DEBUGASSERT(dev != NULL && dev->d_len > 0);
DEBUGASSERT(dev != NULL && dev->d_len > 0 && fwddev != NULL);
ninfo("d_len %u\n", dev->d_len);
if (dev != NULL && dev->d_len > 0)
if (dev != NULL && dev->d_len > 0 && fwddev != NULL)
{
sixlowpan_dumpbuffer("Outgoing UDP packet",
@ -472,7 +472,7 @@ void sixlowpan_udp_send(FAR struct net_driver_s *dev,
* assumes an encoding of the MAC address in the IPv6 address.
*/
ret = sixlowpan_destaddrfromip((FAR struct radio_driver_s *)dev,
ret = sixlowpan_destaddrfromip((FAR struct radio_driver_s *)fwddev,
ipv6udp->ipv6.destipaddr, &destmac);
if (ret < 0)
{

View File

@ -15,44 +15,61 @@ menuconfig WIRELESS_IEEE802154
if WIRELESS_IEEE802154
config IEEE802154_PRIMITIVE_PREALLOC
int "Number of pre-allocated primitive structures"
default 20
---help---
This specifies the total number of preallocated primitive structures.
A primitive is an abstracted data type that provides service information
between the MAC layer and the next highest layer. These may be allocated
from either from tasking logic or from interrupt level logic.
config IEEE802154_PRIMITIVE_IRQRESERVE
int "Reserved pre-allocated primitive structures"
default 0
depends on EXPERIMENTAL
---help---
If primitves can be allocated from interrupt handlers, then this
specifies the number of pre-allocatd meta-data structures that are
reserved for for use only by interrupt handlers. This may be zero to
reserve no meta-data structures for interrupt handlers. In that case,
the allocation will fail if tasking logic has allocated them all.
Interrupt logic will first attempt to allocate from the general,
pre-allocated structure pool that will contain up to (size
CONFIG_IEEE802154_PRIMITIVE_PREALLOC - CONFIG_IEEE802154_PRIMITIVE_IRQRESERVE)
entries. If that fails, then it will try to take a structure from
the reserve (size CONFIG_IEEE802154_PRIMITIVE_IRQRESERVE).
Non-interrupt logic will also first attempt to allocate from the
general, pre-allocated structure pool. If that fails, it will
dynamically allocate the primitive with an additional cost in performance.
NOTE: Currently marked as experimental and with a default of zero
because there are no interrupt level allocations performed by the
current IEEE 802.15.4 MAC code.
config IEEE802154_DEFAULT_EADDR
hex "IEEE 802.15.4 Default Extended Address"
default 0x00fade00deadbeef
---help---
Set the default extended address to be used by MAC networks on init
choice
prompt "IEEE 802.15.4 work queue"
default MAC802154_HPWORK if SCHED_HPWORK
default MAC802154_LPWORK if !SCHED_HPWORK && SCHED_LPWORK
depends on SCHED_WORKQUEUE
config IEEE802154_MAC
bool "Software MAC layer"
default n
---help---
Work queue support is required to use the IEEE 802.15.4 MAC layer.
If the high priority work queue is available, then it should be used by
the driver.
There are two types of IEEE 802.15.4 radios supported. Those that provide
all MAC functionality equivalent to the MAC802154 software implementation,
and radios that provide a lower half to the MAC802154 software layer.
This option enables the software MAC layer that can interface with
the lower-half radio drivers.
WARNING!! The IEEE802.15.4 network device must never run on the same
work queue as does the IEEE 802.15.4 MAC. That configuration will
cause deadlocks: The network logic may be blocked on the work queue
waiting on resources that can only be freed by the MAC logic but the
MAC is unable to run because the work queue is blocked. The
recommended configuration is: Network on the LP work queue; MAC on HP
work queue. Blocking on the HP work queue is a very bad thing in
any case.
config MAC802154_HPWORK
bool "High priority"
depends on SCHED_HPWORK
config MAC802154_LPWORK
bool "Low priority"
depends on SCHED_LPWORK
endchoice # Work queue
if IEEE802154_MAC
config MAC802154_NTXDESC
int "Number or TX descriptors"
default 3
default 5
---help---
Configured number of Tx descriptors. Default: 3
@ -63,16 +80,6 @@ config MAC802154_NTXDESC
Then there should be the maximum pre-allocated buffers for each
possible TX frame.
config MAC802154_NNOTIF
int "Number or notification structures"
default 3
---help---
Configured number of notification strucures Default: 3
When various MAC management events occur, the MAC notifies the registered
receiver with an allocated notification structure indicating the event. The
events are primitives such as Association Indication etc.
config MAC802154_NPANDESC
int "Number of PAN descriptors"
default 5
@ -97,40 +104,6 @@ config MAC802154_LOCK_VERBOSE
---help---
Enable verbose logging of MAC lock management. Default: false
config IEEE802154_IND_PREALLOC
int "Number of pre-allocated meta-data structures"
default 20
---help---
This specifies the total number of preallocated meta data structures
must be allocated with each incoming packet. These may be allocated
from either from tasking logic or from interrupt level logic.
config IEEE802154_IND_IRQRESERVE
int "Reserved pre-allocated meta-data structures"
default 0
depends on EXPERIMENTAL
---help---
If meta-data structures can be allocated from interrupt handlers,
then this specifies the number of pre-allocatd meta-data structures
that are reserved for for use only by interrupt handlers. This may
be zero to reserve no meta-data structures for interrupt handlers.
In that case, the allocation will fail if tasking logic has
allocated them all.
Interrupt logic will first attempt to allocate from the general,
pre-allocated structure pool that will contain up to (size
CONFIG_IEEE802154_IND_PREALLOC - CONFIG_IEEE802154_IND_IRQRESERVE)
entries. If that fails, then it will try to take a structure from
the reserve (size CONFIG_IEEE802154_IND_IRQRESERVE).
Non-interrupt logic will also first attempt to allocate from the
general, pre-allocated structure pool. If that fails, it will
dynamically allocate the meta data structure with an additional cost
in performance.
NOTE: Currently marked as experimental and with a default of zero
because there are no interrupt level allocations performed by the
current IEEE 802.15.4 MAC code.
config IEEE802154_MACDEV
bool "Character driver for IEEE 802.15.4 MAC layer"
@ -221,6 +194,8 @@ config IEEE802154_NETDEV_LPWORK
endchoice # Work queue
endif # IEEE802154_NETDEV
endif # IEEE802154_MACDEV
config IEEE802154_LOOPBACK
bool "IEEE802154 6LoWPAN Loopback"
default n

View File

@ -37,12 +37,16 @@ ifeq ($(CONFIG_WIRELESS_IEEE802154),y)
# Include IEEE 802.15.4 support
CSRCS += ieee802154_indalloc.c mac802154.c mac802154_assoc.c mac802154_disassoc.c
CSRCS += ieee802154_primitive.c
ifeq ($(CONFIG_IEEE802154_MAC),y)
CSRCS += mac802154.c mac802154_assoc.c mac802154_disassoc.c
CSRCS += mac802154_bind.c mac802154_data.c mac802154_get_mhrlen.c
CSRCS += mac802154_getset.c mac802154_gts.c mac802154_ioctl.c
CSRCS += mac802154_notif.c mac802154_orphan.c mac802154_poll.c mac802154_purge.c
CSRCS += mac802154_reset.c mac802154_rxenable.c mac802154_scan.c mac802154_start.c
CSRCS += mac802154_sync.c
CSRCS += mac802154_orphan.c mac802154_poll.c mac802154_purge.c
CSRCS += mac802154_reset.c mac802154_rxenable.c mac802154_scan.c
CSRCS += mac802154_start.c mac802154_sync.c
# Include wireless devices build support
@ -54,6 +58,8 @@ ifeq ($(CONFIG_IEEE802154_NETDEV),y)
CSRCS += mac802154_netdev.c
endif
endif
ifeq ($(CONFIG_IEEE802154_LOOPBACK),y)
CSRCS += mac802154_loopback.c
endif

View File

@ -1,5 +1,5 @@
/****************************************************************************
* wireless/ieee802154/ieee802154_indalloc.c
* wireless/ieee802154/ieee802154_primitive.c
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
@ -43,9 +43,6 @@
#include <string.h>
#include <nuttx/kmalloc.h>
#include <nuttx/mm/iob.h>
#include <nuttx/wireless/ieee802154/ieee802154_mac.h>
#include "mac802154.h"
@ -54,46 +51,46 @@
* Pre-processor Definitions
****************************************************************************/
/* NOTE: The CONFIG_IEEE802154_IND_IRQRESERVE options is marked as marked
/* NOTE: The CONFIG_IEEE802154_PRIMITIVE_IRQRESERVE options is marked as marked
* 'experimental' and with the default 0 zero because there are no interrupt
* level allocations performed by the current IEEE 802.15.4 MAC code.
*/
#if !defined(CONFIG_IEEE802154_IND_PREALLOC) || \
CONFIG_IEEE802154_IND_PREALLOC < 0
# undef CONFIG_IEEE802154_IND_PREALLOC
# define CONFIG_IEEE802154_IND_PREALLOC 20
#if !defined(CONFIG_IEEE802154_PRIMITIVE_PREALLOC) || \
CONFIG_IEEE802154_PRIMITIVE_PREALLOC < 0
# undef CONFIG_IEEE802154_PRIMITIVE_PREALLOC
# define CONFIG_IEEE802154_PRIMITIVE_PREALLOC 20
#endif
#if !defined(CONFIG_IEEE802154_IND_IRQRESERVE) || \
CONFIG_IEEE802154_IND_IRQRESERVE < 0
# undef CONFIG_IEEE802154_IND_IRQRESERVE
# define CONFIG_IEEE802154_IND_IRQRESERVE 0
#if !defined(CONFIG_IEEE802154_PRIMITIVE_IRQRESERVE) || \
CONFIG_IEEE802154_PRIMITIVE_IRQRESERVE < 0
# undef CONFIG_IEEE802154_PRIMITIVE_IRQRESERVE
# define CONFIG_IEEE802154_PRIMITIVE_IRQRESERVE 0
#endif
#if CONFIG_IEEE802154_IND_IRQRESERVE > CONFIG_IEEE802154_IND_PREALLOC
# undef CONFIG_IEEE802154_IND_IRQRESERVE
# define CONFIG_IEEE802154_IND_IRQRESERVE CONFIG_IEEE802154_IND_PREALLOC
#if CONFIG_IEEE802154_PRIMITIVE_IRQRESERVE > CONFIG_IEEE802154_PRIMITIVE_PREALLOC
# undef CONFIG_IEEE802154_PRIMITIVE_IRQRESERVE
# define CONFIG_IEEE802154_PRIMITIVE_IRQRESERVE CONFIG_IEEE802154_PRIMITIVE_PREALLOC
#endif
/* Memory Pools */
#define POOL_IND_GENERAL 0
#define POOL_IND_IRQ 1
#define POOL_IND_DYNAMIC 2
#define POOL_PRIMITIVE_GENERAL 0
#define POOL_PRIMITIVE_IRQ 1
#define POOL_PRIMITIVE_DYNAMIC 2
/****************************************************************************
* Private Data Types
****************************************************************************/
/* Private data type that extends the ieee802154_data_ind_s struct */
/* Private data type that extends the ieee802154_primitive_s struct */
struct ieee802154_priv_ind_s
struct ieee802154_priv_primitive_s
{
/* Must be first member so we can cast to/from */
struct ieee802154_data_ind_s pub;
FAR struct ieee802154_priv_ind_s *flink;
struct ieee802154_primitive_s pub;
FAR struct ieee802154_priv_primitive_s *flink;
uint8_t pool;
};
@ -101,38 +98,40 @@ struct ieee802154_priv_ind_s
* Private Data
****************************************************************************/
#if CONFIG_IEEE802154_IND_PREALLOC > 0
#if CONFIG_IEEE802154_IND_PREALLOC > CONFIG_IEEE802154_IND_IRQRESERVE
/* The g_indfree is a list of meta-data structures that are available for
#if CONFIG_IEEE802154_PRIMITIVE_PREALLOC > 0
#if CONFIG_IEEE802154_PRIMITIVE_PREALLOC > CONFIG_IEEE802154_PRIMITIVE_IRQRESERVE
/* The g_primfree is a list of primitive structures that are available for
* general use. The number of messages in this list is a system configuration
* item.
*/
static struct ieee802154_priv_ind_s *g_indfree;
static struct ieee802154_priv_primitive_s *g_primfree;
#endif
#if CONFIG_IEEE802154_IND_IRQRESERVE > 0
/* The g_indfree_irq is a list of meta-data structures that are reserved for
#if CONFIG_IEEE802154_PRIMITIVE_IRQRESERVE > 0
/* The g_primfree_irq is a list of primitive structures that are reserved for
* use by only by interrupt handlers.
*/
static struct ieee802154_priv_ind_s *g_indfree_irq;
static struct ieee802154_priv_primitive_s *g_primfree_irq;
#endif
/* Pool of pre-allocated meta-data stuctures */
/* Pool of pre-allocated primitive stuctures */
static struct ieee802154_priv_ind_s g_indpool[CONFIG_IEEE802154_IND_PREALLOC];
#endif /* CONFIG_IEEE802154_IND_PREALLOC > 0 */
static struct ieee802154_priv_primitive_s g_primpool[CONFIG_IEEE802154_PRIMITIVE_PREALLOC];
#endif /* CONFIG_IEEE802154_PRIMITIVE_PREALLOC > 0 */
static bool g_poolinit = false;
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: ieee802154_indpool_initialize
* Name: ieee802154_primitivepool_initialize
*
* Description:
* This function initializes the meta-data allocator. This function must
* This function initializes the primitive allocator. This function must
* be called early in the initialization sequence before any radios
* begin operation.
*
@ -144,28 +143,37 @@ static struct ieee802154_priv_ind_s g_indpool[CONFIG_IEEE802154_IND_PREALLOC];
*
****************************************************************************/
void ieee802154_indpool_initialize(void)
void ieee802154_primitivepool_initialize(void)
{
#if CONFIG_IEEE802154_IND_PREALLOC > 0
FAR struct ieee802154_priv_ind_s *pool = g_indpool;
int remaining = CONFIG_IEEE802154_IND_PREALLOC;
/* Only allow the pool to be initialized once */
#if CONFIG_IEEE802154_IND_PREALLOC > CONFIG_IEEE802154_IND_IRQRESERVE
/* Initialize g_indfree, thelist of meta-data structures that are available
if (g_poolinit)
{
return;
}
g_poolinit = true;
#if CONFIG_IEEE802154_PRIMITIVE_PREALLOC > 0
FAR struct ieee802154_priv_primitive_s *pool = g_primpool;
int remaining = CONFIG_IEEE802154_PRIMITIVE_PREALLOC;
#if CONFIG_IEEE802154_PRIMITIVE_PREALLOC > CONFIG_IEEE802154_PRIMITIVE_IRQRESERVE
/* Initialize g_primfree, thelist of primitive structures that are available
* for general use.
*/
g_indfree = NULL;
while (remaining > CONFIG_IEEE802154_IND_IRQRESERVE)
g_primfree = NULL;
while (remaining > CONFIG_IEEE802154_PRIMITIVE_IRQRESERVE)
{
FAR struct ieee802154_priv_ind_s *ind = pool;
FAR struct ieee802154_priv_primitive_s *prim = pool;
/* Add the next meta data structure from the pool to the list of
* general structures.
*/
ind->flink = g_indfree;
g_indfree = ind;
prim->flink = g_primfree;
g_primfree = prim;
/* Set up for the next structure from the pool */
@ -174,22 +182,22 @@ void ieee802154_indpool_initialize(void)
}
#endif
#if CONFIG_IEEE802154_IND_IRQRESERVE > 0
/* Initialize g_indfree_irq is a list of meta-data structures reserved for
#if CONFIG_IEEE802154_PRIMITIVE_IRQRESERVE > 0
/* Initialize g_primfree_irq is a list of primitive structures reserved for
* use by only by interrupt handlers.
*/
g_indfree_irq = NULL;
g_primfree_irq = NULL;
while (remaining > 0)
{
FAR struct ieee802154_priv_ind_s *ind = pool;
FAR struct ieee802154_priv_primitive_s *prim = pool;
/* Add the next meta data structure from the pool to the list of
* general structures.
*/
ind->flink = g_indfree_irq;
g_indfree_irq = ind;
prim->flink = g_primfree_irq;
g_primfree_irq = prim;
/* Set up for the next structure from the pool */
@ -197,39 +205,39 @@ void ieee802154_indpool_initialize(void)
remaining--;
}
#endif
#endif /* CONFIG_IEEE802154_IND_PREALLOC > 0 */
#endif /* CONFIG_IEEE802154_PRIMITIVE_PREALLOC > 0 */
}
/****************************************************************************
* Name: ieee802154_ind_allocate
* Name: ieee802154_primitive_allocate
*
* Description:
* The ieee802154_ind_allocate function will get a free meta-data
* The ieee802154_primitive_allocate function will get a free primitive
* structure for use by the IEEE 802.15.4 MAC.
*
* Interrupt handling logic will first attempt to allocate from the
* g_indfree list. If that list is empty, it will attempt to allocate
* from its reserve, g_indfree_irq. If that list is empty, then the
* g_primfree list. If that list is empty, it will attempt to allocate
* from its reserve, g_primfree_irq. If that list is empty, then the
* allocation fails (NULL is returned).
*
* Non-interrupt handler logic will attempt to allocate from g_indfree
* list. If that the list is empty, then the meta-data structure will be
* Non-interrupt handler logic will attempt to allocate from g_primfree
* list. If that the list is empty, then the primitive structure will be
* allocated from the dynamic memory pool.
*
* Inputs:
* None
*
* Return Value:
* A reference to the allocated msg structure. All user fields in this
* A reference to the allocated primitive structure. All user fields in this
* structure have been zeroed. On a failure to allocate, NULL is
* returned.
*
****************************************************************************/
FAR struct ieee802154_data_ind_s *ieee802154_ind_allocate(void)
FAR struct ieee802154_primitive_s *ieee802154_primitive_allocate(void)
{
#if CONFIG_IEEE802154_IND_PREALLOC > 0
FAR struct ieee802154_priv_ind_s *ind;
#if CONFIG_IEEE802154_PRIMITIVE_PREALLOC > 0
FAR struct ieee802154_priv_primitive_s *prim;
irqstate_t flags;
uint8_t pool;
@ -241,29 +249,29 @@ FAR struct ieee802154_data_ind_s *ieee802154_ind_allocate(void)
flags = enter_critical_section(); /* Always necessary in SMP mode */
if (up_interrupt_context())
{
#if CONFIG_IEEE802154_IND_PREALLOC > CONFIG_IEEE802154_IND_IRQRESERVE
#if CONFIG_IEEE802154_PRIMITIVE_PREALLOC > CONFIG_IEEE802154_PRIMITIVE_IRQRESERVE
/* Try the general free list */
if (g_indfree != NULL)
if (g_primfree != NULL)
{
ind = g_indfree;
g_indfree = ind->flink;
prim = g_primfree;
g_primfree = prim->flink;
leave_critical_section(flags);
pool = POOL_IND_GENERAL;
pool = POOL_PRIMITIVE_GENERAL;
}
else
#endif
#if CONFIG_IEEE802154_IND_IRQRESERVE > 0
#if CONFIG_IEEE802154_PRIMITIVE_IRQRESERVE > 0
/* Try the list list reserved for interrupt handlers */
if (g_indfree_irq != NULL)
if (g_primfree_irq != NULL)
{
ind = g_indfree_irq;
g_indfree_irq = ind->flink;
prim = g_primfree_irq;
g_primfree_irq = prim->flink;
leave_critical_section(flags);
pool = POOL_IND_IRQ;
pool = POOL_PRIMITIVE_IRQ;
}
else
#endif
@ -277,136 +285,116 @@ FAR struct ieee802154_data_ind_s *ieee802154_ind_allocate(void)
else
{
#if CONFIG_IEEE802154_IND_PREALLOC > CONFIG_IEEE802154_IND_IRQRESERVE
#if CONFIG_IEEE802154_PRIMITIVE_PREALLOC > CONFIG_IEEE802154_PRIMITIVE_IRQRESERVE
/* Try the general free list */
if (g_indfree != NULL)
if (g_primfree != NULL)
{
ind = g_indfree;
g_indfree = ind->flink;
prim = g_primfree;
g_primfree = prim->flink;
leave_critical_section(flags);
pool = POOL_IND_GENERAL;
pool = POOL_PRIMITIVE_GENERAL;
}
else
#endif
{
/* If we cannot a meta-data structure from the free list, then we
/* If we cannot a primitive structure from the free list, then we
* will have to allocate one from the kernal memory pool.
*/
leave_critical_section(flags);
ind = (FAR struct ieee802154_priv_ind_s *)
kmm_malloc((sizeof (struct ieee802154_priv_ind_s)));
prim = (FAR struct ieee802154_priv_primitive_s *)
kmm_malloc((sizeof (struct ieee802154_priv_primitive_s)));
/* Check if we allocated the meta-data structure */
/* Check if we allocated the primitive structure */
if (ind != NULL)
if (prim != NULL)
{
/* Yes... remember that this meta-data structure was dynamically allocated */
/* Yes... remember that this primitive structure was dynamically allocated */
pool = POOL_IND_DYNAMIC;
pool = POOL_PRIMITIVE_DYNAMIC;
}
}
}
/* We have successfully allocated memory from some source.
* Zero and tag the alloated meta-data structure.
* Zero and tag the alloated primitive structure.
*/
ind->pool = pool;
memset(&ind->pub, 0, sizeof(struct ieee802154_data_ind_s));
prim->pool = pool;
memset(&prim->pub, 0, sizeof(struct ieee802154_primitive_s));
/* Allocate the IOB for the frame */
ind->pub.frame = iob_alloc(true);
if (ind->pub.frame == NULL)
{
/* Deallocate the ind */
ieee802154_ind_free(&ind->pub);
return NULL;
}
ind->pub.frame->io_flink = NULL;
ind->pub.frame->io_len = 0;
ind->pub.frame->io_offset = 0;
ind->pub.frame->io_pktlen = 0;
return &ind->pub;
wlinfo("Primitive allocated: %p\n", prim);
return &prim->pub;
#else
return NULL;
#endif
}
/****************************************************************************
* Name: ieee802154_ind_free
* Name: ieee802154_primitive_free
*
* Description:
* The ieee802154_ind_free function will return a meta-data structure to
* the free pool of messages if it was a pre-allocated meta-data
* structure. If the meta-data structure was allocated dynamically it will
* The ieee802154_primitive_free function will return a primitive structure to
* the free pool of messages if it was a pre-allocated primitive
* structure. If the primitive structure was allocated dynamically it will
* be deallocated.
*
* Inputs:
* ind - meta-data structure to free
* prim - primitive structure to free
*
* Return Value:
* None
*
****************************************************************************/
void ieee802154_ind_free(FAR struct ieee802154_data_ind_s *ind)
void ieee802154_primitive_free(FAR struct ieee802154_primitive_s *prim)
{
#if CONFIG_IEEE802154_IND_PREALLOC > 0
irqstate_t flags;
FAR struct ieee802154_priv_ind_s *priv =
(FAR struct ieee802154_priv_ind_s *)ind;
/* Check if the IOB is not NULL. The only time it should be NULL is if we
* allocated the data_ind, but the IOB allocation failed so we now have to
* free the data_ind but not the IOB. This really should happen rarely if at all.
*/
if (ind->frame != NULL)
if (--prim->nclients > 0)
{
iob_free(ind->frame);
wlinfo("Remaining Clients: %d\n", prim->nclients);
return;
}
#if CONFIG_IEEE802154_IND_PREALLOC > CONFIG_IEEE802154_IND_IRQRESERVE
/* If this is a generally available pre-allocated meta-data structure,
#if CONFIG_IEEE802154_PRIMITIVE_PREALLOC > 0
irqstate_t flags;
FAR struct ieee802154_priv_primitive_s *priv =
(FAR struct ieee802154_priv_primitive_s *)prim;
#if CONFIG_IEEE802154_PRIMITIVE_PREALLOC > CONFIG_IEEE802154_PRIMITIVE_IRQRESERVE
/* If this is a generally available pre-allocated primitive structure,
* then just put it back in the free list.
*/
if (priv->pool == POOL_IND_GENERAL)
if (priv->pool == POOL_PRIMITIVE_GENERAL)
{
/* Make sure we avoid concurrent access to the free
* list from interrupt handlers.
*/
flags = enter_critical_section();
priv->flink = g_indfree;
g_indfree = priv;
priv->flink = g_primfree;
g_primfree = priv;
leave_critical_section(flags);
}
else
#endif
#if CONFIG_IEEE802154_IND_IRQRESERVE > 0
/* If this is a meta-data structure pre-allocated for interrupts,
#if CONFIG_IEEE802154_PRIMITIVE_IRQRESERVE > 0
/* If this is a primitive structure pre-allocated for interrupts,
* then put it back in the correct free list.
*/
if (priv->pool == POOL_IND_IRQ)
if (priv->pool == POOL_PRIMITIVE_IRQ)
{
/* Make sure we avoid concurrent access to the free
* list from interrupt handlers.
*/
flags = enter_critical_section();
priv->flink = g_indfree_irq;
g_indfree_irq = priv;
priv->flink = g_primfree_irq;
g_primfree_irq = priv;
leave_critical_section(flags);
}
else
@ -415,8 +403,10 @@ void ieee802154_ind_free(FAR struct ieee802154_data_ind_s *ind)
{
/* Otherwise, deallocate it. */
DEBUGASSERT(priv->pool == POOL_IND_DYNAMIC);
DEBUGASSERT(priv->pool == POOL_PRIMITIVE_DYNAMIC);
sched_kfree(priv);
}
#endif
wlinfo("Primitive freed: %p\n", prim);
}

View File

@ -57,7 +57,6 @@
#include <nuttx/mm/iob.h>
#include "mac802154.h"
#include "mac802154_notif.h"
#include "mac802154_internal.h"
#include "mac802154_assoc.h"
#include "mac802154_scan.h"
@ -100,6 +99,8 @@ static void mac802154_rxdataframe(FAR struct ieee802154_privmac_s *priv,
static void mac802154_rxbeaconframe(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_data_ind_s *ind);
static void mac802154_notify_worker(FAR void *arg);
/****************************************************************************
* Private Functions
****************************************************************************/
@ -122,6 +123,7 @@ static void mac802154_resetqueues(FAR struct ieee802154_privmac_s *priv)
sq_init(&priv->gts_queue);
sq_init(&priv->indirect_queue);
sq_init(&priv->dataind_queue);
sq_init(&priv->primitive_queue);
/* Initialize the tx descriptor allocation pool */
@ -132,20 +134,15 @@ static void mac802154_resetqueues(FAR struct ieee802154_privmac_s *priv)
}
nxsem_init(&priv->txdesc_sem, 0, CONFIG_MAC802154_NTXDESC);
/* Initialize the notifcation allocation pool */
mac802154_notifpool_init(priv);
}
/****************************************************************************
* Name: mac802154_txdesc_pool
*
* Description:
* This function allocates a tx descriptor and the dependent notification (data
* confirmation) from the free list. The notification and tx descriptor will
* be freed seperately, both by the MAC layer either directly, or through
* mac802154_notif_free in the case of the notification.
* This function allocates a tx descriptor and the dependent primitive (data
* confirmation) from the free list. The primitive and tx descriptor must be
* freed seperately.
*
* Assumptions:
* priv MAC struct is locked when calling.
@ -162,7 +159,7 @@ int mac802154_txdesc_alloc(FAR struct ieee802154_privmac_s *priv,
bool allow_interrupt)
{
int ret;
FAR struct ieee802154_notif_s *notif;
FAR struct ieee802154_primitive_s *primitive;
/* Try and take a count from the semaphore. If this succeeds, we have
* "reserved" the structure, but still need to unlink it from the free list.
@ -213,27 +210,16 @@ int mac802154_txdesc_alloc(FAR struct ieee802154_privmac_s *priv,
}
/* We have now successfully allocated the tx descriptor. Now we need to allocate
* the notification for the data confirmation that gets passed along with the
* the primitive for the data confirmation that gets passed along with the
* tx descriptor. These are allocated together, but not freed together.
*/
ret = mac802154_notif_alloc(priv, &notif, allow_interrupt);
if (ret < 0)
{
/* The mac802154_notif_alloc function follows the same rules as this
* function. If it returns -EINTR, the MAC layer is already released
*/
/* We need to free the txdesc */
mac802154_txdesc_free(priv, *txdesc);
return -EINTR;
}
primitive = ieee802154_primitive_allocate();
(*txdesc)->purgetime = 0;
(*txdesc)->retrycount = priv->maxretries;
(*txdesc)->conf = &notif->u.dataconf;
(*txdesc)->conf = &primitive->u.dataconf;
return OK;
}
@ -356,6 +342,126 @@ void mac802154_createdatareq(FAR struct ieee802154_privmac_s *priv,
priv->cmd_desc = txdesc;
}
/****************************************************************************
* Name: mac802154_notify
*
* Description:
* Queue the primitive in the queue and queue work on the LPWORK
* queue if is not already scheduled.
*
* Assumptions:
* Called with the MAC locked
*
****************************************************************************/
void mac802154_notify(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_primitive_s *primitive)
{
sq_addlast((FAR sq_entry_t *)primitive, &priv->primitive_queue);
if (work_available(&priv->notifwork))
{
work_queue(LPWORK, &priv->notifwork, mac802154_notify_worker,
(FAR void *)priv, 0);
}
}
/****************************************************************************
* Name: mac802154_notify_worker
*
* Description:
* Pop each primitive off the queue and call the registered
* callbacks. There is special logic for handling ieee802154_data_ind_s.
*
****************************************************************************/
static void mac802154_notify_worker(FAR void *arg)
{
FAR struct ieee802154_privmac_s *priv = (FAR struct ieee802154_privmac_s *)arg;
FAR struct mac802154_maccb_s *cb;
FAR struct ieee802154_primitive_s *primitive;
int ret;
mac802154_lock(priv, false);
primitive =
(FAR struct ieee802154_primitive_s *)sq_remfirst(&priv->primitive_queue);
mac802154_unlock(priv);
while (primitive != NULL)
{
/* Data indications are a special case since the frame can only be passed to
* one place. The return value of the notify call is used to accept or reject
* the primitive. In the case of the data indication, there can only be one
* accept. Callbacks are stored in order of there receiver priority ordered
* when the callbacks are bound in mac802154_bind().
*/
if (primitive->type == IEEE802154_PRIMITIVE_IND_DATA)
{
bool dispose = true;
primitive->nclients = 1;
for (cb = priv->cb; cb != NULL; cb = cb->flink)
{
if (cb->notify != NULL)
{
ret = cb->notify(cb, primitive);
if (ret >= 0)
{
/* The receiver accepted and disposed of the frame and it's
* meta-data. We are done.
*/
dispose = false;
break;
}
}
}
if (dispose)
{
iob_free(primitive->u.dataind.frame);
ieee802154_primitive_free(primitive);
}
}
else
{
/* Set the number of clients count so that the primitive resources will be
* preserved until all clients are finished with it.
*/
primitive->nclients = priv->nclients;
/* Try to notify every registered MAC client */
for (cb = priv->cb; cb != NULL; cb = cb->flink)
{
if (cb->notify != NULL)
{
ret = cb->notify(cb, primitive);
if (ret <= 0)
{
ieee802154_primitive_free(primitive);
}
}
else
{
ieee802154_primitive_free(primitive);
}
}
}
/* Get the next primitive then loop */
mac802154_lock(priv, false);
primitive =
(FAR struct ieee802154_primitive_s *)sq_remfirst(&priv->primitive_queue);
mac802154_unlock(priv);
}
}
/****************************************************************************
* Name: mac802154_updatebeacon
*
@ -579,7 +685,7 @@ 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,
work_queue(HPWORK, &priv->purge_work, mac802154_purge_worker,
(FAR void *)priv, ticks);
}
}
@ -635,8 +741,7 @@ static void mac802154_purge_worker(FAR void *arg)
/* Free the IOB, the notification, and the tx descriptor */
iob_free(txdesc->frame);
mac802154_notif_free_locked(priv,
(FAR struct ieee802154_notif_s *)txdesc->conf);
ieee802154_primitive_free((FAR struct ieee802154_primitive_s *)txdesc->conf);
mac802154_txdesc_free(priv, txdesc);
priv->beaconupdate = true;
@ -646,7 +751,7 @@ static void mac802154_purge_worker(FAR void *arg)
{
/* Reschedule the transaction for the next timeout */
work_queue(MAC802154_WORK, &priv->purge_work, mac802154_purge_worker,
work_queue(HPWORK, &priv->purge_work, mac802154_purge_worker,
(FAR void *)priv, txdesc->purgetime - clock_systimer());
break;
}
@ -740,7 +845,7 @@ static void mac802154_txdone(FAR const struct ieee802154_radiocb_s *radiocb,
if (work_available(&priv->tx_work))
{
work_queue(MAC802154_WORK, &priv->tx_work, mac802154_txdone_worker,
work_queue(HPWORK, &priv->tx_work, mac802154_txdone_worker,
(FAR void *)priv, 0);
}
}
@ -760,7 +865,7 @@ static void mac802154_txdone_worker(FAR void *arg)
FAR struct ieee802154_privmac_s *priv =
(FAR struct ieee802154_privmac_s *)arg;
FAR struct ieee802154_txdesc_s *txdesc;
FAR struct ieee802154_notif_s *notif;
FAR struct ieee802154_primitive_s *primitive;
/* Get exclusive access to the driver structure. We don't care about any
* signals so don't allow interruptions
@ -781,7 +886,7 @@ static void mac802154_txdone_worker(FAR void *arg)
* notification structure to make it easier to use.
*/
notif =(FAR struct ieee802154_notif_s *)txdesc->conf;
primitive =(FAR struct ieee802154_primitive_s *)txdesc->conf;
wlinfo("Tx status: %s\n", IEEE802154_STATUS_STRING[txdesc->conf->status]);
@ -789,13 +894,8 @@ static void mac802154_txdone_worker(FAR void *arg)
{
case IEEE802154_FRAME_DATA:
{
notif->notiftype = IEEE802154_NOTIFY_CONF_DATA;
/* Release the MAC, call the callback, get exclusive access again */
mac802154_unlock(priv)
mac802154_notify(priv, notif);
mac802154_lock(priv, false);
primitive->type = IEEE802154_PRIMITIVE_CONF_DATA;
mac802154_notify(priv, primitive);
}
break;
@ -858,7 +958,7 @@ static void mac802154_txdone_worker(FAR void *arg)
break;
default:
mac802154_notif_free_locked(priv, notif);
ieee802154_primitive_free(primitive);
break;
}
}
@ -866,7 +966,7 @@ static void mac802154_txdone_worker(FAR void *arg)
default:
{
mac802154_notif_free_locked(priv, notif);
ieee802154_primitive_free(primitive);
}
break;
}
@ -922,7 +1022,7 @@ static void mac802154_rxframe(FAR const struct ieee802154_radiocb_s *radiocb,
if (work_available(&priv->rx_work))
{
work_queue(MAC802154_WORK, &priv->rx_work, mac802154_rxframe_worker,
work_queue(HPWORK, &priv->rx_work, mac802154_rxframe_worker,
(FAR void *)priv, 0);
}
}
@ -956,7 +1056,10 @@ static void mac802154_rxframe_worker(FAR void *arg)
mac802154_lock(priv, false);
/* Pop the iob from the head of the frame list for processing */
/* Pop the data indication from the head of the frame list for processing
* Note: dataind_queue contains ieee802154_primitive_s which is safe to
* cast directly to a data indication.
*/
ind = (FAR struct ieee802154_data_ind_s *)sq_remfirst(&priv->dataind_queue);
@ -1040,6 +1143,16 @@ static void mac802154_rxframe_worker(FAR void *arg)
}
}
/* If the MAC is in promiscuous mode, just pass everything to the next layer
* assuming it is data
*/
if (priv->promisc)
{
mac802154_notify(priv, (FAR struct ieee802154_primitive_s *)ind);
continue;
}
ftype = (*frame_ctrl & IEEE802154_FRAMECTRL_FTYPE) >>
IEEE802154_FRAMECTRL_SHIFT_FTYPE;
@ -1073,7 +1186,7 @@ static void mac802154_rxframe_worker(FAR void *arg)
break;
case IEEE802154_CMD_DISASSOC_NOT:
wlinfo("Disassoc notif received\n");
wlinfo("Disassoc primitive received\n");
break;
case IEEE802154_CMD_DATA_REQ:
@ -1082,11 +1195,11 @@ static void mac802154_rxframe_worker(FAR void *arg)
break;
case IEEE802154_CMD_PANID_CONF_NOT:
wlinfo("PAN ID Conflict notif received\n");
wlinfo("PAN ID Conflict primitive received\n");
break;
case IEEE802154_CMD_ORPHAN_NOT:
wlinfo("Orphan notif received\n");
wlinfo("Orphan primitive received\n");
break;
case IEEE802154_CMD_BEACON_REQ:
@ -1104,7 +1217,7 @@ static void mac802154_rxframe_worker(FAR void *arg)
/* Free the data indication struct from the pool */
ieee802154_ind_free(ind);
ieee802154_primitive_free((FAR struct ieee802154_primitive_s *)ind);
}
break;
@ -1112,7 +1225,7 @@ static void mac802154_rxframe_worker(FAR void *arg)
{
wlinfo("Beacon frame received. BSN: 0x%02X\n", ind->dsn);
mac802154_rxbeaconframe(priv, ind);
ieee802154_ind_free(ind);
ieee802154_primitive_free((FAR struct ieee802154_primitive_s *)ind);
}
break;
@ -1123,7 +1236,7 @@ static void mac802154_rxframe_worker(FAR void *arg)
*/
wlinfo("ACK received\n");
ieee802154_ind_free(ind);
ieee802154_primitive_free((FAR struct ieee802154_primitive_s *)ind);
}
break;
}
@ -1142,7 +1255,7 @@ static void mac802154_rxframe_worker(FAR void *arg)
static void mac802154_rxdataframe(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_data_ind_s *ind)
{
FAR struct ieee802154_notif_s *notif;
FAR struct ieee802154_primitive_s *primitive;
/* Get exclusive access to the MAC */
@ -1178,46 +1291,46 @@ static void mac802154_rxdataframe(FAR struct ieee802154_privmac_s *priv,
{
if (!IEEE802154_PANIDCMP(ind->dest.panid, priv->addr.panid))
{
goto notify_with_lock;
mac802154_notify(priv, (FAR struct ieee802154_primitive_s *)ind);
}
if (ind->dest.mode == IEEE802154_ADDRMODE_SHORT &&
!IEEE802154_SADDRCMP(ind->dest.saddr, priv->addr.saddr))
{
goto notify_with_lock;
mac802154_notify(priv, (FAR struct ieee802154_primitive_s *)ind);
}
else if (ind->dest.mode == IEEE802154_ADDRMODE_EXTENDED &&
!IEEE802154_EADDRCMP(ind->dest.eaddr, priv->addr.eaddr))
{
goto notify_with_lock;
mac802154_notify(priv, (FAR struct ieee802154_primitive_s *)ind);
}
else
{
goto notify_with_lock;
mac802154_notify(priv, (FAR struct ieee802154_primitive_s *)ind);
}
}
/* If this was our extracted data, the source addressing field can only
* be NONE if we are trying to extract data from the PAN coordinator.
* A PAN coordinator shouldn't be sending us a frame if it wasn't
* our extracted data. Therefore just assume if the address mode is set
* to NONE, we process it as our extracted frame
*/
* be NONE if we are trying to extract data from the PAN coordinator.
* A PAN coordinator shouldn't be sending us a frame if it wasn't
* our extracted data. Therefore just assume if the address mode is set
* to NONE, we process it as our extracted frame
*/
if (ind->src.mode != priv->cmd_desc->destaddr.mode)
{
goto notify_with_lock;
mac802154_notify(priv, (FAR struct ieee802154_primitive_s *)ind);
}
if (ind->src.mode == IEEE802154_ADDRMODE_SHORT &&
!IEEE802154_SADDRCMP(ind->src.saddr, priv->cmd_desc->destaddr.saddr))
{
goto notify_with_lock;
mac802154_notify(priv, (FAR struct ieee802154_primitive_s *)ind);
}
else if (ind->src.mode == IEEE802154_ADDRMODE_EXTENDED &&
!IEEE802154_EADDRCMP(ind->src.eaddr, priv->cmd_desc->destaddr.eaddr))
{
goto notify_with_lock;
mac802154_notify(priv, (FAR struct ieee802154_primitive_s *)ind);
}
/* If we've gotten this far, the frame is our extracted data. Cancel the
@ -1231,20 +1344,19 @@ static void mac802154_rxdataframe(FAR struct ieee802154_privmac_s *priv,
* MLME-POLL.confirm primitive with a status of NO_DATA. [1] pg. 111
*/
mac802154_notif_alloc(priv, &notif, false);
primitive = ieee802154_primitive_allocate();
if (priv->curr_op == MAC802154_OP_POLL)
{
notif->notiftype = IEEE802154_NOTIFY_CONF_POLL;
primitive->type = IEEE802154_PRIMITIVE_CONF_POLL;
if (ind->frame->io_offset == ind->frame->io_len)
{
ieee802154_ind_free(ind);
notif->u.pollconf.status = IEEE802154_STATUS_NO_DATA;
primitive->u.pollconf.status = IEEE802154_STATUS_NO_DATA;
}
else
{
notif->u.pollconf.status = IEEE802154_STATUS_SUCCESS;
primitive->u.pollconf.status = IEEE802154_STATUS_SUCCESS;
}
}
else if (priv->curr_op == MAC802154_OP_ASSOC)
@ -1253,8 +1365,8 @@ static void mac802154_rxdataframe(FAR struct ieee802154_privmac_s *priv,
* association request, we assume it means there wasn't any data.
*/
notif->notiftype = IEEE802154_NOTIFY_CONF_ASSOC;
notif->u.assocconf.status = IEEE802154_STATUS_NO_DATA;
primitive->type = IEEE802154_PRIMITIVE_CONF_ASSOC;
primitive->u.assocconf.status = IEEE802154_STATUS_NO_DATA;
}
/* We are no longer performing the association operation */
@ -1263,63 +1375,27 @@ static void mac802154_rxdataframe(FAR struct ieee802154_privmac_s *priv,
priv->cmd_desc = NULL;
mac802154_givesem(&priv->opsem);
/* Release the MAC */
/* Release the MAC and notify the next highest layer */
mac802154_unlock(priv)
mac802154_notify(priv, notif);
mac802154_notify(priv, primitive);
/* If there was data, pass it along */
if (ind->frame->io_len > ind->frame->io_offset)
{
goto notify_without_lock;
mac802154_notify(priv, (FAR struct ieee802154_primitive_s *)ind);
}
else
{
ieee802154_primitive_free((FAR struct ieee802154_primitive_s *)ind);
}
}
else
{
FAR struct mac802154_maccb_s *cb;
notify_with_lock:
mac802154_unlock(priv)
notify_without_lock:
/* If there are registered MCPS callback receivers registered,
* then forward the frame in priority order. If there are no
* registered receivers or if none of the receivers accept the
* data frame then drop the frame.
*/
for (cb = priv->cb; cb != NULL; cb = cb->flink)
{
int ret;
/* Does this MAC client want frames? */
if (cb->rxframe != NULL)
{
/* Yes.. Offer this frame to the receiver */
ret = cb->rxframe(cb, ind);
if (ret >= 0)
{
/* The receiver accepted and disposed of the frame and
* its metadata. We are done.
*/
return;
}
}
}
/* We get here if the there are no registered receivers or if
* all of the registered receivers declined the frame.
* Free the data indication struct from the pool
*/
ieee802154_ind_free(ind);
mac802154_notify(priv, (FAR struct ieee802154_primitive_s *)ind);
}
mac802154_unlock(priv)
}
/****************************************************************************
@ -1554,7 +1630,7 @@ static void mac802154_sfevent(FAR const struct ieee802154_radiocb_s *radiocb,
* Function called from the generic RX Frame worker to parse and handle the
* reception of a beacon frame.
*
* Assumptions: MAC is locked
* Assumptions: MAC is unlocked
*
****************************************************************************/
@ -1562,7 +1638,7 @@ static void mac802154_rxbeaconframe(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_data_ind_s *ind)
{
FAR struct ieee802154_txdesc_s *respdesc;
FAR struct ieee802154_notif_s *notif;
FAR struct ieee802154_primitive_s *primitive;
FAR struct ieee802154_beacon_ind_s *beacon;
FAR struct iob_s *iob = ind->frame;
uint8_t ngtsdesc;
@ -1571,15 +1647,15 @@ static void mac802154_rxbeaconframe(FAR struct ieee802154_privmac_s *priv,
bool pending_eaddr = false;
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)
/* Even though we may not use the primitive, we allocate one to hold all the
* parsed beacon information. Freeing the primitive is quick, so it's worth
* 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, &notif, false);
beacon = &notif->u.beaconind;
primitive = ieee802154_primitive_allocate();
beacon = &primitive->u.beaconind;
/* Make sure there is another 2 bytes to process */
@ -1731,6 +1807,8 @@ static void mac802154_rxbeaconframe(FAR struct ieee802154_privmac_s *priv,
/* At this point, we have extracted all relevant info from the incoming frame */
mac802154_lock(priv, false);
if (priv->curr_op == MAC802154_OP_SCAN)
{
/* Check to see if we already have a frame from this coordinator */
@ -1750,7 +1828,8 @@ static void mac802154_rxbeaconframe(FAR struct ieee802154_privmac_s *priv,
/* The beacon is the same as another, so discard it */
mac802154_notif_free_locked(priv, notif);
ieee802154_primitive_free(primitive);
mac802154_unlock(priv);
return;
}
@ -1829,11 +1908,7 @@ static void mac802154_rxbeaconframe(FAR struct ieee802154_privmac_s *priv,
if (beacon->payloadlength > 0)
{
/* Unlock the MAC, notify, then lock again */
mac802154_unlock(priv)
mac802154_notify(priv, notif);
mac802154_lock(priv, false);
mac802154_notify(priv, primitive);
}
/* If we have data pending for us, attempt to extract it. If for some
@ -1881,12 +1956,13 @@ static void mac802154_rxbeaconframe(FAR struct ieee802154_privmac_s *priv,
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 there was a beacon payload, we used the primitive, so
* return here to make sure we don't free the primitive.
*/
if (beacon->payloadlength > 0)
{
mac802154_unlock(priv);
return;
}
}
@ -1897,22 +1973,20 @@ static void mac802154_rxbeaconframe(FAR struct ieee802154_privmac_s *priv,
* by issuing the MLME-BEACON-NOTIFY.indication primitive. [1] pg. 38
*/
/* Unlock the MAC, notify, then lock again */
mac802154_unlock(priv)
mac802154_notify(priv, notif);
mac802154_lock(priv, false);
return; /* Return so that we don't free the notificaiton */
mac802154_notify(priv, primitive);
mac802154_unlock(priv);
return; /* Return so that we don't free the primitive */
}
}
}
mac802154_notif_free_locked(priv, notif);
mac802154_unlock(priv);
ieee802154_primitive_free(primitive);
return;
errout:
wlwarn("Received beacon with bad format\n");
mac802154_notif_free_locked(priv, notif);
ieee802154_primitive_free(primitive);
}
/****************************************************************************
@ -1990,7 +2064,7 @@ MACHANDLE mac802154_create(FAR struct ieee802154_radio_s *radiodev)
/* Initialize our various data pools */
ieee802154_indpool_initialize();
ieee802154_primitivepool_initialize();
mac802154_resetqueues(mac);
mac802154_req_reset((MACHANDLE)mac, true);

View File

@ -68,12 +68,18 @@ struct mac802154_maccb_s
FAR struct mac802154_maccb_s *flink; /* Implements a singly linked list */
uint8_t prio; /* RX frame callback priority */
/* Callback methods */
/* Callback for various MLME or MCPS service events. Return value represents
* whether the callback accepts the primitive. >= 0 means the callback has
* accepted the primitive and is responsible for calling
* ieee802154_primitive_free(). In the case of DATA.indication primitive, only
* one callback can accept the frame. The callbacks are stored in order of
* receiver priority defined by the 'prio' field above. All other
* notifications are offered to all callbacks and all can accept and free
* separately since the primitive will not be freed until the nclients count
* reaches 0. */
CODE void (*notify)(FAR struct mac802154_maccb_s *maccb,
FAR struct ieee802154_notif_s *notif);
CODE int (*rxframe)(FAR struct mac802154_maccb_s *maccb,
FAR struct ieee802154_data_ind_s *ind);
CODE int (*notify)(FAR struct mac802154_maccb_s *maccb,
FAR struct ieee802154_primitive_s *primitive);
};
/****************************************************************************
@ -358,19 +364,6 @@ int mac802154_resp_associate(MACHANDLE mac,
int mac802154_resp_orphan(MACHANDLE mac,
FAR struct ieee802154_orphan_resp_s *resp);
/****************************************************************************
* Name: mac802154_notif_free
*
* Description:
* When the MAC calls the registered callback, it passes a reference
* to a mac802154_notify_s structure. This structure needs to be freed
* after the callback handler is done using it.
*
****************************************************************************/
void mac802154_notif_free(MACHANDLE mac,
FAR struct ieee802154_notif_s *notif);
#undef EXTERN
#ifdef __cplusplus
}

View File

@ -111,12 +111,12 @@ int mac802154_req_associate(MACHANDLE mac,
/* Get exclusive access to the MAC */
ret = mac802154_lock(priv, true);
if (ret < 0)
{
mac802154_givesem(&priv->opsem);
return ret;
}
ret = mac802154_lock(priv, true);
if (ret < 0)
{
mac802154_givesem(&priv->opsem);
return ret;
}
/* Set the channel and channel page of the PHY layer */
@ -452,8 +452,8 @@ void mac802154_txdone_assocreq(FAR struct ieee802154_privmac_s *priv,
{
enum ieee802154_status_e status;
FAR struct ieee802154_txdesc_s *respdesc;
FAR struct ieee802154_notif_s *notif =
(FAR struct ieee802154_notif_s *)txdesc->conf;
FAR struct ieee802154_primitive_s *primitive =
(FAR struct ieee802154_primitive_s *)txdesc->conf;
if(txdesc->conf->status != IEEE802154_STATUS_SUCCESS)
{
@ -463,23 +463,23 @@ void mac802154_txdone_assocreq(FAR struct ieee802154_privmac_s *priv,
*/
/* We can actually high-jack the data conf notification since it
* is allocated as an ieee80215_notif_s anyway. Before we overwrite
* is allocated as an ieee80215_primitive_s anyway. Before we overwrite
* any data though, we need to get the status from the data
* confirmation as that is the method we use to get the reason
* why the tx failed from the radio layer.
*/
status = txdesc->conf->status;
notif->notiftype = IEEE802154_NOTIFY_CONF_ASSOC;
primitive->type = IEEE802154_PRIMITIVE_CONF_ASSOC;
notif->u.assocconf.status = status;
primitive->u.assocconf.status = status;
/* The short device address allocated by the coordinator on
* successful association. This parameter will be equal to 0xffff
* if the association attempt was unsuccessful. [1] pg. 81
*/
IEEE802154_SADDRCOPY(notif->u.assocconf.saddr, &IEEE802154_SADDR_UNSPEC);
IEEE802154_SADDRCOPY(primitive->u.assocconf.saddr, &IEEE802154_SADDR_UNSPEC);
/* We are now done the operation, unlock the semaphore */
@ -490,9 +490,7 @@ void mac802154_txdone_assocreq(FAR struct ieee802154_privmac_s *priv,
/* Release the MAC, call the callback, get exclusive access again */
mac802154_unlock(priv)
mac802154_notify(priv, notif);
mac802154_lock(priv, false);
mac802154_notify(priv, primitive);
}
else
{
@ -564,7 +562,7 @@ void mac802154_txdone_assocreq(FAR struct ieee802154_privmac_s *priv,
/* Deallocate the data conf notification as it is no longer needed. */
mac802154_notif_free_locked(priv, notif);
ieee802154_primitive_free(primitive);
}
}
@ -585,8 +583,8 @@ void mac802154_txdone_datareq_assoc(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_txdesc_s *txdesc)
{
enum ieee802154_status_e status;
FAR struct ieee802154_notif_s *notif =
(FAR struct ieee802154_notif_s *)txdesc->conf;
FAR struct ieee802154_primitive_s *primitive =
(FAR struct ieee802154_primitive_s *)txdesc->conf;
/* If the data request failed to be sent, notify the next layer
* that the association has failed.
@ -596,12 +594,12 @@ void mac802154_txdone_datareq_assoc(FAR struct ieee802154_privmac_s *priv,
* pending at the coordinator. [1] pg. 43
*/
if (notif->u.dataconf.status != IEEE802154_STATUS_SUCCESS ||
if (primitive->u.dataconf.status != IEEE802154_STATUS_SUCCESS ||
txdesc->framepending == 0)
{
if (notif->u.dataconf.status != IEEE802154_STATUS_SUCCESS)
if (primitive->u.dataconf.status != IEEE802154_STATUS_SUCCESS)
{
status = notif->u.dataconf.status;
status = primitive->u.dataconf.status;
}
else
{
@ -615,15 +613,15 @@ void mac802154_txdone_datareq_assoc(FAR struct ieee802154_privmac_s *priv,
status = IEEE802154_STATUS_NO_DATA;
}
notif->notiftype = IEEE802154_NOTIFY_CONF_ASSOC;
notif->u.assocconf.status = status;
primitive->type = IEEE802154_PRIMITIVE_CONF_ASSOC;
primitive->u.assocconf.status = status;
/* The short device address allocated by the coordinator on
* successful association. This parameter will be equal to 0xffff
* if the association attempt was unsuccessful. [1] pg. 81
*/
IEEE802154_SADDRCOPY(notif->u.assocconf.saddr, &IEEE802154_SADDR_UNSPEC);
IEEE802154_SADDRCOPY(primitive->u.assocconf.saddr, &IEEE802154_SADDR_UNSPEC);
/* We are now done the operation, and can release the command */
@ -631,11 +629,7 @@ void mac802154_txdone_datareq_assoc(FAR struct ieee802154_privmac_s *priv,
priv->cmd_desc = NULL;
mac802154_givesem(&priv->opsem);
/* Release the MAC, call the callback, get exclusive access again */
mac802154_unlock(priv)
mac802154_notify(priv, notif);
mac802154_lock(priv, false);
mac802154_notify(priv, primitive);
}
else
{
@ -672,7 +666,7 @@ void mac802154_txdone_datareq_assoc(FAR struct ieee802154_privmac_s *priv,
/* Deallocate the data conf notification as it is no longer needed. */
mac802154_notif_free_locked(priv, notif);
ieee802154_primitive_free(primitive);
}
}
@ -690,17 +684,13 @@ void mac802154_rx_assocreq(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_data_ind_s *ind)
{
FAR struct iob_s *frame = ind->frame;
FAR struct ieee802154_notif_s *notif;
FAR struct ieee802154_primitive_s *primitive;
uint8_t cap;
/* Get exclusive access to the MAC */
mac802154_lock(priv, false);
/* Allocate a notification to pass to the next highest layer */
mac802154_notif_alloc(priv, &notif, false);
notif->notiftype = IEEE802154_NOTIFY_IND_ASSOC;
primitive = ieee802154_primitive_allocate();
primitive->type = IEEE802154_PRIMITIVE_IND_ASSOC;
/* Association Requests should always be sent from a device with source
* addressing mode set to extended mode. Throw out any request received
@ -709,43 +699,39 @@ void mac802154_rx_assocreq(FAR struct ieee802154_privmac_s *priv,
if (ind->src.mode != IEEE802154_ADDRMODE_EXTENDED)
{
goto errout_with_sem;
return;
}
/* Copy the extended address of the requesting device */
IEEE802154_EADDRCOPY(notif->u.assocind.devaddr, ind->src.eaddr);
IEEE802154_EADDRCOPY(primitive->u.assocind.devaddr, ind->src.eaddr);
/* Copy in the capability information from the frame to the notification */
cap = frame->io_data[frame->io_offset++];
notif->u.assocind.capabilities.devtype =
primitive->u.assocind.capabilities.devtype =
(cap >> IEEE802154_CAPABILITY_SHIFT_DEVTYPE) & 0x01;
notif->u.assocind.capabilities.powersource =
primitive->u.assocind.capabilities.powersource =
(cap >> IEEE802154_CAPABILITY_SHIFT_PWRSRC) & 0x01;
notif->u.assocind.capabilities.rxonidle =
primitive->u.assocind.capabilities.rxonidle =
(cap >> IEEE802154_CAPABILITY_SHIFT_RXONIDLE) & 0x01;
notif->u.assocind.capabilities.security =
primitive->u.assocind.capabilities.security =
(cap >> IEEE802154_CAPABILITY_SHIFT_SECURITY) & 0x01;
notif->u.assocind.capabilities.allocaddr =
primitive->u.assocind.capabilities.allocaddr =
(cap >> IEEE802154_CAPABILITY_SHIFT_ALLOCADDR) & 0x01;
#ifdef CONFIG_IEEE802154_SECURITY
#error Missing security logic
#endif
/* Unlock the MAC */
/* Get exclusive access to the MAC */
mac802154_unlock(priv)
mac802154_lock(priv, false);
/* Notify the next highest layer of the association status */
mac802154_notify(priv, notif);
return;
errout_with_sem:
mac802154_notify(priv, primitive);
mac802154_unlock(priv)
return;
}
/****************************************************************************
@ -761,7 +747,7 @@ void mac802154_rx_assocresp(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_data_ind_s *ind)
{
FAR struct iob_s *iob = ind->frame;
FAR struct ieee802154_notif_s *notif;
FAR struct ieee802154_primitive_s *primitive;
/* Check if we are performing an Association operation, if not, we will just
* ignore the frame.
@ -789,15 +775,15 @@ void mac802154_rx_assocresp(FAR struct ieee802154_privmac_s *priv,
mac802154_timercancel(priv);
/* Allocate a notification to pass to the next highest layer */
primitive = ieee802154_primitive_allocate();
primitive->type = IEEE802154_PRIMITIVE_CONF_ASSOC;
/* Get exclusive access to the MAC */
mac802154_lock(priv, false);
/* Allocate a notification to pass to the next highest layer */
mac802154_notif_alloc(priv, &notif, false);
notif->notiftype = IEEE802154_NOTIFY_CONF_ASSOC;
/* Parse the short address from the response */
mac802154_takesaddr(iob, priv->addr.saddr);
@ -822,9 +808,9 @@ void mac802154_rx_assocresp(FAR struct ieee802154_privmac_s *priv,
/* Parse the status from the response */
notif->u.assocconf.status = iob->io_data[iob->io_offset++];
primitive->u.assocconf.status = iob->io_data[iob->io_offset++];
if (notif->u.assocconf.status == IEEE802154_STATUS_SUCCESS)
if (primitive->u.assocconf.status == IEEE802154_STATUS_SUCCESS)
{
priv->isassoc = true;
}
@ -833,7 +819,7 @@ void mac802154_rx_assocresp(FAR struct ieee802154_privmac_s *priv,
priv->isassoc = false;
}
IEEE802154_SADDRCOPY(notif->u.assocconf.saddr, priv->addr.saddr);
IEEE802154_SADDRCOPY(primitive->u.assocconf.saddr, priv->addr.saddr);
/* We are no longer performing the association operation */
@ -842,13 +828,10 @@ void mac802154_rx_assocresp(FAR struct ieee802154_privmac_s *priv,
mac802154_givesem(&priv->opsem);
mac802154_rxdisable(priv);
/* Unlock the MAC */
mac802154_unlock(priv)
/* Notify the next highest layer of the association status */
mac802154_notify(priv, notif);
mac802154_notify(priv, primitive);
mac802154_unlock(priv)
}
/****************************************************************************
@ -867,7 +850,7 @@ void mac802154_rx_assocresp(FAR struct ieee802154_privmac_s *priv,
static void mac802154_assoctimeout(FAR void *arg)
{
FAR struct ieee802154_privmac_s *priv = (FAR struct ieee802154_privmac_s *)arg;
FAR struct ieee802154_notif_s *notif;
FAR struct ieee802154_primitive_s *primitive;
/* If there is work scheduled for the rxframe_worker, we want to reschedule
* this work, so that we make sure if the frame we were waiting for was just
@ -876,7 +859,7 @@ static void mac802154_assoctimeout(FAR void *arg)
if (!work_available(&priv->rx_work))
{
work_queue(MAC802154_WORK, &priv->timer_work, mac802154_assoctimeout, priv, 0);
work_queue(HPWORK, &priv->timer_work, mac802154_assoctimeout, priv, 0);
return;
}
@ -893,8 +876,11 @@ static void mac802154_assoctimeout(FAR void *arg)
* Don't allow EINTR to interrupt.
*/
mac802154_lock(priv, false);
mac802154_notif_alloc(priv, &notif, false);
primitive = ieee802154_primitive_allocate();
primitive->type = IEEE802154_PRIMITIVE_CONF_ASSOC;
primitive->u.assocconf.status = IEEE802154_STATUS_NO_DATA;
IEEE802154_SADDRCOPY(primitive->u.assocconf.saddr, &IEEE802154_SADDR_UNSPEC);
/* We are no longer performing the association operation */
@ -903,13 +889,7 @@ static void mac802154_assoctimeout(FAR void *arg)
mac802154_givesem(&priv->opsem);
mac802154_rxdisable(priv);
/* Release the MAC */
mac802154_lock(priv, false);
mac802154_notify(priv, primitive);
mac802154_unlock(priv)
notif->notiftype = IEEE802154_NOTIFY_CONF_ASSOC;
notif->u.assocconf.status = IEEE802154_STATUS_NO_DATA;
IEEE802154_SADDRCOPY(notif->u.assocconf.saddr, &IEEE802154_SADDR_UNSPEC);
mac802154_notify(priv, notif);
}

View File

@ -99,11 +99,10 @@ struct mac802154_chardevice_s
/* Hold a list of events */
bool enableevents : 1; /* Are events enabled? */
bool geteventpending : 1; /* Is there a get event using the semaphore? */
sem_t geteventsem; /* Signaling semaphore for waiting get event */
FAR struct ieee802154_notif_s *event_head;
FAR struct ieee802154_notif_s *event_tail;
bool enableevents : 1; /* Are events enabled? */
bool geteventpending : 1; /* Is there a get event using the semaphore? */
sem_t geteventsem; /* Signaling semaphore for waiting get event */
sq_queue_t primitive_queue; /* For holding primitives to pass along */
/* The following is a singly linked list of open references to the
* MAC device.
@ -136,15 +135,10 @@ struct mac802154_chardevice_s
static inline int mac802154dev_takesem(sem_t *sem);
#define mac802154dev_givesem(s) nxsem_post(s);
static inline void mac802154dev_pushevent(FAR struct mac802154_chardevice_s *dev,
FAR struct ieee802154_notif_s *notif);
static inline FAR struct ieee802154_notif_s *
mac802154dev_popevent(FAR struct mac802154_chardevice_s *dev);
static void mac802154dev_notify(FAR struct mac802154_maccb_s *maccb,
FAR struct ieee802154_notif_s *notif);
static int mac802154dev_rxframe(FAR struct mac802154_maccb_s *maccb,
FAR struct ieee802154_data_ind_s *ind);
static int mac802154dev_notify(FAR struct mac802154_maccb_s *maccb,
FAR struct ieee802154_primitive_s *primitive);
static int mac802154dev_rxframe(FAR struct mac802154_chardevice_s *dev,
FAR struct ieee802154_data_ind_s *ind);
static int mac802154dev_open(FAR struct file *filep);
static int mac802154dev_close(FAR struct file *filep);
@ -203,63 +197,6 @@ static inline int mac802154dev_takesem(sem_t *sem)
return ret;
}
/****************************************************************************
* Name: mac802154dev_pushevent
*
* Description:
* Push event onto the event queue
*
* Assumptions:
* Called with the char device struct locked.
*
****************************************************************************/
static inline void mac802154dev_pushevent(FAR struct mac802154_chardevice_s *dev,
FAR struct ieee802154_notif_s *notif)
{
notif->flink = NULL;
if (!dev->event_head)
{
dev->event_head = notif;
dev->event_tail = notif;
}
else
{
dev->event_tail->flink = notif;
dev->event_tail = notif;
}
}
/****************************************************************************
* Name: mac802154dev_popevent
*
* Description:
* Pop an event off of the event queue
*
* Assumptions:
* Called with the char device struct locked.
*
****************************************************************************/
static inline FAR struct ieee802154_notif_s *
mac802154dev_popevent(FAR struct mac802154_chardevice_s *dev)
{
FAR struct ieee802154_notif_s *notif = dev->event_head;
if (notif)
{
dev->event_head = notif->flink;
if (!dev->event_head)
{
dev->event_head = NULL;
}
notif->flink = NULL;
}
return notif;
}
/****************************************************************************
* Name: mac802154dev_open
*
@ -408,13 +345,16 @@ static int mac802154dev_close(FAR struct file *filep)
if (dev->md_open)
{
FAR struct ieee802154_notif_s *notif;
FAR struct ieee802154_primitive_s *primitive;
while (dev->event_head != NULL)
primitive =
(FAR struct ieee802154_primitive_s *)sq_remfirst(&dev->primitive_queue);
while (primitive)
{
notif = mac802154dev_popevent(dev);
DEBUGASSERT(notif != NULL);
mac802154_notif_free(dev->md_mac, notif);
ieee802154_primitive_free(primitive);
primitive =
(FAR struct ieee802154_primitive_s *)sq_remfirst(&dev->primitive_queue);
}
}
@ -440,6 +380,7 @@ static ssize_t mac802154dev_read(FAR struct file *filep, FAR char *buffer,
FAR struct mac802154_chardevice_s *dev;
FAR struct mac802154dev_rxframe_s *rx;
FAR struct ieee802154_data_ind_s *ind;
struct ieee802154_get_req_s req;
int ret;
DEBUGASSERT(filep && filep->f_inode);
@ -513,12 +454,34 @@ static ssize_t mac802154dev_read(FAR struct file *filep, FAR char *buffer,
*/
}
rx->length = (ind->frame->io_len - ind->frame->io_offset);
/* Check if the MAC layer is in promiscuous mode. If it is, pass the entire
* frame, including IEEE 802.15.4 header and checksum by assuming the frame
* starts at the beginning of the IOB and goes 2 past the length to account
* for the FCS that the radio driver "removes"
*/
/* Copy the data from the IOB to the user supplied struct */
req.attr = IEEE802154_ATTR_MAC_PROMISCUOUS_MODE;
memcpy(&rx->payload[0], &ind->frame->io_data[ind->frame->io_offset],
rx->length);
ret = mac802154_ioctl(dev->md_mac, MAC802154IOC_MLME_GET_REQUEST,
(unsigned long)&req);
if (ret == 0 && req.attrval.mac.promisc_mode)
{
rx->length = ind->frame->io_len + 2;
/* Copy the data from the IOB to the user supplied struct */
memcpy(&rx->payload[0], &ind->frame->io_data[0], rx->length);
}
else
{
rx->length = (ind->frame->io_len - ind->frame->io_offset);
/* Copy the data from the IOB to the user supplied struct */
memcpy(&rx->payload[0], &ind->frame->io_data[ind->frame->io_offset],
rx->length);
}
memcpy(&rx->meta, ind, sizeof(struct ieee802154_data_ind_s));
@ -527,9 +490,13 @@ static ssize_t mac802154dev_read(FAR struct file *filep, FAR char *buffer,
rx->meta.flink = NULL;
rx->meta.frame = NULL;
/* Free the IOB */
iob_free(ind->frame);
/* Deallocate the data indication */
ieee802154_ind_free(ind);
ieee802154_primitive_free((FAR struct ieee802154_primitive_s *)ind);
return OK;
}
@ -666,25 +633,26 @@ static int mac802154dev_ioctl(FAR struct file *filep, int cmd,
case MAC802154IOC_GET_EVENT:
{
FAR struct ieee802154_notif_s *notif;
FAR struct ieee802154_primitive_s *primitive;
while (1)
{
/* Try popping an event off the queue */
notif = mac802154dev_popevent(dev);
primitive = (FAR struct ieee802154_primitive_s *)
sq_remfirst(&dev->primitive_queue);
/* If there was an event to pop off, copy it into the user data and
* free it from the MAC layer's memory.
*/
if (notif != NULL)
if (primitive != NULL)
{
memcpy(&macarg->notif, notif, sizeof(struct ieee802154_notif_s));
memcpy(&macarg->primitive, primitive, sizeof(struct ieee802154_primitive_s));
/* Free the notification */
mac802154_notif_free(dev->md_mac, notif);
ieee802154_primitive_free(primitive);
ret = OK;
break;
}
@ -750,8 +718,8 @@ static int mac802154dev_ioctl(FAR struct file *filep, int cmd,
return ret;
}
static void mac802154dev_notify(FAR struct mac802154_maccb_s *maccb,
FAR struct ieee802154_notif_s *notif)
static int mac802154dev_notify(FAR struct mac802154_maccb_s *maccb,
FAR struct ieee802154_primitive_s *primitive)
{
FAR struct mac802154dev_callback_s *cb =
(FAR struct mac802154dev_callback_s *)maccb;
@ -760,10 +728,12 @@ static void mac802154dev_notify(FAR struct mac802154_maccb_s *maccb,
DEBUGASSERT(cb != NULL && cb->mc_priv != NULL);
dev = cb->mc_priv;
/* Get exclusive access to the driver structure. We don't care about any
* signals so if we see one, just go back to trying to get access again */
/* Handle the special case for data indications or "incoming frames" */
while (mac802154dev_takesem(&dev->md_exclsem) != 0);
if (primitive->type == IEEE802154_PRIMITIVE_IND_DATA)
{
return mac802154dev_rxframe(dev, &primitive->u.dataind);
}
/* If there is a registered notification receiver, queue the event and signal
* the receiver. Events should be popped from the queue from the application
@ -773,7 +743,13 @@ static void mac802154dev_notify(FAR struct mac802154_maccb_s *maccb,
if (dev->enableevents && (dev->md_open != NULL || dev->md_notify_registered))
{
mac802154dev_pushevent(dev, notif);
/* Get exclusive access to the driver structure. We don't care about any
* signals so if we see one, just go back to trying to get access again */
while (mac802154dev_takesem(&dev->md_exclsem) != 0);
sq_addlast((FAR sq_entry_t *)primitive, &dev->primitive_queue);
/* Check if there is a read waiting for data */
@ -791,28 +767,25 @@ static void mac802154dev_notify(FAR struct mac802154_maccb_s *maccb,
#ifdef CONFIG_CAN_PASS_STRUCTS
union sigval value;
value.sival_int = (int)notif->notiftype;
value.sival_int = (int)primitive->type;
(void)nxsig_queue(dev->md_notify_pid, dev->md_notify_signo,
value);
#else
(void)nxsig_queue(dev->md_notify_pid, dev->md_notify_signo,
(FAR void *)notif->notiftype);
(FAR void *)primitive->type);
#endif
}
#endif
}
else
{
/* Just free the event if the driver is closed and there isn't a registered
* signal number.
*/
mac802154_notif_free(dev->md_mac, notif);
mac802154dev_givesem(&dev->md_exclsem);
return OK;
}
/* Release the driver */
/* By returning a negative value, we let the MAC know that we don't want the
* primitive and it will free it for us
*/
mac802154dev_givesem(&dev->md_exclsem);
return -1;
}
/****************************************************************************
@ -827,16 +800,9 @@ static void mac802154dev_notify(FAR struct mac802154_maccb_s *maccb,
*
****************************************************************************/
static int mac802154dev_rxframe(FAR struct mac802154_maccb_s *maccb,
static int mac802154dev_rxframe(FAR struct mac802154_chardevice_s *dev,
FAR struct ieee802154_data_ind_s *ind)
{
FAR struct mac802154dev_callback_s *cb =
(FAR struct mac802154dev_callback_s *)maccb;
FAR struct mac802154_chardevice_s *dev;
DEBUGASSERT(cb != NULL && cb->mc_priv != NULL);
dev = cb->mc_priv;
/* Get exclusive access to the driver structure. We don't care about any
* signals so if we see one, just go back to trying to get access again */
@ -914,8 +880,7 @@ int mac802154dev_register(MACHANDLE mac, int minor)
nxsem_init(&dev->geteventsem, 0, 0);
nxsem_setprotocol(&dev->geteventsem, SEM_PRIO_NONE);
dev->event_head = NULL;
dev->event_tail = NULL;
sq_init(&dev->primitive_queue);
dev->enableevents = true;
dev->md_notify_registered = false;
@ -928,7 +893,6 @@ int mac802154dev_register(MACHANDLE mac, int minor)
maccb->flink = NULL;
maccb->prio = CONFIG_IEEE802154_MACDEV_RECVRPRIO;
maccb->notify = mac802154dev_notify;
maccb->rxframe = mac802154dev_rxframe;
/* Bind the callback structure */

View File

@ -198,10 +198,21 @@ int mac802154_req_set(MACHANDLE mac, enum ieee802154_attr_e attr,
{
priv->resp_waittime = attrval->mac.resp_waittime;
}
break;
case IEEE802154_ATTR_MAC_RX_ON_WHEN_IDLE:
{
mac802154_setrxonidle(priv, attrval->mac.rxonidle);
}
break;
case IEEE802154_ATTR_MAC_PROMISCUOUS_MODE:
{
ret = priv->radio->setattr(priv->radio, attr, attrval);
if (ret == 0)
{
priv->promisc = attrval->mac.promisc_mode;
}
}
break;
default:
{
/* The attribute may be handled soley in the radio driver, so pass

View File

@ -59,8 +59,6 @@
#include <nuttx/wqueue.h>
#include <nuttx/semaphore.h>
#include "mac802154_notif.h"
#include <nuttx/wireless/ieee802154/ieee802154_mac.h>
#include <nuttx/wireless/ieee802154/ieee802154_radio.h>
@ -73,33 +71,13 @@
* is required.
*/
#if !defined(CONFIG_SCHED_WORKQUEUE)
# error Work queue support is required in this configuration (CONFIG_SCHED_WORKQUEUE)
#else
/* Use the low priority work queue if possible */
# if defined(CONFIG_MAC802154_HPWORK)
# define MAC802154_WORK HPWORK
# elif defined(CONFIG_MAC802154_LPWORK)
# define MAC802154_WORK LPWORK
# else
# error Neither CONFIG_MAC802154_HPWORK nor CONFIG_MAC802154_LPWORK defined
# endif
#endif
#if !defined(CONFIG_MAC802154_NNOTIF) || CONFIG_MAC802154_NNOTIF <= 0
# undef CONFIG_MAC802154_NNOTIF
# define CONFIG_MAC802154_NNOTIF 6
#if !defined(CONFIG_SCHED_HPWORK) || !defined(CONFIG_SCHED_LPWORK)
# error Both Low and High priority work queues are required for this driver
#endif
#if !defined(CONFIG_MAC802154_NTXDESC) || CONFIG_MAC802154_NTXDESC <= 0
# undef CONFIG_MAC802154_NTXDESC
# define CONFIG_MAC802154_NTXDESC 3
#endif
#if CONFIG_MAC802154_NTXDESC > CONFIG_MAC802154_NNOTIF
# error CONFIG_MAC802154_NNOTIF must be greater than CONFIG_MAC802154_NTXDESC
# define CONFIG_MAC802154_NTXDESC 5
#endif
#if !defined(CONFIG_IEEE802154_DEFAULT_EADDR)
@ -182,14 +160,9 @@ struct ieee802154_privmac_s
/******************* Fields related to notifications ************************/
/* Pre-allocated notifications to be passed to the registered callback. These
* need to be freed by the application using mac802154_xxxxnotif_free when
* the callee layer is finished with it's use.
*/
FAR struct mac802154_notif_s *notif_free;
struct mac802154_notif_s notif_pool[CONFIG_MAC802154_NNOTIF];
sem_t notif_sem;
sq_queue_t primitive_queue; /* Queue of primitives to pass via notify()
* callback to registered receivers */
struct work_s notifwork; /* For deferring notifications to LPWORK queue*/
/******************* Tx descriptor queues and pools *************************/
@ -356,20 +329,22 @@ struct ieee802154_privmac_s
* Function Prototypes
****************************************************************************/
int mac802154_txdesc_alloc(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_txdesc_s **txdesc,
bool allow_interrupt);
int mac802154_txdesc_alloc(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_txdesc_s **txdesc, bool allow_interrupt);
void mac802154_setupindirect(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_txdesc_s *txdesc);
FAR struct ieee802154_txdesc_s *txdesc);
void mac802154_createdatareq(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_addr_s *coordaddr,
enum ieee802154_addrmode_e srcmode,
FAR struct ieee802154_txdesc_s *txdesc);
FAR struct ieee802154_addr_s *coordaddr,
enum ieee802154_addrmode_e srcmode,
FAR struct ieee802154_txdesc_s *txdesc);
void mac802154_updatebeacon(FAR struct ieee802154_privmac_s *priv);
void mac802154_notify(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_primitive_s *primitive);
/****************************************************************************
* Helper Macros/Inline Functions
****************************************************************************/
@ -546,7 +521,7 @@ void mac802154_updatebeacon(FAR struct ieee802154_privmac_s *priv);
/* General helpers **********************************************************/
#define mac802154_givesem(s) sem_post(s)
#define mac802154_givesem(s) nxsem_post(s)
static inline int mac802154_takesem(sem_t *sem, bool allowinterrupt)
{
@ -682,7 +657,7 @@ static inline void mac802154_timerstart(FAR struct ieee802154_privmac_s *priv,
/* Schedule the work, converting the number of symbols to the number of CPU ticks */
work_queue(MAC802154_WORK, &priv->timer_work, worker, priv,
work_queue(HPWORK, &priv->timer_work, worker, priv,
mac802154_symtoticks(priv, numsymbols));
}
@ -699,7 +674,7 @@ static inline void mac802154_timerstart(FAR struct ieee802154_privmac_s *priv,
static inline int mac802154_timercancel(FAR struct ieee802154_privmac_s *priv)
{
work_cancel(MAC802154_WORK, &priv->timer_work);
work_cancel(HPWORK, &priv->timer_work);
wlinfo("Timer cancelled\n");
return OK;
}

View File

@ -140,8 +140,8 @@ struct macnet_driver_s
{
/* This holds the information visible to the NuttX network */
struct radio_driver_s md_dev; /* Interface understood by the network */
/* Cast compatible with struct macnet_driver_s */
struct radio_driver_s md_dev; /* Interface understood by the network */
/* Cast compatible with struct macnet_driver_s */
/* For internal use by this driver */
@ -154,11 +154,10 @@ struct macnet_driver_s
/* Hold a list of events */
bool md_enableevents : 1; /* Are events enabled? */
bool md_eventpending : 1; /* Is there a get event using the semaphore? */
sem_t md_eventsem; /* Signaling semaphore for waiting get event */
FAR struct ieee802154_notif_s *md_eventhead;
FAR struct ieee802154_notif_s *md_eventtail;
bool md_enableevents : 1; /* Are events enabled? */
bool md_eventpending : 1; /* Is there a get event using the semaphore? */
sem_t md_eventsem; /* Signaling semaphore for waiting get event */
sq_queue_t primitive_queue; /* For holding primitives to pass along */
#ifndef CONFIG_DISABLE_SIGNALS
/* MAC Service notification information */
@ -178,22 +177,13 @@ struct macnet_driver_s
static int macnet_advertise(FAR struct net_driver_s *dev);
static inline void macnet_netmask(FAR struct net_driver_s *dev);
static inline void macnet_pushevent(FAR struct macnet_driver_s *priv,
FAR struct ieee802154_notif_s *notif);
static inline FAR struct ieee802154_notif_s *
macnet_popevent(FAR struct macnet_driver_s *priv);
/* IEE802.15.4 MAC callback functions ***************************************/
static void macnet_notify(FAR struct mac802154_maccb_s *maccb,
FAR struct ieee802154_notif_s *notif);
static int macnet_rxframe(FAR struct mac802154_maccb_s *maccb,
static int macnet_notify(FAR struct mac802154_maccb_s *maccb,
FAR struct ieee802154_primitive_s *primitive);
static int macnet_rxframe(FAR struct macnet_driver_s *maccb,
FAR struct ieee802154_data_ind_s *ind);
/* Asynchronous event indications, replied to synchronously with responses.
* (none are implemented).
*/
/* Network interface support ************************************************/
/* Common TX logic */
@ -389,63 +379,6 @@ static inline void macnet_netmask(FAR struct net_driver_s *dev)
#endif
}
/****************************************************************************
* Name: macnet_pushevent
*
* Description:
* Push event onto the event queue
*
* Assumptions:
* Called with the device struct locked.
*
****************************************************************************/
static inline void macnet_pushevent(FAR struct macnet_driver_s *priv,
FAR struct ieee802154_notif_s *notif)
{
notif->flink = NULL;
if (!priv->md_eventhead)
{
priv->md_eventhead = notif;
priv->md_eventtail = notif;
}
else
{
priv->md_eventtail->flink = notif;
priv->md_eventtail = notif;
}
}
/****************************************************************************
* Name: macnet_popevent
*
* Description:
* Pop an event off of the event queue
*
* Assumptions:
* Called with the device struct locked.
*
****************************************************************************/
static inline FAR struct ieee802154_notif_s *
macnet_popevent(FAR struct macnet_driver_s *priv)
{
FAR struct ieee802154_notif_s *notif = priv->md_eventhead;
if (notif)
{
priv->md_eventhead = notif->flink;
if (!priv->md_eventhead)
{
priv->md_eventhead = NULL;
}
notif->flink = NULL;
}
return notif;
}
/****************************************************************************
* Name: macnet_notify
*
@ -453,8 +386,8 @@ static inline FAR struct ieee802154_notif_s *
*
****************************************************************************/
static void macnet_notify(FAR struct mac802154_maccb_s *maccb,
FAR struct ieee802154_notif_s *notif)
static int macnet_notify(FAR struct mac802154_maccb_s *maccb,
FAR struct ieee802154_primitive_s *primitive)
{
FAR struct macnet_callback_s *cb =
(FAR struct macnet_callback_s *)maccb;
@ -463,10 +396,12 @@ static void macnet_notify(FAR struct mac802154_maccb_s *maccb,
DEBUGASSERT(cb != NULL && cb->mc_priv != NULL);
priv = cb->mc_priv;
/* Get exclusive access to the driver structure. We don't care about any
* signals so if we see one, just go back to trying to get access again */
/* Handle the special case for data indications or "incoming frames" */
while (nxsem_wait(&priv->md_exclsem) < 0);
if (primitive->type == IEEE802154_PRIMITIVE_IND_DATA)
{
return macnet_rxframe(priv, &primitive->u.dataind);
}
/* If there is a registered notification receiver, queue the event and signal
* the receiver. Events should be popped from the queue from the application
@ -476,7 +411,13 @@ static void macnet_notify(FAR struct mac802154_maccb_s *maccb,
if (priv->md_enableevents)
{
macnet_pushevent(priv, notif);
/* Get exclusive access to the driver structure. We don't care about any
* signals so if we see one, just go back to trying to get access again
*/
while (nxsem_wait(&priv->md_exclsem) < 0);
sq_addlast((FAR sq_entry_t *)primitive, &priv->primitive_queue);
/* Check if there is a read waiting for data */
@ -493,23 +434,18 @@ static void macnet_notify(FAR struct mac802154_maccb_s *maccb,
{
#ifdef CONFIG_CAN_PASS_STRUCTS
union sigval value;
value.sival_int = (int)notif->notiftype;
value.sival_int = (int)primitive->type;
(void)nxsig_queue(priv->md_notify_pid, priv->md_notify_signo,
value);
#else
(void)nxsig_queue(priv->md_notify_pid, priv->md_notify_signo,
(FAR void *)notif->notiftype);
(FAR void *)primitive->type);
#endif
}
#endif
}
else
{
/* Just free the event if the driver is closed and there isn't a registered
* signal number.
*/
mac802154_notif_free(priv->md_mac, notif);
nxsem_post(&priv->md_exclsem);
return OK;
}
nxsem_post(&priv->md_exclsem);
@ -528,18 +464,12 @@ static void macnet_notify(FAR struct mac802154_maccb_s *maccb,
*
****************************************************************************/
static int macnet_rxframe(FAR struct mac802154_maccb_s *maccb,
static int macnet_rxframe(FAR struct macnet_driver_s *priv,
FAR struct ieee802154_data_ind_s *ind)
{
FAR struct macnet_callback_s *cb =
(FAR struct macnet_callback_s *)maccb;
FAR struct macnet_driver_s *priv;
FAR struct iob_s *iob;
int ret;
DEBUGASSERT(cb != NULL && cb->mc_priv != NULL);
priv = cb->mc_priv;
/* Ignore the frame if the network is not up */
if (!priv->md_bifup)
@ -557,6 +487,8 @@ static int macnet_rxframe(FAR struct mac802154_maccb_s *maccb,
ind->frame = NULL;
net_lock();
/* Transfer the frame to the network logic */
#ifdef CONFIG_NET_IEEE802154
@ -597,6 +529,7 @@ static int macnet_rxframe(FAR struct mac802154_maccb_s *maccb,
if (ret < 0)
#endif
{
net_unlock();
ind->frame = iob;
return ret;
}
@ -606,11 +539,13 @@ static int macnet_rxframe(FAR struct mac802154_maccb_s *maccb,
NETDEV_RXPACKETS(&priv->md_dev.r_dev);
NETDEV_RXIPV6(&priv->md_dev.r_dev);
net_unlock();
/* sixlowpan_input() will free the IOB, but we must free the struct
* ieee802154_data_ind_s container here.
* ieee802154_primitive_s container here.
*/
ieee802154_ind_free(ind);
ieee802154_primitive_free((FAR struct ieee802154_primitive_s *)ind);
return OK;
}
@ -1134,25 +1069,26 @@ static int macnet_ioctl(FAR struct net_driver_s *dev, int cmd,
case MAC802154IOC_GET_EVENT:
{
FAR struct ieee802154_notif_s *notif;
FAR struct ieee802154_primitive_s *primitive;
while (1)
{
/* Try popping an event off the queue */
notif = macnet_popevent(priv);
primitive = (FAR struct ieee802154_primitive_s *)
sq_remfirst(&priv->primitive_queue);
/* If there was an event to pop off, copy it into the user
* data and free it from the MAC layer's memory.
*/
if (notif != NULL)
if (primitive != NULL)
{
memcpy(&netmac->u, notif, sizeof(struct ieee802154_notif_s));
memcpy(&netmac->u, primitive, sizeof(struct ieee802154_primitive_s));
/* Free the notification */
mac802154_notif_free(priv->md_mac, notif);
mac802154_primitive_free(priv->md_mac, primitive);
ret = OK;
break;
}
@ -1486,8 +1422,7 @@ int mac802154netdev_register(MACHANDLE mac)
nxsem_init(&priv->md_eventsem, 0, 0);
nxsem_setprotocol(&priv->md_eventsem, SEM_PRIO_NONE);
priv->md_eventhead = NULL;
priv->md_eventtail = NULL;
sq_init(&priv->primitive_queue);
priv->md_enableevents = false;
priv->md_notify_registered = false;
@ -1500,7 +1435,6 @@ int mac802154netdev_register(MACHANDLE mac)
maccb->flink = NULL;
maccb->prio = CONFIG_IEEE802154_NETDEV_RECVRPRIO;
maccb->notify = macnet_notify;
maccb->rxframe = macnet_rxframe;
/* Bind the callback structure */

View File

@ -1,289 +0,0 @@
/****************************************************************************
* wireless/ieee802154/mac802154_notif.c
*
* Copyright (C) 2016 Sebastien Lorquet. All rights reserved.
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Copyright (C) 2017 Verge Inc. All rights reserved.
*
* Author: Sebastien Lorquet <sebastien@lorquet.fr>
* Author: Gregory Nutt <gnutt@nuttx.org>
* Author: Anthony Merlino <anthony@vergeaero.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <string.h>
#include <nuttx/semaphore.h>
#include "mac802154.h"
#include "mac802154_internal.h"
#include <nuttx/wireless/ieee802154/ieee802154_mac.h>
/****************************************************************************
* Public MAC Functions
****************************************************************************/
/****************************************************************************
* Name: mac802154_notif_free
*
* Description:
* When the MAC calls the registered callback, it passes a reference
* to a mac802154_notify_s structure. This structure needs to be freed
* after the callback handler is done using it.
*
****************************************************************************/
void mac802154_notif_free(MACHANDLE mac, FAR struct ieee802154_notif_s *notif)
{
FAR struct ieee802154_privmac_s *priv =
(FAR struct ieee802154_privmac_s *)mac;
/* Lock the MAC */
mac802154_lock(priv, false);
/* Call the internal helper function to free the notification */
mac802154_notif_free_locked(priv, notif);
/* Unlock the MAC */
mac802154_unlock(priv)
}
/****************************************************************************
* Internal MAC Functions
****************************************************************************/
/****************************************************************************
* Name: mac802154_notifpool_init
*
* Description:
* This function initializes the notification structure pool. It allows the
* MAC to pass notifications and for the callee to free them when they are
* done using them, saving copying the data when passing.
*
****************************************************************************/
void mac802154_notifpool_init(FAR struct ieee802154_privmac_s *priv)
{
FAR struct mac802154_notif_s *pool = priv->notif_pool;
int remaining = CONFIG_MAC802154_NNOTIF;
priv->notif_free = NULL;
while (remaining > 0)
{
FAR struct mac802154_notif_s *notif = pool;
/* Add the next meta data structure from the pool to the list of
* general structures.
*/
notif->flink = priv->notif_free;
priv->notif_free = notif;
/* Set up for the next structure from the pool */
pool++;
remaining--;
}
nxsem_init(&priv->notif_sem, 0, CONFIG_MAC802154_NNOTIF);
}
/****************************************************************************
* Name: mac802154_notif_alloc
*
* Description:
* This function allocates a free notification structure from the free list
* to be used for passing to the registered notify callback. The callee software
* is responsible for freeing the notification structure after it is done using
* it via mac802154_notif_free.
*
* Assumptions:
* priv MAC struct is locked when calling.
*
* Notes:
* If any of the semaphore waits inside this function get interrupted, the
* function will release the MAC layer. If this function returns -EINTR, the
* calling code should NOT release the MAC semaphore.
*
****************************************************************************/
int mac802154_notif_alloc(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_notif_s **notif,
bool allow_interrupt)
{
int ret;
FAR struct mac802154_notif_s *privnotif;
/* Try and take a count from the semaphore. If this succeeds, we have
* "reserved" the structure, but still need to unlink it from the free list.
* The MAC is already locked, so there shouldn't be any other conflicting calls
*/
ret = nxsem_trywait(&priv->notif_sem);
if (ret == OK)
{
privnotif = priv->notif_free;
priv->notif_free = privnotif->flink;
privnotif->nclients = 0;
}
else
{
/* Unlock MAC so that other work can be done to free a notification */
mac802154_unlock(priv)
/* Take a count from the notification semaphore, waiting if necessary. We
* only return from here with an error if we are allowing interruptions
* and we received a signal */
ret = mac802154_takesem(&priv->notif_sem, allow_interrupt);
if (ret < 0)
{
/* MAC sem is already released */
return -EINTR;
}
/* If we've taken a count from the semaphore, we have "reserved" the struct
* but now we need to pop it off of the free list. We need to re-lock the
* MAC in order to ensure this happens correctly.
*/
ret = mac802154_lock(priv, allow_interrupt);
if (ret < 0)
{
mac802154_givesem(&priv->notif_sem);
return -EINTR;
}
/* We can now safely unlink the next free structure from the free list */
privnotif = priv->notif_free;
priv->notif_free = privnotif->flink;
privnotif->nclients = 0;
}
*notif = (FAR struct ieee802154_notif_s *)privnotif;
return OK;
}
/****************************************************************************
* Name: mac802154_notif_free_locked
*
* Description:
* When the MAC calls the registered callback, it passes a reference
* to a mac802154_notify_s structure. This structure needs to be freed
* after the callback handler is done using it.
*
* Internal version that already has MAC locked
*
****************************************************************************/
void mac802154_notif_free_locked(FAR struct ieee802154_privmac_s * priv,
FAR struct ieee802154_notif_s *notif)
{
FAR struct mac802154_notif_s *privnotif =
(FAR struct mac802154_notif_s *)notif;
/* We know how many clients have registered for notifications. Each must
* call mac802154_notif_free() before we can release the notification
* resource.
*/
if (privnotif->nclients < 2)
{
/* This is the free from the last notification */
privnotif->flink = priv->notif_free;
priv->notif_free = privnotif;
privnotif->nclients = 0;
mac802154_givesem(&priv->notif_sem);
}
else
{
/* More calls are expected. Decrement the count of expected calls
* and preserve the notification resources.
*/
privnotif->nclients--;
}
}
/****************************************************************************
* Name: mac802154_notify
*
* Description:
* Notify every register MAC client.
*
****************************************************************************/
void mac802154_notify(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_notif_s *notif)
{
FAR struct mac802154_maccb_s *cb;
FAR struct mac802154_notif_s *privnotif = (FAR struct mac802154_notif_s *)notif;
/* Set the notification count so that the notification resources will be
* preserved until the final notification.
*/
privnotif->nclients = priv->nclients;
/* Try to notify every registered MAC client */
for (cb = priv->cb; cb != NULL; cb = cb->flink)
{
/* Does this client want notifications? */
if (cb->notify != NULL)
{
/* Yes.. Notify */
cb->notify(cb, notif);
}
}
}

View File

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

View File

@ -189,9 +189,9 @@ int mac802154_req_poll(MACHANDLE mac, FAR struct ieee802154_poll_req_s *req)
void mac802154_txdone_datareq_poll(FAR struct ieee802154_privmac_s *priv,
FAR struct ieee802154_txdesc_s *txdesc)
{
FAR struct ieee802154_primitive_s * primitive =
(FAR struct ieee802154_primitive_s *)txdesc->conf;
enum ieee802154_status_e status;
FAR struct ieee802154_notif_s *notif =
(FAR struct ieee802154_notif_s *)txdesc->conf;
/* If the data request failed to be sent, notify the next layer
* that the poll has failed.
@ -201,20 +201,20 @@ void mac802154_txdone_datareq_poll(FAR struct ieee802154_privmac_s *priv,
* pending at the coordinator. [1] pg. 43
*/
if (notif->u.dataconf.status != IEEE802154_STATUS_SUCCESS ||
if (txdesc->conf->status != IEEE802154_STATUS_SUCCESS ||
txdesc->framepending == 0)
{
if (notif->u.dataconf.status != IEEE802154_STATUS_SUCCESS)
if (txdesc->conf->status != IEEE802154_STATUS_SUCCESS)
{
status = notif->u.dataconf.status;
status = txdesc->conf->status;
}
else
{
status = IEEE802154_STATUS_NO_DATA;
}
notif->notiftype = IEEE802154_NOTIFY_CONF_POLL;
notif->u.pollconf.status = status;
primitive->type = IEEE802154_PRIMITIVE_CONF_POLL;
txdesc->conf->status = status;
/* We are now done the operation, and can release the command */
@ -222,11 +222,7 @@ void mac802154_txdone_datareq_poll(FAR struct ieee802154_privmac_s *priv,
priv->cmd_desc = NULL;
mac802154_givesem(&priv->opsem);
/* Release the MAC, call the callback, get exclusive access again */
mac802154_unlock(priv)
mac802154_notify(priv, notif);
mac802154_lock(priv, false);
mac802154_notify(priv, primitive);
}
else
{
@ -246,9 +242,9 @@ void mac802154_txdone_datareq_poll(FAR struct ieee802154_privmac_s *priv,
mac802154_timerstart(priv, priv->max_frame_waittime,
mac802154_polltimeout);
/* Deallocate the data conf notification as it is no longer needed. */
/* Deallocate the data conf primitive as it is no longer needed. */
mac802154_notif_free_locked(priv, notif);
ieee802154_primitive_free(primitive);
}
}
@ -264,7 +260,7 @@ void mac802154_txdone_datareq_poll(FAR struct ieee802154_privmac_s *priv,
void mac802154_polltimeout(FAR void *arg)
{
FAR struct ieee802154_privmac_s *priv = (FAR struct ieee802154_privmac_s *)arg;
FAR struct ieee802154_notif_s *notif;
FAR struct ieee802154_primitive_s *primitive;
/* If there is work scheduled for the rxframe_worker, we want to reschedule
* this work, so that we make sure if the frame we were waiting for was just
@ -273,30 +269,23 @@ void mac802154_polltimeout(FAR void *arg)
if (!work_available(&priv->rx_work))
{
work_queue(MAC802154_WORK, &priv->timer_work, mac802154_polltimeout, priv, 0);
work_queue(HPWORK, &priv->timer_work, mac802154_polltimeout, priv, 0);
return;
}
DEBUGASSERT(priv->curr_op == MAC802154_OP_POLL);
/* Allocate a notification struct to pass to the next highest layer.
* Don't allow EINTR to interrupt.
*/
primitive = ieee802154_primitive_allocate();
primitive->type = IEEE802154_PRIMITIVE_CONF_POLL;
primitive->u.pollconf.status = IEEE802154_STATUS_NO_DATA;
mac802154_lock(priv, false);
mac802154_notif_alloc(priv, &notif, false);
/* We are no longer performing the association operation */
priv->curr_op = MAC802154_OP_NONE;
priv->cmd_desc = NULL;
mac802154_givesem(&priv->opsem);
/* Release the MAC */
mac802154_unlock(priv)
notif->notiftype = IEEE802154_NOTIFY_CONF_POLL;
notif->u.pollconf.status = IEEE802154_STATUS_NO_DATA;
mac802154_notify(priv, notif);
mac802154_notify(priv, primitive);
mac802154_unlock(priv);
}

View File

@ -203,39 +203,41 @@ errout:
void mac802154_scanfinish(FAR struct ieee802154_privmac_s *priv,
enum ieee802154_status_e status)
{
FAR struct ieee802154_notif_s * notif;
FAR struct ieee802154_primitive_s * primitive;
FAR struct ieee802154_scan_conf_s *scanconf;
mac802154_lock(priv, false);
mac802154_notif_alloc(priv, &notif, false);
primitive = ieee802154_primitive_allocate();
scanconf = &primitive->u.scanconf;
priv->curr_op = MAC802154_OP_NONE;
mac802154_givesem(&priv->opsem);
notif->notiftype = IEEE802154_NOTIFY_CONF_SCAN;
notif->u.scanconf.type = priv->currscan.type;
notif->u.scanconf.chpage = priv->currscan.chpage;
primitive->type = IEEE802154_PRIMITIVE_CONF_SCAN;
scanconf->type = priv->currscan.type;
scanconf->chpage = priv->currscan.chpage;
/* Copy in the channels that did not get scanned */
if (priv->scanindex != priv->currscan.numchan)
{
notif->u.scanconf.numunscanned = priv->currscan.numchan - priv->scanindex;
memcpy(notif->u.scanconf.unscanned, &priv->currscan.channels[priv->scanindex],
notif->u.scanconf.numunscanned);
scanconf->numunscanned = priv->currscan.numchan - priv->scanindex;
memcpy(scanconf->unscanned, &priv->currscan.channels[priv->scanindex],
scanconf->numunscanned);
}
notif->u.scanconf.numdesc = priv->npandesc;
memcpy(notif->u.scanconf.pandescs, priv->pandescs,
/* Copy the PAN descriptors into the primitive */
memcpy(scanconf->pandescs, priv->pandescs,
sizeof(struct ieee802154_pandesc_s) * priv->npandesc);
notif->u.scanconf.status = status;
scanconf->numdesc = priv->npandesc;
scanconf->status = status;
/* Reset the PAN ID to the setting before the scan started */
mac802154_setpanid(priv, priv->panidbeforescan);
mac802154_unlock(priv)
priv->curr_op = MAC802154_OP_NONE;
mac802154_givesem(&priv->opsem);
mac802154_notify(priv, notif);
mac802154_notify(priv, primitive);
}
/****************************************************************************
@ -256,6 +258,8 @@ static void mac802154_scantimeout(FAR void *arg)
FAR struct ieee802154_privmac_s *priv = (FAR struct ieee802154_privmac_s *)arg;
DEBUGASSERT(priv->curr_op == MAC802154_OP_SCAN);
mac802154_lock(priv, false);
/* If we got here it means we are done scanning that channel */
mac802154_rxdisable(priv);
@ -286,4 +290,5 @@ static void mac802154_scantimeout(FAR void *arg)
mac802154_rxenable(priv);
mac802154_timerstart(priv, priv->scansymdur, mac802154_scantimeout);
mac802154_unlock(priv);
}