
21 changed files with 1630 additions and 9 deletions
@ -0,0 +1,32 @@
|
||||
PKG_NAME=openthread
|
||||
PKG_URL=https://github.com/openthread/openthread.git
|
||||
PKG_VERSION=fbfd76a990b81f007957e1bd774e51bce742e53e
|
||||
PKG_BUILDDIR ?= $(BINDIRBASE)/pkg/$(BOARD)/$(PKG_NAME)
|
||||
|
||||
$(info Compile OpenThread for FTD device) |
||||
OPENTHREAD_ARGS+= --enable-cli-app=ftd --enable-application-coap
|
||||
|
||||
$(info $$OPENTHREAD_ARGS is [${OPENTHREAD_ARGS}]) |
||||
|
||||
.PHONY: all |
||||
|
||||
OPENTHREAD_COMMON_FLAGS=-fdata-sections -ffunction-sections -Os
|
||||
all: git-download |
||||
cd $(PKG_BUILDDIR) && PREFIX="/" ./bootstrap
|
||||
cd $(PKG_BUILDDIR) && CPP="$(CPP)" CC="$(CC)" CXX="$(CXX)"\
|
||||
OBJC="" OBJCXX="" AR="$(AR)" RANLIB="$(RANLIB)" NM="$(NM)" \
|
||||
STRIP="$(STRIP)" \
|
||||
CPPFLAGS="$(OPENTHREAD_COMMON_FLAGS) $(CFLAGS_CPU) " \
|
||||
CFLAGS="$(OPENTHREAD_COMMON_FLAGS) $(CFLAGS_CPU) " \
|
||||
CXXFLAGS="$(OPENTHREAD_COMMON_FLAGS) $(CFLAGS_CPU) -fno-exceptions -fno-rtti " \
|
||||
LDFLAGS="$(OPENTHREAD_COMMON_FLAGS) $(CFLAGS_CPU) -nostartfiles -specs=nano.specs \
|
||||
-specs=nosys.specs -Wl,--gc-sections -Wl,-Map=map.map " \
|
||||
./configure --disable-docs --host=$(TARGET_ARCH) --target=$(TARGET_ARCH) \
|
||||
--prefix=/ --enable-default-logging ${OPENTHREAD_ARGS}
|
||||
cd $(PKG_BUILDDIR) && DESTDIR=$(PKG_BUILDDIR)/output PREFIX=/ make -j4 --no-print-directory install
|
||||
|
||||
cp $(PKG_BUILDDIR)/output/lib/libmbedcrypto.a ${BINDIR}/libmbedcrypto.a
|
||||
cp $(PKG_BUILDDIR)/output/lib/libopenthread-ftd.a ${BINDIR}/libopenthread.a
|
||||
cp $(PKG_BUILDDIR)/output/lib/libopenthread-cli-ftd.a ${BINDIR}/libopenthread-cli.a
|
||||
sed -ie 's/BASE/_BASE/g' $(PKG_BUILDDIR)/output/include/openthread/types.h
|
||||
include $(RIOTBASE)/pkg/pkg.mk |
@ -0,0 +1,11 @@
|
||||
OPENTHREAD_DIR = $(RIOTBASE)/pkg/openthread
|
||||
|
||||
INCLUDES += -I$(OPENTHREAD_DIR)/include \
|
||||
-I$(OPENTHREAD_DIR)/include/openthread \
|
||||
-I$(BINDIRBASE)/pkg/$(BOARD)/openthread/output/include \
|
||||
-I$(BINDIRBASE)/pkg/$(BOARD)/openthread/include/openthread \
|
||||
|
||||
ifneq (,$(filter openthread_contrib,$(USEMODULE))) |
||||
DIRS += $(OPENTHREAD_DIR)/contrib
|
||||
DIRS += $(OPENTHREAD_DIR)/contrib/netdev
|
||||
endif |
@ -0,0 +1,3 @@
|
||||
MODULE := openthread_contrib
|
||||
|
||||
include $(RIOTBASE)/Makefile.base |
@ -0,0 +1,3 @@
|
||||
MODULE := openthread_contrib_netdev
|
||||
|
||||
include $(RIOTBASE)/Makefile.base |
@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Fundacion Inria Chile |
||||
* |
||||
* 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 Netdev adoption for OpenThread |
||||
* |
||||
* @author Jose Ignacio Alamos <jialamos@uc.cl> |
||||
* @} |
||||
*/ |
||||
|
||||
#include <assert.h> |
||||
#include <errno.h> |
||||
#include <string.h> |
||||
#include "msg.h" |
||||
#include "openthread/cli.h" |
||||
#include "openthread/instance.h" |
||||
#include "openthread/ip6.h" |
||||
#include "openthread/platform/alarm.h" |
||||
#include "openthread/platform/uart.h" |
||||
#include "openthread/tasklet.h" |
||||
#include "openthread/thread.h" |
||||
#include "random.h" |
||||
#include "ot.h" |
||||
|
||||
#define ENABLE_DEBUG (0) |
||||
#include "debug.h" |
||||
|
||||
#define OPENTHREAD_QUEUE_LEN (8) |
||||
static msg_t _queue[OPENTHREAD_QUEUE_LEN]; |
||||
|
||||
static kernel_pid_t _pid; |
||||
static otInstance *sInstance; |
||||
|
||||
/**
|
||||
* @name Default configuration for OpenThread network |
||||
* @{ |
||||
*/ |
||||
#ifndef OPENTHREAD_PANID |
||||
#define OPENTHREAD_PANID 0x1234 |
||||
#endif |
||||
#ifndef OPENTHREAD_CHANNEL |
||||
#define OPENTHREAD_CHANNEL (26U) |
||||
#endif |
||||
/** @} */ |
||||
|
||||
uint8_t ot_call_command(char* command, void *arg, void* answer) { |
||||
ot_job_t job; |
||||
|
||||
job.command = command; |
||||
job.arg = arg; |
||||
job.answer = answer; |
||||
|
||||
msg_t msg, reply; |
||||
msg.type = OPENTHREAD_JOB_MSG_TYPE_EVENT; |
||||
msg.content.ptr = &job; |
||||
msg_send_receive(&msg, &reply, openthread_get_pid()); |
||||
return (uint8_t)reply.content.value; |
||||
} |
||||
|
||||
/* OpenThread will call this when switching state from empty tasklet to non-empty tasklet. */ |
||||
void otTaskletsSignalPending(otInstance *aInstance) { |
||||
otTaskletsProcess(aInstance); |
||||
} |
||||
|
||||
static void *_openthread_event_loop(void *arg) { |
||||
_pid = thread_getpid(); |
||||
|
||||
/* enable OpenThread UART */ |
||||
otPlatUartEnable(); |
||||
|
||||
/* init OpenThread */ |
||||
sInstance = otInstanceInit(); |
||||
|
||||
msg_init_queue(_queue, OPENTHREAD_QUEUE_LEN); |
||||
netdev_t *dev; |
||||
msg_t msg, reply; |
||||
|
||||
otCliUartInit(sInstance); |
||||
|
||||
#if OPENTHREAD_ENABLE_DIAG |
||||
diagInit(sInstance); |
||||
#endif |
||||
|
||||
/* Init default parameters */ |
||||
otPanId panid = OPENTHREAD_PANID; |
||||
uint8_t channel = OPENTHREAD_CHANNEL; |
||||
otLinkSetPanId(sInstance, panid); |
||||
otLinkSetChannel(sInstance, channel); |
||||
/* Bring up the IPv6 interface */ |
||||
otIp6SetEnabled(sInstance, true); |
||||
/* Start Thread protocol operation */ |
||||
otThreadSetEnabled(sInstance, true); |
||||
|
||||
uint8_t *buf; |
||||
ot_job_t *job; |
||||
while (1) { |
||||
msg_receive(&msg); |
||||
switch (msg.type) { |
||||
case OPENTHREAD_XTIMER_MSG_TYPE_EVENT: |
||||
/* Tell OpenThread a time event was received */ |
||||
otPlatAlarmFired(sInstance); |
||||
break; |
||||
case OPENTHREAD_NETDEV_MSG_TYPE_EVENT: |
||||
/* Received an event from driver */ |
||||
dev = msg.content.ptr; |
||||
dev->driver->isr(dev); |
||||
break; |
||||
case OPENTHREAD_SERIAL_MSG_TYPE_EVENT: |
||||
/* Tell OpenThread about the reception of a CLI command */ |
||||
buf = msg.content.ptr; |
||||
otPlatUartReceived(buf, strlen((char *) buf)); |
||||
break; |
||||
case OPENTHREAD_JOB_MSG_TYPE_EVENT: |
||||
job = msg.content.ptr; |
||||
reply.content.value = ot_exec_command(sInstance, job->command, job->arg, job->answer); |
||||
msg_reply(&msg, &reply); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return NULL; |
||||
} |
||||
|
||||
static void _event_cb(netdev_t *dev, netdev_event_t event) { |
||||
switch (event) { |
||||
case NETDEV_EVENT_ISR: |
||||
{ |
||||
msg_t msg; |
||||
assert(_pid != KERNEL_PID_UNDEF); |
||||
|
||||
msg.type = OPENTHREAD_NETDEV_MSG_TYPE_EVENT; |
||||
msg.content.ptr = dev; |
||||
|
||||
if (msg_send(&msg, _pid) <= 0) { |
||||
DEBUG("openthread_netdev: possibly lost interrupt.\n"); |
||||
} |
||||
break; |
||||
} |
||||
|
||||
case NETDEV_EVENT_RX_COMPLETE: |
||||
DEBUG("openthread_netdev: Reception of a packet\n"); |
||||
recv_pkt(sInstance, dev); |
||||
break; |
||||
case NETDEV_EVENT_TX_COMPLETE: |
||||
case NETDEV_EVENT_TX_NOACK: |
||||
case NETDEV_EVENT_TX_MEDIUM_BUSY: |
||||
DEBUG("openthread_netdev: Transmission of a packet\n"); |
||||
send_pkt(sInstance, dev, event); |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
} |
||||
|
||||
/* get OpenThread thread pid */ |
||||
kernel_pid_t openthread_get_pid(void) { |
||||
return _pid; |
||||
} |
||||
|
||||
/* starts OpenThread thread */ |
||||
int openthread_netdev_init(char *stack, int stacksize, char priority, |
||||
const char *name, netdev_t *netdev) { |
||||
netdev->driver->init(netdev); |
||||
netdev->event_callback = _event_cb; |
||||
|
||||
netopt_enable_t enable = NETOPT_ENABLE; |
||||
netdev->driver->set(netdev, NETOPT_TX_END_IRQ, &enable, sizeof(enable)); |
||||
|
||||
_pid = thread_create(stack, stacksize, |
||||
priority, THREAD_CREATE_STACKTEST, |
||||
_openthread_event_loop, NULL, name); |
||||
|
||||
if (_pid <= 0) { |
||||
return -EINVAL; |
||||
} |
||||
|
||||
return _pid; |
||||
} |
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Fundacion Inria Chile |
||||
* |
||||
* 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 Implementation of OpenThread main functions |
||||
* |
||||
* @author Jose Ignacio Alamos <jialamos@uc.cl> |
||||
* @} |
||||
*/ |
||||
|
||||
#include <assert.h> |
||||
|
||||
#include "openthread/platform/alarm.h" |
||||
#include "openthread/platform/uart.h" |
||||
#include "ot.h" |
||||
#include "random.h" |
||||
#include "thread.h" |
||||
#include "xtimer.h" |
||||
|
||||
#ifdef MODULE_AT86RF2XX |
||||
#include "at86rf2xx.h" |
||||
#include "at86rf2xx_params.h" |
||||
#endif |
||||
|
||||
#define ENABLE_DEBUG (0) |
||||
#include "debug.h" |
||||
|
||||
#ifdef MODULE_AT86RF2XX /* is mutual exclusive with above ifdef */ |
||||
#define OPENTHREAD_NETIF_NUMOF (sizeof(at86rf2xx_params) / sizeof(at86rf2xx_params[0])) |
||||
#endif |
||||
|
||||
#ifdef MODULE_AT86RF2XX |
||||
static at86rf2xx_t at86rf2xx_dev; |
||||
#endif |
||||
|
||||
#define OPENTHREAD_NETDEV_BUFLEN (ETHERNET_MAX_LEN) |
||||
|
||||
static uint8_t rx_buf[OPENTHREAD_NETDEV_BUFLEN]; |
||||
static uint8_t tx_buf[OPENTHREAD_NETDEV_BUFLEN]; |
||||
static char ot_thread_stack[2 * THREAD_STACKSIZE_MAIN]; |
||||
|
||||
/* init and run OpeanThread's UART simulation (stdio) */ |
||||
void openthread_uart_run(void) |
||||
{ |
||||
char buf[256]; |
||||
msg_t msg; |
||||
|
||||
msg.type = OPENTHREAD_SERIAL_MSG_TYPE_EVENT; |
||||
msg.content.ptr = buf; |
||||
|
||||
buf[1] = 0; |
||||
while (1) { |
||||
char c = getchar(); |
||||
buf[0] = c; |
||||
msg_send(&msg, openthread_get_pid()); |
||||
} |
||||
} |
||||
|
||||
void openthread_bootstrap(void) |
||||
{ |
||||
/* init random */ |
||||
ot_random_init(); |
||||
|
||||
/* setup netdev modules */ |
||||
#ifdef MODULE_AT86RF2XX |
||||
at86rf2xx_setup(&at86rf2xx_dev, &at86rf2xx_params[0]); |
||||
netdev_t *netdev = (netdev_t *) &at86rf2xx_dev; |
||||
#endif |
||||
|
||||
openthread_radio_init(netdev, tx_buf, rx_buf); |
||||
openthread_netdev_init(ot_thread_stack, sizeof(ot_thread_stack), THREAD_PRIORITY_MAIN - 5, "openthread", netdev); |
||||
} |
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Fundacion Inria Chile |
||||
* |
||||
* 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 Implementation of OpenThread alarm platform abstraction |
||||
* |
||||
* @author Jose Ignacio Alamos <jialamos@uc.cl> |
||||
* @} |
||||
*/ |
||||
|
||||
#include <stdint.h> |
||||
|
||||
#include "msg.h" |
||||
#include "openthread/platform/alarm.h" |
||||
#include "ot.h" |
||||
#include "thread.h" |
||||
#include "xtimer.h" |
||||
#include "timex.h" |
||||
|
||||
#define ENABLE_DEBUG (0) |
||||
#include "debug.h" |
||||
|
||||
static xtimer_t ot_timer; |
||||
static msg_t ot_alarm_msg; |
||||
|
||||
/**
|
||||
* Set the alarm to fire at @p aDt milliseconds after @p aT0. |
||||
* |
||||
* @param[in] aInstance The OpenThread instance structure. |
||||
* @param[in] aT0 The reference time. |
||||
* @param[in] aDt The time delay in milliseconds from @p aT0. |
||||
*/ |
||||
void otPlatAlarmStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt) |
||||
{ |
||||
DEBUG("openthread: otPlatAlarmStartAt: aT0: %" PRIu32 ", aDT: %" PRIu32 "\n", aT0, aDt); |
||||
ot_alarm_msg.type = OPENTHREAD_XTIMER_MSG_TYPE_EVENT; |
||||
|
||||
if (aDt == 0) { |
||||
msg_send(&ot_alarm_msg, thread_getpid()); |
||||
} |
||||
else { |
||||
int dt = aDt * US_PER_MS; |
||||
xtimer_set_msg(&ot_timer, dt, &ot_alarm_msg, thread_getpid()); |
||||
} |
||||
} |
||||
|
||||
/* OpenThread will call this to stop alarms */ |
||||
void otPlatAlarmStop(otInstance *aInstance) |
||||
{ |
||||
DEBUG("openthread: otPlatAlarmStop\n"); |
||||
xtimer_remove(&ot_timer); |
||||
} |
||||
|
||||
/* OpenThread will call this for getting running time in millisecs */ |
||||
uint32_t otPlatAlarmGetNow(void) |
||||
{ |
||||
uint32_t now = xtimer_now_usec() / US_PER_MS; |
||||
DEBUG("openthread: otPlatAlarmGetNow: %" PRIu32 "\n", now); |
||||
return now; |
||||
} |
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Fundacion Inria Chile |
||||
* |
||||
* 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 Implementation of OpenThread diagnostics platform abstraction |
||||
* |
||||
* @author Jose Ignacio Alamos <jialamos@uc.cl> |
||||
* @} |
||||
*/ |
||||
|
||||
#include <stdbool.h> |
||||
#include <stdio.h> |
||||
|
||||
static bool sDiagMode = false; |
||||
|
||||
void otPlatDiagProcess(int argc, char *argv[], char *aOutput, size_t aOutputMaxLen) |
||||
{ |
||||
/* add more plarform specific diagnostics features here */ |
||||
(void)argc; |
||||
} |
||||
|
||||
void otPlatDiagModeSet(bool aMode) |
||||
{ |
||||
sDiagMode = aMode; |
||||
} |
||||
|
||||
bool otPlatDiagModeGet(void) |
||||
{ |
||||
return sDiagMode; |
||||
} |
@ -0,0 +1,297 @@
|
||||
/*
|
||||
* Copyright (C) |
||||
* |
||||
* 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 Implementation of OpenThread functions wrapper. They are used to call OT functions from OT thread |
||||
* |
||||
* @author Jose Ignacio Alamos <jialamos@inria.cl> |
||||
* @author Baptiste CLENET <bapclenet@gmail.com> |
||||
* @} |
||||
*/ |
||||
|
||||
#include <stdint.h> |
||||
#include <stdio.h> |
||||
#include "thread.h" |
||||
#include "openthread/ip6.h" |
||||
#include "openthread/thread.h" |
||||
#include "openthread/udp.h" |
||||
#include "ot.h" |
||||
|
||||
#define ENABLE_DEBUG (0) |
||||
#include "debug.h" |
||||
|
||||
typedef uint8_t OT_COMMAND; |
||||
|
||||
OT_COMMAND ot_channel(otInstance* ot_instance, void* arg, void* answer); |
||||
OT_COMMAND ot_eui64(otInstance* ot_instance, void* arg, void* answer); |
||||
OT_COMMAND ot_extaddr(otInstance* ot_instance, void* arg, void* answer); |
||||
OT_COMMAND ot_ipaddr(otInstance* ot_instance, void* arg, void* answer); |
||||
OT_COMMAND ot_masterkey(otInstance* ot_instance, void* arg, void* answer); |
||||
OT_COMMAND ot_networkname(otInstance* ot_instance, void* arg, void* answer); |
||||
OT_COMMAND ot_mode(otInstance* ot_instance, void* arg, void* answer); |
||||
OT_COMMAND ot_panid(otInstance* ot_instance, void* arg, void* answer); |
||||
OT_COMMAND ot_parent(otInstance* ot_instance, void* arg, void* answer); |
||||
OT_COMMAND ot_state(otInstance* ot_instance, void* arg, void* answer); |
||||
OT_COMMAND ot_thread(otInstance* ot_instance, void* arg, void* answer); |
||||
|
||||
/**
|
||||
* @brief Struct containing an OpenThread job command |
||||
*/ |
||||
typedef struct { |
||||
const char *name; /**< A pointer to the job name string. */ |
||||
OT_COMMAND (*function)(otInstance*, void*, void*); /**< function to be called */ |
||||
} ot_command_t; |
||||
|
||||
const ot_command_t otCommands[] = |
||||
{ |
||||
/* channel: arg NULL: get channel in answer | arg not NULL: set channel */ |
||||
{ "channel", &ot_channel }, |
||||
/* eui64 : arg NULL: get eui64 in answer | arg not NULL: set eui64 */ |
||||
{ "eui64", &ot_eui64 }, |
||||
/* extaddr: arg NULL: get extaddr in answer | arg not NULL: set extaddr */ |
||||
{ "extaddr", &ot_extaddr }, |
||||
/* ipaddr: arg NULL: get nb ipaddr in answer | arg not NULL: get ipaddr[arg] */ |
||||
{ "ipaddr", &ot_ipaddr }, |
||||
/* masterkey: arg NULL: get masterkey in answer | arg not NULL: set masterkey */ |
||||
{ "masterkey", &ot_masterkey }, |
||||
/* mode: arg NULL: get mode in answer | arg not NULL: set mode */ |
||||
{ "mode", ot_mode }, |
||||
/* networkname: arg NULL: get networkname in answer | arg not NULL: set networkname */ |
||||
{ "networkname", &ot_networkname }, |
||||
/* panid: arg NULL: get panid in answer | arg not NULL: set panid */ |
||||
{ "panid", &ot_panid }, |
||||
/* parent: arg NULL: get parent in answer */ |
||||
{ "parent", &ot_parent }, |
||||
/* state: arg NULL: get state in answer */ |
||||
{ "state", &ot_state }, |
||||
/* thread: arg "start"/"stop": start/stop thread operation */ |
||||
{ "thread", &ot_thread }, |
||||
}; |
||||
|
||||
uint8_t ot_exec_command(otInstance *ot_instance, const char* command, void *arg, void* answer) { |
||||
uint8_t res = 0xFF; |
||||
/* Check running thread */ |
||||
if (openthread_get_pid() == thread_getpid()) { |
||||
for (uint8_t i = 0; i < sizeof(otCommands) / sizeof(otCommands[0]); i++) { |
||||
if (strcmp(command, otCommands[i].name) == 0) { |
||||
res = (*otCommands[i].function)(ot_instance, arg, answer); |
||||
break; |
||||
} |
||||
} |
||||
if (res == 0xFF) { |
||||
DEBUG("Wrong ot_COMMAND name\n"); |
||||
res = 1; |
||||
} |
||||
} else { |
||||
DEBUG("ERROR: ot_exec_job needs to run in OpenThread thread\n"); |
||||
} |
||||
return res; |
||||
} |
||||
|
||||
void output_bytes(const char* name, const uint8_t *aBytes, uint8_t aLength) |
||||
{ |
||||
DEBUG("%s: ", name); |
||||
for (int i = 0; i < aLength; i++) { |
||||
DEBUG("%02x", aBytes[i]); |
||||
} |
||||
DEBUG("\n"); |
||||
} |
||||
|
||||
OT_COMMAND ot_channel(otInstance* ot_instance, void* arg, void* answer) { |
||||
if (answer != NULL) { |
||||
*((uint8_t *) answer) = otLinkGetChannel(ot_instance); |
||||
DEBUG("Channel: %04x\n", *((uint8_t *) answer)); |
||||
} else if (arg != NULL) { |
||||
uint8_t channel = *((uint8_t *) arg); |
||||
otLinkSetChannel(ot_instance, channel); |
||||
} else { |
||||
DEBUG("ERROR: wrong argument\n"); |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
OT_COMMAND ot_eui64(otInstance* ot_instance, void* arg, void* answer) { |
||||
if (answer != NULL) { |
||||
otExtAddress address; |
||||
otLinkGetFactoryAssignedIeeeEui64(ot_instance, &address); |
||||
output_bytes("eui64", address.m8, OT_EXT_ADDRESS_SIZE); |
||||
*((otExtAddress *) answer) = address; |
||||
} else { |
||||
DEBUG("ERROR: wrong argument\n"); |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
|
||||
OT_COMMAND ot_extaddr(otInstance* ot_instance, void* arg, void* answer) { |
||||
if (answer != NULL) { |
||||
answer = (void*)otLinkGetExtendedAddress(ot_instance); |
||||
output_bytes("extaddr", (const uint8_t *)answer, OT_EXT_ADDRESS_SIZE); |
||||
} else { |
||||
DEBUG("ERROR: wrong argument\n"); |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
OT_COMMAND ot_ipaddr(otInstance* ot_instance, void* arg, void* answer) { |
||||
uint8_t cnt = 0; |
||||
for (const otNetifAddress *addr = otIp6GetUnicastAddresses(ot_instance); addr; addr = addr->mNext) { |
||||
if (arg != NULL && answer != NULL && cnt == *((uint8_t *) arg)) { |
||||
*((otNetifAddress *) answer) = *addr; |
||||
return 0; |
||||
} |
||||
cnt++; |
||||
} |
||||
if (answer != NULL) { |
||||
*((uint8_t *) answer) = cnt; |
||||
} else { |
||||
DEBUG("ERROR: wrong argument\n"); |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
OT_COMMAND ot_masterkey(otInstance* ot_instance, void* arg, void* answer) { |
||||
if (answer != NULL) { |
||||
const otMasterKey* masterkey = otThreadGetMasterKey(ot_instance); |
||||
*((otMasterKey *) answer) = *masterkey; |
||||
output_bytes("masterkey", (const uint8_t *)answer, OT_MASTER_KEY_SIZE); |
||||
} else if (arg != NULL) { |
||||
otThreadSetMasterKey(ot_instance, (otMasterKey*)arg); |
||||
} else { |
||||
DEBUG("ERROR: wrong argument\n"); |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
OT_COMMAND ot_mode(otInstance* ot_instance, void* arg, void* answer) { |
||||
if (arg != NULL) { |
||||
otLinkModeConfig link_mode; |
||||
memset(&link_mode, 0, sizeof(otLinkModeConfig)); |
||||
char mode[6]; |
||||
memcpy(mode, (char*)arg, 5); |
||||
mode[5] = '\0'; |
||||
for (char *arg = &mode[0]; *arg != '\0'; arg++) { |
||||
switch (*arg) { |
||||
case 'r': |
||||
link_mode.mRxOnWhenIdle = 1; |
||||
break; |
||||
case 's': |
||||
link_mode.mSecureDataRequests = 1; |
||||
break; |
||||
case 'd': |
||||
link_mode.mDeviceType = 1; |
||||
break; |
||||
case 'n': |
||||
link_mode.mNetworkData = 1; |
||||
break; |
||||
} |
||||
} |
||||
otThreadSetLinkMode(ot_instance, link_mode); |
||||
DEBUG("OT mode changed to %s\n", (char*)arg); |
||||
} else { |
||||
DEBUG("ERROR: wrong argument\n"); |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
OT_COMMAND ot_networkname(otInstance* ot_instance, void* arg, void* answer) { |
||||
if (answer != NULL) { |
||||
const char* networkName = otThreadGetNetworkName(ot_instance); |
||||
strcpy((char*) answer, networkName); |
||||
DEBUG("networkname: %.*s\n", OT_NETWORK_NAME_MAX_SIZE, networkName); |
||||
} else if (arg != NULL) { |
||||
otThreadSetNetworkName(ot_instance, (char*) arg); |
||||
} else { |
||||
DEBUG("ERROR: wrong argument\n"); |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
|
||||
OT_COMMAND ot_panid(otInstance* ot_instance, void* arg, void* answer) { |
||||
if (answer != NULL) { |
||||
*((uint16_t *) answer) = otLinkGetPanId(ot_instance); |
||||
DEBUG("PanID: %04x\n", *((uint16_t *) answer)); |
||||
} else if (arg != NULL) { |
||||
/* Thread operation needs to be stopped before setting panid */ |
||||
otThreadSetEnabled(ot_instance, false); |
||||
uint16_t panid = *((uint16_t *) arg); |
||||
otLinkSetPanId(ot_instance, panid); |
||||
otThreadSetEnabled(ot_instance, true); |
||||
} else { |
||||
DEBUG("ERROR: wrong argument\n"); |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
OT_COMMAND ot_parent(otInstance* ot_instance, void* arg, void* answer) { |
||||
if (answer != NULL) { |
||||
otRouterInfo parentInfo; |
||||
otThreadGetParentInfo(ot_instance, &parentInfo); |
||||
output_bytes("parent", (const uint8_t *)parentInfo.mExtAddress.m8, sizeof(parentInfo.mExtAddress)); |
||||
DEBUG("Rloc: %x\n", parentInfo.mRloc16); |
||||
*((otRouterInfo *) answer) = parentInfo; |
||||
} else { |
||||
DEBUG("ERROR: wrong argument\n"); |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
OT_COMMAND ot_state(otInstance* ot_instance, void* arg, void* answer) { |
||||
if (answer != NULL) { |
||||
uint8_t state = otThreadGetDeviceRole(ot_instance); |
||||
*((uint8_t *) answer) = state; |
||||
DEBUG("state: "); |
||||
switch (state) { |
||||
case kDeviceRoleOffline: |
||||
puts("offline"); |
||||
break; |
||||
case kDeviceRoleDisabled: |
||||
puts("disabled"); |
||||
break; |
||||
case kDeviceRoleDetached: |
||||
puts("detached"); |
||||
break; |
||||
case kDeviceRoleChild: |
||||
puts("child"); |
||||
break; |
||||
case kDeviceRoleRouter: |
||||
puts("router"); |
||||
break; |
||||
case kDeviceRoleLeader: |
||||
puts("leader"); |
||||
break; |
||||
default: |
||||
puts("invalid state"); |
||||
break; |
||||
} |
||||
} else { |
||||
DEBUG("ERROR: wrong argument\n"); |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
OT_COMMAND ot_thread(otInstance* ot_instance, void* arg, void* answer) { |
||||
if (arg != NULL) { |
||||
if (strcmp((char*)arg, "start") == 0) { |
||||
otThreadSetEnabled(ot_instance, true); |
||||
DEBUG("Thread start\n"); |
||||
} else if (strcmp((char*)arg, "stop") == 0) { |
||||
otThreadSetEnabled(ot_instance, false); |
||||
DEBUG("Thread stop\n"); |
||||
} else { |
||||
DEBUG("ERROR: thread available args: start/stop\n"); |
||||
} |
||||
} else { |
||||
DEBUG("ERROR: wrong argument\n"); |
||||
} |
||||
return 0; |
||||
} |
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Fundacion Inria Chile |
||||
* |
||||
* 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 Implementation of OpenThread logging platform abstraction |
||||
* |
||||
* @author Jose Ignacio Alamos <jialamos@uc.cl> |
||||
* @} |
||||
*/ |
||||
|
||||
#include <ctype.h> |
||||
#include <inttypes.h> |
||||
#include <stdarg.h> |
||||
#include <stdio.h> |
||||
#include <stdint.h> |
||||
#include <string.h> |
||||
#include <time.h> |
||||
|
||||
#include "openthread/platform/logging.h" |
||||
|
||||
/* adapted from OpenThread posix example:
|
||||
* See: https://github.com/openthread/openthread/blob/master/examples/platforms/posix/logging.c */
|
||||
void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...) |
||||
{ |
||||
va_list args; |
||||
|
||||
switch (aLogLevel) { |
||||
case kLogLevelNone: |
||||
fprintf(stderr, "NONE "); |
||||
break; |
||||
|
||||
case kLogLevelCrit: |
||||
fprintf(stderr, "CRIT "); |
||||
break; |
||||
|
||||
case kLogLevelWarn: |
||||
fprintf(stderr, "WARN "); |
||||
break; |
||||
|
||||
case kLogLevelInfo: |
||||
fprintf(stderr, "INFO "); |
||||
break; |
||||
|
||||
case kLogLevelDebg: |
||||
fprintf(stderr, "DEBG "); |
||||
break; |
||||
} |
||||
|
||||
switch (aLogRegion) { |
||||
case kLogRegionApi: |
||||
fprintf(stderr, "API "); |
||||
break; |
||||
|
||||
case kLogRegionMle: |
||||
fprintf(stderr, "MLE "); |
||||
break; |
||||
|
||||
case kLogRegionArp: |
||||
fprintf(stderr, "ARP "); |
||||
break; |
||||
|
||||
case kLogRegionNetData: |
||||
fprintf(stderr, "NETD "); |
||||
break; |
||||
|
||||
case kLogRegionIp6: |
||||
fprintf(stderr, "IPV6 "); |
||||
break; |
||||
|
||||
case kLogRegionIcmp: |
||||
fprintf(stderr, "ICMP "); |
||||
break; |
||||
|
||||
case kLogRegionMac: |
||||
fprintf(stderr, "MAC "); |
||||
break; |
||||
|
||||
case kLogRegionMem: |
||||
fprintf(stderr, "MEM "); |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
|
||||
va_start(args, aFormat); |
||||
vfprintf(stderr, aFormat, args); |
||||
fprintf(stderr, "\r"); |
||||
va_end(args); |
||||
} |
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) Baptiste Clenet |
||||
* |
||||
* 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 Implementation of OpenThread misc platform abstraction |
||||
* |
||||
* @author Baptiste Clenet <bapclenet@gmail.com> |
||||
* @} |
||||
*/ |
||||
|
||||
|
||||
#include "openthread/types.h" |
||||
#include "openthread/platform/misc.h" |
||||
#include "periph/pm.h" |
||||
|
||||
void otPlatReset(otInstance *aInstance) |
||||
{ |
||||
(void)aInstance; |
||||
printf("reboot...\n"); |
||||
pm_reboot(); |
||||
} |
||||
|
||||
otPlatResetReason otPlatGetResetReason(otInstance *aInstance) |
||||
{ |
||||
(void)aInstance; |
||||
/* TODO: Write me! */ |
||||
return kPlatResetReason_PowerOn; |
||||
} |
@ -0,0 +1,422 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Fundacion Inria Chile |
||||
* |
||||
* 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 Implementation of OpenThread radio platform abstraction |
||||
* |
||||
* @author Jose Ignacio Alamos <jialamos@uc.cl> |
||||
* @} |
||||
*/ |
||||
|
||||
#include <assert.h> |
||||
#include <stdio.h> |
||||
#include <string.h> |
||||
|
||||
#include "byteorder.h" |
||||
#include "errno.h" |
||||
#include "net/ethernet/hdr.h" |
||||
#include "net/ethertype.h" |
||||
#include "net/ieee802154.h" |
||||
#include "net/netdev/ieee802154.h" |
||||
#include "openthread/platform/radio.h" |
||||
#include "ot.h" |
||||
|
||||
#define ENABLE_DEBUG (0) |
||||
#include "debug.h" |
||||
|
||||
#define RADIO_IEEE802154_FCS_LEN (2U) |
||||
|
||||
static RadioPacket sTransmitFrame; |
||||
static RadioPacket sReceiveFrame; |
||||
static int8_t Rssi; |
||||
|
||||
static netdev_t *_dev; |
||||
|
||||
static bool sDisabled; |
||||
|
||||
/* set 15.4 channel */ |
||||
static int _set_channel(uint16_t channel) |
||||
{ |
||||
return _dev->driver->set(_dev, NETOPT_CHANNEL, &channel, sizeof(uint16_t)); |
||||
} |
||||
|
||||
/*get transmission power from driver */ |
||||
static int16_t _get_power(void) |
||||
{ |
||||
int16_t power; |
||||
|
||||
_dev->driver->get(_dev, NETOPT_TX_POWER, &power, sizeof(int16_t)); |
||||
return power; |
||||
} |
||||
|
||||
/* set transmission power */ |
||||
static int _set_power(int16_t power) |
||||
{ |
||||
return _dev->driver->set(_dev, NETOPT_TX_POWER, &power, sizeof(int16_t)); |
||||
} |
||||
|
||||
/* set IEEE802.15.4 PAN ID */ |
||||
static int _set_panid(uint16_t panid) |
||||
{ |
||||
return _dev->driver->set(_dev, NETOPT_NID, &panid, sizeof(uint16_t)); |
||||
} |
||||
|
||||
/* set extended HW address */ |
||||
static int _set_long_addr(uint8_t *ext_addr) |
||||
{ |
||||
return _dev->driver->set(_dev, NETOPT_ADDRESS_LONG, ext_addr, IEEE802154_LONG_ADDRESS_LEN); |
||||
} |
||||
|
||||
/* set short address */ |
||||
static int _set_addr(uint16_t addr) |
||||
{ |
||||
return _dev->driver->set(_dev, NETOPT_ADDRESS, &addr, sizeof(uint16_t)); |
||||
} |
||||
|
||||
/* check the state of promiscuous mode */ |
||||
static netopt_enable_t _is_promiscuous(void) |
||||
{ |
||||
netopt_enable_t en; |
||||
|
||||
_dev->driver->get(_dev, NETOPT_PROMISCUOUSMODE, &en, sizeof(en)); |
||||
return en == NETOPT_ENABLE ? true : false;; |
||||
} |
||||
|
||||
/* set the state of promiscuous mode */ |
||||
static int _set_promiscuous(netopt_enable_t enable) |
||||
{ |
||||
return _dev->driver->set(_dev, NETOPT_PROMISCUOUSMODE, &enable, sizeof(enable)); |
||||
} |
||||
|
||||
/* wrapper for setting device state */ |
||||
static void _set_state(netopt_state_t state) |
||||
{ |
||||
_dev->driver->set(_dev, NETOPT_STATE, &state, sizeof(netopt_state_t)); |
||||
} |
||||
|
||||
/* wrapper for getting device state */ |
||||
static netopt_state_t _get_state(void) |
||||
{ |
||||
netopt_state_t state; |
||||
_dev->driver->get(_dev, NETOPT_STATE, &state, sizeof(netopt_state_t)); |
||||
return state; |
||||
} |
||||
|
||||
/* sets device state to SLEEP */ |
||||
static void _set_sleep(void) |
||||
{ |
||||
_set_state(NETOPT_STATE_SLEEP); |
||||
} |
||||
|
||||
/* set device state to IDLE */ |
||||
static void _set_idle(void) |
||||
{ |
||||
_set_state(NETOPT_STATE_IDLE); |
||||
} |
||||
|
||||
/* init framebuffers and initial state */ |
||||
void openthread_radio_init(netdev_t *dev, uint8_t *tb, uint8_t *rb) |
||||
{ |
||||
sTransmitFrame.mPsdu = tb; |
||||
sTransmitFrame.mLength = 0; |
||||
sReceiveFrame.mPsdu = rb; |
||||
sReceiveFrame.mLength = 0; |
||||
_dev = dev; |
||||
} |
||||
|
||||
/* Called upon NETDEV_EVENT_RX_COMPLETE event */ |
||||
void recv_pkt(otInstance *aInstance, netdev_t *dev) |
||||
{ |
||||
DEBUG("Openthread: Received pkt\n"); |
||||
netdev_ieee802154_rx_info_t rx_info; |
||||
/* Read frame length from driver */ |
||||
int len = dev->driver->recv(dev, NULL, 0, &rx_info); |
||||
Rssi = rx_info.rssi; |
||||
|
||||
/* very unlikely */ |
||||
if ((len > (unsigned) UINT16_MAX)) { |
||||
DEBUG("Len too high: %d\n", len); |
||||
otPlatRadioReceiveDone(aInstance, NULL, kThreadError_Abort); |
||||
return; |
||||
} |
||||
|
||||
/* Fill OpenThread receive frame */ |
||||
/* Openthread needs a packet length with FCS included,
|
||||
* OpenThread do not use the data so we don't need to calculate FCS */ |
||||
sReceiveFrame.mLength = len + RADIO_IEEE802154_FCS_LEN; |
||||
sReceiveFrame.mPower = _get_power(); |
||||
|
||||
/* Read received frame */ |
||||
int res = dev->driver->recv(dev, (char *) sReceiveFrame.mPsdu, len, NULL); |
||||
|
||||
DEBUG("Received message: len %d\n", (int) sReceiveFrame.mLength); |
||||
for (int i = 0; i < sReceiveFrame.mLength; ++i) { |
||||
DEBUG("%x ", sReceiveFrame.mPsdu[i]); |
||||
} |
||||
DEBUG("\n"); |
||||
|
||||
/* Tell OpenThread that receive has finished */ |
||||
otPlatRadioReceiveDone(aInstance, res > 0 ? &sReceiveFrame : NULL, res > 0 ? kThreadError_None : kThreadError_Abort); |
||||
} |
||||
|
||||
/* Called upon TX event */ |
||||
void send_pkt(otInstance *aInstance, netdev_t *dev, netdev_event_t event) |
||||
{ |
||||
/* Tell OpenThread transmission is done depending on the NETDEV event */ |
||||
switch (event) { |
||||
case NETDEV_EVENT_TX_COMPLETE: |
||||
DEBUG("openthread: NETDEV_EVENT_TX_COMPLETE\n"); |
||||
otPlatRadioTransmitDone(aInstance, &sTransmitFrame, false, kThreadError_None); |
||||
break; |
||||
case NETDEV_EVENT_TX_COMPLETE_DATA_PENDING: |
||||
DEBUG("openthread: NETDEV_EVENT_TX_COMPLETE_DATA_PENDING\n"); |
||||
otPlatRadioTransmitDone(aInstance, &sTransmitFrame, true, kThreadError_None); |
||||
break; |
||||
case NETDEV_EVENT_TX_NOACK: |
||||
DEBUG("openthread: NETDEV_EVENT_TX_NOACK\n"); |
||||
otPlatRadioTransmitDone(aInstance, &sTransmitFrame, false, kThreadError_NoAck); |
||||
break; |
||||
case NETDEV_EVENT_TX_MEDIUM_BUSY: |
||||
DEBUG("openthread: NETDEV_EVENT_TX_MEDIUM_BUSY\n"); |
||||
otPlatRadioTransmitDone(aInstance, &sTransmitFrame, false, kThreadError_ChannelAccessFailure); |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
} |
||||
|
||||
/* OpenThread will call this for setting PAN ID */ |
||||
void otPlatRadioSetPanId(otInstance *aInstance, uint16_t panid) |
||||
{ |
||||
DEBUG("openthread: otPlatRadioSetPanId: setting PAN ID to %04x\n", panid); |
||||
_set_panid(panid); |
||||
} |
||||
|
||||
/* OpenThread will call this for setting extended address */ |
||||
void otPlatRadioSetExtendedAddress(otInstance *aInstance, uint8_t *aExtendedAddress) |
||||
{ |
||||
DEBUG("openthread: otPlatRadioSetExtendedAddress\n"); |
||||
uint8_t reversed_addr[IEEE802154_LONG_ADDRESS_LEN]; |
||||
for (int i = 0; i < IEEE802154_LONG_ADDRESS_LEN; i++) { |
||||
reversed_addr[i] = aExtendedAddress[IEEE802154_LONG_ADDRESS_LEN - 1 - i]; |
||||
} |
||||
_set_long_addr(reversed_addr); |
||||
} |
||||
|
||||
/* OpenThread will call this for setting short address */ |
||||
void otPlatRadioSetShortAddress(otInstance *aInstance, uint16_t aShortAddress) |
||||
{ |
||||
DEBUG("openthread: otPlatRadioSetShortAddress: setting address to %04x\n", aShortAddress); |
||||
_set_addr(((aShortAddress & 0xff) << 8) | ((aShortAddress >> 8) & 0xff)); |
||||
} |
||||
|
||||
/* OpenThread will call this for enabling the radio */ |
||||
ThreadError otPlatRadioEnable(otInstance *aInstance) |
||||
{ |
||||
DEBUG("openthread: otPlatRadioEnable\n"); |
||||
(void) aInstance; |
||||
|
||||
if (sDisabled) { |
||||
sDisabled = false; |
||||
_set_idle(); |
||||
} |
||||
|
||||
return kThreadError_None; |
||||
} |
||||
|
||||
/* OpenThread will call this for disabling the radio */ |
||||
ThreadError otPlatRadioDisable(otInstance *aInstance) |
||||
{ |
||||
DEBUG("openthread: otPlatRadioDisable\n"); |
||||
(void) aInstance; |
||||
|
||||
if (!sDisabled) { |
||||
sDisabled = true; |
||||
_set_sleep(); |
||||
} |
||||
|
||||
return kThreadError_None; |
||||
} |
||||
|
||||
bool otPlatRadioIsEnabled(otInstance *aInstance) |
||||
{ |
||||
DEBUG("otPlatRadioIsEnabled\n"); |
||||
(void) aInstance; |
||||
netopt_state_t state = _get_state(); |
||||
if (state == NETOPT_STATE_OFF || state == NETOPT_STATE_SLEEP) { |
||||
return false; |
||||
} else { |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
/* OpenThread will call this for setting device state to SLEEP */ |
||||
ThreadError otPlatRadioSleep(otInstance *aInstance) |
||||
{ |
||||
DEBUG("otPlatRadioSleep\n"); |
||||
(void) aInstance; |
||||
|
||||
_set_sleep(); |
||||
return kThreadError_None; |
||||
} |
||||
|
||||
/*OpenThread will call this for waiting the reception of a packet */ |
||||
ThreadError otPlatRadioReceive(otInstance *aInstance, uint8_t aChannel) |
||||
{ |
||||
DEBUG("openthread: otPlatRadioReceive. Channel: %i\n", aChannel); |
||||
(void) aInstance; |
||||
|
||||
_set_idle(); |
||||
_set_channel(aChannel); |
||||
return kThreadError_None; |
||||
} |
||||
|
||||
/* OpenThread will call this function to get the transmit buffer */ |
||||
RadioPacket *otPlatRadioGetTransmitBuffer(otInstance *aInstance) |
||||
{ |
||||
DEBUG("openthread: otPlatRadioGetTransmitBuffer\n"); |
||||
return &sTransmitFrame; |
||||
} |
||||
|
||||
/* OpenThread will call this function to set the transmit power */ |
||||
void otPlatRadioSetDefaultTxPower(otInstance *aInstance, int8_t aPower) |
||||
{ |
||||
(void)aInstance; |
||||
|
||||
_set_power(aPower); |
||||
} |
||||
|
||||
/* OpenThread will call this for transmitting a packet*/ |
||||
ThreadError otPlatRadioTransmit(otInstance *aInstance, RadioPacket *aPacket) |
||||
{ |
||||
(void) aInstance; |
||||
struct iovec pkt; |
||||
|
||||
/* Populate iovec with transmit data
|
||||
* Unlike RIOT, OpenThread includes two bytes FCS (0x00 0x00) so |
||||
* these bytes are removed |
||||
*/ |
||||
pkt.iov_base = aPacket->mPsdu; |
||||
pkt.iov_len = aPacket->mLength - RADIO_IEEE802154_FCS_LEN; |
||||
|
||||
/*Set channel and power based on transmit frame */ |
||||
DEBUG("otPlatRadioTransmit->channel: %i, length %d\n", (int) aPacket->mChannel, (int)aPacket->mLength); |
||||
for (int i = 0; i < aPacket->mLength; ++i) { |
||||
DEBUG("%x ", aPacket->mPsdu[i]); |
||||
} |
||||
DEBUG("\n"); |
||||
_set_channel(aPacket->mChannel); |
||||
_set_power(aPacket->mPower); |
||||
|
||||
/* send packet though netdev */ |
||||
_dev->driver->send(_dev, &pkt, 1); |
||||
|
||||
return kThreadError_None; |
||||
} |
||||
|
||||
/* OpenThread will call this for getting the radio caps */ |
||||
otRadioCaps otPlatRadioGetCaps(otInstance *aInstance) |
||||
{ |
||||
DEBUG("openthread: otPlatRadioGetCaps\n"); |
||||
/* all drivers should handle ACK, including call of NETDEV_EVENT_TX_NOACK */ |
||||
return kRadioCapsNone; |
||||
} |
||||
|
||||
/* OpenThread will call this for getting the state of promiscuous mode */ |
||||
bool otPlatRadioGetPromiscuous(otInstance *aInstance) |
||||
{ |
||||
DEBUG("openthread: otPlatRadioGetPromiscuous\n"); |
||||
return _is_promiscuous(); |
||||
} |
||||
|
||||
/* OpenThread will call this for setting the state of promiscuous mode */ |
||||
void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnable) |
||||
{ |
||||
DEBUG("openthread: otPlatRadioSetPromiscuous\n"); |
||||
_set_promiscuous((aEnable) ? NETOPT_ENABLE : NETOPT_DISABLE); |
||||
} |
||||
|
||||
int8_t otPlatRadioGetRssi(otInstance *aInstance) |
||||
{ |
||||
DEBUG("otPlatRadioGetRssi\n"); |
||||
(void) aInstance; |
||||
return Rssi; |
||||
} |
||||
|
||||
void otPlatRadioEnableSrcMatch(otInstance *aInstance, bool aEnable) |
||||
{ |
||||
DEBUG("otPlatRadioEnableSrcMatch\n"); |
||||
(void)aInstance; |
||||
(void)aEnable; |
||||
} |
||||
|
||||
ThreadError otPlatRadioAddSrcMatchShortEntry(otInstance *aInstance, const uint16_t aShortAddress) |
||||
{ |
||||
DEBUG("otPlatRadioAddSrcMatchShortEntry\n"); |
||||
(void)aInstance; |
||||
(void)aShortAddress; |
||||
return kThreadError_None; |
||||
} |
||||
|
||||
ThreadError otPlatRadioAddSrcMatchExtEntry(otInstance *aInstance, const uint8_t *aExtAddress) |
||||
{ |
||||
DEBUG("otPlatRadioAddSrcMatchExtEntry\n"); |
||||
(void)aInstance; |
||||
(void)aExtAddress; |
||||
return kThreadError_None; |
||||
} |
||||
|
||||
ThreadError otPlatRadioClearSrcMatchShortEntry(otInstance *aInstance, const uint16_t aShortAddress) |
||||
{ |
||||
DEBUG("otPlatRadioClearSrcMatchShortEntry\n"); |
||||
(void)aInstance; |
||||
(void)aShortAddress; |
||||
return kThreadError_None; |
||||
} |
||||
|
||||
ThreadError otPlatRadioClearSrcMatchExtEntry(otInstance *aInstance, const uint8_t *aExtAddress) |
||||
{ |
||||
DEBUG("otPlatRadioClearSrcMatchExtEntry\n"); |
||||
(void)aInstance; |
||||
(void)aExtAddress; |
||||
return kThreadError_None; |
||||
} |
||||
|
||||
void otPlatRadioClearSrcMatchShortEntries(otInstance *aInstance) |
||||
{ |
||||
DEBUG("otPlatRadioClearSrcMatchShortEntries\n"); |
||||
(void)aInstance; |
||||
} |
||||
|
||||
void otPlatRadioClearSrcMatchExtEntries(otInstance *aInstance) |
||||
{ |
||||
DEBUG("otPlatRadioClearSrcMatchExtEntries\n"); |
||||
(void)aInstance; |
||||
} |
||||
|
||||
ThreadError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel, uint16_t aScanDuration) |
||||
{ |
||||
DEBUG("otPlatRadioEnergyScan\n"); |
||||
(void)aInstance; |
||||
(void)aScanChannel; |
||||
(void)aScanDuration; |
||||
return kThreadError_NotImplemented; |
||||
} |
||||
|
||||
void otPlatRadioGetIeeeEui64(otInstance *aInstance, uint8_t *aIeee64Eui64) |
||||
{ |
||||
_dev->driver->get(_dev, NETOPT_IPV6_IID, aIeee64Eui64, sizeof(eui64_t)); |
||||
} |
||||
|
||||
int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance) |
||||
{ |
||||
return -100; |
||||
} |
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Fundacion Inria Chile |
||||
* |
||||
* 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 Implementation of OpenThread random platform abstraction |
||||
* |
||||
* @author Jose Ignacio Alamos <jialamos@uc.cl> |
||||
* @} |
||||
*/ |
||||
|
||||
#include <stdint.h> |
||||
|
||||
#include "openthread/platform/random.h" |
||||
#include "periph/cpuid.h" |
||||
#include "random.h" |
||||
|
||||
#define ENABLE_DEBUG (0) |
||||
#include "debug.h" |
||||
|
||||
/* init random */ |
||||
void ot_random_init(void) |
||||
{ |
||||
#ifdef CPUID_LEN |
||||
char cpu_id[CPUID_LEN]; |
||||
cpuid_get(cpu_id); |
||||
uint32_t seed = 0; |
||||
for (unsigned i = 0; i < CPUID_LEN; i++) { |
||||
seed += cpu_id[i]; |
||||
} |
||||
random_init(seed); |
||||
#else |
||||
#error "CPU not supported (current CPU doesn't provide CPUID, required for entropy)" |
||||
#endif |
||||
} |
||||