]> git.gag.com Git - fw/altos/blob - ao-tools/ao-dumpflash/ao-dumpflash.c
altos: Protect shared storage_data with mutex
[fw/altos] / ao-tools / ao-dumpflash / ao-dumpflash.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 = "frequency", .has_arg = 1, .val = 'F' },
34         { .name = "call", .has_arg = 1, .val = 'C' },
35         { .name = "output", .has_arg = 1, .val = 'o' },
36         { 0, 0, 0, 0},
37 };
38
39 static void usage(char *program)
40 {
41         fprintf(stderr, "usage: %s [--tty <tty-name>] [--device <device-name>] [--remote] [--frequency <radio-frequency>] [--call <radio-callsign>]\n", program);
42         exit(1);
43 }
44
45 int
46 main (int argc, char **argv)
47 {
48         struct cc_usb   *cc;
49         char            *tty = NULL;
50         char            *device = NULL;
51         int             c;
52         char            line[8192];
53         FILE            *out;
54         int             serial_number = 0;
55         int             freq = 434550;
56         char            *call = "N0CALL";
57         int             block;
58         int             addr;
59         int             received_addr;
60         int             data[8];
61         int             i;
62         int             remote = 0;
63         int             storage_size = 0;
64         char            *out_name = NULL;
65
66         while ((c = getopt_long(argc, argv, "T:D:F:C:o:R", options, NULL)) != -1) {
67                 switch (c) {
68                 case 'T':
69                         tty = optarg;
70                         break;
71                 case 'D':
72                         device = optarg;
73                         break;
74                 case 'R':
75                         remote = 1;
76                         break;
77                 case 'F':
78                         freq = atoi(optarg);
79                         break;
80                 case 'C':
81                         call = optarg;
82                         break;
83                 case 'o':
84                         out_name = optarg;
85                         break;
86                 default:
87                         usage(argv[0]);
88                         break;
89                 }
90         }
91         if (!tty) {
92                 if (remote)
93                         tty = cc_usbdevs_find_by_arg(device, "TeleDongle");
94                 else
95                         tty = cc_usbdevs_find_by_arg(device, "TeleMetrum");
96         }
97         if (!tty)
98                 tty = getenv("ALTOS_TTY");
99         if (!tty)
100                 tty="/dev/ttyACM0";
101
102         cc = cc_usb_open(tty);
103         if (!cc)
104                 exit(1);
105         if (remote)
106                 cc_usb_open_remote(cc, freq, call);
107
108         if (out_name) {
109                 out = fopen(out_name, "w");
110                 if (!out) {
111                         perror(out_name);
112                         cc_usb_close(cc);
113                         exit(1);
114                 }
115         } else
116                 out = stdout;
117
118         /* send a 'version' command followed by a 'flash' command */
119         cc_usb_printf(cc, "f\nv\n");
120         for (;;) {
121                 cc_usb_getline(cc, line, sizeof (line));
122                 if (sscanf(line, "serial-number %u", &serial_number) == 1)
123                         continue;
124                 if (sscanf(line, "Storage size: %u", &storage_size) == 1)
125                         continue;
126                 if (!strncmp(line, "software-version", 16))
127                         break;
128         }
129         if (!serial_number) {
130                 fprintf(stderr, "no serial number found\n");
131                 cc_usb_close(cc);
132                 exit(1);
133         }
134         if (!storage_size) {
135                 fprintf(stderr, "no storage size found\n");
136                 cc_usb_close(cc);
137                 exit(1);
138         }
139         printf ("Serial number: %d\n", serial_number);
140         printf ("Storage size:  %d\n", storage_size);
141         fprintf (stderr, "%7d of %7d", 0, storage_size/256);
142         for (block = 0; block < storage_size / 256; block++) {
143                 cc_usb_printf(cc, "e %x\n", block);
144                 fprintf (stderr, "\r%7d of %7d", block + 1, storage_size/256); fflush(stderr);
145                 for (addr = 0; addr < 0x100;) {
146                         cc_usb_getline(cc, line, sizeof (line));
147                         if (sscanf(line, "00%x %x %x %x %x %x %x %x %x",
148                                           &received_addr,
149                                           &data[0], &data[1], &data[2], &data[3],
150                                           &data[4], &data[5], &data[6], &data[7]) == 9)
151                         {
152                                 if (received_addr != addr)
153                                         fprintf(stderr, "data out of sync at 0x%x\n",
154                                                 block * 256 + received_addr);
155
156                                 fprintf (out, "%08x", block * 256 + addr);
157                                 for (i = 0; i < 8; i++)
158                                         fprintf (out, " %02x", data[i]);
159                                 fprintf (out, "\n");
160
161                                 addr += 8;
162                         }
163                 }
164         }
165         fprintf(stderr, "\n");
166         cc_usb_close(cc);
167         exit (0);
168 }