4 XCSoar Glide Computer - http://www.xcsoar.org/
5 Copyright (C) 2000-2013 The XCSoar Project
6 A detailed list of copyright holders can be found in the file "AUTHORS".
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 import java
.util
.Collection
;
27 import java
.util
.LinkedList
;
28 import java
.util
.Iterator
;
29 import android
.util
.Log
;
30 import ioio
.lib
.api
.IOIO
;
31 import ioio
.lib
.api
.IOIOFactory
;
32 import ioio
.lib
.api
.exception
.ConnectionLostException
;
33 import ioio
.lib
.api
.exception
.IncompatibilityException
;
36 * A utility class which wraps the Java API into an easier API for the
39 final class IOIOHelper
extends Thread
implements IOIOConnectionHolder
{
40 private static final String TAG
= "XCSoar";
42 private boolean shutdownFlag
;
47 * The IOIO connection that is currently being established. It may
48 * be used by the client thread to cancel the connection.
50 private IOIO connecting
;
53 * The list of listeners that believe there is no IOIO connection.
55 private Collection
<IOIOConnectionListener
> closedListeners
=
56 new LinkedList
<IOIOConnectionListener
>();
59 * The list of listeners that believe a IOIO connection is
62 private Collection
<IOIOConnectionListener
> openListeners
=
63 new LinkedList
<IOIOConnectionListener
>();
71 private synchronized boolean isOpen() {
76 * Is the IOIO connection currently in use? If not, it may be
79 private synchronized boolean isInUse() {
80 return !openListeners
.isEmpty() || !closedListeners
.isEmpty();
83 public void shutdown() {
87 IOIO ioio
= connecting
;
96 } catch (InterruptedException e
) {
100 private static void openListener(IOIOConnectionListener listener
, IOIO ioio
)
101 throws ConnectionLostException
{
102 /* clear this thread's "interrupted" flag, to avoid interrupting
108 listener
.onIOIOConnect(ioio
);
109 } catch (InterruptedException e
) {
110 /* got an interrupt from another thread; try again */
111 listener
.onIOIOConnect(ioio
);
113 } catch (InterruptedException e
) {
114 Log
.e(TAG
, "Failed to open IOIO device " + listener
, e
);
115 } catch (RuntimeException e
) {
116 Log
.e(TAG
, "Failed to open IOIO device " + listener
, e
);
120 private synchronized void openAllListeners(IOIO ioio
)
121 throws ConnectionLostException
{
122 for (Iterator
<IOIOConnectionListener
> i
= closedListeners
.iterator(); i
.hasNext();) {
123 IOIOConnectionListener listener
= i
.next();
125 openListener(listener
, ioio
);
128 openListeners
.add(listener
);
132 private synchronized void closeAllListeners() {
133 for (Iterator
<IOIOConnectionListener
> i
= openListeners
.iterator(); i
.hasNext();) {
134 IOIOConnectionListener listener
= i
.next();
135 listener
.onIOIODisconnect();
138 closedListeners
.add(listener
);
143 * Called by the connection thread to open a connection.
145 private void synchronousOpen() {
146 Log
.d(TAG
, "open IOIO");
151 if (shutdownFlag
|| interrupted())
154 connecting
= ioio
= IOIOFactory
.create();
158 ioio
.waitForConnect();
159 if (ioio
.getState() == IOIO
.State
.CONNECTED
) {
160 Log
.d(TAG
, "IOIO connection established");
162 Log
.i(TAG
, "IOIO hardware version " +
163 ioio
.getImplVersion(IOIO
.VersionType
.HARDWARE_VER
));
164 Log
.i(TAG
, "IOIO bootloader version " +
165 ioio
.getImplVersion(IOIO
.VersionType
.BOOTLOADER_VER
));
166 Log
.i(TAG
, "IOIO firmware version " +
167 ioio
.getImplVersion(IOIO
.VersionType
.APP_FIRMWARE_VER
));
168 Log
.i(TAG
, "IOIOLib version " +
169 ioio
.getImplVersion(IOIO
.VersionType
.IOIOLIB_VER
));
174 openAllListeners(ioio
);
178 Log
.w(TAG
, "IOIO connection failed");
181 } catch (ConnectionLostException e
) {
182 Log
.w(TAG
, "IOIO connection lost");
184 } catch (IncompatibilityException e
) {
185 Log
.e(TAG
, "IOIO incompatible", e
);
194 private synchronized IOIO
steal() {
195 IOIO ioio
= this.ioio_
;
201 * Called by the connection thread to close the connection.
203 private void synchronousClose() {
212 private synchronized boolean handleNewListeners() {
213 if (ioio_
== null || closedListeners
.isEmpty())
216 /* another thread has registered new listeners; notify them
217 that a IOIO connection exists */
220 openAllListeners(ioio_
);
221 } catch (ConnectionLostException e
) {
222 Log
.w(TAG
, "IOIO connection lost");
228 private void idle() {
234 /* there is a connection: wait for connection error or
235 until Thread.interrupt() gets called */
236 ioio_
.waitForDisconnect();
237 Log
.w(TAG
, "IOIO connection lost");
239 /* there is no connection: wait until Thread.interrupt()
242 /* we're not actually waiting for an Object.notify() call,
243 this is just a dummy call to make this thread idle and
248 } catch (InterruptedException e
) {
253 * The connection thread.
257 if (ioio_
!= null && (ioio_
.getState() != IOIO
.State
.CONNECTED
||
260 else if (ioio_
== null && isInUse() && !shutdownFlag
)
268 if (handleNewListeners())
275 @Override public synchronized void addListener(IOIOConnectionListener l
) {
276 closedListeners
.add(l
);
278 /* ask the thread to initiate a connection or to invoke
279 onIOIOConnect() if the connection is already established */
280 if (connecting
== null)
284 @Override public synchronized void removeListener(IOIOConnectionListener l
) {
285 if (openListeners
.remove(l
))
286 /* this listener thinks the IOIO connection is established;
287 invoke the onIOIODisconnect() method */
288 l
.onIOIODisconnect();
290 /* no method call necessary */
291 closedListeners
.remove(l
);
295 /* ask the thread to auto-close the connection */
298 if (connecting
!= null)
299 /* cancel the current connect attempt after the last listener
301 connecting
.disconnect();
306 public synchronized void cycleListener(IOIOConnectionListener l
) {
310 if (openListeners
.remove(l
)) {
311 l
.onIOIODisconnect();
312 closedListeners
.add(l
);
313 } else if (!closedListeners
.contains(l
))
316 /* ask the thread to reopen the listener */
321 * @ID: ID of UArt to open (0, 1, 2, 3)
322 * @return: ID of opened UArt or -1 if fail
324 public AndroidPort
openUart(int ID
, int baud
) {
325 return new GlueIOIOPort(this, ID
, baud
);