ao-tools/ao-cal-accel: Initialize byte count var 'l'
[fw/altos] / ao-tools / ao-cal-accel / ao-cal-accel.c
1 /*
2  * Copyright © 2014 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 #include <err.h>
20 #include <fcntl.h>
21 #include <gelf.h>
22 #include <stdio.h>
23 #include <stdint.h>
24 #include <stdlib.h>
25 #include <sysexits.h>
26 #include <unistd.h>
27 #include <getopt.h>
28 #include <string.h>
29 #include <stdbool.h>
30 #include <termios.h>
31 #include "ao-elf.h"
32 #include "ccdbg.h"
33 #include "cc-usb.h"
34 #include "cc.h"
35 #include "ao-verbose.h"
36
37 static const struct option options[] = {
38         { .name = "tty", .has_arg = 1, .val = 'T' },
39         { .name = "device", .has_arg = 1, .val = 'D' },
40         { .name = "raw", .has_arg = 0, .val = 'r' },
41         { .name = "verbose", .has_arg = 1, .val = 'v' },
42         { 0, 0, 0, 0},
43 };
44
45 static void usage(char *program)
46 {
47         fprintf(stderr, "usage: %s [--verbose=<verbose>] [--device=<device>] [-tty=<tty>]\n", program);
48         exit(1);
49 }
50
51 static void
52 done(struct cc_usb *cc, int code)
53 {
54         cc_usb_close(cc);
55         exit (code);
56 }
57
58 static char **
59 tok(char *line) {
60         char    **strs = malloc (sizeof (char *)), *str;
61         int     n = 0;
62
63         while ((str = strtok(line, " \t"))) {
64                 line = NULL;
65                 strs = realloc(strs, (n + 2) * sizeof (char *));
66                 strs[n] = strdup(str);
67                 n++;
68         }
69         strs[n] = '\0';
70         return strs;
71 }
72
73 struct flash {
74         struct flash    *next;
75         char            line[512];
76         char            **strs;
77 };
78
79 static struct flash *
80 flash(struct cc_usb *usb)
81 {
82         struct flash    *head = NULL, **tail = &head;
83         cc_usb_printf(usb, "c s\nv\n");
84         for (;;) {
85                 char    line[512];
86                 struct flash    *b;
87
88                 cc_usb_getline(usb, line, sizeof (line));
89                 b = malloc (sizeof (struct flash));
90                 strcpy(b->line, line);
91                 b->strs = tok(line);
92                 b->next = NULL;
93                 *tail = b;
94                 tail = &b->next;
95                 if (strstr(line, "software-version"))
96                         break;
97         }
98         return head;
99 }
100
101 static char **
102 find_flash(struct flash *b, char *word0) {
103         for (;b; b = b->next) {
104                 if (strstr(b->line, word0))
105                         return b->strs;
106         }
107         return NULL;
108 }
109
110 static void
111 await_key(void)
112 {
113         struct termios  termios, termios_save;
114         char    buf[512];
115
116         tcgetattr(0, &termios);
117         termios_save = termios;
118         cfmakeraw(&termios);
119         tcsetattr(0, TCSAFLUSH, &termios);
120         read(0, buf, sizeof (buf));
121         tcsetattr(0, TCSAFLUSH, &termios_save);
122 }
123
124 static int
125 do_cal(struct cc_usb *usb) {
126         struct flash    *b;
127         char    **accel;
128         char    line[1024];
129         int     l = 0;
130         int     running = 0;
131         int     worked = 1;
132
133         cc_usb_printf(usb, "E 1\nc a 0\n");
134
135         for (;;) {
136                 int     c = cc_usb_getchar_timeout(usb, 20*1000);
137
138                 if (c == '\n')
139                         l = 0;
140                 else if (l < sizeof (line) - 1)
141                         line[l++] = c;
142                 line[l] = '\0';
143                 putchar(c); fflush(stdout);
144                 if (strstr(line, "press a key...")) {
145                         await_key();
146                         cc_usb_printf(usb, " ");
147                         l = 0;
148                         running = 1;
149                 }
150                 else if (strstr(line, "Invalid"))
151                         worked = 0;
152                 if (running && strstr(line, ">")) {
153                         printf("\n");
154                         break;
155                 }
156         }
157         cc_usb_printf(usb, "E 0\n");
158
159         if (!worked) {
160                 printf("Calibration failed\n");
161                 return 0;
162         }
163
164         b = flash(usb);
165
166         accel = find_flash(b, "Accel cal");
167         if (!accel) {
168                 printf("no response\n");
169                 return 0;
170         }
171
172         printf ("Accel cal +1g: %s -1g: %s\n",
173                 accel[3], accel[5]);
174
175         printf ("Saving..."); fflush(stdout);
176         cc_usb_printf (usb, "c w\n");
177         cc_usb_sync(usb);
178         b = flash(usb);
179         printf ("done\n");
180
181         return worked;
182 }
183
184 int
185 main (int argc, char **argv)
186 {
187         char                    *device = NULL;
188         int                     c;
189         struct cc_usb           *cc = NULL;
190         char                    *tty = NULL;
191         int                     verbose = 0;
192         int                     ret = 0;
193
194         while ((c = getopt_long(argc, argv, "rT:D:c:s:v:", options, NULL)) != -1) {
195                 switch (c) {
196                 case 'T':
197                         tty = optarg;
198                         break;
199                 case 'D':
200                         device = optarg;
201                         break;
202                 case 'v':
203                         verbose++;
204                         break;
205                 default:
206                         usage(argv[0]);
207                         break;
208                 }
209         }
210
211         ao_verbose = verbose;
212
213         if (verbose > 1)
214                 ccdbg_add_debug(CC_DEBUG_BITBANG);
215
216         if (!tty)
217                 tty = cc_usbdevs_find_by_arg(device, "AltosFlash");
218         if (!tty)
219                 tty = cc_usbdevs_find_by_arg(device, "TeleMega");
220         if (!tty)
221                 tty = getenv("ALTOS_TTY");
222         if (!tty)
223                 tty="/dev/ttyACM0";
224
225         cc = cc_usb_open(tty);
226
227         if (!cc)
228                 exit(1);
229
230         if (!do_cal(cc))
231                 ret = 1;
232         done(cc, ret);
233 }