ao-tools: Add ao-sky-flash to update GPS firmware
[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; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 #include "sky_flash.h"
19 #include <string.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <stdint.h>
23 #include <stdarg.h>
24 #include <getopt.h>
25 #include "cc.h"
26
27 static const struct option options[] = {
28         { .name = "tty", .has_arg = 1, .val = 'T' },
29         { .name = "device", .has_arg = 1, .val = 'D' },
30         { .name = "loader", .has_arg = 1, .val = 'l' },
31         { .name = "firmware", .has_arg = 1, .val = 'f' },
32         { .name = "query", .has_arg = 0, .val = 'q' },
33         { .name = "raw", .has_arg = 0, .val = 'r' },
34         { .name = "quiet", .has_arg = 0, .val = 'Q' },
35         { 0, 0, 0, 0},
36 };
37
38 static uint8_t  query_version[] = {
39         0xa0, 0xa1, 0x00, 0x02, 0x02, 0x01, 0x03, 0x0d, 0x0a
40 };
41
42 static void
43 usage(char *program)
44 {
45         fprintf(stderr,
46                 "usage: %s [--tty <tty-name>]\n"
47                 "          [--device <device-name>]\n"
48                 "          [--loader <srec bootloader file>]\n"
49                 "          [--firmware <binary firmware file>]\n"
50                 "          [--query]\n"
51                 "          [--quiet]\n"
52                 "          [--raw]\n", program);
53         exit(1);
54 }
55
56 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 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, cksum_read;
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         char    buf[512];
138         int     ret;
139         FILE    *input;
140         long    size;
141         unsigned char   cksum;
142         int     c;
143         char    message[1024];
144         char    *tty = NULL;
145         char    *device = NULL;
146         char    *loader = "srec_115200.bin";
147         char    *file = NULL;
148         int     query = 0;
149         int     raw = 0;
150
151         while ((c = getopt_long(argc, argv, "T:D:l:f:qQr", options, NULL)) != -1) {
152                 switch (c) {
153                 case 'T':
154                         tty = optarg;
155                         break;
156                 case 'D':
157                         device = optarg;
158                         break;
159                 case 'l':
160                         loader = optarg;
161                         break;
162                 case 'f':
163                         file = optarg;
164                         break;
165                 case 'q':
166                         query = 1;
167                         break;
168                 case 'Q':
169                         skytraq_verbose = 0;
170                         break;
171                 case 'r':
172                         raw = 1;
173                         break;
174                 default:
175                         usage(argv[0]);
176                         break;
177                 }
178         }
179
180         if (!tty)
181                 tty = cc_usbdevs_find_by_arg(device, "TeleMetrum");
182         if (!tty)
183                 tty = getenv("ALTOS_TTY");
184         if (!tty)
185                 tty="/dev/ttyACM0";
186         fd = skytraq_open(tty);
187         if (fd < 0)
188                 exit(1);
189
190         if (raw) {
191                 /* Set the baud rate to 115200 */
192                 skytraq_setcomm(fd, 115200);
193                 sleep(1);
194                 skytraq_setspeed(fd, 115200);
195         } else {
196                 /* Connect TM to the device */
197                 skytraq_write(fd, "U\n", 2);
198         }
199
200         /* Wait for the device to stabilize after baud rate changes */
201         for (c = 0; c < 6; c++) {
202                 skytraq_flush(fd);
203                 sleep(1);
204         }
205
206         if (query) {
207                 uint8_t query_reply[14];
208
209                 uint8_t         software_type;
210                 uint32_t        kernel_version;
211                 uint32_t        odm_version;
212                 uint32_t        revision;
213
214                 skytraq_write(fd, query_version, 9);
215                 if (skytraq_wait_reply(fd, 0x80, query_reply, sizeof (query_reply)) != 0) {
216                         fprintf(stderr, "query reply failed\n");
217                         exit(1);
218                 }
219
220 #define i8(o)   query_reply[(o)-1]
221 #define i32(o)  ((i8(o) << 24) | (i8(o+1) << 16) | (i8(o+2) << 8) | (i8(o+3)))
222                 software_type = i8(2);
223                 kernel_version = i32(3);
224                 odm_version = i32(7);
225                 revision = i32(11);
226                 skytraq_dbg_printf(0, "\n");
227                 printf ("Software Type %d. Kernel Version %d.%d.%d. ODM Version %d.%d.%d. Revision %d.%d.%d.\n",
228                         software_type,
229                         kernel_version >> 16 & 0xff,
230                         kernel_version >> 8 & 0xff,
231                         kernel_version >> 0 & 0xff,
232                         odm_version >> 16 & 0xff,
233                         odm_version >> 8 & 0xff,
234                         odm_version >> 0 & 0xff,
235                         revision >> 16 & 0xff,
236                         revision >> 8 & 0xff,
237                         revision >> 0 & 0xff);
238                 exit(0);
239         }
240
241         if (!file)
242                 usage(argv[0]);
243
244         ret = skytraq_send_srec(fd, "srec_115200.bin");
245         skytraq_dbg_printf (0, "srec ret %d\n", ret);
246         if (ret < 0)
247                 exit(1);
248
249         sleep(2);
250
251 //      ret = skytraq_send_bin(fd, "STI_01.04.42-01.10.23_4x_9600_Bin_20100901.bin");
252         ret = skytraq_send_bin(fd, "STI_01.06.10-01.07.23_balloon_CRC_7082_9600_20120913.bin");
253
254         printf ("bin ret %d\n", ret);
255         if (ret < 0)
256                 exit(1);
257
258         return 0;
259 }