diff --git a/configs/clicker2-stm32/src/stm32_appinit.c b/configs/clicker2-stm32/src/stm32_appinit.c index 18840ceeab7..74e4d24c578 100644 --- a/configs/clicker2-stm32/src/stm32_appinit.c +++ b/configs/clicker2-stm32/src/stm32_appinit.c @@ -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 diff --git a/configs/same70-xplained/Kconfig b/configs/same70-xplained/Kconfig index ab5c765cfa9..c2bef1b9513 100644 --- a/configs/same70-xplained/Kconfig +++ b/configs/same70-xplained/Kconfig @@ -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" diff --git a/configs/same70-xplained/src/Makefile b/configs/same70-xplained/src/Makefile index 8d2583374b7..4ff7f4b9eb4 100644 --- a/configs/same70-xplained/src/Makefile +++ b/configs/same70-xplained/src/Makefile @@ -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 diff --git a/configs/same70-xplained/src/sam_spi.c b/configs/same70-xplained/src/sam_spi.c index 81184cf83a8..a9095c462d2 100644 --- a/configs/same70-xplained/src/sam_spi.c +++ b/configs/same70-xplained/src/sam_spi.c @@ -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; } diff --git a/configs/same70-xplained/src/sam_xbee.c b/configs/same70-xplained/src/sam_xbee.c index b8ff4329ac0..11542bf0892 100644 --- a/configs/same70-xplained/src/sam_xbee.c +++ b/configs/same70-xplained/src/sam_xbee.c @@ -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) diff --git a/configs/same70-xplained/src/same70-xplained.h b/configs/same70-xplained/src/same70-xplained.h index 009eef7cb51..37219453a73 100644 --- a/configs/same70-xplained/src/same70-xplained.h +++ b/configs/same70-xplained/src/same70-xplained.h @@ -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 */ diff --git a/drivers/wireless/ieee802154/mrf24j40/mrf24j40_interrupt.c b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_interrupt.c index 6bb1f226fd1..6a63918a6b9 100644 --- a/drivers/wireless/ieee802154/mrf24j40/mrf24j40_interrupt.c +++ b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_interrupt.c @@ -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; diff --git a/drivers/wireless/ieee802154/xbee/Kconfig b/drivers/wireless/ieee802154/xbee/Kconfig index 5b28d40b63b..5edea5770cc 100644 --- a/drivers/wireless/ieee802154/xbee/Kconfig +++ b/drivers/wireless/ieee802154/xbee/Kconfig @@ -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 diff --git a/drivers/wireless/ieee802154/xbee/Make.defs b/drivers/wireless/ieee802154/xbee/Make.defs index 241b6bc3221..d4e7371d1c2 100644 --- a/drivers/wireless/ieee802154/xbee/Make.defs +++ b/drivers/wireless/ieee802154/xbee/Make.defs @@ -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 diff --git a/drivers/wireless/ieee802154/xbee/xbee.c b/drivers/wireless/ieee802154/xbee/xbee.c index 6881f636b00..c0a7fd0ca02 100644 --- a/drivers/wireless/ieee802154/xbee/xbee.c +++ b/drivers/wireless/ieee802154/xbee/xbee.c @@ -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, ¬if, 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, ¬if, 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"); } diff --git a/drivers/wireless/ieee802154/xbee/xbee.h b/drivers/wireless/ieee802154/xbee/xbee.h index 92c73851471..b0627229b2c 100644 --- a/drivers/wireless/ieee802154/xbee/xbee.h +++ b/drivers/wireless/ieee802154/xbee/xbee.h @@ -49,19 +49,17 @@ #include #include +#include #include -#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 diff --git a/drivers/wireless/ieee802154/xbee/xbee_dataind.c b/drivers/wireless/ieee802154/xbee/xbee_dataind.c deleted file mode 100644 index 9bf626dc774..00000000000 --- a/drivers/wireless/ieee802154/xbee/xbee_dataind.c +++ /dev/null @@ -1,203 +0,0 @@ -/**************************************************************************** - * drivers/wireless/ieee802154/xbee/xbee_dataind.c - * - * Copyright (C) 2017 Verge Inc. All rights reserved. - * Author: Anthony Merlino - * - * 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 - -#include -#include -#include -#include -#include - -#include -#include -#include - -#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; -} diff --git a/drivers/wireless/ieee802154/xbee/xbee_dataind.h b/drivers/wireless/ieee802154/xbee/xbee_dataind.h deleted file mode 100644 index 074f646f760..00000000000 --- a/drivers/wireless/ieee802154/xbee/xbee_dataind.h +++ /dev/null @@ -1,77 +0,0 @@ -/**************************************************************************** - * drivers/wireless/ieee802154/xbee/xbee_dataind.h - * - * Copyright (C) 2017 Verge Inc. All rights reserved. - * - * Author: Anthony Merlino - * - * 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 - -#include -#include - -#include - -/**************************************************************************** - * 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 */ \ No newline at end of file diff --git a/drivers/wireless/ieee802154/xbee/xbee_mac.c b/drivers/wireless/ieee802154/xbee/xbee_mac.c index 1d22695a78a..edcf7b1043f 100644 --- a/drivers/wireless/ieee802154/xbee/xbee_mac.c +++ b/drivers/wireless/ieee802154/xbee/xbee_mac.c @@ -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; } diff --git a/drivers/wireless/ieee802154/xbee/xbee_mac.h b/drivers/wireless/ieee802154/xbee/xbee_mac.h index 6da504f1175..6548a50ad51 100644 --- a/drivers/wireless/ieee802154/xbee/xbee_mac.h +++ b/drivers/wireless/ieee802154/xbee/xbee_mac.h @@ -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 */ diff --git a/drivers/wireless/ieee802154/xbee/xbee_netdev.c b/drivers/wireless/ieee802154/xbee/xbee_netdev.c index 779dfcb5fe6..d408d21ec34 100644 --- a/drivers/wireless/ieee802154/xbee/xbee_netdev.c +++ b/drivers/wireless/ieee802154/xbee/xbee_netdev.c @@ -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 */ diff --git a/drivers/wireless/ieee802154/xbee/xbee_notif.c b/drivers/wireless/ieee802154/xbee/xbee_notif.c deleted file mode 100644 index d886d71007b..00000000000 --- a/drivers/wireless/ieee802154/xbee/xbee_notif.c +++ /dev/null @@ -1,284 +0,0 @@ -/**************************************************************************** - * drivers/wireless/ieee802154/xbee/xbee_notif.c - * - * Copyright (C) 2017 Verge Inc. All rights reserved. - * Author: Anthony Merlino - * - * 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 - -#include -#include -#include -#include -#include - -#include "xbee.h" -#include "xbee_mac.h" -#include "xbee_notif.h" - -#include -#include -#include - -/**************************************************************************** - * 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); - } - } -} diff --git a/drivers/wireless/ieee802154/xbee/xbee_notif.h b/drivers/wireless/ieee802154/xbee/xbee_notif.h deleted file mode 100644 index 4a55b03dd08..00000000000 --- a/drivers/wireless/ieee802154/xbee/xbee_notif.h +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** - * drivers/wireless/ieee802154/xbee/xbee_notif.h - * - * Copyright (C) 2017 Verge Inc. All rights reserved. - * - * Author: Anthony Merlino - * - * 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 - -#include -#include - -#include - -/**************************************************************************** - * 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 */ \ No newline at end of file diff --git a/include/nuttx/wireless/ieee802154/ieee802154_device.h b/include/nuttx/wireless/ieee802154/ieee802154_device.h index f09e7075d17..3edf202a020 100644 --- a/include/nuttx/wireless/ieee802154/ieee802154_device.h +++ b/include/nuttx/wireless/ieee802154/ieee802154_device.h @@ -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; }; diff --git a/include/nuttx/wireless/ieee802154/ieee802154_mac.h b/include/nuttx/wireless/ieee802154/ieee802154_mac.h index 87a387c3948..10647638485 100644 --- a/include/nuttx/wireless/ieee802154/ieee802154_mac.h +++ b/include/nuttx/wireless/ieee802154/ieee802154_mac.h @@ -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 diff --git a/net/ipforward/ipfwd_forward.c b/net/ipforward/ipfwd_forward.c index 67d0ce1c263..5ead791b6bf 100644 --- a/net/ipforward/ipfwd_forward.c +++ b/net/ipforward/ipfwd_forward.c @@ -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; diff --git a/net/sixlowpan/sixlowpan_framer.c b/net/sixlowpan/sixlowpan_framer.c index 95d44d85597..666c6a3adf1 100644 --- a/net/sixlowpan/sixlowpan_framer.c +++ b/net/sixlowpan/sixlowpan_framer.c @@ -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; } diff --git a/net/sixlowpan/sixlowpan_icmpv6send.c b/net/sixlowpan/sixlowpan_icmpv6send.c index 2bb7a46165b..1e707c80dc6 100644 --- a/net/sixlowpan/sixlowpan_icmpv6send.c +++ b/net/sixlowpan/sixlowpan_icmpv6send.c @@ -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) { diff --git a/net/sixlowpan/sixlowpan_input.c b/net/sixlowpan/sixlowpan_input.c index 7d3d9aa68ca..614ba468435 100644 --- a/net/sixlowpan/sixlowpan_input.c +++ b/net/sixlowpan/sixlowpan_input.c @@ -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; diff --git a/net/sixlowpan/sixlowpan_internal.h b/net/sixlowpan/sixlowpan_internal.h index b8332b5c1a5..1681d8b2720 100644 --- a/net/sixlowpan/sixlowpan_internal.h +++ b/net/sixlowpan/sixlowpan_internal.h @@ -122,6 +122,7 @@ #define REASS_POOL_PREALLOCATED 0 #define REASS_POOL_DYNAMIC 1 +#define REASS_POOL_RADIO 2 /* Debug ********************************************************************/ diff --git a/net/sixlowpan/sixlowpan_reassbuf.c b/net/sixlowpan/sixlowpan_reassbuf.c index b308a04c8fd..c3ae7eeb804 100644 --- a/net/sixlowpan/sixlowpan_reassbuf.c +++ b/net/sixlowpan/sixlowpan_reassbuf.c @@ -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. + */ } diff --git a/net/sixlowpan/sixlowpan_tcpsend.c b/net/sixlowpan/sixlowpan_tcpsend.c index 4fa8788e2bc..d1ee784cc0d 100644 --- a/net/sixlowpan/sixlowpan_tcpsend.c +++ b/net/sixlowpan/sixlowpan_tcpsend.c @@ -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) { diff --git a/net/sixlowpan/sixlowpan_udpsend.c b/net/sixlowpan/sixlowpan_udpsend.c index be7dfce581b..c9ca4c6161a 100644 --- a/net/sixlowpan/sixlowpan_udpsend.c +++ b/net/sixlowpan/sixlowpan_udpsend.c @@ -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) { diff --git a/wireless/ieee802154/Kconfig b/wireless/ieee802154/Kconfig index cf96b166169..fd3e0cd56e1 100644 --- a/wireless/ieee802154/Kconfig +++ b/wireless/ieee802154/Kconfig @@ -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 diff --git a/wireless/ieee802154/Make.defs b/wireless/ieee802154/Make.defs index 18b52f2cf7e..7de9c47d305 100644 --- a/wireless/ieee802154/Make.defs +++ b/wireless/ieee802154/Make.defs @@ -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 diff --git a/wireless/ieee802154/ieee802154_indalloc.c b/wireless/ieee802154/ieee802154_primitive.c similarity index 54% rename from wireless/ieee802154/ieee802154_indalloc.c rename to wireless/ieee802154/ieee802154_primitive.c index 03dcba86308..35db231fcd4 100644 --- a/wireless/ieee802154/ieee802154_indalloc.c +++ b/wireless/ieee802154/ieee802154_primitive.c @@ -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 @@ -43,9 +43,6 @@ #include #include - -#include - #include #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); } diff --git a/wireless/ieee802154/mac802154.c b/wireless/ieee802154/mac802154.c index c0221c04d83..552af9282f6 100644 --- a/wireless/ieee802154/mac802154.c +++ b/wireless/ieee802154/mac802154.c @@ -57,7 +57,6 @@ #include #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, ¬if, 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 = ¬if->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, ¬if, 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, ¬if, false); - beacon = ¬if->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); diff --git a/wireless/ieee802154/mac802154.h b/wireless/ieee802154/mac802154.h index d1f3a6b63f6..ddd125a6e89 100644 --- a/wireless/ieee802154/mac802154.h +++ b/wireless/ieee802154/mac802154.h @@ -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 } diff --git a/wireless/ieee802154/mac802154_assoc.c b/wireless/ieee802154/mac802154_assoc.c index b72ba08556f..56d32a9a349 100644 --- a/wireless/ieee802154/mac802154_assoc.c +++ b/wireless/ieee802154/mac802154_assoc.c @@ -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, ¬if, 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, ¬if, 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, ¬if, 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); } diff --git a/wireless/ieee802154/mac802154_device.c b/wireless/ieee802154/mac802154_device.c index c5dc2b4e28c..dd3bd769e4a 100644 --- a/wireless/ieee802154/mac802154_device.c +++ b/wireless/ieee802154/mac802154_device.c @@ -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 */ diff --git a/wireless/ieee802154/mac802154_getset.c b/wireless/ieee802154/mac802154_getset.c index d6a9ddf8891..25f9a7068af 100644 --- a/wireless/ieee802154/mac802154_getset.c +++ b/wireless/ieee802154/mac802154_getset.c @@ -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 diff --git a/wireless/ieee802154/mac802154_internal.h b/wireless/ieee802154/mac802154_internal.h index ade1f0e4793..dbe22c0b6fc 100644 --- a/wireless/ieee802154/mac802154_internal.h +++ b/wireless/ieee802154/mac802154_internal.h @@ -59,8 +59,6 @@ #include #include -#include "mac802154_notif.h" - #include #include @@ -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; } diff --git a/wireless/ieee802154/mac802154_netdev.c b/wireless/ieee802154/mac802154_netdev.c index bda34e3d2b7..333bb3674b8 100644 --- a/wireless/ieee802154/mac802154_netdev.c +++ b/wireless/ieee802154/mac802154_netdev.c @@ -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 */ diff --git a/wireless/ieee802154/mac802154_notif.c b/wireless/ieee802154/mac802154_notif.c deleted file mode 100644 index 9cc93a12d3e..00000000000 --- a/wireless/ieee802154/mac802154_notif.c +++ /dev/null @@ -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 - * Author: Gregory Nutt - * Author: Anthony Merlino - * - * 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 - -#include -#include -#include -#include -#include - -#include - -#include "mac802154.h" -#include "mac802154_internal.h" - -#include - -/**************************************************************************** - * 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); - } - } -} diff --git a/wireless/ieee802154/mac802154_notif.h b/wireless/ieee802154/mac802154_notif.h deleted file mode 100644 index 886d786c6b6..00000000000 --- a/wireless/ieee802154/mac802154_notif.h +++ /dev/null @@ -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 - * Author: Gregory Nutt - * - * 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 - -#include -#include - -#include - -/**************************************************************************** - * 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 */ \ No newline at end of file diff --git a/wireless/ieee802154/mac802154_poll.c b/wireless/ieee802154/mac802154_poll.c index c14b409dfdd..7701bd7cd4b 100644 --- a/wireless/ieee802154/mac802154_poll.c +++ b/wireless/ieee802154/mac802154_poll.c @@ -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, ¬if, 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); } \ No newline at end of file diff --git a/wireless/ieee802154/mac802154_scan.c b/wireless/ieee802154/mac802154_scan.c index 0c6140b1926..1c131dc7d67 100644 --- a/wireless/ieee802154/mac802154_scan.c +++ b/wireless/ieee802154/mac802154_scan.c @@ -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, ¬if, 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); }