diff src/lwwire-serial.c @ 0:bef2801ac83e

Initial checkin with reference implementation of core protocol Initial checkin. Has the initial version of the protocol documentation along with a reference implementation of the core protocol.
author William Astle <lost@l-w.ca>
date Sun, 08 May 2016 12:56:39 -0600
parents
children cfc9524cca2c
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lwwire-serial.c	Sun May 08 12:56:39 2016 -0600
@@ -0,0 +1,135 @@
+/*
+Set up a serial port and launch a lwwire process to handle it. The lwwire
+process will be called with "exec".
+
+Usage:
+
+lwwire-serial <port> [speed] [lwwire binary args...]
+
+<port> is the device name for the serial port. [speed] is the optional speed
+to set the port to with a default of 115200. [lwwire binary] is the optional
+name for the lwwire binary. Default is "./lwwire". If [lwwire binary] is
+specified, then [speed] must also be specified.
+
+*/
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+int main(int argc, char **argv)
+{
+	char *lwwire = "lwwire";
+	int speed = 115200;
+	char *port;
+	int i, rargc;
+	char **rargv;
+	int fd;
+	struct termios io_mod;
+
+	if (argc >= 4)
+	{
+		lwwire = argv[3];
+	}
+	if (argc >= 3)
+	{
+		speed = strtol(argv[2], NULL, 10);
+	}
+	if (argc < 2)
+	{
+		fprintf(stderr, "Usage: %s <port> [<speed> [<lwwire binary> [args]]]\n", argv[0]);
+		exit(0);
+	}
+	port = argv[1];
+	
+	fprintf(stderr, "Starting lwwire on port '%s' at speed %d\n", port, speed);
+	
+	// open serial port
+	fd = open(port, O_RDWR | O_NOCTTY);
+	if (fd < 0)
+	{
+		fprintf(stderr, "Error opening port %s: %s\n", port, strerror(errno));
+		exit(1);
+	}
+	// set up parameters
+	// this is all theoretically *mostly* posix correct except for some of the 
+	// Bxxxx constants.	
+	tcgetattr(fd, &io_mod);
+	io_mod.c_iflag &= 
+		~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+	io_mod.c_oflag &= ~OPOST;
+	io_mod.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+	io_mod.c_cflag &= ~(CSIZE|PARENB);
+	io_mod.c_cflag |= CS8;
+	switch (speed)
+	{
+	case 38400:
+		cfsetispeed(&io_mod, B38400);
+		cfsetospeed(&io_mod, B38400);
+		break;
+	
+	case 57600:
+		cfsetispeed(&io_mod, B57600);
+		cfsetospeed(&io_mod, B57600);
+		break;
+	
+	case 115200:
+		cfsetispeed(&io_mod, B115200);
+		cfsetospeed(&io_mod, B115200);
+		break;
+	
+	case 230400:
+		cfsetispeed(&io_mod, B230400);
+		cfsetospeed(&io_mod, B230400);
+		break;
+		
+	default:
+		fprintf(stderr, "Unrecognzied speed %d on port %s; using 38400\n", speed, port);
+		cfsetispeed(&io_mod, B38400);
+		cfsetospeed(&io_mod, B38400);
+		break;	
+	}
+
+	if (tcsetattr(fd, TCSANOW, &io_mod) < 0)
+	{
+		fprintf(stderr, "Cannot set serial line mode properly: %s", strerror(errno));
+		exit(1);
+	}
+
+	// set up stdin/stdout
+	if (dup2(fd, 0) < 0)
+	{
+		fprintf(stderr, "Cannot set up stdin file descriptor: %s\n", strerror(errno));
+		exit(1);
+	}
+	if (dup2(fd, 1) < 0)
+	{
+		fprintf(stderr, "Cannot set up stdout file descriptor: %s\n", strerror(errno));
+		exit(1);
+	}
+	// close the original FD since we don't need it any more.
+	close(fd);
+
+	// execute binary
+	rargc = 1;
+	if (argc >= 5)
+	{
+		rargc += argc - 4;
+	}
+	rargv = malloc(sizeof(char *) * (rargc + 1));
+	rargv[0] = lwwire;
+	for (i = 4; i < argc; i++)
+	{
+		fprintf(stderr, "Passing argument %d of %d: %s\n", i - 3, rargc, argv[i]);
+		rargv[i - 3] = argv[i];
+	}
+	rargv[rargc] = NULL;
+	
+	execv(lwwire, rargv);
+	fprintf(stderr, "Failed to execute %s: %s\n", lwwire, strerror(errno));
+	exit(1);
+}