AcmInputStream.java
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2011 Google Inc.
00003  * 
00004  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
00005  * use this file except in compliance with the License. You may obtain a copy of
00006  * the License at
00007  * 
00008  * http://www.apache.org/licenses/LICENSE-2.0
00009  * 
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00012  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
00013  * License for the specific language governing permissions and limitations under
00014  * the License.
00015  */
00016 
00017 package org.ros.android.android_acm_serial;
00018 
00019 import com.google.common.base.Preconditions;
00020 
00021 import android.hardware.usb.UsbConstants;
00022 import android.hardware.usb.UsbDeviceConnection;
00023 import android.hardware.usb.UsbEndpoint;
00024 import android.util.Log;
00025 
00026 import java.io.IOException;
00027 import java.io.InputStream;
00028 
00029 public class AcmInputStream extends InputStream {
00030 
00031   private static final boolean DEBUG = false;
00032   private static final String TAG = "AcmInputStream";
00033 
00034   // Disable USB read timeouts. Reads are expected to block until data becomes
00035   // available.
00036   private static final int TIMEOUT = 0;
00037 
00038   private final UsbDeviceConnection connection;
00039   private final UsbEndpoint endpoint;
00040 
00041   public AcmInputStream(UsbDeviceConnection connection, UsbEndpoint endpoint) {
00042     Preconditions.checkArgument(endpoint.getDirection() == UsbConstants.USB_DIR_IN);
00043     this.connection = connection;
00044     this.endpoint = endpoint;
00045   }
00046 
00047   @Override
00048   public void close() throws IOException {
00049   }
00050 
00051   @Override
00052   public int read(byte[] buffer, int offset, int count) throws IOException {
00053     Preconditions.checkNotNull(buffer);
00054     if (offset < 0 || count < 0 || offset + count > buffer.length) {
00055       throw new IndexOutOfBoundsException();
00056     }
00057     // NOTE(damonkohler): According to the InputStream.read() javadoc, we should
00058     // be able to return 0 when we didn't read anything. However, it also says
00059     // we should block until input is available. Blocking seems to be the
00060     // preferred behavior.
00061     byte[] slice = new byte[count];
00062     if (DEBUG) {
00063       Log.i(TAG, "Reading " + count + " bytes.");
00064     }
00065     int byteCount = 0;
00066     while (byteCount == 0) {
00067       byteCount = connection.bulkTransfer(endpoint, slice, slice.length, TIMEOUT);
00068       if (DEBUG) {
00069         if (byteCount == 0) {
00070           Log.i(TAG, "bulkTransfer() returned 0, retrying.");
00071         }
00072       }
00073     }
00074     if (byteCount < 0) {
00075       throw new IOException("USB read failed.");
00076     }
00077     System.arraycopy(slice, 0, buffer, offset, byteCount);
00078     if (DEBUG) {
00079       Log.i(TAG, "Actually read " + byteCount + " bytes.");
00080       Log.i(TAG, "Slice: " + byteArrayToHexString(slice));
00081     }
00082     return byteCount;
00083   }
00084 
00085   @Override
00086   public int read() throws IOException {
00087     throw new UnsupportedOperationException();
00088   }
00089 
00090   // TODO(damonkohler): Possibly move this to some common place?
00091   private static String byteArrayToHexString(byte[] data) {
00092     if (data == null) {
00093       return "null";
00094     }
00095     if (data.length == 0) {
00096       return "empty";
00097     }
00098     StringBuilder out = new StringBuilder(data.length * 5);
00099     for (byte b : data) {
00100       out.append(String.format("%02x", b));
00101     }
00102     return out.toString();
00103   }
00104 }


android_core
Author(s): Damon Kohler
autogenerated on Thu Aug 27 2015 12:11:33