More ALtosUI changes
[fw/altos] / ao-tools / altosui / AltosSerial.java
1 /*
2  * Copyright © 2010 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 /*
19  * Deal with TeleDongle on a serial port
20  */
21
22 package altosui;
23
24 import java.lang.*;
25 import java.io.*;
26 import java.util.concurrent.LinkedBlockingQueue;
27 import java.util.LinkedList;
28 import java.util.Iterator;
29 import gnu.io.*;
30 import altosui.AltosSerialMonitor;
31
32 /*
33  * This class reads from the serial port and places each received
34  * line in a queue. Dealing with that queue is left up to other
35  * threads.
36  */
37 class AltosSerialReader implements Runnable {
38         InputStream     serial_in;
39         LinkedList<LinkedBlockingQueue<String>> monitors;
40         LinkedBlockingQueue<String> reply_queue;
41         Thread input_thread;
42         String line;
43
44         public void run () {
45                 int c;
46
47                 try {
48                         for (;;) {
49                                 c = serial_in.read();
50                                 if (Thread.interrupted())
51                                         break;
52                                 if (c == -1)
53                                         continue;
54                                 if (c == '\r')
55                                         continue;
56                                 synchronized(this) {
57                                         if (c == '\n') {
58                                                 if (line != "") {
59                                                         if (line.startsWith("VERSION")) {
60                                                                 for (int e = 0; e < monitors.size(); e++) {
61                                                                         LinkedBlockingQueue<String> q = monitors.get(e);
62                                                                         q.put(line);
63                                                                 }
64                                                         } else
65                                                                 reply_queue.put(line);
66                                                         line = "";
67                                                 }
68                                         } else {
69                                                 line = line + (char) c;
70                                         }
71                                 }
72                         }
73                 } catch (IOException e) {
74                 } catch (InterruptedException e) {
75                 }
76         }
77
78         public String get_reply() throws InterruptedException {
79                 return reply_queue.take();
80         }
81
82         public void add_monitor(LinkedBlockingQueue<String> q) {
83                 monitors.add(q);
84         }
85
86         public void remove_monitor(LinkedBlockingQueue<String> q) {
87                 monitors.remove(q);
88         }
89
90         public void flush () {
91                 synchronized(this) {
92                         if (!"VERSION".startsWith(line) && !line.startsWith("VERSION"))
93                                 line = "";
94                         reply_queue.clear();
95                 }
96         }
97
98         public boolean opened() {
99                 return serial_in != null;
100         }
101
102         public void close() {
103                 if (serial_in != null) {
104                         try {
105                                 serial_in.close();
106                         } catch (IOException e) {
107                         }
108                         serial_in = null;
109                 }
110                 if (input_thread != null) {
111                         try {
112                                 input_thread.interrupt();
113                                 input_thread.join();
114                         } catch (InterruptedException e) {
115                         }
116                         input_thread = null;
117                 }
118         }
119
120         public void open(File name) throws FileNotFoundException {
121                 close();
122                 serial_in = new FileInputStream(name);
123                 input_thread = new Thread(this);
124                 input_thread.start();
125         }
126         public void open(CommPort c) throws IOException {
127                 close();
128                 try {
129                 c.enableReceiveTimeout(1000);   /* icky. the read method cannot be interrupted */
130                 } catch (UnsupportedCommOperationException ee) {
131                 }
132                 serial_in = c.getInputStream();
133                 input_thread = new Thread(this);
134                 input_thread.start();
135         }
136         public AltosSerialReader () {
137                 serial_in = null;
138                 input_thread = null;
139                 line = "";
140                 monitors = new LinkedList<LinkedBlockingQueue<String>> ();
141                 reply_queue = new LinkedBlockingQueue<String> ();
142         }
143
144 }
145
146 public class AltosSerial {
147         OutputStream serial_out = null;
148         AltosSerialReader reader = null;
149
150         CommPort comm_port = null;
151
152         public void close() {
153                 try {
154                         serial_out.close();
155                 } catch (IOException ee) {
156                 }
157                 reader.close();
158                 if (comm_port != null) {
159                         comm_port.close();
160                 }
161         }
162
163         public void open(File serial_name) throws FileNotFoundException {
164                 reader.open(serial_name);
165                 serial_out = new FileOutputStream(serial_name);
166         }
167
168         public void open(CommPort c) throws IOException {
169                 reader.open(c);
170                 serial_out = c.getOutputStream();
171         }
172
173         public void connect(String port_name) throws IOException, NoSuchPortException, PortInUseException {
174                 comm_port = new RXTXPort(port_name);
175                 open(comm_port);
176         }
177
178         void init() {
179                 reader = new AltosSerialReader();
180         }
181
182         public void add_monitor(LinkedBlockingQueue<String> q) {
183                 reader.add_monitor(q);
184         }
185
186         public void remove_monitor(LinkedBlockingQueue<String> q) {
187                 reader.remove_monitor(q);
188         }
189
190         public AltosSerial() {
191                 init();
192         }
193
194         public AltosSerial(File serial_name) throws FileNotFoundException {
195                 init();
196                 open(serial_name);
197         }
198
199         public AltosSerial(CommPort comm_port) throws IOException {
200                 init();
201                 open(comm_port);
202         }
203 }