comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:bef2801ac83e
1 /*
2 Set up a serial port and launch a lwwire process to handle it. The lwwire
3 process will be called with "exec".
4
5 Usage:
6
7 lwwire-serial <port> [speed] [lwwire binary args...]
8
9 <port> is the device name for the serial port. [speed] is the optional speed
10 to set the port to with a default of 115200. [lwwire binary] is the optional
11 name for the lwwire binary. Default is "./lwwire". If [lwwire binary] is
12 specified, then [speed] must also be specified.
13
14 */
15
16 #include <errno.h>
17 #include <fcntl.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <termios.h>
22 #include <unistd.h>
23
24 int main(int argc, char **argv)
25 {
26 char *lwwire = "lwwire";
27 int speed = 115200;
28 char *port;
29 int i, rargc;
30 char **rargv;
31 int fd;
32 struct termios io_mod;
33
34 if (argc >= 4)
35 {
36 lwwire = argv[3];
37 }
38 if (argc >= 3)
39 {
40 speed = strtol(argv[2], NULL, 10);
41 }
42 if (argc < 2)
43 {
44 fprintf(stderr, "Usage: %s <port> [<speed> [<lwwire binary> [args]]]\n", argv[0]);
45 exit(0);
46 }
47 port = argv[1];
48
49 fprintf(stderr, "Starting lwwire on port '%s' at speed %d\n", port, speed);
50
51 // open serial port
52 fd = open(port, O_RDWR | O_NOCTTY);
53 if (fd < 0)
54 {
55 fprintf(stderr, "Error opening port %s: %s\n", port, strerror(errno));
56 exit(1);
57 }
58 // set up parameters
59 // this is all theoretically *mostly* posix correct except for some of the
60 // Bxxxx constants.
61 tcgetattr(fd, &io_mod);
62 io_mod.c_iflag &=
63 ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
64 io_mod.c_oflag &= ~OPOST;
65 io_mod.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
66 io_mod.c_cflag &= ~(CSIZE|PARENB);
67 io_mod.c_cflag |= CS8;
68 switch (speed)
69 {
70 case 38400:
71 cfsetispeed(&io_mod, B38400);
72 cfsetospeed(&io_mod, B38400);
73 break;
74
75 case 57600:
76 cfsetispeed(&io_mod, B57600);
77 cfsetospeed(&io_mod, B57600);
78 break;
79
80 case 115200:
81 cfsetispeed(&io_mod, B115200);
82 cfsetospeed(&io_mod, B115200);
83 break;
84
85 case 230400:
86 cfsetispeed(&io_mod, B230400);
87 cfsetospeed(&io_mod, B230400);
88 break;
89
90 default:
91 fprintf(stderr, "Unrecognzied speed %d on port %s; using 38400\n", speed, port);
92 cfsetispeed(&io_mod, B38400);
93 cfsetospeed(&io_mod, B38400);
94 break;
95 }
96
97 if (tcsetattr(fd, TCSANOW, &io_mod) < 0)
98 {
99 fprintf(stderr, "Cannot set serial line mode properly: %s", strerror(errno));
100 exit(1);
101 }
102
103 // set up stdin/stdout
104 if (dup2(fd, 0) < 0)
105 {
106 fprintf(stderr, "Cannot set up stdin file descriptor: %s\n", strerror(errno));
107 exit(1);
108 }
109 if (dup2(fd, 1) < 0)
110 {
111 fprintf(stderr, "Cannot set up stdout file descriptor: %s\n", strerror(errno));
112 exit(1);
113 }
114 // close the original FD since we don't need it any more.
115 close(fd);
116
117 // execute binary
118 rargc = 1;
119 if (argc >= 5)
120 {
121 rargc += argc - 4;
122 }
123 rargv = malloc(sizeof(char *) * (rargc + 1));
124 rargv[0] = lwwire;
125 for (i = 4; i < argc; i++)
126 {
127 fprintf(stderr, "Passing argument %d of %d: %s\n", i - 3, rargc, argv[i]);
128 rargv[i - 3] = argv[i];
129 }
130 rargv[rargc] = NULL;
131
132 execv(lwwire, rargv);
133 fprintf(stderr, "Failed to execute %s: %s\n", lwwire, strerror(errno));
134 exit(1);
135 }