altosdroid: Use single object to pass data to UI
[fw/altos] / altoslib / AltosSelfFlash.java
1 /*
2  * Copyright © 2013 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 package org.altusmetrum.altoslib_5;
19
20 import java.io.*;
21
22 public class AltosSelfFlash extends AltosProgrammer {
23         File                    file;
24         FileInputStream         input;
25         AltosHexfile            image;
26         AltosLink               link;
27         boolean                 aborted;
28         AltosFlashListener      listener;
29         AltosRomconfig          rom_config;
30
31         void action(String s, int percent) {
32                 if (listener != null && !aborted)
33                         listener.position(s, percent);
34         }
35
36         void action(int part, int total) {
37                 int percent = 100 * part / total;
38                 action(String.format("%d/%d (%d%%)",
39                                      part, total, percent),
40                        percent);
41         }
42
43         byte[] read_memory(long addr, int len) throws InterruptedException, IOException {
44                 int b;
45                 byte[]  data = new byte[len];
46
47                 for (int offset = 0; offset < len; offset += 0x100) {
48                         link.printf("R %x\n", addr + offset);
49                         byte[]  reply = link.get_binary_reply(5000, 0x100);
50
51                         if (reply == null)
52                                 throw new IOException("Read device memory timeout");
53                         for (b = 0; b < len; b++)
54                                 data[b+offset] = reply[b];
55                 }
56                 return data;
57         }
58
59         void write_memory(long addr, byte[] data, int start, int len) {
60                 int b;
61                 link.printf("W %x\n", addr);
62                 link.flush_output();
63                 for (b = 0; b < len; b++)
64                         link.putchar(data[start + b]);
65                 for (; b < 0x100; b++)
66                         link.putchar((byte) 0xff);
67         }
68
69         void reboot() {
70                 link.printf("a\n");
71                 link.flush_output();
72         }
73
74         public void flash() {
75                 try {
76                         if (!check_rom_config())
77                                 throw new IOException("Invalid rom config settings");
78
79                         /*
80                          * Store desired config values into image
81                          */
82                         rom_config.write(image);
83
84                         int remain = image.data.length;
85                         long flash_addr = image.address;
86                         int image_start = 0;
87
88                         action("start", 0);
89                         action(0, image.data.length);
90                         while (remain > 0 && !aborted) {
91                                 int this_time = remain;
92                                 if (this_time > 0x100)
93                                         this_time = 0x100;
94
95                                 if (link != null) {
96                                         /* write the data */
97                                         write_memory(flash_addr, image.data, image_start, this_time);
98
99                                         byte[] check = read_memory(flash_addr, this_time);
100                                         for (int i = 0; i < this_time; i++)
101                                                 if (check[i] != image.data[image_start + i])
102                                                         throw new IOException(String.format("Flash write failed at 0x%x (%02x != %02x)",
103                                                                                             image.address + image_start + i,
104                                                                                             check[i], image.data[image_start + i]));
105                                 } else {
106                                         Thread.sleep(100);
107                                 }
108
109                                 remain -= this_time;
110                                 flash_addr += this_time;
111                                 image_start += this_time;
112
113                                 action(image.data.length - remain, image.data.length);
114                         }
115                         if (!aborted) {
116                                 action("done", 100);
117                         }
118                         close();
119                 } catch (IOException ie) {
120                         action(ie.getMessage(), -1);
121                         abort();
122                 } catch (InterruptedException ie) {
123                         abort();
124                 }
125         }
126
127         public void close() {
128                 if (link != null) {
129                         reboot();
130                         try {
131                                 link.close();
132                         } catch (InterruptedException ie) {
133                         }
134                         link = null;
135                 }
136         }
137
138         synchronized public void abort() {
139                 aborted = true;
140                 close();
141         }
142
143         private AltosHexfile get_rom() throws InterruptedException {
144                 try {
145                         int base = AltosRomconfig.fetch_base(image);
146                         int bounds = AltosRomconfig.fetch_bounds(image);
147                         byte[] data = read_memory(base, bounds - base);
148                         AltosHexfile hexfile = new AltosHexfile(data, base);
149                         hexfile.add_symbols(image);
150                         return hexfile;
151                 } catch (AltosNoSymbol none) {
152                         return null;
153                 } catch (IOException ie) {
154                         return null;
155                 }
156
157         }
158
159         public boolean check_rom_config() throws InterruptedException {
160                 if (link == null) {
161                         return true;
162                 }
163                 if (rom_config == null) {
164                         AltosHexfile hexfile = get_rom();
165                         if (hexfile != null)
166                                 rom_config = new AltosRomconfig(hexfile);
167                 }
168                 return rom_config != null && rom_config.valid();
169         }
170
171         public void set_romconfig (AltosRomconfig romconfig) {
172                 rom_config = romconfig;
173         }
174
175         public AltosRomconfig romconfig() throws InterruptedException {
176                 if (!check_rom_config())
177                         return null;
178                 return rom_config;
179         }
180
181         public AltosSelfFlash(File file, AltosLink link, AltosFlashListener listener)
182                 throws IOException, FileNotFoundException, InterruptedException {
183                 this.file = file;
184                 this.link = link;
185                 this.listener = listener;
186                 input = new FileInputStream(file);
187                 image = new AltosHexfile(input);
188         }
189 }