mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
171 lines
5.0 KiB
C
171 lines
5.0 KiB
C
/*
|
|
* Copyright (C) 2015 Freie Universität Berlin
|
|
*
|
|
* This file is subject to the terms and conditions of the GNU Lesser
|
|
* General Public License v2.1. See the file LICENSE in the top level
|
|
* directory for more details.
|
|
*/
|
|
|
|
/**
|
|
* @{
|
|
* @ingroup net_gnrc_netapi
|
|
* @file
|
|
* @brief This file contains a number of helper functions that provide
|
|
* some shortcuts for some always repeating code snippets when
|
|
* servicing the netapi interface
|
|
*
|
|
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
|
* @}
|
|
*/
|
|
|
|
#include "mbox.h"
|
|
#include "msg.h"
|
|
#include "net/gnrc/netreg.h"
|
|
#include "net/gnrc/pktbuf.h"
|
|
#include "net/gnrc/netapi.h"
|
|
|
|
#define ENABLE_DEBUG (0)
|
|
#include "debug.h"
|
|
|
|
/**
|
|
* @brief Unified function for getting and setting netapi options
|
|
*
|
|
* @param[in] pid PID of the targeted thread
|
|
* @param[in] type specify if option is to be set or get
|
|
* @param[in] opt option to set or get
|
|
* @param[in] data data to set or pointer to buffer for reading options
|
|
* @param[in] data_len size of the given buffer
|
|
*
|
|
* @return the value from the received ACK message
|
|
*/
|
|
static inline int _get_set(kernel_pid_t pid, uint16_t type,
|
|
netopt_t opt, uint16_t context,
|
|
void *data, size_t data_len)
|
|
{
|
|
msg_t cmd;
|
|
msg_t ack;
|
|
gnrc_netapi_opt_t o;
|
|
/* set netapi's option struct */
|
|
o.opt = opt;
|
|
o.context = context;
|
|
o.data = data;
|
|
o.data_len = data_len;
|
|
/* set outgoing message's fields */
|
|
cmd.type = type;
|
|
cmd.content.ptr = (void *)&o;
|
|
/* trigger the netapi */
|
|
msg_send_receive(&cmd, &ack, pid);
|
|
assert(ack.type == GNRC_NETAPI_MSG_TYPE_ACK);
|
|
/* return the ACK message's value */
|
|
return (int)ack.content.value;
|
|
}
|
|
|
|
static inline int _snd_rcv(kernel_pid_t pid, uint16_t type, gnrc_pktsnip_t *pkt)
|
|
{
|
|
msg_t msg;
|
|
/* set the outgoing message's fields */
|
|
msg.type = type;
|
|
msg.content.ptr = (void *)pkt;
|
|
/* send message */
|
|
int ret = msg_try_send(&msg, pid);
|
|
if (ret < 1) {
|
|
DEBUG("gnrc_netapi: dropped message to %" PRIkernel_pid " (%s)\n", pid,
|
|
(ret == 0) ? "receiver queue is full" : "invalid receiver");
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#ifdef MODULE_GNRC_NETAPI_MBOX
|
|
static inline int _snd_rcv_mbox(mbox_t *mbox, uint16_t type, gnrc_pktsnip_t *pkt)
|
|
{
|
|
msg_t msg;
|
|
/* set the outgoing message's fields */
|
|
msg.type = type;
|
|
msg.content.ptr = (void *)pkt;
|
|
/* send message */
|
|
int ret = mbox_try_put(mbox, &msg);
|
|
if (ret < 1) {
|
|
DEBUG("gnrc_netapi: dropped message to %p (was full)\n", mbox);
|
|
}
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
int gnrc_netapi_dispatch(gnrc_nettype_t type, uint32_t demux_ctx,
|
|
uint16_t cmd, gnrc_pktsnip_t *pkt)
|
|
{
|
|
int numof = gnrc_netreg_num(type, demux_ctx);
|
|
|
|
if (numof != 0) {
|
|
gnrc_netreg_entry_t *sendto = gnrc_netreg_lookup(type, demux_ctx);
|
|
|
|
gnrc_pktbuf_hold(pkt, numof - 1);
|
|
|
|
while (sendto) {
|
|
#if defined(MODULE_GNRC_NETAPI_MBOX) || defined(MODULE_GNRC_NETAPI_CALLBACKS)
|
|
int release = 0;
|
|
switch (sendto->type) {
|
|
case GNRC_NETREG_TYPE_DEFAULT:
|
|
if (_snd_rcv(sendto->target.pid, cmd, pkt) < 1) {
|
|
/* unable to dispatch packet */
|
|
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;
|
|
break;
|
|
}
|
|
if (release) {
|
|
gnrc_pktbuf_release(pkt);
|
|
}
|
|
#else
|
|
if (_snd_rcv(sendto->target.pid, cmd, pkt) < 1) {
|
|
/* unable to dispatch packet */
|
|
gnrc_pktbuf_release(pkt);
|
|
}
|
|
#endif
|
|
sendto = gnrc_netreg_getnext(sendto);
|
|
}
|
|
}
|
|
|
|
return numof;
|
|
}
|
|
|
|
int gnrc_netapi_send(kernel_pid_t pid, gnrc_pktsnip_t *pkt)
|
|
{
|
|
return _snd_rcv(pid, GNRC_NETAPI_MSG_TYPE_SND, pkt);
|
|
}
|
|
|
|
int gnrc_netapi_receive(kernel_pid_t pid, gnrc_pktsnip_t *pkt)
|
|
{
|
|
return _snd_rcv(pid, GNRC_NETAPI_MSG_TYPE_RCV, pkt);
|
|
}
|
|
|
|
int gnrc_netapi_get(kernel_pid_t pid, netopt_t opt, uint16_t context,
|
|
void *data, size_t data_len)
|
|
{
|
|
return _get_set(pid, GNRC_NETAPI_MSG_TYPE_GET, opt, context,
|
|
data, data_len);
|
|
}
|
|
|
|
int gnrc_netapi_set(kernel_pid_t pid, netopt_t opt, uint16_t context,
|
|
void *data, size_t data_len)
|
|
{
|
|
return _get_set(pid, GNRC_NETAPI_MSG_TYPE_SET, opt, context,
|
|
data, data_len);
|
|
}
|