USBUART
A library for reading/wring data via USB-UART adapters
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules
UsbUartContext.java
Go to the documentation of this file.
1 
7 /* This file is part of USBUART Library. http://usbuart.info/
8  *
9  * Copyright (C) 2016 Eugene Hutorny <eugene@hutorny.in.ua>
10  *
11  * The USBUART Library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public License v2
13  * as published by the Free Software Foundation;
14  *
15  * The USBUART Library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18  * See the GNU Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with the USBUART Library; if not, see
22  * <http://www.gnu.org/licenses/gpl-2.0.html>.
23  */
24 
25 package info.usbuart.api;
26 
27 import android.annotation.TargetApi;
28 import android.hardware.usb.UsbDeviceConnection;
29 import android.os.Build;
30 import android.util.Log;
31 
32 import java.io.*;
33 import java.lang.reflect.Method;
34 
35 @TargetApi(Build.VERSION_CODES.LOLLIPOP)
36 public class UsbUartContext implements Runnable {
37  private static final String TAG = "USBUART";
38  public static final int DEFAULT_LOOP_TIMEOUT = 500; // ms
39 
40  enum error_t {
41  success,
42  no_channels,
45  no_channel,
46  no_access,
48  no_device,
49  no_interface,
51  libusb_error,
52  usb_error,
53  device_error,
54  bad_baudrate,
57  io_error,
58  fcntl_error,
59  poll_error,
60  pipe_error,
63  ;
64  public static error_t cast(int val) {
65  if(val < 0) val = -val;
66  return val > unknown_error.ordinal() ? unknown_error : values()[val];
67  }
68  }
69 
70  public UsbUartContext() {
71  context = create();
72  }
79  public Channel attach(UsbDeviceConnection dev, int ifcnum, FileDescriptor read, FileDescriptor write,
80  final EIA_TIA_232_Info pi) throws Error {
81  ChannelPriv ch = new ChannelPriv(fd(read), fd(write));
82  check(attach(context, dev.getFileDescriptor(), ifcnum, ch, pi));
83  return new ChannelImpl(dev, ch);
84  }
90  public Channel pipe(UsbDeviceConnection dev, int ifcnum, final EIA_TIA_232_Info pi) throws Error {
91  ChannelPriv ch = new ChannelPriv(-1,-1);
92  Log.d("pipe", "fd=" + dev.getFileDescriptor());
93  check(pipe(context, dev.getFileDescriptor(), ifcnum, ch, pi));
94  return new ChannelImpl(dev, ch);
95  }
96  public void hotplug(UsbDeviceConnection dev) {
97  hotplug(context, dev.getFileDescriptor());
98  }
99 
100  private void check(int err) throws Error {
101  if( err != 0 ) throw new Error(err);
102  }
103 
105  public void close(Channel ch) {
106  Log.d(TAG, "closing " + ch);
107  close(context, (ChannelImpl)ch);
108  }
109 
111  private void reset(Channel ch) throws Error {
112  check(reset(context, (ChannelImpl)ch));
113  }
114 
116  public int status(Channel ch) {
117  return ch == null || ! (ch instanceof ChannelImpl) ? 0 : status(context, (ChannelImpl)ch);
118  }
119 
121  private void sendbreak(Channel ch) throws Error {
122  check(sendbreak(context, (ChannelImpl)ch));
123  }
124 
128  public int loop(int timeout) {
129  return loop(context, timeout);
130  }
131 
132  @Override
133  public void run() {
134  int res = 0;
135  while(! Thread.currentThread().isInterrupted() && (res=loop(timeout)) >= no_channels );
136  Log.d(TAG, "loop quit res=" + res);
137  }
138 
139  public static class Error extends Channel.Error {
140  Error(int code) {
141  super(getMessageByCode(code));
142  this.code = code;
143  }
144  final int code;
145  }
146  private static final int no_channels = - error_t.no_channels.ordinal();
147  private static Method getInt;
148  private static Method setInt;
149  private static int fd(FileDescriptor f) {
150  try {
151  if( getInt == null ) getInt = FileDescriptor.class.getDeclaredMethod("getInt$");
152  if( getInt != null ) return (Integer) getInt.invoke(f);
153  } catch (Throwable e) {
154  Log.e(TAG, e.getMessage());
155  }
156  return -1;
157  }
158  private static FileDescriptor fd(int f) throws Channel.Error {
159  if( f < 0 ) throw new Channel.Error("Bad file descriptor");
160  FileDescriptor r = new FileDescriptor();
161  try {
162  if (setInt == null) setInt = FileDescriptor.class.getDeclaredMethod("setInt$", int.class);
163  if (setInt != null) setInt.invoke(r, f);
164  return r;
165  } catch (Throwable e) {
166  Log.e(TAG, e.getMessage());
167  }
168  throw new Channel.Error("File descriptor not available");
169  }
170 
171  private static String getMessageByCode(int code) {
172  switch( error_t.cast(code) ) {
173  case success:
174  return "success";
175  case no_channels: return "context has nor more live channels";
176  case not_implemented:return"method not implemented in this lib";
177  case invalid_param: return "invalid param passed to the API";
178  case no_channel: return "requested channel does not exist";
179  case no_access: return "access permission denied";
180  case not_supported: return "device is not supported";
181  case no_device: return "device does not exist";
182  case no_interface: return "claim interface failed";
183  case interface_busy:return "requested interface busy";
184  case libusb_error: return "libusb error";
185  case usb_error: return "USB level error";
186  case device_error: return "hardware level error";
187  case bad_baudrate: return "unsupported baud rate";
188  case probe_mismatch:return "device returned unexpected value while probing";
189  case control_error: return "control transfer error";
190  case io_error: return "I/O error on an attached file";
191  case fcntl_error: return "fcntl failed on an attached file";
192  case poll_error: return "poll returned EINVAL";
193  case pipe_error: return "failed to create a pipe";
194  case out_of_memory: return "memory allocation failed";
195  default:
196  return "Error " + code;
197  }
198  }
199 
200  private class ChannelImpl extends ChannelPriv implements Channel {
201  private ChannelImpl(UsbDeviceConnection device, ChannelPriv ch) {
202  super(ch);
203  this.device = device;
204  }
205  @Override
206  public InputStream getInputStream() throws Channel.Error {
207  return new FileInputStream(fd(fd_read));
208  }
209 
210  @Override
211  public OutputStream getOutputStream() throws Channel.Error {
212  return new FileOutputStream(fd(fd_write));
213  }
214 
215  @Override
216  public void reset() throws Error {
217  UsbUartContext.this.reset(this);
218  }
219 
220  @Override
221  public void close() {
222  Log.d(TAG,"close");
223  device.close();
224  UsbUartContext.this.close(this);
225  }
226 
227  @Override
228  public int status() {
229  return UsbUartContext.this.status(this);
230  }
231 
232  @Override
233  public void sendBreak() throws Error {
234  UsbUartContext.this.sendbreak(this);
235  }
236 
237  final UsbDeviceConnection device;
238  };
239 
240  private static class ChannelPriv {
241  int fd_read;
242  int fd_write;
243 
244  ChannelPriv(int read, int write) {
245  fd_read = read;
246  fd_write = write;
247  }
248  ChannelPriv(ChannelPriv that ) {
249  fd_read = that.fd_read;
250  fd_write = that.fd_write;
251  }
252  public String toString() {
253  return "{" + fd_read + "," + fd_write + "}";
254  }
255  }
256 
257  static {
258  System.loadLibrary("usbuart");
259  }
260  private static native long create();
261  private static native int loop(long ctx,int to);
262  private static native int attach(long ctx, int fd, int ifcnum, final ChannelPriv ch, final EIA_TIA_232_Info pi);
263  private static native int pipe(long ctx, int fd, int ifcnum, final ChannelPriv ch, final EIA_TIA_232_Info pi);
264  private static native int sendbreak(long ctx, ChannelPriv ch);
265  private static native int status(long ctx, ChannelPriv ch);
266  private static native int reset(long ctx, ChannelPriv ch);
267  private static native void close(long ctx, ChannelPriv ch);
268  private native static void hotplug(long ctx, int fd);
269  private final long context;
270  public int timeout = DEFAULT_LOOP_TIMEOUT;
271 };
272 
requested interface busy
device is not supported
I/O error on an attached file.
poll returned EINVAL
hardware level error
fcntl failed on an attached file
context has nor more live channels
device does not exist
control transfer error
claim interface failed
invalid param passed to the API
memory allocation failed
requested channel does not exist
device returned unexpected value while probing
method not implemented in this lib
error_t
API Error codes.
Definition: usbuart.h:177
access permission denied
failed to create a pipe
unsupported baud rate