41d0ac102d27d86cb24e433bdde9b9441bb6f740
[fw/altos] / ao-tools / ao-dumplog / ao-dumplog.c
1 /*
2  * Copyright © 2009 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 <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <getopt.h>
23 #include <string.h>
24 #include "cc-usb.h"
25 #include "cc.h"
26
27 #define NUM_BLOCK       512
28
29 static const struct option options[] = {
30         { .name = "tty", .has_arg = 1, .val = 'T' },
31         { .name = "device", .has_arg = 1, .val = 'D' },
32         { .name = "remote", .has_arg = 0, .val = 'R' },
33         { .name = "channel", .has_arg = 1, .val = 'C' },
34         { 0, 0, 0, 0},
35 };
36
37 static void usage(char *program)
38 {
39         fprintf(stderr, "usage: %s [--tty <tty-name>] [--device <device-name>] [--remote] [--channel <radio-channel>]\n", program);
40         exit(1);
41 }
42
43 static uint8_t
44 log_checksum(int d[8])
45 {
46         uint8_t sum = 0x5a;
47         int     i;
48
49         for (i = 0; i < 8; i++)
50                 sum += (uint8_t) d[i];
51         return -sum;
52 }
53
54 static const char *state_names[] = {
55         "startup",
56         "idle",
57         "pad",
58         "boost",
59         "fast",
60         "coast",
61         "drogue",
62         "main",
63         "landed",
64         "invalid"
65 };
66
67
68 int
69 main (int argc, char **argv)
70 {
71         struct cc_usb   *cc;
72         char            *tty = NULL;
73         char            *device = NULL;
74         int             c;
75         char            line[8192];
76         FILE            *out;
77         char            *filename;
78         int             serial_number = 0;
79         int             channel = 0;
80         int             flight = 0;
81         char            cmd;
82         int             tick, a, b;
83         int             block;
84         int             addr;
85         int             received_addr;
86         int             data[8];
87         int             done;
88         int             column;
89         int             remote = 0;
90         int             any_valid;
91         int             invalid;
92         char            serial_line[8192];
93         unsigned        storage_size;
94         int             blocks;
95
96         while ((c = getopt_long(argc, argv, "T:D:C:R", options, NULL)) != -1) {
97                 switch (c) {
98                 case 'T':
99                         tty = optarg;
100                         break;
101                 case 'D':
102                         device = optarg;
103                         break;
104                 case 'R':
105                         remote = 1;
106                         break;
107                 case 'C':
108                         channel = atoi(optarg);
109                         break;
110                 default:
111                         usage(argv[0]);
112                         break;
113                 }
114         }
115         if (!tty) {
116                 if (remote)
117                         tty = cc_usbdevs_find_by_arg(device, "TeleDongle");
118                 else
119                         tty = cc_usbdevs_find_by_arg(device, "TeleMetrum");
120         }
121         if (!tty)
122                 tty = getenv("ALTOS_TTY");
123         if (!tty)
124                 tty="/dev/ttyACM0";
125         cc = cc_usb_open(tty);
126         if (!cc)
127                 exit(1);
128         if (remote)
129                 cc_usb_open_remote(cc, channel);
130         /* send a 'version' command followed by a 'log' command */
131         cc_usb_printf(cc, "v\n");
132         out = NULL;
133         for (;;) {
134                 cc_usb_getline(cc, line, sizeof (line));
135                 if (sscanf(line, "serial-number %u", &serial_number) == 1)
136                         strcpy(serial_line, line);
137                 if (!strncmp(line, "software-version", 16))
138                         break;
139         }
140         if (!serial_number) {
141                 fprintf(stderr, "no serial number found\n");
142                 cc_usb_close(cc);
143                 exit(1);
144         }
145         cc_usb_printf(cc, "f\n");
146         storage_size = 0;
147         for (;;) {
148                 cc_usb_getline(cc, line, sizeof(line));
149                 if (sscanf(line, "Storage size: %u", &storage_size) == 1)
150                         break;
151         }
152         printf ("Serial number: %d Storage size: %u\n", serial_number, storage_size);
153         if (storage_size)
154                 blocks = storage_size / 256;
155         else
156                 blocks = 511;
157         done = 0;
158         column = 0;
159         for (block = 0; !done && block < blocks; block++) {
160                 cc_usb_printf(cc, "e %x\n", block);
161                 if (column == 64) {
162                         putchar('\n');
163                         column = 0;
164                 }
165                 putchar('.'); fflush(stdout); column++;
166                 any_valid = 0;
167                 for (addr = 0; addr < 0x100;) {
168                         cc_usb_getline(cc, line, sizeof (line));
169                         if (sscanf(line, "00%x %x %x %x %x %x %x %x %x",
170                                           &received_addr,
171                                           &data[0], &data[1], &data[2], &data[3],
172                                           &data[4], &data[5], &data[6], &data[7]) == 9)
173                         {
174                                 if (received_addr != addr)
175                                         fprintf(stderr, "data out of sync at 0x%x\n",
176                                                 block * 256 + received_addr);
177
178                                 if (log_checksum(data) != 0)
179                                         fprintf (stderr, "invalid checksum at 0x%x\n",
180                                                  block * 256 + received_addr);
181                                 else
182                                         any_valid = 1;
183
184                                 cmd = data[0];
185                                 tick = data[2] + (data[3] << 8);
186                                 a = data[4] + (data[5] << 8);
187                                 b = data[6] + (data[7] << 8);
188                                 if (cmd == 'F') {
189                                         flight = b;
190                                         filename = cc_make_filename(serial_number, flight, "eeprom");
191                                         printf ("Flight:       %d\n", flight);
192                                         printf ("File name:     %s\n", filename);
193                                         out = fopen (filename, "w");
194                                         if (!out) {
195                                                 perror(filename);
196                                                 exit(1);
197                                         }
198                                         fprintf(out, "%s\n", serial_line);
199                                 }
200
201                                 if (cmd == 'S' && a <= 8) {
202                                         if (column) putchar('\n');
203                                         printf("%s\n", state_names[a]);
204                                         column = 0;
205                                 }
206                                 if (out) {
207                                         fprintf(out, "%c %4x %4x %4x\n",
208                                                 cmd, tick, a, b);
209                                         if (cmd == 'S' && a == 8) {
210                                                 fclose(out);
211                                                 out = NULL;
212                                                 done = 1;
213                                         }
214                                 }
215                                 addr += 8;
216                         }
217                 }
218                 if (!any_valid) {
219                         fclose(out);
220                         out = NULL;
221                         done = 1;
222                 }
223         }
224         if (column)
225                 putchar('\n');
226         if (out)
227                 fclose (out);
228         cc_usb_close(cc);
229         exit (0);
230 }