mirror of
https://github.com/espressif/openthread.git
synced 2026-10-03 22:37:36 +00:00
[posix-app] add readline for CLI (#3511)
This commit is contained in:
+3
-2
@@ -428,7 +428,8 @@ build_samr21() {
|
||||
./bootstrap || die
|
||||
# enable code coverage for OpenThread transceiver only
|
||||
CERT_LOG=1 COVERAGE=1 VIRTUAL_TIME_UART=1 make -f examples/Makefile-posix || die
|
||||
CERT_LOG=1 COVERAGE=1 make -f src/posix/Makefile-posix || die
|
||||
# readline supports pipe, editline does not
|
||||
CERT_LOG=1 COVERAGE=1 READLINE=readline make -f src/posix/Makefile-posix || die
|
||||
CERT_LOG=1 COVERAGE=1 PYTHONUNBUFFERED=1 OT_CLI_PATH="$(pwd)/$(ls output/posix/*/bin/ot-cli)" RADIO_DEVICE="$(pwd)/$(ls output/*/bin/ot-ncp-radio)" make -f src/posix/Makefile-posix check || die
|
||||
}
|
||||
|
||||
@@ -451,7 +452,7 @@ build_samr21() {
|
||||
./bootstrap || die
|
||||
CERT_LOG=1 COVERAGE=1 VIRTUAL_TIME_UART=1 make -f examples/Makefile-posix || die
|
||||
# enable code coverage for OpenThread posix radio
|
||||
CERT_LOG=1 COVERAGE=1 make -f src/posix/Makefile-posix || die
|
||||
CERT_LOG=1 COVERAGE=1 READLINE=readline make -f src/posix/Makefile-posix || die
|
||||
CERT_LOG=1 COVERAGE=1 PYTHONUNBUFFERED=1 OT_NCP_PATH="$(pwd)/$(ls output/posix/*/bin/ot-ncp)" RADIO_DEVICE="$(pwd)/$(ls output/*/bin/ot-ncp-radio)" NODE_TYPE=ncp-sim make -f src/posix/Makefile-posix check || die
|
||||
}
|
||||
|
||||
|
||||
@@ -745,6 +745,30 @@ AC_DEFINE_UNQUOTED([OPENTHREAD_ENABLE_NCP_UART],[${OPENTHREAD_ENABLE_NCP_UART}],
|
||||
AC_MSG_CHECKING([should NCP support UART])
|
||||
AC_MSG_RESULT([${OPENTHREAD_ENABLE_UART}])
|
||||
|
||||
#
|
||||
# Readline - readline library to use for POSIX CLI
|
||||
#
|
||||
|
||||
AC_ARG_WITH(
|
||||
[readline],
|
||||
[AS_HELP_STRING([--with-readline],[Specify the readline library (none|readline|edit) @<:@default=none@:>@.])],
|
||||
[],
|
||||
[with_readline=none])
|
||||
|
||||
case "${with_readline}" in
|
||||
"none")
|
||||
;;
|
||||
"readline")
|
||||
AC_CHECK_LIB([readline], [rl_callback_handler_install])
|
||||
;;
|
||||
"edit")
|
||||
AC_CHECK_LIB([edit], [rl_callback_handler_install])
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR([unexpected --with-readline=${with_readline}])
|
||||
;;
|
||||
esac
|
||||
|
||||
#
|
||||
# Thread UDP forward
|
||||
#
|
||||
|
||||
@@ -56,6 +56,7 @@ LEGACY ?= 1
|
||||
LINK_RAW ?= 0
|
||||
MAC_FILTER ?= 1
|
||||
MTD_NETDIAG ?= 1
|
||||
READLINE ?= edit
|
||||
SERVICE ?= 1
|
||||
SNTP_CLIENT ?= 1
|
||||
UDP_FORWARD ?= 1
|
||||
@@ -92,6 +93,10 @@ ifeq ($(PLATFORM_NETIF),1)
|
||||
configure_OPTIONS += --enable-platform-netif
|
||||
endif
|
||||
|
||||
ifneq ($(READLINE),)
|
||||
configure_OPTIONS += --with-readline=$(READLINE)
|
||||
endif
|
||||
|
||||
ifeq ($(VIRTUAL_TIME),1)
|
||||
COMMONCFLAGS += -DOPENTHREAD_POSIX_VIRTUAL_TIME=1
|
||||
endif
|
||||
|
||||
@@ -160,6 +160,7 @@ ot_cli_CPPFLAGS = \
|
||||
|
||||
ot_cli_SOURCES = \
|
||||
main.c \
|
||||
console_cli.c \
|
||||
$(NULL)
|
||||
|
||||
ot_cli_LDADD = \
|
||||
@@ -168,6 +169,7 @@ ot_cli_LDADD = \
|
||||
$(LDADD_COMMON) \
|
||||
$(top_builddir)/src/core/libopenthread-ftd.a \
|
||||
$(LDADD_COMMON) \
|
||||
$(top_builddir)/src/cli/libopenthread-cli-ftd.a \
|
||||
$(NULL)
|
||||
|
||||
ot_cli_LDFLAGS = \
|
||||
@@ -192,4 +194,8 @@ CLEANFILES = $(wildc
|
||||
endif # OPENTHREAD_BUILD_COVERAGE
|
||||
endif # OPENTHREAD_ENABLE_EXECUTABLE
|
||||
|
||||
noinst_HEADERS = \
|
||||
console_cli.h \
|
||||
$(NULL)
|
||||
|
||||
include $(abs_top_nlbuild_autotools_dir)/automake/post.am
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "console_cli.h"
|
||||
|
||||
#include "openthread/config.h"
|
||||
|
||||
#if HAVE_LIBEDIT || HAVE_LIBREADLINE
|
||||
#if HAVE_LIBEDIT
|
||||
#include <editline/readline.h>
|
||||
#elif HAVE_LIBREADLINE
|
||||
#include <readline/history.h>
|
||||
#include <readline/readline.h>
|
||||
#else
|
||||
#error "Missing readline library"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <openthread/cli.h>
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
#include "platform-posix.h"
|
||||
|
||||
static const char sPrompt[] = "> ";
|
||||
|
||||
static int sReadFd;
|
||||
|
||||
static void InputCallback(char *aLine)
|
||||
{
|
||||
if (aLine != NULL)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if ((len = strlen(aLine)) > 0)
|
||||
{
|
||||
add_history(aLine);
|
||||
otCliConsoleInputLine(aLine, (uint16_t)len);
|
||||
}
|
||||
free(aLine);
|
||||
}
|
||||
else
|
||||
{
|
||||
exit(OT_EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
static int OutputCallback(const char *aBuffer, uint16_t aLength, void *aContext)
|
||||
{
|
||||
(void)aContext;
|
||||
|
||||
return (int)write(STDOUT_FILENO, aBuffer, aLength);
|
||||
}
|
||||
|
||||
void otxConsoleInit(otInstance *aInstance)
|
||||
{
|
||||
rl_instream = stdin;
|
||||
rl_outstream = stdout;
|
||||
rl_inhibit_completion = true;
|
||||
sReadFd = fileno(rl_instream);
|
||||
rl_callback_handler_install(sPrompt, InputCallback);
|
||||
otCliConsoleInit(aInstance, OutputCallback, NULL);
|
||||
}
|
||||
|
||||
void otxConsoleDeinit(void)
|
||||
{
|
||||
rl_callback_handler_remove();
|
||||
}
|
||||
|
||||
void otxConsoleUpdate(otSysMainloopContext *aMainloop)
|
||||
{
|
||||
FD_SET(sReadFd, &aMainloop->mReadFdSet);
|
||||
FD_SET(sReadFd, &aMainloop->mErrorFdSet);
|
||||
|
||||
if (aMainloop->mMaxFd < sReadFd)
|
||||
{
|
||||
aMainloop->mMaxFd = sReadFd;
|
||||
}
|
||||
}
|
||||
|
||||
void otxConsoleProcess(const otSysMainloopContext *aMainloop)
|
||||
{
|
||||
if (FD_ISSET(sReadFd, &aMainloop->mErrorFdSet))
|
||||
{
|
||||
perror("console error");
|
||||
exit(OT_EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (FD_ISSET(sReadFd, &aMainloop->mReadFdSet))
|
||||
{
|
||||
rl_callback_read_char();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // HAVE_LIBEDIT || HAVE_LIBREADLINE
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef OPENTHREAD_CONSOLE_CLI_H_
|
||||
#define OPENTHREAD_CONSOLE_CLI_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "openthread-system.h"
|
||||
|
||||
/**
|
||||
* This function initializes CLI console.
|
||||
*
|
||||
* @param[in] aInstance A pointer to the OpenThread instance.
|
||||
*
|
||||
*/
|
||||
void otxConsoleInit(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* This function deinitializes CLI console
|
||||
*
|
||||
*/
|
||||
void otxConsoleDeinit(void);
|
||||
|
||||
/**
|
||||
* This function updates the file descriptor sets with file descriptors used by console.
|
||||
*
|
||||
* @param[inout] aMainloop A pointer to the mainloop context.
|
||||
*
|
||||
*/
|
||||
void otxConsoleUpdate(otSysMainloopContext *aMainloop);
|
||||
|
||||
/**
|
||||
* This function performs console driver processing.
|
||||
*
|
||||
* @param[in] aMainloop A pointer to the mainloop context.
|
||||
*
|
||||
*/
|
||||
void otxConsoleProcess(const otSysMainloopContext *aMainloop);
|
||||
|
||||
#endif // OPENTHREAD_CONSOLE_CLI_H_
|
||||
@@ -49,6 +49,9 @@
|
||||
#include <openthread/ncp.h>
|
||||
#elif OPENTHREAD_POSIX_APP_TYPE == OPENTHREAD_POSIX_APP_TYPE_CLI
|
||||
#include <openthread/cli.h>
|
||||
#if HAVE_LIBEDIT || HAVE_LIBREADLINE
|
||||
#include "console_cli.h"
|
||||
#endif
|
||||
#else
|
||||
#error "Unknown posix app type!"
|
||||
#endif
|
||||
@@ -92,8 +95,12 @@ int main(int argc, char *argv[])
|
||||
#if OPENTHREAD_ENABLE_PLATFORM_NETIF
|
||||
otSysInitNetif(instance);
|
||||
#endif
|
||||
#if HAVE_LIBEDIT || HAVE_LIBREADLINE
|
||||
otxConsoleInit(instance);
|
||||
#else
|
||||
otCliUartInit(instance);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_ENABLE_DIAG
|
||||
otDiagInit(instance);
|
||||
@@ -113,10 +120,18 @@ int main(int argc, char *argv[])
|
||||
mainloop.mTimeout.tv_sec = 10;
|
||||
mainloop.mTimeout.tv_usec = 0;
|
||||
|
||||
#if OPENTHREAD_POSIX_APP_TYPE == OPENTHREAD_POSIX_APP_TYPE_CLI && (HAVE_LIBEDIT || HAVE_LIBREADLINE)
|
||||
otxConsoleUpdate(&mainloop);
|
||||
#endif
|
||||
|
||||
otSysMainloopUpdate(instance, &mainloop);
|
||||
|
||||
if (otSysMainloopPoll(&mainloop) >= 0)
|
||||
{
|
||||
otSysMainloopProcess(instance, &mainloop);
|
||||
#if OPENTHREAD_POSIX_APP_TYPE == OPENTHREAD_POSIX_APP_TYPE_CLI && (HAVE_LIBEDIT || HAVE_LIBREADLINE)
|
||||
otxConsoleProcess(&mainloop);
|
||||
#endif
|
||||
}
|
||||
else if (errno != EINTR)
|
||||
{
|
||||
@@ -125,6 +140,9 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
#if OPENTHREAD_POSIX_APP_TYPE == OPENTHREAD_POSIX_APP_TYPE_CLI && (HAVE_LIBEDIT || HAVE_LIBREADLINE)
|
||||
otxConsoleDeinit();
|
||||
#endif
|
||||
otInstanceFinalize(instance);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
#ifndef OPENTHREAD_SYSTEM_H_
|
||||
#define OPENTHREAD_SYSTEM_H_
|
||||
|
||||
#include <sys/select.h>
|
||||
|
||||
#include <openthread/instance.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -97,7 +97,6 @@ void otSimInit(void)
|
||||
perror("bind");
|
||||
exit(OT_EXIT_FAILURE);
|
||||
}
|
||||
// fprintf(stderr, "[%s] sim fd is %d\r\n", getenv("NODE_ID"), sSockFd);
|
||||
}
|
||||
|
||||
void otSimDeinit(void)
|
||||
@@ -139,8 +138,6 @@ void otSimReceiveEvent(struct Event *aEvent)
|
||||
}
|
||||
|
||||
sNow += aEvent->mDelay;
|
||||
|
||||
// fprintf(stderr, "--[%s] now is %lu type is %d\n", getenv("NODE_ID"), sNow, aEvent->mEvent);
|
||||
}
|
||||
|
||||
void otSimSendSleepEvent(const struct timeval *aTimeout)
|
||||
@@ -196,7 +193,6 @@ void otSimProcess(otInstance *aInstance, const fd_set *aReadFdSet, const fd_set
|
||||
if (FD_ISSET(sSockFd, aReadFdSet))
|
||||
{
|
||||
otSimReceiveEvent(&event);
|
||||
// fprintf(stderr, "[%s] receive event\r\n", getenv("NODE_ID"));
|
||||
}
|
||||
|
||||
otSimRadioSpinelProcess(aInstance, &event);
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include "platform-posix.h"
|
||||
|
||||
#if OPENTHREAD_ENABLE_POSIX_APP_DAEMON
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
@@ -39,6 +38,7 @@
|
||||
#include <sys/un.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
@@ -56,6 +56,7 @@ static int sUartLock = -1;
|
||||
static int sSessionSocket = -1;
|
||||
#endif
|
||||
|
||||
static bool sEnabled = false;
|
||||
static const uint8_t *sWriteBuffer = NULL;
|
||||
static uint16_t sWriteLength = 0;
|
||||
|
||||
@@ -129,12 +130,15 @@ otError otPlatUartEnable(void)
|
||||
exit(OT_EXIT_FAILURE);
|
||||
}
|
||||
#endif // OPENTHREAD_ENABLE_POSIX_APP_DAEMON
|
||||
|
||||
sEnabled = true;
|
||||
return error;
|
||||
}
|
||||
|
||||
otError otPlatUartDisable(void)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
sEnabled = false;
|
||||
|
||||
#if OPENTHREAD_ENABLE_POSIX_APP_DAEMON
|
||||
if (sSessionSocket != -1)
|
||||
@@ -163,6 +167,7 @@ otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
assert(sEnabled);
|
||||
otEXPECT_ACTION(sWriteLength == 0, error = OT_ERROR_BUSY);
|
||||
|
||||
sWriteBuffer = aBuf;
|
||||
@@ -174,6 +179,8 @@ exit:
|
||||
|
||||
void platformUartUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, fd_set *aErrorFdSet, int *aMaxFd)
|
||||
{
|
||||
otEXPECT(sEnabled);
|
||||
|
||||
if (aReadFdSet != NULL)
|
||||
{
|
||||
#if OPENTHREAD_ENABLE_POSIX_APP_DAEMON
|
||||
@@ -214,6 +221,9 @@ void platformUartUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, fd_set *aE
|
||||
*aMaxFd = fd;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void platformUartProcess(const fd_set *aReadFdSet, const fd_set *aWriteFdSet, const fd_set *aErrorFdSet)
|
||||
@@ -221,6 +231,7 @@ void platformUartProcess(const fd_set *aReadFdSet, const fd_set *aWriteFdSet, co
|
||||
ssize_t rval;
|
||||
int fd;
|
||||
|
||||
otEXPECT(sEnabled);
|
||||
#if OPENTHREAD_ENABLE_POSIX_APP_DAEMON
|
||||
if (FD_ISSET(sUartSocket, aErrorFdSet))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user