1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/pkg/openthread/contrib/netdev/openthread_netdev.c
2017-06-01 13:44:05 -04:00

187 lines
5.0 KiB
C

/*
* 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;
}