mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
218 lines
5.4 KiB
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));
|
|
}
|
|
|
|
/** @} */
|