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