Back to project page usb-serial-for-android.
The source code is released under:
GNU Lesser General Public License
If you think the Android project usb-serial-for-android listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
package com.hoho.android.usbserial.driver; //w w w.j av a 2 s.co m import android.hardware.usb.UsbConstants; import android.hardware.usb.UsbDevice; import android.hardware.usb.UsbDeviceConnection; import android.hardware.usb.UsbEndpoint; import android.hardware.usb.UsbInterface; import android.util.Log; import java.io.IOException; import java.util.LinkedHashMap; import java.util.Map; /** * USB CDC/ACM serial driver implementation. * * @author mike wakerly (opensource@hoho.com) * @see <a * href="http://www.usb.org/developers/devclass_docs/usbcdc11.pdf">Universal * Serial Bus Class Definitions for Communication Devices, v1.1</a> */ public class CdcAcmSerialDriver extends UsbSerialDriver { private final String TAG = CdcAcmSerialDriver.class.getSimpleName(); private UsbInterface mControlInterface; private UsbInterface mDataInterface; private UsbEndpoint mControlEndpoint; private UsbEndpoint mReadEndpoint; private UsbEndpoint mWriteEndpoint; private int mBaudRate; private int mDataBits; private int mStopBits; private int mParity; private boolean mRts = false; private boolean mDtr = false; private static final int USB_RECIP_INTERFACE = 0x01; private static final int USB_RT_ACM = UsbConstants.USB_TYPE_CLASS | USB_RECIP_INTERFACE; private static final int SET_LINE_CODING = 0x20; // USB CDC 1.1 section 6.2 private static final int GET_LINE_CODING = 0x21; private static final int SET_CONTROL_LINE_STATE = 0x22; private static final int SEND_BREAK = 0x23; public CdcAcmSerialDriver(UsbDevice device, UsbDeviceConnection connection) { super(device, connection); } @Override public void open() throws IOException { Log.d(TAG, "claiming interfaces, count=" + mDevice.getInterfaceCount()); Log.d(TAG, "Claiming control interface."); mControlInterface = mDevice.getInterface(0); Log.d(TAG, "Control iface=" + mControlInterface); // class should be USB_CLASS_COMM if (!mConnection.claimInterface(mControlInterface, true)) { throw new IOException("Could not claim control interface."); } mControlEndpoint = mControlInterface.getEndpoint(0); Log.d(TAG, "Control endpoint direction: " + mControlEndpoint.getDirection()); Log.d(TAG, "Claiming data interface."); mDataInterface = mDevice.getInterface(1); Log.d(TAG, "data iface=" + mDataInterface); // class should be USB_CLASS_CDC_DATA if (!mConnection.claimInterface(mDataInterface, true)) { throw new IOException("Could not claim data interface."); } mReadEndpoint = mDataInterface.getEndpoint(1); Log.d(TAG, "Read endpoint direction: " + mReadEndpoint.getDirection()); mWriteEndpoint = mDataInterface.getEndpoint(0); Log.d(TAG, "Write endpoint direction: " + mWriteEndpoint.getDirection()); Log.d(TAG, "Setting line coding to 115200/8N1"); mBaudRate = 115200; mDataBits = DATABITS_8; mParity = PARITY_NONE; mStopBits = STOPBITS_1; setParameters(mBaudRate, mDataBits, mStopBits, mParity); } private int sendAcmControlMessage(int request, int value, byte[] buf) { return mConnection.controlTransfer( USB_RT_ACM, request, value, 0, buf, buf != null ? buf.length : 0, 5000); } @Override public void close() throws IOException { mConnection.close(); } @Override public int read(byte[] dest, int timeoutMillis) throws IOException { final int numBytesRead; synchronized (mReadBufferLock) { int readAmt = Math.min(dest.length, mReadBuffer.length); numBytesRead = mConnection.bulkTransfer(mReadEndpoint, mReadBuffer, readAmt, timeoutMillis); if (numBytesRead < 0) { // This sucks: we get -1 on timeout, not 0 as preferred. // We *should* use UsbRequest, except it has a bug/api oversight // where there is no way to determine the number of bytes read // in response :\ -- http://b.android.com/28023 return 0; } System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead); } return numBytesRead; } @Override public int write(byte[] src, int timeoutMillis) throws IOException { // TODO(mikey): Nearly identical to FtdiSerial write. Refactor. int offset = 0; while (offset < src.length) { final int writeLength; final int amtWritten; synchronized (mWriteBufferLock) { final byte[] writeBuffer; writeLength = Math.min(src.length - offset, mWriteBuffer.length); if (offset == 0) { writeBuffer = src; } else { // bulkTransfer does not support offsets, make a copy. System.arraycopy(src, offset, mWriteBuffer, 0, writeLength); writeBuffer = mWriteBuffer; } amtWritten = mConnection.bulkTransfer(mWriteEndpoint, writeBuffer, writeLength, timeoutMillis); } if (amtWritten <= 0) { throw new IOException("Error writing " + writeLength + " bytes at offset " + offset + " length=" + src.length); } Log.d(TAG, "Wrote amt=" + amtWritten + " attempted=" + writeLength); offset += amtWritten; } return offset; } @Deprecated @Override public int setBaudRate(int baudRate) throws IOException { mBaudRate = baudRate; setParameters(mBaudRate, mDataBits, mStopBits, mParity); return mBaudRate; } @Override public void setParameters(int baudRate, int dataBits, int stopBits, int parity) { byte stopBitsByte; switch (stopBits) { case STOPBITS_1: stopBitsByte = 1; break; case STOPBITS_1_5: stopBitsByte = 2; break; case STOPBITS_2: stopBitsByte = 3; break; default: throw new IllegalArgumentException("Bad value for stopBits: " + stopBits); } byte parityBitesByte; switch (parity) { case PARITY_NONE: parityBitesByte = 0; break; case PARITY_ODD: parityBitesByte = 1; break; case PARITY_EVEN: parityBitesByte = 2; break; case PARITY_MARK: parityBitesByte = 3; break; case PARITY_SPACE: parityBitesByte = 4; break; default: throw new IllegalArgumentException("Bad value for parity: " + parity); } byte[] msg = { (byte) ( baudRate & 0xff), (byte) ((baudRate >> 8 ) & 0xff), (byte) ((baudRate >> 16) & 0xff), (byte) ((baudRate >> 24) & 0xff), stopBitsByte, parityBitesByte, (byte) dataBits}; sendAcmControlMessage(SET_LINE_CODING, 0, msg); } @Override public boolean getCD() throws IOException { return false; // TODO } @Override public boolean getCTS() throws IOException { return false; // TODO } @Override public boolean getDSR() throws IOException { return false; // TODO } @Override public boolean getDTR() throws IOException { return mDtr; } @Override public void setDTR(boolean value) throws IOException { mDtr = value; setDtrRts(); } @Override public boolean getRI() throws IOException { return false; // TODO } @Override public boolean getRTS() throws IOException { return mRts; } @Override public void setRTS(boolean value) throws IOException { mRts = value; setDtrRts(); } private void setDtrRts() { int value = (mRts ? 0x2 : 0) | (mDtr ? 0x1 : 0); sendAcmControlMessage(SET_CONTROL_LINE_STATE, value, null); } public static Map<Integer, int[]> getSupportedDevices() { final Map<Integer, int[]> supportedDevices = new LinkedHashMap<Integer, int[]>(); supportedDevices.put(Integer.valueOf(UsbId.VENDOR_ARDUINO), new int[] { UsbId.ARDUINO_UNO, UsbId.ARDUINO_UNO_R3, UsbId.ARDUINO_MEGA_2560, UsbId.ARDUINO_MEGA_2560_R3, UsbId.ARDUINO_SERIAL_ADAPTER, UsbId.ARDUINO_SERIAL_ADAPTER_R3, UsbId.ARDUINO_MEGA_ADK, UsbId.ARDUINO_MEGA_ADK_R3, UsbId.ARDUINO_LEONARDO, }); supportedDevices.put(Integer.valueOf(UsbId.VENDOR_VAN_OOIJEN_TECH), new int[] { UsbId.VAN_OOIJEN_TECH_TEENSYDUINO_SERIAL, }); return supportedDevices; } }