diff --git a/TODO b/TODO index 1cac77e862..f5975ae90b 100644 --- a/TODO +++ b/TODO @@ -1234,14 +1234,14 @@ o Network (net/, drivers/net) Title: ICMPv6 FOR 6loWPAN Description: The current ICMPv6 and neighbor-related logic only works with - Ethernet MAC. For 6loWPAN, a new more conservative ICMPv6 - definitions is provided by RFC 6775. This RFC needs to be - supported in order to support ping6 on a 6loWPAN network. + Ethernet MAC. For 6loWPAN, a new more conservative IPv6 + neigbor discovery is provided by RFC 6775. This RFC needs to + be supported in order to support ping6 on a 6loWPAN network. If RFC 6775 were implemented, then arbitrary IPv6 addresses, including addresses from DHCPv6 could be used. can - UPDATE: With ICMPv6 neighbor discovery, any IPv6 address may + UPDATE: With IPv6 neighbor discovery, any IPv6 address may be associated with any short or extended address. In fact, that is the whole purpose of the neighbor discover logic: It plays the same role as ARP in IPv4; it ultimately just manages @@ -1256,15 +1256,18 @@ o Network (net/, drivers/net) Most of the 6loWPAN compression algorithms exploit this to compress the IPv6 address to nothing but a bit indicating that the IP address derives from the node address. So I - think ICMPv6 is useless in the current implementation. + think IPv6 neighbor discover is useless in the current + implementation. - If we want to use ICMPv6, we could dispense with the all MAC - based addressing. But if we want to retain the more compact - MAC-based addressing, then we don't need ICMPv6. + If we want to use IPv6 neighbor discovery, we could dispense + with the all MAC based addressing. But if we want to retain + the more compact MAC-based addressing, then we don't need + IPv6 neighbor discovery. So, the full neighbor discovery logic is not currently useful, but it would still be nice to have enough in place to support - ping6. + ping6. Full neighbor support would probably be necessary if we + wanted to route 6LoWPAN frames outside of the WPAN. Status: Open Priority: Low for now. I don't plan on implementing this. It would diff --git a/configs/clicker2-stm32/README.txt b/configs/clicker2-stm32/README.txt index 274b9a2b0c..a2287418b3 100644 --- a/configs/clicker2-stm32/README.txt +++ b/configs/clicker2-stm32/README.txt @@ -365,7 +365,7 @@ Configurations nsh> i8 /dev/ieee0 startpan nsh> i8 acceptassoc - 2. Assocate and endpoint device with the WPAN. On the endpoint + 2. Assocate an endpoint device with the WPAN. On the endpoint device: nsh> i8 /dev/ieee0 assoc @@ -432,7 +432,7 @@ Configurations 5. Configuration instructions: Basic PAN configuration is the same as for the ieee802154-mac configuration with the exception that after the PAN has been configured with the i8sak utility, you must - explicity bring the network up: + explicity bring the network up on each node: nsh> ifup wpan0 diff --git a/configs/clicker2-stm32/mrf24j40-6lowpan/defconfig b/configs/clicker2-stm32/mrf24j40-6lowpan/defconfig index b202b30aa8..a8ba381b69 100644 --- a/configs/clicker2-stm32/mrf24j40-6lowpan/defconfig +++ b/configs/clicker2-stm32/mrf24j40-6lowpan/defconfig @@ -1137,12 +1137,14 @@ CONFIG_IOB_THROTTLE=8 CONFIG_WIRELESS=y CONFIG_WIRELESS_IEEE802154=y CONFIG_IEEE802154_DEFAULT_EADDR=0x00fade00deadbeef -CONFIG_IEEE802154_MAC_DEV=y CONFIG_MAC802154_HPWORK=y CONFIG_IEEE802154_NTXDESC=3 CONFIG_IEEE802154_IND_PREALLOC=20 CONFIG_IEEE802154_IND_IRQRESERVE=10 +CONFIG_IEEE802154_MACDEV=y +CONFIG_IEEE802154_MACDEV_RECVRPRIO=0 CONFIG_IEEE802154_NETDEV=y +CONFIG_IEEE802154_NETDEV_RECVRPRIO=1 CONFIG_IEEE802154_NETDEV_HPWORK=y # CONFIG_IEEE802154_LOOPBACK is not set @@ -1448,7 +1450,7 @@ CONFIG_NSH_DISABLE_GET=y # CONFIG_NSH_DISABLE_HELP is not set # CONFIG_NSH_DISABLE_HEXDUMP is not set # CONFIG_NSH_DISABLE_IFCONFIG is not set -CONFIG_NSH_DISABLE_IFUPDOWN=y +# CONFIG_NSH_DISABLE_IFUPDOWN is not set # CONFIG_NSH_DISABLE_KILL is not set # CONFIG_NSH_DISABLE_LOSETUP is not set CONFIG_NSH_DISABLE_LOSMART=y diff --git a/configs/clicker2-stm32/mrf24j40-mac/defconfig b/configs/clicker2-stm32/mrf24j40-mac/defconfig index 8ecd37bd89..d6ba224b4e 100644 --- a/configs/clicker2-stm32/mrf24j40-mac/defconfig +++ b/configs/clicker2-stm32/mrf24j40-mac/defconfig @@ -393,6 +393,7 @@ CONFIG_STM32_HAVE_I2C2=y CONFIG_STM32_HAVE_I2C3=y CONFIG_STM32_HAVE_SPI2=y CONFIG_STM32_HAVE_SPI3=y +CONFIG_STM32_HAVE_I2S3=y # CONFIG_STM32_HAVE_SPI4 is not set # CONFIG_STM32_HAVE_SPI5 is not set # CONFIG_STM32_HAVE_SPI6 is not set @@ -431,6 +432,7 @@ CONFIG_STM32_PWR=y # CONFIG_STM32_SPI1 is not set # CONFIG_STM32_SPI2 is not set CONFIG_STM32_SPI3=y +# CONFIG_STM32_I2S3 is not set CONFIG_STM32_SYSCFG=y # CONFIG_STM32_TIM1 is not set # CONFIG_STM32_TIM2 is not set @@ -968,6 +970,7 @@ CONFIG_MM_IOB=y CONFIG_IOB_NBUFFERS=8 CONFIG_IOB_BUFSIZE=196 CONFIG_IOB_NCHAINS=0 +CONFIG_IOB_THROTTLE=0 # # Audio Support @@ -980,11 +983,12 @@ CONFIG_IOB_NCHAINS=0 CONFIG_WIRELESS=y CONFIG_WIRELESS_IEEE802154=y CONFIG_IEEE802154_DEFAULT_EADDR=0x00fade00deadbeef -CONFIG_IEEE802154_MAC_DEV=y CONFIG_MAC802154_HPWORK=y CONFIG_IEEE802154_NTXDESC=3 CONFIG_IEEE802154_IND_PREALLOC=20 CONFIG_IEEE802154_IND_IRQRESERVE=10 +CONFIG_IEEE802154_MACDEV=y +CONFIG_IEEE802154_MACDEV_RECVRPRIO=0 # # Binary Loader @@ -1162,10 +1166,10 @@ CONFIG_BUILTIN_PROXY_STACKSIZE=1024 CONFIG_EXAMPLES_NSH=y CONFIG_EXAMPLES_NSH_CXXINITIALIZE=y # CONFIG_EXAMPLES_NULL is not set +# CONFIG_EXAMPLES_NX is not set # CONFIG_EXAMPLES_NXFFS is not set # CONFIG_EXAMPLES_NXHELLO is not set # CONFIG_EXAMPLES_NXIMAGE is not set -# CONFIG_EXAMPLES_NX is not set # CONFIG_EXAMPLES_NXLINES is not set # CONFIG_EXAMPLES_NXTERM is not set # CONFIG_EXAMPLES_NXTEXT is not set diff --git a/configs/clicker2-stm32/src/stm32_mrf24j40.c b/configs/clicker2-stm32/src/stm32_mrf24j40.c index 1d5733edde..6ff5ad7bae 100644 --- a/configs/clicker2-stm32/src/stm32_mrf24j40.c +++ b/configs/clicker2-stm32/src/stm32_mrf24j40.c @@ -270,7 +270,7 @@ static int stm32_mrf24j40_devsetup(FAR struct stm32_priv_s *priv) } #endif -#ifdef CONFIG_IEEE802154_MAC_DEV +#ifdef CONFIG_IEEE802154_MACDEV /* If want to call these APIs from userspace, you have to wrap the MAC * interface in a character device viamac802154dev_register(). */ diff --git a/configs/sim/sixlowpan/defconfig b/configs/sim/sixlowpan/defconfig index 5613379e8e..3c2ac60369 100644 --- a/configs/sim/sixlowpan/defconfig +++ b/configs/sim/sixlowpan/defconfig @@ -710,11 +710,11 @@ CONFIG_IOB_THROTTLE=8 CONFIG_WIRELESS=y CONFIG_WIRELESS_IEEE802154=y CONFIG_IEEE802154_DEFAULT_EADDR=0x00fade00deadbeef -# CONFIG_IEEE802154_MAC_DEV is not set CONFIG_MAC802154_HPWORK=y CONFIG_IEEE802154_NTXDESC=3 CONFIG_IEEE802154_IND_PREALLOC=20 CONFIG_IEEE802154_IND_IRQRESERVE=10 +# CONFIG_IEEE802154_MACDEV is not set # CONFIG_IEEE802154_NETDEV is not set CONFIG_IEEE802154_LOOPBACK=y CONFIG_IEEE802154_LOOPBACK_HPWORK=y diff --git a/net/sixlowpan/README.txt b/net/sixlowpan/README.txt index 9eb848144e..4031af925d 100644 --- a/net/sixlowpan/README.txt +++ b/net/sixlowpan/README.txt @@ -1,4 +1,35 @@ -Optimal 6loWPAN Configuration +6LoWPAN Addressing +------------------ + +The current 6LoWPAN implementation uses only link local, MAC-based +addressing addressing (as discussed in more detail below). Thus if you know +the node addressing, then you know the IPv6 address (and vice-versa) + +IPv6 Neighbor Discovery is not supported. The current ICMPv6 and neighbor- +related logic only works with Ethernet MAC. For 6LoWPAN, a +new more conservative IPv6 neigbor discovery is provided by RFC 6775 which +is not currently suppored. With IPv6 neighbor discovery, any IPv6 address +may be associated with any short or extended address. In fact, that is the +whole purpose of the neighbor discover logic: It plays the same role as ARP +in IPv4; it ultimately just manages a neighbor table that, like the arp +table, provides the mapping between IP addresses and node addresses. + +The NuttX, Contiki-based 6LoWPAN implementation circumvents the need for +the neighbor discovery logic by using only MAC-based addressing, i.e., the +lower two or eight bytes of the IP address are the node address. + +Most of the 6LoWPAN compression algorithms exploit this kind of addressing +to compress the IPv6 address to nothing but a single bit indicating that the +IP address derives from the node address. In this use case, IPv6 neighbor +discover is not useful: If we want to use IPv6 neighbor discovery, we could +dispense with the all MAC based addressing. But if we want to retain the +more compact MAC-based addressing, then we don't need IPv6 neighbor discovery. + +However, it would still be nice to have enough in place to support ping6. +Full neighbor support would be necessary if we wanted to route 6LoWPAN frames +outside of the WPAN. + +Optimal 6LoWPAN Configuration ----------------------------- 1. Link local IP addresses: diff --git a/sched/sched/sched_addprioritized.c b/sched/sched/sched_addprioritized.c index 349889f488..1a990bd04d 100644 --- a/sched/sched/sched_addprioritized.c +++ b/sched/sched/sched_addprioritized.c @@ -88,12 +88,12 @@ bool sched_addprioritized(FAR struct tcb_s *tcb, DSEG dq_queue_t *list) ASSERT(sched_priority >= SCHED_PRIORITY_MIN); /* Search the list to find the location to insert the new Tcb. - * Each is list is maintained in ascending sched_priority order. + * Each is list is maintained in descending sched_priority order. */ for (next = (FAR struct tcb_s *)list->head; (next && sched_priority <= next->sched_priority); - next = next->flink); + next = next->flink); /* Add the tcb to the spot found in the list. Check if the tcb * goes at the end of the list. NOTE: This could only happen if list diff --git a/wireless/ieee802154/Kconfig b/wireless/ieee802154/Kconfig index 7ffe2654f4..a471e4804e 100644 --- a/wireless/ieee802154/Kconfig +++ b/wireless/ieee802154/Kconfig @@ -21,14 +21,6 @@ config IEEE802154_DEFAULT_EADDR ---help--- Set the default extended address to be used by MAC networks on init -config IEEE802154_MAC_DEV - bool "Character driver for IEEE 802.15.4 MAC layer" - default n - depends on WIRELESS_IEEE802154 - ---help--- - Enable the device driver to expose the IEEE 802.15.4 MAC layer - access to user space as IOCTLs - choice prompt "IEEE 802.15.4 work queue" default MAC802154_LPWORK if SCHED_LPWORK @@ -83,6 +75,36 @@ 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. + +config IEEE802154_MACDEV + bool "Character driver for IEEE 802.15.4 MAC layer" + default n + depends on WIRELESS_IEEE802154 + ---help--- + Enable the device driver to expose the IEEE 802.15.4 MAC layer + access to user space as IOCTLs + +if IEEE802154_MACDEV + +config IEEE802154_MACDEV_RECVRPRIO + int "Priority of frame receiver registerd with the MAC layer" + default 0 + ---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). + +endif # IEEE802154_MACDEV config IEEE802154_NETDEV bool "IEEE802154 6loWPAN Network Device" @@ -95,6 +117,24 @@ config IEEE802154_NETDEV if IEEE802154_NETDEV +config IEEE802154_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 IEEE802154_NETDEV_LPWORK if SCHED_LPWORK diff --git a/wireless/ieee802154/Make.defs b/wireless/ieee802154/Make.defs index da1b1bc05e..26705a51a7 100644 --- a/wireless/ieee802154/Make.defs +++ b/wireless/ieee802154/Make.defs @@ -46,7 +46,7 @@ CSRCS += mac802154_sync.c # Include wireless devices build support -ifeq ($(CONFIG_IEEE802154_MAC_DEV),y) +ifeq ($(CONFIG_IEEE802154_MACDEV),y) CSRCS += mac802154_device.c endif diff --git a/wireless/ieee802154/mac802154.c b/wireless/ieee802154/mac802154.c index f9322c36df..2c60866e71 100644 --- a/wireless/ieee802154/mac802154.c +++ b/wireless/ieee802154/mac802154.c @@ -628,11 +628,13 @@ static void mac802154_txdone_worker(FAR void *arg) notif->notiftype = IEEE802154_NOTIFY_CONF_DATA; /* Release the MAC, call the callback, get exclusive access again */ + mac802154_givesem(&priv->exclsem); - priv->cb->notify(priv->cb, notif); + mac802154_notify(priv, notif); mac802154_takesem(&priv->exclsem, false); } break; + case IEEE802154_FRAME_COMMAND: { switch (priv->curr_cmd) @@ -640,10 +642,13 @@ static void mac802154_txdone_worker(FAR void *arg) case IEEE802154_CMD_ASSOC_REQ: mac802154_txdone_assocreq(priv, txdesc); break; + case IEEE802154_CMD_ASSOC_RESP: break; + case IEEE802154_CMD_DISASSOC_NOT: break; + case IEEE802154_CMD_DATA_REQ: /* Data requests can be sent for 3 different reasons. * @@ -663,23 +668,31 @@ static void mac802154_txdone_worker(FAR void *arg) case MAC802154_OP_ASSOC: mac802154_txdone_datareq_assoc(priv, txdesc); break; + case MAC802154_OP_POLL: mac802154_txdone_datareq_poll(priv, txdesc); break; + default: break; } break; + case IEEE802154_CMD_PANID_CONF_NOT: break; + case IEEE802154_CMD_ORPHAN_NOT: break; + case IEEE802154_CMD_BEACON_REQ: break; + case IEEE802154_CMD_COORD_REALIGN: break; + case IEEE802154_CMD_GTS_REQ: break; + default: /* We can deallocate the data conf notification as it is no * longer needed. We can't use the public function here @@ -688,10 +701,12 @@ static void mac802154_txdone_worker(FAR void *arg) privnotif->flink = priv->notif_free; priv->notif_free = privnotif; + priv->nnotif = 0; break; } } break; + default: { /* We can deallocate the data conf notification as it is no longer @@ -907,22 +922,30 @@ static void mac802154_rxframe_worker(FAR void *arg) case IEEE802154_CMD_ASSOC_REQ: mac802154_rx_assocreq(priv, ind); break; + case IEEE802154_CMD_ASSOC_RESP: mac802154_rx_assocresp(priv, ind); break; + case IEEE802154_CMD_DISASSOC_NOT: break; + case IEEE802154_CMD_DATA_REQ: mac802154_rx_datareq(priv, ind); break; + case IEEE802154_CMD_PANID_CONF_NOT: break; + case IEEE802154_CMD_ORPHAN_NOT: break; + case IEEE802154_CMD_BEACON_REQ: break; + case IEEE802154_CMD_COORD_REALIGN: break; + case IEEE802154_CMD_GTS_REQ: break; } @@ -1096,8 +1119,7 @@ static void mac802154_rx_dataframe(FAR struct ieee802154_privmac_s *priv, /* Release the MAC */ mac802154_givesem(&priv->exclsem); - - priv->cb->notify(priv->cb, notif); + mac802154_notify(priv, notif); /* If there was data, pass it along */ @@ -1108,26 +1130,48 @@ static void mac802154_rx_dataframe(FAR struct ieee802154_privmac_s *priv, } else { + FAR struct mac802154_maccb_s *cb; + notify_with_lock: mac802154_givesem(&priv->exclsem); notify_without_lock: - /* If there is a registered MCPS callback receiver registered, - * send the frame, otherwise, throw it out. + /* 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. */ - if (priv->cb->rxframe != NULL) + for (cb = priv->cb; cb != NULL; cb = cb->flink) { - priv->cb->rxframe(priv->cb, ind); - } - else - { - /* Free the data indication struct from the pool */ + int ret; - ieee802154_ind_free(ind); + /* 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); } } diff --git a/wireless/ieee802154/mac802154.h b/wireless/ieee802154/mac802154.h index 40d00c9d69..90ff021952 100644 --- a/wireless/ieee802154/mac802154.h +++ b/wireless/ieee802154/mac802154.h @@ -58,18 +58,22 @@ * Public Data Types ****************************************************************************/ -/* Callback operations to notify the next highest layer of various asynchronous - * events, usually triggered by some previous request or response invoked by the - * upper layer. +/* Callback operations to notify the next highest layer of various + * asynchronous events, usually triggered by some previous request or + * response invoked by the upper layer. */ struct mac802154_maccb_s { - CODE void (*notify)(FAR const struct mac802154_maccb_s *maccb, - FAR struct ieee802154_notif_s *notif); + FAR struct mac802154_maccb_s *flink; /* Implements a singly linked list */ + uint8_t prio; /* RX frame callback priority */ - CODE void (*rxframe)(FAR const struct mac802154_maccb_s *maccb, - FAR struct ieee802154_data_ind_s *ind); + /* Callback methods */ + + 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); }; /**************************************************************************** @@ -93,7 +97,7 @@ struct iob_s; /* Forward reference */ * ****************************************************************************/ -int mac802154_bind(MACHANDLE mac, FAR const struct mac802154_maccb_s *cb); +int mac802154_bind(MACHANDLE mac, FAR struct mac802154_maccb_s *cb); /**************************************************************************** * Name: mac802154_ioctl diff --git a/wireless/ieee802154/mac802154_assoc.c b/wireless/ieee802154/mac802154_assoc.c index d9ab6cb19d..c5ef212da0 100644 --- a/wireless/ieee802154/mac802154_assoc.c +++ b/wireless/ieee802154/mac802154_assoc.c @@ -480,7 +480,7 @@ void mac802154_txdone_assocreq(FAR struct ieee802154_privmac_s *priv, /* Release the MAC, call the callback, get exclusive access again */ mac802154_givesem(&priv->exclsem); - priv->cb->notify(priv->cb, notif); + mac802154_notify(priv, notif); mac802154_takesem(&priv->exclsem, false); } else @@ -612,7 +612,7 @@ void mac802154_txdone_datareq_assoc(FAR struct ieee802154_privmac_s *priv, /* Release the MAC, call the callback, get exclusive access again */ mac802154_givesem(&priv->exclsem); - priv->cb->notify(priv->cb, notif); + mac802154_notify(priv, notif); mac802154_takesem(&priv->exclsem, false); } else @@ -708,8 +708,7 @@ void mac802154_rx_assocreq(FAR struct ieee802154_privmac_s *priv, /* Notify the next highest layer of the association status */ - priv->cb->notify(priv->cb, notif); - + mac802154_notify(priv, notif); return; errout_with_sem: @@ -804,7 +803,7 @@ void mac802154_rx_assocresp(FAR struct ieee802154_privmac_s *priv, /* Notify the next highest layer of the association status */ - priv->cb->notify(priv->cb, notif); + mac802154_notify(priv, notif); } /**************************************************************************** @@ -853,5 +852,5 @@ static void mac802154_timeout_assoc(FAR struct ieee802154_privmac_s *priv) notif->u.assocconf.status = IEEE802154_STATUS_NO_DATA; notif->u.assocconf.saddr = IEEE802154_SADDR_UNSPEC; - priv->cb->notify(priv->cb, notif); + mac802154_notify(priv, notif); } diff --git a/wireless/ieee802154/mac802154_bind.c b/wireless/ieee802154/mac802154_bind.c index c173aef477..091d83814a 100644 --- a/wireless/ieee802154/mac802154_bind.c +++ b/wireless/ieee802154/mac802154_bind.c @@ -69,12 +69,48 @@ * ****************************************************************************/ -int mac802154_bind(MACHANDLE mac, FAR const struct mac802154_maccb_s *cb) +int mac802154_bind(MACHANDLE mac, FAR struct mac802154_maccb_s *cb) { FAR struct ieee802154_privmac_s *priv = (FAR struct ieee802154_privmac_s *)mac; + FAR struct mac802154_maccb_s *next; + FAR struct mac802154_maccb_s *prev; + + /* Add the MAC client callback structure to the list of MAC callbacks in + * priority order. + * + * Search the list to find the location to insert the new instance. + * The list is maintained in descending priority order. + */ + + for (prev = NULL, next = priv->cb; + (next != NULL && cb->prio <= next->prio); + prev = next, next = next->flink); + + /* Add the instance to the spot found in the list. Check if the instance + * goes at the head of the list. + */ + + if (prev == NULL) + { + cb->flink = priv->cb; /* May be NULL */ + priv->cb = cb; + } + + /* No.. the instance goes between prev and next */ + + else + { + cb->flink = next; /* May be NULL */ + prev->flink = cb; + } + + /* Keep track of the number of clients requesting notification */ + + if (cb->notify != NULL) + { + priv->nclients++; + } - priv->cb = cb; return OK; } - diff --git a/wireless/ieee802154/mac802154_device.c b/wireless/ieee802154/mac802154_device.c index b03ce94ba8..1d634f9018 100644 --- a/wireless/ieee802154/mac802154_device.c +++ b/wireless/ieee802154/mac802154_device.c @@ -141,10 +141,9 @@ static inline void mac802154dev_pushevent(FAR struct mac802154_chardevice_s *dev static inline FAR struct ieee802154_notif_s * mac802154dev_popevent(FAR struct mac802154_chardevice_s *dev); -static void mac802154dev_notify(FAR const struct mac802154_maccb_s *maccb, +static void mac802154dev_notify(FAR struct mac802154_maccb_s *maccb, FAR struct ieee802154_notif_s *notif); - -static void mac802154dev_rxframe(FAR const struct mac802154_maccb_s *maccb, +static int mac802154dev_rxframe(FAR struct mac802154_maccb_s *maccb, FAR struct ieee802154_data_ind_s *ind); static int mac802154dev_open(FAR struct file *filep); @@ -762,7 +761,7 @@ static int mac802154dev_ioctl(FAR struct file *filep, int cmd, return ret; } -static void mac802154dev_notify(FAR const struct mac802154_maccb_s *maccb, +static void mac802154dev_notify(FAR struct mac802154_maccb_s *maccb, FAR struct ieee802154_notif_s *notif) { FAR struct mac802154dev_callback_s *cb = @@ -826,8 +825,20 @@ static void mac802154dev_notify(FAR const struct mac802154_maccb_s *maccb, mac802154dev_givesem(&dev->md_exclsem); } -static void mac802154dev_rxframe(FAR const struct mac802154_maccb_s *maccb, - FAR struct ieee802154_data_ind_s *ind) +/**************************************************************************** + * Name: mac802154dev_rxframe + * + * Description: + * Handle received frames forward by the IEEE 802.15.4 MAC. + * + * Returned Value: + * any failure. On success, the ind and its contained iob will be freed. + * The ind will be intact if this function returns a failure. + * + ****************************************************************************/ + +static int mac802154dev_rxframe(FAR struct mac802154_maccb_s *maccb, + FAR struct ieee802154_data_ind_s *ind) { FAR struct mac802154dev_callback_s *cb = (FAR struct mac802154dev_callback_s *)maccb; @@ -858,6 +869,7 @@ static void mac802154dev_rxframe(FAR const struct mac802154_maccb_s *maccb, /* Release the driver */ mac802154dev_givesem(&dev->md_exclsem); + return OK; } /**************************************************************************** @@ -923,6 +935,8 @@ int mac802154dev_register(MACHANDLE mac, int minor) dev->md_cb.mc_priv = dev; maccb = &dev->md_cb.mc_cb; + maccb->flink = NULL; + maccb->prio = CONFIG_IEEE802154_MACDEV_RECVRPRIO; maccb->notify = mac802154dev_notify; maccb->rxframe = mac802154dev_rxframe; diff --git a/wireless/ieee802154/mac802154_internal.h b/wireless/ieee802154/mac802154_internal.h index 51c4a1c706..798f48a927 100644 --- a/wireless/ieee802154/mac802154_internal.h +++ b/wireless/ieee802154/mac802154_internal.h @@ -147,10 +147,12 @@ typedef void (*mac802154_worker_t)(FAR struct ieee802154_privmac_s *priv); struct ieee802154_privmac_s { FAR struct ieee802154_radio_s *radio; /* Contained IEEE802.15.4 radio dev */ - FAR const struct mac802154_maccb_s *cb; /* Contained MAC callbacks */ + FAR struct mac802154_maccb_s *cb; /* Head of a list of MAC callbacks */ FAR struct mac802154_radiocb_s radiocb; /* Interface to bind to radio */ - sem_t exclsem; /* Support exclusive access */ + sem_t exclsem; /* Support exclusive access */ + uint8_t nclients; /* Number of notification clients */ + uint8_t nnotif; /* Number of remaining notifications */ /* Only support a single command at any given time. As of now I see no * condition where you need to have more than one command frame simultaneously diff --git a/wireless/ieee802154/mac802154_loopback.c b/wireless/ieee802154/mac802154_loopback.c index 33bbb3f614..e4e54c9b60 100644 --- a/wireless/ieee802154/mac802154_loopback.c +++ b/wireless/ieee802154/mac802154_loopback.c @@ -128,9 +128,10 @@ static uint16_t g_panid = 0xcafe; * Private Function Prototypes ****************************************************************************/ -/* IP address conversion */ +/* Utility functions */ static void lo_addr2ip(FAR struct net_driver_s *dev); +static inline void lo_netmask(FAR struct net_driver_s *dev); /* Polling logic */ @@ -170,7 +171,7 @@ static int lo_req_data(FAR struct ieee802154_driver_s *netdev, * * Description: * Create a MAC-based IP address from the IEEE 802.15.14 short or extended - * address of the MAC. + * address assigned to the node. * * 128 112 96 80 64 48 32 16 * ---- ---- ---- ---- ---- ---- ---- ---- @@ -189,8 +190,8 @@ static void lo_addr2ip(FAR struct net_driver_s *dev) dev->d_ipv6addr[4] = (uint16_t)g_eaddr[0] << 8 | (uint16_t)g_eaddr[1]; dev->d_ipv6addr[5] = (uint16_t)g_eaddr[2] << 8 | (uint16_t)g_eaddr[3]; dev->d_ipv6addr[6] = (uint16_t)g_eaddr[4] << 8 | (uint16_t)g_eaddr[5]; - dev->d_ipv6addr[6] = (uint16_t)g_eaddr[6] << 8 | (uint16_t)g_eaddr[6]; - dev->d_ipv6addr[6] ^= 0x200; + dev->d_ipv6addr[7] = (uint16_t)g_eaddr[6] << 8 | (uint16_t)g_eaddr[6]; + dev->d_ipv6addr[4] ^= 0x200; } #else static void lo_addr2ip(FAR struct net_driver_s *dev) @@ -201,12 +202,45 @@ static void lo_addr2ip(FAR struct net_driver_s *dev) dev->d_ipv6addr[3] = 0; dev->d_ipv6addr[4] = 0; dev->d_ipv6addr[5] = HTONS(0x00ff); - dev->d_ipv6addr[0] = HTONS(0xfe00); - dev->d_ipv6addr[0] = htons(g_saddr) ^ 0x0200; - dev->d_ipv6addr[6] ^= 0x200; + dev->d_ipv6addr[6] = HTONS(0xfe00); + dev->d_ipv6addr[7] = htons(g_saddr); + dev->d_ipv6addr[7] ^= 0x200; } #endif +/**************************************************************************** + * Name: lo_netmask + * + * Description: + * Create a netmask of a MAC-based IP address which may be based on either + * the IEEE 802.15.14 short or extended address of the MAC. + * + * 128 112 96 80 64 48 32 16 + * ---- ---- ---- ---- ---- ---- ---- ---- + * fe80 0000 0000 0000 0000 00ff fe00 xxxx 2-byte short address IEEE 48-bit MAC + * fe80 0000 0000 0000 xxxx xxxx xxxx xxxx 8-byte extended address IEEE EUI-64 + * + ****************************************************************************/ + +static inline void lo_netmask(FAR struct net_driver_s *dev) +{ + dev->d_ipv6netmask[0] = 0xffff; + dev->d_ipv6netmask[1] = 0xffff; + dev->d_ipv6netmask[2] = 0xffff; + dev->d_ipv6netmask[3] = 0xffff; +#ifdef CONFIG_NET_6LOWPAN_EXTENDEDADDR + dev->d_ipv6netmask[4] = 0; + dev->d_ipv6netmask[5] = 0; + dev->d_ipv6netmask[6] = 0; + dev->d_ipv6netmask[7] = 0; +#else + dev->d_ipv6netmask[4] = 0xffff; + dev->d_ipv6netmask[5] = 0xffff; + dev->d_ipv6netmask[6] = 0xffff; + dev->d_ipv6netmask[7] = 0; +#endif +} + /**************************************************************************** * Name: lo_loopback * @@ -861,8 +895,9 @@ int ieee8021514_loopback(void) dev->d_buf = g_iobuffer; /* Attach the IO buffer */ dev->d_private = (FAR void *)priv; /* Used to recover private state from dev */ - /* Advertise our MAC-based IP address */ + /* Set the network mask and advertise our MAC-based IP address */ + lo_netmask(dev); lo_addr2ip(dev); /* Initialize the Network frame-related callbacks */ diff --git a/wireless/ieee802154/mac802154_netdev.c b/wireless/ieee802154/mac802154_netdev.c index 7fcd25e3af..71914e3ead 100644 --- a/wireless/ieee802154/mac802154_netdev.c +++ b/wireless/ieee802154/mac802154_netdev.c @@ -109,7 +109,7 @@ struct macnet_callback_s { /* This holds the information visible to the MAC layer */ - struct mac802154_maccb_s mc_cb; /* Interface understood by the MAC layer */ + struct mac802154_maccb_s mc_cb; /* Interface understood by the MAC layer */ FAR struct macnet_driver_s *mc_priv; /* Our priv data */ }; @@ -136,11 +136,16 @@ struct macnet_driver_s * Private Function Prototypes ****************************************************************************/ +/* Utility functions ********************************************************/ + +static int macnet_advertise(FAR struct net_driver_s *dev); +static inline void macnet_netmask(FAR struct net_driver_s *dev); + /* IEE802.15.4 MAC callback functions ***************************************/ -static void macnet_notify(FAR const struct mac802154_maccb_s *maccb, +static void macnet_notify(FAR struct mac802154_maccb_s *maccb, FAR struct ieee802154_notif_s *notif); -static void macnet_rxframe(FAR const struct mac802154_maccb_s *maccb, +static int macnet_rxframe(FAR struct mac802154_maccb_s *maccb, FAR struct ieee802154_data_ind_s *ind); /* Asynchronous confirmations to requests */ @@ -162,7 +167,7 @@ static void macnet_conf_start(FAR struct macnet_driver_s *priv, static void macnet_conf_poll(FAR struct macnet_driver_s *priv, FAR struct ieee802154_poll_conf_s *conf); - /* Asynchronous event indications, replied to synchronously with responses */ +/* Asynchronous event indications, replied to synchronously with responses */ static void macnet_ind_associate(FAR struct macnet_driver_s *priv, FAR struct ieee802154_assoc_ind_s *conf); @@ -216,6 +221,133 @@ static int macnet_req_data(FAR struct ieee802154_driver_s *netdev, * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: macnet_advertise + * + * Description: + * Advertise the MAC and IPv6 address for this node. + * + * Creates a MAC-based IP address from the IEEE 802.15.14 short or extended + * address assigned to the node. + * + * 128 112 96 80 64 48 32 16 + * ---- ---- ---- ---- ---- ---- ---- ---- + * fe80 0000 0000 0000 0000 00ff fe00 xxxx 2-byte short address IEEE 48-bit MAC + * fe80 0000 0000 0000 xxxx xxxx xxxx xxxx 8-byte extended address IEEE EUI-64 + * + ****************************************************************************/ + +static int macnet_advertise(FAR struct net_driver_s *dev) +{ + struct ieee802154_netmac_s arg; + int ret; + +#ifdef CONFIG_NET_6LOWPAN_EXTENDEDADDR + uint8_t *eaddr; + + /* Get the eaddr from the MAC */ + + memcpy(arg.ifr_name, dev->d_ifname, IFNAMSIZ); + arg.u.getreq.attr = IEEE802154_ATTR_MAC_EXTENDED_ADDR; + ret = dev->d_ioctl(dev, MAC802154IOC_MLME_GET_REQUEST, + (unsigned long)((uintptr_t)&arg)); + if (ret < 0) + { + wlerr("ERROR: MAC802154IOC_MLME_GET_REQUEST failed: %d\n", ret); + return ret; + } + else + { + /* Set the IP address based on the eaddr */ + + eaddr = arg.u.getreq.attrval.mac.eaddr; + memcpy(dev->d_mac.ieee802154.u8, eaddr, 8); + + dev->d_ipv6addr[0] = HTONS(0xfe80); + dev->d_ipv6addr[1] = 0; + dev->d_ipv6addr[2] = 0; + dev->d_ipv6addr[3] = 0; + dev->d_ipv6addr[4] = (uint16_t)eaddr[0] << 8 | (uint16_t)eaddr[1]; + dev->d_ipv6addr[5] = (uint16_t)eaddr[2] << 8 | (uint16_t)eaddr[3]; + dev->d_ipv6addr[6] = (uint16_t)eaddr[4] << 8 | (uint16_t)eaddr[5]; + dev->d_ipv6addr[7] = (uint16_t)eaddr[6] << 8 | (uint16_t)eaddr[6]; + dev->d_ipv6addr[4] ^= 0x200; + return OK; + } + +#else + /* Get the saddr from the MAC */ + + memcpy(arg.ifr_name, dev->d_ifname, IFNAMSIZ); + arg.u.getreq.attr = IEEE802154_ATTR_MAC_SHORT_ADDRESS; + ret = dev->d_ioctl(dev, MAC802154IOC_MLME_GET_REQUEST, + (unsigned long)((uintptr_t)&arg)); + if (ret < 0) + { + wlerr("ERROR: MAC802154IOC_MLME_GET_REQUEST failed: %d\n", ret); + return ret; + } + else + { + union + { + uint16_t u16; + uint8_t u8[2]; + } u; + + u.u16 = arg.u.getreq.attrval.mac.saddr; + dev->d_mac.ieee802154.u8[0] = u.u8[0]; + dev->d_mac.ieee802154.u8[1] = u.u8[1]; + + /* Set the IP address based on the saddr */ + + dev->d_ipv6addr[0] = HTONS(0xfe80); + dev->d_ipv6addr[1] = 0; + dev->d_ipv6addr[2] = 0; + dev->d_ipv6addr[3] = 0; + dev->d_ipv6addr[4] = 0; + dev->d_ipv6addr[5] = HTONS(0x00ff); + dev->d_ipv6addr[6] = HTONS(0xfe00); + dev->d_ipv6addr[7] = u.u16; + dev->d_ipv6addr[7] ^= 0x200; + return OK; + } +#endif +} + +/**************************************************************************** + * Name: macnet_netmask + * + * Description: + * Create a netmask of a MAC-based IP address which may be based on either + * the IEEE 802.15.14 short or extended address of the MAC. + * + * 128 112 96 80 64 48 32 16 + * ---- ---- ---- ---- ---- ---- ---- ---- + * fe80 0000 0000 0000 0000 00ff fe00 xxxx 2-byte short address IEEE 48-bit MAC + * fe80 0000 0000 0000 xxxx xxxx xxxx xxxx 8-byte extended address IEEE EUI-64 + * + ****************************************************************************/ + +static inline void macnet_netmask(FAR struct net_driver_s *dev) +{ + dev->d_ipv6netmask[0] = 0xffff; + dev->d_ipv6netmask[1] = 0xffff; + dev->d_ipv6netmask[2] = 0xffff; + dev->d_ipv6netmask[3] = 0xffff; +#ifdef CONFIG_NET_6LOWPAN_EXTENDEDADDR + dev->d_ipv6netmask[4] = 0; + dev->d_ipv6netmask[5] = 0; + dev->d_ipv6netmask[6] = 0; + dev->d_ipv6netmask[7] = 0; +#else + dev->d_ipv6netmask[4] = 0xffff; + dev->d_ipv6netmask[5] = 0xffff; + dev->d_ipv6netmask[6] = 0xffff; + dev->d_ipv6netmask[7] = 0; +#endif +} + /**************************************************************************** * Name: macnet_notify * @@ -223,7 +355,7 @@ static int macnet_req_data(FAR struct ieee802154_driver_s *netdev, * ****************************************************************************/ -static void macnet_notify(FAR const struct mac802154_maccb_s *maccb, +static void macnet_notify(FAR struct mac802154_maccb_s *maccb, FAR struct ieee802154_notif_s *notif) { FAR struct macnet_callback_s *cb = @@ -244,17 +376,27 @@ static void macnet_notify(FAR const struct mac802154_maccb_s *maccb, default: break; } + + /* Free the event notification */ + + mac802154_notif_free(priv->md_mac, notif); } /**************************************************************************** * Name: macnet_rxframe * * Description: + * Handle received frames forward by the IEEE 802.15.4 MAC. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure. On success, the ind and its contained iob will be freed. + * The ind will be intact if this function returns a failure. * ****************************************************************************/ -static void macnet_rxframe(FAR const struct mac802154_maccb_s *maccb, - FAR struct ieee802154_data_ind_s *ind) +static int macnet_rxframe(FAR struct mac802154_maccb_s *maccb, + FAR struct ieee802154_data_ind_s *ind) { FAR struct macnet_callback_s *cb = (FAR struct macnet_callback_s *)maccb; @@ -264,10 +406,31 @@ static void macnet_rxframe(FAR const struct mac802154_maccb_s *maccb, DEBUGASSERT(cb != NULL && cb->mc_priv != NULL); priv = cb->mc_priv; - /* Extract the IOB containing the frame from the struct ieee802154_data_ind_s */ + /* Ignore the frame if the network is not up */ + + if (!priv->md_bifup) + { + return -ENETDOWN; + } + + /* Peek the IOB contained the frame in the struct ieee802154_data_ind_s */ DEBUGASSERT(priv != NULL && ind != NULL && ind->frame != NULL); - iob = ind->frame; + iob = ind->frame; + + /* If the frame is not a 6LoWPAN frame, then return an error. The first + * byte following the MAC head at the io_offset should be a valid IPHC + * header. + */ + + if ((iob->io_data[iob->io_offset] & SIXLOWPAN_DISPATCH_NALP_MASK) == + SIXLOWPAN_DISPATCH_NALP) + { + return -EINVAL; + } + + /* Remove the IOB containing the frame. */ + ind->frame = NULL; /* Transfer the frame to the network logic */ @@ -279,6 +442,7 @@ static void macnet_rxframe(FAR const struct mac802154_maccb_s *maccb, */ ieee802154_ind_free(ind); + return OK; } /**************************************************************************** @@ -624,34 +788,43 @@ static void macnet_txpoll_expiry(int argc, wdparm_t arg, ...) static int macnet_ifup(FAR struct net_driver_s *dev) { - FAR struct macnet_driver_s *priv = (FAR struct macnet_driver_s *)dev->d_private; + FAR struct macnet_driver_s *priv = + (FAR struct macnet_driver_s *)dev->d_private; + int ret; -#ifdef CONFIG_NET_IPv4 - ninfo("Bringing up: %d.%d.%d.%d\n", - dev->d_ipaddr & 0xff, (dev->d_ipaddr >> 8) & 0xff, - (dev->d_ipaddr >> 16) & 0xff, dev->d_ipaddr >> 24); -#endif -#ifdef CONFIG_NET_IPv6 - ninfo("Bringing up: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", - dev->d_ipv6addr[0], dev->d_ipv6addr[1], dev->d_ipv6addr[2], - dev->d_ipv6addr[3], dev->d_ipv6addr[4], dev->d_ipv6addr[5], - dev->d_ipv6addr[6], dev->d_ipv6addr[7]); + /* Set the IP address based on the addressing assigned to the node */ + + ret = macnet_advertise(dev); + if (ret >= 0) + { + ninfo("Bringing up: %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + dev->d_ipv6addr[0], dev->d_ipv6addr[1], dev->d_ipv6addr[2], + dev->d_ipv6addr[3], dev->d_ipv6addr[4], dev->d_ipv6addr[5], + dev->d_ipv6addr[6], dev->d_ipv6addr[7]); + +#ifdef CONFIG_NET_6LOWPAN_EXTENDEDADDR + ninfo(" Node: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + dev->d_mac.ieee802154.u8[0], dev->d_mac.ieee802154.u8[1], + dev->d_mac.ieee802154.u8[2], dev->d_mac.ieee802154.u8[3], + dev->d_mac.ieee802154.u8[4], dev->d_mac.ieee802154.u8[5], + dev->d_mac.ieee802154.u8[6], dev->d_mac.ieee802154.u8[7]); +#else + ninfo(" Node: %02x:%02x\n", + dev->d_mac.ieee802154.u8[0], dev->d_mac.ieee802154.u8[1]); #endif - /* Initialize PHYs, the IEEE 802.15.4 interface, and setup up IEEE 802.15.4 interrupts */ -#warning Missing logic + /* Set and activate a timer process */ - /* Setup up address filtering */ + (void)wd_start(priv->md_txpoll, TXPOLL_WDDELAY, macnet_txpoll_expiry, + 1, (wdparm_t)priv); - /* Set and activate a timer process */ + /* The interface is now up */ - (void)wd_start(priv->md_txpoll, TXPOLL_WDDELAY, macnet_txpoll_expiry, 1, - (wdparm_t)priv); + priv->md_bifup = true; + ret = OK; + } - /* Enable the IEEE 802.15.4 radio */ - - priv->md_bifup = true; - return OK; + return ret; } /**************************************************************************** @@ -993,7 +1166,7 @@ static int macnet_req_data(FAR struct ieee802154_driver_s *netdev, * * Description: * Register a network driver to access the IEEE 802.15.4 MAC layer from - * a socket using 6loWPAN + * a socket using 6LoWPAN * * Input Parameters: * mac - Pointer to the mac layer struct to be registered. @@ -1062,6 +1235,10 @@ int mac802154netdev_register(MACHANDLE mac) DEBUGASSERT(priv->md_txpoll != NULL); + /* Set the network mask. */ + + macnet_netmask(dev); + /* Initialize the Network frame-related callbacks */ ieee->i_get_mhrlen = macnet_get_mhrlen; /* Get MAC header length */ @@ -1072,6 +1249,8 @@ int mac802154netdev_register(MACHANDLE mac) priv->md_cb.mc_priv = priv; maccb = &priv->md_cb.mc_cb; + maccb->flink = NULL; + maccb->prio = CONFIG_IEEE802154_NETDEV_RECVRPRIO; maccb->notify = macnet_notify; maccb->rxframe = macnet_rxframe; diff --git a/wireless/ieee802154/mac802154_notif.c b/wireless/ieee802154/mac802154_notif.c index 15368a5483..bce299c139 100644 --- a/wireless/ieee802154/mac802154_notif.c +++ b/wireless/ieee802154/mac802154_notif.c @@ -74,18 +74,38 @@ int mac802154_notif_free(MACHANDLE mac, { FAR struct ieee802154_privmac_s *priv = (FAR struct ieee802154_privmac_s *)mac; - FAR struct mac802154_notif_s *privnotif = (FAR struct mac802154_notif_s *)notif; + FAR struct mac802154_notif_s *privnotif = + (FAR struct mac802154_notif_s *)notif; /* Get exclusive access to the MAC */ mac802154_takesem(&priv->exclsem, false); - privnotif->flink = priv->notif_free; - priv->notif_free = privnotif; - mac802154_givesem(&priv->notif_sem); + /* We know how many clients have registered for notifications. Each must + * call mac802154_notif_free() before we can release the notification + * resource. + */ + + if (priv->nnotif < 2) + { + /* This is the free from the last notification */ + + privnotif->flink = priv->notif_free; + priv->notif_free = privnotif; + priv->nnotif = 0; + + mac802154_givesem(&priv->notif_sem); + } + else + { + /* More calls are expected. Decrement the count of expected calls + * and preserve the notification resources. + */ + + priv->nnotif--; + } mac802154_givesem(&priv->exclsem); - return -ENOTTY; } @@ -125,6 +145,7 @@ void mac802154_notifpool_init(FAR struct ieee802154_privmac_s *priv) pool++; remaining--; } + sem_init(&priv->notif_sem, 0, CONFIG_MAC802154_NNOTIF); } @@ -165,6 +186,7 @@ int mac802154_notif_alloc(FAR struct ieee802154_privmac_s *priv, { privnotif = priv->notif_free; priv->notif_free = privnotif->flink; + priv->nnotif = 0; } else { @@ -200,9 +222,44 @@ int mac802154_notif_alloc(FAR struct ieee802154_privmac_s *priv, privnotif = priv->notif_free; priv->notif_free = privnotif->flink; + priv->nnotif = 0; } *notif = (FAR struct ieee802154_notif_s *)privnotif; return OK; -} \ No newline at end of file +} + +/**************************************************************************** + * 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; + + /* Set the notification count so that the notification resources will be + * preserved until the final notification. + */ + + priv->nnotif = 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 index 3cf088163d..3c6bdd3523 100644 --- a/wireless/ieee802154/mac802154_notif.h +++ b/wireless/ieee802154/mac802154_notif.h @@ -63,8 +63,8 @@ struct mac802154_notif_s { - struct ieee802154_notif_s pub; - FAR struct mac802154_notif_s *flink; + struct ieee802154_notif_s pub; /* Publically visible structure */ + FAR struct mac802154_notif_s *flink; /* Supports a singly linked list */ }; /**************************************************************************** @@ -79,4 +79,7 @@ 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); + #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 3f74b55224..57c3154991 100644 --- a/wireless/ieee802154/mac802154_poll.c +++ b/wireless/ieee802154/mac802154_poll.c @@ -50,8 +50,6 @@ #include #include -#include - #include "mac802154.h" #include "mac802154_internal.h" @@ -83,7 +81,6 @@ int mac802154_req_poll(MACHANDLE mac, FAR struct ieee802154_poll_req_s *req) { FAR struct ieee802154_privmac_s *priv = (FAR struct ieee802154_privmac_s *)mac; - FAR struct iob_s *iob; FAR struct ieee802154_txdesc_s *txdesc; int ret; @@ -221,7 +218,7 @@ void mac802154_txdone_datareq_poll(FAR struct ieee802154_privmac_s *priv, /* Release the MAC, call the callback, get exclusive access again */ mac802154_givesem(&priv->exclsem); - priv->cb->notify(priv->cb, notif); + mac802154_notify(priv, notif); mac802154_takesem(&priv->exclsem, false); } else @@ -261,7 +258,7 @@ void mac802154_txdone_datareq_poll(FAR struct ieee802154_privmac_s *priv, * ****************************************************************************/ -static void mac802154_timeout_poll(FAR struct ieee802154_privmac_s *priv) +void mac802154_timeout_poll(FAR struct ieee802154_privmac_s *priv) { FAR struct ieee802154_notif_s *notif; @@ -286,5 +283,5 @@ static void mac802154_timeout_poll(FAR struct ieee802154_privmac_s *priv) notif->notiftype = IEEE802154_NOTIFY_CONF_POLL; notif->u.pollconf.status = IEEE802154_STATUS_NO_DATA; - priv->cb->notify(priv->cb, notif); + mac802154_notify(priv, notif); } \ No newline at end of file