ao-tools: Fix warnings in ao-tools
[fw/altos] / ao-tools / ao-sky-flash / sky_flash.c
1 /*
2  * Copyright © 2012 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 "sky_flash.h"
20 #include <string.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stdint.h>
24 #include <stdarg.h>
25 #include <getopt.h>
26 #include <unistd.h>
27 #include "cc.h"
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 = "firmware", .has_arg = 1, .val = 'f' },
33         { .name = "query", .has_arg = 0, .val = 'q' },
34         { .name = "raw", .has_arg = 0, .val = 'r' },
35         { .name = "quiet", .has_arg = 0, .val = 'Q' },
36         { 0, 0, 0, 0},
37 };
38
39 static uint8_t  query_version[] = {
40         0xa0, 0xa1, 0x00, 0x02, 0x02, 0x01, 0x03, 0x0d, 0x0a
41 };
42
43 static void
44 usage(char *program)
45 {
46         fprintf(stderr,
47                 "usage: %s [--tty <tty-name>]\n"
48                 "          [--device <device-name>]\n"
49                 "          [--firmware <binary firmware file>]\n"
50                 "          [--query]\n"
51                 "          [--quiet]\n"
52                 "          [--raw]\n", program);
53         exit(1);
54 }
55
56 static int
57 skytraq_expect(int fd, uint8_t want, int timeout) {
58         int     c;
59
60         c = skytraq_waitchar(fd, timeout);
61         if (c < 0)
62                 return -1;
63         if (c == want)
64                 return 1;
65         return 0;
66 }
67
68 static int
69 skytraq_wait_reply(int fd, uint8_t reply, uint8_t *buf, uint8_t reply_len) {
70
71         for(;;) {
72                 uint8_t a, b;
73                 uint8_t cksum_computed;
74                 int     len;
75                 switch (skytraq_expect(fd, 0xa0, 10000)) {
76                 case -1:
77                         return -1;
78                 case 0:
79                         continue;
80                 case 1:
81                         break;
82                 }
83                 switch (skytraq_expect(fd, 0xa1, 1000)) {
84                 case -1:
85                         return -1;
86                 case 0:
87                         continue;
88                 }
89                 a = skytraq_waitchar(fd, 1000);
90                 b = skytraq_waitchar(fd, 1000);
91                 switch (skytraq_expect(fd, reply, 1000)) {
92                 case -1:
93                         return -1;
94                 case 0:
95                         continue;
96                 }
97                 len = (a << 16) | b;
98                 if (len != reply_len)
99                         continue;
100                 *buf++ = reply;
101                 len--;
102                 cksum_computed = reply;
103                 while (len--) {
104                         a = skytraq_waitchar(fd, 1000);
105                         if (a < 0)
106                                 return a;
107                         cksum_computed ^= a;
108                         *buf++ = a;
109                 }
110                 switch (skytraq_expect(fd, cksum_computed, 1000)) {
111                 case -1:
112                         return -1;
113                 case 0:
114                         continue;
115                 }
116                 switch (skytraq_expect(fd, 0x0d, 1000)) {
117                 case -1:
118                         return -1;
119                 case 0:
120                         continue;
121                 }
122                 switch (skytraq_expect(fd, 0x0a, 1000)) {
123                 case -1:
124                         return -1;
125                 case 0:
126                         continue;
127                 }
128                 break;
129         }
130         return 0;
131 }
132
133 int
134 main(int argc, char **argv)
135 {
136         int     fd;
137         int     ret;
138         int     c;
139         char    *tty = NULL;
140         char    *device = NULL;
141         char    *file = NULL;
142         int     query = 0;
143         int     raw = 0;
144
145         while ((c = getopt_long(argc, argv, "T:D:l:f:qQr", options, NULL)) != -1) {
146                 switch (c) {
147                 case 'T':
148                         tty = optarg;
149                         break;
150                 case 'D':
151                         device = optarg;
152                         break;
153                 case 'f':
154                         file = optarg;
155                         break;
156                 case 'q':
157                         query = 1;
158                         break;
159                 case 'Q':
160                         skytraq_verbose = 0;
161                         break;
162                 case 'r':
163                         raw = 1;
164                         break;
165                 default:
166                         usage(argv[0]);
167                         break;
168                 }
169         }
170
171         if (!tty)
172                 tty = cc_usbdevs_find_by_arg(device, "TeleMetrum");
173         if (!tty)
174                 tty = getenv("ALTOS_TTY");
175         if (!tty)
176                 tty="/dev/ttyACM0";
177         fd = skytraq_open(tty);
178         if (fd < 0)
179                 exit(1);
180
181         if (raw) {
182                 /* Set the baud rate to 115200 */
183                 skytraq_setcomm(fd, 115200);
184                 sleep(1);
185                 skytraq_setspeed(fd, 115200);
186         } else {
187                 /* Connect TM to the device */
188                 skytraq_write(fd, "U\n", 2);
189         }
190
191         /* Wait for the device to stabilize after baud rate changes */
192         for (c = 0; c < 6; c++) {
193                 skytraq_flush(fd);
194                 sleep(1);
195         }
196
197         if (query) {
198                 uint8_t query_reply[14];
199
200                 uint8_t         software_type;
201                 uint32_t        kernel_version;
202                 uint32_t        odm_version;
203                 uint32_t        revision;
204
205                 skytraq_write(fd, query_version, 9);
206                 if (skytraq_wait_reply(fd, 0x80, query_reply, sizeof (query_reply)) != 0) {
207                         fprintf(stderr, "query reply failed\n");
208                         exit(1);
209                 }
210
211 #define i8(o)   query_reply[(o)-1]
212 #define i32(o)  ((i8(o) << 24) | (i8(o+1) << 16) | (i8(o+2) << 8) | (i8(o+3)))
213                 software_type = i8(2);
214                 kernel_version = i32(3);
215                 odm_version = i32(7);
216                 revision = i32(11);
217                 skytraq_dbg_printf(0, "\n");
218                 printf ("Software Type %d. Kernel Version %d.%d.%d. ODM Version %d.%d.%d. Revision %d.%d.%d.\n",
219                         software_type,
220                         kernel_version >> 16 & 0xff,
221                         kernel_version >> 8 & 0xff,
222                         kernel_version >> 0 & 0xff,
223                         odm_version >> 16 & 0xff,
224                         odm_version >> 8 & 0xff,
225                         odm_version >> 0 & 0xff,
226                         revision >> 16 & 0xff,
227                         revision >> 8 & 0xff,
228                         revision >> 0 & 0xff);
229                 exit(0);
230         }
231
232         if (!file)
233                 usage(argv[0]);
234
235         ret = skytraq_send_srec(fd, "srec_115200.bin");
236         skytraq_dbg_printf (0, "srec ret %d\n", ret);
237         if (ret < 0)
238                 exit(1);
239
240         sleep(2);
241
242 //      ret = skytraq_send_bin(fd, "STI_01.04.42-01.10.23_4x_9600_Bin_20100901.bin");
243         ret = skytraq_send_bin(fd, "STI_01.06.10-01.07.23_balloon_CRC_7082_9600_20120913.bin");
244
245         printf ("bin ret %d\n", ret);
246         if (ret < 0)
247                 exit(1);
248
249         return 0;
250 }