Mercurial > hg > index.cgi
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); +}