[posix-app] add readline for CLI (#3511)

This commit is contained in:
Yakun Xu
2019-03-13 23:32:32 -07:00
committed by Jonathan Hui
parent 160ef467e6
commit dea08b2db7
10 changed files with 259 additions and 7 deletions
+3 -2
View File
@@ -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
}
+24
View File
@@ -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
#
+5
View File
@@ -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
+6
View File
@@ -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
+123
View File
@@ -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
+66
View File
@@ -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_
+18
View File
@@ -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;
+2
View File
@@ -35,6 +35,8 @@
#ifndef OPENTHREAD_SYSTEM_H_
#define OPENTHREAD_SYSTEM_H_
#include <sys/select.h>
#include <openthread/instance.h>
#ifdef __cplusplus
-4
View File
@@ -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);
+12 -1
View File
@@ -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))
{