Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 package org.ros.android.android_acm_serial;
00018
00019 import android.hardware.usb.UsbConstants;
00020 import android.hardware.usb.UsbDevice;
00021 import android.hardware.usb.UsbDeviceConnection;
00022 import android.hardware.usb.UsbEndpoint;
00023 import android.hardware.usb.UsbInterface;
00024
00025 import com.google.common.base.Preconditions;
00026
00027 import org.apache.commons.logging.Log;
00028 import org.apache.commons.logging.LogFactory;
00029 import org.ros.exception.RosRuntimeException;
00030
00031 import java.io.IOException;
00032 import java.io.InputStream;
00033 import java.io.OutputStream;
00034 import java.nio.ByteBuffer;
00035 import java.nio.ByteOrder;
00036
00040 public class AcmDevice {
00041
00042 private static final int CONTROL_TRANSFER_TIMEOUT = 3000;
00043
00044 private final UsbDeviceConnection usbDeviceConnection;
00045 private final UsbDevice usbDevice;
00046 private final UsbInterface usbInterface;
00047 private final InputStream inputStream;
00048 private final OutputStream outputStream;
00049 private final UsbRequestPool usbRequestPool;
00050
00051 private static final Log log = LogFactory.getLog(AcmDevice.class);
00052
00057 private class AcmUsbEndpoints {
00058 private final UsbEndpoint incoming;
00059 private final UsbEndpoint outgoing;
00060
00061 public AcmUsbEndpoints(UsbEndpoint incoming, UsbEndpoint outgoing) {
00062 this.incoming = incoming;
00063 this.outgoing = outgoing;
00064 }
00065
00066 private UsbEndpoint getOutgoing() {
00067 return outgoing;
00068 }
00069
00070 private UsbEndpoint getIncoming() {
00071 return incoming;
00072 }
00073 }
00074
00075 public AcmDevice(UsbDeviceConnection usbDeviceConnection, UsbDevice usbDevice) {
00076 Preconditions.checkNotNull(usbDeviceConnection);
00077 this.usbDeviceConnection = usbDeviceConnection;
00078
00079
00080
00081 UsbInterface usbInterface = null;
00082 AcmUsbEndpoints acmUsbEndpoints = null;
00083 for(int i=0;i<usbDevice.getInterfaceCount() && acmUsbEndpoints == null;i++) {
00084 usbInterface = usbDevice.getInterface(i);
00085 Preconditions.checkNotNull(usbInterface);
00086 Preconditions.checkState(usbDeviceConnection.claimInterface(usbInterface, true));
00087 acmUsbEndpoints = getAcmEndpoints(usbInterface);
00088 }
00089 if(acmUsbEndpoints == null) {
00090 throw new IllegalArgumentException("Couldn't find an interface that looks like ACM on this USB device: " + usbDevice);
00091 }
00092
00093 this.usbInterface = usbInterface;
00094 this.usbDevice = usbDevice;
00095 usbRequestPool = new UsbRequestPool(usbDeviceConnection);
00096 usbRequestPool.addEndpoint(acmUsbEndpoints.getOutgoing(), null);
00097 usbRequestPool.start();
00098
00099 outputStream = new AcmOutputStream(usbRequestPool, acmUsbEndpoints.getOutgoing());
00100 inputStream = new AcmInputStream(usbDeviceConnection, acmUsbEndpoints.getIncoming());
00101 }
00102
00109 private AcmUsbEndpoints getAcmEndpoints(UsbInterface usbInterface) {
00110 UsbEndpoint outgoingEndpoint = null;
00111 UsbEndpoint incomingEndpoint = null;
00112 for (int i = 0; i < usbInterface.getEndpointCount(); i++) {
00113 UsbEndpoint endpoint = usbInterface.getEndpoint(i);
00114 log.info("Interface: " + i + "/" + "Class: " + usbInterface.getInterfaceClass());
00115 if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_CDC_DATA) {
00116 if (endpoint.getDirection() == UsbConstants.USB_DIR_OUT) {
00117 log.info("Endpoint " + i + "/" + usbInterface.getEndpointCount() + ": " + endpoint + ". Type = " + endpoint.getType());
00118 outgoingEndpoint = endpoint;
00119 } else if(endpoint.getDirection() == UsbConstants.USB_DIR_IN) {
00120 log.info("Endpoint " + i + "/" + usbInterface.getEndpointCount() + ": " + endpoint + ". Type = " + endpoint.getType());
00121 incomingEndpoint = endpoint;
00122 }
00123 }
00124 }
00125 if(outgoingEndpoint == null || incomingEndpoint == null) {
00126 return null;
00127 } else {
00128 return new AcmUsbEndpoints(incomingEndpoint, outgoingEndpoint);
00129 }
00130 }
00131
00132 public void setLineCoding(BitRate bitRate, StopBits stopBits, Parity parity, DataBits dataBits) {
00133 ByteBuffer buffer = ByteBuffer.allocate(7);
00134 buffer.order(ByteOrder.LITTLE_ENDIAN);
00135 buffer.putInt(bitRate.getBitRate());
00136 buffer.put(stopBits.getStopBits());
00137 buffer.put(parity.getParity());
00138 buffer.put(dataBits.getDataBits());
00139 setLineCoding(buffer.array());
00140 }
00141
00142 private void setLineCoding(byte[] lineCoding) {
00143 int byteCount;
00144 byteCount =
00145 usbDeviceConnection.controlTransfer(0x21, 0x20, 0, 0, lineCoding, lineCoding.length,
00146 CONTROL_TRANSFER_TIMEOUT);
00147 Preconditions.checkState(byteCount == lineCoding.length, "Failed to set line coding.");
00148 }
00149
00150 public UsbDevice getUsbDevice() {
00151 return this.usbDevice;
00152 }
00153
00154 public UsbInterface getUsbInterface() {
00155 return usbInterface;
00156 }
00157
00158 public InputStream getInputStream() {
00159 return inputStream;
00160 }
00161
00162 public OutputStream getOutputStream() {
00163 return outputStream;
00164 }
00165
00166 public void close() {
00167 usbDeviceConnection.releaseInterface(usbInterface);
00168 usbDeviceConnection.close();
00169 try {
00170 inputStream.close();
00171 outputStream.close();
00172 } catch (IOException e) {
00173 throw new RosRuntimeException(e);
00174 }
00175 }
00176 }