mirror of
https://github.com/espressif/openthread.git
synced 2026-08-12 21:57:47 +00:00
Initial commit
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
#
|
||||
# Copyright (c) 2016, Nest Labs, Inc.
|
||||
# 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
|
||||
|
||||
# Always package (e.g. for 'make dist') these subdirectories.
|
||||
|
||||
DIST_SUBDIRS = \
|
||||
posix \
|
||||
$(NULL)
|
||||
|
||||
# Always build (e.g. for 'make all') these subdirectories.
|
||||
|
||||
SUBDIRS = \
|
||||
posix \
|
||||
$(NULL)
|
||||
|
||||
all:
|
||||
|
||||
include $(abs_top_nlbuild_autotools_dir)/automake/post.am
|
||||
@@ -0,0 +1,71 @@
|
||||
#
|
||||
# Copyright (c) 2016, Nest Labs, Inc.
|
||||
# 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-posix.a
|
||||
|
||||
libopenthread_posix_a_CPPFLAGS = \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/src/core \
|
||||
-I$(top_srcdir)/examples \
|
||||
-I$(top_srcdir)/examples/platform/posix \
|
||||
$(OPENTHREAD_TARGET_DEFINES) \
|
||||
-D_BSD_SOURCE \
|
||||
-D_GNU_SOURCE \
|
||||
$(NULL)
|
||||
|
||||
libopenthread_posix_a_CXXFLAGS = \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/src/core \
|
||||
-I$(top_srcdir)/examplse \
|
||||
-I$(top_srcdir)/examples/platform/posix \
|
||||
$(OPENTHREAD_TARGET_DEFINES) \
|
||||
$(NULL)
|
||||
|
||||
libopenthread_posix_a_SOURCES = \
|
||||
alarm.c \
|
||||
atomic.c \
|
||||
cmdline.c \
|
||||
logging.c \
|
||||
radio.cpp \
|
||||
random.c \
|
||||
serial.c \
|
||||
$(NULL)
|
||||
|
||||
include_HEADERS = \
|
||||
$(NULL)
|
||||
|
||||
install-headers: install-includeHEADERS
|
||||
|
||||
if OPENTHREAD_BUILD_COVERAGE
|
||||
CLEANFILES = $(wildcard *.gcda *.gcno)
|
||||
endif # OPENTHREAD_BUILD_COVERAGE
|
||||
|
||||
include $(abs_top_nlbuild_autotools_dir)/automake/post.am
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* 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 <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <platform/alarm.h>
|
||||
|
||||
static void *alarm_thread(void *arg);
|
||||
|
||||
static bool s_is_running = false;
|
||||
static uint32_t s_alarm = 0;
|
||||
static struct timeval s_start;
|
||||
|
||||
static pthread_t s_thread;
|
||||
static pthread_mutex_t s_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_cond_t s_cond = PTHREAD_COND_INITIALIZER;
|
||||
|
||||
void hwAlarmInit(void)
|
||||
{
|
||||
gettimeofday(&s_start, NULL);
|
||||
pthread_create(&s_thread, NULL, alarm_thread, NULL);
|
||||
}
|
||||
|
||||
uint32_t otPlatAlarmGetNow(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
timersub(&tv, &s_start, &tv);
|
||||
|
||||
return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
|
||||
}
|
||||
|
||||
void otPlatAlarmStartAt(uint32_t t0, uint32_t dt)
|
||||
{
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
s_alarm = t0 + dt;
|
||||
s_is_running = true;
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
pthread_cond_signal(&s_cond);
|
||||
}
|
||||
|
||||
void otPlatAlarmStop(void)
|
||||
{
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
s_is_running = false;
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
}
|
||||
|
||||
void *alarm_thread(void *arg)
|
||||
{
|
||||
int32_t remaining;
|
||||
struct timeval tva;
|
||||
struct timeval tvb;
|
||||
struct timespec ts;
|
||||
|
||||
while (1)
|
||||
{
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
|
||||
if (!s_is_running)
|
||||
{
|
||||
// alarm is not running, wait indefinitely
|
||||
pthread_cond_wait(&s_cond, &s_mutex);
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// alarm is running
|
||||
remaining = s_alarm - otPlatAlarmGetNow();
|
||||
|
||||
if (remaining > 0)
|
||||
{
|
||||
// alarm has not passed, wait
|
||||
gettimeofday(&tva, NULL);
|
||||
tvb.tv_sec = remaining / 1000;
|
||||
tvb.tv_usec = (remaining % 1000) * 1000;
|
||||
timeradd(&tva, &tvb, &tva);
|
||||
|
||||
ts.tv_sec = tva.tv_sec;
|
||||
ts.tv_nsec = tva.tv_usec * 1000;
|
||||
|
||||
pthread_cond_timedwait(&s_cond, &s_mutex, &ts);
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// alarm has passed, signal
|
||||
s_is_running = false;
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
otPlatAlarmSignalFired();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* 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 <pthread.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <platform/atomic.h>
|
||||
#include <platform/posix/platform.h>
|
||||
|
||||
static pthread_mutex_t s_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_cond_t s_cond = PTHREAD_COND_INITIALIZER;
|
||||
|
||||
uint32_t otPlatAtomicBegin(void)
|
||||
{
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void otPlatAtomicEnd(uint32_t state)
|
||||
{
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
pthread_cond_signal(&s_cond);
|
||||
}
|
||||
|
||||
void hwSleep(void)
|
||||
{
|
||||
pthread_cond_wait(&s_cond, &s_mutex);
|
||||
}
|
||||
@@ -0,0 +1,587 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* 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 autogenerated by gengetopt version 2.22.6
|
||||
generated with the following command:
|
||||
gengetopt -i cmdline.ggo
|
||||
|
||||
The developers of gengetopt consider the fixed text that goes in all
|
||||
gengetopt output files to be in the public domain:
|
||||
we make no copyright claims on it.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef FIX_UNUSED
|
||||
#define FIX_UNUSED(X) (void) (X) /* avoid warnings for unused params */
|
||||
#endif
|
||||
|
||||
#include <getopt.h>
|
||||
|
||||
#include "cmdline.h"
|
||||
|
||||
const char *gengetopt_args_info_purpose = "";
|
||||
|
||||
const char *gengetopt_args_info_usage = "Usage: thread [OPTIONS]...";
|
||||
|
||||
const char *gengetopt_args_info_versiontext = "";
|
||||
|
||||
const char *gengetopt_args_info_description = "";
|
||||
|
||||
const char *gengetopt_args_info_help[] = {
|
||||
" -h, --help Print help and exit",
|
||||
" -V, --version Print version and exit",
|
||||
" --nodeid=INT Node ID",
|
||||
" -S, --stdserial Use stdin/stdout for serial (default=on)",
|
||||
0
|
||||
};
|
||||
|
||||
typedef enum {ARG_NO
|
||||
, ARG_FLAG
|
||||
, ARG_INT
|
||||
} cmdline_parser_arg_type;
|
||||
|
||||
static
|
||||
void clear_given (struct gengetopt_args_info *args_info);
|
||||
static
|
||||
void clear_args (struct gengetopt_args_info *args_info);
|
||||
|
||||
static int
|
||||
cmdline_parser_internal (int argc, char **argv, struct gengetopt_args_info *args_info,
|
||||
struct cmdline_parser_params *params, const char *additional_error);
|
||||
|
||||
static int
|
||||
cmdline_parser_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error);
|
||||
|
||||
static char *
|
||||
gengetopt_strdup (const char *s);
|
||||
|
||||
static
|
||||
void clear_given (struct gengetopt_args_info *args_info)
|
||||
{
|
||||
args_info->help_given = 0 ;
|
||||
args_info->version_given = 0 ;
|
||||
args_info->nodeid_given = 0 ;
|
||||
args_info->stdserial_given = 0 ;
|
||||
}
|
||||
|
||||
static
|
||||
void clear_args (struct gengetopt_args_info *args_info)
|
||||
{
|
||||
FIX_UNUSED (args_info);
|
||||
args_info->nodeid_orig = NULL;
|
||||
args_info->stdserial_flag = 1;
|
||||
|
||||
}
|
||||
|
||||
static
|
||||
void init_args_info(struct gengetopt_args_info *args_info)
|
||||
{
|
||||
|
||||
|
||||
args_info->help_help = gengetopt_args_info_help[0] ;
|
||||
args_info->version_help = gengetopt_args_info_help[1] ;
|
||||
args_info->nodeid_help = gengetopt_args_info_help[2] ;
|
||||
args_info->stdserial_help = gengetopt_args_info_help[3] ;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
cmdline_parser_print_version (void)
|
||||
{
|
||||
printf ("%s %s\n",
|
||||
(strlen(CMDLINE_PARSER_PACKAGE_NAME) ? CMDLINE_PARSER_PACKAGE_NAME : CMDLINE_PARSER_PACKAGE),
|
||||
CMDLINE_PARSER_VERSION);
|
||||
|
||||
if (strlen(gengetopt_args_info_versiontext) > 0)
|
||||
printf("\n%s\n", gengetopt_args_info_versiontext);
|
||||
}
|
||||
|
||||
static void print_help_common(void) {
|
||||
cmdline_parser_print_version ();
|
||||
|
||||
if (strlen(gengetopt_args_info_purpose) > 0)
|
||||
printf("\n%s\n", gengetopt_args_info_purpose);
|
||||
|
||||
if (strlen(gengetopt_args_info_usage) > 0)
|
||||
printf("\n%s\n", gengetopt_args_info_usage);
|
||||
|
||||
printf("\n");
|
||||
|
||||
if (strlen(gengetopt_args_info_description) > 0)
|
||||
printf("%s\n\n", gengetopt_args_info_description);
|
||||
}
|
||||
|
||||
void
|
||||
cmdline_parser_print_help (void)
|
||||
{
|
||||
int i = 0;
|
||||
print_help_common();
|
||||
while (gengetopt_args_info_help[i])
|
||||
printf("%s\n", gengetopt_args_info_help[i++]);
|
||||
}
|
||||
|
||||
void
|
||||
cmdline_parser_init (struct gengetopt_args_info *args_info)
|
||||
{
|
||||
clear_given (args_info);
|
||||
clear_args (args_info);
|
||||
init_args_info (args_info);
|
||||
}
|
||||
|
||||
void
|
||||
cmdline_parser_params_init(struct cmdline_parser_params *params)
|
||||
{
|
||||
if (params)
|
||||
{
|
||||
params->override = 0;
|
||||
params->initialize = 1;
|
||||
params->check_required = 1;
|
||||
params->check_ambiguity = 0;
|
||||
params->print_errors = 1;
|
||||
}
|
||||
}
|
||||
|
||||
struct cmdline_parser_params *
|
||||
cmdline_parser_params_create(void)
|
||||
{
|
||||
struct cmdline_parser_params *params =
|
||||
(struct cmdline_parser_params *)malloc(sizeof(struct cmdline_parser_params));
|
||||
cmdline_parser_params_init(params);
|
||||
return params;
|
||||
}
|
||||
|
||||
static void
|
||||
free_string_field (char **s)
|
||||
{
|
||||
if (*s)
|
||||
{
|
||||
free (*s);
|
||||
*s = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cmdline_parser_release (struct gengetopt_args_info *args_info)
|
||||
{
|
||||
|
||||
free_string_field (&(args_info->nodeid_orig));
|
||||
|
||||
|
||||
|
||||
clear_given (args_info);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
write_into_file(FILE *outfile, const char *opt, const char *arg, const char *values[])
|
||||
{
|
||||
FIX_UNUSED (values);
|
||||
if (arg) {
|
||||
fprintf(outfile, "%s=\"%s\"\n", opt, arg);
|
||||
} else {
|
||||
fprintf(outfile, "%s\n", opt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if (!outfile)
|
||||
{
|
||||
fprintf (stderr, "%s: cannot dump options to stream\n", CMDLINE_PARSER_PACKAGE);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (args_info->help_given)
|
||||
write_into_file(outfile, "help", 0, 0 );
|
||||
if (args_info->version_given)
|
||||
write_into_file(outfile, "version", 0, 0 );
|
||||
if (args_info->nodeid_given)
|
||||
write_into_file(outfile, "nodeid", args_info->nodeid_orig, 0);
|
||||
if (args_info->stdserial_given)
|
||||
write_into_file(outfile, "stdserial", 0, 0 );
|
||||
|
||||
|
||||
i = EXIT_SUCCESS;
|
||||
return i;
|
||||
}
|
||||
|
||||
int
|
||||
cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info)
|
||||
{
|
||||
FILE *outfile;
|
||||
int i = 0;
|
||||
|
||||
outfile = fopen(filename, "w");
|
||||
|
||||
if (!outfile)
|
||||
{
|
||||
fprintf (stderr, "%s: cannot open file for writing: %s\n", CMDLINE_PARSER_PACKAGE, filename);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
i = cmdline_parser_dump(outfile, args_info);
|
||||
fclose (outfile);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void
|
||||
cmdline_parser_free (struct gengetopt_args_info *args_info)
|
||||
{
|
||||
cmdline_parser_release (args_info);
|
||||
}
|
||||
|
||||
/** @brief replacement of strdup, which is not standard */
|
||||
char *
|
||||
gengetopt_strdup (const char *s)
|
||||
{
|
||||
char *result = 0;
|
||||
if (!s)
|
||||
return result;
|
||||
|
||||
result = (char*)malloc(strlen(s) + 1);
|
||||
if (result == (char*)0)
|
||||
return (char*)0;
|
||||
strcpy(result, s);
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
cmdline_parser (int argc, char **argv, struct gengetopt_args_info *args_info)
|
||||
{
|
||||
return cmdline_parser2 (argc, argv, args_info, 0, 1, 1);
|
||||
}
|
||||
|
||||
int
|
||||
cmdline_parser_ext (int argc, char **argv, struct gengetopt_args_info *args_info,
|
||||
struct cmdline_parser_params *params)
|
||||
{
|
||||
int result;
|
||||
result = cmdline_parser_internal (argc, argv, args_info, params, 0);
|
||||
|
||||
if (result == EXIT_FAILURE)
|
||||
{
|
||||
cmdline_parser_free (args_info);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
cmdline_parser2 (int argc, char **argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required)
|
||||
{
|
||||
int result;
|
||||
struct cmdline_parser_params params;
|
||||
|
||||
params.override = override;
|
||||
params.initialize = initialize;
|
||||
params.check_required = check_required;
|
||||
params.check_ambiguity = 0;
|
||||
params.print_errors = 1;
|
||||
|
||||
result = cmdline_parser_internal (argc, argv, args_info, ¶ms, 0);
|
||||
|
||||
if (result == EXIT_FAILURE)
|
||||
{
|
||||
cmdline_parser_free (args_info);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name)
|
||||
{
|
||||
int result = EXIT_SUCCESS;
|
||||
|
||||
if (cmdline_parser_required2(args_info, prog_name, 0) > 0)
|
||||
result = EXIT_FAILURE;
|
||||
|
||||
if (result == EXIT_FAILURE)
|
||||
{
|
||||
cmdline_parser_free (args_info);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
cmdline_parser_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error)
|
||||
{
|
||||
int error_occurred = 0;
|
||||
FIX_UNUSED (additional_error);
|
||||
|
||||
/* checks for required options */
|
||||
if (! args_info->nodeid_given)
|
||||
{
|
||||
fprintf (stderr, "%s: '--nodeid' option required%s\n", prog_name, (additional_error ? additional_error : ""));
|
||||
error_occurred = 1;
|
||||
}
|
||||
|
||||
|
||||
/* checks for dependences among options */
|
||||
|
||||
return error_occurred;
|
||||
}
|
||||
|
||||
|
||||
static char *package_name = 0;
|
||||
|
||||
/**
|
||||
* @brief updates an option
|
||||
* @param field the generic pointer to the field to update
|
||||
* @param orig_field the pointer to the orig field
|
||||
* @param field_given the pointer to the number of occurrence of this option
|
||||
* @param prev_given the pointer to the number of occurrence already seen
|
||||
* @param value the argument for this option (if null no arg was specified)
|
||||
* @param possible_values the possible values for this option (if specified)
|
||||
* @param default_value the default value (in case the option only accepts fixed values)
|
||||
* @param arg_type the type of this option
|
||||
* @param check_ambiguity @see cmdline_parser_params.check_ambiguity
|
||||
* @param override @see cmdline_parser_params.override
|
||||
* @param no_free whether to free a possible previous value
|
||||
* @param multiple_option whether this is a multiple option
|
||||
* @param long_opt the corresponding long option
|
||||
* @param short_opt the corresponding short option (or '-' if none)
|
||||
* @param additional_error possible further error specification
|
||||
*/
|
||||
static
|
||||
int update_arg(void *field, char **orig_field,
|
||||
unsigned int *field_given, unsigned int *prev_given,
|
||||
char *value, const char *possible_values[],
|
||||
const char *default_value,
|
||||
cmdline_parser_arg_type arg_type,
|
||||
int check_ambiguity, int override,
|
||||
int no_free, int multiple_option,
|
||||
const char *long_opt, char short_opt,
|
||||
const char *additional_error)
|
||||
{
|
||||
char *stop_char = 0;
|
||||
const char *val = value;
|
||||
int found;
|
||||
FIX_UNUSED (field);
|
||||
|
||||
stop_char = 0;
|
||||
found = 0;
|
||||
|
||||
if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given)))
|
||||
{
|
||||
if (short_opt != '-')
|
||||
fprintf (stderr, "%s: `--%s' (`-%c') option given more than once%s\n",
|
||||
package_name, long_opt, short_opt,
|
||||
(additional_error ? additional_error : ""));
|
||||
else
|
||||
fprintf (stderr, "%s: `--%s' option given more than once%s\n",
|
||||
package_name, long_opt,
|
||||
(additional_error ? additional_error : ""));
|
||||
return 1; /* failure */
|
||||
}
|
||||
|
||||
FIX_UNUSED (default_value);
|
||||
|
||||
if (field_given && *field_given && ! override)
|
||||
return 0;
|
||||
if (prev_given)
|
||||
(*prev_given)++;
|
||||
if (field_given)
|
||||
(*field_given)++;
|
||||
if (possible_values)
|
||||
val = possible_values[found];
|
||||
|
||||
switch(arg_type) {
|
||||
case ARG_FLAG:
|
||||
*((int *)field) = !*((int *)field);
|
||||
break;
|
||||
case ARG_INT:
|
||||
if (val) *((int *)field) = strtol (val, &stop_char, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
/* check numeric conversion */
|
||||
switch(arg_type) {
|
||||
case ARG_INT:
|
||||
if (val && !(stop_char && *stop_char == '\0')) {
|
||||
fprintf(stderr, "%s: invalid numeric value: %s\n", package_name, val);
|
||||
return 1; /* failure */
|
||||
}
|
||||
break;
|
||||
default:
|
||||
;
|
||||
};
|
||||
|
||||
/* store the original value */
|
||||
switch(arg_type) {
|
||||
case ARG_NO:
|
||||
case ARG_FLAG:
|
||||
break;
|
||||
default:
|
||||
if (value && orig_field) {
|
||||
if (no_free) {
|
||||
*orig_field = value;
|
||||
} else {
|
||||
if (*orig_field)
|
||||
free (*orig_field); /* free previous string */
|
||||
*orig_field = gengetopt_strdup (value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return 0; /* OK */
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cmdline_parser_internal (
|
||||
int argc, char **argv, struct gengetopt_args_info *args_info,
|
||||
struct cmdline_parser_params *params, const char *additional_error)
|
||||
{
|
||||
int c; /* Character of the parsed option. */
|
||||
|
||||
int error_occurred = 0;
|
||||
struct gengetopt_args_info local_args_info;
|
||||
|
||||
int override;
|
||||
int initialize;
|
||||
int check_required;
|
||||
int check_ambiguity;
|
||||
|
||||
package_name = argv[0];
|
||||
|
||||
override = params->override;
|
||||
initialize = params->initialize;
|
||||
check_required = params->check_required;
|
||||
check_ambiguity = params->check_ambiguity;
|
||||
|
||||
if (initialize)
|
||||
cmdline_parser_init (args_info);
|
||||
|
||||
cmdline_parser_init (&local_args_info);
|
||||
|
||||
optarg = 0;
|
||||
optind = 0;
|
||||
opterr = params->print_errors;
|
||||
optopt = '?';
|
||||
|
||||
while (1)
|
||||
{
|
||||
int option_index = 0;
|
||||
|
||||
static struct option long_options[] = {
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ "version", 0, NULL, 'V' },
|
||||
{ "nodeid", 1, NULL, 0 },
|
||||
{ "stdserial", 0, NULL, 'S' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
c = getopt_long (argc, argv, "hVS", long_options, &option_index);
|
||||
|
||||
if (c == -1) break; /* Exit from `while (1)' loop. */
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 'h': /* Print help and exit. */
|
||||
cmdline_parser_print_help ();
|
||||
cmdline_parser_free (&local_args_info);
|
||||
exit (EXIT_SUCCESS);
|
||||
|
||||
case 'V': /* Print version and exit. */
|
||||
cmdline_parser_print_version ();
|
||||
cmdline_parser_free (&local_args_info);
|
||||
exit (EXIT_SUCCESS);
|
||||
|
||||
case 'S': /* Use stdin/stdout for serial. */
|
||||
|
||||
|
||||
if (update_arg((void *)&(args_info->stdserial_flag), 0, &(args_info->stdserial_given),
|
||||
&(local_args_info.stdserial_given), optarg, 0, 0, ARG_FLAG,
|
||||
check_ambiguity, override, 1, 0, "stdserial", 'S',
|
||||
additional_error))
|
||||
goto failure;
|
||||
|
||||
break;
|
||||
|
||||
case 0: /* Long option with no short option */
|
||||
/* Node ID. */
|
||||
if (strcmp (long_options[option_index].name, "nodeid") == 0)
|
||||
{
|
||||
|
||||
|
||||
if (update_arg( (void *)&(args_info->nodeid_arg),
|
||||
&(args_info->nodeid_orig), &(args_info->nodeid_given),
|
||||
&(local_args_info.nodeid_given), optarg, 0, 0, ARG_INT,
|
||||
check_ambiguity, override, 0, 0,
|
||||
"nodeid", '-',
|
||||
additional_error))
|
||||
goto failure;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
case '?': /* Invalid option. */
|
||||
/* `getopt_long' already printed an error message. */
|
||||
goto failure;
|
||||
|
||||
default: /* bug: option not considered. */
|
||||
fprintf (stderr, "%s: option unknown: %c%s\n", CMDLINE_PARSER_PACKAGE, c, (additional_error ? additional_error : ""));
|
||||
abort ();
|
||||
} /* switch */
|
||||
} /* while */
|
||||
|
||||
|
||||
|
||||
if (check_required)
|
||||
{
|
||||
error_occurred += cmdline_parser_required2 (args_info, argv[0], additional_error);
|
||||
}
|
||||
|
||||
cmdline_parser_release (&local_args_info);
|
||||
|
||||
if ( error_occurred )
|
||||
return (EXIT_FAILURE);
|
||||
|
||||
return 0;
|
||||
|
||||
failure:
|
||||
|
||||
cmdline_parser_release (&local_args_info);
|
||||
return (EXIT_FAILURE);
|
||||
}
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
#
|
||||
# Copyright (c) 2016, Nest Labs, Inc.
|
||||
# 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.
|
||||
#
|
||||
|
||||
package "thread"
|
||||
version "0.1"
|
||||
purpose ""
|
||||
|
||||
option "nodeid" - "Node ID" int yes
|
||||
option "stdserial" S "Use stdin/stdout for serial" flag on
|
||||
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* 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 cmdline.h
|
||||
* @brief The header file for the command line option parser
|
||||
* generated by GNU Gengetopt version 2.22.6
|
||||
* http://www.gnu.org/software/gengetopt.
|
||||
* DO NOT modify this file, since it can be overwritten
|
||||
* @author GNU Gengetopt by Lorenzo Bettini */
|
||||
|
||||
#ifndef CMDLINE_H
|
||||
#define CMDLINE_H
|
||||
|
||||
#include <stdio.h> /* for FILE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifndef CMDLINE_PARSER_PACKAGE
|
||||
/** @brief the program name (used for printing errors) */
|
||||
#define CMDLINE_PARSER_PACKAGE "thread"
|
||||
#endif
|
||||
|
||||
#ifndef CMDLINE_PARSER_PACKAGE_NAME
|
||||
/** @brief the complete program name (used for help and version) */
|
||||
#define CMDLINE_PARSER_PACKAGE_NAME "thread"
|
||||
#endif
|
||||
|
||||
#ifndef CMDLINE_PARSER_VERSION
|
||||
/** @brief the program version */
|
||||
#define CMDLINE_PARSER_VERSION "0.1"
|
||||
#endif
|
||||
|
||||
/** @brief Where the command line options are stored */
|
||||
struct gengetopt_args_info
|
||||
{
|
||||
const char *help_help; /**< @brief Print help and exit help description. */
|
||||
const char *version_help; /**< @brief Print version and exit help description. */
|
||||
int nodeid_arg; /**< @brief Node ID. */
|
||||
char * nodeid_orig; /**< @brief Node ID original value given at command line. */
|
||||
const char *nodeid_help; /**< @brief Node ID help description. */
|
||||
int stdserial_flag; /**< @brief Use stdin/stdout for serial (default=on). */
|
||||
const char *stdserial_help; /**< @brief Use stdin/stdout for serial help description. */
|
||||
|
||||
unsigned int help_given ; /**< @brief Whether help was given. */
|
||||
unsigned int version_given ; /**< @brief Whether version was given. */
|
||||
unsigned int nodeid_given ; /**< @brief Whether nodeid was given. */
|
||||
unsigned int stdserial_given ; /**< @brief Whether stdserial was given. */
|
||||
|
||||
} ;
|
||||
|
||||
/** @brief The additional parameters to pass to parser functions */
|
||||
struct cmdline_parser_params
|
||||
{
|
||||
int override; /**< @brief whether to override possibly already present options (default 0) */
|
||||
int initialize; /**< @brief whether to initialize the option structure gengetopt_args_info (default 1) */
|
||||
int check_required; /**< @brief whether to check that all required options were provided (default 1) */
|
||||
int check_ambiguity; /**< @brief whether to check for options already specified in the option structure gengetopt_args_info (default 0) */
|
||||
int print_errors; /**< @brief whether getopt_long should print an error message for a bad option (default 1) */
|
||||
} ;
|
||||
|
||||
/** @brief the purpose string of the program */
|
||||
extern const char *gengetopt_args_info_purpose;
|
||||
/** @brief the usage string of the program */
|
||||
extern const char *gengetopt_args_info_usage;
|
||||
/** @brief the description string of the program */
|
||||
extern const char *gengetopt_args_info_description;
|
||||
/** @brief all the lines making the help output */
|
||||
extern const char *gengetopt_args_info_help[];
|
||||
|
||||
/**
|
||||
* The command line parser
|
||||
* @param argc the number of command line options
|
||||
* @param argv the command line options
|
||||
* @param args_info the structure where option information will be stored
|
||||
* @return 0 if everything went fine, NON 0 if an error took place
|
||||
*/
|
||||
int cmdline_parser (int argc, char **argv,
|
||||
struct gengetopt_args_info *args_info);
|
||||
|
||||
/**
|
||||
* The command line parser (version with additional parameters - deprecated)
|
||||
* @param argc the number of command line options
|
||||
* @param argv the command line options
|
||||
* @param args_info the structure where option information will be stored
|
||||
* @param override whether to override possibly already present options
|
||||
* @param initialize whether to initialize the option structure my_args_info
|
||||
* @param check_required whether to check that all required options were provided
|
||||
* @return 0 if everything went fine, NON 0 if an error took place
|
||||
* @deprecated use cmdline_parser_ext() instead
|
||||
*/
|
||||
int cmdline_parser2 (int argc, char **argv,
|
||||
struct gengetopt_args_info *args_info,
|
||||
int override, int initialize, int check_required);
|
||||
|
||||
/**
|
||||
* The command line parser (version with additional parameters)
|
||||
* @param argc the number of command line options
|
||||
* @param argv the command line options
|
||||
* @param args_info the structure where option information will be stored
|
||||
* @param params additional parameters for the parser
|
||||
* @return 0 if everything went fine, NON 0 if an error took place
|
||||
*/
|
||||
int cmdline_parser_ext (int argc, char **argv,
|
||||
struct gengetopt_args_info *args_info,
|
||||
struct cmdline_parser_params *params);
|
||||
|
||||
/**
|
||||
* Save the contents of the option struct into an already open FILE stream.
|
||||
* @param outfile the stream where to dump options
|
||||
* @param args_info the option struct to dump
|
||||
* @return 0 if everything went fine, NON 0 if an error took place
|
||||
*/
|
||||
int cmdline_parser_dump(FILE *outfile,
|
||||
struct gengetopt_args_info *args_info);
|
||||
|
||||
/**
|
||||
* Save the contents of the option struct into a (text) file.
|
||||
* This file can be read by the config file parser (if generated by gengetopt)
|
||||
* @param filename the file where to save
|
||||
* @param args_info the option struct to save
|
||||
* @return 0 if everything went fine, NON 0 if an error took place
|
||||
*/
|
||||
int cmdline_parser_file_save(const char *filename,
|
||||
struct gengetopt_args_info *args_info);
|
||||
|
||||
/**
|
||||
* Print the help
|
||||
*/
|
||||
void cmdline_parser_print_help(void);
|
||||
/**
|
||||
* Print the version
|
||||
*/
|
||||
void cmdline_parser_print_version(void);
|
||||
|
||||
/**
|
||||
* Initializes all the fields a cmdline_parser_params structure
|
||||
* to their default values
|
||||
* @param params the structure to initialize
|
||||
*/
|
||||
void cmdline_parser_params_init(struct cmdline_parser_params *params);
|
||||
|
||||
/**
|
||||
* Allocates dynamically a cmdline_parser_params structure and initializes
|
||||
* all its fields to their default values
|
||||
* @return the created and initialized cmdline_parser_params structure
|
||||
*/
|
||||
struct cmdline_parser_params *cmdline_parser_params_create(void);
|
||||
|
||||
/**
|
||||
* Initializes the passed gengetopt_args_info structure's fields
|
||||
* (also set default values for options that have a default)
|
||||
* @param args_info the structure to initialize
|
||||
*/
|
||||
void cmdline_parser_init (struct gengetopt_args_info *args_info);
|
||||
/**
|
||||
* Deallocates the string fields of the gengetopt_args_info structure
|
||||
* (but does not deallocate the structure itself)
|
||||
* @param args_info the structure to deallocate
|
||||
*/
|
||||
void cmdline_parser_free (struct gengetopt_args_info *args_info);
|
||||
|
||||
/**
|
||||
* Checks that all the required options were specified
|
||||
* @param args_info the structure to check
|
||||
* @param prog_name the name of the program that will be used to print
|
||||
* possible errors
|
||||
* @return
|
||||
*/
|
||||
int cmdline_parser_required (struct gengetopt_args_info *args_info,
|
||||
const char *prog_name);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* CMDLINE_H */
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* 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 <ctype.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <platform/logging.h>
|
||||
|
||||
void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...)
|
||||
{
|
||||
struct timeval tv;
|
||||
char timeString[40];
|
||||
va_list args;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
strftime(timeString, sizeof(timeString), "%Y-%m-%d %H:%M:%S", localtime(&tv.tv_sec));
|
||||
fprintf(stderr, "%s.%06d ", timeString, (uint32_t)tv.tv_usec);
|
||||
|
||||
switch (aLogLevel)
|
||||
{
|
||||
case kLogLevelNone:
|
||||
printf("NONE ");
|
||||
break;
|
||||
|
||||
case kLogLevelCrit:
|
||||
printf("CRIT ");
|
||||
break;
|
||||
|
||||
case kLogLevelWarn:
|
||||
printf("WARN ");
|
||||
break;
|
||||
|
||||
case kLogLevelInfo:
|
||||
printf("INFO ");
|
||||
break;
|
||||
|
||||
case kLogLevelDebg:
|
||||
printf("DEBG ");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (aLogRegion)
|
||||
{
|
||||
case kLogRegionApi:
|
||||
printf("API ");
|
||||
break;
|
||||
|
||||
case kLogRegionMle:
|
||||
printf("MLE ");
|
||||
break;
|
||||
|
||||
case kLogRegionArp:
|
||||
printf("ARP ");
|
||||
break;
|
||||
|
||||
case kLogRegionNetData:
|
||||
printf("NETD ");
|
||||
break;
|
||||
|
||||
case kLogRegionIp6:
|
||||
printf("IPV6 ");
|
||||
break;
|
||||
|
||||
case kLogRegionIcmp:
|
||||
printf("ICMP ");
|
||||
break;
|
||||
|
||||
case kLogRegionMac:
|
||||
printf("MAC ");
|
||||
break;
|
||||
|
||||
case kLogRegionMem:
|
||||
printf("MEM ");
|
||||
break;
|
||||
}
|
||||
|
||||
va_start(args, aFormat);
|
||||
vprintf(aFormat, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* 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_H_
|
||||
#define PLATFORM_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This method initializes the alarm service used by OpenThread.
|
||||
*
|
||||
*/
|
||||
void hwAlarmInit(void);
|
||||
|
||||
/**
|
||||
* This method initializes the radio service used by OpenThread.
|
||||
*
|
||||
*/
|
||||
void hwRadioInit(void);
|
||||
|
||||
/**
|
||||
* This method initializes the random number service used by OpenThread.
|
||||
*
|
||||
*/
|
||||
void hwRandomInit(void);
|
||||
|
||||
/**
|
||||
* This method puts the thread executing OpenThread to sleep.
|
||||
*
|
||||
*/
|
||||
void hwSleep(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // PLATFORM_H_
|
||||
@@ -0,0 +1,454 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* 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 <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <platform/posix/cmdline.h>
|
||||
|
||||
#include <common/code_utils.hpp>
|
||||
#include <common/debug.hpp>
|
||||
#include <mac/mac.hpp>
|
||||
#include <platform/radio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern struct gengetopt_args_info args_info;
|
||||
|
||||
namespace Thread {
|
||||
|
||||
enum PhyState
|
||||
{
|
||||
kStateDisabled = 0,
|
||||
kStateSleep = 1,
|
||||
kStateIdle = 2,
|
||||
kStateListen = 3,
|
||||
kStateReceive = 4,
|
||||
kStateTransmit = 5,
|
||||
};
|
||||
|
||||
static void *phy_receive_thread(void *arg);
|
||||
|
||||
static PhyState s_state = kStateDisabled;
|
||||
static RadioPacket *s_receive_frame = NULL;
|
||||
static RadioPacket *s_transmit_frame = NULL;
|
||||
static RadioPacket m_ack_packet;
|
||||
static bool s_data_pending = false;
|
||||
|
||||
static uint8_t s_extended_address[8];
|
||||
static uint16_t s_short_address;
|
||||
static uint16_t s_panid;
|
||||
|
||||
static pthread_t s_pthread;
|
||||
static pthread_mutex_t s_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_cond_t s_condition_variable = PTHREAD_COND_INITIALIZER;
|
||||
static int s_sockfd;
|
||||
|
||||
ThreadError otPlatRadioSetPanId(uint16_t panid)
|
||||
{
|
||||
s_panid = panid;
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioSetExtendedAddress(uint8_t *address)
|
||||
{
|
||||
for (unsigned i = 0; i < sizeof(s_extended_address); i++)
|
||||
{
|
||||
s_extended_address[i] = address[7 - i];
|
||||
}
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioSetShortAddress(uint16_t address)
|
||||
{
|
||||
s_short_address = address;
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
void hwRadioInit()
|
||||
{
|
||||
struct sockaddr_in sockaddr;
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
sockaddr.sin_family = AF_INET;
|
||||
sockaddr.sin_port = htons(9000 + args_info.nodeid_arg);
|
||||
sockaddr.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
s_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
bind(s_sockfd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
|
||||
|
||||
pthread_create(&s_pthread, NULL, &phy_receive_thread, NULL);
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioEnable()
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
VerifyOrExit(s_state == kStateDisabled, error = kThreadError_Busy);
|
||||
s_state = kStateSleep;
|
||||
pthread_cond_signal(&s_condition_variable);
|
||||
|
||||
exit:
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioDisable()
|
||||
{
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
s_state = kStateDisabled;
|
||||
pthread_cond_signal(&s_condition_variable);
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioSleep()
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
VerifyOrExit(s_state == kStateIdle, error = kThreadError_Busy);
|
||||
s_state = kStateSleep;
|
||||
pthread_cond_signal(&s_condition_variable);
|
||||
|
||||
exit:
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioIdle()
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
|
||||
switch (s_state)
|
||||
{
|
||||
case kStateSleep:
|
||||
s_state = kStateIdle;
|
||||
pthread_cond_signal(&s_condition_variable);
|
||||
break;
|
||||
|
||||
case kStateIdle:
|
||||
break;
|
||||
|
||||
case kStateListen:
|
||||
case kStateTransmit:
|
||||
s_state = kStateIdle;
|
||||
pthread_cond_signal(&s_condition_variable);
|
||||
break;
|
||||
|
||||
case kStateDisabled:
|
||||
case kStateReceive:
|
||||
ExitNow(error = kThreadError_Busy);
|
||||
}
|
||||
|
||||
exit:
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioReceive(RadioPacket *packet)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
VerifyOrExit(s_state == kStateIdle, error = kThreadError_Busy);
|
||||
s_state = kStateListen;
|
||||
pthread_cond_signal(&s_condition_variable);
|
||||
|
||||
s_receive_frame = packet;
|
||||
|
||||
exit:
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioTransmit(RadioPacket *packet)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
struct sockaddr_in sockaddr;
|
||||
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
VerifyOrExit(s_state == kStateIdle, error = kThreadError_Busy);
|
||||
s_state = kStateTransmit;
|
||||
pthread_cond_signal(&s_condition_variable);
|
||||
|
||||
s_transmit_frame = packet;
|
||||
s_data_pending = false;
|
||||
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
sockaddr.sin_family = AF_INET;
|
||||
inet_pton(AF_INET, "127.0.0.1", &sockaddr.sin_addr);
|
||||
|
||||
for (int i = 1; i < 34; i++)
|
||||
{
|
||||
if (args_info.nodeid_arg == i)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
sockaddr.sin_port = htons(9000 + i);
|
||||
sendto(s_sockfd, s_transmit_frame->mPsdu, s_transmit_frame->mLength, 0,
|
||||
(struct sockaddr *)&sockaddr, sizeof(sockaddr));
|
||||
}
|
||||
|
||||
if (!reinterpret_cast<Mac::Frame *>(s_transmit_frame)->GetAckRequest())
|
||||
{
|
||||
otPlatRadioSignalTransmitDone();
|
||||
}
|
||||
|
||||
exit:
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
return error;
|
||||
}
|
||||
|
||||
int8_t otPlatRadioGetNoiseFloor()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioHandleTransmitDone(bool *rxPending)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
VerifyOrExit(s_state == kStateTransmit, error = kThreadError_InvalidState);
|
||||
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
s_state = kStateIdle;
|
||||
pthread_cond_signal(&s_condition_variable);
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
|
||||
if (rxPending != NULL)
|
||||
{
|
||||
*rxPending = s_data_pending;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void *phy_receive_thread(void *arg)
|
||||
{
|
||||
fd_set fds;
|
||||
int rval;
|
||||
RadioPacket receive_frame;
|
||||
int length;
|
||||
uint8_t tx_sequence, rx_sequence;
|
||||
uint8_t command_id;
|
||||
|
||||
while (1)
|
||||
{
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(s_sockfd, &fds);
|
||||
|
||||
rval = select(s_sockfd + 1, &fds, NULL, NULL, NULL);
|
||||
|
||||
if (rval < 0 || !FD_ISSET(s_sockfd, &fds))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
|
||||
while (s_state == kStateIdle)
|
||||
{
|
||||
pthread_cond_wait(&s_condition_variable, &s_mutex);
|
||||
}
|
||||
|
||||
switch (s_state)
|
||||
{
|
||||
case kStateDisabled:
|
||||
case kStateIdle:
|
||||
case kStateSleep:
|
||||
recvfrom(s_sockfd, NULL, 0, 0, NULL, NULL);
|
||||
break;
|
||||
|
||||
case kStateTransmit:
|
||||
length = recvfrom(s_sockfd, receive_frame.mPsdu, Mac::Frame::kMTU, 0, NULL, NULL);
|
||||
|
||||
if (length < 0)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
if (reinterpret_cast<Mac::Frame *>(&receive_frame)->GetType() != Mac::Frame::kFcfFrameAck)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
tx_sequence = reinterpret_cast<Mac::Frame *>(s_transmit_frame)->GetSequence();
|
||||
|
||||
rx_sequence = reinterpret_cast<Mac::Frame *>(&receive_frame)->GetSequence();
|
||||
|
||||
if (tx_sequence != rx_sequence)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (reinterpret_cast<Mac::Frame *>(s_transmit_frame)->GetType() == Mac::Frame::kFcfFrameMacCmd)
|
||||
{
|
||||
reinterpret_cast<Mac::Frame *>(s_transmit_frame)->GetCommandId(command_id);
|
||||
|
||||
if (command_id == Mac::Frame::kMacCmdDataRequest)
|
||||
{
|
||||
s_data_pending = true;
|
||||
}
|
||||
}
|
||||
|
||||
otPlatRadioSignalTransmitDone();
|
||||
break;
|
||||
|
||||
case kStateListen:
|
||||
s_state = kStateReceive;
|
||||
otPlatRadioSignalReceiveDone();
|
||||
|
||||
while (s_state == kStateReceive)
|
||||
{
|
||||
pthread_cond_wait(&s_condition_variable, &s_mutex);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case kStateReceive:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void send_ack()
|
||||
{
|
||||
Mac::Frame *ack_frame;
|
||||
uint8_t sequence;
|
||||
struct sockaddr_in sockaddr;
|
||||
|
||||
sequence = reinterpret_cast<Mac::Frame *>(s_receive_frame)->GetSequence();
|
||||
|
||||
ack_frame = reinterpret_cast<Mac::Frame *>(&m_ack_packet);
|
||||
ack_frame->InitMacHeader(Mac::Frame::kFcfFrameAck, Mac::Frame::kSecNone);
|
||||
ack_frame->SetSequence(sequence);
|
||||
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
sockaddr.sin_family = AF_INET;
|
||||
inet_pton(AF_INET, "127.0.0.1", &sockaddr.sin_addr);
|
||||
|
||||
for (int i = 1; i < 34; i++)
|
||||
{
|
||||
if (args_info.nodeid_arg == i)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
sockaddr.sin_port = htons(9000 + i);
|
||||
sendto(s_sockfd, m_ack_packet.mPsdu, m_ack_packet.mLength, 0,
|
||||
(struct sockaddr *)&sockaddr, sizeof(sockaddr));
|
||||
}
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioHandleReceiveDone()
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
Mac::Frame *receive_frame;
|
||||
uint16_t dstpan;
|
||||
Mac::Address dstaddr;
|
||||
int length;
|
||||
|
||||
VerifyOrExit(s_state == kStateReceive, error = kThreadError_InvalidState);
|
||||
|
||||
length = recvfrom(s_sockfd, s_receive_frame->mPsdu, Mac::Frame::kMTU, 0, NULL, NULL);
|
||||
receive_frame = reinterpret_cast<Mac::Frame *>(s_receive_frame);
|
||||
|
||||
receive_frame->GetDstAddr(dstaddr);
|
||||
|
||||
switch (dstaddr.mLength)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case 2:
|
||||
receive_frame->GetDstPanId(dstpan);
|
||||
VerifyOrExit((dstpan == Mac::kShortAddrBroadcast || dstpan == s_panid) &&
|
||||
(dstaddr.mShortAddress == Mac::kShortAddrBroadcast || dstaddr.mShortAddress == s_short_address),
|
||||
error = kThreadError_Abort);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
receive_frame->GetDstPanId(dstpan);
|
||||
VerifyOrExit((dstpan == Mac::kShortAddrBroadcast || dstpan == s_panid) &&
|
||||
memcmp(&dstaddr.mExtAddress, s_extended_address, sizeof(dstaddr.mExtAddress)) == 0,
|
||||
error = kThreadError_Abort);
|
||||
break;
|
||||
|
||||
default:
|
||||
ExitNow(error = kThreadError_Abort);
|
||||
}
|
||||
|
||||
s_receive_frame->mLength = length;
|
||||
s_receive_frame->mPower = -20;
|
||||
|
||||
// generate acknowledgment
|
||||
if (reinterpret_cast<Mac::Frame *>(s_receive_frame)->GetAckRequest())
|
||||
{
|
||||
send_ack();
|
||||
}
|
||||
|
||||
exit:
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
|
||||
if (s_state != kStateDisabled)
|
||||
{
|
||||
s_state = kStateIdle;
|
||||
}
|
||||
|
||||
pthread_cond_signal(&s_condition_variable);
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // end of extern "C"
|
||||
#endif
|
||||
|
||||
} // namespace Thread
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* 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 a pseudo-random number generator.
|
||||
*
|
||||
* @warning
|
||||
* This implementation is not a true random number generator and does @em satisfy the Thread requirements.
|
||||
*/
|
||||
|
||||
#include <platform/random.h>
|
||||
#include <platform/posix/cmdline.h>
|
||||
|
||||
extern struct gengetopt_args_info args_info;
|
||||
|
||||
static uint32_t s_state = 1;
|
||||
|
||||
void hwRandomInit(void)
|
||||
{
|
||||
s_state = args_info.nodeid_arg;
|
||||
}
|
||||
|
||||
uint32_t otPlatRandomGet(void)
|
||||
{
|
||||
uint32_t mlcg, p, q;
|
||||
uint64_t tmpstate;
|
||||
|
||||
tmpstate = (uint64_t)33614 * (uint64_t)s_state;
|
||||
q = tmpstate & 0xffffffff;
|
||||
q = q >> 1;
|
||||
p = tmpstate >> 32;
|
||||
mlcg = p + q;
|
||||
|
||||
if (mlcg & 0x80000000)
|
||||
{
|
||||
mlcg &= 0x7fffffff;
|
||||
mlcg++;
|
||||
}
|
||||
|
||||
s_state = mlcg;
|
||||
|
||||
return mlcg;
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* 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 <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <stdlib.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <common/code_utils.hpp>
|
||||
#include <platform/posix/cmdline.h>
|
||||
#include <platform/serial.h>
|
||||
|
||||
static void *serial_receive_thread(void *arg);
|
||||
|
||||
#ifdef OPENTHREAD_TARGET_LINUX
|
||||
int posix_openpt(int oflag);
|
||||
int grantpt(int fildes);
|
||||
int unlockpt(int fd);
|
||||
char *ptsname(int fd);
|
||||
#endif // OPENTHREAD_TARGET_LINUX
|
||||
|
||||
extern struct gengetopt_args_info args_info;
|
||||
|
||||
static uint8_t s_receive_buffer[128];
|
||||
static int s_in_fd;
|
||||
static int s_out_fd;
|
||||
static struct termios s_in_termios;
|
||||
static struct termios s_out_termios;
|
||||
static pthread_t s_pthread;
|
||||
static sem_t *s_semaphore;
|
||||
|
||||
ThreadError otPlatSerialEnable(void)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
struct termios termios;
|
||||
char *path;
|
||||
char cmd[256];
|
||||
|
||||
if (args_info.stdserial_given == 1)
|
||||
{
|
||||
s_in_fd = dup(STDIN_FILENO);
|
||||
s_out_fd = dup(STDOUT_FILENO);
|
||||
dup2(STDERR_FILENO, STDOUT_FILENO);
|
||||
}
|
||||
else
|
||||
{
|
||||
// open file
|
||||
#ifdef OPENTHREAD_TARGET_DARWIN
|
||||
|
||||
asprintf(&path, "/dev/ptyp%d", args_info.nodeid_arg);
|
||||
VerifyOrExit((s_in_fd = open(path, O_RDWR | O_NOCTTY)) >= 0, perror("posix_openpt"); error = kThreadError_Error);
|
||||
free(path);
|
||||
|
||||
// print pty path
|
||||
printf("/dev/ttyp%d\n", args_info.nodeid_arg);
|
||||
|
||||
#elif defined(OPENTHREAD_TARGET_LINUX)
|
||||
|
||||
VerifyOrExit((s_in_fd = posix_openpt(O_RDWR | O_NOCTTY)) >= 0, perror("posix_openpt"); error = kThreadError_Error);
|
||||
VerifyOrExit(grantpt(s_in_fd) == 0, perror("grantpt"); error = kThreadError_Error);
|
||||
VerifyOrExit(unlockpt(s_in_fd) == 0, perror("unlockpt"); error = kThreadError_Error);
|
||||
|
||||
// print pty path
|
||||
VerifyOrExit((path = ptsname(s_in_fd)) != NULL, perror("ptsname"); error = kThreadError_Error);
|
||||
printf("%s\n", path);
|
||||
|
||||
#else
|
||||
#error "Unknown platform."
|
||||
#endif
|
||||
|
||||
// check if file descriptor is pointing to a TTY device
|
||||
VerifyOrExit(isatty(s_in_fd), error = kThreadError_Error);
|
||||
|
||||
s_out_fd = dup(s_in_fd);
|
||||
|
||||
if (isatty(s_in_fd))
|
||||
{
|
||||
// get current configuration
|
||||
VerifyOrExit(tcgetattr(s_in_fd, &termios) == 0, perror("tcgetattr"); error = kThreadError_Error);
|
||||
s_in_termios = termios;
|
||||
|
||||
// turn off input processing
|
||||
termios.c_iflag &= ~(IGNBRK | BRKINT | ICRNL | INLCR | PARMRK | INPCK | ISTRIP | IXON);
|
||||
|
||||
// turn off output processing
|
||||
termios.c_oflag = 0;
|
||||
|
||||
// turn off line processing
|
||||
termios.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
|
||||
|
||||
// turn off character processing
|
||||
termios.c_cflag &= ~(CSIZE | PARENB);
|
||||
termios.c_cflag |= CS8;
|
||||
|
||||
// return 1 byte at a time
|
||||
termios.c_cc[VMIN] = 1;
|
||||
|
||||
// turn off inter-character timer
|
||||
termios.c_cc[VTIME] = 0;
|
||||
|
||||
// configure baud rate
|
||||
VerifyOrExit(cfsetispeed(&termios, B115200) == 0, perror("cfsetispeed"); error = kThreadError_Error);
|
||||
|
||||
// set configuration
|
||||
VerifyOrExit(tcsetattr(s_in_fd, TCSAFLUSH, &termios) == 0, perror("tcsetattr"); error = kThreadError_Error);
|
||||
}
|
||||
|
||||
if (isatty(s_out_fd))
|
||||
{
|
||||
// get current configuration
|
||||
VerifyOrExit(tcgetattr(s_out_fd, &termios) == 0, perror("tcgetattr"); error = kThreadError_Error);
|
||||
s_out_termios = termios;
|
||||
|
||||
// turn off output processing
|
||||
termios.c_oflag = 0;
|
||||
|
||||
// turn off line processing
|
||||
termios.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
|
||||
|
||||
// turn off character processing
|
||||
termios.c_cflag &= ~(CSIZE | PARENB);
|
||||
termios.c_cflag |= CS8;
|
||||
|
||||
// return 1 byte at a time
|
||||
termios.c_cc[VMIN] = 1;
|
||||
|
||||
// turn off inter-character timer
|
||||
termios.c_cc[VTIME] = 0;
|
||||
|
||||
// configure baud rate
|
||||
VerifyOrExit(cfsetospeed(&termios, B115200) == 0, perror("cfsetospeed"); error = kThreadError_Error);
|
||||
|
||||
// set configuration
|
||||
VerifyOrExit(tcsetattr(s_out_fd, TCSAFLUSH, &termios) == 0, perror("tcsetattr"); error = kThreadError_Error);
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(cmd, sizeof(cmd), "thread_serial_semaphore_%d", args_info.nodeid_arg);
|
||||
s_semaphore = sem_open(cmd, O_CREAT, 0644, 0);
|
||||
pthread_create(&s_pthread, NULL, &serial_receive_thread, NULL);
|
||||
|
||||
return error;
|
||||
|
||||
exit:
|
||||
close(s_in_fd);
|
||||
close(s_out_fd);
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatSerialDisable(void)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
close(s_in_fd);
|
||||
close(s_out_fd);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatSerialSend(const uint8_t *aBuf, uint16_t aBufLength)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
VerifyOrExit(write(s_out_fd, aBuf, aBufLength) >= 0, error = kThreadError_Error);
|
||||
otPlatSerialSignalSendDone();
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void otPlatSerialHandleSendDone(void)
|
||||
{
|
||||
}
|
||||
|
||||
void *serial_receive_thread(void *aContext)
|
||||
{
|
||||
fd_set fds;
|
||||
int rval;
|
||||
|
||||
while (1)
|
||||
{
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(s_in_fd, &fds);
|
||||
|
||||
rval = select(s_in_fd + 1, &fds, NULL, NULL, NULL);
|
||||
|
||||
if (rval >= 0 && FD_ISSET(s_in_fd, &fds))
|
||||
{
|
||||
otPlatSerialSignalReceive();
|
||||
sem_wait(s_semaphore);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const uint8_t *otPlatSerialGetReceivedBytes(uint16_t *aBufLength)
|
||||
{
|
||||
size_t length;
|
||||
int i;
|
||||
|
||||
length = read(s_in_fd, s_receive_buffer, sizeof(s_receive_buffer));
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
if (s_receive_buffer[i] == 0x03)
|
||||
{
|
||||
otPlatSerialDisable();
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (aBufLength != NULL)
|
||||
{
|
||||
*aBufLength = length;
|
||||
}
|
||||
|
||||
return s_receive_buffer;
|
||||
}
|
||||
|
||||
void otPlatSerialHandleReceiveDone(void)
|
||||
{
|
||||
sem_post(s_semaphore);
|
||||
}
|
||||
Reference in New Issue
Block a user