2017-05-19 01:02:19 +02:00
|
|
|
/*
|
|
|
|
* 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>
|
2018-06-12 17:40:27 +02:00
|
|
|
* @author Baptiste Clenet <bapclenet@gmail.com>
|
2017-05-19 01:02:19 +02:00
|
|
|
* @}
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "msg.h"
|
|
|
|
#include "openthread/cli.h"
|
|
|
|
#include "openthread/instance.h"
|
|
|
|
#include "openthread/ip6.h"
|
2018-06-12 17:40:27 +02:00
|
|
|
#include "openthread/platform/alarm-milli.h"
|
2017-05-19 01:02:19 +02:00
|
|
|
#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;
|
|
|
|
|
|
|
|
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) {
|
2018-06-12 17:40:27 +02:00
|
|
|
(void) aInstance;
|
2017-05-19 01:02:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void *_openthread_event_loop(void *arg) {
|
make: fix various compile errors with Wextra
pkg, nordic_softdevice_ble: disable CFLAGS to omit compiler error
sys, pm_layered: fix casting nonscalar to the same type
cpu, stm32_common: fix type-limits, remove always true assert
cpu, stm32f4: fix pointer arithmetic in periph/i2c
drivers, at86rf2xx: fix type-limits where condition always true
saul, gpio: fix if no gpio configured for saul
cpu, saml21: add frequency check to periph/timer
driver, cc110x: fix unused param and type-limts errors
boards, wsn430-common: fix old-style-declaration
make: fix old style definition
drivers, sdcard_spi: fix old style typedef
driver, at30tse: remove unnecessary check
driver, nrf24: fix type-limit
driver, pn532: change buffer from char to uint8_t
tests/driver_sdcard: fix type limits
boards, feather-m0: add missing field inits
driver, tcs37727: fix type limits
pkg, emb6: disable some compiler warnings
tests/emb6: disable some compiler warings
pkg, openthread: fix sign compare and unused params
tests/trickle: fix struct init
tests/pthread_cooperation: fix type limits
board, mips-malta: remove feature periph_uart
shell: fix var size for netif command
gnrc, netif: fix sign-compare
gnrc, nib: fix sign-compare
shell: fix output in netif command
posix: fix type-limits in pthread_cond
2017-10-31 11:52:18 +01:00
|
|
|
(void)arg;
|
2017-05-19 01:02:19 +02:00
|
|
|
_pid = thread_getpid();
|
|
|
|
|
|
|
|
/* enable OpenThread UART */
|
|
|
|
otPlatUartEnable();
|
|
|
|
|
|
|
|
/* init OpenThread */
|
2018-06-12 17:40:27 +02:00
|
|
|
sInstance = otInstanceInitSingle();
|
2017-05-19 01:02:19 +02:00
|
|
|
|
|
|
|
msg_init_queue(_queue, OPENTHREAD_QUEUE_LEN);
|
|
|
|
netdev_t *dev;
|
|
|
|
msg_t msg, reply;
|
|
|
|
|
2019-05-08 14:47:03 +02:00
|
|
|
#if defined(MODULE_OPENTHREAD_CLI)
|
|
|
|
serial_msg_t* serialBuffer;
|
2017-05-19 01:02:19 +02:00
|
|
|
otCliUartInit(sInstance);
|
|
|
|
/* 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);
|
2018-06-12 17:40:27 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if OPENTHREAD_ENABLE_DIAG
|
|
|
|
diagInit(sInstance);
|
|
|
|
#endif
|
2017-05-19 01:02:19 +02:00
|
|
|
|
|
|
|
ot_job_t *job;
|
|
|
|
while (1) {
|
2018-06-12 17:40:27 +02:00
|
|
|
otTaskletsProcess(sInstance);
|
|
|
|
if (otTaskletsArePending(sInstance) == false) {
|
|
|
|
msg_receive(&msg);
|
|
|
|
switch (msg.type) {
|
|
|
|
case OPENTHREAD_XTIMER_MSG_TYPE_EVENT:
|
|
|
|
/* Tell OpenThread a time event was received */
|
|
|
|
otPlatAlarmMilliFired(sInstance);
|
|
|
|
break;
|
|
|
|
case OPENTHREAD_NETDEV_MSG_TYPE_EVENT:
|
|
|
|
/* Received an event from driver */
|
|
|
|
dev = msg.content.ptr;
|
|
|
|
dev->driver->isr(dev);
|
|
|
|
break;
|
2019-05-08 14:47:03 +02:00
|
|
|
#ifdef MODULE_OPENTHREAD_CLI
|
2018-06-12 17:40:27 +02:00
|
|
|
case OPENTHREAD_SERIAL_MSG_TYPE_EVENT:
|
|
|
|
/* Tell OpenThread about the reception of a CLI command */
|
|
|
|
serialBuffer = (serial_msg_t*)msg.content.ptr;
|
|
|
|
otPlatUartReceived((uint8_t*) serialBuffer->buf,serialBuffer->length);
|
|
|
|
serialBuffer->serial_buffer_status = OPENTHREAD_SERIAL_BUFFER_STATUS_FREE;
|
|
|
|
break;
|
2019-05-08 14:47:03 +02:00
|
|
|
#endif
|
2018-06-12 17:40:27 +02:00
|
|
|
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;
|
|
|
|
}
|
2017-05-19 01:02:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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));
|
2018-07-12 12:13:54 +02:00
|
|
|
netdev->driver->set(netdev, NETOPT_RX_END_IRQ, &enable, sizeof(enable));
|
2017-05-19 01:02:19 +02:00
|
|
|
|
|
|
|
_pid = thread_create(stack, stacksize,
|
|
|
|
priority, THREAD_CREATE_STACKTEST,
|
|
|
|
_openthread_event_loop, NULL, name);
|
|
|
|
|
|
|
|
if (_pid <= 0) {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return _pid;
|
|
|
|
}
|