summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-12-13 10:34:11 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-12-13 10:34:11 -0600
commit26ebd60ef8a3983dcef6dca9d8370d56465be79b (patch)
tree53c7508c4b4cd85d1c7e95a619e25d8a8ae09002 /apps
parent7e91f8810fdd60503d351af80ed91c5d4e31ca91 (diff)
downloadnuttx-26ebd60ef8a3983dcef6dca9d8370d56465be79b.tar.gz
nuttx-26ebd60ef8a3983dcef6dca9d8370d56465be79b.tar.bz2
nuttx-26ebd60ef8a3983dcef6dca9d8370d56465be79b.zip
.
Diffstat (limited to 'apps')
-rw-r--r--apps/system/cu/.gitignore11
-rw-r--r--apps/system/cu/Kconfig17
-rw-r--r--apps/system/cu/Makefile138
-rw-r--r--apps/system/cu/cu.h80
-rw-r--r--apps/system/cu/cu_main.c430
5 files changed, 676 insertions, 0 deletions
diff --git a/apps/system/cu/.gitignore b/apps/system/cu/.gitignore
new file mode 100644
index 000000000..fa1ec7579
--- /dev/null
+++ b/apps/system/cu/.gitignore
@@ -0,0 +1,11 @@
+/Make.dep
+/.depend
+/.built
+/*.asm
+/*.obj
+/*.rel
+/*.lst
+/*.sym
+/*.adb
+/*.lib
+/*.src
diff --git a/apps/system/cu/Kconfig b/apps/system/cu/Kconfig
new file mode 100644
index 000000000..22d3dfd9e
--- /dev/null
+++ b/apps/system/cu/Kconfig
@@ -0,0 +1,17 @@
+#
+# For a description of the syntax of this configuration file,
+# see misc/tools/kconfig-language.txt.
+#
+
+config SYSTEM_CUTERM
+ bool "CU serial terminal"
+ default n
+ ---help---
+ Enable the CU serial terminal. This is a minimalistic
+ implementation of the 'cu' terminal program (part of Taylor UUCP for
+ ages). Using it, you can simply open a serial port and interact with
+ it. Using '~.' you can leave the terminal program and drop back to nsh.
+
+ This terminal might come in handy for other people that have e.g. GS
+ modems, GPS receivers or other devices with text based serial
+ communications attached to their Nuttx systems.
diff --git a/apps/system/cu/Makefile b/apps/system/cu/Makefile
new file mode 100644
index 000000000..3a3416f8c
--- /dev/null
+++ b/apps/system/cu/Makefile
@@ -0,0 +1,138 @@
+############################################################################
+# apps/examples/cu/Makefile
+#
+# Copyright (C) 2011-2013 Gregory Nutt. All rights reserved.
+# Author: Gregory Nutt <gnutt@nuttx.org>
+#
+# 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 NuttX 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 OWNER 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 $(TOPDIR)/.config
+-include $(TOPDIR)/Make.defs
+include $(APPDIR)/Make.defs
+
+# USB terminal example
+
+ASRCS =
+CSRCS =
+MAINSRC = cu_main.c
+
+AOBJS = $(ASRCS:.S=$(OBJEXT))
+COBJS = $(CSRCS:.c=$(OBJEXT))
+MAINOBJ = $(MAINSRC:.c=$(OBJEXT))
+
+SRCS = $(ASRCS) $(CSRCS) $(MAINSRC)
+OBJS = $(AOBJS) $(COBJS)
+
+ifneq ($(CONFIG_BUILD_KERNEL),y)
+ OBJS += $(MAINOBJ)
+endif
+
+ifeq ($(CONFIG_WINDOWS_NATIVE),y)
+ BIN = ..\..\libapps$(LIBEXT)
+else
+ifeq ($(WINTOOL),y)
+ BIN = ..\\..\\libapps$(LIBEXT)
+else
+ BIN = ../../libapps$(LIBEXT)
+endif
+endif
+
+ifeq ($(WINTOOL),y)
+ INSTALL_DIR = "${shell cygpath -w $(BIN_DIR)}"
+else
+ INSTALL_DIR = $(BIN_DIR)
+endif
+
+CONFIG_XYZ_PROGNAME ?= cu$(EXEEXT)
+PROGNAME = $(CONFIG_XYZ_PROGNAME)
+
+ROOTDEPPATH = --dep-path .
+
+# Built-in application info
+
+APPNAME = cu
+PRIORITY = SCHED_PRIORITY_DEFAULT
+STACKSIZE = 2048
+
+# Common build
+
+VPATH =
+
+all: .built
+.PHONY: context clean depend distclean
+
+$(AOBJS): %$(OBJEXT): %.S
+ $(call ASSEMBLE, $<, $@)
+
+$(COBJS) $(MAINOBJ): %$(OBJEXT): %.c
+ $(call COMPILE, $<, $@)
+
+.built: $(OBJS)
+ $(call ARCHIVE, $(BIN), $(OBJS))
+ @touch .built
+
+ifeq ($(CONFIG_BUILD_KERNEL),y)
+$(BIN_DIR)$(DELIM)$(PROGNAME): $(OBJS) $(MAINOBJ)
+ @echo "LD: $(PROGNAME)"
+ $(Q) $(LD) $(LDELFFLAGS) $(LDLIBPATH) -o $(INSTALL_DIR)$(DELIM)$(PROGNAME) $(ARCHCRT0OBJ) $(MAINOBJ) $(LDLIBS)
+ $(Q) $(NM) -u $(INSTALL_DIR)$(DELIM)$(PROGNAME)
+
+install: $(BIN_DIR)$(DELIM)$(PROGNAME)
+
+else
+install:
+
+endif
+
+ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
+$(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat: $(DEPCONFIG) Makefile
+ $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
+
+context: $(BUILTIN_REGISTRY)$(DELIM)$(APPNAME)_main.bdat
+else
+context:
+endif
+
+.depend: Makefile $(SRCS)
+ @$(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
+ @touch $@
+
+depend: .depend
+
+clean:
+ $(call DELFILE, .built)
+ $(call CLEAN)
+
+distclean: clean
+ $(call DELFILE, Make.dep)
+ $(call DELFILE, .depend)
+
+-include Make.dep
+
diff --git a/apps/system/cu/cu.h b/apps/system/cu/cu.h
new file mode 100644
index 000000000..98b656f72
--- /dev/null
+++ b/apps/system/cu/cu.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+ * system/cu/cu.h
+ *
+ * Copyright (C) 2014 sysmocom - s.f.m.c. GmbH. All rights reserved.
+ * Author: Harald Welte <hwelte@sysmocom.de>
+ *
+ * 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 NuttX 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 OWNER 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 __APPS_SYSTEM_CU_CUTERM_H
+#define __APPS_SYSTEM_CU_CUTERM_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <semaphore.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* All terminal state data is packaged in a single structure to minimize
+ * name conflicts with other global symbols -- a poor man's name space.
+ */
+
+struct cu_globals_s
+{
+ int infd; /* Incmoming data from serial port */
+ int outfd; /* Outgoing data to serial port */
+ pthread_t listener; /* Terminal listener thread */
+};
+
+/****************************************************************************
+ * Public Variables
+ ****************************************************************************/
+
+/* terminal state data */
+
+extern struct cu_globals_s g_cu;
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#endif /* __APPS_SYSTEM_CU_CUTERM_H */
diff --git a/apps/system/cu/cu_main.c b/apps/system/cu/cu_main.c
new file mode 100644
index 000000000..b4fef578c
--- /dev/null
+++ b/apps/system/cu/cu_main.c
@@ -0,0 +1,430 @@
+/****************************************************************************
+ * examples/cu/cu_main.c
+ *
+ * Copyright (C) 2014 sysmocom - s.f.m.c. GmbH. All rights reserved.
+ * Author: Harald Welte <hwelte@sysmocom.de>
+ *
+ * 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 NuttX 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 OWNER 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <termios.h>
+#include <debug.h>
+
+#include <apps/readline.h>
+
+#include "cu.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define SIGINT 2
+#define SIGKILL 9
+#define SIGTERM 15
+
+enum parity_mode
+{
+ PARITY_NONE,
+ PARITY_EVEN,
+ PARITY_ODD,
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* terminal state data */
+
+struct cu_globals_s g_cu;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cu_listener
+ *
+ * Description:
+ * Entry point for the listener thread.
+ *
+ ****************************************************************************/
+
+static FAR void *cu_listener(FAR void *parameter)
+{
+ for (;;)
+ {
+ int rc;
+ char ch;
+
+ rc = read(g_cu.infd, &ch, 1);
+ if (rc <= 0)
+ {
+ break;
+ }
+
+ fputc(ch, stdout);
+ fflush(stdout);
+ }
+
+ /* Won't get here */
+
+ return NULL;
+}
+
+static void sigint(int sig)
+{
+ pthread_cancel(g_cu.listener);
+ close(g_cu.outfd);
+ close(g_cu.infd);
+ exit(0);
+}
+
+static int enable_crlf_conversion(int fd)
+{
+#ifdef CONFIG_SERIAL_TERMIOS
+ int rc = 0;
+ int ret;
+ struct termios tio;
+
+ /* enable \n -> \r\n conversion during write */
+
+ ret = tcgetattr(fd, &tio);
+ if (ret)
+ {
+ fprintf(stderr, "en_crlf_conv: ERROR during tcgetattr(): %d\n", errno);
+ rc = -1;
+ }
+
+ tio.c_oflag = OPOST | ONLCR;
+ ret = tcsetattr(fd, TCSANOW, &tio);
+ if (ret)
+ {
+ fprintf(stderr, "en_crlf_conv: ERROR during tcsetattr(): %d\n", errno);
+ rc = -1;
+ }
+
+ return rc;
+#else
+ return -1;
+#endif
+}
+
+static int set_baudrate(int fd, int rate, enum parity_mode parity, int rtscts)
+{
+#ifdef CONFIG_SERIAL_TERMIOS
+ int rc = 0;
+ int ret;
+ struct termios tio;
+
+ /* enable \n -> \r\n conversion during write */
+
+ ret = tcgetattr(fd, &tio);
+ if (ret)
+ {
+ fprintf(stderr, "set_baudrate: ERROR during tcgetattr(): %d\n", errno);
+ rc = -1;
+ }
+
+ if (rate != 0)
+ {
+ cfsetspeed(&tio, rate);
+ }
+
+ switch (parity)
+ {
+ case PARITY_EVEN:
+ tio.c_cflag = PARENB;
+ break;
+
+ case PARITY_ODD:
+ tio.c_cflag = PARENB | PARODD;
+ break;
+
+ case PARITY_NONE:
+ break;
+ }
+
+ if (rtscts)
+ {
+ tio.c_cflag |= CRTS_IFLOW | CCTS_OFLOW;
+ }
+
+ ret = tcsetattr(fd, TCSANOW, &tio);
+ if (ret)
+ {
+ fprintf(stderr, "set_baudrate: ERROR during tcsetattr(): %d\n", errno);
+ rc = -1;
+ }
+
+ return rc;
+#else
+ if (rate == 0)
+ {
+ return 0;
+ }
+
+ return -1;
+#endif
+}
+
+static void print_help(void)
+{
+ printf("Usage: cu [options]\n"
+ " -l: Use named device (e.g. /dev/ttyS1)\n"
+ " -e: Set even parity\n"
+ " -o: Set odd parity\n"
+ " -s: Use given speed\n"
+ " -r: Disable RTS/CTS flow control (default: on)\n"
+ " -?: This help\n");
+}
+
+static void print_escape_help(void)
+{
+ printf("[Escape sequences]\n"
+ "[~. hangup]\n"
+ );
+}
+
+static int cu_cmd(char bcmd)
+{
+ switch (bcmd)
+ {
+ case '?':
+ print_escape_help();
+ break;
+
+ case '.':
+ return 1;
+
+ /* FIXME: implement other commands such as send/receive file */
+ }
+
+ return 0;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cu_main
+ *
+ * Description:
+ * Main entry point for the serial terminal example.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_BUILD_KERNEL
+int main(int argc, FAR char *argv[])
+#else
+int cu_main(int argc, FAR char *argv[])
+#endif
+{
+ pthread_attr_t attr;
+ struct sigaction sa;
+ FAR char *devname = NULL;
+ int baudrate = 0;
+ enum parity_mode parity = PARITY_NONE;
+ int rtscts = 1;
+ int option;
+ int ret;
+ int bcmd;
+ int start_of_line = 1;
+
+ /* Initialize global data */
+
+ memset(&g_cu, 0, sizeof(struct cu_globals_s));
+
+ /* Install signal handlers */
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = sigint;
+ sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGTERM, &sa, NULL);
+ sigaction(SIGKILL, &sa, NULL);
+
+ while ((option = getopt(argc, argv, "l:s:eor?")) != ERROR)
+ {
+ switch (option)
+ {
+ case 'l':
+ devname = optarg;
+ break;
+
+ case 's':
+ baudrate = atoi(optarg);
+ break;
+
+ case 'e':
+ parity = PARITY_ODD;
+ break;
+
+ case 'o':
+ parity = PARITY_EVEN;
+ break;
+
+ case 'r':
+ rtscts = 0;
+ break;
+
+ case '?':
+ print_help();
+ return EXIT_SUCCESS;
+
+ default:
+ return EXIT_FAILURE;
+ }
+ }
+
+ /* Open the serial device for writing */
+
+ g_cu.outfd = open(devname, O_WRONLY);
+ if (g_cu.outfd < 0)
+ {
+ fprintf(stderr, "cu_main: ERROR: Failed to open %s for writing: %d\n",
+ devname, errno);
+ goto errout_with_devinit;
+ }
+
+ enable_crlf_conversion(g_cu.outfd);
+ set_baudrate(g_cu.outfd, baudrate, parity, rtscts);
+
+ /* Open the serial device for reading. Since we are already connected, this
+ * should not fail.
+ */
+
+ g_cu.infd = open(devname, O_RDONLY);
+ if (g_cu.infd < 0)
+ {
+ fprintf(stderr, "cu_main: ERROR: Failed to open %s for reading: %d\n",
+ devname, errno);
+ goto errout_with_outfd;
+ }
+
+ /* Start the serial receiver thread */
+
+ ret = pthread_attr_init(&attr);
+ if (ret != OK)
+ {
+ fprintf(stderr, "cu_main: pthread_attr_init failed: %d\n", ret);
+ goto errout_with_fds;
+ }
+
+ ret = pthread_create(&g_cu.listener, &attr,
+ cu_listener, (pthread_addr_t)0);
+ if (ret != 0)
+ {
+ fprintf(stderr, "cu_main: Error in thread creation: %d\n", ret);
+ goto errout_with_fds;
+ }
+
+ /* Send messages and get responses -- forever */
+
+ for (;;)
+ {
+ int ch = getc(stdin);
+
+ if (ch <= 0)
+ {
+ break;
+ }
+
+ if (start_of_line == 1 && ch == '~')
+ {
+ /* we've seen and escape (~) character, echo it to local
+ * terminal and read the next char from serial
+ */
+
+ fputc(ch, stdout);
+ bcmd = getc(stdin);
+ if (bcmd == ch)
+ {
+ /* Escaping a tilde: handle like normal char */
+
+ write(g_cu.outfd, &ch, 1);
+ continue;
+ }
+ else
+ {
+ if (cu_cmd(bcmd) == 1)
+ {
+ break;
+ }
+ }
+ }
+
+ /* Normal character */
+
+ write(g_cu.outfd, &ch, 1);
+
+ /* Determine if we are now at the start of a new line or not */
+
+ if (ch == '\n' || ch == '\r')
+ {
+ start_of_line = 1;
+ }
+ else
+ {
+ start_of_line = 0;
+ }
+ }
+
+ pthread_cancel(g_cu.listener);
+ pthread_attr_destroy(&attr);
+
+ /* Error exits */
+
+errout_with_fds:
+ close(g_cu.infd);
+errout_with_outfd:
+ close(g_cu.outfd);
+errout_with_devinit:
+ return EXIT_FAILURE;
+}