commit 894585b0ec9e43c4c278e9fa54e5ecc58ed76006
Author: Erik Gilling <konkers@konkers.net>
Date: Thu, 16 Dec 2010 14:49:14 -0800
initial import
Converted to linux kernel style and added propper BSD licence banner.
Signed-off-by: Erik Gilling <konkers@konkers.net>
Diffstat:
A | Makefile | | | 1 | + |
A | README | | | 2 | ++ |
A | sconsole.c | | | 250 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
3 files changed, 253 insertions(+), 0 deletions(-)
diff --git a/Makefile b/Makefile
@@ -0,0 +1 @@
+sconsole: sconsole.o
diff --git a/README b/README
@@ -0,0 +1 @@
+see sconsole.c for licence and information
+\ No newline at end of file
diff --git a/sconsole.c b/sconsole.c
@@ -0,0 +1,250 @@
+/* sconsole - cheap serial console (for xterm, etc)
+ *
+ * Copyright (c) 2005-2010
+ * Brian Swetland.
+ *
+ * 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 University 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 REGENTS 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 REGENTS 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <termios.h>
+#include <signal.h>
+#include <poll.h>
+#include <unistd.h>
+
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/fcntl.h>
+#include <sys/types.h>
+
+static struct termios tio_save;
+
+static void stdin_raw_init(void)
+{
+ struct termios tio;
+
+ if (tcgetattr(0, &tio))
+ return;
+ if (tcgetattr(0, &tio_save))
+ return;
+
+ /* disable CANON, ECHO*, etc */
+ tio.c_lflag = 0;
+
+ /* no timeout but request at least one character per read */
+ tio.c_cc[VTIME] = 0;
+ tio.c_cc[VMIN] = 1;
+
+ tcsetattr(0, TCSANOW, &tio);
+ tcflush(0, TCIFLUSH);
+}
+
+static void stdin_raw_restore(void)
+{
+ tcsetattr(0, TCSANOW, &tio_save);
+ tcflush(0, TCIFLUSH);
+}
+
+void oops(int x)
+{
+ char *msg = "\n[ killed by signal ]\n";
+ write(2, msg, strlen(msg));
+ stdin_raw_restore();
+ exit(1);
+}
+
+int text2speed(const char *s)
+{
+ int n = atoi(s);
+ switch (n) {
+ case 115200:
+ return B115200;
+ case 38400:
+ return B38400;
+ case 19200:
+ return B19200;
+ case 9600:
+ return B9600;
+ default:
+ return B115200;
+ }
+}
+
+int openserial(const char *device, int speed)
+{
+ struct termios tio;
+ int fd;
+ fd = open(device, O_RDWR | O_NOCTTY);
+
+ if (fd < 0)
+ return -1;
+
+ if (tcgetattr(fd, &tio))
+ memset(&tio, 0, sizeof(tio));
+
+ tio.c_cflag = B57600 | CS8 | CLOCAL | CREAD;
+ tio.c_iflag = IGNPAR;
+ tio.c_lflag = 0; /* turn of CANON, ECHO*, etc */
+ tio.c_cc[VTIME] = 0;
+ tio.c_cc[VMIN] = 1;
+ tcsetattr(fd, TCSANOW, &tio);
+ tcflush(fd, TCIFLUSH);
+
+ tio.c_cflag = speed | CS8 | CLOCAL | CREAD;
+ tcsetattr(fd, TCSANOW, &tio);
+ tcflush(fd, TCIFLUSH);
+ return fd;
+}
+
+static unsigned char valid[256];
+
+#define STATE_IDLE 0
+#define STATE_PREFIX 1
+#define STATE_COMMAND 2
+
+int main(int argc, char *argv[])
+{
+ struct pollfd fds[2];
+ int speed = B115200;
+ const char *device = "/dev/ttyUSB0";
+ int fd, n;
+ int escape = 0;
+ int logfd = -1;
+
+ for (n = ' '; n < 127; n++)
+ valid[n] = 1;
+
+ valid[8] = 1; /* backspace */
+ valid[9] = 1; /* tab */
+ valid[10] = 1; /* newline */
+ valid[13] = 1; /* carriage return */
+
+ while ((argc > 1) && (argv[1][0] == '-')) {
+ switch (argv[1][1]) {
+ case 't':
+ /* transparent mode */
+ for (n = 0; n < 256; n++)
+ valid[n] = 1;
+ break;
+ case 'l':
+ /* log */
+ logfd = open("console.log", O_CREAT | O_WRONLY, 0644);
+ break;
+ default:
+ fprintf(stderr, "unknown option %s\n", argv[1]);
+ return 1;
+ }
+ argv++;
+ argc--;
+ }
+
+ if (argc > 1) {
+ device = argv[1];
+ argc--;
+ argv++;
+ }
+
+ if (argc > 1) {
+ speed = text2speed(argv[1]);
+ fprintf(stderr, "SPEED: %s %08x\n", argv[1], speed);
+ argc--;
+ argv++;
+ }
+
+ fd = openserial(device, speed);
+ if (fd < 0) {
+ fprintf(stderr, "stderr open '%s'\n", device);
+ return -1;
+ }
+
+ stdin_raw_init();
+ signal(SIGINT, oops);
+
+ fds[0].fd = 0;
+ fds[0].events = POLLIN;
+
+ fds[1].fd = fd;
+ fds[1].events = POLLIN;
+
+ fprintf(stderr, "[ %s ]\n", device);
+
+ for (;;) {
+ unsigned char x, t;
+
+ if (poll(fds, 2, -1) > 0) {
+ if (fds[0].revents & (POLLERR | POLLHUP)) {
+ fprintf(stderr, "\n[ stdin port closed ]\n");
+ break;
+ }
+ if (fds[1].revents & (POLLERR | POLLHUP)) {
+ fprintf(stderr, "\n[ serial port closed ]\n");
+ break;
+ }
+ if ((fds[0].revents & POLLIN) && (read(0, &x, 1) == 1)) {
+ if (escape) {
+ escape = 0;
+ switch (x) {
+ case 27:
+ write(fd, &x, 1);
+ break;
+ case 'b':
+ fprintf(stderr, "[ break ]\n");
+ tcsendbreak(fd, 0);
+ break;
+ case 'x':
+ fprintf(stderr, "[ exit ]\n");
+ goto done;
+ default:
+ fprintf(stderr, "[ huh? ]\n");
+ break;
+ }
+ } else {
+ if (x == 27) {
+ fprintf(stderr, "\n[ (b)reak? e(x)it? ]\n");
+ escape = 1;
+ } else {
+ write(fd, &x, 1);
+ }
+ }
+ }
+ if ((fds[1].revents & POLLIN) && (read(fd, &x, 1) == 1)) {
+ if (!valid[x])
+ x = '.';
+ write(1, &x, 1);
+ if (logfd != -1)
+ write(logfd, &x, 1);
+ }
+ }
+ }
+
+done:
+ stdin_raw_restore();
+ return 0;
+}