1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/pkg/emb6/contrib/netdev/emb6_netdev.c

218 lines
5.4 KiB
C

/*
* Copyright (C) 2016 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.
*/
/**
* @{
*
* @file
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
*/
#include <assert.h>
#include <stdint.h>
#include <sys/uio.h>
#include "msg.h"
#include "net/netdev.h"
#include "evproc.h"
#include "emb6.h"
#include "linkaddr.h"
#include "packetbuf.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
extern uip_lladdr_t uip_lladdr;
static netdev_t *_dev = NULL;
static s_nsLowMac_t *_lowmac = NULL;
static int8_t _rssi_base_value = -100;
static uint8_t _last_rssi;
static int8_t _netdev_init(s_ns_t *p_ns);
static int8_t _netdev_send(const void *pr_payload, uint8_t c_len);
static int8_t _netdev_on(void);
static int8_t _netdev_off(void);
static void _netdev_set_txpower(int8_t power);
static int8_t _netdev_get_txpower(void);
static void _netdev_set_sensitivity(int8_t sens);
static int8_t _netdev_get_sensitivity(void);
static int8_t _netdev_get_rssi(void);
static void _netdev_set_promisc(uint8_t c_on_off);
const s_nsIf_t emb6_netdev_driver = {
.name = "netdev",
.init = &_netdev_init,
.send = &_netdev_send,
.on = &_netdev_on,
.off = &_netdev_off,
.set_txpower = &_netdev_set_txpower,
.get_txpower = &_netdev_get_txpower,
.set_sensitivity = &_netdev_set_sensitivity,
.get_sensitivity = &_netdev_get_sensitivity,
.get_rssi = &_netdev_get_rssi,
.ant_div = NULL,
.ant_rf_switch = NULL,
.set_promisc = &_netdev_set_promisc,
};
static void _get_recv_pkt(void)
{
char *dataptr;
struct netdev_radio_rx_info rx_info;
int8_t len;
packetbuf_clear();
dataptr = packetbuf_dataptr();
len = _dev->driver->recv(_dev, dataptr, PACKETBUF_SIZE, &rx_info);
_last_rssi = rx_info.rssi;
if ((len > 0) && (_lowmac != NULL)) {
packetbuf_set_datalen(len);
_lowmac->input();
}
}
static void _event_cb(netdev_t *dev, netdev_event_t event)
{
if (event == NETDEV_EVENT_ISR) {
/* EVENT_TYPE_PCK_LL is supposed to be used by drivers, so use it
* (though NETDEV_EVENT_ISR technically doesn't only signify
* incoming packets) */
evproc_putEvent(E_EVPROC_HEAD, EVENT_TYPE_PCK_LL, NULL);
}
else {
switch (event) {
case NETDEV_EVENT_RX_COMPLETE: {
_get_recv_pkt();
}
break;
default:
break;
}
}
}
static void _emb6_netdev_callback(c_event_t c_event, p_data_t p_data)
{
(void)p_data;
if (c_event == EVENT_TYPE_PCK_LL) {
_dev->driver->isr(_dev);
}
}
static void _configure_netdev(void)
{
/* Enable RX-complete interrupts */
static const netopt_enable_t enable = NETOPT_ENABLE;
int res = _dev->driver->set(_dev, NETOPT_RX_END_IRQ, &enable, sizeof(enable));
if (res < 0) {
DEBUG("emb6: enable NETOPT_RX_END_IRQ failed: %d\n", res);
}
}
int emb6_netdev_setup(netdev_t *dev)
{
if (_dev == NULL) {
_dev = dev;
return 0;
}
return -1;
}
static int8_t _netdev_init(s_ns_t *p_ns)
{
if ((_dev != NULL) && (p_ns != NULL) && (p_ns->lmac != NULL)) {
_dev->event_callback = _event_cb;
_dev->driver->get(_dev, NETOPT_ADDRESS_LONG, &mac_phy_config.mac_address,
sizeof(mac_phy_config.mac_address));
memcpy(&uip_lladdr, mac_phy_config.mac_address,
sizeof(mac_phy_config.mac_address));
_dev->driver->get(_dev, NETOPT_NID, &mac_phy_config.pan_id,
sizeof(mac_phy_config.pan_id));
_configure_netdev();
linkaddr_set_node_addr((linkaddr_t *)&uip_lladdr);
_lowmac = p_ns->lmac;
evproc_regCallback(EVENT_TYPE_PCK_LL, _emb6_netdev_callback);
return 1;
}
return 0;
}
static int8_t _netdev_send(const void *pr_payload, uint8_t c_len)
{
if (_dev != NULL) {
iolist_t iolist = {
.iol_base = (void *)pr_payload,
.iol_len = c_len,
};
if (_dev->driver->send(_dev, &iolist) < 0) {
DEBUG("Error on send\n");
return RADIO_TX_ERR;
}
DEBUG("Packet of length %u was transmitted\n", (unsigned)c_len);
return RADIO_TX_OK;
}
DEBUG("Device was not initialized\n");
return RADIO_TX_ERR;
}
static int8_t _netdev_on(void)
{
/* TODO: turn netdev on */
return 1;
}
static int8_t _netdev_off(void)
{
/* TODO: turn netdev off */
return 1;
}
static void _netdev_set_txpower(int8_t power)
{
int16_t pwr = power;
_dev->driver->set(_dev, NETOPT_TX_POWER, &pwr, sizeof(pwr));
}
static int8_t _netdev_get_txpower(void)
{
int16_t power = 0;
_dev->driver->get(_dev, NETOPT_TX_POWER, &power, sizeof(power));
return (int8_t)power;
}
static void _netdev_set_sensitivity(int8_t sens)
{
/* TODO: set sensitivity */
}
static int8_t _netdev_get_sensitivity(void)
{
/* TODO: get sensitivity */
return 0;
}
static int8_t _netdev_get_rssi(void)
{
return (int8_t)(_rssi_base_value + 1.03 * _last_rssi);
}
static void _netdev_set_promisc(uint8_t c_on_off)
{
netopt_enable_t en = (c_on_off) ? NETOPT_ENABLE : NETOPT_DISABLE;
_dev->driver->set(_dev, NETOPT_PROMISCUOUSMODE, &en, sizeof(en));
}
/** @} */