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