Bump java lib versions in preparation for 1.9.2
[fw/altos] / altosdroid / app / src / main / java / org / altusmetrum / AltosDroid / AltosUsb.java
1 /*
2  * Copyright © 2015 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 package org.altusmetrum.AltosDroid;
20
21 import java.io.InputStream;
22 import java.io.OutputStream;
23 import java.util.HashMap;
24
25 import android.content.Context;
26 import android.hardware.usb.*;
27 import android.app.*;
28 import android.os.Handler;
29
30 import org.altusmetrum.altoslib_14.*;
31
32 public class AltosUsb extends AltosDroidLink {
33
34         private Thread           input_thread   = null;
35
36         private Handler          handler;
37
38         private UsbManager              manager;
39         private UsbDevice               device;
40         private UsbDeviceConnection     connection;
41         private UsbInterface            iface;
42         private UsbEndpoint             in, out;
43
44         private InputStream      input;
45         private OutputStream     output;
46
47         // Constructor
48         public AltosUsb(Context context, UsbDevice device, Handler handler) {
49                 super(handler);
50 //              set_debug(D);
51                 this.handler = handler;
52
53                 iface = null;
54                 in = null;
55                 out = null;
56
57                 int     niface = device.getInterfaceCount();
58
59                 for (int i = 0; i < niface; i++) {
60
61                         iface = device.getInterface(i);
62
63                         in = null;
64                         out = null;
65
66                         int nendpoints = iface.getEndpointCount();
67
68                         for (int e = 0; e < nendpoints; e++) {
69                                 UsbEndpoint     endpoint = iface.getEndpoint(e);
70
71                                 if (endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
72                                         switch (endpoint.getDirection()) {
73                                         case UsbConstants.USB_DIR_OUT:
74                                                 out = endpoint;
75                                                 break;
76                                         case UsbConstants.USB_DIR_IN:
77                                                 in = endpoint;
78                                                 break;
79                                         }
80                                 }
81                         }
82
83                         if (in != null && out != null)
84                                 break;
85                 }
86
87                 if (in != null && out != null) {
88                         AltosDebug.debug("\tin %s out %s\n", in.toString(), out.toString());
89
90                         manager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
91
92                         if (manager == null) {
93                                 AltosDebug.debug("USB_SERVICE failed");
94                                 return;
95                         }
96
97                         connection = manager.openDevice(device);
98
99                         if (connection == null) {
100                                 AltosDebug.debug("openDevice failed");
101                                 return;
102                         }
103
104                         connection.claimInterface(iface, true);
105
106                         input_thread = new Thread(this);
107                         input_thread.start();
108
109                         // Configure the newly connected device for telemetry
110                         print("~\nE 0\n");
111                         set_monitor(false);
112                 }
113         }
114
115         static private boolean isAltusMetrum(UsbDevice device) {
116                 if (device.getVendorId() != AltosLib.vendor_altusmetrum)
117                         return false;
118                 if (device.getProductId() < AltosLib.product_altusmetrum_min)
119                         return false;
120                 if (device.getProductId() > AltosLib.product_altusmetrum_max)
121                         return false;
122                 return true;
123         }
124
125         static boolean matchProduct(int want_product, UsbDevice device) {
126
127                 if (!isAltusMetrum(device))
128                         return false;
129
130                 if (want_product == AltosLib.product_any)
131                         return true;
132
133                 int have_product = device.getProductId();
134
135                 if (want_product == AltosLib.product_basestation)
136                         return have_product == AltosLib.product_teledongle ||
137                                 have_product == AltosLib.product_teleterra ||
138                                 have_product == AltosLib.product_telebt ||
139                                 have_product == AltosLib.product_megadongle;
140
141                 if (want_product == AltosLib.product_altimeter)
142                         return have_product == AltosLib.product_telemetrum ||
143                                 have_product == AltosLib.product_telemega ||
144                                 have_product == AltosLib.product_easymega ||
145                                 have_product == AltosLib.product_telegps ||
146                                 have_product == AltosLib.product_easymini ||
147                                 have_product == AltosLib.product_telemini;
148
149                 if (have_product == AltosLib.product_altusmetrum)       /* old devices match any request */
150                         return true;
151
152                 if (want_product == have_product)
153                         return true;
154
155                 return false;
156         }
157
158         static public boolean request_permission(Context context, UsbDevice device, PendingIntent pi) {
159                 UsbManager      manager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
160
161 //              if (manager.hasPermission(device))
162 //                      return true;
163
164                 AltosDebug.debug("request permission for USB device " + device.toString());
165
166                 manager.requestPermission(device, pi);
167                 return false;
168         }
169
170         static public UsbDevice find_device(Context context, int match_product) {
171                 UsbManager      manager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
172
173                 HashMap<String,UsbDevice>       devices = manager.getDeviceList();
174
175                 for (UsbDevice  device : devices.values()) {
176                         int     vendor = device.getVendorId();
177                         int     product = device.getProductId();
178
179                         if (matchProduct(match_product, device)) {
180                                 AltosDebug.debug("found USB device " + device.toString());
181                                 return device;
182                         }
183                 }
184
185                 return null;
186         }
187
188         private void disconnected() {
189                 if (closed()) {
190                         AltosDebug.debug("disconnected after closed");
191                         return;
192                 }
193
194                 AltosDebug.debug("Sending disconnected message");
195                 handler.obtainMessage(TelemetryService.MSG_DISCONNECTED, this).sendToTarget();
196         }
197
198         void close_device() {
199                 UsbDeviceConnection     tmp_connection;
200
201                 synchronized(this) {
202                         tmp_connection = connection;
203                         connection = null;
204                 }
205
206                 if (tmp_connection != null) {
207                         AltosDebug.debug("Closing USB device");
208                         tmp_connection.close();
209                 }
210         }
211
212         int read(byte[] buffer, int len) {
213                 int ret = connection.bulkTransfer(in, buffer, len, -1);
214                 AltosDebug.debug("read(%d) = %d\n", len, ret);
215                 return ret;
216         }
217
218         int write(byte[] buffer, int len) {
219                 int ret = connection.bulkTransfer(out, buffer, len, -1);
220                 AltosDebug.debug("write(%d) = %d\n", len, ret);
221                 return ret;
222         }
223
224         // Stubs of required methods when extending AltosLink
225         public boolean can_cancel_reply()   { return false; }
226         public boolean show_reply_timeout() { return true; }
227         public void hide_reply_timeout()    { }
228
229 }