[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:
Yakun Xu
2020-02-27 12:55:56 -08:00
committed by GitHub
parent fb16fd44d7
commit a551133493
48 changed files with 205 additions and 205 deletions
@@ -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)
+78
View File
@@ -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
+72
View File
@@ -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
```
+319
View File
@@ -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
+80
View File
@@ -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
+136
View File
@@ -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;
}
+164
View File
@@ -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;
}
+80
View File
@@ -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)
+101
View File
@@ -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_
+884
View File
@@ -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
+87
View File
@@ -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
+165
View File
@@ -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
+365
View File
@@ -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