mirror of
https://github.com/espressif/openthread.git
synced 2026-10-06 07:47:41 +00:00
[build] rename example platform POSIX to simulation (#4555)
Having examples/posix and src/core/posix is confusing. This commit renames the examples posix platform to simulation.
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
#
|
||||
# Copyright (c) 2019, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
set(OT_PLATFORM_LIB "openthread-simulation" PARENT_SCOPE)
|
||||
|
||||
if(NOT OT_CONFIG)
|
||||
set(OT_CONFIG "openthread-core-simulation-config.h")
|
||||
set(OT_CONFIG ${OT_CONFIG} PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
list(APPEND OT_PLATFORM_DEFINES
|
||||
"_BSD_SOURCE=1"
|
||||
"_DEFAULT_SOURCE=1"
|
||||
"OPENTHREAD_EXAMPLES_SIMULATION=1"
|
||||
"OPENTHREAD_POSIX=1"
|
||||
"OPENTHREAD_CONFIG_NCP_UART_ENABLE=1"
|
||||
)
|
||||
set(OT_PLATFORM_DEFINES ${OT_PLATFORM_DEFINES} PARENT_SCOPE)
|
||||
|
||||
list(APPEND OT_PLATFORM_DEFINES "OPENTHREAD_PROJECT_CORE_CONFIG_FILE=\"${OT_CONFIG}\"")
|
||||
|
||||
add_library(openthread-simulation
|
||||
alarm.c
|
||||
diag.c
|
||||
entropy.c
|
||||
flash.c
|
||||
logging.c
|
||||
misc.c
|
||||
radio.c
|
||||
spi-stubs.c
|
||||
system.c
|
||||
uart.c
|
||||
virtual_time/alarm-sim.c
|
||||
virtual_time/platform-sim.c
|
||||
$<TARGET_OBJECTS:openthread-platform-utils>
|
||||
)
|
||||
|
||||
set_property(TARGET openthread-simulation PROPERTY C_STANDARD 99)
|
||||
|
||||
find_library(LIBRT rt)
|
||||
if(LIBRT)
|
||||
target_link_libraries(openthread-simulation PRIVATE ${LIBRT})
|
||||
endif()
|
||||
|
||||
target_link_libraries(openthread-simulation PRIVATE openthread-platform-utils)
|
||||
|
||||
target_compile_definitions(openthread-simulation PUBLIC ${OT_PLATFORM_DEFINES})
|
||||
|
||||
target_compile_options(openthread-simulation PRIVATE
|
||||
${OT_CFLAGS}
|
||||
)
|
||||
|
||||
target_include_directories(openthread-simulation PRIVATE
|
||||
${OT_PUBLIC_INCLUDES}
|
||||
${OT_PRIVATE_INCLUDES}
|
||||
${PROJECT_SOURCE_DIR}/examples/platforms
|
||||
${PROJECT_SOURCE_DIR}/src/core
|
||||
)
|
||||
|
||||
set(CPACK_PACKAGE_NAME "openthread-simulation")
|
||||
set(CPACK_GENERATOR "DEB")
|
||||
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "OpenThread Authors <[email protected]")
|
||||
set(CPACK_PACKAGE_CONTACT "OpenThread Authors <[email protected]")
|
||||
include(CPack)
|
||||
@@ -0,0 +1,78 @@
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
|
||||
|
||||
lib_LIBRARIES = libopenthread-simulation.a
|
||||
|
||||
libopenthread_simulation_a_CPPFLAGS = \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/examples/platforms \
|
||||
-I$(top_srcdir)/src/core \
|
||||
-D_GNU_SOURCE \
|
||||
$(NULL)
|
||||
|
||||
PLATFORM_SOURCES = \
|
||||
alarm.c \
|
||||
diag.c \
|
||||
entropy.c \
|
||||
flash.c \
|
||||
logging.c \
|
||||
misc.c \
|
||||
openthread-core-simulation-config.h \
|
||||
platform-config.h \
|
||||
platform-simulation.h \
|
||||
radio.c \
|
||||
spi-stubs.c \
|
||||
system.c \
|
||||
uart.c \
|
||||
virtual_time/alarm-sim.c \
|
||||
virtual_time/platform-sim.c \
|
||||
$(NULL)
|
||||
|
||||
libopenthread_simulation_a_SOURCES = \
|
||||
$(PLATFORM_SOURCES) \
|
||||
$(NULL)
|
||||
|
||||
PRETTY_FILES = \
|
||||
$(PLATFORM_SOURCES) \
|
||||
$(NULL)
|
||||
|
||||
Dash = -
|
||||
libopenthread_simulation_a_LIBADD = \
|
||||
$(shell find $(top_builddir)/examples/platforms/utils $(Dash)type f $(Dash)name "*.o")
|
||||
|
||||
if OPENTHREAD_BUILD_COVERAGE
|
||||
libopenthread_simulation_a_CPPFLAGS += \
|
||||
-DOPENTHREAD_ENABLE_COVERAGE \
|
||||
$(NULL)
|
||||
|
||||
CLEANFILES = $(wildcard *.gcda *.gcno)
|
||||
endif # OPENTHREAD_BUILD_COVERAGE
|
||||
|
||||
include $(abs_top_nlbuild_autotools_dir)/automake/post.am
|
||||
@@ -0,0 +1,41 @@
|
||||
#
|
||||
# Copyright (c) 2017, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
#
|
||||
# Simulation platform-specific Makefile
|
||||
#
|
||||
|
||||
LDADD_COMMON += \
|
||||
$(top_builddir)/examples/platforms/simulation/libopenthread-simulation.a \
|
||||
$(NULL)
|
||||
|
||||
if OPENTHREAD_TARGET_LINUX
|
||||
LDADD_COMMON += \
|
||||
-lrt \
|
||||
$(NULL)
|
||||
endif
|
||||
@@ -0,0 +1,72 @@
|
||||
# OpenThread Simulation on POSIX
|
||||
|
||||
This directory contains example platform drivers for simulation on POSIX.
|
||||
|
||||
## Build Examples
|
||||
|
||||
### Build using autotools
|
||||
|
||||
```bash
|
||||
$ cd <path-to-openthread>
|
||||
$ ./bootstrap
|
||||
$ make -f examples/Makefile-simulation
|
||||
```
|
||||
|
||||
After a successful build, the `elf` files are found in:
|
||||
|
||||
- `<path-to-openthread>/output/<platform>/bin`
|
||||
|
||||
### Build using cmake/ninja
|
||||
|
||||
```bash
|
||||
$ cd <path-to-openthread>
|
||||
$ mkdir build && cd build
|
||||
$ cmake -GNinja -DOT_PLATFORM=simulation ..
|
||||
$ ninja
|
||||
```
|
||||
|
||||
After a successful build, the `elf` files are found in:
|
||||
|
||||
- `<path-to-openthread>/build/examples/apps/cli`
|
||||
- `<path-to-openthread>/build/examples/apps/ncp`
|
||||
|
||||
## Interact
|
||||
|
||||
1. Spawn the process:
|
||||
|
||||
```bash
|
||||
$ cd <path-to-openthread>/output/<platform>/bin
|
||||
$ ./ot-cli-ftd 1
|
||||
```
|
||||
|
||||
2. Type `help` for list of commands.
|
||||
|
||||
```bash
|
||||
> help
|
||||
help
|
||||
channel
|
||||
childtimeout
|
||||
contextreusedelay
|
||||
extaddr
|
||||
extpanid
|
||||
ipaddr
|
||||
keysequence
|
||||
leaderweight
|
||||
masterkey
|
||||
mode
|
||||
netdataregister
|
||||
networkidtimeout
|
||||
networkname
|
||||
panid
|
||||
ping
|
||||
prefix
|
||||
releaserouterid
|
||||
rloc16
|
||||
route
|
||||
routerupgradethreshold
|
||||
scan
|
||||
start
|
||||
state
|
||||
stop
|
||||
whitelist
|
||||
```
|
||||
@@ -0,0 +1,319 @@
|
||||
/*
|
||||
* Copyright (c) 2016, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "platform-simulation.h"
|
||||
|
||||
#if OPENTHREAD_SIMULATION_VIRTUAL_TIME == 0
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "utils/code_utils.h"
|
||||
|
||||
#ifndef __linux__
|
||||
#define __linux__ 0
|
||||
#endif
|
||||
|
||||
// linux microsecond timer
|
||||
#if __linux__
|
||||
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifndef OPENTHREAD_CONFIG_MICRO_TIMER_SIGNAL
|
||||
#define OPENTHREAD_CONFIG_MICRO_TIMER_SIGNAL SIGRTMIN
|
||||
#endif
|
||||
|
||||
timer_t sMicroTimer;
|
||||
#endif // __linux__
|
||||
|
||||
#include <openthread/platform/alarm-micro.h>
|
||||
#include <openthread/platform/alarm-milli.h>
|
||||
#include <openthread/platform/diag.h>
|
||||
|
||||
#define MS_PER_S 1000
|
||||
#define NS_PER_US 1000
|
||||
#define US_PER_MS 1000
|
||||
#define US_PER_S 1000000
|
||||
|
||||
#define DEFAULT_TIMEOUT 10 // seconds
|
||||
|
||||
static bool sIsMsRunning = false;
|
||||
static uint32_t sMsAlarm = 0;
|
||||
|
||||
static bool sIsUsRunning = false;
|
||||
static uint32_t sUsAlarm = 0;
|
||||
|
||||
static uint32_t sSpeedUpFactor = 1;
|
||||
|
||||
#if __linux__
|
||||
static void microTimerHandler(int aSignal, siginfo_t *aSignalInfo, void *aUserContext)
|
||||
{
|
||||
assert(aSignal == OPENTHREAD_CONFIG_MICRO_TIMER_SIGNAL);
|
||||
assert(aSignalInfo->si_value.sival_ptr == &sMicroTimer);
|
||||
(void)aUserContext;
|
||||
}
|
||||
#endif
|
||||
|
||||
void platformAlarmInit(uint32_t aSpeedUpFactor)
|
||||
{
|
||||
sSpeedUpFactor = aSpeedUpFactor;
|
||||
|
||||
#if __linux__
|
||||
{
|
||||
struct sigaction sa;
|
||||
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
sa.sa_sigaction = microTimerHandler;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
|
||||
if (sigaction(OPENTHREAD_CONFIG_MICRO_TIMER_SIGNAL, &sa, NULL) == -1)
|
||||
{
|
||||
perror("sigaction");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
struct sigevent sev;
|
||||
|
||||
sev.sigev_notify = SIGEV_SIGNAL;
|
||||
sev.sigev_signo = OPENTHREAD_CONFIG_MICRO_TIMER_SIGNAL;
|
||||
sev.sigev_value.sival_ptr = &sMicroTimer;
|
||||
|
||||
if (-1 == timer_create(CLOCK_REALTIME, &sev, &sMicroTimer))
|
||||
{
|
||||
perror("timer_create");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(CLOCK_MONOTONIC_RAW) || defined(CLOCK_MONOTONIC)
|
||||
uint64_t platformGetNow(void)
|
||||
{
|
||||
struct timespec now;
|
||||
int err;
|
||||
|
||||
#ifdef CLOCK_MONOTONIC_RAW
|
||||
err = clock_gettime(CLOCK_MONOTONIC_RAW, &now);
|
||||
#else
|
||||
err = clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
#endif
|
||||
|
||||
assert(err == 0);
|
||||
|
||||
return (uint64_t)now.tv_sec * sSpeedUpFactor * US_PER_S + (uint64_t)now.tv_nsec * sSpeedUpFactor / NS_PER_US;
|
||||
}
|
||||
#else
|
||||
uint64_t platformGetNow(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
int err;
|
||||
|
||||
err = gettimeofday(&tv, NULL);
|
||||
|
||||
assert(err == 0);
|
||||
|
||||
return (uint64_t)tv.tv_sec * sSpeedUpFactor * US_PER_S + (uint64_t)tv.tv_usec * sSpeedUpFactor;
|
||||
}
|
||||
#endif // defined(CLOCK_MONOTONIC_RAW) || defined(CLOCK_MONOTONIC)
|
||||
|
||||
uint32_t otPlatAlarmMilliGetNow(void)
|
||||
{
|
||||
return (uint32_t)(platformGetNow() / US_PER_MS);
|
||||
}
|
||||
|
||||
void otPlatAlarmMilliStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
sMsAlarm = aT0 + aDt;
|
||||
sIsMsRunning = true;
|
||||
}
|
||||
|
||||
void otPlatAlarmMilliStop(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
sIsMsRunning = false;
|
||||
}
|
||||
|
||||
uint32_t otPlatAlarmMicroGetNow(void)
|
||||
{
|
||||
return (uint32_t)platformGetNow();
|
||||
}
|
||||
|
||||
void otPlatAlarmMicroStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
sUsAlarm = aT0 + aDt;
|
||||
sIsUsRunning = true;
|
||||
|
||||
#if __linux__
|
||||
{
|
||||
struct itimerspec its;
|
||||
uint32_t diff = sUsAlarm - otPlatAlarmMicroGetNow();
|
||||
|
||||
its.it_value.tv_sec = diff / US_PER_S;
|
||||
its.it_value.tv_nsec = (diff % US_PER_S) * NS_PER_US;
|
||||
|
||||
its.it_interval.tv_sec = 0;
|
||||
its.it_interval.tv_nsec = 0;
|
||||
|
||||
if (-1 == timer_settime(sMicroTimer, 0, &its, NULL))
|
||||
{
|
||||
perror("otPlatAlarmMicroStartAt timer_settime()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
#endif // __linux__
|
||||
}
|
||||
|
||||
void otPlatAlarmMicroStop(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
sIsUsRunning = false;
|
||||
|
||||
#if __linux__
|
||||
{
|
||||
struct itimerspec its = {{0, 0}, {0, 0}};
|
||||
|
||||
if (-1 == timer_settime(sMicroTimer, 0, &its, NULL))
|
||||
{
|
||||
perror("otPlatAlarmMicroStop timer_settime()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
#endif // __linux__
|
||||
}
|
||||
|
||||
void platformAlarmUpdateTimeout(struct timeval *aTimeout)
|
||||
{
|
||||
int32_t usRemaining = DEFAULT_TIMEOUT * US_PER_S;
|
||||
int32_t msRemaining = DEFAULT_TIMEOUT * MS_PER_S;
|
||||
|
||||
if (aTimeout == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (sIsUsRunning)
|
||||
{
|
||||
usRemaining = (int32_t)(sUsAlarm - otPlatAlarmMicroGetNow());
|
||||
}
|
||||
|
||||
if (sIsMsRunning)
|
||||
{
|
||||
msRemaining = (int32_t)(sMsAlarm - otPlatAlarmMilliGetNow());
|
||||
}
|
||||
|
||||
if (usRemaining <= 0 || msRemaining <= 0)
|
||||
{
|
||||
aTimeout->tv_sec = 0;
|
||||
aTimeout->tv_usec = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int64_t remaining = ((int64_t)msRemaining) * US_PER_MS;
|
||||
|
||||
if (usRemaining < remaining)
|
||||
{
|
||||
remaining = usRemaining;
|
||||
}
|
||||
|
||||
remaining /= sSpeedUpFactor;
|
||||
|
||||
if (remaining == 0)
|
||||
{
|
||||
remaining = 1;
|
||||
}
|
||||
|
||||
aTimeout->tv_sec = (time_t)remaining / US_PER_S;
|
||||
aTimeout->tv_usec = remaining % US_PER_S;
|
||||
}
|
||||
}
|
||||
|
||||
void platformAlarmProcess(otInstance *aInstance)
|
||||
{
|
||||
int32_t remaining;
|
||||
|
||||
if (sIsMsRunning)
|
||||
{
|
||||
remaining = (int32_t)(sMsAlarm - otPlatAlarmMilliGetNow());
|
||||
|
||||
if (remaining <= 0)
|
||||
{
|
||||
sIsMsRunning = false;
|
||||
|
||||
#if OPENTHREAD_CONFIG_DIAG_ENABLE
|
||||
|
||||
if (otPlatDiagModeGet())
|
||||
{
|
||||
otPlatDiagAlarmFired(aInstance);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
otPlatAlarmMilliFired(aInstance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
|
||||
|
||||
if (sIsUsRunning)
|
||||
{
|
||||
remaining = (int32_t)(sUsAlarm - otPlatAlarmMicroGetNow());
|
||||
|
||||
if (remaining <= 0)
|
||||
{
|
||||
sIsUsRunning = false;
|
||||
|
||||
otPlatAlarmMicroFired(aInstance);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
|
||||
}
|
||||
|
||||
uint64_t otPlatTimeGet(void)
|
||||
{
|
||||
return platformGetNow();
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
uint16_t otPlatTimeGetXtalAccuracy(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // OPENTHREAD_SIMULATION_VIRTUAL_TIME == 0
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2016, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "platform-simulation.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <openthread/config.h>
|
||||
#include <openthread/platform/alarm-milli.h>
|
||||
#include <openthread/platform/radio.h>
|
||||
|
||||
#if OPENTHREAD_CONFIG_DIAG_ENABLE
|
||||
|
||||
/**
|
||||
* Diagnostics mode variables.
|
||||
*
|
||||
*/
|
||||
static bool sDiagMode = false;
|
||||
|
||||
void otPlatDiagModeSet(bool aMode)
|
||||
{
|
||||
sDiagMode = aMode;
|
||||
}
|
||||
|
||||
bool otPlatDiagModeGet()
|
||||
{
|
||||
return sDiagMode;
|
||||
}
|
||||
|
||||
void otPlatDiagChannelSet(uint8_t aChannel)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aChannel);
|
||||
}
|
||||
|
||||
void otPlatDiagTxPowerSet(int8_t aTxPower)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aTxPower);
|
||||
}
|
||||
|
||||
void otPlatDiagRadioReceived(otInstance *aInstance, otRadioFrame *aFrame, otError aError)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
OT_UNUSED_VARIABLE(aFrame);
|
||||
OT_UNUSED_VARIABLE(aError);
|
||||
}
|
||||
|
||||
void otPlatDiagAlarmCallback(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_DIAG_ENABLE
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (c) 2019, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements an entropy source based on /dev/urandom or pseudo-random generator.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "platform-simulation.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openthread/platform/entropy.h>
|
||||
|
||||
#include "utils/code_utils.h"
|
||||
|
||||
#ifndef __SANITIZE_ADDRESS__
|
||||
#define __SANITIZE_ADDRESS__ 0
|
||||
#endif
|
||||
|
||||
#if __SANITIZE_ADDRESS__ != 0
|
||||
|
||||
static uint32_t sState = 1;
|
||||
|
||||
#endif // __SANITIZE_ADDRESS__
|
||||
|
||||
void platformRandomInit(void)
|
||||
{
|
||||
#if __SANITIZE_ADDRESS__ != 0
|
||||
|
||||
// Multiplying gNodeId assures that no two nodes gets the same seed within an hour.
|
||||
sState = (uint32_t)time(NULL) + (3600 * gNodeId);
|
||||
|
||||
#endif // __SANITIZE_ADDRESS__
|
||||
}
|
||||
|
||||
#if __SANITIZE_ADDRESS__ != 0
|
||||
|
||||
static uint32_t randomUint32Get(void)
|
||||
{
|
||||
uint32_t mlcg, p, q;
|
||||
uint64_t tmpstate;
|
||||
|
||||
tmpstate = (uint64_t)33614 * (uint64_t)sState;
|
||||
q = tmpstate & 0xffffffff;
|
||||
q = q >> 1;
|
||||
p = tmpstate >> 32;
|
||||
mlcg = p + q;
|
||||
|
||||
if (mlcg & 0x80000000)
|
||||
{
|
||||
mlcg &= 0x7fffffff;
|
||||
mlcg++;
|
||||
}
|
||||
|
||||
sState = mlcg;
|
||||
|
||||
return mlcg;
|
||||
}
|
||||
|
||||
#endif // __SANITIZE_ADDRESS__
|
||||
|
||||
otError otPlatEntropyGet(uint8_t *aOutput, uint16_t aOutputLength)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
#if __SANITIZE_ADDRESS__ == 0
|
||||
|
||||
FILE * file = NULL;
|
||||
size_t readLength;
|
||||
|
||||
otEXPECT_ACTION(aOutput && aOutputLength, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
file = fopen("/dev/urandom", "rb");
|
||||
otEXPECT_ACTION(file != NULL, error = OT_ERROR_FAILED);
|
||||
|
||||
readLength = fread(aOutput, 1, aOutputLength, file);
|
||||
otEXPECT_ACTION(readLength == aOutputLength, error = OT_ERROR_FAILED);
|
||||
|
||||
exit:
|
||||
|
||||
if (file != NULL)
|
||||
{
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
#else // __SANITIZE_ADDRESS__
|
||||
|
||||
/*
|
||||
* THE IMPLEMENTATION BELOW IS NOT COMPLIANT WITH THE THREAD SPECIFICATION.
|
||||
*
|
||||
* Address Sanitizer triggers test failures when reading random
|
||||
* values from /dev/urandom. The pseudo-random number generator
|
||||
* implementation below is only used to enable continuous
|
||||
* integration checks with Address Sanitizer enabled.
|
||||
*/
|
||||
otEXPECT_ACTION(aOutput && aOutputLength, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
for (uint16_t length = 0; length < aOutputLength; length++)
|
||||
{
|
||||
aOutput[length] = (uint8_t)randomUint32Get();
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
#endif // __SANITIZE_ADDRESS__
|
||||
|
||||
return error;
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright (c) 2016, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "platform-simulation.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <openthread/config.h>
|
||||
|
||||
#include "utils/code_utils.h"
|
||||
#include "utils/flash.h"
|
||||
|
||||
static int sFlashFd = -1;
|
||||
uint32_t sEraseAddress;
|
||||
|
||||
enum
|
||||
{
|
||||
FLASH_SIZE = 0x40000,
|
||||
FLASH_PAGE_SIZE = 0x800,
|
||||
FLASH_PAGE_NUM = 128,
|
||||
};
|
||||
|
||||
otError utilsFlashInit(void)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
const char *path = OPENTHREAD_CONFIG_POSIX_SETTINGS_PATH;
|
||||
char fileName[sizeof(OPENTHREAD_CONFIG_POSIX_SETTINGS_PATH) + 32];
|
||||
struct stat st;
|
||||
bool create = false;
|
||||
const char *offset = getenv("PORT_OFFSET");
|
||||
|
||||
memset(&st, 0, sizeof(st));
|
||||
|
||||
if (stat(path, &st) == -1)
|
||||
{
|
||||
mkdir(path, 0777);
|
||||
}
|
||||
|
||||
if (offset == NULL)
|
||||
{
|
||||
offset = "0";
|
||||
}
|
||||
|
||||
snprintf(fileName, sizeof(fileName), "%s/%s_%d.flash", path, offset, gNodeId);
|
||||
|
||||
if (access(fileName, 0))
|
||||
{
|
||||
create = true;
|
||||
}
|
||||
|
||||
sFlashFd = open(fileName, O_RDWR | O_CREAT | O_CLOEXEC, 0600);
|
||||
lseek(sFlashFd, 0, SEEK_SET);
|
||||
|
||||
otEXPECT_ACTION(sFlashFd >= 0, error = OT_ERROR_FAILED);
|
||||
|
||||
if (create)
|
||||
{
|
||||
for (uint16_t index = 0; index < FLASH_PAGE_NUM; index++)
|
||||
{
|
||||
error = utilsFlashErasePage(index * FLASH_PAGE_SIZE);
|
||||
otEXPECT(error == OT_ERROR_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
uint32_t utilsFlashGetSize(void)
|
||||
{
|
||||
return FLASH_SIZE;
|
||||
}
|
||||
|
||||
otError utilsFlashErasePage(uint32_t aAddress)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
uint32_t address;
|
||||
uint8_t dummyPage[FLASH_SIZE];
|
||||
|
||||
otEXPECT_ACTION(sFlashFd >= 0, error = OT_ERROR_FAILED);
|
||||
otEXPECT_ACTION(aAddress < FLASH_SIZE, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
// Get start address of the flash page that includes aAddress
|
||||
address = aAddress & (~(uint32_t)(FLASH_PAGE_SIZE - 1));
|
||||
|
||||
// set the page to the erased state.
|
||||
memset((void *)(&dummyPage[0]), 0xff, FLASH_PAGE_SIZE);
|
||||
|
||||
// Write the page
|
||||
ssize_t r;
|
||||
r = pwrite(sFlashFd, &(dummyPage[0]), FLASH_PAGE_SIZE, (off_t)address);
|
||||
otEXPECT_ACTION(((int)r) == ((int)(FLASH_PAGE_SIZE)), error = OT_ERROR_FAILED);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError utilsFlashStatusWait(uint32_t aTimeout)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aTimeout);
|
||||
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
uint32_t utilsFlashWrite(uint32_t aAddress, uint8_t *aData, uint32_t aSize)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
uint32_t index = 0;
|
||||
uint8_t byte;
|
||||
|
||||
otEXPECT(sFlashFd >= 0 && aAddress < FLASH_SIZE);
|
||||
|
||||
for (index = 0; index < aSize; index++)
|
||||
{
|
||||
otEXPECT((ret = utilsFlashRead(aAddress + index, &byte, 1)) == 1);
|
||||
// Use bitwise AND to emulate the behavior of flash memory
|
||||
byte &= aData[index];
|
||||
otEXPECT((ret = (uint32_t)pwrite(sFlashFd, &byte, 1, (off_t)(aAddress + index))) == 1);
|
||||
}
|
||||
|
||||
exit:
|
||||
return index;
|
||||
}
|
||||
|
||||
uint32_t utilsFlashRead(uint32_t aAddress, uint8_t *aData, uint32_t aSize)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
otEXPECT(sFlashFd >= 0 && aAddress < FLASH_SIZE);
|
||||
ret = (uint32_t)pread(sFlashFd, aData, aSize, (off_t)aAddress);
|
||||
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2016, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "platform-simulation.h"
|
||||
#include <openthread-core-config.h>
|
||||
#include <openthread/config.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <openthread/platform/logging.h>
|
||||
#include <openthread/platform/toolchain.h>
|
||||
|
||||
#include "utils/code_utils.h"
|
||||
|
||||
// Macro to append content to end of the log string.
|
||||
|
||||
#define LOG_PRINTF(...) \
|
||||
charsWritten = snprintf(&logString[offset], sizeof(logString) - offset, __VA_ARGS__); \
|
||||
otEXPECT_ACTION(charsWritten >= 0, logString[offset] = 0); \
|
||||
offset += (unsigned int)charsWritten; \
|
||||
otEXPECT_ACTION(offset < sizeof(logString), logString[sizeof(logString) - 1] = 0)
|
||||
|
||||
#if (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED) || \
|
||||
(OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_NCP_SPINEL)
|
||||
OT_TOOL_WEAK void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aLogLevel);
|
||||
OT_UNUSED_VARIABLE(aLogRegion);
|
||||
|
||||
char logString[512];
|
||||
unsigned int offset;
|
||||
int charsWritten;
|
||||
va_list args;
|
||||
|
||||
offset = 0;
|
||||
|
||||
LOG_PRINTF("[%d] ", gNodeId);
|
||||
|
||||
va_start(args, aFormat);
|
||||
charsWritten = vsnprintf(&logString[offset], sizeof(logString) - offset, aFormat, args);
|
||||
va_end(args);
|
||||
|
||||
otEXPECT_ACTION(charsWritten >= 0, logString[offset] = 0);
|
||||
|
||||
exit:
|
||||
syslog(LOG_CRIT, "%s", logString);
|
||||
}
|
||||
|
||||
#endif // #if (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED)
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 2016, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "platform-simulation.h"
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <openthread/platform/misc.h>
|
||||
|
||||
#include "openthread-system.h"
|
||||
|
||||
extern jmp_buf gResetJump;
|
||||
|
||||
static otPlatResetReason sPlatResetReason = OT_PLAT_RESET_REASON_POWER_ON;
|
||||
bool gPlatformPseudoResetWasRequested;
|
||||
static otPlatMcuPowerState gPlatMcuPowerState = OT_PLAT_MCU_POWER_STATE_ON;
|
||||
|
||||
void otPlatReset(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
#if OPENTHREAD_PLATFORM_USE_PSEUDO_RESET
|
||||
gPlatformPseudoResetWasRequested = true;
|
||||
sPlatResetReason = OT_PLAT_RESET_REASON_SOFTWARE;
|
||||
|
||||
#else // OPENTHREAD_PLATFORM_USE_PSEUDO_RESET
|
||||
// Restart the process using execvp.
|
||||
otSysDeinit();
|
||||
platformUartRestore();
|
||||
|
||||
longjmp(gResetJump, 1);
|
||||
assert(false);
|
||||
|
||||
#endif // OPENTHREAD_PLATFORM_USE_PSEUDO_RESET
|
||||
}
|
||||
|
||||
otPlatResetReason otPlatGetResetReason(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
return sPlatResetReason;
|
||||
}
|
||||
|
||||
void otPlatWakeHost(void)
|
||||
{
|
||||
// TODO: implement an operation to wake the host from sleep state.
|
||||
}
|
||||
|
||||
otError otPlatSetMcuPowerState(otInstance *aInstance, otPlatMcuPowerState aState)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
switch (aState)
|
||||
{
|
||||
case OT_PLAT_MCU_POWER_STATE_ON:
|
||||
case OT_PLAT_MCU_POWER_STATE_LOW_POWER:
|
||||
gPlatMcuPowerState = aState;
|
||||
break;
|
||||
|
||||
default:
|
||||
error = OT_ERROR_FAILED;
|
||||
break;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
otPlatMcuPowerState otPlatGetMcuPowerState(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
return gPlatMcuPowerState;
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (c) 2017, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes simulation compile-time configuration constants
|
||||
* for OpenThread.
|
||||
*/
|
||||
|
||||
#ifndef OPENTHREAD_CORE_SIMULATION_CONFIG_H_
|
||||
#define OPENTHREAD_CORE_SIMULATION_CONFIG_H_
|
||||
|
||||
#ifndef OPENTHREAD_RADIO
|
||||
#define OPENTHREAD_RADIO 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_PLATFORM_INFO
|
||||
*
|
||||
* The platform-specific string to insert into the OpenThread version string.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_CONFIG_PLATFORM_INFO "SIMULATION"
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_LOG_OUTPUT
|
||||
*
|
||||
* Specify where the log output should go.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_LOG_OUTPUT /* allow command line override */
|
||||
#define OPENTHREAD_CONFIG_LOG_OUTPUT OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
|
||||
*
|
||||
* Define as 1 to enable support for adding of auto-configured SLAAC addresses by OpenThread.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE /* allows command line override */
|
||||
#define OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE 1
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_RADIO
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_SOFTWARE_ACK_TIMEOUT_ENABLE
|
||||
*
|
||||
* Define to 1 if you want to enable software ACK timeout logic.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_SOFTWARE_ACK_TIMEOUT_ENABLE
|
||||
#define OPENTHREAD_CONFIG_SOFTWARE_ACK_TIMEOUT_ENABLE 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_SOFTWARE_ENERGY_SCAN_ENABLE
|
||||
*
|
||||
* Define to 1 if you want to enable software energy scanning logic.
|
||||
*
|
||||
* Applicable only if raw link layer API is enabled (i.e., `OPENTHREAD_CONFIG_LINK_RAW_ENABLE` is set).
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_SOFTWARE_ENERGY_SCAN_ENABLE
|
||||
#define OPENTHREAD_CONFIG_SOFTWARE_ENERGY_SCAN_ENABLE 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_SOFTWARE_RETRANSMIT_ENABLE
|
||||
*
|
||||
* Define to 1 if you want to enable software retransmission logic.
|
||||
*
|
||||
* Applicable only if raw link layer API is enabled (i.e., `OPENTHREAD_CONFIG_LINK_RAW_ENABLE` is set).
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_SOFTWARE_RETRANSMIT_ENABLE
|
||||
#define OPENTHREAD_CONFIG_SOFTWARE_RETRANSMIT_ENABLE 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_SOFTWARE_CSMA_BACKOFF_ENABLE
|
||||
*
|
||||
* Define to 1 if you want to enable software CSMA-CA backoff logic.
|
||||
*
|
||||
* Applicable only if raw link layer API is enabled (i.e., `OPENTHREAD_CONFIG_LINK_RAW_ENABLE` is set).
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_SOFTWARE_CSMA_BACKOFF_ENABLE
|
||||
#define OPENTHREAD_CONFIG_SOFTWARE_CSMA_BACKOFF_ENABLE 1
|
||||
#endif
|
||||
#endif // OPENTHREAD_RADIO
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
|
||||
*
|
||||
* Define to 1 if you want to support microsecond timer in platform.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE 1
|
||||
|
||||
/**
|
||||
* @def CLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER
|
||||
*
|
||||
* Define to 1 to use DefaultHandler for unhandled requests
|
||||
*
|
||||
*/
|
||||
#define CLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER 1
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE
|
||||
*
|
||||
* Define to 1 if you want to enable radio coexistence implemented in platform.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE
|
||||
#define OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE 1
|
||||
#endif
|
||||
|
||||
#ifndef OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
|
||||
#define OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE 1
|
||||
#endif
|
||||
|
||||
#endif // OPENTHREAD_CORE_SIMULATION_CONFIG_H_
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2018, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes the platform-specific configuration.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_SIMULATION_UART_BAUDRATE
|
||||
*
|
||||
* This setting configures the baud rate of the UART.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_SIMULATION_UART_BAUDRATE
|
||||
#define OPENTHREAD_SIMULATION_UART_BAUDRATE B115200
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_SIMULATION_VIRTUAL_TIME
|
||||
*
|
||||
* This setting configures whether to use virtual time (used for simulation) in simulation platform.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_SIMULATION_VIRTUAL_TIME
|
||||
#define OPENTHREAD_SIMULATION_VIRTUAL_TIME 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART
|
||||
*
|
||||
* This setting configures whether to use virtual time for UART.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART
|
||||
#define OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_PLATFORM_USE_PSEUDO_RESET
|
||||
*
|
||||
* Define as 1 to enable pseudo-reset.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_PLATFORM_USE_PSEUDO_RESET
|
||||
#define OPENTHREAD_PLATFORM_USE_PSEUDO_RESET 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_NCP_SPI_ENABLE
|
||||
*
|
||||
* Define as 1 to enable SPI NCP interface.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_NCP_SPI_ENABLE
|
||||
#define OPENTHREAD_CONFIG_NCP_SPI_ENABLE 0
|
||||
#endif
|
||||
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* Copyright (c) 2016, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
* This file includes the platform-specific initializers.
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_SIMULATION_H_
|
||||
#define PLATFORM_SIMULATION_H_
|
||||
|
||||
#include <openthread-core-config.h>
|
||||
#include <openthread/config.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <openthread/instance.h>
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
#include "platform-config.h"
|
||||
|
||||
enum
|
||||
{
|
||||
OT_SIM_EVENT_ALARM_FIRED = 0,
|
||||
OT_SIM_EVENT_RADIO_RECEIVED = 1,
|
||||
OT_SIM_EVENT_UART_WRITE = 2,
|
||||
OT_SIM_EVENT_RADIO_SPINEL_WRITE = 3,
|
||||
OT_EVENT_DATA_MAX_SIZE = 1024,
|
||||
};
|
||||
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
struct Event
|
||||
{
|
||||
uint64_t mDelay;
|
||||
uint8_t mEvent;
|
||||
uint16_t mDataLength;
|
||||
uint8_t mData[OT_EVENT_DATA_MAX_SIZE];
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
enum
|
||||
{
|
||||
WELLKNOWN_NODE_ID = 34, ///< Well-known Unique ID used by a simulated radio that supports promiscuous mode.
|
||||
};
|
||||
|
||||
/**
|
||||
* Unique node ID.
|
||||
*
|
||||
*/
|
||||
extern uint32_t gNodeId;
|
||||
|
||||
/**
|
||||
* This function initializes the alarm service used by OpenThread.
|
||||
*
|
||||
*/
|
||||
void platformAlarmInit(uint32_t aSpeedUpFactor);
|
||||
|
||||
/**
|
||||
* This function retrieves the time remaining until the alarm fires.
|
||||
*
|
||||
* @param[out] aTimeval A pointer to the timeval struct.
|
||||
*
|
||||
*/
|
||||
void platformAlarmUpdateTimeout(struct timeval *tv);
|
||||
|
||||
/**
|
||||
* This function performs alarm driver processing.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance structure.
|
||||
*
|
||||
*/
|
||||
void platformAlarmProcess(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* This function returns the next alarm event time.
|
||||
*
|
||||
* @returns The next alarm fire time.
|
||||
*
|
||||
*/
|
||||
int32_t platformAlarmGetNext(void);
|
||||
|
||||
/**
|
||||
* This function returns the current alarm time.
|
||||
*
|
||||
* @returns The current alarm time.
|
||||
*
|
||||
*/
|
||||
uint64_t platformAlarmGetNow(void);
|
||||
|
||||
/**
|
||||
* This function advances the alarm time by @p aDelta.
|
||||
*
|
||||
* @param[in] aDelta The amount of time to advance.
|
||||
*
|
||||
*/
|
||||
void platformAlarmAdvanceNow(uint64_t aDelta);
|
||||
|
||||
/**
|
||||
* This function initializes the radio service used by OpenThread.
|
||||
*
|
||||
*/
|
||||
void platformRadioInit(void);
|
||||
|
||||
/**
|
||||
* This function shuts down the radio service used by OpenThread.
|
||||
*
|
||||
*/
|
||||
void platformRadioDeinit(void);
|
||||
|
||||
/**
|
||||
* This function inputs a received radio frame.
|
||||
*
|
||||
* @param[in] aInstance A pointer to the OpenThread instance.
|
||||
* @param[in] aBuf A pointer to the received radio frame.
|
||||
* @param[in] aBufLength The size of the received radio frame.
|
||||
*
|
||||
*/
|
||||
void platformRadioReceive(otInstance *aInstance, uint8_t *aBuf, uint16_t aBufLength);
|
||||
|
||||
/**
|
||||
* This function updates the file descriptor sets with file descriptors used by the radio driver.
|
||||
*
|
||||
* @param[inout] aReadFdSet A pointer to the read file descriptors.
|
||||
* @param[inout] aWriteFdSet A pointer to the write file descriptors.
|
||||
* @param[inout] aMaxFd A pointer to the max file descriptor.
|
||||
*
|
||||
*/
|
||||
void platformRadioUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, int *aMaxFd);
|
||||
|
||||
/**
|
||||
* This function performs radio driver processing.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance structure.
|
||||
* @param[in] aReadFdSet A pointer to the read file descriptors.
|
||||
* @param[in] aWriteFdSet A pointer to the write file descriptors.
|
||||
*
|
||||
*/
|
||||
void platformRadioProcess(otInstance *aInstance, const fd_set *aReadFdSet, const fd_set *aWriteFdSet);
|
||||
|
||||
/**
|
||||
* This function initializes the random number service used by OpenThread.
|
||||
*
|
||||
*/
|
||||
void platformRandomInit(void);
|
||||
|
||||
/**
|
||||
* This function updates the file descriptor sets with file descriptors used by the UART driver.
|
||||
*
|
||||
* @param[inout] aReadFdSet A pointer to the read file descriptors.
|
||||
* @param[inout] aWriteFdSet A pointer to the write file descriptors.
|
||||
* @param[inout] aMaxFd A pointer to the max file descriptor.
|
||||
*
|
||||
*/
|
||||
void platformUartUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, fd_set *aErrorFdSet, int *aMaxFd);
|
||||
|
||||
/**
|
||||
* This function performs radio driver processing.
|
||||
*
|
||||
*/
|
||||
void platformUartProcess(void);
|
||||
|
||||
/**
|
||||
* This function restores the Uart.
|
||||
*
|
||||
*/
|
||||
void platformUartRestore(void);
|
||||
|
||||
/**
|
||||
* This function sends a simulation event.
|
||||
*
|
||||
* @param[in] aEvent A pointer to the simulation event to send
|
||||
*
|
||||
*/
|
||||
void otSimSendEvent(const struct Event *aEvent);
|
||||
|
||||
/**
|
||||
* This function sends Uart data through simulation.
|
||||
*
|
||||
* @param[in] aData A pointer to the UART data.
|
||||
* @param[in] aLength Length of UART data.
|
||||
*
|
||||
*/
|
||||
void otSimSendUartWriteEvent(const uint8_t *aData, uint16_t aLength);
|
||||
|
||||
/**
|
||||
* This function checks if radio transmitting is pending.
|
||||
*
|
||||
* @returns Whether radio transmitting is pending.
|
||||
*
|
||||
*/
|
||||
bool platformRadioIsTransmitPending(void);
|
||||
|
||||
#endif // PLATFORM_SIMULATION_H_
|
||||
@@ -0,0 +1,884 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2019, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "platform-simulation.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <openthread/dataset.h>
|
||||
#include <openthread/random_noncrypto.h>
|
||||
#include <openthread/platform/alarm-micro.h>
|
||||
#include <openthread/platform/alarm-milli.h>
|
||||
#include <openthread/platform/diag.h>
|
||||
#include <openthread/platform/radio.h>
|
||||
#include <openthread/platform/time.h>
|
||||
|
||||
#include "utils/code_utils.h"
|
||||
#include "utils/mac_frame.h"
|
||||
#include "utils/soft_source_match_table.h"
|
||||
|
||||
// The IPv4 group for receiving packets of radio simulation
|
||||
#define OT_RADIO_GROUP "224.0.0.116"
|
||||
|
||||
enum
|
||||
{
|
||||
IEEE802154_ACK_LENGTH = 5,
|
||||
|
||||
IEEE802154_FRAME_TYPE_ACK = 2 << 0,
|
||||
|
||||
IEEE802154_FRAME_PENDING = 1 << 4,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SIM_RECEIVE_SENSITIVITY = -100, // dBm
|
||||
|
||||
SIM_HIGH_RSSI_SAMPLE = -30, // dBm
|
||||
SIM_LOW_RSSI_SAMPLE = -98, // dBm
|
||||
SIM_HIGH_RSSI_PROB_INC_PER_CHANNEL = 5,
|
||||
};
|
||||
|
||||
#if OPENTHREAD_SIMULATION_VIRTUAL_TIME
|
||||
extern int sSockFd;
|
||||
extern uint16_t sPortOffset;
|
||||
#else
|
||||
static int sTxFd = -1;
|
||||
static int sRxFd = -1;
|
||||
static uint16_t sPortOffset = 0;
|
||||
static uint16_t sPort = 0;
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
SIM_RADIO_CHANNEL_MIN = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MIN,
|
||||
SIM_RADIO_CHANNEL_MAX = OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MAX,
|
||||
};
|
||||
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
struct RadioMessage
|
||||
{
|
||||
uint8_t mChannel;
|
||||
uint8_t mPsdu[OT_RADIO_FRAME_MAX_SIZE];
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
static void radioTransmit(struct RadioMessage *aMessage, const struct otRadioFrame *aFrame);
|
||||
static void radioSendMessage(otInstance *aInstance);
|
||||
static void radioSendAck(void);
|
||||
static void radioProcessFrame(otInstance *aInstance);
|
||||
|
||||
static otRadioState sState = OT_RADIO_STATE_DISABLED;
|
||||
static struct RadioMessage sReceiveMessage;
|
||||
static struct RadioMessage sTransmitMessage;
|
||||
static struct RadioMessage sAckMessage;
|
||||
static otRadioFrame sReceiveFrame;
|
||||
static otRadioFrame sTransmitFrame;
|
||||
static otRadioFrame sAckFrame;
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
static otRadioIeInfo sTransmitIeInfo;
|
||||
#endif
|
||||
|
||||
static otExtAddress sExtAddress;
|
||||
static otShortAddress sShortAddress;
|
||||
static otPanId sPanid;
|
||||
static bool sPromiscuous = false;
|
||||
static bool sTxWait = false;
|
||||
static int8_t sTxPower = 0;
|
||||
static int8_t sCcaEdThresh = -74;
|
||||
|
||||
static bool sSrcMatchEnabled = false;
|
||||
|
||||
#if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE
|
||||
static bool sRadioCoexEnabled = true;
|
||||
#endif
|
||||
|
||||
static void ReverseExtAddress(otExtAddress *aReversed, const otExtAddress *aOrigin)
|
||||
{
|
||||
for (size_t i = 0; i < sizeof(*aReversed); i++)
|
||||
{
|
||||
aReversed->m8[i] = aOrigin->m8[sizeof(*aOrigin) - 1 - i];
|
||||
}
|
||||
}
|
||||
|
||||
static bool isDataRequestAndHasFramePending(const otRadioFrame *aFrame)
|
||||
{
|
||||
bool rval = false;
|
||||
otMacAddress src;
|
||||
|
||||
otEXPECT(otMacFrameIsDataRequest(aFrame));
|
||||
otEXPECT_ACTION(sSrcMatchEnabled, rval = true);
|
||||
otEXPECT(otMacFrameGetSrcAddr(aFrame, &src) == OT_ERROR_NONE);
|
||||
|
||||
switch (src.mType)
|
||||
{
|
||||
case OT_MAC_ADDRESS_TYPE_SHORT:
|
||||
rval = utilsSoftSrcMatchShortFindEntry(src.mAddress.mShortAddress) >= 0;
|
||||
break;
|
||||
case OT_MAC_ADDRESS_TYPE_EXTENDED:
|
||||
{
|
||||
otExtAddress extAddr;
|
||||
|
||||
ReverseExtAddress(&extAddr, &src.mAddress.mExtAddress);
|
||||
rval = utilsSoftSrcMatchExtFindEntry(&extAddr) >= 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
exit:
|
||||
return rval;
|
||||
}
|
||||
|
||||
static uint16_t crc16_citt(uint16_t aFcs, uint8_t aByte)
|
||||
{
|
||||
// CRC-16/CCITT, CRC-16/CCITT-TRUE, CRC-CCITT
|
||||
// width=16 poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 check=0x2189 name="KERMIT"
|
||||
// http://reveng.sourceforge.net/crc-catalogue/16.htm#crc.cat.kermit
|
||||
static const uint16_t sFcsTable[256] = {
|
||||
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5,
|
||||
0xe97e, 0xf8f7, 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 0x9cc9, 0x8d40, 0xbfdb, 0xae52,
|
||||
0xdaed, 0xcb64, 0xf9ff, 0xe876, 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 0xad4a, 0xbcc3,
|
||||
0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
|
||||
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9,
|
||||
0x2732, 0x36bb, 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 0x5285, 0x430c, 0x7197, 0x601e,
|
||||
0x14a1, 0x0528, 0x37b3, 0x263a, 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 0x6306, 0x728f,
|
||||
0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
|
||||
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862,
|
||||
0x9af9, 0x8b70, 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x0840, 0x19c9, 0x2b52, 0x3adb,
|
||||
0x4e64, 0x5fed, 0x6d76, 0x7cff, 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 0x18c1, 0x0948,
|
||||
0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
|
||||
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226,
|
||||
0xd0bd, 0xc134, 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 0xc60c, 0xd785, 0xe51e, 0xf497,
|
||||
0x8028, 0x91a1, 0xa33a, 0xb2b3, 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 0xd68d, 0xc704,
|
||||
0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
|
||||
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb,
|
||||
0x0e70, 0x1ff9, 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7, 0x6a4e, 0x58d5, 0x495c,
|
||||
0x3de3, 0x2c6a, 0x1ef1, 0x0f78};
|
||||
return (aFcs >> 8) ^ sFcsTable[(aFcs ^ aByte) & 0xff];
|
||||
}
|
||||
|
||||
void otPlatRadioGetIeeeEui64(otInstance *aInstance, uint8_t *aIeeeEui64)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
aIeeeEui64[0] = 0x18;
|
||||
aIeeeEui64[1] = 0xb4;
|
||||
aIeeeEui64[2] = 0x30;
|
||||
aIeeeEui64[3] = 0x00;
|
||||
aIeeeEui64[4] = (gNodeId >> 24) & 0xff;
|
||||
aIeeeEui64[5] = (gNodeId >> 16) & 0xff;
|
||||
aIeeeEui64[6] = (gNodeId >> 8) & 0xff;
|
||||
aIeeeEui64[7] = gNodeId & 0xff;
|
||||
}
|
||||
|
||||
void otPlatRadioSetPanId(otInstance *aInstance, otPanId aPanid)
|
||||
{
|
||||
assert(aInstance != NULL);
|
||||
|
||||
sPanid = aPanid;
|
||||
utilsSoftSrcMatchSetPanId(aPanid);
|
||||
}
|
||||
|
||||
void otPlatRadioSetExtendedAddress(otInstance *aInstance, const otExtAddress *aExtAddress)
|
||||
{
|
||||
assert(aInstance != NULL);
|
||||
|
||||
ReverseExtAddress(&sExtAddress, aExtAddress);
|
||||
}
|
||||
|
||||
void otPlatRadioSetShortAddress(otInstance *aInstance, otShortAddress aAddress)
|
||||
{
|
||||
assert(aInstance != NULL);
|
||||
|
||||
sShortAddress = aAddress;
|
||||
}
|
||||
|
||||
void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnable)
|
||||
{
|
||||
assert(aInstance != NULL);
|
||||
|
||||
sPromiscuous = aEnable;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_SIMULATION_VIRTUAL_TIME == 0
|
||||
static void initFds(void)
|
||||
{
|
||||
int fd;
|
||||
int one = 1;
|
||||
struct sockaddr_in sockaddr;
|
||||
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
|
||||
otEXPECT_ACTION((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1, perror("socket(sTxFd)"));
|
||||
|
||||
sPort = (uint16_t)(9000 + sPortOffset + gNodeId);
|
||||
sockaddr.sin_family = AF_INET;
|
||||
sockaddr.sin_port = htons(sPort);
|
||||
sockaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
|
||||
otEXPECT_ACTION(setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &sockaddr.sin_addr, sizeof(sockaddr.sin_addr)) != -1,
|
||||
perror("setsockopt(sTxFd, IP_MULTICAST_IF)"));
|
||||
|
||||
otEXPECT_ACTION(setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &one, sizeof(one)) != -1,
|
||||
perror("setsockopt(sRxFd, IP_MULTICAST_LOOP)"));
|
||||
|
||||
otEXPECT_ACTION(bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) != -1, perror("bind(sTxFd)"));
|
||||
|
||||
// Tx fd is successfully initialized.
|
||||
sTxFd = fd;
|
||||
|
||||
otEXPECT_ACTION((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1, perror("socket(sRxFd)"));
|
||||
|
||||
otEXPECT_ACTION(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) != -1,
|
||||
perror("setsockopt(sRxFd, SO_REUSEADDR)"));
|
||||
otEXPECT_ACTION(setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) != -1,
|
||||
perror("setsockopt(sRxFd, SO_REUSEPORT)"));
|
||||
|
||||
{
|
||||
struct ip_mreqn mreq;
|
||||
|
||||
memset(&mreq, 0, sizeof(mreq));
|
||||
inet_pton(AF_INET, OT_RADIO_GROUP, &mreq.imr_multiaddr);
|
||||
|
||||
// Always use loopback device to send simulation packets.
|
||||
mreq.imr_address.s_addr = inet_addr("127.0.0.1");
|
||||
|
||||
otEXPECT_ACTION(setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &mreq.imr_address, sizeof(mreq.imr_address)) != -1,
|
||||
perror("setsockopt(sRxFd, IP_MULTICAST_IF)"));
|
||||
otEXPECT_ACTION(setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) != -1,
|
||||
perror("setsockopt(sRxFd, IP_ADD_MEMBERSHIP)"));
|
||||
}
|
||||
|
||||
sockaddr.sin_family = AF_INET;
|
||||
sockaddr.sin_port = htons((uint16_t)(9000 + sPortOffset + WELLKNOWN_NODE_ID));
|
||||
sockaddr.sin_addr.s_addr = inet_addr(OT_RADIO_GROUP);
|
||||
|
||||
otEXPECT_ACTION(bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) != -1, perror("bind(sRxFd)"));
|
||||
|
||||
// Rx fd is successfully initialized.
|
||||
sRxFd = fd;
|
||||
|
||||
exit:
|
||||
if (sRxFd == -1 || sTxFd == -1)
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
#endif // OPENTHREAD_SIMULATION_VIRTUAL_TIME == 0
|
||||
|
||||
void platformRadioInit(void)
|
||||
{
|
||||
#if OPENTHREAD_SIMULATION_VIRTUAL_TIME == 0
|
||||
char *offset;
|
||||
|
||||
offset = getenv("PORT_OFFSET");
|
||||
|
||||
if (offset)
|
||||
{
|
||||
char *endptr;
|
||||
|
||||
sPortOffset = (uint16_t)strtol(offset, &endptr, 0);
|
||||
|
||||
if (*endptr != '\0')
|
||||
{
|
||||
fprintf(stderr, "Invalid PORT_OFFSET: %s\n", offset);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
sPortOffset *= WELLKNOWN_NODE_ID;
|
||||
}
|
||||
|
||||
initFds();
|
||||
#endif // OPENTHREAD_SIMULATION_VIRTUAL_TIME == 0
|
||||
|
||||
sReceiveFrame.mPsdu = sReceiveMessage.mPsdu;
|
||||
sTransmitFrame.mPsdu = sTransmitMessage.mPsdu;
|
||||
sAckFrame.mPsdu = sAckMessage.mPsdu;
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
sTransmitFrame.mInfo.mTxInfo.mIeInfo = &sTransmitIeInfo;
|
||||
#else
|
||||
sTransmitFrame.mInfo.mTxInfo.mIeInfo = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool otPlatRadioIsEnabled(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
return (sState != OT_RADIO_STATE_DISABLED) ? true : false;
|
||||
}
|
||||
|
||||
otError otPlatRadioEnable(otInstance *aInstance)
|
||||
{
|
||||
if (!otPlatRadioIsEnabled(aInstance))
|
||||
{
|
||||
sState = OT_RADIO_STATE_SLEEP;
|
||||
}
|
||||
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
otError otPlatRadioDisable(otInstance *aInstance)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
otEXPECT(otPlatRadioIsEnabled(aInstance));
|
||||
otEXPECT_ACTION(sState == OT_RADIO_STATE_SLEEP, error = OT_ERROR_INVALID_STATE);
|
||||
|
||||
sState = OT_RADIO_STATE_DISABLED;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError otPlatRadioSleep(otInstance *aInstance)
|
||||
{
|
||||
assert(aInstance != NULL);
|
||||
|
||||
otError error = OT_ERROR_INVALID_STATE;
|
||||
|
||||
if (sState == OT_RADIO_STATE_SLEEP || sState == OT_RADIO_STATE_RECEIVE)
|
||||
{
|
||||
error = OT_ERROR_NONE;
|
||||
sState = OT_RADIO_STATE_SLEEP;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
otError otPlatRadioReceive(otInstance *aInstance, uint8_t aChannel)
|
||||
{
|
||||
assert(aInstance != NULL);
|
||||
|
||||
otError error = OT_ERROR_INVALID_STATE;
|
||||
|
||||
if (sState != OT_RADIO_STATE_DISABLED)
|
||||
{
|
||||
error = OT_ERROR_NONE;
|
||||
sState = OT_RADIO_STATE_RECEIVE;
|
||||
sTxWait = false;
|
||||
sReceiveFrame.mChannel = aChannel;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aRadio)
|
||||
{
|
||||
assert(aInstance != NULL);
|
||||
assert(aRadio != NULL);
|
||||
|
||||
otError error = OT_ERROR_INVALID_STATE;
|
||||
|
||||
if (sState == OT_RADIO_STATE_RECEIVE)
|
||||
{
|
||||
error = OT_ERROR_NONE;
|
||||
sState = OT_RADIO_STATE_TRANSMIT;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance)
|
||||
{
|
||||
assert(aInstance != NULL);
|
||||
|
||||
return &sTransmitFrame;
|
||||
}
|
||||
|
||||
int8_t otPlatRadioGetRssi(otInstance *aInstance)
|
||||
{
|
||||
assert(aInstance != NULL);
|
||||
|
||||
int8_t rssi = SIM_LOW_RSSI_SAMPLE;
|
||||
uint8_t channel = sReceiveFrame.mChannel;
|
||||
uint32_t probabilityThreshold;
|
||||
|
||||
otEXPECT((SIM_RADIO_CHANNEL_MIN <= channel) && channel <= (SIM_RADIO_CHANNEL_MAX));
|
||||
|
||||
// To emulate a simple interference model, we return either a high or
|
||||
// a low RSSI value with a fixed probability per each channel. The
|
||||
// probability is increased per channel by a constant.
|
||||
|
||||
probabilityThreshold = (channel - SIM_RADIO_CHANNEL_MIN) * SIM_HIGH_RSSI_PROB_INC_PER_CHANNEL;
|
||||
|
||||
if (otRandomNonCryptoGetUint16() < (probabilityThreshold * 0xffff / 100))
|
||||
{
|
||||
rssi = SIM_HIGH_RSSI_SAMPLE;
|
||||
}
|
||||
|
||||
exit:
|
||||
return rssi;
|
||||
}
|
||||
|
||||
otRadioCaps otPlatRadioGetCaps(otInstance *aInstance)
|
||||
{
|
||||
assert(aInstance != NULL);
|
||||
|
||||
return OT_RADIO_CAPS_NONE;
|
||||
}
|
||||
|
||||
bool otPlatRadioGetPromiscuous(otInstance *aInstance)
|
||||
{
|
||||
assert(aInstance != NULL);
|
||||
|
||||
return sPromiscuous;
|
||||
}
|
||||
|
||||
static void radioReceive(otInstance *aInstance)
|
||||
{
|
||||
bool isTxDone = false;
|
||||
bool isAck = otMacFrameIsAck(&sReceiveFrame);
|
||||
|
||||
otEXPECT(sReceiveFrame.mChannel == sReceiveMessage.mChannel);
|
||||
otEXPECT(sState == OT_RADIO_STATE_RECEIVE || sState == OT_RADIO_STATE_TRANSMIT);
|
||||
|
||||
// Unable to simulate SFD, so use the rx done timestamp instead.
|
||||
sReceiveFrame.mInfo.mRxInfo.mTimestamp = otPlatTimeGet();
|
||||
|
||||
if (sTxWait)
|
||||
{
|
||||
if (otMacFrameIsAckRequested(&sTransmitFrame))
|
||||
{
|
||||
isTxDone = isAck && otMacFrameGetSequence(&sReceiveFrame) == otMacFrameGetSequence(&sTransmitFrame);
|
||||
}
|
||||
#if OPENTHREAD_SIMULATION_VIRTUAL_TIME
|
||||
// Simulate tx done when receiving the echo frame.
|
||||
else
|
||||
{
|
||||
isTxDone = !isAck && sTransmitFrame.mLength == sReceiveFrame.mLength &&
|
||||
memcmp(sTransmitFrame.mPsdu, sReceiveFrame.mPsdu, sTransmitFrame.mLength) == 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (isTxDone)
|
||||
{
|
||||
sState = OT_RADIO_STATE_RECEIVE;
|
||||
sTxWait = false;
|
||||
|
||||
#if OPENTHREAD_CONFIG_DIAG_ENABLE
|
||||
|
||||
if (otPlatDiagModeGet())
|
||||
{
|
||||
otPlatDiagRadioTransmitDone(aInstance, &sTransmitFrame, OT_ERROR_NONE);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
otPlatRadioTxDone(aInstance, &sTransmitFrame, (isAck ? &sReceiveFrame : NULL), OT_ERROR_NONE);
|
||||
}
|
||||
}
|
||||
else if (!isAck || sPromiscuous)
|
||||
{
|
||||
radioProcessFrame(aInstance);
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
static void radioComputeCrc(struct RadioMessage *aMessage, uint16_t aLength)
|
||||
{
|
||||
uint16_t crc = 0;
|
||||
uint16_t crc_offset = aLength - sizeof(uint16_t);
|
||||
|
||||
for (uint16_t i = 0; i < crc_offset; i++)
|
||||
{
|
||||
crc = crc16_citt(crc, aMessage->mPsdu[i]);
|
||||
}
|
||||
|
||||
aMessage->mPsdu[crc_offset] = crc & 0xff;
|
||||
aMessage->mPsdu[crc_offset + 1] = crc >> 8;
|
||||
}
|
||||
|
||||
void radioSendMessage(otInstance *aInstance)
|
||||
{
|
||||
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
bool notifyFrameUpdated = false;
|
||||
|
||||
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
if (sTransmitFrame.mInfo.mTxInfo.mIeInfo->mTimeIeOffset != 0)
|
||||
{
|
||||
uint8_t *timeIe = sTransmitFrame.mPsdu + sTransmitFrame.mInfo.mTxInfo.mIeInfo->mTimeIeOffset;
|
||||
uint64_t time = (uint64_t)((int64_t)otPlatTimeGet() + sTransmitFrame.mInfo.mTxInfo.mIeInfo->mNetworkTimeOffset);
|
||||
|
||||
*timeIe = sTransmitFrame.mInfo.mTxInfo.mIeInfo->mTimeSyncSeq;
|
||||
|
||||
*(++timeIe) = (uint8_t)(time & 0xff);
|
||||
for (uint8_t i = 1; i < sizeof(uint64_t); i++)
|
||||
{
|
||||
time = time >> 8;
|
||||
*(++timeIe) = (uint8_t)(time & 0xff);
|
||||
}
|
||||
|
||||
notifyFrameUpdated = true;
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
|
||||
if (notifyFrameUpdated)
|
||||
{
|
||||
otMacFrameProcessTransmitAesCcm(&sTransmitFrame, &sExtAddress);
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
|
||||
sTransmitMessage.mChannel = sTransmitFrame.mChannel;
|
||||
|
||||
otPlatRadioTxStarted(aInstance, &sTransmitFrame);
|
||||
radioComputeCrc(&sTransmitMessage, sTransmitFrame.mLength);
|
||||
radioTransmit(&sTransmitMessage, &sTransmitFrame);
|
||||
|
||||
#if OPENTHREAD_SIMULATION_VIRTUAL_TIME == 0
|
||||
sTxWait = otMacFrameIsAckRequested(&sTransmitFrame);
|
||||
|
||||
if (!sTxWait)
|
||||
{
|
||||
sState = OT_RADIO_STATE_RECEIVE;
|
||||
|
||||
#if OPENTHREAD_CONFIG_DIAG_ENABLE
|
||||
|
||||
if (otPlatDiagModeGet())
|
||||
{
|
||||
otPlatDiagRadioTransmitDone(aInstance, &sTransmitFrame, OT_ERROR_NONE);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
otPlatRadioTxDone(aInstance, &sTransmitFrame, NULL, OT_ERROR_NONE);
|
||||
}
|
||||
}
|
||||
#else
|
||||
// Wait for echo radio in virtual time mode.
|
||||
sTxWait = true;
|
||||
#endif // OPENTHREAD_SIMULATION_VIRTUAL_TIME
|
||||
}
|
||||
|
||||
bool platformRadioIsTransmitPending(void)
|
||||
{
|
||||
return sState == OT_RADIO_STATE_TRANSMIT && !sTxWait;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_SIMULATION_VIRTUAL_TIME
|
||||
void platformRadioReceive(otInstance *aInstance, uint8_t *aBuf, uint16_t aBufLength)
|
||||
{
|
||||
assert(sizeof(sReceiveMessage) >= aBufLength);
|
||||
|
||||
memcpy(&sReceiveMessage, aBuf, aBufLength);
|
||||
|
||||
sReceiveFrame.mLength = (uint8_t)(aBufLength - 1);
|
||||
|
||||
radioReceive(aInstance);
|
||||
}
|
||||
#else
|
||||
void platformRadioUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, int *aMaxFd)
|
||||
{
|
||||
if (aReadFdSet != NULL && (sState != OT_RADIO_STATE_TRANSMIT || sTxWait))
|
||||
{
|
||||
FD_SET(sRxFd, aReadFdSet);
|
||||
|
||||
if (aMaxFd != NULL && *aMaxFd < sRxFd)
|
||||
{
|
||||
*aMaxFd = sRxFd;
|
||||
}
|
||||
}
|
||||
|
||||
if (aWriteFdSet != NULL && platformRadioIsTransmitPending())
|
||||
{
|
||||
FD_SET(sTxFd, aWriteFdSet);
|
||||
|
||||
if (aMaxFd != NULL && *aMaxFd < sTxFd)
|
||||
{
|
||||
*aMaxFd = sTxFd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// no need to close in virtual time mode.
|
||||
void platformRadioDeinit(void)
|
||||
{
|
||||
if (sRxFd != -1)
|
||||
{
|
||||
close(sRxFd);
|
||||
}
|
||||
|
||||
if (sTxFd != -1)
|
||||
{
|
||||
close(sTxFd);
|
||||
}
|
||||
}
|
||||
#endif // OPENTHREAD_SIMULATION_VIRTUAL_TIME
|
||||
|
||||
void platformRadioProcess(otInstance *aInstance, const fd_set *aReadFdSet, const fd_set *aWriteFdSet)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aReadFdSet);
|
||||
OT_UNUSED_VARIABLE(aWriteFdSet);
|
||||
|
||||
#if OPENTHREAD_SIMULATION_VIRTUAL_TIME == 0
|
||||
if (FD_ISSET(sRxFd, aReadFdSet))
|
||||
{
|
||||
struct sockaddr_in sockaddr;
|
||||
socklen_t len = sizeof(sockaddr);
|
||||
ssize_t rval;
|
||||
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
rval =
|
||||
recvfrom(sRxFd, (char *)&sReceiveMessage, sizeof(sReceiveMessage), 0, (struct sockaddr *)&sockaddr, &len);
|
||||
|
||||
if (rval > 0)
|
||||
{
|
||||
if (sockaddr.sin_port != htons(sPort))
|
||||
{
|
||||
sReceiveFrame.mLength = (uint16_t)(rval - 1);
|
||||
|
||||
radioReceive(aInstance);
|
||||
}
|
||||
}
|
||||
else if (rval == 0)
|
||||
{
|
||||
// socket is closed, which should not happen
|
||||
assert(false);
|
||||
}
|
||||
else if (errno != EINTR && errno != EAGAIN)
|
||||
{
|
||||
perror("recvfrom(sRxFd)");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (platformRadioIsTransmitPending())
|
||||
{
|
||||
radioSendMessage(aInstance);
|
||||
}
|
||||
}
|
||||
|
||||
void radioTransmit(struct RadioMessage *aMessage, const struct otRadioFrame *aFrame)
|
||||
{
|
||||
#if OPENTHREAD_SIMULATION_VIRTUAL_TIME == 0
|
||||
ssize_t rval;
|
||||
struct sockaddr_in sockaddr;
|
||||
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
sockaddr.sin_family = AF_INET;
|
||||
inet_pton(AF_INET, OT_RADIO_GROUP, &sockaddr.sin_addr);
|
||||
|
||||
sockaddr.sin_port = htons((uint16_t)(9000 + sPortOffset + WELLKNOWN_NODE_ID));
|
||||
rval =
|
||||
sendto(sTxFd, (const char *)aMessage, 1 + aFrame->mLength, 0, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
|
||||
|
||||
if (rval < 0)
|
||||
{
|
||||
perror("sendto(sTxFd)");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#else // OPENTHREAD_SIMULATION_VIRTUAL_TIME == 0
|
||||
struct Event event;
|
||||
|
||||
event.mDelay = 1; // 1us for now
|
||||
event.mEvent = OT_SIM_EVENT_RADIO_RECEIVED;
|
||||
event.mDataLength = 1 + aFrame->mLength; // include channel in first byte
|
||||
memcpy(event.mData, aMessage, event.mDataLength);
|
||||
|
||||
otSimSendEvent(&event);
|
||||
#endif // OPENTHREAD_SIMULATION_VIRTUAL_TIME == 0
|
||||
}
|
||||
|
||||
void radioSendAck(void)
|
||||
{
|
||||
sAckFrame.mLength = IEEE802154_ACK_LENGTH;
|
||||
sAckMessage.mPsdu[0] = IEEE802154_FRAME_TYPE_ACK;
|
||||
|
||||
if (isDataRequestAndHasFramePending(&sReceiveFrame))
|
||||
{
|
||||
sAckMessage.mPsdu[0] |= IEEE802154_FRAME_PENDING;
|
||||
sReceiveFrame.mInfo.mRxInfo.mAckedWithFramePending = true;
|
||||
}
|
||||
|
||||
sAckMessage.mPsdu[1] = 0;
|
||||
sAckMessage.mPsdu[2] = otMacFrameGetSequence(&sReceiveFrame);
|
||||
|
||||
sAckMessage.mChannel = sReceiveFrame.mChannel;
|
||||
|
||||
radioComputeCrc(&sAckMessage, sAckFrame.mLength);
|
||||
radioTransmit(&sAckMessage, &sAckFrame);
|
||||
}
|
||||
|
||||
void radioProcessFrame(otInstance *aInstance)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
sReceiveFrame.mInfo.mRxInfo.mRssi = -20;
|
||||
sReceiveFrame.mInfo.mRxInfo.mLqi = OT_RADIO_LQI_NONE;
|
||||
|
||||
sReceiveFrame.mInfo.mRxInfo.mAckedWithFramePending = false;
|
||||
|
||||
otEXPECT(sPromiscuous == false);
|
||||
|
||||
otEXPECT_ACTION(otMacFrameDoesAddrMatch(&sReceiveFrame, sPanid, sShortAddress, &sExtAddress),
|
||||
error = OT_ERROR_ABORT);
|
||||
|
||||
// generate acknowledgment
|
||||
if (otMacFrameIsAckRequested(&sReceiveFrame))
|
||||
{
|
||||
radioSendAck();
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
if (error != OT_ERROR_ABORT)
|
||||
{
|
||||
#if OPENTHREAD_CONFIG_DIAG_ENABLE
|
||||
if (otPlatDiagModeGet())
|
||||
{
|
||||
otPlatDiagRadioReceiveDone(aInstance, error == OT_ERROR_NONE ? &sReceiveFrame : NULL, error);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
otPlatRadioReceiveDone(aInstance, error == OT_ERROR_NONE ? &sReceiveFrame : NULL, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void otPlatRadioEnableSrcMatch(otInstance *aInstance, bool aEnable)
|
||||
{
|
||||
assert(aInstance != NULL);
|
||||
|
||||
sSrcMatchEnabled = aEnable;
|
||||
}
|
||||
|
||||
otError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel, uint16_t aScanDuration)
|
||||
{
|
||||
assert(aInstance != NULL);
|
||||
assert(aScanChannel >= SIM_RADIO_CHANNEL_MIN && aScanChannel <= SIM_RADIO_CHANNEL_MAX);
|
||||
assert(aScanDuration > 0);
|
||||
|
||||
return OT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
otError otPlatRadioGetTransmitPower(otInstance *aInstance, int8_t *aPower)
|
||||
{
|
||||
assert(aInstance != NULL);
|
||||
|
||||
*aPower = sTxPower;
|
||||
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
otError otPlatRadioSetTransmitPower(otInstance *aInstance, int8_t aPower)
|
||||
{
|
||||
assert(aInstance != NULL);
|
||||
|
||||
sTxPower = aPower;
|
||||
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
otError otPlatRadioGetCcaEnergyDetectThreshold(otInstance *aInstance, int8_t *aThreshold)
|
||||
{
|
||||
assert(aInstance != NULL);
|
||||
|
||||
*aThreshold = sCcaEdThresh;
|
||||
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
otError otPlatRadioSetCcaEnergyDetectThreshold(otInstance *aInstance, int8_t aThreshold)
|
||||
{
|
||||
assert(aInstance != NULL);
|
||||
|
||||
sCcaEdThresh = aThreshold;
|
||||
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance)
|
||||
{
|
||||
assert(aInstance != NULL);
|
||||
|
||||
return SIM_RECEIVE_SENSITIVITY;
|
||||
}
|
||||
|
||||
otRadioState otPlatRadioGetState(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
return sState;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE
|
||||
otError otPlatRadioSetCoexEnabled(otInstance *aInstance, bool aEnabled)
|
||||
{
|
||||
assert(aInstance != NULL);
|
||||
|
||||
sRadioCoexEnabled = aEnabled;
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
bool otPlatRadioIsCoexEnabled(otInstance *aInstance)
|
||||
{
|
||||
assert(aInstance != NULL);
|
||||
|
||||
return sRadioCoexEnabled;
|
||||
}
|
||||
|
||||
otError otPlatRadioGetCoexMetrics(otInstance *aInstance, otRadioCoexMetrics *aCoexMetrics)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
assert(aInstance != NULL);
|
||||
otEXPECT_ACTION(aCoexMetrics != NULL, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
memset(aCoexMetrics, 0, sizeof(otRadioCoexMetrics));
|
||||
|
||||
aCoexMetrics->mStopped = false;
|
||||
aCoexMetrics->mNumGrantGlitch = 1;
|
||||
aCoexMetrics->mNumTxRequest = 2;
|
||||
aCoexMetrics->mNumTxGrantImmediate = 3;
|
||||
aCoexMetrics->mNumTxGrantWait = 4;
|
||||
aCoexMetrics->mNumTxGrantWaitActivated = 5;
|
||||
aCoexMetrics->mNumTxGrantWaitTimeout = 6;
|
||||
aCoexMetrics->mNumTxGrantDeactivatedDuringRequest = 7;
|
||||
aCoexMetrics->mNumTxDelayedGrant = 8;
|
||||
aCoexMetrics->mAvgTxRequestToGrantTime = 9;
|
||||
aCoexMetrics->mNumRxRequest = 10;
|
||||
aCoexMetrics->mNumRxGrantImmediate = 11;
|
||||
aCoexMetrics->mNumRxGrantWait = 12;
|
||||
aCoexMetrics->mNumRxGrantWaitActivated = 13;
|
||||
aCoexMetrics->mNumRxGrantWaitTimeout = 14;
|
||||
aCoexMetrics->mNumRxGrantDeactivatedDuringRequest = 15;
|
||||
aCoexMetrics->mNumRxDelayedGrant = 16;
|
||||
aCoexMetrics->mAvgRxRequestToGrantTime = 17;
|
||||
aCoexMetrics->mNumRxGrantNone = 18;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2016, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "platform-simulation.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <openthread/config.h>
|
||||
#include <openthread/platform/spi-slave.h>
|
||||
#include <openthread/platform/uart.h>
|
||||
|
||||
#if OPENTHREAD_CONFIG_NCP_SPI_ENABLE
|
||||
|
||||
// Spi-slave stubs
|
||||
|
||||
otError otPlatSpiSlaveEnable(otPlatSpiSlaveTransactionCompleteCallback aCompleteCallback,
|
||||
otPlatSpiSlaveTransactionProcessCallback aProcessCallback,
|
||||
void * aContext)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aCompleteCallback);
|
||||
OT_UNUSED_VARIABLE(aProcessCallback);
|
||||
OT_UNUSED_VARIABLE(aContext);
|
||||
|
||||
fprintf(stderr, "\nNo SPI support for simulation platform.");
|
||||
exit(0);
|
||||
|
||||
return OT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
void otPlatSpiSlaveDisable(void)
|
||||
{
|
||||
}
|
||||
|
||||
otError otPlatSpiSlavePrepareTransaction(uint8_t *aOutputBuf,
|
||||
uint16_t aOutputBufLen,
|
||||
uint8_t *aInputBuf,
|
||||
uint16_t aInputBufLen,
|
||||
bool aRequestTransactionFlag)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aOutputBuf);
|
||||
OT_UNUSED_VARIABLE(aOutputBufLen);
|
||||
OT_UNUSED_VARIABLE(aInputBuf);
|
||||
OT_UNUSED_VARIABLE(aInputBufLen);
|
||||
OT_UNUSED_VARIABLE(aRequestTransactionFlag);
|
||||
|
||||
return OT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// Uart
|
||||
|
||||
void otPlatUartSendDone(void)
|
||||
{
|
||||
}
|
||||
|
||||
void otPlatUartReceived(const uint8_t *aBuf, uint16_t aBufLength)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aBuf);
|
||||
OT_UNUSED_VARIABLE(aBufLength);
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_NCP_SPI_ENABLE
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright (c) 2016, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
* This file includes the platform-specific initializers.
|
||||
*/
|
||||
|
||||
#include "platform-simulation.h"
|
||||
|
||||
#if OPENTHREAD_SIMULATION_VIRTUAL_TIME == 0
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <libgen.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <openthread/tasklet.h>
|
||||
#include <openthread/platform/alarm-milli.h>
|
||||
|
||||
uint32_t gNodeId = 1;
|
||||
|
||||
extern bool gPlatformPseudoResetWasRequested;
|
||||
|
||||
static volatile bool gTerminate = false;
|
||||
|
||||
static void handleSignal(int aSignal)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aSignal);
|
||||
|
||||
gTerminate = true;
|
||||
}
|
||||
|
||||
void otSysInit(int aArgCount, char *aArgVector[])
|
||||
{
|
||||
char * endptr;
|
||||
uint32_t speedUpFactor = 1;
|
||||
|
||||
if (gPlatformPseudoResetWasRequested)
|
||||
{
|
||||
gPlatformPseudoResetWasRequested = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (aArgCount < 2)
|
||||
{
|
||||
fprintf(stderr, "Syntax:\n %s NodeId [TimeSpeedUpFactor]\n", aArgVector[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
openlog(basename(aArgVector[0]), LOG_PID, LOG_USER);
|
||||
setlogmask(setlogmask(0) & LOG_UPTO(LOG_NOTICE));
|
||||
|
||||
signal(SIGTERM, &handleSignal);
|
||||
signal(SIGHUP, &handleSignal);
|
||||
|
||||
gNodeId = (uint32_t)strtol(aArgVector[1], &endptr, 0);
|
||||
|
||||
if (*endptr != '\0' || gNodeId < 1 || gNodeId >= WELLKNOWN_NODE_ID)
|
||||
{
|
||||
fprintf(stderr, "Invalid NodeId: %s\n", aArgVector[1]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (aArgCount > 2)
|
||||
{
|
||||
speedUpFactor = (uint32_t)strtol(aArgVector[2], &endptr, 0);
|
||||
|
||||
if (*endptr != '\0' || speedUpFactor == 0)
|
||||
{
|
||||
fprintf(stderr, "Invalid value for TimerSpeedUpFactor: %s\n", aArgVector[2]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
platformAlarmInit(speedUpFactor);
|
||||
platformRadioInit();
|
||||
platformRandomInit();
|
||||
}
|
||||
|
||||
bool otSysPseudoResetWasRequested(void)
|
||||
{
|
||||
return gPlatformPseudoResetWasRequested;
|
||||
}
|
||||
|
||||
void otSysDeinit(void)
|
||||
{
|
||||
platformRadioDeinit();
|
||||
}
|
||||
|
||||
void otSysProcessDrivers(otInstance *aInstance)
|
||||
{
|
||||
fd_set read_fds;
|
||||
fd_set write_fds;
|
||||
fd_set error_fds;
|
||||
int max_fd = -1;
|
||||
struct timeval timeout;
|
||||
int rval;
|
||||
|
||||
FD_ZERO(&read_fds);
|
||||
FD_ZERO(&write_fds);
|
||||
FD_ZERO(&error_fds);
|
||||
|
||||
platformUartUpdateFdSet(&read_fds, &write_fds, &error_fds, &max_fd);
|
||||
platformRadioUpdateFdSet(&read_fds, &write_fds, &max_fd);
|
||||
platformAlarmUpdateTimeout(&timeout);
|
||||
|
||||
if (otTaskletsArePending(aInstance))
|
||||
{
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 0;
|
||||
}
|
||||
|
||||
rval = select(max_fd + 1, &read_fds, &write_fds, &error_fds, &timeout);
|
||||
|
||||
if (rval >= 0)
|
||||
{
|
||||
platformUartProcess();
|
||||
platformRadioProcess(aInstance, &read_fds, &write_fds);
|
||||
}
|
||||
else if (errno != EINTR)
|
||||
{
|
||||
perror("select");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
platformAlarmProcess(aInstance);
|
||||
|
||||
if (gTerminate)
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_SIMULATION_VIRTUAL_TIME == 0
|
||||
@@ -0,0 +1,365 @@
|
||||
/*
|
||||
* Copyright (c) 2016, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "platform-simulation.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <openthread/platform/debug_uart.h>
|
||||
#include <openthread/platform/uart.h>
|
||||
|
||||
#include "utils/code_utils.h"
|
||||
|
||||
#if OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART == 0
|
||||
#ifdef OPENTHREAD_TARGET_LINUX
|
||||
#include <sys/prctl.h>
|
||||
int posix_openpt(int oflag);
|
||||
int grantpt(int fildes);
|
||||
int unlockpt(int fd);
|
||||
char *ptsname(int fd);
|
||||
#endif // OPENTHREAD_TARGET_LINUX
|
||||
|
||||
static uint8_t s_receive_buffer[128];
|
||||
static const uint8_t *s_write_buffer;
|
||||
static uint16_t s_write_length;
|
||||
static int s_in_fd;
|
||||
static int s_out_fd;
|
||||
|
||||
static struct termios original_stdin_termios;
|
||||
static struct termios original_stdout_termios;
|
||||
|
||||
static void restore_stdin_termios(void)
|
||||
{
|
||||
tcsetattr(s_in_fd, TCSAFLUSH, &original_stdin_termios);
|
||||
}
|
||||
|
||||
static void restore_stdout_termios(void)
|
||||
{
|
||||
tcsetattr(s_out_fd, TCSAFLUSH, &original_stdout_termios);
|
||||
}
|
||||
|
||||
void platformUartRestore(void)
|
||||
{
|
||||
restore_stdin_termios();
|
||||
restore_stdout_termios();
|
||||
dup2(s_out_fd, STDOUT_FILENO);
|
||||
}
|
||||
|
||||
otError otPlatUartEnable(void)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
struct termios termios;
|
||||
|
||||
#ifdef OPENTHREAD_TARGET_LINUX
|
||||
// Ensure we terminate this process if the
|
||||
// parent process dies.
|
||||
prctl(PR_SET_PDEATHSIG, SIGHUP);
|
||||
#endif
|
||||
|
||||
s_in_fd = dup(STDIN_FILENO);
|
||||
s_out_fd = dup(STDOUT_FILENO);
|
||||
dup2(STDERR_FILENO, STDOUT_FILENO);
|
||||
|
||||
// We need this signal to make sure that this
|
||||
// process terminates properly.
|
||||
signal(SIGPIPE, SIG_DFL);
|
||||
|
||||
if (isatty(s_in_fd))
|
||||
{
|
||||
tcgetattr(s_in_fd, &original_stdin_termios);
|
||||
atexit(&restore_stdin_termios);
|
||||
}
|
||||
|
||||
if (isatty(s_out_fd))
|
||||
{
|
||||
tcgetattr(s_out_fd, &original_stdout_termios);
|
||||
atexit(&restore_stdout_termios);
|
||||
}
|
||||
|
||||
if (isatty(s_in_fd))
|
||||
{
|
||||
// get current configuration
|
||||
otEXPECT_ACTION(tcgetattr(s_in_fd, &termios) == 0, perror("tcgetattr"); error = OT_ERROR_GENERIC);
|
||||
|
||||
// Set up the termios settings for raw mode. This turns
|
||||
// off input/output processing, line processing, and character processing.
|
||||
cfmakeraw(&termios);
|
||||
|
||||
// Set up our cflags for local use. Turn on hangup-on-close.
|
||||
termios.c_cflag |= HUPCL | CREAD | CLOCAL;
|
||||
|
||||
// "Minimum number of characters for noncanonical read"
|
||||
termios.c_cc[VMIN] = 1;
|
||||
|
||||
// "Timeout in deciseconds for noncanonical read"
|
||||
termios.c_cc[VTIME] = 0;
|
||||
|
||||
// configure baud rate
|
||||
otEXPECT_ACTION(cfsetispeed(&termios, OPENTHREAD_SIMULATION_UART_BAUDRATE) == 0, perror("cfsetispeed");
|
||||
error = OT_ERROR_GENERIC);
|
||||
|
||||
// set configuration
|
||||
otEXPECT_ACTION(tcsetattr(s_in_fd, TCSANOW, &termios) == 0, perror("tcsetattr"); error = OT_ERROR_GENERIC);
|
||||
}
|
||||
|
||||
if (isatty(s_out_fd))
|
||||
{
|
||||
// get current configuration
|
||||
otEXPECT_ACTION(tcgetattr(s_out_fd, &termios) == 0, perror("tcgetattr"); error = OT_ERROR_GENERIC);
|
||||
|
||||
// Set up the termios settings for raw mode. This turns
|
||||
// off input/output processing, line processing, and character processing.
|
||||
cfmakeraw(&termios);
|
||||
|
||||
// Absolutely obliterate all output processing.
|
||||
termios.c_oflag = 0;
|
||||
|
||||
// Set up our cflags for local use. Turn on hangup-on-close.
|
||||
termios.c_cflag |= HUPCL | CREAD | CLOCAL;
|
||||
|
||||
// configure baud rate
|
||||
otEXPECT_ACTION(cfsetospeed(&termios, OPENTHREAD_SIMULATION_UART_BAUDRATE) == 0, perror("cfsetospeed");
|
||||
error = OT_ERROR_GENERIC);
|
||||
|
||||
// set configuration
|
||||
otEXPECT_ACTION(tcsetattr(s_out_fd, TCSANOW, &termios) == 0, perror("tcsetattr"); error = OT_ERROR_GENERIC);
|
||||
}
|
||||
|
||||
return error;
|
||||
|
||||
exit:
|
||||
close(s_in_fd);
|
||||
close(s_out_fd);
|
||||
return error;
|
||||
}
|
||||
|
||||
otError otPlatUartDisable(void)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
close(s_in_fd);
|
||||
close(s_out_fd);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
otEXPECT_ACTION(s_write_length == 0, error = OT_ERROR_BUSY);
|
||||
|
||||
s_write_buffer = aBuf;
|
||||
s_write_length = aBufLength;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void platformUartUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, fd_set *aErrorFdSet, int *aMaxFd)
|
||||
{
|
||||
if (aReadFdSet != NULL)
|
||||
{
|
||||
FD_SET(s_in_fd, aReadFdSet);
|
||||
|
||||
if (aErrorFdSet != NULL)
|
||||
{
|
||||
FD_SET(s_in_fd, aErrorFdSet);
|
||||
}
|
||||
|
||||
if (aMaxFd != NULL && *aMaxFd < s_in_fd)
|
||||
{
|
||||
*aMaxFd = s_in_fd;
|
||||
}
|
||||
}
|
||||
|
||||
if ((aWriteFdSet != NULL) && (s_write_length > 0))
|
||||
{
|
||||
FD_SET(s_out_fd, aWriteFdSet);
|
||||
|
||||
if (aErrorFdSet != NULL)
|
||||
{
|
||||
FD_SET(s_out_fd, aErrorFdSet);
|
||||
}
|
||||
|
||||
if (aMaxFd != NULL && *aMaxFd < s_out_fd)
|
||||
{
|
||||
*aMaxFd = s_out_fd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
otError otPlatUartFlush(void)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
ssize_t count;
|
||||
|
||||
otEXPECT_ACTION(s_write_buffer != NULL && s_write_length > 0, error = OT_ERROR_INVALID_STATE);
|
||||
|
||||
while ((count = write(s_out_fd, s_write_buffer, s_write_length)) > 0 && (s_write_length -= count) > 0)
|
||||
{
|
||||
s_write_buffer += count;
|
||||
}
|
||||
|
||||
if (count != -1)
|
||||
{
|
||||
assert(s_write_length == 0);
|
||||
s_write_buffer = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
perror("write(UART)");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void platformUartProcess(void)
|
||||
{
|
||||
ssize_t rval;
|
||||
const int error_flags = POLLERR | POLLNVAL | POLLHUP;
|
||||
struct pollfd pollfd[] = {
|
||||
{s_in_fd, POLLIN | error_flags, 0},
|
||||
{s_out_fd, POLLOUT | error_flags, 0},
|
||||
};
|
||||
|
||||
errno = 0;
|
||||
|
||||
rval = poll(pollfd, sizeof(pollfd) / sizeof(*pollfd), 0);
|
||||
|
||||
if (rval < 0)
|
||||
{
|
||||
perror("poll");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (rval > 0)
|
||||
{
|
||||
if ((pollfd[0].revents & error_flags) != 0)
|
||||
{
|
||||
perror("s_in_fd");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if ((pollfd[1].revents & error_flags) != 0)
|
||||
{
|
||||
perror("s_out_fd");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (pollfd[0].revents & POLLIN)
|
||||
{
|
||||
rval = read(s_in_fd, s_receive_buffer, sizeof(s_receive_buffer));
|
||||
|
||||
if (rval <= 0)
|
||||
{
|
||||
perror("read");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
otPlatUartReceived(s_receive_buffer, (uint16_t)rval);
|
||||
}
|
||||
|
||||
if ((s_write_length > 0) && (pollfd[1].revents & POLLOUT))
|
||||
{
|
||||
rval = write(s_out_fd, s_write_buffer, s_write_length);
|
||||
|
||||
if (rval >= 0)
|
||||
{
|
||||
s_write_buffer += (uint16_t)rval;
|
||||
s_write_length -= (uint16_t)rval;
|
||||
|
||||
if (s_write_length == 0)
|
||||
{
|
||||
otPlatUartSendDone();
|
||||
}
|
||||
}
|
||||
else if (errno != EINTR)
|
||||
{
|
||||
perror("write");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART == 0
|
||||
|
||||
#if OPENTHREAD_CONFIG_ENABLE_DEBUG_UART && (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_DEBUG_UART)
|
||||
|
||||
static FILE *posix_logfile;
|
||||
|
||||
otError otPlatDebugUart_logfile(const char *filename)
|
||||
{
|
||||
posix_logfile = fopen(filename, "wt");
|
||||
|
||||
return posix_logfile ? OT_ERROR_NONE : OT_ERROR_FAILED;
|
||||
}
|
||||
|
||||
void otPlatDebugUart_putchar_raw(int c)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
/* note: log file will have a mix of cr/lf and
|
||||
* in some/many cases duplicate cr because in
|
||||
* some cases the log function {ie: Mbed} already
|
||||
* includes the CR or LF... but other log functions
|
||||
* do not include cr/lf and expect it appended
|
||||
*/
|
||||
fp = posix_logfile;
|
||||
|
||||
if (fp != NULL)
|
||||
{
|
||||
/* log is lost ... until a file is setup */
|
||||
fputc(c, fp);
|
||||
/* we could "fflush" but will not */
|
||||
}
|
||||
}
|
||||
|
||||
int otPlatDebugUart_kbhit(void)
|
||||
{
|
||||
/* not supported */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int otPlatDebugUart_getc(void)
|
||||
{
|
||||
/* not supported */
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright (c) 2018, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "platform-simulation.h"
|
||||
|
||||
#if OPENTHREAD_SIMULATION_VIRTUAL_TIME
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openthread/platform/alarm-micro.h>
|
||||
#include <openthread/platform/alarm-milli.h>
|
||||
#include <openthread/platform/diag.h>
|
||||
|
||||
#define US_PER_MS 1000
|
||||
|
||||
extern uint64_t sNow; // microseconds
|
||||
|
||||
static bool sIsMsRunning = false;
|
||||
static uint32_t sMsAlarm = 0;
|
||||
|
||||
static bool sIsUsRunning = false;
|
||||
static uint32_t sUsAlarm = 0;
|
||||
|
||||
void platformAlarmInit(uint32_t aSpeedUpFactor)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aSpeedUpFactor);
|
||||
|
||||
sNow = 0;
|
||||
}
|
||||
|
||||
uint64_t platformAlarmGetNow(void)
|
||||
{
|
||||
return sNow;
|
||||
}
|
||||
|
||||
void platformAlarmAdvanceNow(uint64_t aDelta)
|
||||
{
|
||||
sNow += aDelta;
|
||||
}
|
||||
|
||||
uint32_t otPlatAlarmMilliGetNow(void)
|
||||
{
|
||||
return (uint32_t)(sNow / US_PER_MS);
|
||||
}
|
||||
|
||||
void otPlatAlarmMilliStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
sMsAlarm = aT0 + aDt;
|
||||
sIsMsRunning = true;
|
||||
}
|
||||
|
||||
void otPlatAlarmMilliStop(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
sIsMsRunning = false;
|
||||
}
|
||||
|
||||
uint32_t otPlatAlarmMicroGetNow(void)
|
||||
{
|
||||
return (uint32_t)sNow;
|
||||
}
|
||||
|
||||
void otPlatAlarmMicroStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
sUsAlarm = aT0 + aDt;
|
||||
sIsUsRunning = true;
|
||||
}
|
||||
|
||||
void otPlatAlarmMicroStop(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
sIsUsRunning = false;
|
||||
}
|
||||
|
||||
int32_t platformAlarmGetNext(void)
|
||||
{
|
||||
int32_t remaining = INT32_MAX;
|
||||
|
||||
if (sIsMsRunning)
|
||||
{
|
||||
int32_t milli = (int32_t)(sMsAlarm - otPlatAlarmMilliGetNow());
|
||||
|
||||
remaining = milli * US_PER_MS;
|
||||
|
||||
if (remaining < 0 && milli > 0)
|
||||
{
|
||||
remaining = INT32_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
|
||||
|
||||
if (sIsUsRunning)
|
||||
{
|
||||
int32_t micro = (int32_t)(sUsAlarm - otPlatAlarmMicroGetNow());
|
||||
|
||||
if (remaining > micro)
|
||||
{
|
||||
remaining = micro;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
|
||||
|
||||
return remaining;
|
||||
}
|
||||
|
||||
void platformAlarmProcess(otInstance *aInstance)
|
||||
{
|
||||
int32_t remaining;
|
||||
|
||||
if (sIsMsRunning)
|
||||
{
|
||||
remaining = (int32_t)(sMsAlarm - otPlatAlarmMilliGetNow());
|
||||
|
||||
if (remaining <= 0)
|
||||
{
|
||||
sIsMsRunning = false;
|
||||
|
||||
#if OPENTHREAD_CONFIG_DIAG_ENABLE
|
||||
|
||||
if (otPlatDiagModeGet())
|
||||
{
|
||||
otPlatDiagAlarmFired(aInstance);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
otPlatAlarmMilliFired(aInstance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
|
||||
|
||||
if (sIsUsRunning)
|
||||
{
|
||||
remaining = (int32_t)(sUsAlarm - otPlatAlarmMicroGetNow());
|
||||
|
||||
if (remaining <= 0)
|
||||
{
|
||||
sIsUsRunning = false;
|
||||
|
||||
otPlatAlarmMicroFired(aInstance);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
|
||||
}
|
||||
|
||||
uint64_t otPlatTimeGet(void)
|
||||
{
|
||||
return platformAlarmGetNow();
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
uint16_t otPlatTimeGetXtalAccuracy(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // OPENTHREAD_SIMULATION_VIRTUAL_TIME
|
||||
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
* Copyright (c) 2018, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
* This file includes the platform-specific initializers.
|
||||
*/
|
||||
|
||||
#include "platform-simulation.h"
|
||||
|
||||
#if OPENTHREAD_SIMULATION_VIRTUAL_TIME
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <libgen.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <openthread/tasklet.h>
|
||||
#include <openthread/platform/alarm-milli.h>
|
||||
#include <openthread/platform/uart.h>
|
||||
|
||||
uint32_t gNodeId = 1;
|
||||
|
||||
extern bool gPlatformPseudoResetWasRequested;
|
||||
static volatile bool gTerminate = false;
|
||||
|
||||
int gArgumentsCount = 0;
|
||||
char **gArguments = NULL;
|
||||
|
||||
uint64_t sNow = 0; // microseconds
|
||||
int sSockFd;
|
||||
uint16_t sPortOffset;
|
||||
|
||||
static void handleSignal(int aSignal)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aSignal);
|
||||
|
||||
gTerminate = true;
|
||||
}
|
||||
|
||||
void otSimSendEvent(const struct Event *aEvent)
|
||||
{
|
||||
ssize_t rval;
|
||||
struct sockaddr_in sockaddr;
|
||||
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
sockaddr.sin_family = AF_INET;
|
||||
inet_pton(AF_INET, "127.0.0.1", &sockaddr.sin_addr);
|
||||
sockaddr.sin_port = htons(9000 + sPortOffset);
|
||||
|
||||
rval = sendto(sSockFd, aEvent, offsetof(struct Event, mData) + aEvent->mDataLength, 0, (struct sockaddr *)&sockaddr,
|
||||
sizeof(sockaddr));
|
||||
|
||||
if (rval < 0)
|
||||
{
|
||||
perror("sendto");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
static void receiveEvent(otInstance *aInstance)
|
||||
{
|
||||
struct Event event;
|
||||
ssize_t rval = recvfrom(sSockFd, (char *)&event, sizeof(event), 0, NULL, NULL);
|
||||
|
||||
if (rval < 0 || (uint16_t)rval < offsetof(struct Event, mData))
|
||||
{
|
||||
perror("recvfrom");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
platformAlarmAdvanceNow(event.mDelay);
|
||||
|
||||
switch (event.mEvent)
|
||||
{
|
||||
case OT_SIM_EVENT_ALARM_FIRED:
|
||||
break;
|
||||
|
||||
case OT_SIM_EVENT_RADIO_RECEIVED:
|
||||
platformRadioReceive(aInstance, event.mData, event.mDataLength);
|
||||
break;
|
||||
|
||||
case OT_SIM_EVENT_UART_WRITE:
|
||||
otPlatUartReceived(event.mData, event.mDataLength);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
static void platformSendSleepEvent(void)
|
||||
{
|
||||
struct Event event;
|
||||
|
||||
assert(platformAlarmGetNext() > 0);
|
||||
|
||||
event.mDelay = (uint64_t)platformAlarmGetNext();
|
||||
event.mEvent = OT_SIM_EVENT_ALARM_FIRED;
|
||||
event.mDataLength = 0;
|
||||
|
||||
otSimSendEvent(&event);
|
||||
}
|
||||
|
||||
#if OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART
|
||||
void platformUartRestore(void)
|
||||
{
|
||||
}
|
||||
|
||||
otError otPlatUartEnable(void)
|
||||
{
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
otError otPlatUartDisable(void)
|
||||
{
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
otError otPlatUartSend(const uint8_t *aData, uint16_t aLength)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
struct Event event;
|
||||
|
||||
event.mDelay = 0;
|
||||
event.mEvent = OT_SIM_EVENT_UART_WRITE;
|
||||
event.mDataLength = aLength;
|
||||
|
||||
memcpy(event.mData, aData, aLength);
|
||||
|
||||
otSimSendEvent(&event);
|
||||
|
||||
otPlatUartSendDone();
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
otError otPlatUartFlush(void)
|
||||
{
|
||||
return OT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
#endif // OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART
|
||||
|
||||
static void socket_init(void)
|
||||
{
|
||||
struct sockaddr_in sockaddr;
|
||||
char * offset;
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
sockaddr.sin_family = AF_INET;
|
||||
|
||||
offset = getenv("PORT_OFFSET");
|
||||
|
||||
if (offset)
|
||||
{
|
||||
char *endptr;
|
||||
|
||||
sPortOffset = (uint16_t)strtol(offset, &endptr, 0);
|
||||
|
||||
if (*endptr != '\0')
|
||||
{
|
||||
fprintf(stderr, "Invalid PORT_OFFSET: %s\n", offset);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
sPortOffset *= WELLKNOWN_NODE_ID;
|
||||
}
|
||||
|
||||
sockaddr.sin_port = htons(9000 + sPortOffset + gNodeId);
|
||||
sockaddr.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
sSockFd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
|
||||
if (sSockFd == -1)
|
||||
{
|
||||
perror("socket");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (bind(sSockFd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) == -1)
|
||||
{
|
||||
perror("bind");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void otSysInit(int argc, char *argv[])
|
||||
{
|
||||
char *endptr;
|
||||
|
||||
if (gPlatformPseudoResetWasRequested)
|
||||
{
|
||||
gPlatformPseudoResetWasRequested = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
openlog(basename(argv[0]), LOG_PID, LOG_USER);
|
||||
setlogmask(setlogmask(0) & LOG_UPTO(LOG_NOTICE));
|
||||
|
||||
gArgumentsCount = argc;
|
||||
gArguments = argv;
|
||||
|
||||
gNodeId = (uint32_t)strtol(argv[1], &endptr, 0);
|
||||
|
||||
if (*endptr != '\0' || gNodeId < 1 || gNodeId >= WELLKNOWN_NODE_ID)
|
||||
{
|
||||
fprintf(stderr, "Invalid NodeId: %s\n", argv[1]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
socket_init();
|
||||
|
||||
platformAlarmInit(1);
|
||||
platformRadioInit();
|
||||
platformRandomInit();
|
||||
|
||||
signal(SIGTERM, &handleSignal);
|
||||
signal(SIGHUP, &handleSignal);
|
||||
}
|
||||
|
||||
bool otSysPseudoResetWasRequested(void)
|
||||
{
|
||||
return gPlatformPseudoResetWasRequested;
|
||||
}
|
||||
|
||||
void otSysDeinit(void)
|
||||
{
|
||||
close(sSockFd);
|
||||
}
|
||||
|
||||
void otSysProcessDrivers(otInstance *aInstance)
|
||||
{
|
||||
fd_set read_fds;
|
||||
fd_set write_fds;
|
||||
fd_set error_fds;
|
||||
int max_fd = -1;
|
||||
int rval;
|
||||
|
||||
if (gTerminate)
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
|
||||
FD_ZERO(&read_fds);
|
||||
FD_ZERO(&write_fds);
|
||||
FD_ZERO(&error_fds);
|
||||
|
||||
FD_SET(sSockFd, &read_fds);
|
||||
max_fd = sSockFd;
|
||||
|
||||
#if OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART == 0
|
||||
platformUartUpdateFdSet(&read_fds, &write_fds, &error_fds, &max_fd);
|
||||
#endif
|
||||
|
||||
if (!otTaskletsArePending(aInstance) && platformAlarmGetNext() > 0 && !platformRadioIsTransmitPending())
|
||||
{
|
||||
platformSendSleepEvent();
|
||||
|
||||
rval = select(max_fd + 1, &read_fds, &write_fds, &error_fds, NULL);
|
||||
|
||||
if ((rval < 0) && (errno != EINTR))
|
||||
{
|
||||
perror("select");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (rval > 0 && FD_ISSET(sSockFd, &read_fds))
|
||||
{
|
||||
receiveEvent(aInstance);
|
||||
}
|
||||
}
|
||||
|
||||
platformAlarmProcess(aInstance);
|
||||
platformRadioProcess(aInstance, &read_fds, &write_fds);
|
||||
#if OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART == 0
|
||||
platformUartProcess();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_SIMULATION_VIRTUAL_TIME
|
||||
Reference in New Issue
Block a user