diff --git a/Makefile.pseudomodules b/Makefile.pseudomodules index 438fa415ad90cc9e8ff7c3b359cd07b921676906..27976a1dab9b386be6ad4d44c15d65990712c214 100644 --- a/Makefile.pseudomodules +++ b/Makefile.pseudomodules @@ -12,6 +12,7 @@ PSEUDOMODULES += gnrc_ipv6_router PSEUDOMODULES += gnrc_ipv6_router_default PSEUDOMODULES += gnrc_netdev_default PSEUDOMODULES += gnrc_neterr +PSEUDOMODULES += gnrc_netapi_callbacks PSEUDOMODULES += gnrc_netapi_mbox PSEUDOMODULES += gnrc_pktbuf PSEUDOMODULES += gnrc_sixlowpan_border_router_default diff --git a/sys/include/net/gnrc/netapi.h b/sys/include/net/gnrc/netapi.h index 63ea497b7820bd80643c52782ffa9ff81cba057e..25dc2a41dd731e6ad7156478d9e7133fb0ae4ac5 100644 --- a/sys/include/net/gnrc/netapi.h +++ b/sys/include/net/gnrc/netapi.h @@ -36,6 +36,21 @@ * USEMODULE += gnrc_netapi_mbox * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * @} + * + * @defgroup net_gnrc_netapi_callbacks Callback extension + * @ingroup net_gnrc_netapi + * @brief Callback extension for @ref net_gnrc_netapi + * @{ + * @details The submodule `gnrc_netapi_callbacks` provides an extension for + * callbacks to run GNRC thread-less. + * + * To use, add the module `gnrc_netapi_callbacks` to the `USEMODULE` macro in + * your application's Makefile: + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.mk} + * USEMODULE += gnrc_netapi_callbacks + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * @} * @author Martine Lenders <mlenders@inf.fu-berlin.de> * @author Hauke Petersen <hauke.petersen@fu-berlin.de> */ diff --git a/sys/include/net/gnrc/netreg.h b/sys/include/net/gnrc/netreg.h index d040f332c95cb0a2fba4cb0519c01140b88ce23a..e078a51d9c2d1e3cedd2a862f87a3d7c9ece9c58 100644 --- a/sys/include/net/gnrc/netreg.h +++ b/sys/include/net/gnrc/netreg.h @@ -35,13 +35,16 @@ extern "C" { #endif -#if defined(MODULE_GNRC_NETAPI_MBOX) || defined(DOXYGEN) +#if defined(MODULE_GNRC_NETAPI_MBOX) || defined(MODULE_GNRC_NETAPI_CALLBACKS) || \ + defined(DOXYGEN) typedef enum { GNRC_NETREG_TYPE_DEFAULT = 0, #if defined(MODULE_GNRC_NETAPI_MBOX) || defined(DOXYGEN) GNRC_NETREG_TYPE_MBOX, #endif +#if defined(MODULE_GNRC_NETAPI_CALLBACKS) || defined(DOXYGEN) GNRC_NETREG_TYPE_CB, +#endif } gnrc_netreg_type_t; #endif @@ -77,7 +80,7 @@ typedef enum { * for the netreg entry * @param[in] mbox Target @ref core_mbox "mailbox" for the registry entry * - * @note Only available with @ref net_gnrc_netreg_extra. + * @note Only available with @ref net_gnrc_netapi_mbox. * * @return An initialized netreg entry */ @@ -86,6 +89,48 @@ typedef enum { { .mbox = mbox } } #endif +#if defined(MODULE_GNRC_NETAPI_CALLBACKS) || defined(DOXYGEN) +/** + * @brief Initializes a netreg entry statically with callback + * + * @param[in] demux_ctx The @ref gnrc_netreg_entry_t::demux_ctx "demux context" + * for the netreg entry + * @param[in] cb Target callback for the registry entry + * + * @note Only available with @ref net_gnrc_netapi_callbacks. + * + * @return An initialized netreg entry + */ +#define GNRC_NETREG_ENTRY_INIT_CB(demux_ctx, cbd) { NULL, demux_ctx, \ + GNRC_NETREG_TYPE_CB, \ + { .cbd = cbd } } + +/** + * @brief Packet handler callback for netreg entries with callback. + * + * @pre `cmd` $\in$ { @ref GNRC_NETAPI_MSG_TYPE_RCV, @ref GNRC_NETAPI_MSG_TYPE_SND } + * + * @note Only available with @ref net_gnrc_netapi_callbacks. + * + * @param[in] cmd @ref net_gnrc_netapi command type. Must be either + * @ref GNRC_NETAPI_MSG_TYPE_SND or + * @ref GNRC_NETAPI_MSG_TYPE_RCV + * @param[in] pkt The packet to handle. + * @param[in] ctx Application context. + */ +typedef void (*gnrc_netreg_entry_cb_t)(uint16_t cmd, gnrc_pktsnip_t *pkt, + void *ctx); + +/** + * @brief Callback + Context descriptor + * @note Only available with @ref net_gnrc_netapi_callbacks. + */ +typedef struct { + gnrc_netreg_entry_cb_t cb; /**< the callback */ + void *ctx; /**< application context for the callback */ +} gnrc_netreg_entry_cbd_t; +#endif + /** * @brief Entry to the @ref net_gnrc_netreg */ @@ -105,7 +150,8 @@ typedef struct gnrc_netreg_entry { * ports in UDP/TCP, or similar. */ uint32_t demux_ctx; -#if defined(MODULE_GNRC_NETAPI_MBOX) || defined(DOXYGEN) +#if defined(MODULE_GNRC_NETAPI_MBOX) || defined(MODULE_GNRC_NETAPI_CALLBACKS) || \ + defined(DOXYGEN) /** * @brief Type of the registry entry * @@ -124,6 +170,15 @@ typedef struct gnrc_netreg_entry { */ mbox_t *mbox; #endif + +#if defined(MODULE_GNRC_NETAPI_CALLBACKS) || defined(DOXYGEN) + /** + * @brief Target callback for the registry entry + * + * @note Only available with @ref net_gnrc_netapi_callbacks. + */ + gnrc_netreg_entry_cbd_t *cbd; +#endif } target; /**< Target for the registry entry */ } gnrc_netreg_entry_t; @@ -147,7 +202,7 @@ static inline void gnrc_netreg_entry_init_pid(gnrc_netreg_entry_t *entry, { entry->next = NULL; entry->demux_ctx = demux_ctx; -#ifdef MODULE_GNRC_NETAPI_MBOX +#if defined(MODULE_GNRC_NETAPI_MBOX) || defined(MODULE_GNRC_NETAPI_CALLBACKS) entry->type = GNRC_NETREG_TYPE_DEFAULT; #endif entry->target.pid = pid; @@ -175,6 +230,28 @@ static inline void gnrc_netreg_entry_init_mbox(gnrc_netreg_entry_t *entry, } #endif +#if defined(MODULE_GNRC_NETAPI_CALLBACKS) || defined(DOXYGEN) +/** + * @brief Initializes a netreg entry dynamically with callback + * + * @param[out] entry A netreg entry + * @param[in] demux_ctx The @ref gnrc_netreg_entry_t::demux_ctx "demux context" + * for the netreg entry + * @param[in] mbox Target callback for the registry entry + * + * @note Only available with @ref net_gnrc_netapi_callbacks. + */ +static inline void gnrc_netreg_entry_init_cb(gnrc_netreg_entry_t *entry, + uint32_t demux_ctx, + gnrc_netreg_entry_cbd_t *cbd) +{ + entry->next = NULL; + entry->demux_ctx = demux_ctx; + entry->type = GNRC_NETREG_TYPE_CB; + entry->target.cbd = cbd; +} +#endif + /** * @brief Registers a thread to the registry. * diff --git a/sys/net/gnrc/netapi/gnrc_netapi.c b/sys/net/gnrc/netapi/gnrc_netapi.c index 5f80302524108256c0dedd64d6b57f1929482550..d110ebf34af4fd9e1ac0dd7f1141fe3aa3a97271 100644 --- a/sys/net/gnrc/netapi/gnrc_netapi.c +++ b/sys/net/gnrc/netapi/gnrc_netapi.c @@ -102,7 +102,7 @@ int gnrc_netapi_dispatch(gnrc_nettype_t type, uint32_t demux_ctx, gnrc_pktbuf_hold(pkt, numof - 1); while (sendto) { -#ifdef MODULE_GNRC_NETAPI_MBOX +#if defined(MODULE_GNRC_NETAPI_MBOX) || defined(MODULE_GNRC_NETAPI_CALLBACKS) int release = 0; switch (sendto->type) { case GNRC_NETREG_TYPE_DEFAULT: @@ -111,12 +111,19 @@ int gnrc_netapi_dispatch(gnrc_nettype_t type, uint32_t demux_ctx, release = 1; } break; +#ifdef MODULE_GNRC_NETAPI_MBOX case GNRC_NETREG_TYPE_MBOX: if (_snd_rcv_mbox(sendto->target.mbox, cmd, pkt) < 1) { /* unable to dispatch packet */ release = 1; } break; +#endif +#ifdef MODULE_GNRC_NETAPI_CALLBACKS + case GNRC_NETREG_TYPE_CB: + sendto->target.cbd->cb(cmd, pkt, sendto->target.cbd->ctx); + break; +#endif default: /* unknown dispatch type */ release = 1;