annotate src/lwwire-serial.c @ 4:56f53e48ab50

Fix off by one bug in protocol extension negotiation. Arrays are indexed from zero!!!!
author William Astle <lost@l-w.ca>
date Sun, 29 May 2016 21:50:51 -0600
parents cfc9524cca2c
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
1 /*
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
2 Set up a serial port and launch a lwwire process to handle it. The lwwire
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
3 process will be called with "exec".
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
4
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
5 Usage:
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
6
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
7 lwwire-serial <port> [speed] [lwwire binary args...]
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
8
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
9 <port> is the device name for the serial port. [speed] is the optional speed
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
10 to set the port to with a default of 115200. [lwwire binary] is the optional
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
11 name for the lwwire binary. Default is "./lwwire". If [lwwire binary] is
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
12 specified, then [speed] must also be specified.
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
13
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
14 */
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
15
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
16 #include <errno.h>
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
17 #include <fcntl.h>
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
18 #include <stdio.h>
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
19 #include <stdlib.h>
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
20 #include <string.h>
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
21 #include <termios.h>
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
22 #include <unistd.h>
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
23
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
24 int main(int argc, char **argv)
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
25 {
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
26 char *lwwire = "lwwire";
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
27 int speed = 115200;
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
28 char *port;
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
29 int i, rargc;
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
30 char **rargv;
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
31 int fd;
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
32 struct termios io_mod;
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
33
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
34 if (argc >= 4)
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
35 {
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
36 lwwire = argv[3];
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
37 }
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
38 if (argc >= 3)
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
39 {
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
40 speed = strtol(argv[2], NULL, 10);
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
41 }
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
42 if (argc < 2)
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
43 {
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
44 fprintf(stderr, "Usage: %s <port> [<speed> [<lwwire binary> [args]]]\n", argv[0]);
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
45 exit(0);
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
46 }
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
47 port = argv[1];
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
48
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
49 fprintf(stderr, "Starting lwwire on port '%s' at speed %d\n", port, speed);
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
50
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
51 // open serial port
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
52 fd = open(port, O_RDWR | O_NOCTTY);
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
53 if (fd < 0)
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
54 {
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
55 fprintf(stderr, "Error opening port %s: %s\n", port, strerror(errno));
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
56 exit(1);
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
57 }
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
58 // set up parameters
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
59 // this is all theoretically *mostly* posix correct except for some of the
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
60 // Bxxxx constants.
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
61 tcgetattr(fd, &io_mod);
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
62 io_mod.c_iflag &=
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
63 ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
64 io_mod.c_oflag &= ~OPOST;
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
65 io_mod.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
66 io_mod.c_cflag &= ~(CSIZE|PARENB);
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
67 io_mod.c_cflag |= CS8;
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
68 switch (speed)
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
69 {
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
70 case 38400:
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
71 cfsetispeed(&io_mod, B38400);
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
72 cfsetospeed(&io_mod, B38400);
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
73 break;
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
74
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
75 case 57600:
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
76 cfsetispeed(&io_mod, B57600);
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
77 cfsetospeed(&io_mod, B57600);
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
78 break;
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
79
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
80 case 115200:
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
81 cfsetispeed(&io_mod, B115200);
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
82 cfsetospeed(&io_mod, B115200);
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
83 break;
1
cfc9524cca2c Add 430600 and 921600 baud rates to serial shim
William Astle <lost@l-w.ca>
parents: 0
diff changeset
84
cfc9524cca2c Add 430600 and 921600 baud rates to serial shim
William Astle <lost@l-w.ca>
parents: 0
diff changeset
85 #ifdef B230400
0
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
86 case 230400:
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
87 cfsetispeed(&io_mod, B230400);
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
88 cfsetospeed(&io_mod, B230400);
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
89 break;
1
cfc9524cca2c Add 430600 and 921600 baud rates to serial shim
William Astle <lost@l-w.ca>
parents: 0
diff changeset
90 #endif
cfc9524cca2c Add 430600 and 921600 baud rates to serial shim
William Astle <lost@l-w.ca>
parents: 0
diff changeset
91
cfc9524cca2c Add 430600 and 921600 baud rates to serial shim
William Astle <lost@l-w.ca>
parents: 0
diff changeset
92 #ifdef B460800
cfc9524cca2c Add 430600 and 921600 baud rates to serial shim
William Astle <lost@l-w.ca>
parents: 0
diff changeset
93 case 460800:
cfc9524cca2c Add 430600 and 921600 baud rates to serial shim
William Astle <lost@l-w.ca>
parents: 0
diff changeset
94 cfsetispeed(&io_mod, B460800);
cfc9524cca2c Add 430600 and 921600 baud rates to serial shim
William Astle <lost@l-w.ca>
parents: 0
diff changeset
95 cfsetospeed(&io_mod, B460800);
cfc9524cca2c Add 430600 and 921600 baud rates to serial shim
William Astle <lost@l-w.ca>
parents: 0
diff changeset
96 break;
cfc9524cca2c Add 430600 and 921600 baud rates to serial shim
William Astle <lost@l-w.ca>
parents: 0
diff changeset
97 #endif
cfc9524cca2c Add 430600 and 921600 baud rates to serial shim
William Astle <lost@l-w.ca>
parents: 0
diff changeset
98
cfc9524cca2c Add 430600 and 921600 baud rates to serial shim
William Astle <lost@l-w.ca>
parents: 0
diff changeset
99 #ifdef B921600
cfc9524cca2c Add 430600 and 921600 baud rates to serial shim
William Astle <lost@l-w.ca>
parents: 0
diff changeset
100 case 921600:
cfc9524cca2c Add 430600 and 921600 baud rates to serial shim
William Astle <lost@l-w.ca>
parents: 0
diff changeset
101 cfsetispeed(&io_mod, B921600);
cfc9524cca2c Add 430600 and 921600 baud rates to serial shim
William Astle <lost@l-w.ca>
parents: 0
diff changeset
102 cfsetospeed(&io_mod, B921600);
cfc9524cca2c Add 430600 and 921600 baud rates to serial shim
William Astle <lost@l-w.ca>
parents: 0
diff changeset
103 break;
cfc9524cca2c Add 430600 and 921600 baud rates to serial shim
William Astle <lost@l-w.ca>
parents: 0
diff changeset
104 #endif
cfc9524cca2c Add 430600 and 921600 baud rates to serial shim
William Astle <lost@l-w.ca>
parents: 0
diff changeset
105
0
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
106 default:
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
107 fprintf(stderr, "Unrecognzied speed %d on port %s; using 38400\n", speed, port);
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
108 cfsetispeed(&io_mod, B38400);
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
109 cfsetospeed(&io_mod, B38400);
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
110 break;
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
111 }
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
112
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
113 if (tcsetattr(fd, TCSANOW, &io_mod) < 0)
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
114 {
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
115 fprintf(stderr, "Cannot set serial line mode properly: %s", strerror(errno));
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
116 exit(1);
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
117 }
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
118
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
119 // set up stdin/stdout
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
120 if (dup2(fd, 0) < 0)
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
121 {
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
122 fprintf(stderr, "Cannot set up stdin file descriptor: %s\n", strerror(errno));
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
123 exit(1);
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
124 }
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
125 if (dup2(fd, 1) < 0)
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
126 {
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
127 fprintf(stderr, "Cannot set up stdout file descriptor: %s\n", strerror(errno));
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
128 exit(1);
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
129 }
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
130 // close the original FD since we don't need it any more.
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
131 close(fd);
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
132
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
133 // execute binary
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
134 rargc = 1;
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
135 if (argc >= 5)
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
136 {
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
137 rargc += argc - 4;
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
138 }
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
139 rargv = malloc(sizeof(char *) * (rargc + 1));
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
140 rargv[0] = lwwire;
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
141 for (i = 4; i < argc; i++)
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
142 {
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
143 fprintf(stderr, "Passing argument %d of %d: %s\n", i - 3, rargc, argv[i]);
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
144 rargv[i - 3] = argv[i];
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
145 }
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
146 rargv[rargc] = NULL;
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
147
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
148 execv(lwwire, rargv);
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
149 fprintf(stderr, "Failed to execute %s: %s\n", lwwire, strerror(errno));
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
150 exit(1);
bef2801ac83e Initial checkin with reference implementation of core protocol
William Astle <lost@l-w.ca>
parents:
diff changeset
151 }