Merge pull request #3683 from kaspar030/add_gnrc_netdev2_support
sys: net: add gnrc netdev2 supportdev/timer
commit
48baf5ddcf
@ -1,5 +1,4 @@
|
||||
ifneq (,$(filter gnrc_netif_default,$(USEMODULE)))
|
||||
USEMODULE += dev_eth_tap
|
||||
USEMODULE += gnrc_netdev_eth
|
||||
USEMODULE += gnrc_nomac
|
||||
USEMODULE += netdev2_tap
|
||||
USEMODULE += gnrc_netdev2
|
||||
endif
|
||||
|
@ -1,5 +1,3 @@
|
||||
MODULE = dev_eth_tap
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
||||
|
||||
INCLUDES = $(NATIVEINCLUDES)
|
@ -1,3 +0,0 @@
|
||||
MODULE = dev_eth_autoinit
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "net/dev_eth.h"
|
||||
#include "dev_eth_autoinit.h"
|
||||
|
||||
#ifdef MODULE_DEV_ETH_TAP
|
||||
#include "dev_eth_tap.h"
|
||||
#endif
|
||||
|
||||
#ifdef MODULE_ENCX24J600
|
||||
#include "encx24j600.h"
|
||||
encx24j600_t dev_eth_encx24j600;
|
||||
#endif
|
||||
|
||||
dev_eth_t * const dev_eth_devices[] = {
|
||||
#ifdef MODULE_DEV_ETH_TAP
|
||||
[DEV_ETH_TAP] = (dev_eth_t*)&dev_eth_tap,
|
||||
#endif
|
||||
#ifdef MODULE_ENCX24J600
|
||||
[DEV_ETH_ENCX24J600] = (dev_eth_t*)&dev_eth_encx24j600,
|
||||
#endif
|
||||
};
|
||||
|
||||
void dev_eth_autoinit(void)
|
||||
{
|
||||
#ifdef MODULE_ENCX24J600
|
||||
/* TODO: use sensible defines */
|
||||
encx24j600_setup(&dev_eth_encx24j600, SPI_0, GPIO_1, GPIO_2);
|
||||
#endif
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
|
||||
*
|
||||
* 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 auto_init_gnrc_netif
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Auto initialization for netdev Ethernet network interfaces
|
||||
*
|
||||
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
||||
* @author Oliver Hahm <oliver.hahm@inria.fr>
|
||||
*/
|
||||
|
||||
#ifdef MODULE_GNRC_NETDEV_ETH
|
||||
|
||||
#include "board.h"
|
||||
#include "net/gnrc/nomac.h"
|
||||
#include "net/gnrc.h"
|
||||
|
||||
#include "net/gnrc/netdev_eth.h"
|
||||
#include "net/dev_eth.h"
|
||||
#include "dev_eth_tap.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
/**
|
||||
* @brief Define stack parameters for the MAC layer thread
|
||||
* @{
|
||||
*/
|
||||
#define NETDEV_ETH_MAC_STACKSIZE (THREAD_STACKSIZE_DEFAULT)
|
||||
#define NETDEV_ETH_MAC_PRIO (THREAD_PRIORITY_MAIN - 4)
|
||||
|
||||
static char _nomac_stack[NETDEV_ETH_MAC_STACKSIZE];
|
||||
|
||||
void auto_init_gnrc_netdev_eth(void)
|
||||
{
|
||||
DEBUG("Initializing NETDEV_ETH device\n");
|
||||
int res = gnrc_netdev_eth_init(&gnrc_netdev_eth, (dev_eth_t*)&dev_eth_tap);
|
||||
|
||||
if (res < 0) {
|
||||
DEBUG("Error initializing NETDEV_ETH device!");
|
||||
}
|
||||
else {
|
||||
gnrc_nomac_init(_nomac_stack, NETDEV_ETH_MAC_STACKSIZE, NETDEV_ETH_MAC_PRIO,
|
||||
"tapnet", (gnrc_netdev_t *)&gnrc_netdev_eth);
|
||||
}
|
||||
}
|
||||
#else
|
||||
typedef int dont_be_pedantic;
|
||||
#endif /* MODULE_GNRC_NETDEV_ETH */
|
||||
|
||||
/** @} */
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
|
||||
*
|
||||
* 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 auto_init_ng_netif
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Auto initialization for ethernet devices
|
||||
*
|
||||
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
||||
*/
|
||||
|
||||
#ifdef MODULE_NETDEV2_TAP
|
||||
|
||||
#define ENABLE_DEBUG (1)
|
||||
#include "debug.h"
|
||||
|
||||
#include "netdev2_tap.h"
|
||||
#include "net/gnrc/gnrc_netdev2_eth.h"
|
||||
|
||||
extern netdev2_tap_t netdev2_tap;
|
||||
|
||||
/**
|
||||
* @brief Define stack parameters for the MAC layer thread
|
||||
* @{
|
||||
*/
|
||||
#define TAP_MAC_STACKSIZE (THREAD_STACKSIZE_DEFAULT + DEBUG_EXTRA_STACKSIZE)
|
||||
#define TAP_MAC_PRIO (THREAD_PRIORITY_MAIN - 3)
|
||||
|
||||
/**
|
||||
* @brief Stacks for the MAC layer threads
|
||||
*/
|
||||
static char _netdev2_eth_stack[TAP_MAC_STACKSIZE + DEBUG_EXTRA_STACKSIZE];
|
||||
static gnrc_netdev2_t _gnrc_netdev2_tap;
|
||||
|
||||
void auto_init_netdev2_tap(void)
|
||||
{
|
||||
gnrc_netdev2_eth_init(&_gnrc_netdev2_tap, (netdev2_t*)&netdev2_tap);
|
||||
|
||||
gnrc_netdev2_init(_netdev2_eth_stack, TAP_MAC_STACKSIZE,
|
||||
TAP_MAC_PRIO, "gnrc_netdev2_tap", &_gnrc_netdev2_tap);
|
||||
}
|
||||
|
||||
#else
|
||||
typedef int dont_be_pedantic;
|
||||
#endif /* MODULE_NETDEV2_TAP */
|
||||
/** @} */
|
@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup sys_net_dev_eth dev_eth auto setup
|
||||
* @ingroup net_ethernet
|
||||
* @file
|
||||
* @brief Automatically setup available ethernet devices
|
||||
* @{
|
||||
*
|
||||
* @brief header for dev_eth automatic initialization
|
||||
*
|
||||
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
||||
*/
|
||||
|
||||
#ifndef DEV_ETH_AUTOINIT_H
|
||||
#define DEV_ETH_AUTOINIT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief enum for available ethernet devices
|
||||
*/
|
||||
enum {
|
||||
#ifdef MODULE_DEV_ETH_TAP
|
||||
DEV_ETH_TAP,
|
||||
#endif
|
||||
#ifdef MODULE_ENCX24J600
|
||||
DEV_ETH_ENCX24J600,
|
||||
#endif
|
||||
/* must be last: */
|
||||
NUM_DEV_ETH
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Array of const pointers to available ethernet devices
|
||||
*/
|
||||
extern dev_eth_t *const dev_eth_devices[];
|
||||
|
||||
/**
|
||||
* @brief Automatically sets up available dev_eth ethernet devices
|
||||
*
|
||||
* ... by calling the respective *_setup() functions if available.
|
||||
*/
|
||||
void dev_eth_autoinit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/** @} */
|
||||
#endif /* DEV_ETH_AUTOINIT_H */
|
@ -1,216 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
|
||||
* Ell-i open source co-operative
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup net_dev_eth Low-Level Driver Interface
|
||||
* @ingroup net_ethernet
|
||||
* @brief Low-level ethernet driver interface
|
||||
*
|
||||
* This interface is supposed to be a low-level interface for ethernet drivers.
|
||||
* In order to be universally usable, it leaves out many implementation details
|
||||
* to the implementation of an actual network stack using this interface.
|
||||
*
|
||||
* In order to write a driver for this interface, you have to
|
||||
*
|
||||
* 1. create a (possibly const) eth_driver_t structure for your device type,
|
||||
* implement it's functions
|
||||
*
|
||||
* 2. create a dev_eth_t structure, used as device state and handle, for each device
|
||||
*
|
||||
* In order to use this interface, you have to
|
||||
*
|
||||
* 1. implement dev_eth_isr, dev_eth_rx_handler and dev_eth_linkstate_handler
|
||||
* 2. run a loop that get's notified by dev_eth_isr
|
||||
*
|
||||
* A devices send function should always be able to send a frame (and make sure of proper locking).
|
||||
*
|
||||
* Receive packet flow:
|
||||
*
|
||||
* 1. Ethernet driver receives packet, executes driver's internal ISR.
|
||||
* 2. driver's internal ISR should do minimal acknowledging and house keeping and then
|
||||
* call dev_eth_isr
|
||||
* 3. dev_eth_isr should notify a user of this API (e.g., the network stack's L2 thread)
|
||||
* 4. That thread executes the driver's user-space isr (dev->driver->isr)
|
||||
* 5. user space ISR handles less timing critical stuff, eventually calling
|
||||
* dev_eth_linkstate_handler and / or dev_eth_rx_handler
|
||||
*
|
||||
* Check out the dev_eth test application as example.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Definitions low-level ethernet driver interface
|
||||
*
|
||||
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
||||
*/
|
||||
|
||||
#ifndef DEV_ETH_H
|
||||
#define DEV_ETH_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include "ethernet/hdr.h"
|
||||
|
||||
/**
|
||||
* @brief Structure to hold driver state
|
||||
*
|
||||
* Supposed to be extended by driver implementations.
|
||||
* The extended structure should contain all variable driver state.
|
||||
*/
|
||||
typedef struct dev_eth {
|
||||
const struct eth_driver *driver; /**< ptr to that driver's interface.
|
||||
driver->init() expects this to be present,
|
||||
so set this before using the device. */
|
||||
} dev_eth_t;
|
||||
|
||||
/**
|
||||
* @brief Structure to hold driver interface -> function mapping
|
||||
*
|
||||
* The send/receive functions expect/return a full ethernet
|
||||
* frame (dst mac, src mac, ethertype, payload, no checksum).
|
||||
*/
|
||||
typedef struct eth_driver {
|
||||
/**
|
||||
* @brief Send ethernet frame
|
||||
*
|
||||
* Expects a full ethernet frame (dst mac, src mac, ethertype, payload,
|
||||
* no checksum).
|
||||
*
|
||||
* @param buf buffer to read from
|
||||
* @param len nr of bytes to send
|
||||
*
|
||||
* @return nr of bytes sent, or <=0 on error
|
||||
*/
|
||||
int (*send)(dev_eth_t *dev, char* buf, int len);
|
||||
|
||||
/**
|
||||
* @brief Get a received ethernet frame
|
||||
*
|
||||
* Supposed to be called from dev_eth_rx_handler().
|
||||
*
|
||||
* Make sure buf can hold the maximum expected ethernet frame size.
|
||||
*
|
||||
* @param buf buffer to write to
|
||||
* @param len maximum nr. of bytes to read
|
||||
*
|
||||
* @return nr of bytes read or <=0 on error
|
||||
*/
|
||||
int (*recv)(dev_eth_t *dev, char* buf, int len);
|
||||
|
||||
/**
|
||||
* @brief get the device's MAC address
|
||||
*
|
||||
* @param buf location to write to. Make sure this is can take least 6 bytes
|
||||
*/
|
||||
void (*get_mac_addr)(dev_eth_t *dev, uint8_t *buf);
|
||||
|
||||
/**
|
||||
* @brief get the device's promiscous status
|
||||
*
|
||||
* Default is not promiscous.
|
||||
* Promiscous means, receive all ethernet frames.
|
||||
* Not promiscous means only receive broadcast, multicast or frames with
|
||||
* the device's MAC address as dst address.
|
||||
*
|
||||
* @return 1 for promiscous, 0 for not promiscous
|
||||
*/
|
||||
int (*get_promiscous)(dev_eth_t *dev);
|
||||
/**
|
||||
* @brief set the devices promiscous mode
|
||||
*
|
||||
* @param value 1 for promiscous, 0 for not promiscous
|
||||
* @return the new value (device might not support wanted mode)
|
||||
*/
|
||||
int (*set_promiscous)(dev_eth_t *dev, int value);
|
||||
/**
|
||||
* @brief the driver's initialization function
|
||||
*
|
||||
* @return <=0 on error, >0 on success
|
||||
*/
|
||||
int (*init)(dev_eth_t *dev);
|
||||
/**
|
||||
* @brief the driver's cleanup function (optional)
|
||||
*/
|
||||
void (*cleanup)(dev_eth_t *dev);
|
||||
/**
|
||||
* @brief a driver's user-space ISR handler
|
||||
*
|
||||
* This function will be called from a network stack's loop when being notified
|
||||
* by dev_eth_isr.
|
||||
*
|
||||
* It is supposed to call dev_eth_rx_handler for each available received packed,
|
||||
* and dev_eth_linkstate_handler whenever a link state change event occurs.
|
||||
*
|
||||
* See receive packet flow description for details.
|
||||
*/
|
||||
void (*isr)(dev_eth_t *dev);
|
||||
} eth_driver_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize a device given by dev (convenience function)
|
||||
*
|
||||
* The device given as parameter *must* be previously setup by the
|
||||
* drivers *_setup() function.
|
||||
*
|
||||
*/
|
||||
static inline int dev_eth_init(dev_eth_t *dev) {
|
||||
return dev->driver->init(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Cleanup a device given by dev (convenience function)
|
||||
*
|
||||
* This function is to be called on reboot if the init function is not
|
||||
* idempotent.
|
||||
*
|
||||
*/
|
||||
static inline void dev_eth_cleanup(dev_eth_t *dev) {
|
||||
if (dev->driver->cleanup) {
|
||||
dev->driver->cleanup(dev);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief global dev_eth interrupt handling function.
|
||||
*
|
||||
* This function should be called from your device's ISR from whithin ISR context.
|
||||
* It is supposed to wake up a waiting user-space event loop.
|
||||
*/
|
||||
extern void dev_eth_isr(dev_eth_t *dev);
|
||||
|
||||
/**
|
||||
* @brief dev_eth event callback for packets that were received.
|
||||
*
|
||||
* This function should be called from whithin your driver's isr()
|
||||
* (as defined in eth_driver_t), once for every packet that was received.
|
||||
*
|
||||
* It needs to call dev->driver->recv() in order to get received packet
|
||||
* from the driver.
|
||||
*/
|
||||
extern void dev_eth_rx_handler(dev_eth_t *dev);
|
||||
|
||||
/**
|
||||
* @brief dev_eth ethernet link state handler
|
||||
*
|
||||
* This function should be called from whithin your driver's isr()
|
||||
* (as defined in eth_driver_t) for every layer 2 link state change.
|
||||
*
|
||||
* @param dev device that triggered the event
|
||||
* @param newstate 1 for "link established", 0 for "link down"
|
||||
*/
|
||||
extern void dev_eth_linkstate_handler(dev_eth_t *dev, int newstate);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/** @} */
|
||||
#endif /* DEV_ETH_H */
|
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
|
||||
*
|
||||
* 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
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief netdev2 gnrc glue code interface
|
||||
*
|
||||
* This interface is supposed to provide common adaption code between the
|
||||
* low-level network device interface "netdev2" and the gnrc network stack.
|
||||
*
|
||||
* GNRC sends around "gnrc_pktsnip_t" structures, but netdev can only handle
|
||||
* "struct iovec" structures when sending, or a flat buffer when receiving.
|
||||
*
|
||||
* The purpose of gnrc_netdev is to bring these two interfaces together.
|
||||
*
|
||||
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
||||
*/
|
||||
|
||||
#ifndef GNRC_NETDEV2_H
|
||||
#define GNRC_NETDEV2_H
|
||||
|
||||
#include "kernel_types.h"
|
||||
#include "net/netdev2.h"
|
||||
#include "net/gnrc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define NETDEV2_MSG_TYPE_EVENT 0x1234
|
||||
|
||||
typedef struct gnrc_netdev2 gnrc_netdev2_t;
|
||||
|
||||
/**
|
||||
* @brief Structure holding gnrc netdev2 adapter state
|
||||
*
|
||||
* This structure is supposed to hold any state parameters needed
|
||||
* to use a netdev2 device from gnrc.
|
||||
*
|
||||
* It can be extended
|
||||
*/
|
||||
struct gnrc_netdev2 {
|
||||
/**
|
||||
* @brief Send a pktsnip using this device
|
||||
*
|
||||
* This function should convert the pktsnip into a format
|
||||
* the underlying device understands and send it.
|
||||
*/
|
||||
int (*send)(gnrc_netdev2_t *dev, gnrc_pktsnip_t *snip);
|
||||
|
||||
/**
|
||||
* @brief Receive a pktsnip from this device
|
||||
*
|
||||
* This function should receive a raw frame from the underlying
|
||||
* device and convert it into a pktsnip while adding a netif header
|
||||
* and possibly marking out higher-layer headers.
|
||||
*/
|
||||
gnrc_pktsnip_t * (*recv)(gnrc_netdev2_t *dev);
|
||||
|
||||
/**
|
||||
* @brief netdev2 handle this adapter is working with
|
||||
*/
|
||||
netdev2_t *dev;
|
||||
|
||||
/**
|
||||
* @brief PID of this adapter for netapi messages
|
||||
*/
|
||||
kernel_pid_t pid;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Initialize gnrc netdev2 handler thread
|
||||
*
|
||||
* @param[in] stack ptr to preallocated stack buffer
|
||||
* @param[in] stacksize size of stack buffer
|
||||
* @param[in] priority priority of thread
|
||||
* @param[in] name name of thread
|
||||
* @param[in] gnrc_netdev2 ptr to netdev2 device to handle in created thread
|
||||
*
|
||||
* @return pid of created thread
|
||||
* @return KERNEL_PID_UNDEF on error
|
||||
*/
|
||||
kernel_pid_t gnrc_netdev2_init(char *stack, int stacksize, char priority,
|
||||
const char *name, gnrc_netdev2_t *gnrc_netdev2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GNRC_NETDEV2_H */
|
||||
/** @} */
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
|
||||
*
|
||||
* 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
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief netdev2 gnrc ethernet glue code interface
|
||||
*
|
||||
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
||||
*/
|
||||
|
||||
#ifndef GNRC_NETDEV2_ETH_H
|
||||
#define GNRC_NETDEV2_ETH_H
|
||||
|
||||
#include "net/gnrc/gnrc_netdev2.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize gnrc handler thread for netdev2 ethernet device
|
||||
*
|
||||
* @param[in] gnrc_netdev2 gnrc_netdev2 struct to initialize
|
||||
* @param[in] dev netdev2 device to handle
|
||||
*
|
||||
* @return 1 on success
|
||||
* @return <=0 on error
|
||||
*/
|
||||
int gnrc_netdev2_eth_init(gnrc_netdev2_t *gnrc_netdev2, netdev2_t *dev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GNRC_NETDEV2_ETH_H */
|
||||
/** @} */
|
@ -1,3 +1,3 @@
|
||||
MODULE = gnrc_netdev_eth
|
||||
MODULE = gnrc_netdev2
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Freie Universität Berlin
|
||||
* 2015 Kaspar Schleiser <kaspar@schleiser.de>
|
||||
*
|
||||
* 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
|
||||
* @file
|
||||
* @brief Glue for netdev2 devices to netapi
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "kernel.h"
|
||||
#include "msg.h"
|
||||
#include "thread.h"
|
||||
|
||||
#include "net/gnrc.h"
|
||||
#include "net/gnrc/nettype.h"
|
||||
#include "net/netdev2.h"
|
||||
|
||||
#include "net/gnrc/gnrc_netdev2.h"
|
||||
#include "net/ethernet/hdr.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
#if defined(MODULE_OD) && ENABLE_DEBUG
|
||||
#include "od.h"
|
||||
#endif
|
||||
|
||||
#define NETDEV2_NETAPI_MSG_QUEUE_SIZE 8
|
||||
|
||||
static void _pass_on_packet(gnrc_pktsnip_t *pkt);
|
||||
|
||||
/**
|
||||
* @brief Function called by the device driver on device events
|
||||
*
|
||||
* @param[in] event type of event
|
||||
* @param[in] data optional parameter
|
||||
*/
|
||||
static void _event_cb(netdev2_t *dev, netdev2_event_t event, void *data)
|
||||
{
|
||||
(void) data;
|
||||
gnrc_netdev2_t *gnrc_netdev2 = (gnrc_netdev2_t*) dev->isr_arg;
|
||||
|
||||
if (event == NETDEV2_EVENT_ISR) {
|
||||
msg_t msg;
|
||||
|
||||
msg.type = NETDEV2_MSG_TYPE_EVENT;
|
||||
msg.content.ptr = (void*) gnrc_netdev2;
|
||||
|
||||
if (msg_send(&msg, gnrc_netdev2->pid) <= 0) {
|
||||
puts("gnrc_netdev2: possibly lost interrupt.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
DEBUG("gnrc_netdev2: event triggered -> %i\n", event);
|
||||
switch(event) {
|
||||
case NETDEV2_EVENT_RX_COMPLETE:
|
||||
{
|
||||
gnrc_pktsnip_t *pkt = gnrc_netdev2->recv(gnrc_netdev2);
|
||||
|
||||
if (pkt) {
|
||||
_pass_on_packet(pkt);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
DEBUG("gnrc_netdev2: warning: unhandled event %u.\n", event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void _pass_on_packet(gnrc_pktsnip_t *pkt)
|
||||
{
|
||||
gnrc_netreg_entry_t *sendto;
|
||||
|
||||
/* find out, who to send the packet to */
|
||||
sendto = gnrc_netreg_lookup(pkt->type, GNRC_NETREG_DEMUX_CTX_ALL);
|
||||
|
||||
/* throw away packet if no one is interested */
|
||||
if (sendto == NULL) {
|
||||
DEBUG("gnrc_netdev2: unable to forward packet of type %i\n", pkt->type);
|
||||
gnrc_pktbuf_release(pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
/* send the packet to everyone interested in it's type */
|
||||
gnrc_pktbuf_hold(pkt, gnrc_netreg_num(pkt->type, GNRC_NETREG_DEMUX_CTX_ALL) - 1);
|
||||
while (sendto != NULL) {
|
||||
DEBUG("gnrc_netdev2: sending pkt %p to PID %u\n", (void*)pkt, sendto->pid);
|
||||
gnrc_netapi_receive(sendto->pid, pkt);
|
||||
sendto = gnrc_netreg_getnext(sendto);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Startup code and event loop of the gnrc_netdev2 layer
|
||||
*
|
||||
* @param[in] args expects a pointer to the underlying netdev device
|
||||
*
|
||||
* @return never returns
|
||||
*/
|
||||
static void *_gnrc_netdev2_thread(void *args)
|
||||
{
|
||||
DEBUG("gnrc_netdev2: starting thread\n");
|
||||
|
||||
gnrc_netdev2_t *gnrc_netdev2 = (gnrc_netdev2_t*) args;
|
||||
netdev2_t *dev = gnrc_netdev2->dev;
|
||||
|
||||
gnrc_netdev2->pid = thread_getpid();
|
||||
|
||||
gnrc_netapi_opt_t *opt;
|
||||
int res;
|
||||
msg_t msg, reply, msg_queue[NETDEV2_NETAPI_MSG_QUEUE_SIZE];
|
||||
|
||||
/* setup the MAC layers message queue */
|
||||
msg_init_queue(msg_queue, NETDEV2_NETAPI_MSG_QUEUE_SIZE);
|
||||
|
||||
/* register the event callback with the device driver */
|
||||
dev->event_callback = _event_cb;
|
||||
dev->isr_arg = (void*) gnrc_netdev2;
|
||||
|
||||
/* register the device to the network stack*/
|
||||
gnrc_netif_add(thread_getpid()); |